Recently Tim pointed me a solution that utilized the "parameter as an
expression" feature. This is quite powerful feature and very flexible.

If found that if the expression contained a symbol code, the string
returned by the Tcl_Eval function may contain UTF-8 encoded characters.
The UDrawSting0 function in text.c is not aware of this and will draw funny
characters.

Here's some sample library code:


%! PostScript set of library objects for XCircuit
%  Version: 3.10
%  Library name is: spicelib
%  Author: Daniel Moore <moore...@suncup.net>
%

% Depend spicelib::vdc

% XCircuitLib library objects

/spicelib::vdc {
<</p_yps 34 /p_xps 48 /p_rot 0 /p_jst 20
/@ac_mag (1.0)
/p_deg () (if {[expr @ac_mag] == 0} { return "" } else { return "\260" })
pop
/p_degrees (\260)
>> begingate

0.647 0.165 0.165 scb
mark
p_deg {/Symbol cf} (p_deg = ) {/Times-Roman cf} {CR} p_degrees {/Symbol cf}
(p_degrees = ) {/Times-Roman cf}
ctmk p_jst p_rot 0.750 p_xps p_yps
label

endgate
} def

% EndLib


The parameter /p_deg is an expression, and will return either an empty
string or the symbol code for the degrees character.  As shown in the
attached .png file, note that there is a stylized "R" before the intended
symbol (that the degree symbol shows up at all is a coincidence).

Here's a patch that solves this.  I've tested it in a variety of ways and
so far, so good.

diff --git a/tclxcircuit.c b/tclxcircuit.c
index bdb3178..e58c023 100644
--- a/tclxcircuit.c
+++ b/tclxcircuit.c
@@ -9155,6 +9155,37 @@ char *evaluate_expr(objectptr thisobj, oparamptr
ops, objinstptr pinst)
       }
    }

+   /* If TCL expression contained a three digit octal value \ooo   */
+   /* then string returned by TclEval() can contain be a           */
+   /* multi-byte UTF-8 character.                                  */
+   /*                                                              */
+   /* This multi-byte character needs to be converted back to a    */
+   /* character that can be displayed.                             */
+   /*                                                              */
+   /* The following "fix" assumes that at most two bytes will be   */
+   /* represent any converted character.  In these cases, the most */
+   /* significant digit (octal) of the first byte will be 3, and   */
+   /* the most significant digit of the second byte will be 2.     */
+   /*                                                              */
+   /* re: https://en.wikipedia.org/wiki/UTF-8                      */
+
+   if ((rexpr != NULL) && ((status == TCL_RETURN) || (status == TCL_OK))) {
+      u_char *strptr1 = rexpr;
+      u_char *strptr2 = rexpr;
+      while(*strptr1 != '\0') {
+         if (*strptr1 >= 0300 && *(strptr1 + 1) >= 0200) {
+            *strptr2 = ((*strptr1 & ~0300) << 6) | (*(strptr1+1) & 0077);
+            strptr1+=2;
+         } else {
+            *strptr2 = *strptr1;
+            strptr1++;
+         }
+         strptr2++;
+      }
+      if(*strptr1 == '\0')
+         *strptr2 = *strptr1;
+   }
+
    /* If an instance redefines an expression, don't preserve */
    /* the result.  It is necessary in this case that the */
    /* expression does not reference objects during redisplay, */
_______________________________________________
Xcircuit-dev mailing list
Xcircuit-dev@opencircuitdesign.com
http://www.opencircuitdesign.com/mailman/listinfo/xcircuit-dev

Reply via email to