1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. 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 <stdio.h> 76 77typedef struct _TMStringBufRec { 78 _XtString start; 79 _XtString current; 80 Cardinal max; 81} TMStringBufRec, *TMStringBuf; 82 83#define STR_THRESHOLD 25 84#define STR_INCAMOUNT 100 85 86#define CHECK_STR_OVERFLOW(sb) \ 87 if (sb->current - sb->start > (int)sb->max - STR_THRESHOLD) \ 88 { \ 89 _XtString old = sb->start; \ 90 sb->start = XtRealloc(old, (Cardinal)(sb->max += STR_INCAMOUNT)); \ 91 sb->current = sb->current - old + sb->start; \ 92 } 93 94#define ExpandForChars(sb, nchars ) \ 95 if ((unsigned)(sb->current - sb->start) > (sb->max - STR_THRESHOLD - (Cardinal) nchars)) { \ 96 _XtString old = sb->start; \ 97 sb->start = XtRealloc(old, \ 98 (Cardinal)(sb->max = (Cardinal)(sb->max + STR_INCAMOUNT + (Cardinal) nchars))); \ 99 sb->current = sb->current - old + sb->start; \ 100 } 101 102#define ExpandToFit(sb, more) \ 103{ \ 104 size_t l = strlen(more); \ 105 ExpandForChars(sb, l); \ 106 } 107 108static void 109PrintModifiers(TMStringBuf sb, unsigned long mask, unsigned long mod) 110{ 111 Boolean notfirst = False; 112 113 CHECK_STR_OVERFLOW(sb); 114 115 if (mask == ~0UL && mod == 0) { 116 *sb->current++ = '!'; 117 *sb->current = '\0'; 118 return; 119 } 120 121#define PRINTMOD(modmask,modstring) \ 122 if (mask & modmask) { \ 123 if (! (mod & modmask)) { \ 124 *sb->current++ = '~'; \ 125 notfirst = True; \ 126 } \ 127 else if (notfirst) \ 128 *sb->current++ = ' '; \ 129 else notfirst = True; \ 130 strcpy(sb->current, modstring); \ 131 sb->current += strlen(sb->current); \ 132 } 133 134 PRINTMOD(ShiftMask, "Shift"); 135 PRINTMOD(ControlMask, "Ctrl"); /* name is not CtrlMask... */ 136 PRINTMOD(LockMask, "Lock"); 137 PRINTMOD(Mod1Mask, "Mod1"); 138 CHECK_STR_OVERFLOW(sb); 139 PRINTMOD(Mod2Mask, "Mod2"); 140 PRINTMOD(Mod3Mask, "Mod3"); 141 PRINTMOD(Mod4Mask, "Mod4"); 142 PRINTMOD(Mod5Mask, "Mod5"); 143 CHECK_STR_OVERFLOW(sb); 144 PRINTMOD(Button1Mask, "Button1"); 145 PRINTMOD(Button2Mask, "Button2"); 146 PRINTMOD(Button3Mask, "Button3"); 147 CHECK_STR_OVERFLOW(sb); 148 PRINTMOD(Button4Mask, "Button4"); 149 PRINTMOD(Button5Mask, "Button5"); 150 (void) notfirst; 151 152#undef PRINTMOD 153} 154 155static void 156PrintEventType(TMStringBuf sb, unsigned long event) 157{ 158 CHECK_STR_OVERFLOW(sb); 159 switch (event) { 160#define PRINTEVENT(event, name) case event: (void) strcpy(sb->current, name); break; 161 PRINTEVENT(KeyPress, "<KeyPress>") 162 PRINTEVENT(KeyRelease, "<KeyRelease>") 163 PRINTEVENT(ButtonPress, "<ButtonPress>") 164 PRINTEVENT(ButtonRelease, "<ButtonRelease>") 165 PRINTEVENT(MotionNotify, "<MotionNotify>") 166 PRINTEVENT(EnterNotify, "<EnterNotify>") 167 PRINTEVENT(LeaveNotify, "<LeaveNotify>") 168 PRINTEVENT(FocusIn, "<FocusIn>") 169 PRINTEVENT(FocusOut, "<FocusOut>") 170 PRINTEVENT(KeymapNotify, "<KeymapNotify>") 171 PRINTEVENT(Expose, "<Expose>") 172 PRINTEVENT(GraphicsExpose, "<GraphicsExpose>") 173 PRINTEVENT(NoExpose, "<NoExpose>") 174 PRINTEVENT(VisibilityNotify, "<VisibilityNotify>") 175 PRINTEVENT(CreateNotify, "<CreateNotify>") 176 PRINTEVENT(DestroyNotify, "<DestroyNotify>") 177 PRINTEVENT(UnmapNotify, "<UnmapNotify>") 178 PRINTEVENT(MapNotify, "<MapNotify>") 179 PRINTEVENT(MapRequest, "<MapRequest>") 180 PRINTEVENT(ReparentNotify, "<ReparentNotify>") 181 PRINTEVENT(ConfigureNotify, "<ConfigureNotify>") 182 PRINTEVENT(ConfigureRequest, "<ConfigureRequest>") 183 PRINTEVENT(GravityNotify, "<GravityNotify>") 184 PRINTEVENT(ResizeRequest, "<ResizeRequest>") 185 PRINTEVENT(CirculateNotify, "<CirculateNotify>") 186 PRINTEVENT(CirculateRequest, "<CirculateRequest>") 187 PRINTEVENT(PropertyNotify, "<PropertyNotify>") 188 PRINTEVENT(SelectionClear, "<SelectionClear>") 189 PRINTEVENT(SelectionRequest, "<SelectionRequest>") 190 PRINTEVENT(SelectionNotify, "<SelectionNotify>") 191 PRINTEVENT(ColormapNotify, "<ColormapNotify>") 192 PRINTEVENT(ClientMessage, "<ClientMessage>") 193 case _XtEventTimerEventType: 194 (void) strcpy(sb->current, "<EventTimer>"); 195 break; 196 default: 197 (void) sprintf(sb->current, "<0x%x>", (int) event); 198#undef PRINTEVENT 199 } 200 sb->current += strlen(sb->current); 201} 202 203static void 204PrintCode(TMStringBuf sb, unsigned long mask, unsigned long code) 205{ 206 CHECK_STR_OVERFLOW(sb); 207 if (mask != 0) { 208 if (mask != ~0UL) 209 (void) sprintf(sb->current, "0x%lx:0x%lx", mask, code); 210 else 211 (void) sprintf(sb->current, /*"0x%lx" */ "%u", (unsigned) code); 212 sb->current += strlen(sb->current); 213 } 214} 215 216static void 217PrintKeysym(TMStringBuf sb, KeySym keysym) 218{ 219 String keysymName; 220 221 if (keysym == 0) 222 return; 223 224 CHECK_STR_OVERFLOW(sb); 225 keysymName = XKeysymToString(keysym); 226 if (keysymName == NULL) 227 PrintCode(sb, ~0UL, (unsigned long) keysym); 228 else { 229 ExpandToFit(sb, keysymName); 230 strcpy(sb->current, keysymName); 231 sb->current += strlen(sb->current); 232 } 233} 234 235static void 236PrintAtom(TMStringBuf sb, Display *dpy, Atom atom) 237{ 238 _XtString atomName; 239 240 if (atom == 0) 241 return; 242 243 atomName = (dpy ? XGetAtomName(dpy, atom) : NULL); 244 245 if (!atomName) 246 PrintCode(sb, ~0UL, (unsigned long) atom); 247 else { 248 ExpandToFit(sb, atomName); 249 strcpy(sb->current, atomName); 250 sb->current += strlen(sb->current); 251 XFree(atomName); 252 } 253} 254 255static void 256PrintLateModifiers(TMStringBuf sb, LateBindingsPtr lateModifiers) 257{ 258 for (; lateModifiers->keysym; lateModifiers++) { 259 CHECK_STR_OVERFLOW(sb); 260 if (lateModifiers->knot) { 261 *sb->current++ = '~'; 262 } 263 else { 264 *sb->current++ = ' '; 265 } 266 strcpy(sb->current, XKeysymToString(lateModifiers->keysym)); 267 sb->current += strlen(sb->current); 268 if (lateModifiers->pair) { 269 *(sb->current -= 2) = '\0'; /* strip "_L" */ 270 lateModifiers++; /* skip _R keysym */ 271 } 272 } 273} 274 275static void 276PrintEvent(TMStringBuf sb, 277 register TMTypeMatch typeMatch, 278 register TMModifierMatch modMatch, 279 Display *dpy) 280{ 281 if (modMatch->standard) 282 *sb->current++ = ':'; 283 284 PrintModifiers(sb, modMatch->modifierMask, modMatch->modifiers); 285 if (modMatch->lateModifiers != NULL) 286 PrintLateModifiers(sb, modMatch->lateModifiers); 287 PrintEventType(sb, typeMatch->eventType); 288 switch (typeMatch->eventType) { 289 case KeyPress: 290 case KeyRelease: 291 PrintKeysym(sb, (KeySym) typeMatch->eventCode); 292 break; 293 294 case PropertyNotify: 295 case SelectionClear: 296 case SelectionRequest: 297 case SelectionNotify: 298 case ClientMessage: 299 PrintAtom(sb, dpy, (Atom) typeMatch->eventCode); 300 break; 301 302 default: 303 PrintCode(sb, typeMatch->eventCodeMask, typeMatch->eventCode); 304 } 305} 306 307static void 308PrintParams(TMStringBuf sb, String *params, Cardinal num_params) 309{ 310 register Cardinal i; 311 312 for (i = 0; i < num_params; i++) { 313 ExpandToFit(sb, params[i]); 314 if (i != 0) { 315 *sb->current++ = ','; 316 *sb->current++ = ' '; 317 } 318 *sb->current++ = '"'; 319 strcpy(sb->current, params[i]); 320 sb->current += strlen(sb->current); 321 *sb->current++ = '"'; 322 } 323 *sb->current = '\0'; 324} 325 326static void 327PrintActions(TMStringBuf sb, 328 register ActionPtr actions, 329 XrmQuark *quarkTbl, 330 Widget accelWidget) 331{ 332 while (actions != NULL) { 333 String proc; 334 335 *sb->current++ = ' '; 336 337 if (accelWidget) { 338 /* accelerator */ 339 String name = XtName(accelWidget); 340 int nameLen = (int) strlen(name); 341 342 ExpandForChars(sb, nameLen); 343 XtMemmove(sb->current, name, nameLen); 344 sb->current += nameLen; 345 *sb->current++ = '`'; 346 } 347 proc = XrmQuarkToString(quarkTbl[actions->idx]); 348 ExpandToFit(sb, proc); 349 strcpy(sb->current, proc); 350 sb->current += strlen(proc); 351 *sb->current++ = '('; 352 PrintParams(sb, actions->params, actions->num_params); 353 *sb->current++ = ')'; 354 actions = actions->next; 355 } 356 *sb->current = '\0'; 357} 358 359static Boolean 360LookAheadForCycleOrMulticlick(register StatePtr state, 361 StatePtr *state_return, /* state to print, usually startState */ 362 int *countP, 363 StatePtr *nextLevelP) 364{ 365 int repeatCount = 0; 366 StatePtr startState = state; 367 Boolean isCycle = startState->isCycleEnd; 368 TMTypeMatch sTypeMatch; 369 TMModifierMatch sModMatch; 370 371 LOCK_PROCESS; 372 sTypeMatch = TMGetTypeMatch(startState->typeIndex); 373 sModMatch = TMGetModifierMatch(startState->modIndex); 374 375 *state_return = startState; 376 377 for (state = state->nextLevel; state != NULL; state = state->nextLevel) { 378 TMTypeMatch typeMatch = TMGetTypeMatch(state->typeIndex); 379 TMModifierMatch modMatch = TMGetModifierMatch(state->modIndex); 380 381 /* try to pick up the correct state with actions, to be printed */ 382 /* This is to accommodate <ButtonUp>(2+), for example */ 383 if (state->isCycleStart) 384 *state_return = state; 385 386 if (state->isCycleEnd) { 387 *countP = repeatCount; 388 UNLOCK_PROCESS; 389 return True; 390 } 391 if ((startState->typeIndex == state->typeIndex) && 392 (startState->modIndex == state->modIndex)) { 393 repeatCount++; 394 *nextLevelP = state; 395 } 396 else if (typeMatch->eventType == _XtEventTimerEventType) 397 continue; 398 else { /* not same event as starting event and not timer */ 399 400 unsigned int type = (unsigned) sTypeMatch->eventType; 401 unsigned int t = (unsigned) typeMatch->eventType; 402 403 if ((type == ButtonPress && t != ButtonRelease) 404 || (type == ButtonRelease && t != ButtonPress) 405 || (type == KeyPress && t != KeyRelease) 406 || (type == KeyRelease && t != KeyPress) 407 || typeMatch->eventCode != sTypeMatch->eventCode 408 || modMatch->modifiers != sModMatch->modifiers 409 || modMatch->modifierMask != sModMatch->modifierMask 410 || modMatch->lateModifiers != sModMatch->lateModifiers 411 || typeMatch->eventCodeMask != sTypeMatch->eventCodeMask 412 || typeMatch->matchEvent != sTypeMatch->matchEvent 413 || modMatch->standard != sModMatch->standard) 414 /* not inverse of starting event, either */ 415 break; 416 } 417 } 418 *countP = repeatCount; 419 UNLOCK_PROCESS; 420 return isCycle; 421} 422 423static void 424PrintComplexState(TMStringBuf sb, 425 Boolean includeRHS, 426 StatePtr state, 427 TMStateTree stateTree, 428 Widget accelWidget, 429 Display *dpy) 430{ 431 int clickCount = 0; 432 Boolean cycle; 433 StatePtr nextLevel = NULL; 434 StatePtr triggerState = NULL; 435 436 /* print the current state */ 437 if (!state) 438 return; 439 LOCK_PROCESS; 440 cycle = LookAheadForCycleOrMulticlick(state, &triggerState, &clickCount, 441 &nextLevel); 442 443 PrintEvent(sb, TMGetTypeMatch(triggerState->typeIndex), 444 TMGetModifierMatch(triggerState->modIndex), dpy); 445 446 if (cycle || clickCount) { 447 if (clickCount) 448 sprintf(sb->current, "(%d%s)", clickCount + 1, cycle ? "+" : ""); 449 else 450 (void) strncpy(sb->current, "(+)", 4); 451 sb->current += strlen(sb->current); 452 if (!state->actions && nextLevel) 453 state = nextLevel; 454 while (!state->actions && !state->isCycleEnd) 455 state = state->nextLevel; /* should be trigger state */ 456 } 457 458 if (state->actions) { 459 if (includeRHS) { 460 CHECK_STR_OVERFLOW(sb); 461 *sb->current++ = ':'; 462 PrintActions(sb, 463 state->actions, 464 ((TMSimpleStateTree) stateTree)->quarkTbl, 465 accelWidget); 466 *sb->current++ = '\n'; 467 } 468 } 469 else { 470 if (state->nextLevel && !cycle && !clickCount) 471 *sb->current++ = ','; 472 else { 473 /* no actions are attached to this production */ 474 *sb->current++ = ':'; 475 *sb->current++ = '\n'; 476 } 477 } 478 *sb->current = '\0'; 479 480 /* print succeeding states */ 481 if (state->nextLevel && !cycle && !clickCount) 482 PrintComplexState(sb, includeRHS, state->nextLevel, 483 stateTree, accelWidget, dpy); 484 UNLOCK_PROCESS; 485} 486 487typedef struct { 488 TMShortCard tIndex; 489 TMShortCard bIndex; 490} PrintRec, *Print; 491 492static int 493FindNextMatch(PrintRec *printData, 494 TMShortCard numPrints, 495 XtTranslations xlations, 496 TMBranchHead branchHead, 497 StatePtr nextLevel, 498 TMShortCard startIndex) 499{ 500 TMShortCard i; 501 StatePtr currState, candState; 502 Boolean noMatch = True; 503 504 for (i = startIndex; noMatch && i < numPrints; i++) { 505 TMBranchHead prBranchHead; 506 TMComplexStateTree stateTree; 507 508 stateTree = (TMComplexStateTree) 509 xlations->stateTreeTbl[printData[i].tIndex]; 510 prBranchHead = &(stateTree->branchHeadTbl[printData[i].bIndex]); 511 512 if ((prBranchHead->typeIndex == branchHead->typeIndex) && 513 (prBranchHead->modIndex == branchHead->modIndex)) { 514 if (prBranchHead->isSimple) { 515 if (!nextLevel) 516 return i; 517 } 518 else { 519 currState = TMComplexBranchHead(stateTree, prBranchHead); 520 currState = currState->nextLevel; 521 candState = nextLevel; 522 for (; 523 ((currState && !currState->isCycleEnd) && 524 (candState && !candState->isCycleEnd)); 525 currState = currState->nextLevel, 526 candState = candState->nextLevel) { 527 if ((currState->typeIndex != candState->typeIndex) || 528 (currState->modIndex != candState->modIndex)) 529 break; 530 } 531 if (candState == currState) { 532 return i; 533 } 534 } 535 } 536 } 537 return TM_NO_MATCH; 538} 539 540static void 541ProcessLaterMatches(PrintRec *printData, 542 XtTranslations xlations, 543 TMShortCard tIndex, 544 int bIndex, 545 TMShortCard *numPrintsRtn) 546{ 547 TMComplexStateTree stateTree; 548 int i, j; 549 TMBranchHead branchHead, matchBranch = NULL; 550 551 for (i = tIndex; i < (int) xlations->numStateTrees; i++) { 552 stateTree = (TMComplexStateTree) xlations->stateTreeTbl[i]; 553 if (i == tIndex) { 554 matchBranch = &stateTree->branchHeadTbl[bIndex]; 555 j = bIndex + 1; 556 } 557 else 558 j = 0; 559 for (branchHead = &stateTree->branchHeadTbl[j]; 560 j < (int) stateTree->numBranchHeads; j++, branchHead++) { 561 if ((branchHead->typeIndex == matchBranch->typeIndex) && 562 (branchHead->modIndex == matchBranch->modIndex)) { 563 StatePtr state; 564 565 if (!branchHead->isSimple) 566 state = TMComplexBranchHead(stateTree, branchHead); 567 else 568 state = NULL; 569 if ((!branchHead->isSimple || branchHead->hasActions) && 570 (FindNextMatch(printData, 571 *numPrintsRtn, 572 xlations, 573 branchHead, 574 (state ? state->nextLevel : NULL), 575 0) == TM_NO_MATCH)) { 576 printData[*numPrintsRtn].tIndex = (TMShortCard) i; 577 printData[*numPrintsRtn].bIndex = (TMShortCard) j; 578 (*numPrintsRtn)++; 579 } 580 } 581 } 582 } 583} 584 585static void 586ProcessStateTree(PrintRec *printData, 587 XtTranslations xlations, 588 TMShortCard tIndex, 589 TMShortCard *numPrintsRtn) 590{ 591 TMComplexStateTree stateTree; 592 int i; 593 TMBranchHead branchHead; 594 595 stateTree = (TMComplexStateTree) xlations->stateTreeTbl[tIndex]; 596 597 for (i = 0, branchHead = stateTree->branchHeadTbl; 598 i < (int) stateTree->numBranchHeads; i++, branchHead++) { 599 StatePtr state; 600 601 if (!branchHead->isSimple) 602 state = TMComplexBranchHead(stateTree, branchHead); 603 else 604 state = NULL; 605 if (FindNextMatch(printData, *numPrintsRtn, xlations, branchHead, 606 (state ? state->nextLevel : NULL), 0) 607 == TM_NO_MATCH) { 608 if (!branchHead->isSimple || branchHead->hasActions) { 609 printData[*numPrintsRtn].tIndex = tIndex; 610 printData[*numPrintsRtn].bIndex = (TMShortCard) i; 611 (*numPrintsRtn)++; 612 } 613 LOCK_PROCESS; 614 if (_XtGlobalTM.newMatchSemantics == False) 615 ProcessLaterMatches(printData, 616 xlations, tIndex, i, numPrintsRtn); 617 UNLOCK_PROCESS; 618 } 619 } 620} 621 622static void 623PrintState(TMStringBuf sb, 624 TMStateTree tree, 625 TMBranchHead branchHead, 626 Boolean includeRHS, 627 Widget accelWidget, 628 Display *dpy) 629{ 630 TMComplexStateTree stateTree = (TMComplexStateTree) tree; 631 632 LOCK_PROCESS; 633 if (branchHead->isSimple) { 634 PrintEvent(sb, 635 TMGetTypeMatch(branchHead->typeIndex), 636 TMGetModifierMatch(branchHead->modIndex), dpy); 637 if (includeRHS) { 638 ActionRec actRec; 639 640 CHECK_STR_OVERFLOW(sb); 641 *sb->current++ = ':'; 642 actRec.idx = TMBranchMore(branchHead); 643 actRec.num_params = 0; 644 actRec.params = NULL; 645 actRec.next = NULL; 646 PrintActions(sb, &actRec, stateTree->quarkTbl, accelWidget); 647 *sb->current++ = '\n'; 648 } 649 else 650 *sb->current++ = ','; 651#ifdef TRACE_TM 652 if (!branchHead->hasActions) 653 printf(" !! no actions !! "); 654#endif 655 } 656 else { /* it's a complex branchHead */ 657 StatePtr state = TMComplexBranchHead(stateTree, branchHead); 658 659 PrintComplexState(sb, 660 includeRHS, 661 state, tree, accelWidget, (Display *) NULL); 662 } 663 *sb->current = '\0'; 664 UNLOCK_PROCESS; 665} 666 667_XtString 668_XtPrintXlations(Widget w, 669 XtTranslations xlations, 670 Widget accelWidget, 671 _XtBoolean includeRHS) 672{ 673 register Cardinal i; 674 675#define STACKPRINTSIZE 250 676 PrintRec stackPrints[STACKPRINTSIZE]; 677 PrintRec *prints; 678 TMStringBufRec sbRec, *sb = &sbRec; 679 TMShortCard numPrints, maxPrints; 680 681#ifdef TRACE_TM 682 TMBindData bindData = (TMBindData) w->core.tm.proc_table; 683 Boolean hasAccel = (accelWidget ? True : False); 684#endif /* TRACE_TM */ 685 if (xlations == NULL) 686 return NULL; 687 688 sb->current = sb->start = __XtMalloc((Cardinal) 1000); 689 sb->max = 1000; 690 maxPrints = 0; 691 for (i = 0; i < xlations->numStateTrees; i++) 692 maxPrints = (TMShortCard) (maxPrints + 693 ((TMSimpleStateTree) 694 (xlations->stateTreeTbl[i]))-> 695 numBranchHeads); 696 prints = (PrintRec *) 697 XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints); 698 699 numPrints = 0; 700 for (i = 0; i < xlations->numStateTrees; i++) 701 ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints); 702 703 for (i = 0; i < numPrints; i++) { 704 TMSimpleStateTree stateTree = (TMSimpleStateTree) 705 xlations->stateTreeTbl[prints[i].tIndex]; 706 TMBranchHead branchHead = &stateTree->branchHeadTbl[prints[i].bIndex]; 707 708#ifdef TRACE_TM 709 TMComplexBindProcs complexBindProcs; 710 711 if (hasAccel == False) { 712 accelWidget = NULL; 713 if (bindData->simple.isComplex) { 714 complexBindProcs = TMGetComplexBindEntry(bindData, 0); 715 accelWidget = complexBindProcs[prints[i].tIndex].widget; 716 } 717 } 718#endif /* TRACE_TM */ 719 PrintState(sb, (TMStateTree) stateTree, branchHead, 720 (Boolean) includeRHS, accelWidget, XtDisplay(w)); 721 } 722 XtStackFree((XtPointer) prints, (XtPointer) stackPrints); 723 return (sb->start); 724} 725 726#ifndef NO_MIT_HACKS 727void 728_XtDisplayTranslations(Widget widget, 729 XEvent *event _X_UNUSED, 730 String *params _X_UNUSED, 731 Cardinal *num_params _X_UNUSED) 732{ 733 _XtString xString; 734 735 xString = _XtPrintXlations(widget, 736 widget->core.tm.translations, NULL, True); 737 if (xString) { 738 printf("%s\n", xString); 739 XtFree(xString); 740 } 741} 742 743void 744_XtDisplayAccelerators(Widget widget, 745 XEvent *event _X_UNUSED, 746 String *params _X_UNUSED, 747 Cardinal *num_params _X_UNUSED) 748{ 749 _XtString xString; 750 751 xString = _XtPrintXlations(widget, widget->core.accelerators, NULL, True); 752 if (xString) { 753 printf("%s\n", xString); 754 XtFree(xString); 755 } 756} 757 758void 759_XtDisplayInstalledAccelerators(Widget widget, 760 XEvent *event, 761 String *params _X_UNUSED, 762 Cardinal *num_params _X_UNUSED) 763{ 764 Widget eventWidget 765 = XtWindowToWidget(event->xany.display, event->xany.window); 766 register Cardinal i; 767 TMStringBufRec sbRec, *sb = &sbRec; 768 XtTranslations xlations; 769 770#define STACKPRINTSIZE 250 771 PrintRec stackPrints[STACKPRINTSIZE]; 772 PrintRec *prints; 773 TMShortCard numPrints, maxPrints; 774 TMBindData bindData; 775 TMComplexBindProcs complexBindProcs; 776 777 if ((eventWidget == NULL) || (eventWidget->core.tm.translations == NULL)) 778 return; 779 780 xlations = eventWidget->core.tm.translations; 781 bindData = (TMBindData) eventWidget->core.tm.proc_table; 782 if (bindData->simple.isComplex == False) 783 return; 784 785 sb->current = sb->start = __XtMalloc((Cardinal) 1000); 786 sb->start[0] = '\0'; 787 sb->max = 1000; 788 maxPrints = 0; 789 for (i = 0; i < xlations->numStateTrees; i++) 790 maxPrints = (TMShortCard) (maxPrints + 791 ((TMSimpleStateTree) xlations-> 792 stateTreeTbl[i])->numBranchHeads); 793 prints = (PrintRec *) 794 XtStackAlloc(maxPrints * sizeof(PrintRec), stackPrints); 795 796 numPrints = 0; 797 798 complexBindProcs = TMGetComplexBindEntry(bindData, 0); 799 for (i = 0; i < xlations->numStateTrees; i++, complexBindProcs++) { 800 if (complexBindProcs->widget) { 801 ProcessStateTree(prints, xlations, (TMShortCard) i, &numPrints); 802 } 803 } 804 for (i = 0; i < numPrints; i++) { 805 TMSimpleStateTree stateTree = (TMSimpleStateTree) 806 xlations->stateTreeTbl[prints[i].tIndex]; 807 TMBranchHead branchHead = &stateTree->branchHeadTbl[prints[i].bIndex]; 808 809 complexBindProcs = TMGetComplexBindEntry(bindData, 0); 810 811 PrintState(sb, (TMStateTree) stateTree, branchHead, True, 812 complexBindProcs[prints[i].tIndex].widget, 813 XtDisplay(widget)); 814 } 815 XtStackFree((XtPointer) prints, (XtPointer) stackPrints); 816 printf("%s\n", sb->start); 817 XtFree(sb->start); 818} 819#endif /*NO_MIT_HACKS */ 820 821String 822_XtPrintActions(register ActionRec *actions, XrmQuark *quarkTbl) 823{ 824 TMStringBufRec sbRec, *sb = &sbRec; 825 826 sb->max = 1000; 827 sb->current = sb->start = __XtMalloc((Cardinal) 1000); 828 PrintActions(sb, actions, quarkTbl, (Widget) NULL); 829 return sb->start; 830} 831 832String 833_XtPrintState(TMStateTree stateTree, TMBranchHead branchHead) 834{ 835 TMStringBufRec sbRec, *sb = &sbRec; 836 837 sb->current = sb->start = __XtMalloc((Cardinal) 1000); 838 sb->max = 1000; 839 PrintState(sb, stateTree, branchHead, 840 True, (Widget) NULL, (Display *) NULL); 841 return sb->start; 842} 843 844String 845_XtPrintEventSeq(register EventSeqPtr eventSeq, Display *dpy) 846{ 847 TMStringBufRec sbRec, *sb = &sbRec; 848 849#define MAXSEQS 100 850 EventSeqPtr eventSeqs[MAXSEQS]; 851 TMShortCard i, j; 852 Boolean cycle = False; 853 854 sb->current = sb->start = __XtMalloc((Cardinal) 1000); 855 sb->max = 1000; 856 for (i = 0; 857 i < MAXSEQS && eventSeq != NULL && !cycle; 858 eventSeq = eventSeq->next, i++) { 859 eventSeqs[i] = eventSeq; 860 for (j = 0; j < i && !cycle; j++) 861 if (eventSeqs[j] == eventSeq) 862 cycle = True; 863 } 864 LOCK_PROCESS; 865 for (j = 0; j < i; j++) { 866 TMTypeMatch typeMatch; 867 TMModifierMatch modMatch; 868 869 typeMatch = TMGetTypeMatch(_XtGetTypeIndex(&eventSeqs[j]->event)); 870 modMatch = 871 TMGetModifierMatch(_XtGetModifierIndex(&eventSeqs[j]->event)); 872 PrintEvent(sb, typeMatch, modMatch, dpy); 873 *sb->current++ = ','; 874 } 875 UNLOCK_PROCESS; 876 return sb->start; 877} 878