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