TMparse.c revision 2265a131
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,NULL, 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 actionsP = NULL; 1840 str = ParseEventSeq(str, &eventSeq, &actionsP,error); 1841 if (*error == TRUE) { 1842 ShowProduction(production); 1843 FreeEventSeq(eventSeq); 1844 return (str); 1845 } 1846 ScanWhitespace(str); 1847 str = ParseActionSeq(parseTree, str, actionsP, error); 1848 if (*error == TRUE) { 1849 ShowProduction(production); 1850 FreeEventSeq(eventSeq); 1851 return (str); 1852 } 1853 1854 _XtAddEventSeqToStateTree(eventSeq, parseTree); 1855 FreeEventSeq(eventSeq); 1856 return (str); 1857} 1858 1859static String CheckForPoundSign( 1860 String str, 1861 _XtTranslateOp defaultOp, 1862 _XtTranslateOp *actualOpRtn) 1863{ 1864 String start; 1865 char operation[20]; 1866 _XtTranslateOp opType; 1867 1868 opType = defaultOp; 1869 ScanWhitespace(str); 1870 if (*str == '#') { 1871 int len; 1872 str++; 1873 start = str; 1874 str = ScanIdent(str); 1875 len = MIN(19, str-start); 1876 (void) memmove(operation, start, len); 1877 operation[len] = '\0'; 1878 if (!strcmp(operation,"replace")) 1879 opType = XtTableReplace; 1880 else if (!strcmp(operation,"augment")) 1881 opType = XtTableAugment; 1882 else if (!strcmp(operation,"override")) 1883 opType = XtTableOverride; 1884 ScanWhitespace(str); 1885 if (IsNewline(*str)) { 1886 str++; 1887 ScanWhitespace(str); 1888 } 1889 } 1890 *actualOpRtn = opType; 1891 return str; 1892} 1893 1894static XtTranslations ParseTranslationTable( 1895 String source, 1896 Boolean isAccelerator, 1897 _XtTranslateOp defaultOp, 1898 Boolean* error) 1899{ 1900 XtTranslations xlations; 1901 TMStateTree stateTrees[8]; 1902 TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec; 1903 XrmQuark stackQuarks[200]; 1904 TMBranchHeadRec stackBranchHeads[200]; 1905 StatePtr stackComplexBranchHeads[200]; 1906 _XtTranslateOp actualOp; 1907 1908 if (source == NULL) 1909 return (XtTranslations)NULL; 1910 1911 source = CheckForPoundSign(source, defaultOp, &actualOp); 1912 if (isAccelerator && actualOp == XtTableReplace) 1913 actualOp = defaultOp; 1914 1915 parseTree->isSimple = TRUE; 1916 parseTree->mappingNotifyInterest = FALSE; 1917 parseTree->isAccelerator = isAccelerator; 1918 parseTree->isStackBranchHeads = 1919 parseTree->isStackQuarks = 1920 parseTree->isStackComplexBranchHeads = TRUE; 1921 1922 parseTree->numQuarks = 1923 parseTree->numBranchHeads = 1924 parseTree->numComplexBranchHeads = 0; 1925 1926 parseTree->quarkTblSize = 1927 parseTree->branchHeadTblSize = 1928 parseTree->complexBranchHeadTblSize = 200; 1929 1930 parseTree->quarkTbl = stackQuarks; 1931 parseTree->branchHeadTbl = stackBranchHeads; 1932 parseTree->complexBranchHeadTbl = stackComplexBranchHeads; 1933 1934 while (source != NULL && *source != '\0') { 1935 source = ParseTranslationTableProduction(parseTree, source, error); 1936 if (*error == TRUE) break; 1937 } 1938 stateTrees[0] = _XtParseTreeToStateTree(parseTree); 1939 1940 if (!parseTree->isStackQuarks) 1941 XtFree((char *)parseTree->quarkTbl); 1942 if (!parseTree->isStackBranchHeads) 1943 XtFree((char *)parseTree->branchHeadTbl); 1944 if (!parseTree->isStackComplexBranchHeads) 1945 XtFree((char *)parseTree->complexBranchHeadTbl); 1946 1947 xlations = _XtCreateXlations(stateTrees, 1, NULL, NULL); 1948 xlations->operation = actualOp; 1949 1950#ifdef notdef 1951 XtFree(stateTrees); 1952#endif /* notdef */ 1953 return xlations; 1954} 1955 1956/*** public procedures ***/ 1957 1958/*ARGSUSED*/ 1959Boolean XtCvtStringToAcceleratorTable( 1960 Display* dpy, 1961 XrmValuePtr args, 1962 Cardinal *num_args, 1963 XrmValuePtr from, 1964 XrmValuePtr to, 1965 XtPointer *closure) 1966{ 1967 String str; 1968 Boolean error = FALSE; 1969 1970 if (*num_args != 0) 1971 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 1972 "wrongParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, 1973 "String to AcceleratorTable conversion needs no extra arguments", 1974 (String *)NULL, (Cardinal *)NULL); 1975 str = (String)(from->addr); 1976 if (str == NULL) { 1977 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 1978 "badParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, 1979 "String to AcceleratorTable conversion needs string", 1980 (String *)NULL, (Cardinal *)NULL); 1981 return FALSE; 1982 } 1983 if (to->addr != NULL) { 1984 if (to->size < sizeof(XtAccelerators)) { 1985 to->size = sizeof(XtAccelerators); 1986 return FALSE; 1987 } 1988 *(XtAccelerators*)to->addr = 1989 (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); 1990 } 1991 else { 1992 static XtAccelerators staticStateTable; 1993 staticStateTable = 1994 (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); 1995 to->addr = (XPointer) &staticStateTable; 1996 to->size = sizeof(XtAccelerators); 1997 } 1998 if (error == TRUE) 1999 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2000 "parseError","cvtStringToAcceleratorTable",XtCXtToolkitError, 2001 "String to AcceleratorTable conversion encountered errors", 2002 (String *)NULL, (Cardinal *)NULL); 2003 return (error != TRUE); 2004} 2005 2006 2007/*ARGSUSED*/ 2008Boolean 2009XtCvtStringToTranslationTable( 2010 Display *dpy, 2011 XrmValuePtr args, 2012 Cardinal *num_args, 2013 XrmValuePtr from, 2014 XrmValuePtr to, 2015 XtPointer *closure_ret) 2016{ 2017 String str; 2018 Boolean error = FALSE; 2019 2020 if (*num_args != 0) 2021 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2022 "wrongParameters","cvtStringToTranslationTable",XtCXtToolkitError, 2023 "String to TranslationTable conversion needs no extra arguments", 2024 (String *)NULL, (Cardinal *)NULL); 2025 str = (String)(from->addr); 2026 if (str == NULL) { 2027 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2028 "badParameters","cvtStringToTranslation",XtCXtToolkitError, 2029 "String to TranslationTable conversion needs string", 2030 (String *)NULL, (Cardinal *)NULL); 2031 return FALSE; 2032 } 2033 if (to->addr != NULL) { 2034 if (to->size < sizeof(XtTranslations)) { 2035 to->size = sizeof(XtTranslations); 2036 return FALSE; 2037 } 2038 *(XtTranslations*)to->addr = 2039 ParseTranslationTable(str, FALSE, XtTableReplace, &error); 2040 } 2041 else { 2042 static XtTranslations staticStateTable; 2043 staticStateTable = 2044 ParseTranslationTable(str, FALSE, XtTableReplace, &error); 2045 to->addr = (XPointer) &staticStateTable; 2046 to->size = sizeof(XtTranslations); 2047 } 2048 if (error == TRUE) 2049 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2050 "parseError","cvtStringToTranslationTable",XtCXtToolkitError, 2051 "String to TranslationTable conversion encountered errors", 2052 (String *)NULL, (Cardinal *)NULL); 2053 return (error != TRUE); 2054} 2055 2056 2057/* 2058 * Parses a user's or applications translation table 2059 */ 2060XtAccelerators XtParseAcceleratorTable( 2061 _Xconst char* source) 2062{ 2063 Boolean error = FALSE; 2064 XtAccelerators ret = 2065 (XtAccelerators) ParseTranslationTable ((char *)source, TRUE, XtTableAugment, &error); 2066 if (error == TRUE) 2067 XtWarningMsg ("parseError", "cvtStringToAcceleratorTable", 2068 XtCXtToolkitError, 2069 "String to AcceleratorTable conversion encountered errors", 2070 (String *)NULL, (Cardinal *)NULL); 2071 return ret; 2072} 2073 2074XtTranslations XtParseTranslationTable( 2075 _Xconst char* source) 2076{ 2077 Boolean error = FALSE; 2078 XtTranslations ret = ParseTranslationTable((char *)source, FALSE, XtTableReplace, &error); 2079 if (error == TRUE) 2080 XtWarningMsg ("parseError", 2081 "cvtStringToTranslationTable", XtCXtToolkitError, 2082 "String to TranslationTable conversion encountered errors", 2083 (String *)NULL, (Cardinal *)NULL); 2084 return ret; 2085} 2086 2087void _XtTranslateInitialize(void) 2088{ 2089 LOCK_PROCESS; 2090 if (initialized) { 2091 XtWarningMsg("translationError","xtTranslateInitialize", 2092 XtCXtToolkitError,"Initializing Translation manager twice.", 2093 (String *)NULL, (Cardinal *)NULL); 2094 UNLOCK_PROCESS; 2095 return; 2096 } 2097 2098 initialized = TRUE; 2099 UNLOCK_PROCESS; 2100 QMeta = XrmPermStringToQuark("Meta"); 2101 QCtrl = XrmPermStringToQuark("Ctrl"); 2102 QNone = XrmPermStringToQuark("None"); 2103 QAny = XrmPermStringToQuark("Any"); 2104 2105 Compile_XtEventTable( events, XtNumber(events) ); 2106 Compile_XtModifierTable( modifiers, XtNumber(modifiers) ); 2107 CompileNameValueTable( buttonNames ); 2108 CompileNameValueTable( notifyModes ); 2109 CompileNameValueTable( motionDetails ); 2110#if 0 2111 CompileNameValueTable( notifyDetail ); 2112 CompileNameValueTable( visibilityNotify ); 2113 CompileNameValueTable( circulation ); 2114 CompileNameValueTable( propertyChanged ); 2115#endif 2116 CompileNameValueTable( mappingNotify ); 2117} 2118 2119void _XtAddTMConverters( 2120 ConverterTable table) 2121{ 2122 _XtTableAddConverter(table, 2123 _XtQString, 2124 XrmPermStringToQuark(XtRTranslationTable), 2125 XtCvtStringToTranslationTable, (XtConvertArgList) NULL, 2126 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2127 _XtTableAddConverter(table, _XtQString, 2128 XrmPermStringToQuark(XtRAcceleratorTable), 2129 XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL, 2130 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2131 _XtTableAddConverter(table, 2132 XrmPermStringToQuark( _XtRStateTablePair ), 2133 XrmPermStringToQuark(XtRTranslationTable), 2134 _XtCvtMergeTranslations, (XtConvertArgList) NULL, 2135 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2136} 2137