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