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