TMparse.c revision 4f45da70
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 char* name; 117 XrmQuark signature; 118 ModifierProc modifierParseProc; 119 Value value; 120} ModifierRec, *ModifierKeys; 121 122typedef struct _EventKey { 123 char *event; 124 XrmQuark signature; 125 EventType eventType; 126 ParseProc parseDetail; 127 Opaque closure; 128}EventKey, *EventKeys; 129 130typedef struct { 131 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#ifndef __UNIXOS2__ 384#define IsNewline(str) ((str) == '\n') 385#else 386#define IsNewline(str) ((str) == '\n' || (str) == '\r') 387#endif 388 389#define ScanFor(str, ch) \ 390 while ((*(str) != (ch)) && (*(str) != '\0') && !IsNewline(*(str))) (str)++ 391 392#define ScanNumeric(str) while ('0' <= *(str) && *(str) <= '9') (str)++ 393 394#define ScanAlphanumeric(str) \ 395 while (('A' <= *(str) && *(str) <= 'Z') || \ 396 ('a' <= *(str) && *(str) <= 'z') || \ 397 ('0' <= *(str) && *(str) <= '9')) (str)++ 398 399#ifndef __UNIXOS2__ 400#define ScanWhitespace(str) \ 401 while (*(str) == ' ' || *(str) == '\t') (str)++ 402#else 403#define ScanWhitespace(str) \ 404 while (*(str) == ' ' || *(str) == '\t' || *(str) == '\r') (str)++ 405#endif 406 407static Boolean initialized = FALSE; 408static XrmQuark QMeta; 409static XrmQuark QCtrl; 410static XrmQuark QNone; 411static XrmQuark QAny; 412 413static void FreeEventSeq( 414 EventSeqPtr eventSeq) 415{ 416 register EventSeqPtr evs = eventSeq; 417 418 while (evs != NULL) { 419 evs->state = (StatePtr) evs; 420 if (evs->next != NULL 421 && evs->next->state == (StatePtr) evs->next) 422 evs->next = NULL; 423 evs = evs->next; 424 } 425 426 evs = eventSeq; 427 while (evs != NULL) { 428 register EventPtr event = evs; 429 evs = evs->next; 430 if (evs == event) evs = NULL; 431 XtFree((char *)event); 432 } 433} 434 435static void CompileNameValueTable( 436 NameValueTable table) 437{ 438 register int i; 439 440 for (i=0; table[i].name; i++) 441 table[i].signature = XrmPermStringToQuark(table[i].name); 442} 443 444static int OrderEvents(_Xconst void *a, _Xconst void *b) 445{ 446 return ((((_Xconst EventKey *)a)->signature < 447 ((_Xconst EventKey *)b)->signature) ? -1 : 1); 448} 449 450static void Compile_XtEventTable( 451 EventKeys table, 452 Cardinal count) 453{ 454 register int i; 455 register EventKeys entry = table; 456 457 for (i=count; --i >= 0; entry++) 458 entry->signature = XrmPermStringToQuark(entry->event); 459 qsort(table, count, sizeof(EventKey), OrderEvents); 460} 461 462static int OrderModifiers(_Xconst void *a, _Xconst void *b) 463{ 464 return ((((_Xconst ModifierRec *)a)->signature < 465 ((_Xconst ModifierRec *)b)->signature) ? -1 : 1); 466} 467 468static void Compile_XtModifierTable( 469 ModifierKeys table, 470 Cardinal count) 471{ 472 register int i; 473 register ModifierKeys entry = table; 474 475 for (i=count; --i >= 0; entry++) 476 entry->signature = XrmPermStringToQuark(entry->name); 477 qsort(table, count, sizeof(ModifierRec), OrderModifiers); 478} 479 480static String PanicModeRecovery( 481 String str) 482{ 483 ScanFor(str,'\n'); 484 if (*str == '\n') str++; 485 return str; 486 487} 488 489 490static void Syntax( 491 String str0,String str1) 492{ 493 Cardinal num_params = 2; 494 String params[2]; 495 496 params[0] = str0; 497 params[1] = str1; 498 XtWarningMsg(XtNtranslationParseError,"parseError",XtCXtToolkitError, 499 "translation table syntax error: %s %s",params,&num_params); 500} 501 502 503 504static Cardinal LookupTMEventType( 505 String eventStr, 506 Boolean *error) 507{ 508 register int i = 0, left, right; 509 register XrmQuark signature; 510 static int previous = 0; 511 512 LOCK_PROCESS; 513 if ((signature = StringToQuark(eventStr)) == events[previous].signature) { 514 UNLOCK_PROCESS; 515 return (Cardinal) previous; 516 } 517 518 left = 0; 519 right = XtNumber(events) - 1; 520 while (left <= right) { 521 i = (left + right) >> 1; 522 if (signature < events[i].signature) 523 right = i - 1; 524 else if (signature > events[i].signature) 525 left = i + 1; 526 else { 527 previous = i; 528 UNLOCK_PROCESS; 529 return (Cardinal) i; 530 } 531 } 532 533 Syntax("Unknown event type : ",eventStr); 534 *error = TRUE; 535 UNLOCK_PROCESS; 536 return (Cardinal) i; 537} 538 539static void StoreLateBindings( 540 KeySym keysymL, 541 Boolean notL, 542 KeySym keysymR, 543 Boolean notR, 544 LateBindingsPtr* lateBindings) 545{ 546 LateBindingsPtr temp; 547 Boolean pair = FALSE; 548 unsigned long count,number; 549 if (lateBindings != NULL){ 550 temp = *lateBindings; 551 if (temp != NULL) { 552 for (count = 0; temp[count].keysym; count++){/*EMPTY*/} 553 } 554 else count = 0; 555 if (! keysymR){ 556 number = 1;pair = FALSE; 557 } else{ 558 number = 2;pair = TRUE; 559 } 560 561 temp = (LateBindingsPtr)XtRealloc((char *)temp, 562 (unsigned)((count+number+1) * sizeof(LateBindings)) ); 563 *lateBindings = temp; 564 temp[count].knot = notL; 565 temp[count].pair = pair; 566 if (count == 0) 567 temp[count].ref_count = 1; 568 temp[count++].keysym = keysymL; 569 if (keysymR){ 570 temp[count].knot = notR; 571 temp[count].pair = FALSE; 572 temp[count].ref_count = 0; 573 temp[count++].keysym = keysymR; 574 } 575 temp[count].knot = temp[count].pair = FALSE; 576 temp[count].ref_count = 0; 577 temp[count].keysym = 0; 578 } 579} 580 581static void _XtParseKeysymMod( 582 String name, 583 LateBindingsPtr* lateBindings, 584 Boolean notFlag, 585 Value *valueP, 586 Boolean *error) 587{ 588 KeySym keySym; 589 keySym = StringToKeySym(name, error); 590 *valueP = 0; 591 if (keySym != NoSymbol) { 592 StoreLateBindings(keySym,notFlag,(KeySym) NULL,FALSE,lateBindings); 593 } 594} 595 596static Boolean _XtLookupModifier( 597 XrmQuark signature, 598 LateBindingsPtr* lateBindings, 599 Boolean notFlag, 600 Value *valueP, 601 Bool constMask) 602{ 603 register int i, left, right; 604 static int previous = 0; 605 606 LOCK_PROCESS; 607 if (signature == modifiers[previous].signature) { 608 if (constMask) *valueP = modifiers[previous].value; 609 else /* if (modifiers[previous].modifierParseProc) always true */ 610 (*modifiers[previous].modifierParseProc) 611 (modifiers[previous].value, lateBindings, notFlag, valueP); 612 UNLOCK_PROCESS; 613 return TRUE; 614 } 615 616 left = 0; 617 right = XtNumber(modifiers) - 1; 618 while (left <= right) { 619 i = (left + right) >> 1; 620 if (signature < modifiers[i].signature) 621 right = i - 1; 622 else if (signature > modifiers[i].signature) 623 left = i + 1; 624 else { 625 previous = i; 626 if (constMask) *valueP = modifiers[i].value; 627 else /* if (modifiers[i].modifierParseProc) always true */ 628 (*modifiers[i].modifierParseProc) 629 (modifiers[i].value, lateBindings, notFlag, valueP); 630 UNLOCK_PROCESS; 631 return TRUE; 632 } 633 } 634 UNLOCK_PROCESS; 635 return FALSE; 636} 637 638 639static String ScanIdent( 640 register String str) 641{ 642 ScanAlphanumeric(str); 643 while ( 644 ('A' <= *str && *str <= 'Z') 645 || ('a' <= *str && *str <= 'z') 646 || ('0' <= *str && *str <= '9') 647 || (*str == '-') 648 || (*str == '_') 649 || (*str == '$') 650 ) str++; 651 return str; 652} 653 654static String FetchModifierToken( 655 String str, 656 XrmQuark *token_return) 657{ 658 String start = str; 659 660 if (*str == '$') { 661 *token_return = QMeta; 662 str++; 663 return str; 664 } 665 if (*str == '^') { 666 *token_return = QCtrl; 667 str++; 668 return str; 669 } 670 str = ScanIdent(str); 671 if (start != str) { 672 char modStrbuf[100]; 673 char* modStr; 674 675 modStr = XtStackAlloc ((size_t)(str - start + 1), modStrbuf); 676 if (modStr == NULL) _XtAllocError (NULL); 677 (void) memmove(modStr, start, str-start); 678 modStr[str-start] = '\0'; 679 *token_return = XrmStringToQuark(modStr); 680 XtStackFree (modStr, modStrbuf); 681 return str; 682 } 683 return str; 684} 685 686static String ParseModifiers( 687 register String str, 688 EventPtr event, 689 Boolean* error) 690{ 691 register String start; 692 Boolean notFlag, exclusive, keysymAsMod; 693 Value maskBit; 694 XrmQuark Qmod; 695 696 ScanWhitespace(str); 697 start = str; 698 str = FetchModifierToken(str, &Qmod); 699 exclusive = FALSE; 700 if (start != str) { 701 if (Qmod == QNone) { 702 event->event.modifierMask = ~0; 703 event->event.modifiers = 0; 704 ScanWhitespace(str); 705 return str; 706 } else if (Qmod == QAny) { /*backward compatability*/ 707 event->event.modifierMask = 0; 708 event->event.modifiers = AnyModifier; 709 ScanWhitespace(str); 710 return str; 711 } 712 str = start; /*if plain modifier, reset to beginning */ 713 } 714 else while (*str == '!' || *str == ':') { 715 if (*str == '!') { 716 exclusive = TRUE; 717 str++; 718 ScanWhitespace(str); 719 } 720 if (*str == ':') { 721 event->event.standard = TRUE; 722 str++; 723 ScanWhitespace(str); 724 } 725 } 726 727 while (*str != '<') { 728 if (*str == '~') { 729 notFlag = TRUE; 730 str++; 731 } else 732 notFlag = FALSE; 733 if (*str == '@') { 734 keysymAsMod = TRUE; 735 str++; 736 } 737 else keysymAsMod = FALSE; 738 start = str; 739 str = FetchModifierToken(str, &Qmod); 740 if (start == str) { 741 Syntax("Modifier or '<' expected",""); 742 *error = TRUE; 743 return PanicModeRecovery(str); 744 } 745 if (keysymAsMod) { 746 _XtParseKeysymMod(XrmQuarkToString(Qmod), 747 &event->event.lateModifiers, 748 notFlag,&maskBit, error); 749 if (*error) 750 return PanicModeRecovery(str); 751 752 } else 753 if (!_XtLookupModifier(Qmod, &event->event.lateModifiers, 754 notFlag, &maskBit, FALSE)) { 755 Syntax("Unknown modifier name: ", XrmQuarkToString(Qmod)); 756 *error = TRUE; 757 return PanicModeRecovery(str); 758 } 759 event->event.modifierMask |= maskBit; 760 if (notFlag) event->event.modifiers &= ~maskBit; 761 else event->event.modifiers |= maskBit; 762 ScanWhitespace(str); 763 } 764 if (exclusive) event->event.modifierMask = ~0; 765 return str; 766} 767 768static String ParseXtEventType( 769 register String str, 770 EventPtr event, 771 Cardinal *tmEventP, 772 Boolean* error) 773{ 774 String start = str; 775 char eventTypeStrbuf[100]; 776 char* eventTypeStr; 777 778 ScanAlphanumeric(str); 779 eventTypeStr = XtStackAlloc ((size_t)(str - start + 1), eventTypeStrbuf); 780 if (eventTypeStr == NULL) _XtAllocError (NULL); 781 (void) memmove(eventTypeStr, start, str-start); 782 eventTypeStr[str-start] = '\0'; 783 *tmEventP = LookupTMEventType(eventTypeStr,error); 784 XtStackFree (eventTypeStr, eventTypeStrbuf); 785 if (*error) 786 return PanicModeRecovery(str); 787 event->event.eventType = events[*tmEventP].eventType; 788 return str; 789} 790 791static unsigned long StrToHex( 792 String str) 793{ 794 register char c; 795 register unsigned long val = 0; 796 797 while ((c = *str)) { 798 if ('0' <= c && c <= '9') val = val*16+c-'0'; 799 else if ('a' <= c && c <= 'z') val = val*16+c-'a'+10; 800 else if ('A' <= c && c <= 'Z') val = val*16+c-'A'+10; 801 else return 0; 802 str++; 803 } 804 805 return val; 806} 807 808static unsigned long StrToOct( 809 String str) 810{ 811 register char c; 812 register unsigned long val = 0; 813 814 while ((c = *str)) { 815 if ('0' <= c && c <= '7') val = val*8+c-'0'; else return 0; 816 str++; 817 } 818 819 return val; 820} 821 822static unsigned long StrToNum( 823 String str) 824{ 825 register char c; 826 register unsigned long val = 0; 827 828 if (*str == '0') { 829 str++; 830 if (*str == 'x' || *str == 'X') return StrToHex(++str); 831 else return StrToOct(str); 832 } 833 834 while ((c = *str)) { 835 if ('0' <= c && c <= '9') val = val*10+c-'0'; 836 else return 0; 837 str++; 838 } 839 840 return val; 841} 842 843static KeySym StringToKeySym( 844 String str, 845 Boolean *error) 846{ 847 KeySym k; 848 849 if (str == NULL || *str == '\0') return (KeySym) 0; 850 851#ifndef NOTASCII 852 /* special case single character ASCII, for speed */ 853 if (*(str+1) == '\0') { 854 if (' ' <= *str && *str <= '~') return XK_space + (*str - ' '); 855 } 856#endif 857 858 if ('0' <= *str && *str <= '9') return (KeySym) StrToNum(str); 859 k = XStringToKeysym(str); 860 if (k != NoSymbol) return k; 861 862#ifdef NOTASCII 863 /* fall-back case to preserve backwards compatibility; no-one 864 * should be relying upon this! 865 */ 866 if (*(str+1) == '\0') return (KeySym) *str; 867#endif 868 869 Syntax("Unknown keysym name: ", str); 870 *error = TRUE; 871 return NoSymbol; 872} 873/* ARGSUSED */ 874static void ParseModImmed( 875 Value value, 876 LateBindingsPtr* lateBindings, 877 Boolean notFlag, 878 Value* valueP) 879{ 880 *valueP = value; 881} 882 883 /* is only valid with keysyms that have an _L and _R in their name; 884 * and ignores keysym lookup errors (i.e. assumes only valid keysyms) 885 */ 886static void ParseModSym( 887 Value value, 888 LateBindingsPtr* lateBindings, 889 Boolean notFlag, 890 Value* valueP) 891{ 892 register KeySym keysymL = (KeySym)value; 893 register KeySym keysymR = keysymL + 1; /* valid for supported keysyms */ 894 StoreLateBindings(keysymL,notFlag,keysymR,notFlag,lateBindings); 895 *valueP = 0; 896} 897 898#ifdef sparc 899/* 900 * The stupid optimizer in SunOS 4.0.3 and below generates bogus code that 901 * causes the value of the most recently used variable to be returned instead 902 * of the value passed in. 903 */ 904static String stupid_optimizer_kludge; 905#define BROKEN_OPTIMIZER_HACK(val) stupid_optimizer_kludge = (val) 906#else 907#define BROKEN_OPTIMIZER_HACK(val) val 908#endif 909 910/* ARGSUSED */ 911static String ParseImmed( 912 register String str, 913 register Opaque closure, 914 register EventPtr event, 915 Boolean* error) 916{ 917 event->event.eventCode = (unsigned long)closure; 918 event->event.eventCodeMask = ~0UL; 919 920 return BROKEN_OPTIMIZER_HACK(str); 921} 922 923/* ARGSUSED */ 924static String ParseAddModifier( 925 register String str, 926 register Opaque closure, 927 register EventPtr event, 928 Boolean* error) 929{ 930 register unsigned long modval = (unsigned long)closure; 931 event->event.modifiers |= modval; 932 if (modval != AnyButtonMask) /* AnyButtonMask is don't-care mask */ 933 event->event.modifierMask |= modval; 934 935 return BROKEN_OPTIMIZER_HACK(str); 936} 937 938 939static String ParseKeyAndModifiers( 940 String str, 941 Opaque closure, 942 EventPtr event, 943 Boolean* error) 944{ 945 str = ParseKeySym(str, closure, event,error); 946 if ((unsigned long) closure == 0) { 947 Value metaMask; /* unused */ 948 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE, 949 &metaMask, FALSE); 950 } else { 951 event->event.modifiers |= (unsigned long) closure; 952 event->event.modifierMask |= (unsigned long) closure; 953 } 954 return str; 955} 956 957/*ARGSUSED*/ 958static String ParseKeySym( 959 register String str, 960 Opaque closure, 961 EventPtr event, 962 Boolean* error) 963{ 964 char *start; 965 char keySymNamebuf[100]; 966 char* keySymName; 967 968 ScanWhitespace(str); 969 970 if (*str == '\\') { 971 keySymName = keySymNamebuf; 972 str++; 973 keySymName[0] = *str; 974 if (*str != '\0' && !IsNewline(*str)) str++; 975 keySymName[1] = '\0'; 976 event->event.eventCode = StringToKeySym(keySymName, error); 977 event->event.eventCodeMask = ~0L; 978 } else if (*str == ',' || *str == ':' || 979 /* allow leftparen to be single char symbol, 980 * for backwards compatibility 981 */ 982 (*str == '(' && *(str+1) >= '0' && *(str+1) <= '9')) { 983 keySymName = keySymNamebuf; /* just so we can stackfree it later */ 984 /* no detail */ 985 event->event.eventCode = 0L; 986 event->event.eventCodeMask = 0L; 987 } else { 988 start = str; 989 while ( 990 *str != ',' 991 && *str != ':' 992 && *str != ' ' 993 && *str != '\t' 994 && !IsNewline(*str) 995 && (*str != '(' || *(str+1) <= '0' || *(str+1) >= '9') 996 && *str != '\0') str++; 997 keySymName = XtStackAlloc ((size_t)(str - start + 1), keySymNamebuf); 998 (void) memmove(keySymName, start, str-start); 999 keySymName[str-start] = '\0'; 1000 event->event.eventCode = StringToKeySym(keySymName, error); 1001 event->event.eventCodeMask = ~0L; 1002 } 1003 if (*error) { 1004 /* We never get here when keySymName hasn't been allocated */ 1005 if (keySymName[0] == '<') { 1006 /* special case for common error */ 1007 XtWarningMsg(XtNtranslationParseError, "missingComma", 1008 XtCXtToolkitError, 1009 "... possibly due to missing ',' in event sequence.", 1010 (String*)NULL, (Cardinal*)NULL); 1011 } 1012 XtStackFree (keySymName, keySymNamebuf); 1013 return PanicModeRecovery(str); 1014 } 1015 if (event->event.standard) 1016 event->event.matchEvent = _XtMatchUsingStandardMods; 1017 else 1018 event->event.matchEvent = _XtMatchUsingDontCareMods; 1019 1020 XtStackFree (keySymName, keySymNamebuf); 1021 1022 return str; 1023} 1024 1025static String ParseTable( 1026 register String str, 1027 Opaque closure, 1028 EventPtr event, 1029 Boolean* error) 1030{ 1031 register String start = str; 1032 register XrmQuark signature; 1033 NameValueTable table = (NameValueTable) closure; 1034 char tableSymName[100]; 1035 1036 event->event.eventCode = 0L; 1037 ScanAlphanumeric(str); 1038 if (str == start) {event->event.eventCodeMask = 0L; return str; } 1039 if (str-start >= 99) { 1040 Syntax("Invalid Detail Type (string is too long).", ""); 1041 *error = TRUE; 1042 return str; 1043 } 1044 (void) memmove(tableSymName, start, str-start); 1045 tableSymName[str-start] = '\0'; 1046 signature = StringToQuark(tableSymName); 1047 for (; table->signature != NULLQUARK; table++) 1048 if (table->signature == signature) { 1049 event->event.eventCode = table->value; 1050 event->event.eventCodeMask = ~0L; 1051 return str; 1052 } 1053 1054 Syntax("Unknown Detail Type: ", tableSymName); 1055 *error = TRUE; 1056 return PanicModeRecovery(str); 1057} 1058 1059/*ARGSUSED*/ 1060static String ParseNone( 1061 String str, 1062 Opaque closure, 1063 EventPtr event, 1064 Boolean* error) 1065{ 1066 event->event.eventCode = 0; 1067 event->event.eventCodeMask = 0; 1068 1069 return BROKEN_OPTIMIZER_HACK(str); 1070} 1071 1072/*ARGSUSED*/ 1073static String ParseAtom( 1074 String str, 1075 Opaque closure, 1076 EventPtr event, 1077 Boolean* error) 1078{ 1079 ScanWhitespace(str); 1080 1081 if (*str == ',' || *str == ':') { 1082 /* no detail */ 1083 event->event.eventCode = 0L; 1084 event->event.eventCodeMask = 0L; 1085 } else { 1086 char *start, atomName[1000]; 1087 start = str; 1088 while ( 1089 *str != ',' 1090 && *str != ':' 1091 && *str != ' ' 1092 && *str != '\t' 1093 && !IsNewline(*str) 1094 && *str != '\0') str++; 1095 if (str-start >= 999) { 1096 Syntax( "Atom name must be less than 1000 characters long.", "" ); 1097 *error = TRUE; 1098 return str; 1099 } 1100 (void) memmove(atomName, start, str-start); 1101 atomName[str-start] = '\0'; 1102 event->event.eventCode = XrmStringToQuark(atomName); 1103 event->event.matchEvent = _XtMatchAtom; 1104 } 1105 return str; 1106} 1107 1108static ModifierMask buttonModifierMasks[] = { 1109 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask 1110}; 1111static String ParseRepeat(String, int *, Boolean *, Boolean *); 1112 1113static String ParseEvent( 1114 register String str, 1115 EventPtr event, 1116 int* reps, 1117 Boolean* plus, 1118 Boolean* error) 1119{ 1120 Cardinal tmEvent; 1121 1122 str = ParseModifiers(str, event,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 str = ParseXtEventType(str, event, &tmEvent,error); 1131 if (*error) return str; 1132 if (*str != '>'){ 1133 Syntax("Missing '>' while parsing event type",""); 1134 *error = TRUE; 1135 return PanicModeRecovery(str); 1136 } 1137 else str++; 1138 if (*str == '(') { 1139 str = ParseRepeat(str, reps, plus, error); 1140 if (*error) return str; 1141 } 1142 str = (*(events[tmEvent].parseDetail))( 1143 str, events[tmEvent].closure, event,error); 1144 if (*error) return str; 1145 1146/* gross hack! ||| this kludge is related to the X11 protocol deficiency w.r.t. 1147 * modifiers in grabs. 1148 */ 1149 if ((event->event.eventType == ButtonRelease) 1150 && (event->event.modifiers | event->event.modifierMask) /* any */ 1151 && (event->event.modifiers != AnyModifier)) 1152 { 1153 event->event.modifiers 1154 |= buttonModifierMasks[event->event.eventCode]; 1155 /* the button that is going up will always be in the modifiers... */ 1156 } 1157 1158 return str; 1159} 1160 1161static String ParseQuotedStringEvent( 1162 register String str, 1163 register EventPtr event, 1164 Boolean *error) 1165{ 1166 Value metaMask; 1167 char s[2]; 1168 1169 if (*str=='^') { 1170 str++; 1171 event->event.modifiers = ControlMask; 1172 } else if (*str == '$') { 1173 str++; 1174 (void) _XtLookupModifier(QMeta, &event->event.lateModifiers, FALSE, 1175 &metaMask, FALSE); 1176 } 1177 if (*str == '\\') 1178 str++; 1179 s[0] = *str; 1180 s[1] = '\0'; 1181 if (*str != '\0' && !IsNewline(*str)) str++; 1182 event->event.eventType = KeyPress; 1183 event->event.eventCode = StringToKeySym(s, error); 1184 if (*error) return PanicModeRecovery(str); 1185 event->event.eventCodeMask = ~0L; 1186 event->event.matchEvent = _XtMatchUsingStandardMods; 1187 event->event.standard = TRUE; 1188 1189 return str; 1190} 1191 1192 1193static EventSeqRec timerEventRec = { 1194 {0, 0, NULL, _XtEventTimerEventType, 0L, 0L, NULL, False}, 1195 /* (StatePtr) -1 */ NULL, 1196 NULL, 1197 NULL 1198}; 1199 1200static void RepeatDown( 1201 EventPtr *eventP, 1202 int reps, 1203 ActionPtr **actionsP) 1204{ 1205 EventRec upEventRec; 1206 register EventPtr event, downEvent; 1207 EventPtr upEvent = &upEventRec; 1208 register int i; 1209 1210 downEvent = event = *eventP; 1211 *upEvent = *downEvent; 1212 upEvent->event.eventType = ((event->event.eventType == ButtonPress) ? 1213 ButtonRelease : KeyRelease); 1214 if ((upEvent->event.eventType == ButtonRelease) 1215 && (upEvent->event.modifiers != AnyModifier) 1216 && (upEvent->event.modifiers | upEvent->event.modifierMask)) 1217 upEvent->event.modifiers 1218 |= buttonModifierMasks[event->event.eventCode]; 1219 1220 if (event->event.lateModifiers) 1221 event->event.lateModifiers->ref_count += (reps - 1) * 2; 1222 1223 for (i=1; i<reps; i++) { 1224 1225 /* up */ 1226 event->next = XtNew(EventSeqRec); 1227 event = event->next; 1228 *event = *upEvent; 1229 1230 /* timer */ 1231 event->next = XtNew(EventSeqRec); 1232 event = event->next; 1233 *event = timerEventRec; 1234 1235 /* down */ 1236 event->next = XtNew(EventSeqRec); 1237 event = event->next; 1238 *event = *downEvent; 1239 1240 } 1241 1242 event->next = NULL; 1243 *eventP = event; 1244 *actionsP = &event->actions; 1245} 1246 1247static void RepeatDownPlus( 1248 EventPtr *eventP, 1249 int reps, 1250 ActionPtr **actionsP) 1251{ 1252 EventRec upEventRec; 1253 register EventPtr event, downEvent, lastDownEvent = NULL; 1254 EventPtr upEvent = &upEventRec; 1255 register int i; 1256 1257 downEvent = event = *eventP; 1258 *upEvent = *downEvent; 1259 upEvent->event.eventType = ((event->event.eventType == ButtonPress) ? 1260 ButtonRelease : KeyRelease); 1261 if ((upEvent->event.eventType == ButtonRelease) 1262 && (upEvent->event.modifiers != AnyModifier) 1263 && (upEvent->event.modifiers | upEvent->event.modifierMask)) 1264 upEvent->event.modifiers 1265 |= buttonModifierMasks[event->event.eventCode]; 1266 1267 if (event->event.lateModifiers) 1268 event->event.lateModifiers->ref_count += reps * 2 - 1; 1269 1270 for (i=0; i<reps; i++) { 1271 1272 if (i > 0) { 1273 /* down */ 1274 event->next = XtNew(EventSeqRec); 1275 event = event->next; 1276 *event = *downEvent; 1277 } 1278 lastDownEvent = event; 1279 1280 /* up */ 1281 event->next = XtNew(EventSeqRec); 1282 event = event->next; 1283 *event = *upEvent; 1284 1285 /* timer */ 1286 event->next = XtNew(EventSeqRec); 1287 event = event->next; 1288 *event = timerEventRec; 1289 1290 } 1291 1292 event->next = lastDownEvent; 1293 *eventP = event; 1294 *actionsP = &lastDownEvent->actions; 1295} 1296 1297static void RepeatUp( 1298 EventPtr *eventP, 1299 int reps, 1300 ActionPtr **actionsP) 1301{ 1302 EventRec upEventRec; 1303 register EventPtr event, downEvent; 1304 EventPtr upEvent = &upEventRec; 1305 register int i; 1306 1307 /* the event currently sitting in *eventP is an "up" event */ 1308 /* we want to make it a "down" event followed by an "up" event, */ 1309 /* so that sequence matching on the "state" side works correctly. */ 1310 1311 downEvent = event = *eventP; 1312 *upEvent = *downEvent; 1313 downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ? 1314 ButtonPress : KeyPress); 1315 if ((downEvent->event.eventType == ButtonPress) 1316 && (downEvent->event.modifiers != AnyModifier) 1317 && (downEvent->event.modifiers | downEvent->event.modifierMask)) 1318 downEvent->event.modifiers 1319 &= ~buttonModifierMasks[event->event.eventCode]; 1320 1321 if (event->event.lateModifiers) 1322 event->event.lateModifiers->ref_count += reps * 2 - 1; 1323 1324 /* up */ 1325 event->next = XtNew(EventSeqRec); 1326 event = event->next; 1327 *event = *upEvent; 1328 1329 for (i=1; i<reps; i++) { 1330 1331 /* timer */ 1332 event->next = XtNew(EventSeqRec); 1333 event = event->next; 1334 *event = timerEventRec; 1335 1336 /* down */ 1337 event->next = XtNew(EventSeqRec); 1338 event = event->next; 1339 *event = *downEvent; 1340 1341 /* up */ 1342 event->next = XtNew(EventSeqRec); 1343 event = event->next; 1344 *event = *upEvent; 1345 1346 } 1347 1348 event->next = NULL; 1349 *eventP = event; 1350 *actionsP = &event->actions; 1351} 1352 1353static void RepeatUpPlus( 1354 EventPtr *eventP, 1355 int reps, 1356 ActionPtr **actionsP) 1357{ 1358 EventRec upEventRec; 1359 register EventPtr event, downEvent, lastUpEvent = NULL; 1360 EventPtr upEvent = &upEventRec; 1361 register int i; 1362 1363 /* the event currently sitting in *eventP is an "up" event */ 1364 /* we want to make it a "down" event followed by an "up" event, */ 1365 /* so that sequence matching on the "state" side works correctly. */ 1366 1367 downEvent = event = *eventP; 1368 *upEvent = *downEvent; 1369 downEvent->event.eventType = ((event->event.eventType == ButtonRelease) ? 1370 ButtonPress : KeyPress); 1371 if ((downEvent->event.eventType == ButtonPress) 1372 && (downEvent->event.modifiers != AnyModifier) 1373 && (downEvent->event.modifiers | downEvent->event.modifierMask)) 1374 downEvent->event.modifiers 1375 &= ~buttonModifierMasks[event->event.eventCode]; 1376 1377 if (event->event.lateModifiers) 1378 event->event.lateModifiers->ref_count += reps * 2; 1379 1380 for (i=0; i<reps; i++) { 1381 1382 /* up */ 1383 event->next = XtNew(EventSeqRec); 1384 lastUpEvent = event = event->next; 1385 *event = *upEvent; 1386 1387 /* timer */ 1388 event->next = XtNew(EventSeqRec); 1389 event = event->next; 1390 *event = timerEventRec; 1391 1392 /* down */ 1393 event->next = XtNew(EventSeqRec); 1394 event = event->next; 1395 *event = *downEvent; 1396 1397 } 1398 1399 event->next = lastUpEvent; 1400 *eventP = event; 1401 *actionsP = &lastUpEvent->actions; 1402} 1403 1404static void RepeatOther( 1405 EventPtr *eventP, 1406 int reps, 1407 ActionPtr **actionsP) 1408{ 1409 register EventPtr event, tempEvent; 1410 register int i; 1411 1412 tempEvent = event = *eventP; 1413 1414 if (event->event.lateModifiers) 1415 event->event.lateModifiers->ref_count += reps - 1; 1416 1417 for (i=1; i<reps; i++) { 1418 event->next = XtNew(EventSeqRec); 1419 event = event->next; 1420 *event = *tempEvent; 1421 } 1422 1423 *eventP = event; 1424 *actionsP = &event->actions; 1425} 1426 1427static void RepeatOtherPlus( 1428 EventPtr *eventP, 1429 int reps, 1430 ActionPtr **actionsP) 1431{ 1432 register EventPtr event, tempEvent; 1433 register int i; 1434 1435 tempEvent = event = *eventP; 1436 1437 if (event->event.lateModifiers) 1438 event->event.lateModifiers->ref_count += reps - 1; 1439 1440 for (i=1; i<reps; i++) { 1441 event->next = XtNew(EventSeqRec); 1442 event = event->next; 1443 *event = *tempEvent; 1444 } 1445 1446 event->next = event; 1447 *eventP = event; 1448 *actionsP = &event->actions; 1449} 1450 1451static void RepeatEvent( 1452 EventPtr *eventP, 1453 int reps, 1454 Boolean plus, 1455 ActionPtr **actionsP) 1456{ 1457 switch ((*eventP)->event.eventType) { 1458 1459 case ButtonPress: 1460 case KeyPress: 1461 if (plus) RepeatDownPlus(eventP, reps, actionsP); 1462 else RepeatDown(eventP, reps, actionsP); 1463 break; 1464 1465 case ButtonRelease: 1466 case KeyRelease: 1467 if (plus) RepeatUpPlus(eventP, reps, actionsP); 1468 else RepeatUp(eventP, reps, actionsP); 1469 break; 1470 1471 default: 1472 if (plus) RepeatOtherPlus(eventP, reps, actionsP); 1473 else RepeatOther(eventP, reps, actionsP); 1474 } 1475} 1476 1477static String ParseRepeat( 1478 register String str, 1479 int *reps, 1480 Boolean *plus, Boolean *error) 1481{ 1482 1483 /*** Parse the repetitions, for double click etc... ***/ 1484 if (*str != '(' || !(isdigit(str[1]) || str[1] == '+' || str[1] == ')')) 1485 return str; 1486 str++; 1487 if (isdigit(*str)) { 1488 String start = str; 1489 char repStr[7]; 1490 size_t len; 1491 1492 ScanNumeric(str); 1493 len = (str - start); 1494 if (len < sizeof repStr) { 1495 (void) memmove(repStr, start, len); 1496 repStr[len] = '\0'; 1497 *reps = StrToNum(repStr); 1498 } else { 1499 Syntax("Repeat count too large.", ""); 1500 *error = TRUE; 1501 return str; 1502 } 1503 } 1504 if (*reps == 0) { 1505 Syntax("Missing repeat count.",""); 1506 *error = True; 1507 return str; 1508 } 1509 1510 if (*str == '+') { 1511 *plus = TRUE; 1512 str++; 1513 } 1514 if (*str == ')') 1515 str++; 1516 else { 1517 Syntax("Missing ')'.",""); 1518 *error = TRUE; 1519 } 1520 1521 return str; 1522} 1523 1524/*********************************************************************** 1525 * ParseEventSeq 1526 * Parses the left hand side of a translation table production 1527 * up to, and consuming the ":". 1528 * Takes a pointer to a char* (where to start parsing) and returns an 1529 * event seq (in a passed in variable), having updated the String 1530 **********************************************************************/ 1531 1532static String ParseEventSeq( 1533 register String str, 1534 EventSeqPtr *eventSeqP, 1535 ActionPtr **actionsP, 1536 Boolean *error) 1537{ 1538 EventSeqPtr *nextEvent = eventSeqP; 1539 1540 *eventSeqP = NULL; 1541 1542 while ( *str != '\0' && !IsNewline(*str)) { 1543 static Event nullEvent = 1544 {0, 0,NULL, 0, 0L, 0L,_XtRegularMatch,FALSE}; 1545 EventPtr event; 1546 1547 ScanWhitespace(str); 1548 1549 if (*str == '"') { 1550 str++; 1551 while (*str != '"' && *str != '\0' && !IsNewline(*str)) { 1552 event = XtNew(EventRec); 1553 event->event = nullEvent; 1554 event->state = /* (StatePtr) -1 */ NULL; 1555 event->next = NULL; 1556 event->actions = NULL; 1557 str = ParseQuotedStringEvent(str, event,error); 1558 if (*error) { 1559 XtWarningMsg(XtNtranslationParseError, "nonLatin1", 1560 XtCXtToolkitError, 1561 "... probably due to non-Latin1 character in quoted string", 1562 (String*)NULL, (Cardinal*)NULL); 1563 return PanicModeRecovery(str); 1564 } 1565 *nextEvent = event; 1566 *actionsP = &event->actions; 1567 nextEvent = &event->next; 1568 } 1569 if (*str != '"') { 1570 Syntax("Missing '\"'.",""); 1571 *error = TRUE; 1572 return PanicModeRecovery(str); 1573 } 1574 else str++; 1575 } else { 1576 int reps = 0; 1577 Boolean plus = FALSE; 1578 1579 event = XtNew(EventRec); 1580 event->event = nullEvent; 1581 event->state = /* (StatePtr) -1 */ NULL; 1582 event->next = NULL; 1583 event->actions = NULL; 1584 1585 str = ParseEvent(str, event, &reps, &plus, error); 1586 if (*error) return str; 1587 *nextEvent = event; 1588 *actionsP = &event->actions; 1589 if (reps > 1 || plus) 1590 RepeatEvent(&event, reps, plus, actionsP); 1591 nextEvent = &event->next; 1592 } 1593 ScanWhitespace(str); 1594 if (*str == ':') break; 1595 else { 1596 if (*str != ',') { 1597 Syntax("',' or ':' expected while parsing event sequence.",""); 1598 *error = TRUE; 1599 return PanicModeRecovery(str); 1600 } else str++; 1601 } 1602 } 1603 1604 if (*str != ':') { 1605 Syntax("Missing ':'after event sequence.",""); 1606 *error = TRUE; 1607 return PanicModeRecovery(str); 1608 } else str++; 1609 1610 return str; 1611} 1612 1613 1614static String ParseActionProc( 1615 register String str, 1616 XrmQuark *actionProcNameP, 1617 Boolean *error) 1618{ 1619 register String start = str; 1620 char procName[200]; 1621 1622 str = ScanIdent(str); 1623 if (str-start >= 199) { 1624 Syntax("Action procedure name is longer than 199 chars",""); 1625 *error = TRUE; 1626 return str; 1627 } 1628 (void) memmove(procName, start, str-start); 1629 procName[str-start] = '\0'; 1630 *actionProcNameP = XrmStringToQuark( procName ); 1631 return str; 1632} 1633 1634 1635static String ParseString( 1636 register String str, 1637 String *strP) 1638{ 1639 register String start; 1640 1641 if (*str == '"') { 1642 register unsigned prev_len, len; 1643 str++; 1644 start = str; 1645 *strP = NULL; 1646 prev_len = 0; 1647 1648 while (*str != '"' && *str != '\0') { 1649 /* \" produces double quote embedded in a quoted parameter 1650 * \\" produces backslash as last character of a quoted parameter 1651 */ 1652 if (*str == '\\' && 1653 (*(str+1) == '"' || (*(str+1) == '\\' && *(str+2) == '"'))) { 1654 len = prev_len + (str-start+2); 1655 *strP = XtRealloc(*strP, len); 1656 (void) memmove(*strP + prev_len, start, str-start); 1657 prev_len = len-1; 1658 str++; 1659 (*strP)[prev_len-1] = *str; 1660 (*strP)[prev_len] = '\0'; 1661 start = str+1; 1662 } 1663 str++; 1664 } 1665 len = prev_len + (str-start+1); 1666 *strP = XtRealloc(*strP, len); 1667 (void) memmove( *strP + prev_len, start, str-start); 1668 (*strP)[len-1] = '\0'; 1669 if (*str == '"') str++; else 1670 XtWarningMsg(XtNtranslationParseError,"parseString", 1671 XtCXtToolkitError,"Missing '\"'.", 1672 (String *)NULL, (Cardinal *)NULL); 1673 } else { 1674 /* scan non-quoted string, stop on whitespace, ',' or ')' */ 1675 start = str; 1676 while (*str != ' ' 1677 && *str != '\t' 1678 && *str != ',' 1679 && *str != ')' 1680 && !IsNewline(*str) 1681 && *str != '\0') str++; 1682 *strP = __XtMalloc((unsigned)(str-start+1)); 1683 (void) memmove(*strP, start, str-start); 1684 (*strP)[str-start] = '\0'; 1685 } 1686 return str; 1687} 1688 1689 1690static String ParseParamSeq( 1691 register String str, 1692 String **paramSeqP, 1693 Cardinal *paramNumP) 1694{ 1695 typedef struct _ParamRec *ParamPtr; 1696 typedef struct _ParamRec { 1697 ParamPtr next; 1698 String param; 1699 } ParamRec; 1700 1701 ParamPtr params = NULL; 1702 register Cardinal num_params = 0; 1703 register Cardinal i; 1704 1705 ScanWhitespace(str); 1706 while (*str != ')' && *str != '\0' && !IsNewline(*str)) { 1707 String newStr; 1708 str = ParseString(str, &newStr); 1709 if (newStr != NULL) { 1710 ParamPtr temp = (ParamRec*) 1711 ALLOCATE_LOCAL( (unsigned)sizeof(ParamRec) ); 1712 if (temp == NULL) _XtAllocError (NULL); 1713 1714 num_params++; 1715 temp->next = params; 1716 params = temp; 1717 temp->param = newStr; 1718 ScanWhitespace(str); 1719 if (*str == ',') { 1720 str++; 1721 ScanWhitespace(str); 1722 } 1723 } 1724 } 1725 1726 if (num_params != 0) { 1727 String *paramP = (String *) 1728 __XtMalloc( (unsigned)(num_params+1) * sizeof(String) ); 1729 *paramSeqP = paramP; 1730 *paramNumP = num_params; 1731 paramP += num_params; /* list is LIFO right now */ 1732 *paramP-- = NULL; 1733 for (i=0; i < num_params; i++) { 1734 ParamPtr next = params->next; 1735 *paramP-- = params->param; 1736 DEALLOCATE_LOCAL( (char *)params ); 1737 params = next; 1738 } 1739 } else { 1740 *paramSeqP = NULL; 1741 *paramNumP = 0; 1742 } 1743 1744 return str; 1745} 1746 1747static String ParseAction( 1748 String str, 1749 ActionPtr actionP, 1750 XrmQuark* quarkP, 1751 Boolean* error) 1752{ 1753 str = ParseActionProc(str, quarkP, error); 1754 if (*error) return str; 1755 1756 if (*str == '(') { 1757 str++; 1758 str = ParseParamSeq(str, &actionP->params, &actionP->num_params); 1759 } else { 1760 Syntax("Missing '(' while parsing action sequence",""); 1761 *error = TRUE; 1762 return str; 1763 } 1764 if (*str == ')') str++; 1765 else{ 1766 Syntax("Missing ')' while parsing action sequence",""); 1767 *error = TRUE; 1768 return str; 1769 } 1770 return str; 1771} 1772 1773 1774static String ParseActionSeq( 1775 TMParseStateTree parseTree, 1776 String str, 1777 ActionPtr *actionsP, 1778 Boolean *error) 1779{ 1780 ActionPtr *nextActionP = actionsP; 1781 1782 *actionsP = NULL; 1783 while (*str != '\0' && !IsNewline(*str)) { 1784 register ActionPtr action; 1785 XrmQuark quark; 1786 1787 action = XtNew(ActionRec); 1788 action->params = NULL; 1789 action->num_params = 0; 1790 action->next = NULL; 1791 1792 str = ParseAction(str, action, &quark, error); 1793 if (*error) return PanicModeRecovery(str); 1794 1795 action->idx = _XtGetQuarkIndex(parseTree, quark); 1796 ScanWhitespace(str); 1797 *nextActionP = action; 1798 nextActionP = &action->next; 1799 } 1800 if (IsNewline(*str)) str++; 1801 ScanWhitespace(str); 1802 return str; 1803} 1804 1805 1806static void ShowProduction( 1807 String currentProduction) 1808{ 1809 Cardinal num_params = 1; 1810 String params[1]; 1811 size_t len; 1812 char *eol, *production, productionbuf[500]; 1813 1814#ifdef __UNIXOS2__ 1815 eol = strchr(currentProduction, '\r'); 1816 if (!eol) /* try '\n' as well below */ 1817#endif 1818 eol = strchr(currentProduction, '\n'); 1819 if (eol) len = eol - currentProduction; 1820 else len = strlen (currentProduction); 1821 production = XtStackAlloc (len + 1, productionbuf); 1822 if (production == NULL) _XtAllocError (NULL); 1823 (void) memmove(production, currentProduction, len); 1824 production[len] = '\0'; 1825 1826 params[0] = production; 1827 XtWarningMsg(XtNtranslationParseError, "showLine", XtCXtToolkitError, 1828 "... found while parsing '%s'", params, &num_params); 1829 1830 XtStackFree (production, productionbuf); 1831} 1832 1833/*********************************************************************** 1834 * ParseTranslationTableProduction 1835 * Parses one line of event bindings. 1836 ***********************************************************************/ 1837 1838static String ParseTranslationTableProduction( 1839 TMParseStateTree parseTree, 1840 register String str, 1841 Boolean* error) 1842{ 1843 EventSeqPtr eventSeq = NULL; 1844 ActionPtr *actionsP; 1845 String production = str; 1846 1847 actionsP = NULL; 1848 str = ParseEventSeq(str, &eventSeq, &actionsP,error); 1849 if (*error == TRUE) { 1850 ShowProduction(production); 1851 FreeEventSeq(eventSeq); 1852 return (str); 1853 } 1854 ScanWhitespace(str); 1855 str = ParseActionSeq(parseTree, str, actionsP, error); 1856 if (*error == TRUE) { 1857 ShowProduction(production); 1858 FreeEventSeq(eventSeq); 1859 return (str); 1860 } 1861 1862 _XtAddEventSeqToStateTree(eventSeq, parseTree); 1863 FreeEventSeq(eventSeq); 1864 return (str); 1865} 1866 1867static String CheckForPoundSign( 1868 String str, 1869 _XtTranslateOp defaultOp, 1870 _XtTranslateOp *actualOpRtn) 1871{ 1872 String start; 1873 char operation[20]; 1874 _XtTranslateOp opType; 1875 1876 opType = defaultOp; 1877 ScanWhitespace(str); 1878 if (*str == '#') { 1879 int len; 1880 str++; 1881 start = str; 1882 str = ScanIdent(str); 1883 len = MIN(19, str-start); 1884 (void) memmove(operation, start, len); 1885 operation[len] = '\0'; 1886 if (!strcmp(operation,"replace")) 1887 opType = XtTableReplace; 1888 else if (!strcmp(operation,"augment")) 1889 opType = XtTableAugment; 1890 else if (!strcmp(operation,"override")) 1891 opType = XtTableOverride; 1892 ScanWhitespace(str); 1893 if (IsNewline(*str)) { 1894 str++; 1895 ScanWhitespace(str); 1896 } 1897 } 1898 *actualOpRtn = opType; 1899 return str; 1900} 1901 1902static XtTranslations ParseTranslationTable( 1903 String source, 1904 Boolean isAccelerator, 1905 _XtTranslateOp defaultOp, 1906 Boolean* error) 1907{ 1908 XtTranslations xlations; 1909 TMStateTree stateTrees[8]; 1910 TMParseStateTreeRec parseTreeRec, *parseTree = &parseTreeRec; 1911 XrmQuark stackQuarks[200]; 1912 TMBranchHeadRec stackBranchHeads[200]; 1913 StatePtr stackComplexBranchHeads[200]; 1914 _XtTranslateOp actualOp; 1915 1916 if (source == NULL) 1917 return (XtTranslations)NULL; 1918 1919 source = CheckForPoundSign(source, defaultOp, &actualOp); 1920 if (isAccelerator && actualOp == XtTableReplace) 1921 actualOp = defaultOp; 1922 1923 parseTree->isSimple = TRUE; 1924 parseTree->mappingNotifyInterest = FALSE; 1925 parseTree->isAccelerator = isAccelerator; 1926 parseTree->isStackBranchHeads = 1927 parseTree->isStackQuarks = 1928 parseTree->isStackComplexBranchHeads = TRUE; 1929 1930 parseTree->numQuarks = 1931 parseTree->numBranchHeads = 1932 parseTree->numComplexBranchHeads = 0; 1933 1934 parseTree->quarkTblSize = 1935 parseTree->branchHeadTblSize = 1936 parseTree->complexBranchHeadTblSize = 200; 1937 1938 parseTree->quarkTbl = stackQuarks; 1939 parseTree->branchHeadTbl = stackBranchHeads; 1940 parseTree->complexBranchHeadTbl = stackComplexBranchHeads; 1941 1942 while (source != NULL && *source != '\0') { 1943 source = ParseTranslationTableProduction(parseTree, source, error); 1944 if (*error == TRUE) break; 1945 } 1946 stateTrees[0] = _XtParseTreeToStateTree(parseTree); 1947 1948 if (!parseTree->isStackQuarks) 1949 XtFree((char *)parseTree->quarkTbl); 1950 if (!parseTree->isStackBranchHeads) 1951 XtFree((char *)parseTree->branchHeadTbl); 1952 if (!parseTree->isStackComplexBranchHeads) 1953 XtFree((char *)parseTree->complexBranchHeadTbl); 1954 1955 xlations = _XtCreateXlations(stateTrees, 1, NULL, NULL); 1956 xlations->operation = actualOp; 1957 1958#ifdef notdef 1959 XtFree(stateTrees); 1960#endif /* notdef */ 1961 return xlations; 1962} 1963 1964/*** public procedures ***/ 1965 1966/*ARGSUSED*/ 1967Boolean XtCvtStringToAcceleratorTable( 1968 Display* dpy, 1969 XrmValuePtr args, 1970 Cardinal *num_args, 1971 XrmValuePtr from, 1972 XrmValuePtr to, 1973 XtPointer *closure) 1974{ 1975 String str; 1976 Boolean error = FALSE; 1977 1978 if (*num_args != 0) 1979 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 1980 "wrongParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, 1981 "String to AcceleratorTable conversion needs no extra arguments", 1982 (String *)NULL, (Cardinal *)NULL); 1983 str = (String)(from->addr); 1984 if (str == NULL) { 1985 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 1986 "badParameters","cvtStringToAcceleratorTable",XtCXtToolkitError, 1987 "String to AcceleratorTable conversion needs string", 1988 (String *)NULL, (Cardinal *)NULL); 1989 return FALSE; 1990 } 1991 if (to->addr != NULL) { 1992 if (to->size < sizeof(XtAccelerators)) { 1993 to->size = sizeof(XtAccelerators); 1994 return FALSE; 1995 } 1996 *(XtAccelerators*)to->addr = 1997 (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); 1998 } 1999 else { 2000 static XtAccelerators staticStateTable; 2001 staticStateTable = 2002 (XtAccelerators) ParseTranslationTable(str, TRUE, XtTableAugment, &error); 2003 to->addr = (XPointer) &staticStateTable; 2004 to->size = sizeof(XtAccelerators); 2005 } 2006 if (error == TRUE) 2007 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2008 "parseError","cvtStringToAcceleratorTable",XtCXtToolkitError, 2009 "String to AcceleratorTable conversion encountered errors", 2010 (String *)NULL, (Cardinal *)NULL); 2011 return (error != TRUE); 2012} 2013 2014 2015/*ARGSUSED*/ 2016Boolean 2017XtCvtStringToTranslationTable( 2018 Display *dpy, 2019 XrmValuePtr args, 2020 Cardinal *num_args, 2021 XrmValuePtr from, 2022 XrmValuePtr to, 2023 XtPointer *closure_ret) 2024{ 2025 String str; 2026 Boolean error = FALSE; 2027 2028 if (*num_args != 0) 2029 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2030 "wrongParameters","cvtStringToTranslationTable",XtCXtToolkitError, 2031 "String to TranslationTable conversion needs no extra arguments", 2032 (String *)NULL, (Cardinal *)NULL); 2033 str = (String)(from->addr); 2034 if (str == NULL) { 2035 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2036 "badParameters","cvtStringToTranslation",XtCXtToolkitError, 2037 "String to TranslationTable conversion needs string", 2038 (String *)NULL, (Cardinal *)NULL); 2039 return FALSE; 2040 } 2041 if (to->addr != NULL) { 2042 if (to->size < sizeof(XtTranslations)) { 2043 to->size = sizeof(XtTranslations); 2044 return FALSE; 2045 } 2046 *(XtTranslations*)to->addr = 2047 ParseTranslationTable(str, FALSE, XtTableReplace, &error); 2048 } 2049 else { 2050 static XtTranslations staticStateTable; 2051 staticStateTable = 2052 ParseTranslationTable(str, FALSE, XtTableReplace, &error); 2053 to->addr = (XPointer) &staticStateTable; 2054 to->size = sizeof(XtTranslations); 2055 } 2056 if (error == TRUE) 2057 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 2058 "parseError","cvtStringToTranslationTable",XtCXtToolkitError, 2059 "String to TranslationTable conversion encountered errors", 2060 (String *)NULL, (Cardinal *)NULL); 2061 return (error != TRUE); 2062} 2063 2064 2065/* 2066 * Parses a user's or applications translation table 2067 */ 2068XtAccelerators XtParseAcceleratorTable( 2069 _Xconst char* source) 2070{ 2071 Boolean error = FALSE; 2072 XtAccelerators ret = 2073 (XtAccelerators) ParseTranslationTable ((char *)source, TRUE, XtTableAugment, &error); 2074 if (error == TRUE) 2075 XtWarningMsg ("parseError", "cvtStringToAcceleratorTable", 2076 XtCXtToolkitError, 2077 "String to AcceleratorTable conversion encountered errors", 2078 (String *)NULL, (Cardinal *)NULL); 2079 return ret; 2080} 2081 2082XtTranslations XtParseTranslationTable( 2083 _Xconst char* source) 2084{ 2085 Boolean error = FALSE; 2086 XtTranslations ret = ParseTranslationTable((char *)source, FALSE, XtTableReplace, &error); 2087 if (error == TRUE) 2088 XtWarningMsg ("parseError", 2089 "cvtStringToTranslationTable", XtCXtToolkitError, 2090 "String to TranslationTable conversion encountered errors", 2091 (String *)NULL, (Cardinal *)NULL); 2092 return ret; 2093} 2094 2095void _XtTranslateInitialize(void) 2096{ 2097 LOCK_PROCESS; 2098 if (initialized) { 2099 XtWarningMsg("translationError","xtTranslateInitialize", 2100 XtCXtToolkitError,"Initializing Translation manager twice.", 2101 (String *)NULL, (Cardinal *)NULL); 2102 UNLOCK_PROCESS; 2103 return; 2104 } 2105 2106 initialized = TRUE; 2107 UNLOCK_PROCESS; 2108 QMeta = XrmPermStringToQuark("Meta"); 2109 QCtrl = XrmPermStringToQuark("Ctrl"); 2110 QNone = XrmPermStringToQuark("None"); 2111 QAny = XrmPermStringToQuark("Any"); 2112 2113 Compile_XtEventTable( events, XtNumber(events) ); 2114 Compile_XtModifierTable( modifiers, XtNumber(modifiers) ); 2115 CompileNameValueTable( buttonNames ); 2116 CompileNameValueTable( notifyModes ); 2117 CompileNameValueTable( motionDetails ); 2118#if 0 2119 CompileNameValueTable( notifyDetail ); 2120 CompileNameValueTable( visibilityNotify ); 2121 CompileNameValueTable( circulation ); 2122 CompileNameValueTable( propertyChanged ); 2123#endif 2124 CompileNameValueTable( mappingNotify ); 2125} 2126 2127void _XtAddTMConverters( 2128 ConverterTable table) 2129{ 2130 _XtTableAddConverter(table, 2131 _XtQString, 2132 XrmPermStringToQuark(XtRTranslationTable), 2133 XtCvtStringToTranslationTable, (XtConvertArgList) NULL, 2134 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2135 _XtTableAddConverter(table, _XtQString, 2136 XrmPermStringToQuark(XtRAcceleratorTable), 2137 XtCvtStringToAcceleratorTable, (XtConvertArgList) NULL, 2138 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2139 _XtTableAddConverter(table, 2140 XrmPermStringToQuark( _XtRStateTablePair ), 2141 XrmPermStringToQuark(XtRTranslationTable), 2142 _XtCvtMergeTranslations, (XtConvertArgList) NULL, 2143 (Cardinal)0, True, CACHED, _XtFreeTranslations, True); 2144} 2145