TMparse.c revision 444c061a
1/* $Xorg: TMparse.c,v 1.6 2001/02/09 02:03:58 xorgcvs Exp $ */ 2 3/*********************************************************** 4Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, 5Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA. 6 7 All Rights Reserved 8 9Permission to use, copy, modify, and distribute this software and its 10documentation for any purpose and without fee is hereby granted, 11provided that the above copyright notice appear in all copies and that 12both that copyright notice and this permission notice appear in 13supporting documentation, and that the names of Digital or Sun not be 14used in advertising or publicity pertaining to distribution of the 15software without specific, written prior permission. 16 17DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 18ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 19DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 20ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 21WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 22ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23SOFTWARE. 24 25SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 27NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 28ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 29ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 30PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 31OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 32THE USE OR PERFORMANCE OF THIS SOFTWARE. 33 34******************************************************************/ 35/* $XFree86: xc/lib/Xt/TMparse.c,v 3.10tsi Exp $ */ 36 37/* 38 39Copyright 1987, 1988, 1998 The Open Group 40 41Permission to use, copy, modify, distribute, and sell this software and its 42documentation for any purpose is hereby granted without fee, provided that 43the above copyright notice appear in all copies and that both that 44copyright notice and this permission notice appear in supporting 45documentation. 46 47The above copyright notice and this permission notice shall be included in 48all copies or substantial portions of the Software. 49 50THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 54AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 55CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 56 57Except as contained in this notice, the name of The Open Group shall not be 58used in advertising or otherwise to promote the sale, use or other dealings 59in this Software without prior written authorization from The Open Group. 60 61*/ 62 63#ifdef HAVE_CONFIG_H 64#include <config.h> 65#endif 66#include "IntrinsicI.h" 67#include "StringDefs.h" 68#include <ctype.h> 69#include <stdlib.h> 70#ifndef NOTASCII 71#define XK_LATIN1 72#endif 73#define XK_MISCELLANY 74#include <X11/keysymdef.h> 75 76#ifdef CACHE_TRANSLATIONS 77# ifdef REFCNT_TRANSLATIONS 78# define CACHED XtCacheAll | XtCacheRefCount 79# else 80# define CACHED XtCacheAll 81# endif 82#else 83# define CACHED XtCacheNone 84#endif 85 86#ifndef MAX 87#define MAX(a,b) (((a) > (b)) ? (a) : (b)) 88#endif 89 90#ifndef MIN 91#define MIN(a,b) (((a) < (b)) ? (a) : (b)) 92#endif 93 94static String XtNtranslationParseError = "translationParseError"; 95 96typedef int EventType; 97 98typedef String (*ParseProc)( 99 String /* str; */, 100 Opaque /* closure; */, 101 EventPtr /* event; */, 102 Boolean* /* error */); 103 104typedef TMShortCard Value; 105typedef void (*ModifierProc)(Value, LateBindingsPtr*, Boolean, Value*); 106 107typedef struct _ModifierRec { 108 char* name; 109 XrmQuark signature; 110 ModifierProc modifierParseProc; 111 Value value; 112} ModifierRec, *ModifierKeys; 113 114typedef struct _EventKey { 115 char *event; 116 XrmQuark signature; 117 EventType eventType; 118 ParseProc parseDetail; 119 Opaque closure; 120}EventKey, *EventKeys; 121 122typedef struct { 123 char *name; 124 XrmQuark signature; 125 Value value; 126} NameValueRec, *NameValueTable; 127 128static void ParseModImmed(Value, LateBindingsPtr*, Boolean, Value*); 129static void ParseModSym(Value, LateBindingsPtr*, Boolean, Value*); 130static String PanicModeRecovery(String); 131static String CheckForPoundSign(String, _XtTranslateOp, _XtTranslateOp *); 132static KeySym StringToKeySym(String, Boolean *); 133static ModifierRec modifiers[] = { 134 {"Shift", 0, ParseModImmed,ShiftMask}, 135 {"Lock", 0, ParseModImmed,LockMask}, 136 {"Ctrl", 0, ParseModImmed,ControlMask}, 137 {"Mod1", 0, ParseModImmed,Mod1Mask}, 138 {"Mod2", 0, ParseModImmed,Mod2Mask}, 139 {"Mod3", 0, ParseModImmed,Mod3Mask}, 140 {"Mod4", 0, ParseModImmed,Mod4Mask}, 141 {"Mod5", 0, ParseModImmed,Mod5Mask}, 142 {"Meta", 0, ParseModSym, XK_Meta_L}, 143 {"m", 0, ParseModSym, XK_Meta_L}, 144 {"h", 0, ParseModSym, XK_Hyper_L}, 145 {"su", 0, ParseModSym, XK_Super_L}, 146 {"a", 0, ParseModSym, XK_Alt_L}, 147 {"Hyper", 0, ParseModSym, XK_Hyper_L}, 148 {"Super", 0, ParseModSym, XK_Super_L}, 149 {"Alt", 0, ParseModSym, XK_Alt_L}, 150 {"Button1", 0, ParseModImmed,Button1Mask}, 151 {"Button2", 0, ParseModImmed,Button2Mask}, 152 {"Button3", 0, ParseModImmed,Button3Mask}, 153 {"Button4", 0, ParseModImmed,Button4Mask}, 154 {"Button5", 0, ParseModImmed,Button5Mask}, 155 {"c", 0, ParseModImmed,ControlMask}, 156 {"s", 0, ParseModImmed,ShiftMask}, 157 {"l", 0, ParseModImmed,LockMask}, 158}; 159 160static NameValueRec buttonNames[] = { 161 {"Button1", 0, Button1}, 162 {"Button2", 0, Button2}, 163 {"Button3", 0, Button3}, 164 {"Button4", 0, Button4}, 165 {"Button5", 0, Button5}, 166 {NULL, NULLQUARK, 0}, 167}; 168 169static NameValueRec motionDetails[] = { 170 {"Normal", 0, NotifyNormal}, 171 {"Hint", 0, NotifyHint}, 172 {NULL, NULLQUARK, 0}, 173}; 174 175static NameValueRec notifyModes[] = { 176 {"Normal", 0, NotifyNormal}, 177 {"Grab", 0, NotifyGrab}, 178 {"Ungrab", 0, NotifyUngrab}, 179 {"WhileGrabbed", 0, NotifyWhileGrabbed}, 180 {NULL, NULLQUARK, 0}, 181}; 182 183#if 0 184static NameValueRec notifyDetail[] = { 185 {"Ancestor", 0, NotifyAncestor}, 186 {"Virtual", 0, NotifyVirtual}, 187 {"Inferior", 0, NotifyInferior}, 188 {"Nonlinear", 0, NotifyNonlinear}, 189 {"NonlinearVirtual", 0, NotifyNonlinearVirtual}, 190 {"Pointer", 0, NotifyPointer}, 191 {"PointerRoot", 0, NotifyPointerRoot}, 192 {"DetailNone", 0, NotifyDetailNone}, 193 {NULL, NULLQUARK, 0}, 194}; 195 196static NameValueRec visibilityNotify[] = { 197 {"Unobscured", 0, VisibilityUnobscured}, 198 {"PartiallyObscured", 0, VisibilityPartiallyObscured}, 199 {"FullyObscured", 0, VisibilityFullyObscured}, 200 {NULL, NULLQUARK, 0}, 201}; 202 203static NameValueRec circulation[] = { 204 {"OnTop", 0, PlaceOnTop}, 205 {"OnBottom", 0, PlaceOnBottom}, 206 {NULL, NULLQUARK, 0}, 207}; 208 209static NameValueRec propertyChanged[] = { 210 {"NewValue", 0, PropertyNewValue}, 211 {"Delete", 0, PropertyDelete}, 212 {NULL, NULLQUARK, 0}, 213}; 214#endif /*0*/ 215 216static NameValueRec mappingNotify[] = { 217 {"Modifier", 0, MappingModifier}, 218 {"Keyboard", 0, MappingKeyboard}, 219 {"Pointer", 0, MappingPointer}, 220 {NULL, NULLQUARK, 0}, 221}; 222 223static String ParseKeySym(String, Opaque, EventPtr, Boolean*); 224static String ParseKeyAndModifiers(String, Opaque, EventPtr, Boolean*); 225static String ParseTable(String, Opaque, EventPtr, Boolean*); 226static String ParseImmed(String, Opaque, EventPtr, Boolean*); 227static String ParseAddModifier(String, Opaque, EventPtr, Boolean*); 228static String ParseNone(String, Opaque, EventPtr, Boolean*); 229static String ParseAtom(String, Opaque, EventPtr, Boolean*); 230 231static EventKey events[] = { 232 233/* Event Name, Quark, Event Type, Detail Parser, Closure */ 234 235{"KeyPress", NULLQUARK, KeyPress, ParseKeySym, NULL}, 236{"Key", NULLQUARK, KeyPress, ParseKeySym, NULL}, 237{"KeyDown", NULLQUARK, KeyPress, ParseKeySym, NULL}, 238{"Ctrl", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)ControlMask}, 239{"Shift", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)ShiftMask}, 240{"Meta", NULLQUARK, KeyPress, ParseKeyAndModifiers,(Opaque)NULL}, 241{"KeyUp", NULLQUARK, KeyRelease, ParseKeySym, NULL}, 242{"KeyRelease", NULLQUARK, KeyRelease, ParseKeySym, NULL}, 243 244{"ButtonPress", NULLQUARK, ButtonPress, ParseTable,(Opaque)buttonNames}, 245{"BtnDown", NULLQUARK, ButtonPress, ParseTable,(Opaque)buttonNames}, 246{"Btn1Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button1}, 247{"Btn2Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button2}, 248{"Btn3Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button3}, 249{"Btn4Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button4}, 250{"Btn5Down", NULLQUARK, ButtonPress, ParseImmed,(Opaque)Button5}, 251 252/* Event Name, Quark, Event Type, Detail Parser, Closure */ 253 254{"ButtonRelease", NULLQUARK, ButtonRelease, ParseTable,(Opaque)buttonNames}, 255{"BtnUp", NULLQUARK, ButtonRelease, ParseTable,(Opaque)buttonNames}, 256{"Btn1Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button1}, 257{"Btn2Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button2}, 258{"Btn3Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button3}, 259{"Btn4Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button4}, 260{"Btn5Up", NULLQUARK, ButtonRelease, ParseImmed,(Opaque)Button5}, 261 262{"MotionNotify", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, 263{"PtrMoved", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, 264{"Motion", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, 265{"MouseMoved", NULLQUARK, MotionNotify, ParseTable, (Opaque)motionDetails}, 266{"BtnMotion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)AnyButtonMask}, 267{"Btn1Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button1Mask}, 268{"Btn2Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button2Mask}, 269{"Btn3Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button3Mask}, 270{"Btn4Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button4Mask}, 271{"Btn5Motion", NULLQUARK, MotionNotify, ParseAddModifier, (Opaque)Button5Mask}, 272 273{"EnterNotify", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes}, 274{"Enter", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes}, 275{"EnterWindow", NULLQUARK, EnterNotify, ParseTable,(Opaque)notifyModes}, 276 277{"LeaveNotify", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes}, 278{"LeaveWindow", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes}, 279{"Leave", NULLQUARK, LeaveNotify, ParseTable,(Opaque)notifyModes}, 280 281/* Event Name, Quark, Event Type, Detail Parser, Closure */ 282 283{"FocusIn", NULLQUARK, FocusIn, ParseTable,(Opaque)notifyModes}, 284 285{"FocusOut", NULLQUARK, FocusOut, ParseTable,(Opaque)notifyModes}, 286 287{"KeymapNotify", NULLQUARK, KeymapNotify, ParseNone, NULL}, 288{"Keymap", NULLQUARK, KeymapNotify, ParseNone, NULL}, 289 290{"Expose", NULLQUARK, Expose, ParseNone, NULL}, 291 292{"GraphicsExpose", NULLQUARK, GraphicsExpose, ParseNone, NULL}, 293{"GrExp", NULLQUARK, GraphicsExpose, ParseNone, NULL}, 294 295{"NoExpose", NULLQUARK, NoExpose, ParseNone, NULL}, 296{"NoExp", NULLQUARK, NoExpose, ParseNone, NULL}, 297 298{"VisibilityNotify",NULLQUARK, VisibilityNotify,ParseNone, NULL}, 299{"Visible", NULLQUARK, VisibilityNotify,ParseNone, NULL}, 300 301{"CreateNotify", NULLQUARK, CreateNotify, ParseNone, NULL}, 302{"Create", NULLQUARK, CreateNotify, ParseNone, NULL}, 303 304/* Event Name, Quark, Event Type, Detail Parser, Closure */ 305 306{"DestroyNotify", NULLQUARK, DestroyNotify, ParseNone, NULL}, 307{"Destroy", NULLQUARK, DestroyNotify, ParseNone, NULL}, 308 309{"UnmapNotify", NULLQUARK, UnmapNotify, ParseNone, NULL}, 310{"Unmap", NULLQUARK, UnmapNotify, ParseNone, NULL}, 311 312{"MapNotify", NULLQUARK, MapNotify, ParseNone, NULL}, 313{"Map", NULLQUARK, MapNotify, ParseNone, NULL}, 314 315{"MapRequest", NULLQUARK, MapRequest, ParseNone, NULL}, 316{"MapReq", NULLQUARK, MapRequest, ParseNone, NULL}, 317 318{"ReparentNotify", NULLQUARK, ReparentNotify, ParseNone, NULL}, 319{"Reparent", NULLQUARK, ReparentNotify, ParseNone, NULL}, 320 321{"ConfigureNotify", NULLQUARK, ConfigureNotify, ParseNone, NULL}, 322{"Configure", NULLQUARK, ConfigureNotify, ParseNone, NULL}, 323 324{"ConfigureRequest",NULLQUARK, ConfigureRequest,ParseNone, NULL}, 325{"ConfigureReq", NULLQUARK, ConfigureRequest,ParseNone, NULL}, 326 327/* Event Name, Quark, Event Type, Detail Parser, Closure */ 328 329{"GravityNotify", NULLQUARK, GravityNotify, ParseNone, NULL}, 330{"Grav", NULLQUARK, GravityNotify, ParseNone, NULL}, 331 332{"ResizeRequest", NULLQUARK, ResizeRequest, ParseNone, NULL}, 333{"ResReq", NULLQUARK, ResizeRequest, ParseNone, NULL}, 334 335{"CirculateNotify", NULLQUARK, CirculateNotify, ParseNone, NULL}, 336{"Circ", NULLQUARK, CirculateNotify, ParseNone, NULL}, 337 338{"CirculateRequest",NULLQUARK, CirculateRequest,ParseNone, NULL}, 339{"CircReq", NULLQUARK, CirculateRequest,ParseNone, NULL}, 340 341{"PropertyNotify", NULLQUARK, PropertyNotify, ParseAtom, NULL}, 342{"Prop", NULLQUARK, PropertyNotify, ParseAtom, NULL}, 343 344{"SelectionClear", NULLQUARK, SelectionClear, ParseAtom, NULL}, 345{"SelClr", NULLQUARK, SelectionClear, ParseAtom, NULL}, 346 347{"SelectionRequest",NULLQUARK, SelectionRequest,ParseAtom, NULL}, 348{"SelReq", NULLQUARK, SelectionRequest,ParseAtom, NULL}, 349 350/* Event Name, Quark, Event Type, Detail Parser, Closure */ 351 352{"SelectionNotify", NULLQUARK, SelectionNotify, ParseAtom, NULL}, 353{"Select", NULLQUARK, SelectionNotify, ParseAtom, NULL}, 354 355{"ColormapNotify", NULLQUARK, ColormapNotify, ParseNone, NULL}, 356{"Clrmap", NULLQUARK, ColormapNotify, ParseNone, NULL}, 357 358{"ClientMessage", NULLQUARK, ClientMessage, ParseAtom, NULL}, 359{"Message", NULLQUARK, ClientMessage, ParseAtom, NULL}, 360 361{"MappingNotify", NULLQUARK, MappingNotify, ParseTable, (Opaque)mappingNotify}, 362{"Mapping", NULLQUARK, MappingNotify, ParseTable, (Opaque)mappingNotify}, 363 364#ifdef DEBUG 365# ifdef notdef 366{"Timer", NULLQUARK, _XtTimerEventType,ParseNone, NULL}, 367# endif /* notdef */ 368{"EventTimer", NULLQUARK, _XtEventTimerEventType,ParseNone,NULL}, 369#endif /* DEBUG */ 370 371/* Event Name, Quark, Event Type, Detail Parser, Closure */ 372 373}; 374 375#ifndef __UNIXOS2__ 376#define IsNewline(str) ((str) == '\n') 377#else 378#define IsNewline(str) ((str) == '\n' || (str) == '\r') 379#endif 380 381#define ScanFor(str, ch) \ 382 while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))) (str)++ 383 384#define ScanNumeric(str) while ('0' <= *(str) && *(str) <= '9') (str)++ 385 386#define ScanAlphanumeric(str) \ 387 while (('A' <= *(str) && *(str) <= 'Z') || \ 388 ('a' <= *(str) && *(str) <= 'z') || \ 389 ('0' <= *(str) && *(str) <= '9')) (str)++ 390 391#ifndef __UNIXOS2__ 392#define ScanWhitespace(str) \ 393 while (*(str) == ' ' || *(str) == '\t') (str)++ 394#else 395#define ScanWhitespace(str) \ 396 while (*(str) == ' ' || *(str) == '\t' || *(str) == '\r') (str)++ 397#endif 398 399static Boolean initialized = FALSE; 400static XrmQuark QMeta; 401static XrmQuark QCtrl; 402static XrmQuark QNone; 403static XrmQuark QAny; 404 405static void FreeEventSeq( 406 EventSeqPtr eventSeq) 407{ 408 register EventSeqPtr evs = eventSeq; 409 410 while (evs != NULL) { 411 evs->state = (StatePtr) evs; 412 if (evs->next != NULL 413 && evs->next->state == (StatePtr) evs->next) 414 evs->next = NULL; 415 evs = evs->next; 416 } 417 418 evs = eventSeq; 419 while (evs != NULL) { 420 register EventPtr event = evs; 421 evs = evs->next; 422 if (evs == event) evs = NULL; 423 XtFree((char *)event); 424 } 425} 426 427static void CompileNameValueTable( 428 NameValueTable table) 429{ 430 register int i; 431 432 for (i=0; table[i].name; i++) 433 table[i].signature = XrmPermStringToQuark(table[i].name); 434} 435 436static int OrderEvents(_Xconst void *a, _Xconst void *b) 437{ 438 return ((((_Xconst EventKey *)a)->signature < 439 ((_Xconst EventKey *)b)->signature) ? -1 : 1); 440} 441 442static void Compile_XtEventTable( 443 EventKeys table, 444 Cardinal count) 445{ 446 register int i; 447 register EventKeys entry = table; 448 449 for (i=count; --i >= 0; entry++) 450 entry->signature = XrmPermStringToQuark(entry->event); 451 qsort(table, count, sizeof(EventKey), OrderEvents); 452} 453 454static int OrderModifiers(_Xconst void *a, _Xconst void *b) 455{ 456 return ((((_Xconst ModifierRec *)a)->signature < 457 ((_Xconst ModifierRec *)b)->signature) ? -1 : 1); 458} 459 460static void Compile_XtModifierTable( 461 ModifierKeys table, 462 Cardinal count) 463{ 464 register int i; 465 register ModifierKeys entry = table; 466 467 for (i=count; --i >= 0; entry++) 468 entry->signature = XrmPermStringToQuark(entry->name); 469 qsort(table, count, sizeof(ModifierRec), OrderModifiers); 470} 471 472static String PanicModeRecovery( 473 String str) 474{ 475 ScanFor(str,'\n'); 476 if (*str == '\n') str++; 477 return str; 478 479} 480 481 482static void Syntax( 483 String str0,String str1) 484{ 485 Cardinal num_params = 2; 486 String params[2]; 487 488 params[0] = str0; 489 params[1] = str1; 490 XtWarningMsg(XtNtranslationParseError,"parseError",XtCXtToolkitError, 491 "translation table syntax error: %s %s",params,&num_params); 492} 493 494 495 496static Cardinal LookupTMEventType( 497 String eventStr, 498 Boolean *error) 499{ 500 register int i = 0, left, right; 501 register XrmQuark signature; 502 static int previous = 0; 503 504 LOCK_PROCESS; 505 if ((signature = StringToQuark(eventStr)) == events[previous].signature) { 506 UNLOCK_PROCESS; 507 return (Cardinal) previous; 508 } 509 510 left = 0; 511 right = XtNumber(events) - 1; 512 while (left <= right) { 513 i = (left + right) >> 1; 514 if (signature < events[i].signature) 515 right = i - 1; 516 else if (signature > events[i].signature) 517 left = i + 1; 518 else { 519 previous = i; 520 UNLOCK_PROCESS; 521 return (Cardinal) i; 522 } 523 } 524 525 Syntax("Unknown event type : ",eventStr); 526 *error = TRUE; 527 UNLOCK_PROCESS; 528 return (Cardinal) i; 529} 530 531static void StoreLateBindings( 532 KeySym keysymL, 533 Boolean notL, 534 KeySym keysymR, 535 Boolean notR, 536 LateBindingsPtr* lateBindings) 537{ 538 LateBindingsPtr temp; 539 Boolean pair = FALSE; 540 unsigned long count,number; 541 if (lateBindings != NULL){ 542 temp = *lateBindings; 543 if (temp != NULL) { 544 for (count = 0; temp[count].keysym; count++){/*EMPTY*/} 545 } 546 else count = 0; 547 if (! keysymR){ 548 number = 1;pair = FALSE; 549 } else{ 550 number = 2;pair = TRUE; 551 } 552 553 temp = (LateBindingsPtr)XtRealloc((char *)temp, 554 (unsigned)((count+number+1) * sizeof(LateBindings)) ); 555 *lateBindings = temp; 556 temp[count].knot = notL; 557 temp[count].pair = pair; 558 if (count == 0) 559 temp[count].ref_count = 1; 560 temp[count++].keysym = keysymL; 561 if (keysymR){ 562 temp[count].knot = notR; 563 temp[count].pair = FALSE; 564 temp[count].ref_count = 0; 565 temp[count++].keysym = keysymR; 566 } 567 temp[count].knot = temp[count].pair = FALSE; 568 temp[count].ref_count = 0; 569 temp[count].keysym = 0; 570 } 571} 572 573static void _XtParseKeysymMod( 574 String name, 575 LateBindingsPtr* lateBindings, 576 Boolean notFlag, 577 Value *valueP, 578 Boolean *error) 579{ 580 KeySym keySym; 581 keySym = StringToKeySym(name, error); 582 *valueP = 0; 583 if (keySym != NoSymbol) { 584 StoreLateBindings(keySym,notFlag,(KeySym) NULL,FALSE,lateBindings); 585 } 586} 587 588static Boolean _XtLookupModifier( 589 XrmQuark signature, 590 LateBindingsPtr* lateBindings, 591 Boolean notFlag, 592 Value *valueP, 593 Bool constMask) 594{ 595 register int i, left, right; 596 static int previous = 0; 597 598 LOCK_PROCESS; 599 if (signature == modifiers[previous].signature) { 600 if (constMask) *valueP = modifiers[previous].value; 601 else /* if (modifiers[previous].modifierParseProc) always true */ 602 (*modifiers[previous].modifierParseProc) 603 (modifiers[previous].value, lateBindings, notFlag, valueP); 604 UNLOCK_PROCESS; 605 return TRUE; 606 } 607 608 left = 0; 609 right = XtNumber(modifiers) - 1; 610 while (left <= right) { 611 i = (left + right) >> 1; 612 if (signature < modifiers[i].signature) 613 right = i - 1; 614 else if (signature > modifiers[i].signature) 615 left = i + 1; 616 else { 617 previous = i; 618 if (constMask) *valueP = modifiers[i].value; 619 else /* if (modifiers[i].modifierParseProc) always true */ 620 (*modifiers[i].modifierParseProc) 621 (modifiers[i].value, lateBindings, notFlag, valueP); 622 UNLOCK_PROCESS; 623 return TRUE; 624 } 625 } 626 UNLOCK_PROCESS; 627 return FALSE; 628} 629 630 631static String ScanIdent( 632 register String str) 633{ 634 ScanAlphanumeric(str); 635 while ( 636 ('A' <= *str && *str <= 'Z') 637 || ('a' <= *str && *str <= 'z') 638 || ('0' <= *str && *str <= '9') 639 || (*str == '-') 640 || (*str == '_') 641 || (*str == '$') 642 ) str++; 643 return str; 644} 645 646static String FetchModifierToken( 647 String str, 648 XrmQuark *token_return) 649{ 650 String start = str; 651 652 if (*str == '$') { 653 *token_return = QMeta; 654 str++; 655 return str; 656 } 657 if (*str == '^') { 658 *token_return = QCtrl; 659 str++; 660 return str; 661 } 662 str = ScanIdent(str); 663 if (start != str) { 664 char modStrbuf[100]; 665 char* modStr; 666 667 modStr = XtStackAlloc ((size_t)(str - start + 1), modStrbuf); 668 if (modStr == NULL) _XtAllocError (NULL); 669 (void) memmove(modStr, start, str-start); 670 modStr[str-start] = '\0'; 671 *token_return = XrmStringToQuark(modStr); 672 XtStackFree (modStr, modStrbuf); 673 return str; 674 } 675 return str; 676} 677 678static String ParseModifiers( 679 register String str, 680 EventPtr event, 681 Boolean* error) 682{ 683 register String start; 684 Boolean notFlag, exclusive, keysymAsMod; 685 Value maskBit; 686 XrmQuark Qmod; 687 688 ScanWhitespace(str); 689 start = str; 690 str = FetchModifierToken(str, &Qmod); 691 exclusive = FALSE; 692 if (start != str) { 693 if (Qmod == QNone) { 694 event->event.modifierMask = ~0; 695 event->event.modifiers = 0; 696 ScanWhitespace(str); 697 return str; 698 } else if (Qmod == QAny) { /*backward compatability*/ 699 event->event.modifierMask = 0; 700 event->event.modifiers = AnyModifier; 701 ScanWhitespace(str); 702 return str; 703 } 704 str = start; /*if plain modifier, reset to beginning */ 705 } 706 else while (*str == '!' || *str == ':') { 707 if (*str == '!') { 708 exclusive = TRUE; 709 str++; 710 ScanWhitespace(str); 711 } 712 if (*str == ':') { 713 event->event.standard = TRUE; 714 str++; 715 ScanWhitespace(str); 716 } 717 } 718 719 while (*str != '<') { 720 if (*str == '~') { 721 notFlag = TRUE; 722 str++; 723 } else 724 notFlag = FALSE; 725 if (*str == '@') { 726 keysymAsMod = TRUE; 727 str++; 728 } 729 else keysymAsMod = FALSE; 730 start = str; 731 str = FetchModifierToken(str, &Qmod); 732 if (start == str) { 733 Syntax("Modifier or '<' expected",""); 734 *error = TRUE; 735 return PanicModeRecovery(str); 736 } 737 if (keysymAsMod) { 738 _XtParseKeysymMod(XrmQuarkToString(Qmod), 739 &event->event.lateModifiers, 740 notFlag,&maskBit, error); 741 if (*error) 742 return PanicModeRecovery(str); 743 744 } else 745 if (!_XtLookupModifier(Qmod, &event->event.lateModifiers, 746 notFlag, &maskBit, FALSE)) { 747 Syntax("Unknown modifier name: ", XrmQuarkToString(Qmod)); 748 *error = TRUE; 749 return PanicModeRecovery(str); 750 } 751 event->event.modifierMask |= maskBit; 752 if (notFlag) event->event.modifiers &= ~maskBit; 753 else event->event.modifiers |= maskBit; 754 ScanWhitespace(str); 755 } 756 if (exclusive) event->event.modifierMask = ~0; 757 return str; 758} 759 760static String ParseXtEventType( 761 register String str, 762 EventPtr event, 763 Cardinal *tmEventP, 764 Boolean* error) 765{ 766 String start = str; 767 char eventTypeStrbuf[100]; 768 char* eventTypeStr; 769 770 ScanAlphanumeric(str); 771 eventTypeStr = XtStackAlloc ((size_t)(str - start + 1), eventTypeStrbuf); 772 if (eventTypeStr == NULL) _XtAllocError (NULL); 773 (void) memmove(eventTypeStr, start, str-start); 774 eventTypeStr[str-start] = '\0'; 775 *tmEventP = LookupTMEventType(eventTypeStr,error); 776 XtStackFree (eventTypeStr, eventTypeStrbuf); 777 if (*error) 778 return PanicModeRecovery(str); 779 event->event.eventType = events[*tmEventP].eventType; 780 return str; 781} 782 783static unsigned long StrToHex( 784 String str) 785{ 786 register char c; 787 register unsigned long val = 0; 788 789 while ((c = *str)) { 790 if ('0' <= c && c <= '9') val = val*16+c-'0'; 791 else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10; 792 else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10; 793 else return 0; 794 str++; 795 } 796 797 return val; 798} 799 800static unsigned long StrToOct( 801 String str) 802{ 803 register char c; 804 register unsigned long val = 0; 805 806 while ((c = *str)) { 807 if ('0' <= c && c <= '7') val = val*8+c-'0'; else return 0; 808 str++; 809 } 810 811 return val; 812} 813 814static unsigned long StrToNum( 815 String str) 816{ 817 register char c; 818 register unsigned long val = 0; 819 820 if (*str == '0') { 821 str++; 822 if (*str == 'x' || *str == 'X') return StrToHex(++str); 823 else return StrToOct(str); 824 } 825 826 while ((c = *str)) { 827 if ('0' <= c && c <= '9') val = val*10+c-'0'; 828 else return 0; 829 str++; 830 } 831 832 return val; 833} 834 835static KeySym StringToKeySym( 836 String str, 837 Boolean *error) 838{ 839 KeySym k; 840 841 if (str == NULL || *str == '\0') return (KeySym) 0; 842 843#ifndef NOTASCII 844 /* special case single character ASCII, for speed */ 845 if (*(str+1) == '\0') { 846 if (' ' <= *str && *str <= '~') return XK_space + (*str - ' '); 847 } 848#endif 849 850 if ('0' <= *str && *str <= '9') return (KeySym) StrToNum(str); 851 k = XStringToKeysym(str); 852 if (k != NoSymbol) return k; 853 854#ifdef NOTASCII 855 /* fall-back case to preserve backwards compatibility; no-one 856 * should be relying upon this! 857 */ 858 if (*(str+1) == '\0') return (KeySym) *str; 859#endif 860 861 Syntax("Unknown keysym name: ", str); 862 *error = TRUE; 863 return NoSymbol; 864} 865/* ARGSUSED */ 866static void ParseModImmed( 867 Value value, 868 LateBindingsPtr* lateBindings, 869 Boolean notFlag, 870 Value* valueP) 871{ 872 *valueP = value; 873} 874 875 /* is only valid with keysyms that have an _L and _R in their name; 876 * and ignores keysym lookup errors (i.e. assumes only valid keysyms) 877 */ 878static void ParseModSym( 879 Value value, 880 LateBindingsPtr* lateBindings, 881 Boolean notFlag, 882 Value* valueP) 883{ 884 register KeySym keysymL = (KeySym)value; 885 register KeySym keysymR = keysymL + 1; /* valid for supported keysyms */ 886 StoreLateBindings(keysymL,notFlag,keysymR,notFlag,lateBindings); 887 *valueP = 0; 888} 889 890#ifdef sparc 891/* 892 * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that 893 * causes the value of the most recently used variable to be returned instead 894 * of the value passed in. 895 */ 896static String stupid_optimizer_kludge; 897#define BROKEN_OPTIMIZER_HACK(val) stupid_optimizer_kludge = (val) 898#else 899#define BROKEN_OPTIMIZER_HACK(val) val 900#endif 901 902/* ARGSUSED */ 903static String ParseImmed( 904 register String str, 905 register Opaque closure, 906 register EventPtr event, 907 Boolean* error) 908{ 909 event->event.eventCode = (unsigned long)closure; 910 event->event.eventCodeMask = ~0UL; 911 912 return BROKEN_OPTIMIZER_HACK(str); 913} 914 915/* ARGSUSED */ 916static String ParseAddModifier( 917 register String str, 918 register Opaque closure, 919 register EventPtr event, 920 Boolean* error) 921{ 922 register unsigned long modval = (unsigned long)closure; 923 event->event.modifiers |= modval; 924 if (modval != AnyButtonMask) /* AnyButtonMask is don't-care mask */ 925 event->event.modifierMask |= modval; 926 927 return BROKEN_OPTIMIZER_HACK(str); 928} 929 930 931static String ParseKeyAndModifiers( 932 String str, 933 Opaque closure, 934 EventPtr event, 935 Boolean* error) 936{ 937 str = ParseKeySym(str, closure, event,error); 938 if ((unsigned long) closure == 0) { 939 Value metaMask; /* unused */ 940 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE, 941 &metaMask, FALSE); 942 } else { 943 event->event.modifiers |= (unsigned long) closure; 944 event->event.modifierMask |= (unsigned long) closure; 945 } 946 return str; 947} 948 949/*ARGSUSED*/ 950static String ParseKeySym( 951 register String str, 952 Opaque closure, 953 EventPtr event, 954 Boolean* error) 955{ 956 char *start; 957 char keySymNamebuf[100]; 958 char* keySymName; 959 960 ScanWhitespace(str); 961 962 if (*str == '\\') { 963 keySymName = keySymNamebuf; 964 str++; 965 keySymName[0] = *str; 966 if (*str != '\0' && !IsNewline(*str)) str++; 967 keySymName[1] = '\0'; 968 event->event.eventCode = StringToKeySym(keySymName, error); 969 event->event.eventCodeMask = ~0L; 970 } else if (*str == ',' || *str == ':' || 971 /* allow leftparen to be single char symbol, 972 * for backwards compatibility 973 */ 974 (*str == '(' && *(str+1) >= '0' && *(str+1) <= '9')) { 975 keySymName = keySymNamebuf; /* just so we can stackfree it later */ 976 /* no detail */ 977 event->event.eventCode = 0L; 978 event->event.eventCodeMask = 0L; 979 } else { 980 start = str; 981 while ( 982 *str != ',' 983 && *str != ':' 984 && *str != ' ' 985 && *str != '\t' 986 && !IsNewline(*str) 987 && (*str != '(' || *(str+1) <= '0' || *(str+1) >= '9') 988 && *str != '\0') str++; 989 keySymName = XtStackAlloc ((size_t)(str - start + 1), keySymNamebuf); 990 (void) memmove(keySymName, start, str-start); 991 keySymName[str-start] = '\0'; 992 event->event.eventCode = StringToKeySym(keySymName, error); 993 event->event.eventCodeMask = ~0L; 994 } 995 if (*error) { 996 /* We never get here when keySymName hasn't been allocated */ 997 if (keySymName[0] == '<') { 998 /* special case for common error */ 999 XtWarningMsg(XtNtranslationParseError, "missingComma", 1000 XtCXtToolkitError, 1001 "... possibly due to missing ',' in event sequence.", 1002 (String*)NULL, (Cardinal*)NULL); 1003 } 1004 XtStackFree (keySymName, keySymNamebuf); 1005 return PanicModeRecovery(str); 1006 } 1007 if (event->event.standard) 1008 event->event.matchEvent = _XtMatchUsingStandardMods; 1009 else 1010 event->event.matchEvent = _XtMatchUsingDontCareMods; 1011 1012 XtStackFree (keySymName, keySymNamebuf); 1013 1014 return str; 1015} 1016 1017static String ParseTable( 1018 register String str, 1019 Opaque closure, 1020 EventPtr event, 1021 Boolean* error) 1022{ 1023 register String start = str; 1024 register XrmQuark signature; 1025 NameValueTable table = (NameValueTable) closure; 1026 char tableSymName[100]; 1027 1028 event->event.eventCode = 0L; 1029 ScanAlphanumeric(str); 1030 if (str == start) {event->event.eventCodeMask = 0L; return str; } 1031 if (str-start >= 99) { 1032 Syntax("Invalid Detail Type (string is too long).", ""); 1033 *error = TRUE; 1034 return str; 1035 } 1036 (void) memmove(tableSymName, start, str-start); 1037 tableSymName[str-start] = '\0'; 1038 signature = StringToQuark(tableSymName); 1039 for (; table->signature != NULLQUARK; table++) 1040 if (table->signature == signature) { 1041 event->event.eventCode = table->value; 1042 event->event.eventCodeMask = ~0L; 1043 return str; 1044 } 1045 1046 Syntax("Unknown Detail Type: ", tableSymName); 1047 *error = TRUE; 1048 return PanicModeRecovery(str); 1049} 1050 1051/*ARGSUSED*/ 1052static String ParseNone( 1053 String str, 1054 Opaque closure, 1055 EventPtr event, 1056 Boolean* error) 1057{ 1058 event->event.eventCode = 0; 1059 event->event.eventCodeMask = 0; 1060 1061 return BROKEN_OPTIMIZER_HACK(str); 1062} 1063 1064/*ARGSUSED*/ 1065static String ParseAtom( 1066 String str, 1067 Opaque closure, 1068 EventPtr event, 1069 Boolean* error) 1070{ 1071 ScanWhitespace(str); 1072 1073 if (*str == ',' || *str == ':') { 1074 /* no detail */ 1075 event->event.eventCode = 0L; 1076 event->event.eventCodeMask = 0L; 1077 } else { 1078 char *start, atomName[1000]; 1079 start = str; 1080 while ( 1081 *str != ',' 1082 && *str != ':' 1083 && *str != ' ' 1084 && *str != '\t' 1085 && !IsNewline(*str) 1086 && *str != '\0') str++; 1087 if (str-start >= 999) { 1088 Syntax( "Atom name must be less than 1000 characters long.", "" ); 1089 *error = TRUE; 1090 return str; 1091 } 1092 (void) memmove(atomName, start, str-start); 1093 atomName[str-start] = '\0'; 1094 event->event.eventCode = XrmStringToQuark(atomName); 1095 event->event.matchEvent = _XtMatchAtom; 1096 } 1097 return str; 1098} 1099 1100static ModifierMask buttonModifierMasks[] = { 1101 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask 1102}; 1103static String ParseRepeat(String, int *, Boolean *, Boolean *); 1104 1105static String ParseEvent( 1106 register String str, 1107 EventPtr event, 1108 int* reps, 1109 Boolean* plus, 1110 Boolean* error) 1111{ 1112 Cardinal tmEvent; 1113 1114 str = ParseModifiers(str, event,error); 1115 if (*error) return str; 1116 if (*str != '<') { 1117 Syntax("Missing '<' while parsing event type.",""); 1118 *error = TRUE; 1119 return PanicModeRecovery(str); 1120 } 1121 else str++; 1122 str = ParseXtEventType(str, event, &tmEvent,error); 1123 if (*error) return str; 1124 if (*str != '>'){ 1125 Syntax("Missing '>' while parsing event type",""); 1126 *error = TRUE; 1127 return PanicModeRecovery(str); 1128 } 1129 else str++; 1130 if (*str == '(') { 1131 str = ParseRepeat(str, reps, plus, error); 1132 if (*error) return str; 1133 } 1134 str = (*(events[tmEvent].parseDetail))( 1135 str, events[tmEvent].closure, event,error); 1136 if (*error) return str; 1137 1138/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t. 1139 * modifiers in grabs. 1140 */ 1141 if ((event->event.eventType == ButtonRelease) 1142 && (event->event.modifiers | event->event.modifierMask) /* any */ 1143 && (event->event.modifiers != AnyModifier)) 1144 { 1145 event->event.modifiers 1146 |= buttonModifierMasks[event->event.eventCode]; 1147 /* the button that is going up will always be in the modifiers... */ 1148 } 1149 1150 return str; 1151} 1152 1153static String ParseQuotedStringEvent( 1154 register String str, 1155 register EventPtr event, 1156 Boolean *error) 1157{ 1158 Value metaMask; 1159 char s[2]; 1160 1161 if (*str=='^') { 1162 str++; 1163 event->event.modifiers = ControlMask; 1164 } else if (*str == '$') { 1165 str++; 1166 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE, 1167 &metaMask, FALSE); 1168 } 1169 if (*str == '\\') 1170 str++; 1171 s[0] = *str; 1172 s[1] = '\0'; 1173 if (*str != '\0' && !IsNewline(*str)) str++; 1174 event->event.eventType = KeyPress; 1175 event->event.eventCode = StringToKeySym(s, error); 1176 if (*error) return PanicModeRecovery(str); 1177 event->event.eventCodeMask = ~0L; 1178 event->event.matchEvent = _XtMatchUsingStandardMods; 1179 event->event.standard = TRUE; 1180 1181 return str; 1182} 1183 1184 1185static EventSeqRec timerEventRec = { 1186 {0, 0, NULL, _XtEventTimerEventType, 0L, 0L, NULL, False}, 1187 /* (StatePtr) -1 */ NULL, 1188 NULL, 1189 NULL 1190}; 1191 1192static void RepeatDown( 1193 EventPtr *eventP, 1194 int reps, 1195 ActionPtr **actionsP) 1196{ 1197 EventRec upEventRec; 1198 register EventPtr event, downEvent; 1199 EventPtr upEvent = &upEventRec; 1200 register int i; 1201 1202 downEvent = event = *eventP; 1203 *upEvent = *downEvent; 1204 upEvent->event.eventType = ((event->event.eventType == ButtonPress) ? 1205 ButtonRelease : KeyRelease); 1206 if ((upEvent->event.eventType == ButtonRelease) 1207 && (upEvent->event.modifiers != AnyModifier) 1208 && (upEvent->event.modifiers | upEvent->event.modifierMask)) 1209 upEvent->event.modifiers 1210 |= buttonModifierMasks[event->event.eventCode]; 1211 1212 if (event->event.lateModifiers) 1213 event->event.lateModifiers->ref_count += (reps - 1) * 2; 1214 1215 for (i=1; i<reps; i++) { 1216 1217 /* up */ 1218 event->next = XtNew(EventSeqRec); 1219 event = event->next; 1220 *event = *upEvent; 1221 1222 /* timer */ 1223 event->next = XtNew(EventSeqRec); 1224 event = event->next; 1225 *event = timerEventRec; 1226 1227 /* down */ 1228 event->next = XtNew(EventSeqRec); 1229 event = event->next; 1230 *event = *downEvent; 1231 1232 } 1233 1234 event->next = NULL; 1235 *eventP = event; 1236 *actionsP = &event->actions; 1237} 1238 1239static void RepeatDownPlus( 1240 EventPtr *eventP, 1241 int reps, 1242 ActionPtr **actionsP) 1243{ 1244 EventRec upEventRec; 1245 register EventPtr event, downEvent, lastDownEvent = NULL; 1246 EventPtr upEvent = &upEventRec; 1247 register int i; 1248 1249 downEvent = event = *eventP; 1250 *upEvent = *downEvent; 1251 upEvent->event.eventType = ((event->event.eventType == ButtonPress) ? 1252 ButtonRelease : KeyRelease); 1253 if ((upEvent->event.eventType == ButtonRelease) 1254 && (upEvent->event.modifiers != AnyModifier) 1255 && (upEvent->event.modifiers | upEvent->event.modifierMask)) 1256 upEvent->event.modifiers 1257 |= buttonModifierMasks[event->event.eventCode]; 1258 1259 if (event->event.lateModifiers) 1260 event->event.lateModifiers->ref_count += reps * 2 - 1; 1261 1262 for (i=0; i<reps; i++) { 1263 1264 if (i > 0) { 1265 /* down */ 1266 event->next = XtNew(EventSeqRec); 1267 event = event->next; 1268 *event = *downEvent; 1269 } 1270 lastDownEvent = event; 1271 1272 /* up */ 1273 event->next = XtNew(EventSeqRec); 1274 event = event->next; 1275 *event = *upEvent; 1276 1277 /* timer */ 1278 event->next = XtNew(EventSeqRec); 1279 event = event->next; 1280 *event = timerEventRec; 1281 1282 } 1283 1284 event->next = lastDownEvent; 1285 *eventP = event; 1286 *actionsP = &lastDownEvent->actions; 1287} 1288 1289static void RepeatUp( 1290 EventPtr *eventP, 1291 int reps, 1292 ActionPtr **actionsP) 1293{ 1294 EventRec upEventRec; 1295 register EventPtr event, downEvent; 1296 EventPtr upEvent = &upEventRec; 1297 register int i; 1298 1299 /* the event currently sitting in *eventP is an "up" event */ 1300 /* we want to make it a "down" event followed by an "up" event, */ 1301 /* so that sequence matching on the "state" side works correctly. */ 1302 1303 downEvent = event = *eventP; 1304 *upEvent = *downEvent; 1305 downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ? 1306 ButtonPress : KeyPress); 1307 if ((downEvent->event.eventType == ButtonPress) 1308 && (downEvent->event.modifiers != AnyModifier) 1309 && (downEvent->event.modifiers | downEvent->event.modifierMask)) 1310 downEvent->event.modifiers 1311 &= ~buttonModifierMasks[event->event.eventCode]; 1312 1313 if (event->event.lateModifiers) 1314 event->event.lateModifiers->ref_count += reps * 2 - 1; 1315 1316 /* up */ 1317 event->next = XtNew(EventSeqRec); 1318 event = event->next; 1319 *event = *upEvent; 1320 1321 for (i=1; i<reps; i++) { 1322 1323 /* timer */ 1324 event->next = XtNew(EventSeqRec); 1325 event = event->next; 1326 *event = timerEventRec; 1327 1328 /* down */ 1329 event->next = XtNew(EventSeqRec); 1330 event = event->next; 1331 *event = *downEvent; 1332 1333 /* up */ 1334 event->next = XtNew(EventSeqRec); 1335 event = event->next; 1336 *event = *upEvent; 1337 1338 } 1339 1340 event->next = NULL; 1341 *eventP = event; 1342 *actionsP = &event->actions; 1343} 1344 1345static void RepeatUpPlus( 1346 EventPtr *eventP, 1347 int reps, 1348 ActionPtr **actionsP) 1349{ 1350 EventRec upEventRec; 1351 register EventPtr event, downEvent, lastUpEvent = NULL; 1352 EventPtr upEvent = &upEventRec; 1353 register int i; 1354 1355 /* the event currently sitting in *eventP is an "up" event */ 1356 /* we want to make it a "down" event followed by an "up" event, */ 1357 /* so that sequence matching on the "state" side works correctly. */ 1358 1359 downEvent = event = *eventP; 1360 *upEvent = *downEvent; 1361 downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ? 1362 ButtonPress : KeyPress); 1363 if ((downEvent->event.eventType == ButtonPress) 1364 && (downEvent->event.modifiers != AnyModifier) 1365 && (downEvent->event.modifiers | downEvent->event.modifierMask)) 1366 downEvent->event.modifiers 1367 &= ~buttonModifierMasks[event->event.eventCode]; 1368 1369 if (event->event.lateModifiers) 1370 event->event.lateModifiers->ref_count += reps * 2; 1371 1372 for (i=0; i<reps; i++) { 1373 1374 /* up */ 1375 event->next = XtNew(EventSeqRec); 1376 lastUpEvent = event = event->next; 1377 *event = *upEvent; 1378 1379 /* timer */ 1380 event->next = XtNew(EventSeqRec); 1381 event = event->next; 1382 *event = timerEventRec; 1383 1384 /* down */ 1385 event->next = XtNew(EventSeqRec); 1386 event = event->next; 1387 *event = *downEvent; 1388 1389 } 1390 1391 event->next = lastUpEvent; 1392 *eventP = event; 1393 *actionsP = &lastUpEvent->actions; 1394} 1395 1396static void RepeatOther( 1397 EventPtr *eventP, 1398 int reps, 1399 ActionPtr **actionsP) 1400{ 1401 register EventPtr event, tempEvent; 1402 register int i; 1403 1404 tempEvent = event = *eventP; 1405 1406 if (event->event.lateModifiers) 1407 event->event.lateModifiers->ref_count += reps - 1; 1408 1409 for (i=1; i<reps; i++) { 1410 event->next = XtNew(EventSeqRec); 1411 event = event->next; 1412 *event = *tempEvent; 1413 } 1414 1415 *eventP = event; 1416 *actionsP = &event->actions; 1417} 1418 1419static void RepeatOtherPlus( 1420 EventPtr *eventP, 1421 int reps, 1422 ActionPtr **actionsP) 1423{ 1424 register EventPtr event, tempEvent; 1425 register int i; 1426 1427 tempEvent = event = *eventP; 1428 1429 if (event->event.lateModifiers) 1430 event->event.lateModifiers->ref_count += reps - 1; 1431 1432 for (i=1; i<reps; i++) { 1433 event->next = XtNew(EventSeqRec); 1434 event = event->next; 1435 *event = *tempEvent; 1436 } 1437 1438 event->next = event; 1439 *eventP = event; 1440 *actionsP = &event->actions; 1441} 1442 1443static void RepeatEvent( 1444 EventPtr *eventP, 1445 int reps, 1446 Boolean plus, 1447 ActionPtr **actionsP) 1448{ 1449 switch ((*eventP)->event.eventType) { 1450 1451 case ButtonPress: 1452 case KeyPress: 1453 if (plus) RepeatDownPlus(eventP, reps, actionsP); 1454 else RepeatDown(eventP, reps, actionsP); 1455 break; 1456 1457 case ButtonRelease: 1458 case KeyRelease: 1459 if (plus) RepeatUpPlus(eventP, reps, actionsP); 1460 else RepeatUp(eventP, reps, actionsP); 1461 break; 1462 1463 default: 1464 if (plus) RepeatOtherPlus(eventP, reps, actionsP); 1465 else RepeatOther(eventP, reps, actionsP); 1466 } 1467} 1468 1469static String ParseRepeat( 1470 register String str, 1471 int *reps, 1472 Boolean *plus, Boolean *error) 1473{ 1474 1475 /*** Parse the repetitions, for double click etc... ***/ 1476 if (*str != '(' || !(isdigit(str[1]) || str[1] == '+' || str[1] == ')')) 1477 return str; 1478 str++; 1479 if (isdigit(*str)) { 1480 String start = str; 1481 char repStr[7]; 1482 size_t len; 1483 1484 ScanNumeric(str); 1485 len = (str - start); 1486 if (len < sizeof repStr) { 1487 (void) memmove(repStr, start, len); 1488 repStr[len] = '\0'; 1489 *reps = StrToNum(repStr); 1490 } else { 1491 Syntax("Repeat count too large.", ""); 1492 *error = TRUE; 1493 return str; 1494 } 1495 } 1496 if (*reps == 0) { 1497 Syntax("Missing repeat count.",""); 1498 *error = True; 1499 return str; 1500 } 1501 1502 if (*str == '+') { 1503 *plus = TRUE; 1504 str++; 1505 } 1506 if (*str == ')') 1507 str++; 1508 else { 1509 Syntax("Missing ')'.",""); 1510 *error = TRUE; 1511 } 1512 1513 return str; 1514} 1515 1516/*********************************************************************** 1517 * ParseEventSeq 1518 * Parses the left hand side of a translation table production 1519 * up to, and consuming the ":". 1520 * Takes a pointer to a char* (where to start parsing) and returns an 1521 * event seq (in a passed in variable), having updated the String 1522 **********************************************************************/ 1523 1524static String ParseEventSeq( 1525 register String str, 1526 EventSeqPtr *eventSeqP, 1527 ActionPtr **actionsP, 1528 Boolean *error) 1529{ 1530 EventSeqPtr *nextEvent = eventSeqP; 1531 1532 *eventSeqP = NULL; 1533 1534 while ( *str != '\0' && !IsNewline(*str)) { 1535 static Event nullEvent = 1536 {0, 0,0L, 0, 0L, 0L,_XtRegularMatch,FALSE}; 1537 EventPtr event; 1538 1539 ScanWhitespace(str); 1540 1541 if (*str == '"') { 1542 str++; 1543 while (*str != '"' && *str != '\0' && !IsNewline(*str)) { 1544 event = XtNew(EventRec); 1545 event->event = nullEvent; 1546 event->state = /* (StatePtr) -1 */ NULL; 1547 event->next = NULL; 1548 event->actions = NULL; 1549 str = ParseQuotedStringEvent(str, event,error); 1550 if (*error) { 1551 XtWarningMsg(XtNtranslationParseError, "nonLatin1", 1552 XtCXtToolkitError, 1553 "... probably due to non-Latin1 character in quoted string", 1554 (String*)NULL, (Cardinal*)NULL); 1555 return PanicModeRecovery(str); 1556 } 1557 *nextEvent = event; 1558 *actionsP = &event->actions; 1559 nextEvent = &event->next; 1560 } 1561 if (*str != '"') { 1562 Syntax("Missing '\"'.",""); 1563 *error = TRUE; 1564 return PanicModeRecovery(str); 1565 } 1566 else str++; 1567 } else { 1568 int reps = 0; 1569 Boolean plus = FALSE; 1570 1571 event = XtNew(EventRec); 1572 event->event = nullEvent; 1573 event->state = /* (StatePtr) -1 */ NULL; 1574 event->next = NULL; 1575 event->actions = NULL; 1576 1577 str = ParseEvent(str, event, &reps, &plus, error); 1578 if (*error) return str; 1579 *nextEvent = event; 1580 *actionsP = &event->actions; 1581 if (reps > 1 || plus) 1582 RepeatEvent(&event, reps, plus, actionsP); 1583 nextEvent = &event->next; 1584 } 1585 ScanWhitespace(str); 1586 if (*str == ':') break; 1587 else { 1588 if (*str != ',') { 1589 Syntax("',' or ':' expected while parsing event sequence.",""); 1590 *error = TRUE; 1591 return PanicModeRecovery(str); 1592 } else str++; 1593 } 1594 } 1595 1596 if (*str != ':') { 1597 Syntax("Missing ':'after event sequence.",""); 1598 *error = TRUE; 1599 return PanicModeRecovery(str); 1600 } else str++; 1601 1602 return str; 1603} 1604 1605 1606static String ParseActionProc( 1607 register String str, 1608 XrmQuark *actionProcNameP, 1609 Boolean *error) 1610{ 1611 register String start = str; 1612 char procName[200]; 1613 1614 str = ScanIdent(str); 1615 if (str-start >= 199) { 1616 Syntax("Action procedure name is longer than 199 chars",""); 1617 *error = TRUE; 1618 return str; 1619 } 1620 (void) memmove(procName, start, str-start); 1621 procName[str-start] = '\0'; 1622 *actionProcNameP = XrmStringToQuark( procName ); 1623 return str; 1624} 1625 1626 1627static String ParseString( 1628 register String str, 1629 String *strP) 1630{ 1631 register String start; 1632 1633 if (*str == '"') { 1634 register unsigned prev_len, len; 1635 str++; 1636 start = str; 1637 *strP = NULL; 1638 prev_len = 0; 1639 1640 while (*str != '"' && *str != '\0') { 1641 /* \" produces double quote embedded in a quoted parameter 1642 * \\" produces backslash as last character of a quoted parameter 1643 */ 1644 if (*str == '\\' && 1645 (*(str+1) == '"' || (*(str+1) == '\\' && *(str+2) == '"'))) { 1646 len = prev_len + (str-start+2); 1647 *strP = XtRealloc(*strP, len); 1648 (void) memmove(*strP + prev_len, start, str-start); 1649 prev_len = len-1; 1650 str++; 1651 (*strP)[prev_len-1] = *str; 1652 (*strP)[prev_len] = '\0'; 1653 start = str+1; 1654 } 1655 str++; 1656 } 1657 len = prev_len + (str-start+1); 1658 *strP = XtRealloc(*strP, len); 1659 (void) memmove( *strP + prev_len, start, str-start); 1660 (*strP)[len-1] = '\0'; 1661 if (*str == '"') str++; else 1662 XtWarningMsg(XtNtranslationParseError,"parseString", 1663 XtCXtToolkitError,"Missing '\"'.", 1664 (String *)NULL, (Cardinal *)NULL); 1665 } else { 1666 /* scan non-quoted string, stop on whitespace, ',' or ')' */ 1667 start = str; 1668 while (*str != ' ' 1669 && *str != '\t' 1670 && *str != ',' 1671 && *str != ')' 1672 && !IsNewline(*str) 1673 && *str != '\0') str++; 1674 *strP = __XtMalloc((unsigned)(str-start+1)); 1675 (void) memmove(*strP, start, str-start); 1676 (*strP)[str-start] = '\0'; 1677 } 1678 return str; 1679} 1680 1681 1682static String ParseParamSeq( 1683 register String str, 1684 String **paramSeqP, 1685 Cardinal *paramNumP) 1686{ 1687 typedef struct _ParamRec *ParamPtr; 1688 typedef struct _ParamRec { 1689 ParamPtr next; 1690 String param; 1691 } ParamRec; 1692 1693 ParamPtr params = NULL; 1694 register Cardinal num_params = 0; 1695 register Cardinal i; 1696 1697 ScanWhitespace(str); 1698 while (*str != ')' && *str != '\0' && !IsNewline(*str)) { 1699 String newStr; 1700 str = ParseString(str, &newStr); 1701 if (newStr != NULL) { 1702 ParamPtr temp = (ParamRec*) 1703 ALLOCATE_LOCAL( (unsigned)sizeof(ParamRec) ); 1704 if (temp == NULL) _XtAllocError (NULL); 1705 1706 num_params++; 1707 temp->next = params; 1708 params = temp; 1709 temp->param = newStr; 1710 ScanWhitespace(str); 1711 if (*str == ',') { 1712 str++; 1713 ScanWhitespace(str); 1714 } 1715 } 1716 } 1717 1718 if (num_params != 0) { 1719 String *paramP = (String *) 1720 __XtMalloc( (unsigned)(num_params+1) * sizeof(String) ); 1721 *paramSeqP = paramP; 1722 *paramNumP = num_params; 1723 paramP += num_params; /* list is LIFO right now */ 1724 *paramP-- = NULL; 1725 for (i=0; i < num_params; i++) { 1726 ParamPtr next = params->next; 1727 *paramP-- = params->param; 1728 DEALLOCATE_LOCAL( (char *)params ); 1729 params = next; 1730 } 1731 } else { 1732 *paramSeqP = NULL; 1733 *paramNumP = 0; 1734 } 1735 1736 return str; 1737} 1738 1739static String ParseAction( 1740 String str, 1741 ActionPtr actionP, 1742 XrmQuark* quarkP, 1743 Boolean* error) 1744{ 1745 str = ParseActionProc(str, quarkP, error); 1746 if (*error) return str; 1747 1748 if (*str == '(') { 1749 str++; 1750 str = ParseParamSeq(str, &actionP->params, &actionP->num_params); 1751 } else { 1752 Syntax("Missing '(' while parsing action sequence",""); 1753 *error = TRUE; 1754 return str; 1755 } 1756 if (*str == ')') str++; 1757 else{ 1758 Syntax("Missing ')' while parsing action sequence",""); 1759 *error = TRUE; 1760 return str; 1761 } 1762 return str; 1763} 1764 1765 1766static String ParseActionSeq( 1767 TMParseStateTree parseTree, 1768 String str, 1769 ActionPtr *actionsP, 1770 Boolean *error) 1771{ 1772 ActionPtr *nextActionP = actionsP; 1773 1774 *actionsP = NULL; 1775 while (*str != '\0' && !IsNewline(*str)) { 1776 register ActionPtr action; 1777 XrmQuark quark; 1778 1779 action = XtNew(ActionRec); 1780 action->params = NULL; 1781 action->num_params = 0; 1782 action->next = NULL; 1783 1784 str = ParseAction(str, action, &quark, error); 1785 if (*error) return PanicModeRecovery(str); 1786 1787 action->idx = _XtGetQuarkIndex(parseTree, quark); 1788 ScanWhitespace(str); 1789 *nextActionP = action; 1790 nextActionP = &action->next; 1791 } 1792 if (IsNewline(*str)) str++; 1793 ScanWhitespace(str); 1794 return str; 1795} 1796 1797 1798static void ShowProduction( 1799 String currentProduction) 1800{ 1801 Cardinal num_params = 1; 1802 String params[1]; 1803 size_t len; 1804 char *eol, *production, productionbuf[500]; 1805 1806#ifdef __UNIXOS2__ 1807 eol = strchr(currentProduction, '\r'); 1808 if (!eol) /* try '\n' as well below */ 1809#endif 1810 eol = strchr(currentProduction, '\n'); 1811 if (eol) len = eol - currentProduction; 1812 else len = strlen (currentProduction); 1813 production = XtStackAlloc (len + 1, productionbuf); 1814 if (production == NULL) _XtAllocError (NULL); 1815 (void) memmove(production, currentProduction, len); 1816 production[len] = '\0'; 1817 1818 params[0] = production; 1819 XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError, 1820 "... found while parsing '%s'", params, &num_params); 1821 1822 XtStackFree (production, productionbuf); 1823} 1824 1825/*********************************************************************** 1826 * ParseTranslationTableProduction 1827 * Parses one line of event bindings. 1828 ***********************************************************************/ 1829 1830static String ParseTranslationTableProduction( 1831 TMParseStateTree parseTree, 1832 register String str, 1833 Boolean* error) 1834{ 1835 EventSeqPtr eventSeq = NULL; 1836 ActionPtr *actionsP; 1837 String production = str; 1838 1839 str = ParseEventSeq(str, &eventSeq, &actionsP,error); 1840 if (*error == TRUE) { 1841 ShowProduction(production); 1842 FreeEventSeq(eventSeq); 1843 return (str); 1844 } 1845 ScanWhitespace(str); 1846 str = ParseActionSeq(parseTree, str, actionsP, error); 1847 if (*error == TRUE) { 1848 ShowProduction(production); 1849 FreeEventSeq(eventSeq); 1850 return (str); 1851 } 1852 1853 _XtAddEventSeqToStateTree(eventSeq, parseTree); 1854 FreeEventSeq(eventSeq); 1855 return (str); 1856} 1857 1858static String CheckForPoundSign( 1859 String str, 1860 _XtTranslateOp defaultOp, 1861 _XtTranslateOp *actualOpRtn) 1862{ 1863 String start; 1864 char operation[20]; 1865 _XtTranslateOp opType; 1866 1867 opType = defaultOp; 1868 ScanWhitespace(str); 1869 if (*str == '#') { 1870 int len; 1871 str++; 1872 start = str; 1873 str = ScanIdent(str); 1874 len = MIN(19, str-start); 1875 (void) memmove(operation, start, len); 1876 operation[len] = '\0'; 1877 if (!strcmp(operation,"replace")) 1878 opType = XtTableReplace; 1879 else if (!strcmp(operation,"augment")) 1880 opType = XtTableAugment; 1881 else if (!strcmp(operation,"override")) 1882 opType = XtTableOverride; 1883 ScanWhitespace(str); 1884 if (IsNewline(*str)) { 1885 str++; 1886 ScanWhitespace(str); 1887 } 1888 } 1889 *actualOpRtn = opType; 1890 return str; 1891} 1892 1893static XtTranslations ParseTranslationTable( 1894 String source, 1895 Boolean isAccelerator, 1896 _XtTranslateOp defaultOp, 1897 Boolean* error) 1898{ 1899 XtTranslations xlations; 1900 TMStateTree stateTrees[8]; 1901 TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec; 1902 XrmQuark stackQuarks[200]; 1903 TMBranchHeadRec stackBranchHeads[200]; 1904 StatePtr stackComplexBranchHeads[200]; 1905 _XtTranslateOp actualOp; 1906 1907 if (source == NULL) 1908 return (XtTranslations)NULL; 1909 1910 source = CheckForPoundSign(source, defaultOp, &actualOp); 1911 if (isAccelerator && actualOp == XtTableReplace) 1912 actualOp = defaultOp; 1913 1914 parseTree->isSimple = TRUE; 1915 parseTree->mappingNotifyInterest = FALSE; 1916 parseTree->isAccelerator = isAccelerator; 1917 parseTree->isStackBranchHeads = 1918 parseTree->isStackQuarks = 1919 parseTree->isStackComplexBranchHeads = TRUE; 1920 1921 parseTree->numQuarks = 1922 parseTree->numBranchHeads = 1923 parseTree->numComplexBranchHeads = 0; 1924 1925 parseTree->quarkTblSize = 1926 parseTree->branchHeadTblSize = 1927 parseTree->complexBranchHeadTblSize = 200; 1928 1929 parseTree->quarkTbl = stackQuarks; 1930 parseTree->branchHeadTbl = stackBranchHeads; 1931 parseTree->complexBranchHeadTbl = stackComplexBranchHeads; 1932 1933 while (source != NULL && *source != '\0') { 1934 source = ParseTranslationTableProduction(parseTree, source, error); 1935 if (*error == TRUE) break; 1936 } 1937 stateTrees[0] = _XtParseTreeToStateTree(parseTree); 1938 1939 if (!parseTree->isStackQuarks) 1940 XtFree((char *)parseTree->quarkTbl); 1941 if (!parseTree->isStackBranchHeads) 1942 XtFree((char *)parseTree->branchHeadTbl); 1943 if (!parseTree->isStackComplexBranchHeads) 1944 XtFree((char *)parseTree->complexBranchHeadTbl); 1945 1946 xlations = _XtCreateXlations(stateTrees, 1, NULL, NULL); 1947 xlations->operation = actualOp; 1948 1949#ifdef notdef 1950 XtFree(stateTrees); 1951#endif /* notdef */ 1952 return xlations; 1953} 1954 1955/*** public procedures ***/ 1956 1957/*ARGSUSED*/ 1958Boolean XtCvtStringToAcceleratorTable( 1959 Display* dpy, 1960 XrmValuePtr args, 1961 Cardinal *num_args, 1962 XrmValuePtr from, 1963 XrmValuePtr to, 1964 XtPointer *closure) 1965{ 1966 String str; 1967 Boolean error = FALSE; 1968 1969 if (*num_args != 0) 1970 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 1971 "wrongParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, 1972 "String to AcceleratorTable conversion needs no extra arguments", 1973 (String *)NULL, (Cardinal *)NULL); 1974 str = (String)(from->addr); 1975 if (str == NULL) { 1976 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 1977 "badParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, 1978 "String to AcceleratorTable conversion needs string", 1979 (String *)NULL, (Cardinal *)NULL); 1980 return FALSE; 1981 } 1982 if (to->addr != NULL) { 1983 if (to->size < sizeof(XtAccelerators)) { 1984 to->size = sizeof(XtAccelerators); 1985 return FALSE; 1986 } 1987 *(XtAccelerators*)to->addr = 1988 (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); 1989 } 1990 else { 1991 static XtAccelerators staticStateTable; 1992 staticStateTable = 1993 (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); 1994 to->addr = (XPointer) &staticStateTable; 1995 to->size = sizeof(XtAccelerators); 1996 } 1997 if (error == TRUE) 1998 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 1999 "parseError","cvtStringToAcceleratorTable",XtCXtToolkitError, 2000 "String to AcceleratorTable conversion encountered errors", 2001 (String *)NULL, (Cardinal *)NULL); 2002 return (error != TRUE); 2003} 2004 2005 2006/*ARGSUSED*/ 2007Boolean 2008XtCvtStringToTranslationTable( 2009 Display *dpy, 2010 XrmValuePtr args, 2011 Cardinal *num_args, 2012 XrmValuePtr from, 2013 XrmValuePtr to, 2014 XtPointer *closure_ret) 2015{ 2016 String str; 2017 Boolean error = FALSE; 2018 2019 if (*num_args != 0) 2020 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2021 "wrongParameters","cvtStringToTranslationTable",XtCXtToolkitError, 2022 "String to TranslationTable conversion needs no extra arguments", 2023 (String *)NULL, (Cardinal *)NULL); 2024 str = (String)(from->addr); 2025 if (str == NULL) { 2026 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2027 "badParameters","cvtStringToTranslation",XtCXtToolkitError, 2028 "String to TranslationTable conversion needs string", 2029 (String *)NULL, (Cardinal *)NULL); 2030 return FALSE; 2031 } 2032 if (to->addr != NULL) { 2033 if (to->size < sizeof(XtTranslations)) { 2034 to->size = sizeof(XtTranslations); 2035 return FALSE; 2036 } 2037 *(XtTranslations*)to->addr = 2038 ParseTranslationTable(str, FALSE, XtTableReplace, &error); 2039 } 2040 else { 2041 static XtTranslations staticStateTable; 2042 staticStateTable = 2043 ParseTranslationTable(str, FALSE, XtTableReplace, &error); 2044 to->addr = (XPointer) &staticStateTable; 2045 to->size = sizeof(XtTranslations); 2046 } 2047 if (error == TRUE) 2048 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2049 "parseError","cvtStringToTranslationTable",XtCXtToolkitError, 2050 "String to TranslationTable conversion encountered errors", 2051 (String *)NULL, (Cardinal *)NULL); 2052 return (error != TRUE); 2053} 2054 2055 2056/* 2057 * Parses a user's or applications translation table 2058 */ 2059XtAccelerators XtParseAcceleratorTable( 2060 _Xconst char* source) 2061{ 2062 Boolean error = FALSE; 2063 XtAccelerators ret = 2064 (XtAccelerators) ParseTranslationTable ((char *)source, TRUE, XtTableAugment, &error); 2065 if (error == TRUE) 2066 XtWarningMsg ("parseError", "cvtStringToAcceleratorTable", 2067 XtCXtToolkitError, 2068 "String to AcceleratorTable conversion encountered errors", 2069 (String *)NULL, (Cardinal *)NULL); 2070 return ret; 2071} 2072 2073XtTranslations XtParseTranslationTable( 2074 _Xconst char* source) 2075{ 2076 Boolean error = FALSE; 2077 XtTranslations ret = ParseTranslationTable((char *)source, FALSE, XtTableReplace, &error); 2078 if (error == TRUE) 2079 XtWarningMsg ("parseError", 2080 "cvtStringToTranslationTable", XtCXtToolkitError, 2081 "String to TranslationTable conversion encountered errors", 2082 (String *)NULL, (Cardinal *)NULL); 2083 return ret; 2084} 2085 2086void _XtTranslateInitialize(void) 2087{ 2088 LOCK_PROCESS; 2089 if (initialized) { 2090 XtWarningMsg("translationError","xtTranslateInitialize", 2091 XtCXtToolkitError,"Initializing Translation manager twice.", 2092 (String *)NULL, (Cardinal *)NULL); 2093 UNLOCK_PROCESS; 2094 return; 2095 } 2096 2097 initialized = TRUE; 2098 UNLOCK_PROCESS; 2099 QMeta = XrmPermStringToQuark("Meta"); 2100 QCtrl = XrmPermStringToQuark("Ctrl"); 2101 QNone = XrmPermStringToQuark("None"); 2102 QAny = XrmPermStringToQuark("Any"); 2103 2104 Compile_XtEventTable( events, XtNumber(events) ); 2105 Compile_XtModifierTable( modifiers, XtNumber(modifiers) ); 2106 CompileNameValueTable( buttonNames ); 2107 CompileNameValueTable( notifyModes ); 2108 CompileNameValueTable( motionDetails ); 2109#if 0 2110 CompileNameValueTable( notifyDetail ); 2111 CompileNameValueTable( visibilityNotify ); 2112 CompileNameValueTable( circulation ); 2113 CompileNameValueTable( propertyChanged ); 2114#endif 2115 CompileNameValueTable( mappingNotify ); 2116} 2117 2118void _XtAddTMConverters( 2119 ConverterTable table) 2120{ 2121 _XtTableAddConverter(table, 2122 _XtQString, 2123 XrmPermStringToQuark(XtRTranslationTable), 2124 XtCvtStringToTranslationTable, (XtConvertArgList) NULL, 2125 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2126 _XtTableAddConverter(table, _XtQString, 2127 XrmPermStringToQuark(XtRAcceleratorTable), 2128 XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL, 2129 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2130 _XtTableAddConverter(table, 2131 XrmPermStringToQuark( _XtRStateTablePair ), 2132 XrmPermStringToQuark(XtRTranslationTable), 2133 _XtCvtMergeTranslations, (XtConvertArgList) NULL, 2134 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2135} 2136