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