const char * TkpGetString( TkWindow *winPtr, /* Window where event occurred: needed to get * input context. */ XEvent *eventPtr, /* X keyboard event. */ Tcl_DString *dsPtr) /* Uninitialized or empty string to hold * result. */ { XKeyEvent *keyEv = &eventPtr->xkey; Tcl_DStringInit(dsPtr); if (keyEv->send_event == -1) { if (keyEv->nbytes > 0) { Tcl_ExternalToUtfDString(TkWinGetKeyInputEncoding(), keyEv->trans_chars, keyEv->nbytes, dsPtr); } } else if (keyEv->send_event == -2) { /* * Special case for win2000 multi-lingal IME input. xkey.trans_chars[] * already contains a UNICODE char. */ int unichar; char buf[TCL_UTF_MAX]; int len; unichar = keyEv->trans_chars[1] & 0xff; unichar <<= 8; unichar |= keyEv->trans_chars[0] & 0xff; len = Tcl_UniCharToUtf((Tcl_UniChar) unichar, buf); Tcl_DStringAppend(dsPtr, buf, len); } else if (keyEv->send_event == -3) { /* * Special case for WM_UNICHAR. xkey.trans_chars[] already contains a * UTF-8 char. */ Tcl_DStringAppend(dsPtr, keyEv->trans_chars, keyEv->nbytes); } else { /* * This is an event generated from generic code. It has no nchars or * trans_chars members. */ KeySym keysym = KeycodeToKeysym(keyEv->keycode, keyEv->state, 0); if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256)) || (keysym == XK_Return) || (keysym == XK_Tab)) { char buf[TCL_UTF_MAX]; int len; len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf); Tcl_DStringAppend(dsPtr, buf, len); } } return Tcl_DStringValue(dsPtr); }
static int ToUtf( const WCHAR *wSrc, char *dst) { char *start; start = dst; while (*wSrc != '\0') { dst += Tcl_UniCharToUtf(*wSrc, dst); wSrc++; } *dst = '\0'; return (int) (dst - start); }
/* Initialize the escape sequence hash table */ static void EscInit(void){ int i; /* For looping thru the list of escape sequences */ int h; /* The hash on a sequence */ for(i=0; i<sizeof(esc_sequences)/sizeof(esc_sequences[i]); i++){ /* #ifdef TCL_UTF_MAX */ #if 0 { int c = esc_sequences[i].value[0]; Tcl_UniCharToUtf(c, esc_sequences[i].value); } #endif h = EscHash(esc_sequences[i].zName); esc_sequences[i].pNext = apEscHash[h]; apEscHash[h] = &esc_sequences[i]; TestPoint(0); } #ifdef TEST EscHashStats(); #endif }
void TkpSetKeycodeAndState( Tk_Window tkwin, KeySym keysym, XEvent *eventPtr) { if (keysym == NoSymbol) { eventPtr->xkey.keycode = 0; } else { Display *display = Tk_Display(tkwin); int macKeycode = XKeysymToMacKeycode(display, keysym); /* * See also XKeysymToKeycode. */ if ((keysym >= XK_F1) && (keysym <= XK_F35)) { eventPtr->xkey.keycode = 0x0010; } else { eventPtr->xkey.keycode = 0x00FF & keysym; } eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16; if (shiftKey & macKeycode) { eventPtr->xkey.state |= ShiftMask; } if (optionKey & macKeycode) { eventPtr->xkey.state |= OPTION_MASK; } if (keysym <= LATIN1_MAX) { int done; done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars); eventPtr->xkey.trans_chars[done] = 0; } else { eventPtr->xkey.trans_chars[0] = 0; } } }
static int ValidateFormat( Tcl_Interp *interp, /* Current interpreter. */ const char *format, /* The format string. */ int numVars, /* The number of variables passed to the scan * command. */ int *totalSubs) /* The number of variables that will be * required. */ { int gotXpg, gotSequential, value, i, flags; char *end; Tcl_UniChar ch; int objIndex, xpgSize, nspace = numVars; int *nassign = TclStackAlloc(interp, nspace * sizeof(int)); char buf[TCL_UTF_MAX+1]; Tcl_Obj *errorMsg; /* Place to build an error messages. Note that * these are messy operations because we do * not want to use the formatting engine; * we're inside there! */ /* * Initialize an array that records the number of times a variable is * assigned to by the format string. We use this to detect if a variable * is multiply assigned or left unassigned. */ for (i = 0; i < nspace; i++) { nassign[i] = 0; } xpgSize = objIndex = gotXpg = gotSequential = 0; while (*format != '\0') { format += Tcl_UtfToUniChar(format, &ch); flags = 0; if (ch != '%') { continue; } format += Tcl_UtfToUniChar(format, &ch); if (ch == '%') { continue; } if (ch == '*') { flags |= SCAN_SUPPRESS; format += Tcl_UtfToUniChar(format, &ch); goto xpgCheckDone; } if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ /* * Check for an XPG3-style %n$ specification. Note: there must * not be a mixture of XPG3 specs and non-XPG3 specs in the same * format string. */ value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */ if (*end != '$') { goto notXpg; } format = end+1; format += Tcl_UtfToUniChar(format, &ch); gotXpg = 1; if (gotSequential) { goto mixedXPG; } objIndex = value - 1; if ((objIndex < 0) || (numVars && (objIndex >= numVars))) { goto badIndex; } else if (numVars == 0) { /* * In the case where no vars are specified, the user can * specify %9999$ legally, so we have to consider special * rules for growing the assign array. 'value' is guaranteed * to be > 0. */ xpgSize = (xpgSize > value) ? xpgSize : value; } goto xpgCheckDone; } notXpg: gotSequential = 1; if (gotXpg) { mixedXPG: Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot mix \"%\" and \"%n$\" conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "MIXEDSPECTYPES", NULL); goto error; } xpgCheckDone: /* * Parse any width specifier. */ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ value = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */ flags |= SCAN_WIDTH; format += Tcl_UtfToUniChar(format, &ch); } /* * Handle any size specifier. */ switch (ch) { case 'l': if (*format == 'l') { flags |= SCAN_BIG; format += 1; format += Tcl_UtfToUniChar(format, &ch); break; } case 'L': flags |= SCAN_LONGER; case 'h': format += Tcl_UtfToUniChar(format, &ch); } if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) { goto badIndex; } /* * Handle the various field types. */ switch (ch) { case 'c': if (flags & SCAN_WIDTH) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "field width may not be specified in %c conversion", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", NULL); goto error; } /* * Fall through! */ case 'n': case 's': if (flags & (SCAN_LONGER|SCAN_BIG)) { invalidFieldSize: buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; errorMsg = Tcl_NewStringObj( "field size modifier may not be specified in %", -1); Tcl_AppendToObj(errorMsg, buf, -1); Tcl_AppendToObj(errorMsg, " conversion", -1); Tcl_SetObjResult(interp, errorMsg); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", NULL); goto error; } /* * Fall through! */ case 'd': case 'e': case 'E': case 'f': case 'g': case 'G': case 'i': case 'o': case 'x': case 'X': case 'b': break; case 'u': if (flags & SCAN_BIG) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unsigned bignum scans are invalid", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADUNSIGNED",NULL); goto error; } break; /* * Bracket terms need special checking */ case '[': if (flags & (SCAN_LONGER|SCAN_BIG)) { goto invalidFieldSize; } if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); if (ch == '^') { if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); } if (ch == ']') { if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); } while (ch != ']') { if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); } break; badSet: Tcl_SetObjResult(interp, Tcl_NewStringObj( "unmatched [ in format string", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", NULL); goto error; default: buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; errorMsg = Tcl_NewStringObj( "bad scan conversion character \"", -1); Tcl_AppendToObj(errorMsg, buf, -1); Tcl_AppendToObj(errorMsg, "\"", -1); Tcl_SetObjResult(interp, errorMsg); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL); goto error; } if (!(flags & SCAN_SUPPRESS)) { if (objIndex >= nspace) { /* * Expand the nassign buffer. If we are using XPG specifiers, * make sure that we grow to a large enough size. xpgSize is * guaranteed to be at least one larger than objIndex. */ value = nspace; if (xpgSize) { nspace = xpgSize; } else { nspace += 16; /* formerly STATIC_LIST_SIZE */ } nassign = TclStackRealloc(interp, nassign, nspace * sizeof(int)); for (i = value; i < nspace; i++) { nassign[i] = 0; } } nassign[objIndex]++; objIndex++; } } /* * Verify that all of the variable were assigned exactly once. */ if (numVars == 0) { if (xpgSize) { numVars = xpgSize; } else { numVars = objIndex; } } if (totalSubs) { *totalSubs = numVars; } for (i = 0; i < numVars; i++) { if (nassign[i] > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "variable is assigned by multiple \"%n$\" conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "POLYASSIGNED", NULL); goto error; } else if (!xpgSize && (nassign[i] == 0)) { /* * If the space is empty, and xpgSize is 0 (means XPG wasn't used, * and/or numVars != 0), then too many vars were given */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "variable is not assigned by any conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", NULL); goto error; } } TclStackFree(interp, nassign); return TCL_OK; badIndex: if (gotXpg) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"%n$\" argument index out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", NULL); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( "different numbers of variable names and field specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", NULL); } error: TclStackFree(interp, nassign); return TCL_ERROR; }
const char * TkpGetString( TkWindow *winPtr, /* Window where event occurred */ XEvent *eventPtr, /* X keyboard event. */ Tcl_DString *dsPtr) /* Initialized, empty string to hold result. */ { int len; Tcl_DString buf; TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr; /* * If we have the value cached already, use it now. [Bug 1373712] */ if (kePtr->charValuePtr != NULL) { Tcl_DStringSetLength(dsPtr, kePtr->charValueLen); memcpy(Tcl_DStringValue(dsPtr), kePtr->charValuePtr, (unsigned) kePtr->charValueLen+1); return Tcl_DStringValue(dsPtr); } #ifdef TK_USE_INPUT_METHODS if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM) && (winPtr->inputContext != NULL) && (eventPtr->type == KeyPress)) { Status status; #if X_HAVE_UTF8_STRING Tcl_DStringSetLength(dsPtr, TCL_DSTRING_STATIC_SIZE-1); len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), &kePtr->keysym, &status); if (status == XBufferOverflow) { /* * Expand buffer and try again. */ Tcl_DStringSetLength(dsPtr, len); len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), &kePtr->keysym, &status); } if ((status != XLookupChars) && (status != XLookupBoth)) { len = 0; } Tcl_DStringSetLength(dsPtr, len); #else /* !X_HAVE_UTF8_STRING */ /* * Overallocate the dstring to the maximum stack amount. */ Tcl_DStringInit(&buf); Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1); len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf), &kePtr->keysym, &status); /* * If the buffer wasn't big enough, grow the buffer and try again. */ if (status == XBufferOverflow) { Tcl_DStringSetLength(&buf, len); len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey, Tcl_DStringValue(&buf), len, &kePtr->keysym, &status); } if ((status != XLookupChars) && (status != XLookupBoth)) { len = 0; } Tcl_DStringSetLength(&buf, len); Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buf), len, dsPtr); Tcl_DStringFree(&buf); #endif /* X_HAVE_UTF8_STRING */ } else #endif /* TK_USE_INPUT_METHODS */ { /* * Fall back to convert a keyboard event to a UTF-8 string using * XLookupString. This is used when input methods are turned off and * for KeyRelease events. * * Note: XLookupString() normally returns a single ISO Latin 1 or * ASCII control character. */ Tcl_DStringInit(&buf); Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1); len = XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf), TCL_DSTRING_STATIC_SIZE, &kePtr->keysym, 0); Tcl_DStringValue(&buf)[len] = '\0'; if (len == 1) { len = Tcl_UniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0], Tcl_DStringValue(dsPtr)); Tcl_DStringSetLength(dsPtr, len); } else { /* * len > 1 should only happen if someone has called XRebindKeysym. * Assume UTF-8. */ Tcl_DStringSetLength(dsPtr, len); strncpy(Tcl_DStringValue(dsPtr), Tcl_DStringValue(&buf), len); } } /* * Cache the string in the event so that if/when we return to this * function, we will be able to produce it without asking X. This stops us * from having to reenter the XIM engine. [Bug 1373712] */ kePtr->charValuePtr = ckalloc(len + 1); kePtr->charValueLen = len; memcpy(kePtr->charValuePtr, Tcl_DStringValue(dsPtr), (unsigned) len + 1); return Tcl_DStringValue(dsPtr); }
/* Translate escape sequences in the string "z". "z" is overwritten ** with the translated sequence. ** ** Unrecognized escape sequences are unaltered. ** ** Example: ** ** input = "AT&T > MCI" ** output = "AT&T > MCI" */ LOCAL void HtmlTranslateEscapes(char *z){ int from; /* Read characters from this position in z[] */ int to; /* Write characters into this position in z[] */ int h; /* A hash on the escape sequence */ struct sgEsc *p; /* For looping down the escape sequence collision chain */ static int isInit = 0; /* True after initialization */ from = to = 0; if( !isInit ){ EscInit(); isInit = 1; } while( z[from] ){ if( z[from]=='&' ){ if( z[from+1]=='#' ){ int i = from + 2; int v = 0; while( isdigit(z[i]) ){ v = v*10 + z[i] - '0'; i++; } if( z[i]==';' ){ i++; } /* On Unix systems, translate the non-standard microsoft ** characters in the range of 0x80 to 0x9f into something ** we can see. */ #ifndef __WIN32__ if( v>=0x80 && v<0xa0 ){ v = acMsChar[v&0x1f]; } #endif /* Put the character in the output stream in place of ** the "�". How we do this depends on whether or ** not we are using UTF-8. */ #ifdef TCL_UTF_MAX { int j, n; char value[8]; n = Tcl_UniCharToUtf(v,value); for(j=0; j<n; j++){ z[to++] = value[j]; } } #else z[to++] = v; #endif from = i; }else{ int i = from+1; int c; while( z[i] && isalnum(z[i]) ){ TestPoint(0); i++; } c = z[i]; z[i] = 0; h = EscHash(&z[from+1]); p = apEscHash[h]; while( p && strcmp(p->zName,&z[from+1])!=0 ){ p = p->pNext; } z[i] = c; if( p ){ int j; for(j=0; p->value[j]; j++){ z[to++] = p->value[j]; } from = i; if( c==';' ){ from++; } }else{ z[to++] = z[from++]; } } /* On UNIX systems, look for the non-standard microsoft characters ** between 0x80 and 0x9f and translate them into printable ASCII ** codes. Separate algorithms are required to do this for plain ** ascii and for utf-8. */ #ifndef __WIN32__ #ifdef TCL_UTF_MAX }else if( (z[from]&0x80)!=0 ){ Tcl_UniChar c; int n; n = Tcl_UtfToUniChar(&z[from], &c); if( c>=0x80 && c<0xa0 ){ z[to++] = acMsChar[c & 0x1f]; from += n; }else{ while( n-- ) z[to++] = z[from++]; } #else /* if !defined(TCL_UTF_MAX) */ }else if( ((unsigned char)z[from])>=0x80 && ((unsigned char)z[from])<0xa0 ){ z[to++] = acMsChar[z[from++]&0x1f]; #endif /* TCL_UTF_MAX */ #endif /* __WIN32__ */ }else{ z[to++] = z[from++]; TestPoint(0); } } z[to] = 0; }