1444c061aSmrg/*********************************************************** 2fdf6a26fSmrgCopyright (c) 1993, Oracle and/or its affiliates. 31477040fSmrg 41477040fSmrgPermission is hereby granted, free of charge, to any person obtaining a 51477040fSmrgcopy of this software and associated documentation files (the "Software"), 61477040fSmrgto deal in the Software without restriction, including without limitation 71477040fSmrgthe rights to use, copy, modify, merge, publish, distribute, sublicense, 81477040fSmrgand/or sell copies of the Software, and to permit persons to whom the 91477040fSmrgSoftware is furnished to do so, subject to the following conditions: 101477040fSmrg 111477040fSmrgThe above copyright notice and this permission notice (including the next 121477040fSmrgparagraph) shall be included in all copies or substantial portions of the 131477040fSmrgSoftware. 141477040fSmrg 151477040fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161477040fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171477040fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 181477040fSmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 191477040fSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 201477040fSmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 211477040fSmrgDEALINGS IN THE SOFTWARE. 221477040fSmrg 231477040fSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24444c061aSmrg 25444c061aSmrg All Rights Reserved 26444c061aSmrg 27444c061aSmrgPermission to use, copy, modify, and distribute this software and its 28444c061aSmrgdocumentation for any purpose and without fee is hereby granted, 29444c061aSmrgprovided that the above copyright notice appear in all copies and that 30444c061aSmrgboth that copyright notice and this permission notice appear in 311477040fSmrgsupporting documentation, and that the name of Digital not be 32444c061aSmrgused in advertising or publicity pertaining to distribution of the 33444c061aSmrgsoftware without specific, written prior permission. 34444c061aSmrg 35444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41444c061aSmrgSOFTWARE. 42444c061aSmrg 43444c061aSmrg******************************************************************/ 44444c061aSmrg 45444c061aSmrg/* 46444c061aSmrg 47444c061aSmrgCopyright 1987, 1988, 1994, 1998 The Open Group 48444c061aSmrg 49444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its 50444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that 51444c061aSmrgthe above copyright notice appear in all copies and that both that 52444c061aSmrgcopyright notice and this permission notice appear in supporting 53444c061aSmrgdocumentation. 54444c061aSmrg 55444c061aSmrgThe above copyright notice and this permission notice shall be included in 56444c061aSmrgall copies or substantial portions of the Software. 57444c061aSmrg 58444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64444c061aSmrg 65444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be 66444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings 67444c061aSmrgin this Software without prior written authorization from The Open Group. 68444c061aSmrg 69444c061aSmrg*/ 70444c061aSmrg 71444c061aSmrg/* TMstate.c -- maintains the state table of actions for the translation 72444c061aSmrg * manager. 73444c061aSmrg */ 74444c061aSmrg#ifdef HAVE_CONFIG_H 75444c061aSmrg#include <config.h> 76444c061aSmrg#endif 77444c061aSmrg#include "IntrinsicI.h" 78444c061aSmrg#ifndef TM_NO_MATCH 79444c061aSmrg#define TM_NO_MATCH (-2) 80a3bd7f05Smrg#endif /* TM_NO_MATCH */ 81444c061aSmrg/* forward definitions */ 82444c061aSmrgstatic StatePtr NewState(TMParseStateTree, TMShortCard, TMShortCard); 83444c061aSmrg 84444c061aSmrgstatic String XtNtranslationError = "translationError"; 85444c061aSmrg 86a3bd7f05SmrgTMGlobalRec _XtGlobalTM; /* initialized to zero K&R */ 87444c061aSmrg 88444c061aSmrg#define MatchIncomingEvent(tmEvent, typeMatch, modMatch) \ 89444c061aSmrg (typeMatch->eventType == tmEvent->event.eventType && \ 90444c061aSmrg (typeMatch->matchEvent != NULL) && \ 91444c061aSmrg (*typeMatch->matchEvent)(typeMatch, modMatch, tmEvent)) 92444c061aSmrg 93444c061aSmrg#define NumStateTrees(xlations) \ 94444c061aSmrg ((translateData->isSimple) ? 1 : (TMComplexXlations(xlations))->numTrees) 95444c061aSmrg 96a3bd7f05Smrgstatic TMShortCard 97a3bd7f05SmrgGetBranchHead(TMParseStateTree parseTree, 98a3bd7f05Smrg TMShortCard typeIndex, 99a3bd7f05Smrg TMShortCard modIndex, 100a3bd7f05Smrg Boolean isDummy) 101444c061aSmrg{ 102fdf6a26fSmrg#define TM_BRANCH_HEAD_TBL_ALLOC ((TMShortCard) 8) 103fdf6a26fSmrg#define TM_BRANCH_HEAD_TBL_REALLOC ((TMShortCard) 8) 104444c061aSmrg 105444c061aSmrg TMBranchHead branchHead = parseTree->branchHeadTbl; 106a3bd7f05Smrg 107444c061aSmrg /* 108444c061aSmrg * dummy is used as a place holder for later matching in old-style 109444c061aSmrg * matching behavior. If there's already an entry we don't need 110444c061aSmrg * another dummy. 111444c061aSmrg */ 112444c061aSmrg if (isDummy) { 113a3bd7f05Smrg TMShortCard i; 114a3bd7f05Smrg 115a3bd7f05Smrg for (i = 0; i < parseTree->numBranchHeads; i++, branchHead++) { 116a3bd7f05Smrg if ((branchHead->typeIndex == typeIndex) && 117a3bd7f05Smrg (branchHead->modIndex == modIndex)) 118a3bd7f05Smrg return i; 119a3bd7f05Smrg } 120a3bd7f05Smrg } 121a3bd7f05Smrg if (parseTree->numBranchHeads == parseTree->branchHeadTblSize) { 122a3bd7f05Smrg 123a3bd7f05Smrg if (parseTree->branchHeadTblSize == 0) 124fdf6a26fSmrg parseTree->branchHeadTblSize = TM_BRANCH_HEAD_TBL_ALLOC; 125a3bd7f05Smrg else 126fdf6a26fSmrg parseTree->branchHeadTblSize += TM_BRANCH_HEAD_TBL_REALLOC; 127fdf6a26fSmrg 128a3bd7f05Smrg if (parseTree->isStackBranchHeads) { 129a3bd7f05Smrg TMBranchHead oldBranchHeadTbl = parseTree->branchHeadTbl; 130a3bd7f05Smrg 131fdf6a26fSmrg parseTree->branchHeadTbl = 132fdf6a26fSmrg XtMallocArray((Cardinal) parseTree->branchHeadTblSize, 133fdf6a26fSmrg (Cardinal) sizeof(TMBranchHeadRec)); 134fdf6a26fSmrg memcpy(parseTree->branchHeadTbl, oldBranchHeadTbl, 135fdf6a26fSmrg parseTree->branchHeadTblSize * sizeof(TMBranchHeadRec)); 136a3bd7f05Smrg parseTree->isStackBranchHeads = False; 137a3bd7f05Smrg } 138a3bd7f05Smrg else { 139a3bd7f05Smrg parseTree->branchHeadTbl = (TMBranchHead) 140fdf6a26fSmrg XtReallocArray(parseTree->branchHeadTbl, 141fdf6a26fSmrg (Cardinal) parseTree->branchHeadTblSize, 142fdf6a26fSmrg (Cardinal) sizeof(TMBranchHeadRec)); 143a3bd7f05Smrg } 144a3bd7f05Smrg } 145444c061aSmrg#ifdef TRACE_TM 146444c061aSmrg LOCK_PROCESS; 147444c061aSmrg _XtGlobalTM.numBranchHeads++; 148444c061aSmrg UNLOCK_PROCESS; 149a3bd7f05Smrg#endif /* TRACE_TM */ 150a3bd7f05Smrg branchHead = &parseTree->branchHeadTbl[parseTree->numBranchHeads++]; 151444c061aSmrg branchHead->typeIndex = typeIndex; 152444c061aSmrg branchHead->modIndex = modIndex; 153444c061aSmrg branchHead->more = 0; 154444c061aSmrg branchHead->isSimple = True; 155444c061aSmrg branchHead->hasActions = False; 156444c061aSmrg branchHead->hasCycles = False; 1570568f49bSmrg return (TMShortCard) (parseTree->numBranchHeads - 1); 158444c061aSmrg} 159444c061aSmrg 160a3bd7f05SmrgTMShortCard 161a3bd7f05Smrg_XtGetQuarkIndex(TMParseStateTree parseTree, XrmQuark quark) 162444c061aSmrg{ 163fdf6a26fSmrg#define TM_QUARK_TBL_ALLOC ((TMShortCard) 16) 164fdf6a26fSmrg#define TM_QUARK_TBL_REALLOC ((TMShortCard) 16) 1650568f49bSmrg TMShortCard i; 166444c061aSmrg 167a3bd7f05Smrg for (i = 0; i < parseTree->numQuarks; i++) 168a3bd7f05Smrg if (parseTree->quarkTbl[i] == quark) 169a3bd7f05Smrg break; 170a3bd7f05Smrg 171a3bd7f05Smrg if (i == parseTree->numQuarks) { 172a3bd7f05Smrg if (parseTree->numQuarks == parseTree->quarkTblSize) { 173a3bd7f05Smrg 174a3bd7f05Smrg if (parseTree->quarkTblSize == 0) 175fdf6a26fSmrg parseTree->quarkTblSize = TM_QUARK_TBL_ALLOC; 176a3bd7f05Smrg else 177fdf6a26fSmrg parseTree->quarkTblSize += TM_QUARK_TBL_REALLOC; 178a3bd7f05Smrg 179a3bd7f05Smrg if (parseTree->isStackQuarks) { 180a3bd7f05Smrg XrmQuark *oldquarkTbl = parseTree->quarkTbl; 181a3bd7f05Smrg 182fdf6a26fSmrg parseTree->quarkTbl = 183fdf6a26fSmrg XtMallocArray((Cardinal) parseTree->quarkTblSize, 184fdf6a26fSmrg (Cardinal) sizeof(XrmQuark)); 185fdf6a26fSmrg memcpy(parseTree->quarkTbl, oldquarkTbl, 186fdf6a26fSmrg parseTree->quarkTblSize * sizeof(XrmQuark)); 187a3bd7f05Smrg parseTree->isStackQuarks = False; 188a3bd7f05Smrg } 189a3bd7f05Smrg else { 190a3bd7f05Smrg parseTree->quarkTbl = (XrmQuark *) 191fdf6a26fSmrg XtReallocArray(parseTree->quarkTbl, 192fdf6a26fSmrg (Cardinal) parseTree->quarkTblSize, 193fdf6a26fSmrg (Cardinal) sizeof(XrmQuark)); 194a3bd7f05Smrg } 195a3bd7f05Smrg } 196a3bd7f05Smrg parseTree->quarkTbl[parseTree->numQuarks++] = quark; 197a3bd7f05Smrg } 198444c061aSmrg return i; 199444c061aSmrg} 200444c061aSmrg 201444c061aSmrg/* 202444c061aSmrg * Get an entry from the parseTrees complex branchHead tbl. If there's none 203444c061aSmrg * there then allocate one 204444c061aSmrg */ 205a3bd7f05Smrgstatic TMShortCard 206a3bd7f05SmrgGetComplexBranchIndex(TMParseStateTree parseTree, 207a3bd7f05Smrg TMShortCard typeIndex _X_UNUSED, 208a3bd7f05Smrg TMShortCard modIndex _X_UNUSED) 209444c061aSmrg{ 210444c061aSmrg#define TM_COMPLEXBRANCH_HEAD_TBL_ALLOC 8 211444c061aSmrg#define TM_COMPLEXBRANCH_HEAD_TBL_REALLOC 4 212444c061aSmrg 213444c061aSmrg if (parseTree->numComplexBranchHeads == parseTree->complexBranchHeadTblSize) { 214a3bd7f05Smrg if (parseTree->complexBranchHeadTblSize == 0) 215a3bd7f05Smrg parseTree->complexBranchHeadTblSize = 216a3bd7f05Smrg (TMShortCard) (parseTree->complexBranchHeadTblSize + 217a3bd7f05Smrg TM_COMPLEXBRANCH_HEAD_TBL_ALLOC); 218a3bd7f05Smrg else 219a3bd7f05Smrg parseTree->complexBranchHeadTblSize = 220a3bd7f05Smrg (TMShortCard) (parseTree->complexBranchHeadTblSize + 221a3bd7f05Smrg TM_COMPLEXBRANCH_HEAD_TBL_REALLOC); 222a3bd7f05Smrg 223a3bd7f05Smrg if (parseTree->isStackComplexBranchHeads) { 224a3bd7f05Smrg StatePtr *oldcomplexBranchHeadTbl = parseTree->complexBranchHeadTbl; 225a3bd7f05Smrg 226fdf6a26fSmrg parseTree->complexBranchHeadTbl = 227fdf6a26fSmrg XtMallocArray((Cardinal) parseTree->complexBranchHeadTblSize, 228fdf6a26fSmrg (Cardinal) sizeof(StatePtr)); 229fdf6a26fSmrg memcpy(parseTree->complexBranchHeadTbl, oldcomplexBranchHeadTbl, 230fdf6a26fSmrg parseTree->complexBranchHeadTblSize * sizeof(StatePtr)); 231a3bd7f05Smrg parseTree->isStackComplexBranchHeads = False; 232a3bd7f05Smrg } 233a3bd7f05Smrg else { 234a3bd7f05Smrg parseTree->complexBranchHeadTbl = (StatePtr *) 235fdf6a26fSmrg XtReallocArray(parseTree->complexBranchHeadTbl, 236fdf6a26fSmrg (Cardinal) parseTree->complexBranchHeadTblSize, 237fdf6a26fSmrg (Cardinal) sizeof(StatePtr)); 238a3bd7f05Smrg } 239444c061aSmrg } 240444c061aSmrg parseTree->complexBranchHeadTbl[parseTree->numComplexBranchHeads++] = NULL; 2410568f49bSmrg return (TMShortCard) (parseTree->numComplexBranchHeads - 1); 242444c061aSmrg} 243444c061aSmrg 244a3bd7f05SmrgTMShortCard 245a3bd7f05Smrg_XtGetTypeIndex(Event *event) 246444c061aSmrg{ 247a3bd7f05Smrg TMShortCard i, j = TM_TYPE_SEGMENT_SIZE; 248a3bd7f05Smrg TMShortCard typeIndex = 0; 249a3bd7f05Smrg TMTypeMatch typeMatch; 250a3bd7f05Smrg TMTypeMatch segment = NULL; 251444c061aSmrg 252444c061aSmrg LOCK_PROCESS; 253444c061aSmrg for (i = 0; i < _XtGlobalTM.numTypeMatchSegments; i++) { 254a3bd7f05Smrg segment = _XtGlobalTM.typeMatchSegmentTbl[i]; 255a3bd7f05Smrg for (j = 0; 256a3bd7f05Smrg typeIndex < _XtGlobalTM.numTypeMatches && j < TM_TYPE_SEGMENT_SIZE; 257a3bd7f05Smrg j++, typeIndex++) { 258a3bd7f05Smrg typeMatch = &(segment[j]); 259a3bd7f05Smrg if (event->eventType == typeMatch->eventType && 260a3bd7f05Smrg event->eventCode == typeMatch->eventCode && 261a3bd7f05Smrg event->eventCodeMask == typeMatch->eventCodeMask && 262a3bd7f05Smrg event->matchEvent == typeMatch->matchEvent) { 263a3bd7f05Smrg UNLOCK_PROCESS; 264a3bd7f05Smrg return typeIndex; 265a3bd7f05Smrg } 266a3bd7f05Smrg } 267444c061aSmrg } 268444c061aSmrg 269444c061aSmrg if (j == TM_TYPE_SEGMENT_SIZE) { 270a3bd7f05Smrg if (_XtGlobalTM.numTypeMatchSegments == 271a3bd7f05Smrg _XtGlobalTM.typeMatchSegmentTblSize) { 272a3bd7f05Smrg _XtGlobalTM.typeMatchSegmentTblSize = 273a3bd7f05Smrg (TMShortCard) (_XtGlobalTM.typeMatchSegmentTblSize + 4); 274a3bd7f05Smrg _XtGlobalTM.typeMatchSegmentTbl = (TMTypeMatch *) 275fdf6a26fSmrg XtReallocArray(_XtGlobalTM.typeMatchSegmentTbl, 276fdf6a26fSmrg (Cardinal) _XtGlobalTM.typeMatchSegmentTblSize, 277fdf6a26fSmrg (Cardinal) sizeof(TMTypeMatch)); 278a3bd7f05Smrg } 279a3bd7f05Smrg _XtGlobalTM.typeMatchSegmentTbl[_XtGlobalTM.numTypeMatchSegments++] = 280fdf6a26fSmrg segment = XtMallocArray(TM_TYPE_SEGMENT_SIZE, 281fdf6a26fSmrg (Cardinal) sizeof(TMTypeMatchRec)); 282a3bd7f05Smrg j = 0; 283444c061aSmrg } 284444c061aSmrg typeMatch = &segment[j]; 285444c061aSmrg typeMatch->eventType = event->eventType; 286444c061aSmrg typeMatch->eventCode = event->eventCode; 287444c061aSmrg typeMatch->eventCodeMask = event->eventCodeMask; 288444c061aSmrg typeMatch->matchEvent = event->matchEvent; 289444c061aSmrg _XtGlobalTM.numTypeMatches++; 290444c061aSmrg UNLOCK_PROCESS; 291444c061aSmrg return typeIndex; 292444c061aSmrg} 293444c061aSmrg 294a3bd7f05Smrgstatic Boolean 295a3bd7f05SmrgCompareLateModifiers(LateBindingsPtr lateBind1P, LateBindingsPtr lateBind2P) 296444c061aSmrg{ 297444c061aSmrg LateBindingsPtr late1P = lateBind1P; 298444c061aSmrg LateBindingsPtr late2P = lateBind2P; 299444c061aSmrg 300444c061aSmrg if (late1P != NULL || late2P != NULL) { 301a3bd7f05Smrg int i = 0; 302a3bd7f05Smrg int j = 0; 303a3bd7f05Smrg 304a3bd7f05Smrg if (late1P != NULL) 305a3bd7f05Smrg for (; late1P->keysym != NoSymbol; i++) 306a3bd7f05Smrg late1P++; 307a3bd7f05Smrg if (late2P != NULL) 308a3bd7f05Smrg for (; late2P->keysym != NoSymbol; j++) 309a3bd7f05Smrg late2P++; 310a3bd7f05Smrg if (i != j) 311a3bd7f05Smrg return FALSE; 312a3bd7f05Smrg late1P--; 313a3bd7f05Smrg while (late1P >= lateBind1P) { 314a3bd7f05Smrg Boolean last = True; 315a3bd7f05Smrg 316a3bd7f05Smrg for (late2P = lateBind2P + i - 1; late2P >= lateBind2P; late2P--) { 317a3bd7f05Smrg if (late1P->keysym == late2P->keysym 318a3bd7f05Smrg && late1P->knot == late2P->knot) { 319a3bd7f05Smrg j--; 320a3bd7f05Smrg if (last) 321a3bd7f05Smrg i--; 322a3bd7f05Smrg break; 323a3bd7f05Smrg } 324a3bd7f05Smrg last = False; 325a3bd7f05Smrg } 326a3bd7f05Smrg late1P--; 327a3bd7f05Smrg } 328a3bd7f05Smrg if (j != 0) 329a3bd7f05Smrg return FALSE; 330444c061aSmrg } 331444c061aSmrg return TRUE; 332444c061aSmrg} 333444c061aSmrg 334a3bd7f05SmrgTMShortCard 335a3bd7f05Smrg_XtGetModifierIndex(Event *event) 336444c061aSmrg{ 337a3bd7f05Smrg TMShortCard i, j = TM_MOD_SEGMENT_SIZE; 338a3bd7f05Smrg TMShortCard modIndex = 0; 339a3bd7f05Smrg TMModifierMatch modMatch; 340a3bd7f05Smrg TMModifierMatch segment = NULL; 341444c061aSmrg 342444c061aSmrg LOCK_PROCESS; 343444c061aSmrg for (i = 0; i < _XtGlobalTM.numModMatchSegments; i++) { 344a3bd7f05Smrg segment = _XtGlobalTM.modMatchSegmentTbl[i]; 345a3bd7f05Smrg for (j = 0; 346a3bd7f05Smrg modIndex < _XtGlobalTM.numModMatches && j < TM_MOD_SEGMENT_SIZE; 347a3bd7f05Smrg j++, modIndex++) { 348a3bd7f05Smrg modMatch = &(segment[j]); 349a3bd7f05Smrg if (event->modifiers == modMatch->modifiers && 350a3bd7f05Smrg event->modifierMask == modMatch->modifierMask && 351a3bd7f05Smrg event->standard == modMatch->standard && 352a3bd7f05Smrg ((!event->lateModifiers && !modMatch->lateModifiers) || 353a3bd7f05Smrg CompareLateModifiers(event->lateModifiers, 354a3bd7f05Smrg modMatch->lateModifiers))) { 355a3bd7f05Smrg /* 356a3bd7f05Smrg * if we found a match then we can free the parser's 357a3bd7f05Smrg * late modifiers. If there isn't a match we use the 358a3bd7f05Smrg * parser's copy 359a3bd7f05Smrg */ 360a3bd7f05Smrg if (event->lateModifiers && 361a3bd7f05Smrg --event->lateModifiers->ref_count == 0) { 362a3bd7f05Smrg XtFree((char *) event->lateModifiers); 363a3bd7f05Smrg event->lateModifiers = NULL; 364a3bd7f05Smrg } 365a3bd7f05Smrg UNLOCK_PROCESS; 366a3bd7f05Smrg return modIndex; 367a3bd7f05Smrg } 368a3bd7f05Smrg } 369444c061aSmrg } 370444c061aSmrg 371444c061aSmrg if (j == TM_MOD_SEGMENT_SIZE) { 372a3bd7f05Smrg if (_XtGlobalTM.numModMatchSegments == 373a3bd7f05Smrg _XtGlobalTM.modMatchSegmentTblSize) { 374a3bd7f05Smrg _XtGlobalTM.modMatchSegmentTblSize = 375a3bd7f05Smrg (TMShortCard) (_XtGlobalTM.modMatchSegmentTblSize + 4); 376a3bd7f05Smrg _XtGlobalTM.modMatchSegmentTbl = (TMModifierMatch *) 377fdf6a26fSmrg XtReallocArray(_XtGlobalTM.modMatchSegmentTbl, 378fdf6a26fSmrg (Cardinal) _XtGlobalTM.modMatchSegmentTblSize, 379fdf6a26fSmrg (Cardinal) sizeof(TMModifierMatch)); 380a3bd7f05Smrg } 381a3bd7f05Smrg _XtGlobalTM.modMatchSegmentTbl[_XtGlobalTM.numModMatchSegments++] = 382fdf6a26fSmrg segment = XtMallocArray(TM_MOD_SEGMENT_SIZE, 383fdf6a26fSmrg (Cardinal) sizeof(TMModifierMatchRec)); 384a3bd7f05Smrg j = 0; 385444c061aSmrg } 386444c061aSmrg modMatch = &segment[j]; 3870568f49bSmrg modMatch->modifiers = event->modifiers; 388444c061aSmrg modMatch->modifierMask = event->modifierMask; 389444c061aSmrg modMatch->standard = event->standard; 390444c061aSmrg /* 391444c061aSmrg * We use the parser's copy of the late binding array 392444c061aSmrg */ 393444c061aSmrg#ifdef TRACE_TM 394444c061aSmrg if (event->lateModifiers) 395a3bd7f05Smrg _XtGlobalTM.numLateBindings++; 396a3bd7f05Smrg#endif /* TRACE_TM */ 397444c061aSmrg modMatch->lateModifiers = event->lateModifiers; 398444c061aSmrg _XtGlobalTM.numModMatches++; 399444c061aSmrg UNLOCK_PROCESS; 400444c061aSmrg return modIndex; 401444c061aSmrg} 402444c061aSmrg 403444c061aSmrg/* 404444c061aSmrg * This is called from the SimpleStateHandler to match a stateTree 405444c061aSmrg * entry to the event coming in 406444c061aSmrg */ 407a3bd7f05Smrgstatic int 408a3bd7f05SmrgMatchBranchHead(TMSimpleStateTree stateTree, int startIndex, TMEventPtr event) 409444c061aSmrg{ 410444c061aSmrg TMBranchHead branchHead = &stateTree->branchHeadTbl[startIndex]; 411444c061aSmrg int i; 412444c061aSmrg 413444c061aSmrg LOCK_PROCESS; 414a3bd7f05Smrg for (i = startIndex; i < (int) stateTree->numBranchHeads; i++, branchHead++) { 415a3bd7f05Smrg TMTypeMatch typeMatch; 416a3bd7f05Smrg TMModifierMatch modMatch; 417a3bd7f05Smrg 418a3bd7f05Smrg typeMatch = TMGetTypeMatch(branchHead->typeIndex); 419a3bd7f05Smrg modMatch = TMGetModifierMatch(branchHead->modIndex); 420a3bd7f05Smrg 421a3bd7f05Smrg if (MatchIncomingEvent(event, typeMatch, modMatch)) { 422a3bd7f05Smrg UNLOCK_PROCESS; 423a3bd7f05Smrg return i; 424a3bd7f05Smrg } 425a3bd7f05Smrg } 426444c061aSmrg UNLOCK_PROCESS; 427444c061aSmrg return (TM_NO_MATCH); 428444c061aSmrg} 429444c061aSmrg 430a3bd7f05SmrgBoolean 431a3bd7f05Smrg_XtRegularMatch(TMTypeMatch typeMatch, 432a3bd7f05Smrg TMModifierMatch modMatch, 433a3bd7f05Smrg TMEventPtr eventSeq) 434444c061aSmrg{ 435a3bd7f05Smrg Modifiers computed = 0; 436a3bd7f05Smrg Modifiers computedMask = 0; 437444c061aSmrg Boolean resolved = TRUE; 438a3bd7f05Smrg 439444c061aSmrg if (typeMatch->eventCode != (eventSeq->event.eventCode & 440a3bd7f05Smrg typeMatch->eventCodeMask)) 441a3bd7f05Smrg return FALSE; 442444c061aSmrg if (modMatch->lateModifiers != NULL) 443a3bd7f05Smrg resolved = _XtComputeLateBindings(eventSeq->xev->xany.display, 444a3bd7f05Smrg modMatch->lateModifiers, 445a3bd7f05Smrg &computed, &computedMask); 446a3bd7f05Smrg if (!resolved) 447a3bd7f05Smrg return FALSE; 4480568f49bSmrg computed = (Modifiers) (computed | modMatch->modifiers); 4490568f49bSmrg computedMask = (Modifiers) (computedMask | modMatch->modifierMask); 450444c061aSmrg 451a3bd7f05Smrg return ((computed & computedMask) == 452a3bd7f05Smrg (eventSeq->event.modifiers & computedMask)); 453444c061aSmrg} 454444c061aSmrg 455a3bd7f05SmrgBoolean 456a3bd7f05Smrg_XtMatchAtom(TMTypeMatch typeMatch, 457a3bd7f05Smrg TMModifierMatch modMatch _X_UNUSED, 458a3bd7f05Smrg TMEventPtr eventSeq) 459444c061aSmrg{ 460a3bd7f05Smrg Atom atom; 461444c061aSmrg 462444c061aSmrg atom = XInternAtom(eventSeq->xev->xany.display, 463a3bd7f05Smrg XrmQuarkToString((XrmQuark) (typeMatch->eventCode)), 464a3bd7f05Smrg False); 465444c061aSmrg return (atom == eventSeq->event.eventCode); 466444c061aSmrg} 467444c061aSmrg 468444c061aSmrg#define IsOn(vec,idx) ((vec)[(idx)>>3] & (1 << ((idx) & 7))) 469444c061aSmrg 470444c061aSmrg/* 471444c061aSmrg * there are certain cases where you want to ignore the event and stay 472444c061aSmrg * in the same state. 473444c061aSmrg */ 474a3bd7f05Smrgstatic Boolean 475a3bd7f05SmrgIgnore(TMEventPtr event) 476444c061aSmrg{ 477444c061aSmrg Display *dpy; 478444c061aSmrg XtPerDisplay pd; 479444c061aSmrg 480444c061aSmrg if (event->event.eventType == MotionNotify) 481a3bd7f05Smrg return TRUE; 482444c061aSmrg if (!(event->event.eventType == KeyPress || 483a3bd7f05Smrg event->event.eventType == KeyRelease)) 484a3bd7f05Smrg return FALSE; 485444c061aSmrg dpy = event->xev->xany.display; 486a3bd7f05Smrg 487444c061aSmrg pd = _XtGetPerDisplay(dpy); 488444c061aSmrg _InitializeKeysymTables(dpy, pd); 489444c061aSmrg return IsOn(pd->isModifier, event->event.eventCode) ? TRUE : FALSE; 490444c061aSmrg} 491444c061aSmrg 492a3bd7f05Smrgstatic void 493a3bd7f05SmrgXEventToTMEvent(XEvent *event, TMEventPtr tmEvent) 494444c061aSmrg{ 495444c061aSmrg tmEvent->xev = event; 496444c061aSmrg tmEvent->event.eventCodeMask = 0; 497444c061aSmrg tmEvent->event.modifierMask = 0; 4980568f49bSmrg tmEvent->event.eventType = (TMLongCard) event->type; 499444c061aSmrg tmEvent->event.lateModifiers = NULL; 500444c061aSmrg tmEvent->event.matchEvent = NULL; 501444c061aSmrg tmEvent->event.standard = FALSE; 502444c061aSmrg 503444c061aSmrg switch (event->type) { 504444c061aSmrg 505a3bd7f05Smrg case KeyPress: 506a3bd7f05Smrg case KeyRelease: 507a3bd7f05Smrg tmEvent->event.eventCode = event->xkey.keycode; 508a3bd7f05Smrg tmEvent->event.modifiers = event->xkey.state; 509a3bd7f05Smrg break; 510a3bd7f05Smrg 511a3bd7f05Smrg case ButtonPress: 512a3bd7f05Smrg case ButtonRelease: 513a3bd7f05Smrg tmEvent->event.eventCode = event->xbutton.button; 514a3bd7f05Smrg tmEvent->event.modifiers = event->xbutton.state; 515a3bd7f05Smrg break; 516a3bd7f05Smrg 517a3bd7f05Smrg case MotionNotify: 518a3bd7f05Smrg tmEvent->event.eventCode = (TMLongCard) event->xmotion.is_hint; 519a3bd7f05Smrg tmEvent->event.modifiers = event->xmotion.state; 520a3bd7f05Smrg break; 521a3bd7f05Smrg 522a3bd7f05Smrg case EnterNotify: 523a3bd7f05Smrg case LeaveNotify: 524a3bd7f05Smrg tmEvent->event.eventCode = (TMLongCard) event->xcrossing.mode; 525a3bd7f05Smrg tmEvent->event.modifiers = event->xcrossing.state; 526a3bd7f05Smrg break; 527a3bd7f05Smrg 528a3bd7f05Smrg case PropertyNotify: 529a3bd7f05Smrg tmEvent->event.eventCode = event->xproperty.atom; 530a3bd7f05Smrg tmEvent->event.modifiers = 0; 531a3bd7f05Smrg break; 532a3bd7f05Smrg 533a3bd7f05Smrg case SelectionClear: 534a3bd7f05Smrg tmEvent->event.eventCode = event->xselectionclear.selection; 535a3bd7f05Smrg tmEvent->event.modifiers = 0; 536a3bd7f05Smrg break; 537a3bd7f05Smrg 538a3bd7f05Smrg case SelectionRequest: 539a3bd7f05Smrg tmEvent->event.eventCode = event->xselectionrequest.selection; 540a3bd7f05Smrg tmEvent->event.modifiers = 0; 541a3bd7f05Smrg break; 542a3bd7f05Smrg 543a3bd7f05Smrg case SelectionNotify: 544a3bd7f05Smrg tmEvent->event.eventCode = event->xselection.selection; 545a3bd7f05Smrg tmEvent->event.modifiers = 0; 546a3bd7f05Smrg break; 547a3bd7f05Smrg 548a3bd7f05Smrg case ClientMessage: 549a3bd7f05Smrg tmEvent->event.eventCode = event->xclient.message_type; 550a3bd7f05Smrg tmEvent->event.modifiers = 0; 551a3bd7f05Smrg break; 552a3bd7f05Smrg 553a3bd7f05Smrg case MappingNotify: 554a3bd7f05Smrg tmEvent->event.eventCode = (TMLongCard) event->xmapping.request; 555a3bd7f05Smrg tmEvent->event.modifiers = 0; 556a3bd7f05Smrg break; 557a3bd7f05Smrg 558a3bd7f05Smrg case FocusIn: 559a3bd7f05Smrg case FocusOut: 560a3bd7f05Smrg tmEvent->event.eventCode = (TMLongCard) event->xfocus.mode; 561a3bd7f05Smrg tmEvent->event.modifiers = 0; 562a3bd7f05Smrg break; 563a3bd7f05Smrg 564a3bd7f05Smrg default: 565a3bd7f05Smrg tmEvent->event.eventCode = 0; 566a3bd7f05Smrg tmEvent->event.modifiers = 0; 567a3bd7f05Smrg break; 568444c061aSmrg } 569444c061aSmrg} 570444c061aSmrg 571a3bd7f05Smrgstatic unsigned long 572a3bd7f05SmrgGetTime(XtTM tm, XEvent *event) 573444c061aSmrg{ 574444c061aSmrg switch (event->type) { 575444c061aSmrg 576a3bd7f05Smrg case KeyPress: 577a3bd7f05Smrg case KeyRelease: 578a3bd7f05Smrg return event->xkey.time; 579444c061aSmrg 580a3bd7f05Smrg case ButtonPress: 581a3bd7f05Smrg case ButtonRelease: 582a3bd7f05Smrg return event->xbutton.time; 583444c061aSmrg 584a3bd7f05Smrg default: 585a3bd7f05Smrg return tm->lastEventTime; 586444c061aSmrg 587444c061aSmrg } 588444c061aSmrg 589444c061aSmrg} 590444c061aSmrg 591a3bd7f05Smrgstatic void 592a3bd7f05SmrgHandleActions(Widget w, 593a3bd7f05Smrg XEvent *event, 594a3bd7f05Smrg TMSimpleStateTree stateTree, 595a3bd7f05Smrg Widget accelWidget, 596a3bd7f05Smrg XtActionProc *procs, 597a3bd7f05Smrg ActionRec *actions) 598444c061aSmrg{ 599a3bd7f05Smrg ActionHook actionHookList; 600a3bd7f05Smrg Widget bindWidget; 601444c061aSmrg 602444c061aSmrg bindWidget = accelWidget ? accelWidget : w; 603444c061aSmrg if (accelWidget && !XtIsSensitive(accelWidget) && 604a3bd7f05Smrg (event->type == KeyPress || event->type == KeyRelease || 605a3bd7f05Smrg event->type == ButtonPress || event->type == ButtonRelease || 606a3bd7f05Smrg event->type == MotionNotify || event->type == EnterNotify || 607a3bd7f05Smrg event->type == LeaveNotify || event->type == FocusIn || 608a3bd7f05Smrg event->type == FocusOut)) 609a3bd7f05Smrg return; 610444c061aSmrg 611444c061aSmrg actionHookList = XtWidgetToApplicationContext(w)->action_hook_list; 612444c061aSmrg 613444c061aSmrg while (actions != NULL) { 614a3bd7f05Smrg /* perform any actions */ 615a3bd7f05Smrg if (procs[actions->idx] != NULL) { 616a3bd7f05Smrg if (actionHookList) { 617a3bd7f05Smrg ActionHook hook; 618a3bd7f05Smrg ActionHook next_hook; 619a3bd7f05Smrg String procName = 620a3bd7f05Smrg XrmQuarkToString(stateTree->quarkTbl[actions->idx]); 621a3bd7f05Smrg 622a3bd7f05Smrg for (hook = actionHookList; hook != NULL;) { 623a3bd7f05Smrg /* 624a3bd7f05Smrg * Need to cache hook->next because the following action 625a3bd7f05Smrg * proc may free hook via XtRemoveActionHook making 626a3bd7f05Smrg * hook->next invalid upon return from the action proc. 627a3bd7f05Smrg */ 628a3bd7f05Smrg next_hook = hook->next; 629a3bd7f05Smrg (*hook->proc) (bindWidget, 630a3bd7f05Smrg hook->closure, 631a3bd7f05Smrg procName, 632a3bd7f05Smrg event, 633a3bd7f05Smrg actions->params, &actions->num_params); 634a3bd7f05Smrg hook = next_hook; 635a3bd7f05Smrg } 636a3bd7f05Smrg } 637a3bd7f05Smrg (*(procs[actions->idx])) 638a3bd7f05Smrg (bindWidget, event, actions->params, &actions->num_params); 639a3bd7f05Smrg } 640a3bd7f05Smrg actions = actions->next; 641444c061aSmrg } 642444c061aSmrg} 643444c061aSmrg 644444c061aSmrgtypedef struct { 645444c061aSmrg unsigned int isCycleStart:1; 646444c061aSmrg unsigned int isCycleEnd:1; 647444c061aSmrg TMShortCard typeIndex; 648444c061aSmrg TMShortCard modIndex; 649a3bd7f05Smrg} MatchPairRec, *MatchPair; 650444c061aSmrg 651a3bd7f05Smrgtypedef struct TMContextRec { 652a3bd7f05Smrg TMShortCard numMatches; 653a3bd7f05Smrg TMShortCard maxMatches; 654a3bd7f05Smrg MatchPair matches; 655a3bd7f05Smrg} TMContextRec, *TMContext; 656444c061aSmrg 657a3bd7f05Smrgstatic TMContextRec contextCache[2]; 658444c061aSmrg 659444c061aSmrg#define GetContextPtr(tm) ((TMContext *)&(tm->current_state)) 660444c061aSmrg 661444c061aSmrg#define TM_CONTEXT_MATCHES_ALLOC 4 662444c061aSmrg#define TM_CONTEXT_MATCHES_REALLOC 2 663444c061aSmrg 664a3bd7f05Smrgstatic void 665a3bd7f05SmrgPushContext(TMContext *contextPtr, StatePtr newState) 666444c061aSmrg{ 667a3bd7f05Smrg TMContext context = *contextPtr; 668444c061aSmrg 669444c061aSmrg LOCK_PROCESS; 670a3bd7f05Smrg if (context == NULL) { 671a3bd7f05Smrg if (contextCache[0].numMatches == 0) 672a3bd7f05Smrg context = &contextCache[0]; 673a3bd7f05Smrg else if (contextCache[1].numMatches == 0) 674a3bd7f05Smrg context = &contextCache[1]; 675a3bd7f05Smrg if (!context) { 676a3bd7f05Smrg context = XtNew(TMContextRec); 677a3bd7f05Smrg context->matches = NULL; 678a3bd7f05Smrg context->numMatches = context->maxMatches = 0; 679a3bd7f05Smrg } 680a3bd7f05Smrg } 681444c061aSmrg if (context->numMatches && 682a3bd7f05Smrg context->matches[context->numMatches - 1].isCycleEnd) { 683a3bd7f05Smrg TMShortCard i; 684a3bd7f05Smrg 685a3bd7f05Smrg for (i = 0; 686a3bd7f05Smrg i < context->numMatches && 687a3bd7f05Smrg !(context->matches[i].isCycleStart); i++) { 688a3bd7f05Smrg }; 689a3bd7f05Smrg if (i < context->numMatches) 690a3bd7f05Smrg context->numMatches = (TMShortCard) (i + 1); 691444c061aSmrg#ifdef DEBUG 692a3bd7f05Smrg else 693a3bd7f05Smrg XtWarning("pushing cycle end with no cycle start"); 694a3bd7f05Smrg#endif /* DEBUG */ 695a3bd7f05Smrg } 696a3bd7f05Smrg else { 697a3bd7f05Smrg if (context->numMatches == context->maxMatches) { 698a3bd7f05Smrg if (context->maxMatches == 0) 699a3bd7f05Smrg context->maxMatches = 700a3bd7f05Smrg (TMShortCard) (context->maxMatches + 701a3bd7f05Smrg TM_CONTEXT_MATCHES_ALLOC); 702a3bd7f05Smrg else 703a3bd7f05Smrg context->maxMatches = 704a3bd7f05Smrg (TMShortCard) (context->maxMatches + 705a3bd7f05Smrg TM_CONTEXT_MATCHES_REALLOC); 706a3bd7f05Smrg context->matches = (MatchPairRec *) 707fdf6a26fSmrg XtReallocArray(context->matches, 708fdf6a26fSmrg (Cardinal) context->maxMatches, 709fdf6a26fSmrg sizeof(MatchPairRec)); 710a3bd7f05Smrg } 711a3bd7f05Smrg context->matches[context->numMatches].isCycleStart = 712a3bd7f05Smrg newState->isCycleStart; 713a3bd7f05Smrg context->matches[context->numMatches].isCycleEnd = newState->isCycleEnd; 714a3bd7f05Smrg context->matches[context->numMatches].typeIndex = newState->typeIndex; 715a3bd7f05Smrg context->matches[context->numMatches++].modIndex = newState->modIndex; 716a3bd7f05Smrg *contextPtr = context; 717a3bd7f05Smrg } 718a3bd7f05Smrg UNLOCK_PROCESS; 719444c061aSmrg} 720444c061aSmrg 721a3bd7f05Smrgstatic void 722a3bd7f05SmrgFreeContext(TMContext *contextPtr) 723444c061aSmrg{ 724a3bd7f05Smrg TMContext context = NULL; 725444c061aSmrg 726444c061aSmrg LOCK_PROCESS; 727444c061aSmrg 728444c061aSmrg if (&contextCache[0] == *contextPtr) 729a3bd7f05Smrg context = &contextCache[0]; 730444c061aSmrg else if (&contextCache[1] == *contextPtr) 731a3bd7f05Smrg context = &contextCache[1]; 732444c061aSmrg 733444c061aSmrg if (context) 734a3bd7f05Smrg context->numMatches = 0; 735a3bd7f05Smrg else if (*contextPtr) { 736a3bd7f05Smrg XtFree((char *) ((*contextPtr)->matches)); 737a3bd7f05Smrg XtFree((char *) *contextPtr); 738444c061aSmrg } 739444c061aSmrg 740444c061aSmrg *contextPtr = NULL; 741444c061aSmrg UNLOCK_PROCESS; 742444c061aSmrg} 743444c061aSmrg 744a3bd7f05Smrgstatic int 745a3bd7f05SmrgMatchExact(TMSimpleStateTree stateTree, 746a3bd7f05Smrg int startIndex, 747a3bd7f05Smrg TMShortCard typeIndex, 748a3bd7f05Smrg TMShortCard modIndex) 749444c061aSmrg{ 750444c061aSmrg TMBranchHead branchHead = &(stateTree->branchHeadTbl[startIndex]); 751444c061aSmrg int i; 752444c061aSmrg 753a3bd7f05Smrg for (i = startIndex; i < (int) stateTree->numBranchHeads; i++, branchHead++) { 754a3bd7f05Smrg if ((branchHead->typeIndex == typeIndex) && 755a3bd7f05Smrg (branchHead->modIndex == modIndex)) 756a3bd7f05Smrg return i; 757a3bd7f05Smrg } 758444c061aSmrg return (TM_NO_MATCH); 759444c061aSmrg} 760444c061aSmrg 761a3bd7f05Smrgstatic void 762a3bd7f05SmrgHandleSimpleState(Widget w, XtTM tmRecPtr, TMEventRec *curEventPtr) 763444c061aSmrg{ 764a3bd7f05Smrg XtTranslations xlations = tmRecPtr->translations; 765a3bd7f05Smrg TMContext *contextPtr = GetContextPtr(tmRecPtr); 766a3bd7f05Smrg TMShortCard i; 767a3bd7f05Smrg ActionRec *actions = NULL; 768a3bd7f05Smrg Boolean matchExact = False; 769a3bd7f05Smrg Boolean match = False; 770a3bd7f05Smrg StatePtr complexMatchState = NULL; 771a3bd7f05Smrg TMShortCard typeIndex = 0, modIndex = 0; 772a3bd7f05Smrg int matchTreeIndex = TM_NO_MATCH; 773444c061aSmrg 774444c061aSmrg LOCK_PROCESS; 775444c061aSmrg for (i = 0; 776a3bd7f05Smrg ((!match || !complexMatchState) && (i < xlations->numStateTrees)); 777a3bd7f05Smrg i++) { 778a3bd7f05Smrg int currIndex = -1; 779a3bd7f05Smrg TMSimpleStateTree stateTree = 780a3bd7f05Smrg (TMSimpleStateTree) xlations->stateTreeTbl[i]; 781a3bd7f05Smrg 782a3bd7f05Smrg /* 783a3bd7f05Smrg * don't process this tree if we're only looking for a 784a3bd7f05Smrg * complexMatchState and there are no complex states 785a3bd7f05Smrg */ 786a3bd7f05Smrg while (!(match && stateTree->isSimple) && 787a3bd7f05Smrg ((!match || !complexMatchState) && (currIndex != TM_NO_MATCH))) { 788a3bd7f05Smrg currIndex++; 789a3bd7f05Smrg if (matchExact) 790a3bd7f05Smrg currIndex = 791a3bd7f05Smrg MatchExact(stateTree, currIndex, typeIndex, modIndex); 792a3bd7f05Smrg else 793a3bd7f05Smrg currIndex = MatchBranchHead(stateTree, currIndex, curEventPtr); 794a3bd7f05Smrg if (currIndex != TM_NO_MATCH) { 795a3bd7f05Smrg TMBranchHead branchHead; 796a3bd7f05Smrg StatePtr currState; 797a3bd7f05Smrg 798a3bd7f05Smrg branchHead = &stateTree->branchHeadTbl[currIndex]; 799a3bd7f05Smrg if (branchHead->isSimple) 800a3bd7f05Smrg currState = NULL; 801a3bd7f05Smrg else 802a3bd7f05Smrg currState = ((TMComplexStateTree) stateTree) 803a3bd7f05Smrg ->complexBranchHeadTbl[TMBranchMore(branchHead)]; 804a3bd7f05Smrg 805a3bd7f05Smrg /* 806a3bd7f05Smrg * first check for a complete match 807a3bd7f05Smrg */ 808a3bd7f05Smrg if (!match) { 809a3bd7f05Smrg if (branchHead->hasActions) { 810a3bd7f05Smrg if (branchHead->isSimple) { 811a3bd7f05Smrg static ActionRec dummyAction; 812a3bd7f05Smrg 813a3bd7f05Smrg dummyAction.idx = TMBranchMore(branchHead); 814a3bd7f05Smrg actions = &dummyAction; 815a3bd7f05Smrg } 816a3bd7f05Smrg else 817a3bd7f05Smrg actions = currState->actions; 818a3bd7f05Smrg tmRecPtr->lastEventTime = 819a3bd7f05Smrg GetTime(tmRecPtr, curEventPtr->xev); 820a3bd7f05Smrg FreeContext((TMContext *) &tmRecPtr->current_state); 821a3bd7f05Smrg match = True; 822a3bd7f05Smrg matchTreeIndex = i; 823a3bd7f05Smrg } 824a3bd7f05Smrg /* 825a3bd7f05Smrg * if it doesn't have actions and 826a3bd7f05Smrg * it's bc mode then it's a potential match node that is 827a3bd7f05Smrg * used to match later sequences. 828a3bd7f05Smrg */ 829a3bd7f05Smrg if (!TMNewMatchSemantics() && !matchExact) { 830a3bd7f05Smrg matchExact = True; 831a3bd7f05Smrg typeIndex = branchHead->typeIndex; 832a3bd7f05Smrg modIndex = branchHead->modIndex; 833a3bd7f05Smrg } 834a3bd7f05Smrg } 835a3bd7f05Smrg /* 836a3bd7f05Smrg * check for it being an event sequence which can be 837a3bd7f05Smrg * a future match 838a3bd7f05Smrg */ 839a3bd7f05Smrg if (!branchHead->isSimple && 840a3bd7f05Smrg !branchHead->hasActions && !complexMatchState) 841a3bd7f05Smrg complexMatchState = currState; 842a3bd7f05Smrg } 843a3bd7f05Smrg } 844a3bd7f05Smrg } 845a3bd7f05Smrg if (match) { 846a3bd7f05Smrg TMBindData bindData = (TMBindData) tmRecPtr->proc_table; 847a3bd7f05Smrg XtActionProc *procs; 848a3bd7f05Smrg Widget accelWidget; 849a3bd7f05Smrg 850a3bd7f05Smrg if (bindData->simple.isComplex) { 851a3bd7f05Smrg TMComplexBindProcs bindProcs = 852a3bd7f05Smrg TMGetComplexBindEntry(bindData, matchTreeIndex); 853a3bd7f05Smrg procs = bindProcs->procs; 854a3bd7f05Smrg accelWidget = bindProcs->widget; 855a3bd7f05Smrg } 856a3bd7f05Smrg else { 857a3bd7f05Smrg TMSimpleBindProcs bindProcs = 858a3bd7f05Smrg TMGetSimpleBindEntry(bindData, matchTreeIndex); 859a3bd7f05Smrg procs = bindProcs->procs; 860a3bd7f05Smrg accelWidget = NULL; 861a3bd7f05Smrg } 862a3bd7f05Smrg HandleActions 863a3bd7f05Smrg (w, 864a3bd7f05Smrg curEventPtr->xev, 865a3bd7f05Smrg (TMSimpleStateTree) xlations->stateTreeTbl[matchTreeIndex], 866a3bd7f05Smrg accelWidget, procs, actions); 867a3bd7f05Smrg } 868444c061aSmrg if (complexMatchState) 869a3bd7f05Smrg PushContext(contextPtr, complexMatchState); 870444c061aSmrg UNLOCK_PROCESS; 871444c061aSmrg} 872444c061aSmrg 873a3bd7f05Smrgstatic int 874a3bd7f05SmrgMatchComplexBranch(TMComplexStateTree stateTree, 875a3bd7f05Smrg int startIndex, 876a3bd7f05Smrg TMContext context, 877a3bd7f05Smrg StatePtr *leafStateRtn) 878444c061aSmrg{ 879a3bd7f05Smrg TMShortCard i; 880444c061aSmrg 881444c061aSmrg LOCK_PROCESS; 882a3bd7f05Smrg for (i = (TMShortCard) startIndex; i < stateTree->numComplexBranchHeads; 883a3bd7f05Smrg i++) { 884a3bd7f05Smrg StatePtr candState; 885a3bd7f05Smrg TMShortCard numMatches = context->numMatches; 886a3bd7f05Smrg MatchPair statMatch = context->matches; 887a3bd7f05Smrg 888a3bd7f05Smrg for (candState = stateTree->complexBranchHeadTbl[i]; 889a3bd7f05Smrg numMatches && candState; 890a3bd7f05Smrg numMatches--, statMatch++, candState = candState->nextLevel) { 891a3bd7f05Smrg if ((statMatch->typeIndex != candState->typeIndex) || 892a3bd7f05Smrg (statMatch->modIndex != candState->modIndex)) 893a3bd7f05Smrg break; 894a3bd7f05Smrg } 895a3bd7f05Smrg if (numMatches == 0) { 896a3bd7f05Smrg *leafStateRtn = candState; 897a3bd7f05Smrg UNLOCK_PROCESS; 898a3bd7f05Smrg return i; 899a3bd7f05Smrg } 900a3bd7f05Smrg } 901444c061aSmrg *leafStateRtn = NULL; 902444c061aSmrg UNLOCK_PROCESS; 903444c061aSmrg return (TM_NO_MATCH); 904444c061aSmrg} 905444c061aSmrg 906a3bd7f05Smrgstatic StatePtr 907a3bd7f05SmrgTryCurrentTree(TMComplexStateTree *stateTreePtr, 908a3bd7f05Smrg XtTM tmRecPtr, 909a3bd7f05Smrg TMEventRec *curEventPtr) 910444c061aSmrg{ 911a3bd7f05Smrg StatePtr candState = NULL, matchState = NULL; 912a3bd7f05Smrg TMContext *contextPtr = GetContextPtr(tmRecPtr); 913a3bd7f05Smrg TMTypeMatch typeMatch; 914a3bd7f05Smrg TMModifierMatch modMatch; 915a3bd7f05Smrg int currIndex = -1; 916444c061aSmrg 917444c061aSmrg /* 918444c061aSmrg * we want the first sequence that both matches and has actions. 919444c061aSmrg * we keep on looking till we find both 920444c061aSmrg */ 921444c061aSmrg LOCK_PROCESS; 922444c061aSmrg while ((currIndex = 923a3bd7f05Smrg MatchComplexBranch(*stateTreePtr, 924a3bd7f05Smrg ++currIndex, (*contextPtr), &candState)) 925a3bd7f05Smrg != TM_NO_MATCH) { 926a3bd7f05Smrg if (candState != NULL) { 927a3bd7f05Smrg typeMatch = TMGetTypeMatch(candState->typeIndex); 928a3bd7f05Smrg modMatch = TMGetModifierMatch(candState->modIndex); 929a3bd7f05Smrg 930a3bd7f05Smrg /* does this state's index match? --> done */ 931a3bd7f05Smrg if (MatchIncomingEvent(curEventPtr, typeMatch, modMatch)) { 932a3bd7f05Smrg if (candState->actions) { 933a3bd7f05Smrg UNLOCK_PROCESS; 934a3bd7f05Smrg return candState; 935a3bd7f05Smrg } 936a3bd7f05Smrg else 937a3bd7f05Smrg matchState = candState; 938a3bd7f05Smrg } 939a3bd7f05Smrg /* is this an event timer? */ 940a3bd7f05Smrg if (typeMatch->eventType == _XtEventTimerEventType) { 941a3bd7f05Smrg StatePtr nextState = candState->nextLevel; 942a3bd7f05Smrg 943a3bd7f05Smrg /* does the succeeding state match? */ 944a3bd7f05Smrg if (nextState != NULL) { 945a3bd7f05Smrg TMTypeMatch nextTypeMatch; 946a3bd7f05Smrg TMModifierMatch nextModMatch; 947a3bd7f05Smrg 948a3bd7f05Smrg nextTypeMatch = TMGetTypeMatch(nextState->typeIndex); 949a3bd7f05Smrg nextModMatch = TMGetModifierMatch(nextState->modIndex); 950a3bd7f05Smrg 951a3bd7f05Smrg /* is it within the timeout? */ 952a3bd7f05Smrg if (MatchIncomingEvent(curEventPtr, 953a3bd7f05Smrg nextTypeMatch, nextModMatch)) { 954a3bd7f05Smrg XEvent *xev = curEventPtr->xev; 955a3bd7f05Smrg unsigned long time = GetTime(tmRecPtr, xev); 956a3bd7f05Smrg XtPerDisplay pd = _XtGetPerDisplay(xev->xany.display); 957a3bd7f05Smrg unsigned long delta = 958a3bd7f05Smrg (unsigned long) pd->multi_click_time; 959a3bd7f05Smrg 960a3bd7f05Smrg if ((tmRecPtr->lastEventTime + delta) >= time) { 961a3bd7f05Smrg if (nextState->actions) { 962a3bd7f05Smrg UNLOCK_PROCESS; 963a3bd7f05Smrg return candState; 964a3bd7f05Smrg } 965a3bd7f05Smrg else 966a3bd7f05Smrg matchState = candState; 967a3bd7f05Smrg } 968a3bd7f05Smrg } 969a3bd7f05Smrg } 970a3bd7f05Smrg } 971a3bd7f05Smrg } 972444c061aSmrg } 973444c061aSmrg UNLOCK_PROCESS; 974444c061aSmrg return matchState; 975444c061aSmrg} 976444c061aSmrg 977a3bd7f05Smrgstatic void 978a3bd7f05SmrgHandleComplexState(Widget w, XtTM tmRecPtr, TMEventRec *curEventPtr) 979444c061aSmrg{ 980a3bd7f05Smrg XtTranslations xlations = tmRecPtr->translations; 981a3bd7f05Smrg TMContext *contextPtr = GetContextPtr(tmRecPtr); 982a3bd7f05Smrg TMShortCard i, matchTreeIndex = 0; 983a3bd7f05Smrg StatePtr matchState = NULL, candState; 984a3bd7f05Smrg TMComplexStateTree *stateTreePtr = 985a3bd7f05Smrg (TMComplexStateTree *) &xlations->stateTreeTbl[0]; 986444c061aSmrg 987444c061aSmrg LOCK_PROCESS; 988a3bd7f05Smrg for (i = 0; i < xlations->numStateTrees; i++, stateTreePtr++) { 989a3bd7f05Smrg /* 990a3bd7f05Smrg * some compilers sign extend Boolean bit fields so test for 991a3bd7f05Smrg * false ||| 992a3bd7f05Smrg */ 993a3bd7f05Smrg if (((*stateTreePtr)->isSimple == False) && 994a3bd7f05Smrg (candState = TryCurrentTree(stateTreePtr, tmRecPtr, curEventPtr))) { 995a3bd7f05Smrg if (!matchState || candState->actions) { 996a3bd7f05Smrg matchTreeIndex = i; 997a3bd7f05Smrg matchState = candState; 998a3bd7f05Smrg if (candState->actions) 999a3bd7f05Smrg break; 1000a3bd7f05Smrg } 1001a3bd7f05Smrg } 1002a3bd7f05Smrg } 1003a3bd7f05Smrg if (matchState == NULL) { 1004a3bd7f05Smrg /* couldn't find it... */ 1005a3bd7f05Smrg if (!Ignore(curEventPtr)) { 1006a3bd7f05Smrg FreeContext(contextPtr); 1007a3bd7f05Smrg HandleSimpleState(w, tmRecPtr, curEventPtr); 1008a3bd7f05Smrg } 1009444c061aSmrg } 1010444c061aSmrg else { 1011a3bd7f05Smrg TMBindData bindData = (TMBindData) tmRecPtr->proc_table; 1012a3bd7f05Smrg XtActionProc *procs; 1013a3bd7f05Smrg Widget accelWidget; 1014a3bd7f05Smrg TMTypeMatch typeMatch; 1015a3bd7f05Smrg 1016a3bd7f05Smrg typeMatch = TMGetTypeMatch(matchState->typeIndex); 1017a3bd7f05Smrg 1018a3bd7f05Smrg PushContext(contextPtr, matchState); 1019a3bd7f05Smrg if (typeMatch->eventType == _XtEventTimerEventType) { 1020a3bd7f05Smrg matchState = matchState->nextLevel; 1021a3bd7f05Smrg PushContext(contextPtr, matchState); 1022a3bd7f05Smrg } 1023a3bd7f05Smrg tmRecPtr->lastEventTime = GetTime(tmRecPtr, curEventPtr->xev); 1024a3bd7f05Smrg 1025a3bd7f05Smrg if (bindData->simple.isComplex) { 1026a3bd7f05Smrg TMComplexBindProcs bindProcs = 1027a3bd7f05Smrg TMGetComplexBindEntry(bindData, matchTreeIndex); 1028a3bd7f05Smrg procs = bindProcs->procs; 1029a3bd7f05Smrg accelWidget = bindProcs->widget; 1030a3bd7f05Smrg } 1031a3bd7f05Smrg else { 1032a3bd7f05Smrg TMSimpleBindProcs bindProcs = 1033a3bd7f05Smrg TMGetSimpleBindEntry(bindData, matchTreeIndex); 1034a3bd7f05Smrg procs = bindProcs->procs; 1035a3bd7f05Smrg accelWidget = NULL; 1036a3bd7f05Smrg } 1037a3bd7f05Smrg HandleActions(w, curEventPtr->xev, (TMSimpleStateTree) 1038a3bd7f05Smrg xlations->stateTreeTbl[matchTreeIndex], 1039a3bd7f05Smrg accelWidget, procs, matchState->actions); 1040444c061aSmrg } 1041444c061aSmrg UNLOCK_PROCESS; 1042444c061aSmrg} 1043444c061aSmrg 1044a3bd7f05Smrgvoid 1045a3bd7f05Smrg_XtTranslateEvent(Widget w, XEvent *event) 1046444c061aSmrg{ 1047a3bd7f05Smrg XtTM tmRecPtr = &w->core.tm; 1048a3bd7f05Smrg TMEventRec curEvent; 1049a3bd7f05Smrg StatePtr current_state = tmRecPtr->current_state; 1050444c061aSmrg 1051a3bd7f05Smrg XEventToTMEvent(event, &curEvent); 1052444c061aSmrg 1053a3bd7f05Smrg if (!tmRecPtr->translations) { 1054444c061aSmrg XtAppWarningMsg(XtWidgetToApplicationContext(w), 1055a3bd7f05Smrg XtNtranslationError, "nullTable", XtCXtToolkitError, 1056a3bd7f05Smrg "Can't translate event through NULL table", NULL, NULL); 1057a3bd7f05Smrg return; 1058444c061aSmrg } 1059444c061aSmrg if (current_state == NULL) 1060a3bd7f05Smrg HandleSimpleState(w, tmRecPtr, &curEvent); 1061444c061aSmrg else 1062a3bd7f05Smrg HandleComplexState(w, tmRecPtr, &curEvent); 1063444c061aSmrg} 1064444c061aSmrg 1065a3bd7f05Smrgstatic StatePtr 1066a3bd7f05SmrgNewState(TMParseStateTree stateTree _X_UNUSED, 1067a3bd7f05Smrg TMShortCard typeIndex, 1068a3bd7f05Smrg TMShortCard modIndex) 1069444c061aSmrg{ 1070444c061aSmrg StatePtr state = XtNew(StateRec); 1071444c061aSmrg 1072444c061aSmrg#ifdef TRACE_TM 1073444c061aSmrg LOCK_PROCESS; 1074444c061aSmrg _XtGlobalTM.numComplexStates++; 1075444c061aSmrg UNLOCK_PROCESS; 1076a3bd7f05Smrg#endif /* TRACE_TM */ 1077444c061aSmrg state->typeIndex = typeIndex; 1078444c061aSmrg state->modIndex = modIndex; 1079444c061aSmrg state->nextLevel = NULL; 1080444c061aSmrg state->actions = NULL; 1081444c061aSmrg state->isCycleStart = state->isCycleEnd = False; 1082444c061aSmrg return state; 1083444c061aSmrg} 1084444c061aSmrg 1085444c061aSmrg/* 1086444c061aSmrg * This routine is an iterator for state trees. If the func returns 1087444c061aSmrg * true then iteration is over. 1088444c061aSmrg */ 1089a3bd7f05Smrgvoid 1090a3bd7f05Smrg_XtTraverseStateTree(TMStateTree tree, _XtTraversalProc func, XtPointer data) 1091444c061aSmrg{ 1092a3bd7f05Smrg TMComplexStateTree stateTree = (TMComplexStateTree) tree; 1093a3bd7f05Smrg TMBranchHead currBH; 1094a3bd7f05Smrg TMShortCard i; 1095a3bd7f05Smrg StateRec dummyStateRec, *dummyState = &dummyStateRec; 1096a3bd7f05Smrg ActionRec dummyActionRec, *dummyAction = &dummyActionRec; 1097a3bd7f05Smrg Boolean firstSimple = True; 1098a3bd7f05Smrg StatePtr currState; 1099444c061aSmrg 1100444c061aSmrg /* first traverse the complex states */ 1101444c061aSmrg if (stateTree->isSimple == False) 1102a3bd7f05Smrg for (i = 0; i < stateTree->numComplexBranchHeads; i++) { 1103a3bd7f05Smrg currState = stateTree->complexBranchHeadTbl[i]; 1104a3bd7f05Smrg for (; currState; currState = currState->nextLevel) { 1105a3bd7f05Smrg if (func(currState, data)) 1106a3bd7f05Smrg return; 1107a3bd7f05Smrg if (currState->isCycleEnd) 1108a3bd7f05Smrg break; 1109a3bd7f05Smrg } 1110a3bd7f05Smrg } 1111444c061aSmrg 1112444c061aSmrg /* now traverse the simple ones */ 1113444c061aSmrg for (i = 0, currBH = stateTree->branchHeadTbl; 1114a3bd7f05Smrg i < stateTree->numBranchHeads; i++, currBH++) { 1115a3bd7f05Smrg if (currBH->isSimple && currBH->hasActions) { 1116a3bd7f05Smrg if (firstSimple) { 1117a3bd7f05Smrg XtBZero((char *) dummyState, sizeof(StateRec)); 1118a3bd7f05Smrg XtBZero((char *) dummyAction, sizeof(ActionRec)); 1119a3bd7f05Smrg dummyState->actions = dummyAction; 1120a3bd7f05Smrg firstSimple = False; 1121a3bd7f05Smrg } 1122a3bd7f05Smrg dummyState->typeIndex = currBH->typeIndex; 1123a3bd7f05Smrg dummyState->modIndex = currBH->modIndex; 1124a3bd7f05Smrg dummyAction->idx = currBH->more; 1125a3bd7f05Smrg if (func(dummyState, data)) 1126a3bd7f05Smrg return; 1127a3bd7f05Smrg } 1128a3bd7f05Smrg } 1129444c061aSmrg} 1130444c061aSmrg 1131a3bd7f05Smrgstatic EventMask 1132a3bd7f05SmrgEventToMask(TMTypeMatch typeMatch, TMModifierMatch modMatch) 1133444c061aSmrg{ 1134444c061aSmrg EventMask returnMask; 1135444c061aSmrg unsigned long eventType = typeMatch->eventType; 1136444c061aSmrg 1137444c061aSmrg if (eventType == MotionNotify) { 11380568f49bSmrg Modifiers modifierMask = (Modifiers) modMatch->modifierMask; 1139444c061aSmrg Modifiers tempMask; 1140444c061aSmrg 1141a3bd7f05Smrg returnMask = 0; 1142444c061aSmrg if (modifierMask == 0) { 1143a3bd7f05Smrg if (modMatch->modifiers == AnyButtonMask) 1144a3bd7f05Smrg return ButtonMotionMask; 1145a3bd7f05Smrg else 1146a3bd7f05Smrg return PointerMotionMask; 1147a3bd7f05Smrg } 1148444c061aSmrg tempMask = modifierMask & 1149a3bd7f05Smrg (Button1Mask | Button2Mask | Button3Mask 1150a3bd7f05Smrg | Button4Mask | Button5Mask); 1151444c061aSmrg if (tempMask == 0) 1152a3bd7f05Smrg return PointerMotionMask; 1153444c061aSmrg if (tempMask & Button1Mask) 1154444c061aSmrg returnMask |= Button1MotionMask; 1155444c061aSmrg if (tempMask & Button2Mask) 1156444c061aSmrg returnMask |= Button2MotionMask; 1157444c061aSmrg if (tempMask & Button3Mask) 1158444c061aSmrg returnMask |= Button3MotionMask; 1159444c061aSmrg if (tempMask & Button4Mask) 1160444c061aSmrg returnMask |= Button4MotionMask; 1161444c061aSmrg if (tempMask & Button5Mask) 1162444c061aSmrg returnMask |= Button5MotionMask; 1163444c061aSmrg return returnMask; 1164444c061aSmrg } 1165a3bd7f05Smrg returnMask = _XtConvertTypeToMask((int) eventType); 1166a3bd7f05Smrg if (returnMask == (StructureNotifyMask | SubstructureNotifyMask)) 1167a3bd7f05Smrg returnMask = StructureNotifyMask; 1168444c061aSmrg return returnMask; 1169444c061aSmrg} 1170444c061aSmrg 1171a3bd7f05Smrgstatic void 1172a3bd7f05SmrgDispatchMappingNotify(Widget widget _X_UNUSED, /* will be NULL from _RefreshMapping */ 1173a3bd7f05Smrg XtPointer closure, /* real Widget */ 1174a3bd7f05Smrg XtPointer call_data) /* XEvent* */ 1175444c061aSmrg{ 1176a3bd7f05Smrg _XtTranslateEvent((Widget) closure, (XEvent *) call_data); 1177444c061aSmrg} 1178444c061aSmrg 1179a3bd7f05Smrgstatic void 1180a3bd7f05SmrgRemoveFromMappingCallbacks(Widget widget, 1181a3bd7f05Smrg XtPointer closure, /* target widget */ 1182a3bd7f05Smrg XtPointer call_data _X_UNUSED) 1183444c061aSmrg{ 1184a3bd7f05Smrg _XtRemoveCallback(&_XtGetPerDisplay(XtDisplay(widget))->mapping_callbacks, 1185a3bd7f05Smrg DispatchMappingNotify, closure); 1186444c061aSmrg} 1187444c061aSmrg 1188a3bd7f05Smrgstatic Boolean 1189a3bd7f05SmrgAggregateEventMask(StatePtr state, XtPointer data) 1190444c061aSmrg{ 1191444c061aSmrg LOCK_PROCESS; 1192a3bd7f05Smrg *((EventMask *) data) |= EventToMask(TMGetTypeMatch(state->typeIndex), 1193a3bd7f05Smrg TMGetModifierMatch(state->modIndex)); 1194444c061aSmrg UNLOCK_PROCESS; 1195444c061aSmrg return False; 1196444c061aSmrg} 1197444c061aSmrg 1198a3bd7f05Smrgvoid 1199a3bd7f05Smrg_XtInstallTranslations(Widget widget) 1200444c061aSmrg{ 1201444c061aSmrg XtTranslations xlations; 1202a3bd7f05Smrg Cardinal i; 1203a3bd7f05Smrg Boolean mappingNotifyInterest = False; 1204444c061aSmrg 1205444c061aSmrg xlations = widget->core.tm.translations; 1206a3bd7f05Smrg if (xlations == NULL) 1207a3bd7f05Smrg return; 1208444c061aSmrg 1209444c061aSmrg /* 1210444c061aSmrg * check for somebody stuffing the translations directly into the 1211444c061aSmrg * instance structure. We will end up being called again out of 1212444c061aSmrg * ComposeTranslations but we *should* have bindings by then 1213444c061aSmrg */ 1214444c061aSmrg if (widget->core.tm.proc_table == NULL) { 1215a3bd7f05Smrg _XtMergeTranslations(widget, NULL, XtTableReplace); 1216a3bd7f05Smrg /* 1217a3bd7f05Smrg * if we're realized then we'll be called out of 1218a3bd7f05Smrg * ComposeTranslations 1219a3bd7f05Smrg */ 1220a3bd7f05Smrg if (XtIsRealized(widget)) 1221a3bd7f05Smrg return; 1222444c061aSmrg } 1223444c061aSmrg 1224444c061aSmrg xlations->eventMask = 0; 1225a3bd7f05Smrg for (i = 0; i < xlations->numStateTrees; i++) { 1226a3bd7f05Smrg TMStateTree stateTree = xlations->stateTreeTbl[i]; 1227a3bd7f05Smrg 1228a3bd7f05Smrg _XtTraverseStateTree(stateTree, 1229a3bd7f05Smrg AggregateEventMask, 1230a3bd7f05Smrg (XtPointer) &xlations->eventMask); 1231a3bd7f05Smrg mappingNotifyInterest = 1232a3bd7f05Smrg (Boolean) (mappingNotifyInterest | 1233a3bd7f05Smrg stateTree->simple.mappingNotifyInterest); 1234a3bd7f05Smrg } 1235444c061aSmrg /* double click needs to make sure that you have selected on both 1236a3bd7f05Smrg button down and up. */ 1237444c061aSmrg 1238444c061aSmrg if (xlations->eventMask & ButtonPressMask) 1239a3bd7f05Smrg xlations->eventMask |= ButtonReleaseMask; 1240444c061aSmrg if (xlations->eventMask & ButtonReleaseMask) 1241a3bd7f05Smrg xlations->eventMask |= ButtonPressMask; 1242444c061aSmrg 1243444c061aSmrg if (mappingNotifyInterest) { 1244a3bd7f05Smrg XtPerDisplay pd = _XtGetPerDisplay(XtDisplay(widget)); 1245a3bd7f05Smrg 1246a3bd7f05Smrg if (pd->mapping_callbacks) 1247a3bd7f05Smrg _XtAddCallbackOnce(&(pd->mapping_callbacks), 1248a3bd7f05Smrg DispatchMappingNotify, (XtPointer) widget); 1249a3bd7f05Smrg else 1250a3bd7f05Smrg _XtAddCallback(&(pd->mapping_callbacks), 1251a3bd7f05Smrg DispatchMappingNotify, (XtPointer) widget); 1252a3bd7f05Smrg 1253a3bd7f05Smrg if (widget->core.destroy_callbacks != NULL) 1254a3bd7f05Smrg _XtAddCallbackOnce((InternalCallbackList *) 1255a3bd7f05Smrg &widget->core.destroy_callbacks, 1256a3bd7f05Smrg RemoveFromMappingCallbacks, (XtPointer) widget); 1257a3bd7f05Smrg else 1258a3bd7f05Smrg _XtAddCallback((InternalCallbackList *) 1259a3bd7f05Smrg &widget->core.destroy_callbacks, 1260a3bd7f05Smrg RemoveFromMappingCallbacks, (XtPointer) widget); 1261a3bd7f05Smrg } 1262a3bd7f05Smrg _XtBindActions(widget, (XtTM) &widget->core.tm); 1263444c061aSmrg _XtRegisterGrabs(widget); 1264444c061aSmrg} 1265444c061aSmrg 1266a3bd7f05Smrgvoid 1267a3bd7f05Smrg_XtRemoveTranslations(Widget widget) 1268444c061aSmrg{ 1269a3bd7f05Smrg Cardinal i; 1270a3bd7f05Smrg Boolean mappingNotifyInterest = False; 1271a3bd7f05Smrg XtTranslations xlations = widget->core.tm.translations; 1272444c061aSmrg 1273444c061aSmrg if (xlations == NULL) 1274a3bd7f05Smrg return; 1275a3bd7f05Smrg 1276a3bd7f05Smrg for (i = 0; i < xlations->numStateTrees; i++) { 1277a3bd7f05Smrg TMSimpleStateTree stateTree = 1278a3bd7f05Smrg (TMSimpleStateTree) xlations->stateTreeTbl[i]; 1279a3bd7f05Smrg mappingNotifyInterest = 1280a3bd7f05Smrg (Boolean) (mappingNotifyInterest | 1281a3bd7f05Smrg stateTree->mappingNotifyInterest); 1282a3bd7f05Smrg } 1283444c061aSmrg if (mappingNotifyInterest) 1284a3bd7f05Smrg RemoveFromMappingCallbacks(widget, (XtPointer) widget, NULL); 1285444c061aSmrg} 1286444c061aSmrg 1287a3bd7f05Smrgstatic void 1288a3bd7f05Smrg_XtUninstallTranslations(Widget widget) 1289444c061aSmrg{ 1290a3bd7f05Smrg XtTranslations xlations = widget->core.tm.translations; 1291444c061aSmrg 1292a3bd7f05Smrg _XtUnbindActions(widget, xlations, (TMBindData) widget->core.tm.proc_table); 1293444c061aSmrg _XtRemoveTranslations(widget); 1294444c061aSmrg widget->core.tm.translations = NULL; 1295a3bd7f05Smrg FreeContext((TMContext *) &widget->core.tm.current_state); 1296444c061aSmrg} 1297444c061aSmrg 1298a3bd7f05Smrgvoid 1299a3bd7f05Smrg_XtDestroyTMData(Widget widget) 1300444c061aSmrg{ 1301a3bd7f05Smrg TMComplexBindData cBindData; 1302444c061aSmrg 1303444c061aSmrg _XtUninstallTranslations(widget); 1304444c061aSmrg 1305a3bd7f05Smrg if ((cBindData = (TMComplexBindData) widget->core.tm.proc_table)) { 1306a3bd7f05Smrg if (cBindData->isComplex) { 1307a3bd7f05Smrg ATranslations nXlations = (ATranslations) cBindData->accel_context; 1308a3bd7f05Smrg 1309a3bd7f05Smrg while (nXlations) { 1310a3bd7f05Smrg ATranslations aXlations = nXlations; 1311a3bd7f05Smrg 1312a3bd7f05Smrg nXlations = nXlations->next; 1313a3bd7f05Smrg XtFree((char *) aXlations); 1314a3bd7f05Smrg } 1315a3bd7f05Smrg } 1316a3bd7f05Smrg XtFree((char *) cBindData); 1317444c061aSmrg } 1318444c061aSmrg} 1319444c061aSmrg 1320444c061aSmrg/*** Public procedures ***/ 1321444c061aSmrg 1322a3bd7f05Smrgvoid 1323a3bd7f05SmrgXtUninstallTranslations(Widget widget) 1324444c061aSmrg{ 1325a3bd7f05Smrg EventMask oldMask; 1326444c061aSmrg Widget hookobj; 1327a3bd7f05Smrg 1328444c061aSmrg WIDGET_TO_APPCON(widget); 1329444c061aSmrg 1330444c061aSmrg LOCK_APP(app); 1331a3bd7f05Smrg if (!widget->core.tm.translations) { 1332a3bd7f05Smrg UNLOCK_APP(app); 1333a3bd7f05Smrg return; 1334444c061aSmrg } 1335444c061aSmrg oldMask = widget->core.tm.translations->eventMask; 1336444c061aSmrg _XtUninstallTranslations(widget); 1337444c061aSmrg if (XtIsRealized(widget) && oldMask) 1338a3bd7f05Smrg XSelectInput(XtDisplay(widget), XtWindow(widget), 1339a3bd7f05Smrg (long) XtBuildEventMask(widget)); 1340444c061aSmrg hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 1341444c061aSmrg if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 1342a3bd7f05Smrg XtChangeHookDataRec call_data; 1343444c061aSmrg 1344a3bd7f05Smrg call_data.type = XtHuninstallTranslations; 1345a3bd7f05Smrg call_data.widget = widget; 1346a3bd7f05Smrg XtCallCallbackList(hookobj, 1347a3bd7f05Smrg ((HookObject) hookobj)->hooks.changehook_callbacks, 1348a3bd7f05Smrg (XtPointer) &call_data); 1349444c061aSmrg } 1350444c061aSmrg UNLOCK_APP(app); 1351444c061aSmrg} 1352444c061aSmrg 1353a3bd7f05SmrgXtTranslations 1354a3bd7f05Smrg_XtCreateXlations(TMStateTree *stateTrees, 1355a3bd7f05Smrg TMShortCard numStateTrees, 1356a3bd7f05Smrg XtTranslations first, 1357a3bd7f05Smrg XtTranslations second) 1358444c061aSmrg{ 1359a3bd7f05Smrg XtTranslations xlations; 1360444c061aSmrg TMShortCard i; 1361444c061aSmrg 1362444c061aSmrg xlations = (XtTranslations) 1363a3bd7f05Smrg __XtMalloc((Cardinal) (sizeof(TranslationData) + 1364a3bd7f05Smrg (size_t) (numStateTrees - 1365a3bd7f05Smrg 1) * sizeof(TMStateTree))); 1366444c061aSmrg#ifdef TRACE_TM 1367444c061aSmrg LOCK_PROCESS; 1368444c061aSmrg if (_XtGlobalTM.numTms == _XtGlobalTM.tmTblSize) { 1369a3bd7f05Smrg _XtGlobalTM.tmTblSize = (TMShortCard) (_XtGlobalTM.tmTblSize + 16); 1370a3bd7f05Smrg _XtGlobalTM.tmTbl = (XtTranslations *) 1371fdf6a26fSmrg XtReallocArray(_XtGlobalTM.tmTbl, 1372fdf6a26fSmrg (Cardinal) _XtGlobalTM.tmTblSize, 1373fdf6a26fSmrg (Cardinal) sizeof(XtTranslations)); 1374444c061aSmrg } 1375444c061aSmrg _XtGlobalTM.tmTbl[_XtGlobalTM.numTms++] = xlations; 1376444c061aSmrg UNLOCK_PROCESS; 1377a3bd7f05Smrg#endif /* TRACE_TM */ 1378444c061aSmrg 1379444c061aSmrg xlations->composers[0] = first; 1380444c061aSmrg xlations->composers[1] = second; 1381444c061aSmrg xlations->hasBindings = False; 1382444c061aSmrg xlations->operation = XtTableReplace; 1383444c061aSmrg 1384a3bd7f05Smrg for (i = 0; i < numStateTrees; i++) { 1385a3bd7f05Smrg xlations->stateTreeTbl[i] = (TMStateTree) stateTrees[i]; 1386a3bd7f05Smrg stateTrees[i]->simple.refCount++; 1387a3bd7f05Smrg } 1388444c061aSmrg xlations->numStateTrees = numStateTrees; 1389444c061aSmrg xlations->eventMask = 0; 1390444c061aSmrg return xlations; 1391444c061aSmrg} 1392444c061aSmrg 1393a3bd7f05SmrgTMStateTree 1394a3bd7f05Smrg_XtParseTreeToStateTree(TMParseStateTree parseTree) 1395444c061aSmrg{ 1396a3bd7f05Smrg TMSimpleStateTree simpleTree; 1397444c061aSmrg 1398444c061aSmrg if (parseTree->numComplexBranchHeads) { 1399a3bd7f05Smrg TMComplexStateTree complexTree; 1400a3bd7f05Smrg 1401a3bd7f05Smrg complexTree = XtNew(TMComplexStateTreeRec); 1402a3bd7f05Smrg complexTree->isSimple = False; 1403fdf6a26fSmrg complexTree->complexBranchHeadTbl = 1404fdf6a26fSmrg XtMallocArray((Cardinal) parseTree->numComplexBranchHeads, 1405fdf6a26fSmrg (Cardinal) sizeof(StatePtr)); 1406fdf6a26fSmrg memcpy(complexTree->complexBranchHeadTbl, 1407fdf6a26fSmrg parseTree->complexBranchHeadTbl, 1408fdf6a26fSmrg parseTree->numComplexBranchHeads * sizeof(StatePtr)); 1409a3bd7f05Smrg complexTree->numComplexBranchHeads = parseTree->numComplexBranchHeads; 1410a3bd7f05Smrg simpleTree = (TMSimpleStateTree) complexTree; 1411444c061aSmrg } 1412444c061aSmrg else { 1413a3bd7f05Smrg simpleTree = XtNew(TMSimpleStateTreeRec); 1414a3bd7f05Smrg simpleTree->isSimple = True; 1415444c061aSmrg } 1416444c061aSmrg simpleTree->isAccelerator = parseTree->isAccelerator; 1417444c061aSmrg simpleTree->refCount = 0; 1418444c061aSmrg simpleTree->mappingNotifyInterest = parseTree->mappingNotifyInterest; 1419444c061aSmrg 1420fdf6a26fSmrg simpleTree->branchHeadTbl = 1421fdf6a26fSmrg XtMallocArray((Cardinal) parseTree->numBranchHeads, 1422fdf6a26fSmrg (Cardinal) sizeof(TMBranchHeadRec)); 1423fdf6a26fSmrg memcpy(simpleTree->branchHeadTbl, parseTree->branchHeadTbl, 1424fdf6a26fSmrg parseTree->numBranchHeads * sizeof(TMBranchHeadRec)); 1425444c061aSmrg simpleTree->numBranchHeads = parseTree->numBranchHeads; 1426444c061aSmrg 1427fdf6a26fSmrg simpleTree->quarkTbl = XtMallocArray((Cardinal) parseTree->numQuarks, 1428fdf6a26fSmrg (Cardinal) sizeof(XrmQuark)); 1429fdf6a26fSmrg memcpy(simpleTree->quarkTbl, parseTree->quarkTbl, 1430fdf6a26fSmrg parseTree->numQuarks * sizeof(XrmQuark)); 1431444c061aSmrg simpleTree->numQuarks = parseTree->numQuarks; 1432444c061aSmrg 1433a3bd7f05Smrg return (TMStateTree) simpleTree; 1434444c061aSmrg} 1435444c061aSmrg 1436a3bd7f05Smrgstatic void 1437a3bd7f05SmrgFreeActions(ActionPtr actions) 1438444c061aSmrg{ 1439444c061aSmrg ActionPtr action; 1440444c061aSmrg TMShortCard i; 1441a3bd7f05Smrg 1442444c061aSmrg for (action = actions; action;) { 1443a3bd7f05Smrg ActionPtr nextAction = action->next; 1444a3bd7f05Smrg 1445a3bd7f05Smrg for (i = (TMShortCard) action->num_params; i;) { 1446a3bd7f05Smrg XtFree((_XtString) action->params[--i]); 1447a3bd7f05Smrg } 1448a3bd7f05Smrg XtFree((char *) action->params); 1449a3bd7f05Smrg XtFree((char *) action); 1450a3bd7f05Smrg action = nextAction; 1451444c061aSmrg } 1452444c061aSmrg} 1453444c061aSmrg 1454a3bd7f05Smrgstatic void 1455a3bd7f05SmrgAmbigActions(EventSeqPtr initialEvent, 1456a3bd7f05Smrg StatePtr *state, 1457a3bd7f05Smrg TMParseStateTree stateTree) 1458444c061aSmrg{ 1459a3bd7f05Smrg String params[3]; 1460a3bd7f05Smrg Cardinal numParams = 0; 1461444c061aSmrg 1462444c061aSmrg params[numParams++] = _XtPrintEventSeq(initialEvent, NULL); 1463444c061aSmrg params[numParams++] = _XtPrintActions((*state)->actions, 1464a3bd7f05Smrg stateTree->quarkTbl); 1465a3bd7f05Smrg XtWarningMsg(XtNtranslationError, "oldActions", XtCXtToolkitError, 1466a3bd7f05Smrg "Previous entry was: %s %s", params, &numParams); 1467a3bd7f05Smrg XtFree((char *) params[0]); 1468a3bd7f05Smrg XtFree((char *) params[1]); 1469444c061aSmrg numParams = 0; 1470a3bd7f05Smrg params[numParams++] = _XtPrintActions(initialEvent->actions, 1471a3bd7f05Smrg stateTree->quarkTbl); 1472a3bd7f05Smrg XtWarningMsg(XtNtranslationError, "newActions", XtCXtToolkitError, 1473a3bd7f05Smrg "New actions are:%s", params, &numParams); 1474a3bd7f05Smrg XtFree((char *) params[0]); 1475a3bd7f05Smrg XtWarningMsg(XtNtranslationError, "ambiguousActions", 1476a3bd7f05Smrg XtCXtToolkitError, 1477a3bd7f05Smrg "Overriding earlier translation manager actions.", NULL, NULL); 1478444c061aSmrg 1479444c061aSmrg FreeActions((*state)->actions); 1480444c061aSmrg (*state)->actions = NULL; 1481444c061aSmrg} 1482444c061aSmrg 1483a3bd7f05Smrgvoid 1484a3bd7f05Smrg_XtAddEventSeqToStateTree(EventSeqPtr eventSeq, TMParseStateTree stateTree) 1485444c061aSmrg{ 1486a3bd7f05Smrg StatePtr *state; 1487a3bd7f05Smrg EventSeqPtr initialEvent = eventSeq; 1488a3bd7f05Smrg TMBranchHead branchHead; 1489a3bd7f05Smrg TMShortCard idx, modIndex, typeIndex; 1490444c061aSmrg 1491a3bd7f05Smrg if (eventSeq == NULL) 1492a3bd7f05Smrg return; 1493444c061aSmrg 1494444c061aSmrg /* note that all states in the event seq passed in start out null */ 1495444c061aSmrg /* we fill them in with the matching state as we traverse the list */ 1496444c061aSmrg 1497444c061aSmrg /* 1498444c061aSmrg * We need to free the parser data structures !!! 1499444c061aSmrg */ 1500444c061aSmrg 1501444c061aSmrg typeIndex = _XtGetTypeIndex(&eventSeq->event); 1502444c061aSmrg modIndex = _XtGetModifierIndex(&eventSeq->event); 1503444c061aSmrg idx = GetBranchHead(stateTree, typeIndex, modIndex, False); 1504444c061aSmrg branchHead = &stateTree->branchHeadTbl[idx]; 1505444c061aSmrg 1506444c061aSmrg /* 1507444c061aSmrg * Need to check for pre-existing actions with same lhs ||| 1508444c061aSmrg */ 1509444c061aSmrg 1510444c061aSmrg /* 1511444c061aSmrg * Check for optimized case. Don't assume that the eventSeq has actions. 1512444c061aSmrg */ 1513444c061aSmrg if (!eventSeq->next && 1514a3bd7f05Smrg eventSeq->actions && 1515a3bd7f05Smrg !eventSeq->actions->next && !eventSeq->actions->num_params) { 1516a3bd7f05Smrg if (eventSeq->event.eventType == MappingNotify) 1517a3bd7f05Smrg stateTree->mappingNotifyInterest = True; 1518a3bd7f05Smrg branchHead->hasActions = True; 1519a3bd7f05Smrg XtSetBits(branchHead->more, eventSeq->actions->idx, 13); 1520a3bd7f05Smrg FreeActions(eventSeq->actions); 1521a3bd7f05Smrg eventSeq->actions = NULL; 1522a3bd7f05Smrg return; 1523a3bd7f05Smrg } 1524444c061aSmrg 1525444c061aSmrg branchHead->isSimple = False; 1526444c061aSmrg if (!eventSeq->next) 1527a3bd7f05Smrg branchHead->hasActions = True; 1528a3bd7f05Smrg XtSetBits(branchHead->more, 1529a3bd7f05Smrg GetComplexBranchIndex(stateTree, typeIndex, modIndex), 13); 1530444c061aSmrg state = &stateTree->complexBranchHeadTbl[TMBranchMore(branchHead)]; 1531444c061aSmrg 1532444c061aSmrg for (;;) { 1533a3bd7f05Smrg *state = NewState(stateTree, typeIndex, modIndex); 1534444c061aSmrg 1535a3bd7f05Smrg if (eventSeq->event.eventType == MappingNotify) 1536a3bd7f05Smrg stateTree->mappingNotifyInterest = True; 1537444c061aSmrg 1538a3bd7f05Smrg /* *state now points at state record matching event */ 1539a3bd7f05Smrg eventSeq->state = *state; 1540444c061aSmrg 1541a3bd7f05Smrg if (eventSeq->actions != NULL) { 1542a3bd7f05Smrg if ((*state)->actions != NULL) 1543a3bd7f05Smrg AmbigActions(initialEvent, state, stateTree); 1544a3bd7f05Smrg (*state)->actions = eventSeq->actions; 1545444c061aSmrg#ifdef TRACE_TM 1546a3bd7f05Smrg LOCK_PROCESS; 1547a3bd7f05Smrg _XtGlobalTM.numComplexActions++; 1548a3bd7f05Smrg UNLOCK_PROCESS; 1549a3bd7f05Smrg#endif /* TRACE_TM */ 1550a3bd7f05Smrg } 1551a3bd7f05Smrg 1552a3bd7f05Smrg if (((eventSeq = eventSeq->next) == NULL) || (eventSeq->state)) 1553a3bd7f05Smrg break; 1554a3bd7f05Smrg 1555a3bd7f05Smrg state = &(*state)->nextLevel; 1556a3bd7f05Smrg typeIndex = _XtGetTypeIndex(&eventSeq->event); 1557a3bd7f05Smrg modIndex = _XtGetModifierIndex(&eventSeq->event); 1558a3bd7f05Smrg LOCK_PROCESS; 1559a3bd7f05Smrg if (!TMNewMatchSemantics()) { 1560a3bd7f05Smrg /* 1561a3bd7f05Smrg * force a potential empty entry into the branch head 1562a3bd7f05Smrg * table in order to emulate old matching behavior 1563a3bd7f05Smrg */ 1564a3bd7f05Smrg (void) GetBranchHead(stateTree, typeIndex, modIndex, True); 1565a3bd7f05Smrg } 1566a3bd7f05Smrg UNLOCK_PROCESS; 1567444c061aSmrg } 1568444c061aSmrg 1569444c061aSmrg if (eventSeq && eventSeq->state) { 1570a3bd7f05Smrg /* we've been here before... must be a cycle in the event seq. */ 1571a3bd7f05Smrg branchHead->hasCycles = True; 1572a3bd7f05Smrg (*state)->nextLevel = eventSeq->state; 1573a3bd7f05Smrg eventSeq->state->isCycleStart = True; 1574a3bd7f05Smrg (*state)->isCycleEnd = TRUE; 1575444c061aSmrg } 1576444c061aSmrg} 1577444c061aSmrg 1578444c061aSmrg/* 1579444c061aSmrg * Internal Converter for merging. Old and New must both be valid xlations 1580444c061aSmrg */ 1581a3bd7f05SmrgBoolean 1582a3bd7f05Smrg_XtCvtMergeTranslations(Display *dpy _X_UNUSED, 1583a3bd7f05Smrg XrmValuePtr args _X_UNUSED, 1584a3bd7f05Smrg Cardinal *num_args, 1585a3bd7f05Smrg XrmValuePtr from, 1586a3bd7f05Smrg XrmValuePtr to, 1587a3bd7f05Smrg XtPointer *closure_ret _X_UNUSED) 1588444c061aSmrg{ 1589a3bd7f05Smrg XtTranslations first, second, xlations; 1590a3bd7f05Smrg TMStateTree *stateTrees, stackStateTrees[16]; 1591a3bd7f05Smrg TMShortCard numStateTrees, i; 1592444c061aSmrg 1593444c061aSmrg if (*num_args != 0) 1594a3bd7f05Smrg XtWarningMsg("invalidParameters", "mergeTranslations", 1595a3bd7f05Smrg XtCXtToolkitError, 1596a3bd7f05Smrg "MergeTM to TranslationTable needs no extra arguments", 1597a3bd7f05Smrg NULL, NULL); 1598444c061aSmrg 1599444c061aSmrg if (to->addr != NULL && to->size < sizeof(XtTranslations)) { 1600a3bd7f05Smrg to->size = sizeof(XtTranslations); 1601a3bd7f05Smrg return False; 1602444c061aSmrg } 1603444c061aSmrg 1604a3bd7f05Smrg first = ((TMConvertRec *) from->addr)->old; 1605a3bd7f05Smrg second = ((TMConvertRec *) from->addr)->new; 1606444c061aSmrg 1607a3bd7f05Smrg numStateTrees = 1608a3bd7f05Smrg (TMShortCard) (first->numStateTrees + second->numStateTrees); 1609444c061aSmrg 1610444c061aSmrg stateTrees = (TMStateTree *) 1611a3bd7f05Smrg XtStackAlloc(numStateTrees * sizeof(TMStateTree), stackStateTrees); 1612444c061aSmrg 1613444c061aSmrg for (i = 0; i < first->numStateTrees; i++) 1614a3bd7f05Smrg stateTrees[i] = first->stateTreeTbl[i]; 1615444c061aSmrg for (i = 0; i < second->numStateTrees; i++) 1616a3bd7f05Smrg stateTrees[i + first->numStateTrees] = second->stateTreeTbl[i]; 1617444c061aSmrg 1618444c061aSmrg xlations = _XtCreateXlations(stateTrees, numStateTrees, first, second); 1619444c061aSmrg 1620444c061aSmrg if (to->addr != NULL) { 1621a3bd7f05Smrg *(XtTranslations *) to->addr = xlations; 1622444c061aSmrg } 1623444c061aSmrg else { 1624a3bd7f05Smrg static XtTranslations staticStateTable; 1625a3bd7f05Smrg 1626a3bd7f05Smrg staticStateTable = xlations; 1627a3bd7f05Smrg to->addr = (XPointer) &staticStateTable; 1628a3bd7f05Smrg to->size = sizeof(XtTranslations); 1629444c061aSmrg } 1630444c061aSmrg 1631a3bd7f05Smrg XtStackFree((XtPointer) stateTrees, (XtPointer) stackStateTrees); 1632444c061aSmrg return True; 1633444c061aSmrg} 1634444c061aSmrg 1635a3bd7f05Smrgstatic XtTranslations 1636a3bd7f05SmrgMergeThem(Widget dest, XtTranslations first, XtTranslations second) 1637444c061aSmrg{ 1638a3bd7f05Smrg XtCacheRef cache_ref; 1639a3bd7f05Smrg static XrmQuark from_type = NULLQUARK, to_type; 1640a3bd7f05Smrg XrmValue from, to; 1641a3bd7f05Smrg TMConvertRec convert_rec; 1642a3bd7f05Smrg XtTranslations newTable; 1643444c061aSmrg 1644444c061aSmrg LOCK_PROCESS; 1645444c061aSmrg if (from_type == NULLQUARK) { 1646a3bd7f05Smrg from_type = XrmPermStringToQuark(_XtRStateTablePair); 1647a3bd7f05Smrg to_type = XrmPermStringToQuark(XtRTranslationTable); 1648444c061aSmrg } 1649444c061aSmrg UNLOCK_PROCESS; 1650a3bd7f05Smrg from.addr = (XPointer) &convert_rec; 1651444c061aSmrg from.size = sizeof(TMConvertRec); 1652a3bd7f05Smrg to.addr = (XPointer) &newTable; 1653444c061aSmrg to.size = sizeof(XtTranslations); 1654444c061aSmrg convert_rec.old = first; 1655444c061aSmrg convert_rec.new = second; 1656444c061aSmrg 1657444c061aSmrg LOCK_PROCESS; 1658a3bd7f05Smrg if (!_XtConvert(dest, from_type, &from, to_type, &to, &cache_ref)) { 1659a3bd7f05Smrg UNLOCK_PROCESS; 1660a3bd7f05Smrg return NULL; 1661444c061aSmrg } 1662444c061aSmrg UNLOCK_PROCESS; 1663444c061aSmrg 1664444c061aSmrg#ifndef REFCNT_TRANSLATIONS 1665444c061aSmrg 1666444c061aSmrg if (cache_ref) 1667a3bd7f05Smrg XtAddCallback(dest, XtNdestroyCallback, 1668a3bd7f05Smrg XtCallbackReleaseCacheRef, (XtPointer) cache_ref); 1669444c061aSmrg 1670444c061aSmrg#endif 1671444c061aSmrg 1672444c061aSmrg return newTable; 1673444c061aSmrg} 1674444c061aSmrg 1675444c061aSmrg/* 1676444c061aSmrg * Unmerge will recursively traverse the xlation compose tree and 1677444c061aSmrg * generate a new xlation that is the result of all instances of 1678444c061aSmrg * xlations being removed. It currently doesn't differentiate between 1679444c061aSmrg * the potential that an xlation will be both an accelerator and 1680444c061aSmrg * normal. This is not supported by the spec anyway. 1681444c061aSmrg */ 1682a3bd7f05Smrgstatic XtTranslations 1683a3bd7f05SmrgUnmergeTranslations(Widget widget, 1684a3bd7f05Smrg XtTranslations xlations, 1685a3bd7f05Smrg XtTranslations unmergeXlations, 1686a3bd7f05Smrg TMShortCard currIndex, 1687a3bd7f05Smrg TMComplexBindProcs oldBindings, 1688a3bd7f05Smrg TMShortCard numOldBindings, 1689a3bd7f05Smrg TMComplexBindProcs newBindings, 1690a3bd7f05Smrg TMShortCard *numNewBindingsRtn) 1691444c061aSmrg{ 1692444c061aSmrg XtTranslations first, second, result; 1693444c061aSmrg 1694444c061aSmrg if (!xlations || (xlations == unmergeXlations)) 1695a3bd7f05Smrg return NULL; 1696444c061aSmrg 1697444c061aSmrg if (xlations->composers[0]) { 1698a3bd7f05Smrg first = UnmergeTranslations(widget, xlations->composers[0], 1699a3bd7f05Smrg unmergeXlations, currIndex, 1700a3bd7f05Smrg oldBindings, numOldBindings, 1701a3bd7f05Smrg newBindings, numNewBindingsRtn); 1702444c061aSmrg } 1703444c061aSmrg else 1704a3bd7f05Smrg first = NULL; 1705444c061aSmrg 17060568f49bSmrg if (xlations->composers[0] 1707a3bd7f05Smrg && xlations->composers[1]) { 1708a3bd7f05Smrg second = UnmergeTranslations(widget, xlations->composers[1], 1709a3bd7f05Smrg unmergeXlations, (TMShortCard) 1710a3bd7f05Smrg (currIndex + 1711a3bd7f05Smrg xlations->composers[0]->numStateTrees), 1712a3bd7f05Smrg oldBindings, 1713a3bd7f05Smrg numOldBindings, newBindings, 1714a3bd7f05Smrg numNewBindingsRtn); 1715444c061aSmrg } 1716444c061aSmrg else 1717a3bd7f05Smrg second = NULL; 1718444c061aSmrg 1719444c061aSmrg if (first || second) { 1720a3bd7f05Smrg if (first && second) { 1721a3bd7f05Smrg if ((first != xlations->composers[0]) || 1722a3bd7f05Smrg (second != xlations->composers[1])) 1723a3bd7f05Smrg result = MergeThem(widget, first, second); 1724a3bd7f05Smrg else 1725a3bd7f05Smrg result = xlations; 1726a3bd7f05Smrg } 1727a3bd7f05Smrg else { 1728a3bd7f05Smrg if (first) 1729a3bd7f05Smrg result = first; 1730a3bd7f05Smrg else 1731a3bd7f05Smrg result = second; 1732a3bd7f05Smrg } 1733a3bd7f05Smrg } 1734a3bd7f05Smrg else { /* only update for leaf nodes */ 1735a3bd7f05Smrg if (numOldBindings) { 1736a3bd7f05Smrg Cardinal i; 1737a3bd7f05Smrg 1738a3bd7f05Smrg for (i = 0; i < xlations->numStateTrees; i++) { 1739a3bd7f05Smrg if (xlations->stateTreeTbl[i]->simple.isAccelerator) 1740a3bd7f05Smrg newBindings[*numNewBindingsRtn] = 1741a3bd7f05Smrg oldBindings[currIndex + i]; 1742a3bd7f05Smrg (*numNewBindingsRtn)++; 1743a3bd7f05Smrg } 1744a3bd7f05Smrg } 1745a3bd7f05Smrg result = xlations; 1746444c061aSmrg } 1747444c061aSmrg return result; 1748444c061aSmrg} 1749444c061aSmrg 1750444c061aSmrgtypedef struct { 1751444c061aSmrg XtTranslations xlations; 1752444c061aSmrg TMComplexBindProcs bindings; 1753a3bd7f05Smrg} MergeBindRec, *MergeBind; 1754a3bd7f05Smrg 1755a3bd7f05Smrgstatic XtTranslations 1756a3bd7f05SmrgMergeTranslations(Widget widget, 1757a3bd7f05Smrg XtTranslations oldXlations, 1758a3bd7f05Smrg XtTranslations newXlations, 1759a3bd7f05Smrg _XtTranslateOp operation, 1760a3bd7f05Smrg Widget source, 1761a3bd7f05Smrg TMComplexBindProcs oldBindings, 1762a3bd7f05Smrg TMComplexBindProcs newBindings, 1763a3bd7f05Smrg TMShortCard *numNewRtn) 1764444c061aSmrg{ 1765a3bd7f05Smrg XtTranslations newTable = NULL, xlations; 1766a3bd7f05Smrg TMComplexBindProcs bindings; 1767a3bd7f05Smrg TMShortCard i, j; 1768a3bd7f05Smrg TMStateTree *treePtr; 1769a3bd7f05Smrg TMShortCard numNew; 1770a3bd7f05Smrg MergeBindRec bindPair[2]; 1771444c061aSmrg 1772444c061aSmrg /* If the new translation has an accelerator context then pull it 1773444c061aSmrg * off and pass it and the real xlations in to the caching merge 1774444c061aSmrg * routine. 1775444c061aSmrg */ 1776444c061aSmrg if (newXlations->hasBindings) { 1777a3bd7f05Smrg xlations = ((ATranslations) newXlations)->xlations; 1778a3bd7f05Smrg bindings = (TMComplexBindProcs) 1779a3bd7f05Smrg &((ATranslations) newXlations)->bindTbl[0]; 1780444c061aSmrg } 1781444c061aSmrg else { 1782a3bd7f05Smrg xlations = newXlations; 1783a3bd7f05Smrg bindings = NULL; 1784a3bd7f05Smrg } 1785a3bd7f05Smrg switch (operation) { 1786fdf6a26fSmrg default: 1787a3bd7f05Smrg case XtTableReplace: 1788a3bd7f05Smrg newTable = bindPair[0].xlations = xlations; 1789a3bd7f05Smrg bindPair[0].bindings = bindings; 1790a3bd7f05Smrg bindPair[1].xlations = NULL; 1791a3bd7f05Smrg bindPair[1].bindings = NULL; 1792a3bd7f05Smrg break; 1793a3bd7f05Smrg case XtTableAugment: 1794a3bd7f05Smrg bindPair[0].xlations = oldXlations; 1795a3bd7f05Smrg bindPair[0].bindings = oldBindings; 1796a3bd7f05Smrg bindPair[1].xlations = xlations; 1797a3bd7f05Smrg bindPair[1].bindings = bindings; 1798a3bd7f05Smrg newTable = NULL; 1799a3bd7f05Smrg break; 1800a3bd7f05Smrg case XtTableOverride: 1801a3bd7f05Smrg bindPair[0].xlations = xlations; 1802a3bd7f05Smrg bindPair[0].bindings = bindings; 1803a3bd7f05Smrg bindPair[1].xlations = oldXlations; 1804a3bd7f05Smrg bindPair[1].bindings = oldBindings; 1805a3bd7f05Smrg newTable = NULL; 1806a3bd7f05Smrg break; 1807444c061aSmrg } 1808444c061aSmrg if (!newTable) 1809a3bd7f05Smrg newTable = 1810a3bd7f05Smrg MergeThem(widget, bindPair[0].xlations, bindPair[1].xlations); 1811444c061aSmrg 1812444c061aSmrg for (i = 0, numNew = 0; i < 2; i++) { 1813a3bd7f05Smrg if (bindPair[i].xlations) 1814a3bd7f05Smrg for (j = 0; j < bindPair[i].xlations->numStateTrees; j++, numNew++) { 1815a3bd7f05Smrg if (bindPair[i].xlations->stateTreeTbl[j]->simple.isAccelerator) { 1816a3bd7f05Smrg if (bindPair[i].bindings) 1817a3bd7f05Smrg newBindings[numNew] = bindPair[i].bindings[j]; 1818a3bd7f05Smrg else { 1819a3bd7f05Smrg newBindings[numNew].widget = source; 1820a3bd7f05Smrg newBindings[numNew].aXlations = bindPair[i].xlations; 1821a3bd7f05Smrg } 1822a3bd7f05Smrg } 1823a3bd7f05Smrg } 1824444c061aSmrg } 1825444c061aSmrg *numNewRtn = numNew; 1826444c061aSmrg treePtr = &newTable->stateTreeTbl[0]; 1827444c061aSmrg for (i = 0; i < newTable->numStateTrees; i++, treePtr++) 1828a3bd7f05Smrg (*treePtr)->simple.refCount++; 1829444c061aSmrg return newTable; 1830444c061aSmrg} 1831444c061aSmrg 1832a3bd7f05Smrgstatic TMBindData 1833a3bd7f05SmrgMakeBindData(TMComplexBindProcs bindings, 1834a3bd7f05Smrg TMShortCard numBindings, 1835a3bd7f05Smrg TMBindData oldBindData) 1836444c061aSmrg{ 1837a3bd7f05Smrg TMLongCard bytes; 1838a3bd7f05Smrg TMShortCard i; 1839a3bd7f05Smrg Boolean isComplex; 1840a3bd7f05Smrg TMBindData bindData; 1841444c061aSmrg 1842444c061aSmrg if (numBindings == 0) 1843a3bd7f05Smrg return NULL; 1844444c061aSmrg for (i = 0; i < numBindings; i++) 1845a3bd7f05Smrg if (bindings[i].widget) 1846a3bd7f05Smrg break; 1847444c061aSmrg isComplex = (i < numBindings); 1848444c061aSmrg if (isComplex) 1849a3bd7f05Smrg bytes = (sizeof(TMComplexBindDataRec) + 1850a3bd7f05Smrg ((TMLongCard) (numBindings - 1) * 1851a3bd7f05Smrg sizeof(TMComplexBindProcsRec))); 1852444c061aSmrg else 1853a3bd7f05Smrg bytes = (sizeof(TMSimpleBindDataRec) + 1854a3bd7f05Smrg ((TMLongCard) (numBindings - 1) * 1855a3bd7f05Smrg sizeof(TMSimpleBindProcsRec))); 1856444c061aSmrg 1857a3bd7f05Smrg bindData = 1858a3bd7f05Smrg (TMBindData) __XtCalloc((Cardinal) sizeof(char), (Cardinal) bytes); 18590568f49bSmrg XtSetBit(bindData->simple.isComplex, isComplex); 1860444c061aSmrg if (isComplex) { 1861a3bd7f05Smrg TMComplexBindData cBindData = (TMComplexBindData) bindData; 1862a3bd7f05Smrg 1863a3bd7f05Smrg /* 1864a3bd7f05Smrg * If there were any accelerator contexts in the old bindData 1865a3bd7f05Smrg * then propagate them to the new one. 1866a3bd7f05Smrg */ 1867a3bd7f05Smrg if (oldBindData && oldBindData->simple.isComplex) 1868a3bd7f05Smrg cBindData->accel_context = 1869a3bd7f05Smrg ((TMComplexBindData) oldBindData)->accel_context; 1870fdf6a26fSmrg memcpy(&cBindData->bindTbl[0], bindings, 1871fdf6a26fSmrg numBindings * sizeof(TMComplexBindProcsRec)); 1872444c061aSmrg } 1873444c061aSmrg return bindData; 1874444c061aSmrg} 1875444c061aSmrg 1876444c061aSmrg/* 1877444c061aSmrg * This routine is the central clearinghouse for merging translations 1878444c061aSmrg * into a widget. It takes care of preping the action bindings for 1879444c061aSmrg * realize time and calling the converter or doing a straight merge if 1880444c061aSmrg * the destination is empty. 1881444c061aSmrg */ 1882a3bd7f05Smrgstatic Boolean 1883a3bd7f05SmrgComposeTranslations(Widget dest, 1884a3bd7f05Smrg _XtTranslateOp operation, 1885a3bd7f05Smrg Widget source, 1886a3bd7f05Smrg XtTranslations newXlations) 1887444c061aSmrg{ 1888a3bd7f05Smrg XtTranslations newTable, oldXlations; 1889a3bd7f05Smrg XtTranslations accNewXlations; 1890a3bd7f05Smrg EventMask oldMask = 0; 1891a3bd7f05Smrg TMBindData bindData; 1892a3bd7f05Smrg TMComplexBindProcs oldBindings = NULL; 1893a3bd7f05Smrg TMShortCard numOldBindings = 0, numNewBindings = 0, numBytes; 1894444c061aSmrg TMComplexBindProcsRec stackBindings[16], *newBindings; 1895444c061aSmrg 1896444c061aSmrg /* 1897444c061aSmrg * how should we be handling the refcount decrement for the 1898444c061aSmrg * replaced translation table ??? 1899444c061aSmrg */ 1900a3bd7f05Smrg if (!newXlations) { 1901a3bd7f05Smrg XtAppWarningMsg(XtWidgetToApplicationContext(dest), 1902a3bd7f05Smrg XtNtranslationError, "nullTable", XtCXtToolkitError, 1903a3bd7f05Smrg "table to (un)merge must not be null", NULL, NULL); 1904a3bd7f05Smrg return False; 1905a3bd7f05Smrg } 1906444c061aSmrg 1907444c061aSmrg accNewXlations = newXlations; 1908444c061aSmrg newXlations = ((newXlations->hasBindings) 1909a3bd7f05Smrg ? ((ATranslations) newXlations)->xlations : newXlations); 1910444c061aSmrg 1911444c061aSmrg if (!(oldXlations = dest->core.tm.translations)) 1912a3bd7f05Smrg operation = XtTableReplace; 1913444c061aSmrg 1914444c061aSmrg /* 1915444c061aSmrg * try to avoid generation of duplicate state trees. If the source 1916444c061aSmrg * isn't simple (1 state Tree) then it's too much hassle 1917444c061aSmrg */ 1918444c061aSmrg if (((operation == XtTableAugment) || 1919a3bd7f05Smrg (operation == XtTableOverride)) && (newXlations->numStateTrees == 1)) { 1920a3bd7f05Smrg Cardinal i; 1921a3bd7f05Smrg 1922a3bd7f05Smrg for (i = 0; i < oldXlations->numStateTrees; i++) 1923a3bd7f05Smrg if (oldXlations->stateTreeTbl[i] == newXlations->stateTreeTbl[0]) 1924a3bd7f05Smrg break; 1925a3bd7f05Smrg if (i < oldXlations->numStateTrees) { 1926a3bd7f05Smrg if (operation == XtTableAugment) { 1927a3bd7f05Smrg /* 1928a3bd7f05Smrg * we don't need to do anything since it's already 1929a3bd7f05Smrg * there 1930a3bd7f05Smrg */ 1931a3bd7f05Smrg return True; 1932a3bd7f05Smrg } 1933a3bd7f05Smrg else { /* operation == XtTableOverride */ 1934a3bd7f05Smrg /* 1935a3bd7f05Smrg * We'll get rid of the duplicate trees throughout the 1936a3bd7f05Smrg * and leave it with a pruned translation table. This 1937a3bd7f05Smrg * will only work if the same table has been merged 1938a3bd7f05Smrg * into this table (or one of it's composers 1939a3bd7f05Smrg */ 1940a3bd7f05Smrg _XtUnmergeTranslations(dest, newXlations); 1941a3bd7f05Smrg /* 1942a3bd7f05Smrg * reset oldXlations so we're back in sync 1943a3bd7f05Smrg */ 1944a3bd7f05Smrg if (!(oldXlations = dest->core.tm.translations)) 1945a3bd7f05Smrg operation = XtTableReplace; 1946a3bd7f05Smrg } 1947a3bd7f05Smrg } 1948444c061aSmrg } 1949444c061aSmrg 1950444c061aSmrg bindData = (TMBindData) dest->core.tm.proc_table; 1951444c061aSmrg if (bindData) { 1952a3bd7f05Smrg numOldBindings = (oldXlations ? oldXlations->numStateTrees : 0); 1953a3bd7f05Smrg if (bindData->simple.isComplex) 1954a3bd7f05Smrg oldBindings = &((TMComplexBindData) bindData)->bindTbl[0]; 1955a3bd7f05Smrg else 1956a3bd7f05Smrg oldBindings = (TMComplexBindProcs) 1957a3bd7f05Smrg (&((TMSimpleBindData) bindData)->bindTbl[0]); 1958444c061aSmrg } 1959444c061aSmrg 1960a3bd7f05Smrg numBytes = 1961a3bd7f05Smrg (TMShortCard) ((size_t) ((oldXlations ? oldXlations->numStateTrees : 0) 1962a3bd7f05Smrg + 1963a3bd7f05Smrg newXlations->numStateTrees) * 1964a3bd7f05Smrg sizeof(TMComplexBindProcsRec)); 1965a3bd7f05Smrg newBindings = (TMComplexBindProcs) XtStackAlloc(numBytes, stackBindings); 1966a3bd7f05Smrg XtBZero((char *) newBindings, numBytes); 1967444c061aSmrg 1968444c061aSmrg if (operation == XtTableUnmerge) { 1969a3bd7f05Smrg newTable = UnmergeTranslations(dest, 1970a3bd7f05Smrg oldXlations, 1971a3bd7f05Smrg newXlations, 1972a3bd7f05Smrg 0, 1973a3bd7f05Smrg oldBindings, numOldBindings, 1974a3bd7f05Smrg newBindings, &numNewBindings); 1975444c061aSmrg#ifdef DEBUG 1976a3bd7f05Smrg /* check for no match for unmerge */ 1977a3bd7f05Smrg if (newTable == oldXlations) { 1978a3bd7f05Smrg XtWarning("attempt to unmerge invalid table"); 1979a3bd7f05Smrg XtStackFree((char *) newBindings, (char *) stackBindings); 1980a3bd7f05Smrg return (newTable != NULL); 1981a3bd7f05Smrg } 1982a3bd7f05Smrg#endif /* DEBUG */ 1983444c061aSmrg } 1984444c061aSmrg else { 1985a3bd7f05Smrg newTable = MergeTranslations(dest, 1986a3bd7f05Smrg oldXlations, 1987a3bd7f05Smrg accNewXlations, 1988a3bd7f05Smrg operation, 1989a3bd7f05Smrg source, 1990a3bd7f05Smrg oldBindings, newBindings, &numNewBindings); 1991444c061aSmrg } 1992444c061aSmrg if (XtIsRealized(dest)) { 1993a3bd7f05Smrg oldMask = 0; 1994a3bd7f05Smrg if (oldXlations) 1995a3bd7f05Smrg oldMask = oldXlations->eventMask; 1996a3bd7f05Smrg _XtUninstallTranslations(dest); 1997444c061aSmrg } 1998444c061aSmrg 1999444c061aSmrg dest->core.tm.proc_table = 2000a3bd7f05Smrg (XtActionProc *) MakeBindData(newBindings, numNewBindings, bindData); 2001444c061aSmrg 2002a3bd7f05Smrg XtFree((char *) bindData); 2003444c061aSmrg 2004444c061aSmrg dest->core.tm.translations = newTable; 2005444c061aSmrg 2006444c061aSmrg if (XtIsRealized(dest)) { 2007a3bd7f05Smrg EventMask mask = 0; 2008a3bd7f05Smrg 2009a3bd7f05Smrg _XtInstallTranslations(dest); 2010a3bd7f05Smrg if (newTable) 2011a3bd7f05Smrg mask = newTable->eventMask; 2012a3bd7f05Smrg if (mask != oldMask) 2013a3bd7f05Smrg XSelectInput(XtDisplay(dest), XtWindow(dest), 2014a3bd7f05Smrg (long) XtBuildEventMask(dest)); 2015a3bd7f05Smrg } 2016a3bd7f05Smrg XtStackFree((XtPointer) newBindings, (XtPointer) stackBindings); 2017a3bd7f05Smrg return (newTable != NULL); 2018444c061aSmrg} 2019444c061aSmrg 2020444c061aSmrg/* 2021444c061aSmrg * If a GetValues is done on a translation resource that contains 2022444c061aSmrg * accelerators we need to return the accelerator context in addition 2023444c061aSmrg * to the pure translations. Since this means returning memory that 2024fdf6a26fSmrg * the client controls but we still own, we will track the "headers" 2025444c061aSmrg * that we return (via a linked list pointed to from the bindData) and 2026444c061aSmrg * free it at destroy time. 2027444c061aSmrg */ 2028a3bd7f05SmrgXtTranslations 2029a3bd7f05Smrg_XtGetTranslationValue(Widget w) 2030444c061aSmrg{ 2031a3bd7f05Smrg XtTM tmRecPtr = (XtTM) &w->core.tm; 2032a3bd7f05Smrg ATranslations *aXlationsPtr; 2033a3bd7f05Smrg TMComplexBindData cBindData = (TMComplexBindData) tmRecPtr->proc_table; 2034a3bd7f05Smrg XtTranslations xlations = tmRecPtr->translations; 2035444c061aSmrg 2036444c061aSmrg if (!xlations || !cBindData || !cBindData->isComplex) 2037a3bd7f05Smrg return xlations; 2038444c061aSmrg 2039444c061aSmrg /* Walk the list looking to see if we already have generated a 2040444c061aSmrg * header for the currently installed translations. If we have, 2041444c061aSmrg * just return that header. Otherwise create a new header. 2042444c061aSmrg */ 2043444c061aSmrg for (aXlationsPtr = (ATranslations *) &cBindData->accel_context; 2044a3bd7f05Smrg *aXlationsPtr && (*aXlationsPtr)->xlations != xlations; 2045a3bd7f05Smrg aXlationsPtr = &(*aXlationsPtr)->next); 2046444c061aSmrg if (*aXlationsPtr) 2047a3bd7f05Smrg return (XtTranslations) *aXlationsPtr; 2048444c061aSmrg else { 2049a3bd7f05Smrg /* create a new aXlations context */ 2050a3bd7f05Smrg ATranslations aXlations; 2051a3bd7f05Smrg Cardinal numBindings = xlations->numStateTrees; 2052a3bd7f05Smrg 2053a3bd7f05Smrg (*aXlationsPtr) = aXlations = (ATranslations) 2054a3bd7f05Smrg __XtMalloc((Cardinal) (sizeof(ATranslationData) + 2055a3bd7f05Smrg (numBindings - 2056a3bd7f05Smrg 1) * sizeof(TMComplexBindProcsRec))); 2057a3bd7f05Smrg 2058a3bd7f05Smrg aXlations->hasBindings = True; 2059a3bd7f05Smrg aXlations->xlations = xlations; 2060a3bd7f05Smrg aXlations->next = NULL; 2061fdf6a26fSmrg memcpy(&aXlations->bindTbl[0], 2062fdf6a26fSmrg &cBindData->bindTbl[0], 2063fdf6a26fSmrg numBindings * sizeof(TMComplexBindProcsRec)); 2064a3bd7f05Smrg return (XtTranslations) aXlations; 2065444c061aSmrg } 2066444c061aSmrg} 2067444c061aSmrg 2068a3bd7f05Smrgstatic void 2069a3bd7f05SmrgRemoveStateTree(TMStateTree tree _X_UNUSED) 2070444c061aSmrg{ 2071444c061aSmrg#ifdef REFCNT_TRANSLATIONS 2072a3bd7f05Smrg TMComplexStateTree stateTree = (TMComplexStateTree) tree; 2073444c061aSmrg 2074444c061aSmrg if (--stateTree->refCount == 0) { 2075a3bd7f05Smrg /* 2076a3bd7f05Smrg * should we free/refcount the match recs ? 2077a3bd7f05Smrg */ 2078a3bd7f05Smrg if (!stateTree->isSimple) { 2079a3bd7f05Smrg StatePtr currState, nextState; 2080a3bd7f05Smrg TMShortCard i; 2081a3bd7f05Smrg 2082a3bd7f05Smrg for (i = 0; i < stateTree->numComplexBranchHeads; i++) { 2083a3bd7f05Smrg currState = nextState = stateTree->complexBranchHeadTbl[i]; 2084a3bd7f05Smrg for (; nextState;) { 2085a3bd7f05Smrg FreeActions(currState->actions); 2086a3bd7f05Smrg currState->actions = NULL; 2087a3bd7f05Smrg if (!currState->isCycleEnd) 2088a3bd7f05Smrg nextState = currState->nextLevel; 2089a3bd7f05Smrg else 2090a3bd7f05Smrg nextState = NULL; 2091a3bd7f05Smrg XtFree((char *) currState); 2092a3bd7f05Smrg } 2093a3bd7f05Smrg } 2094a3bd7f05Smrg XtFree((char *) stateTree->complexBranchHeadTbl); 2095a3bd7f05Smrg } 2096a3bd7f05Smrg XtFree((char *) stateTree->branchHeadTbl); 2097a3bd7f05Smrg XtFree((char *) stateTree); 2098a3bd7f05Smrg } 2099a3bd7f05Smrg#endif /* REFCNT_TRANSLATIONS */ 2100444c061aSmrg} 2101444c061aSmrg 2102a3bd7f05Smrgvoid 2103a3bd7f05Smrg_XtRemoveStateTreeByIndex(XtTranslations xlations, TMShortCard i) 2104444c061aSmrg{ 2105a3bd7f05Smrg TMStateTree *stateTrees = xlations->stateTreeTbl; 2106444c061aSmrg 2107444c061aSmrg RemoveStateTree(stateTrees[i]); 2108444c061aSmrg xlations->numStateTrees--; 2109444c061aSmrg 2110a3bd7f05Smrg for (; i < xlations->numStateTrees; i++) { 2111a3bd7f05Smrg stateTrees[i] = stateTrees[i + 1]; 2112a3bd7f05Smrg } 2113444c061aSmrg} 2114444c061aSmrg 2115a3bd7f05Smrgvoid 2116a3bd7f05Smrg_XtFreeTranslations(XtAppContext app, 2117a3bd7f05Smrg XrmValuePtr toVal, 2118a3bd7f05Smrg XtPointer closure _X_UNUSED, 2119a3bd7f05Smrg XrmValuePtr args _X_UNUSED, 2120a3bd7f05Smrg Cardinal *num_args) 2121444c061aSmrg{ 2122a3bd7f05Smrg XtTranslations xlations; 2123a3bd7f05Smrg int i; 2124444c061aSmrg 2125444c061aSmrg if (*num_args != 0) 2126a3bd7f05Smrg XtAppWarningMsg(app, 2127a3bd7f05Smrg "invalidParameters", "freeTranslations", 2128a3bd7f05Smrg XtCXtToolkitError, 2129a3bd7f05Smrg "Freeing XtTranslations requires no extra arguments", 2130a3bd7f05Smrg NULL, NULL); 2131a3bd7f05Smrg 2132a3bd7f05Smrg xlations = *(XtTranslations *) toVal->addr; 2133a3bd7f05Smrg for (i = 0; i < (int) xlations->numStateTrees; i++) 2134a3bd7f05Smrg RemoveStateTree(xlations->stateTreeTbl[i]); 2135a3bd7f05Smrg XtFree((char *) xlations); 2136444c061aSmrg} 2137444c061aSmrg 2138444c061aSmrg/* The spec is not clear on when actions specified in accelerators are bound; 2139444c061aSmrg * Bind them at Realize the same as translations 2140444c061aSmrg */ 2141a3bd7f05Smrgvoid 2142a3bd7f05SmrgXtInstallAccelerators(Widget destination, Widget source) 2143444c061aSmrg{ 2144a3bd7f05Smrg XtTranslations aXlations; 2145a3bd7f05Smrg _XtTranslateOp op; 2146a3bd7f05Smrg 2147444c061aSmrg WIDGET_TO_APPCON(destination); 2148444c061aSmrg 2149444c061aSmrg /* 2150444c061aSmrg * test that it was parsed as an accelarator table. Even though 2151444c061aSmrg * there doesn't need to be a distinction it makes life easier if 2152444c061aSmrg * we honor the spec implication that aXlations is an accelerator 2153444c061aSmrg */ 2154444c061aSmrg LOCK_APP(app); 2155444c061aSmrg LOCK_PROCESS; 2156444c061aSmrg if ((!XtIsWidget(source)) || 2157a3bd7f05Smrg ((aXlations = source->core.accelerators) == NULL) || 2158a3bd7f05Smrg (aXlations->stateTreeTbl[0]->simple.isAccelerator == False)) { 2159a3bd7f05Smrg UNLOCK_PROCESS; 2160a3bd7f05Smrg UNLOCK_APP(app); 2161a3bd7f05Smrg return; 2162444c061aSmrg } 2163444c061aSmrg 2164444c061aSmrg aXlations = source->core.accelerators; 2165444c061aSmrg op = aXlations->operation; 2166444c061aSmrg 2167444c061aSmrg if (ComposeTranslations(destination, op, source, aXlations) && 2168a3bd7f05Smrg (XtClass(source)->core_class.display_accelerator != NULL)) { 2169a3bd7f05Smrg _XtString buf = _XtPrintXlations(destination, aXlations, source, False); 2170a3bd7f05Smrg 2171a3bd7f05Smrg (*(XtClass(source)->core_class.display_accelerator)) (source, buf); 2172a3bd7f05Smrg XtFree(buf); 2173444c061aSmrg } 2174444c061aSmrg UNLOCK_PROCESS; 2175444c061aSmrg UNLOCK_APP(app); 2176444c061aSmrg} 2177444c061aSmrg 2178a3bd7f05Smrgvoid 2179a3bd7f05SmrgXtInstallAllAccelerators(Widget destination, Widget source) 2180444c061aSmrg{ 2181444c061aSmrg Cardinal i; 2182a3bd7f05Smrg 2183444c061aSmrg WIDGET_TO_APPCON(destination); 2184444c061aSmrg 2185444c061aSmrg /* Recurse down normal children */ 2186444c061aSmrg LOCK_APP(app); 2187444c061aSmrg LOCK_PROCESS; 2188444c061aSmrg if (XtIsComposite(source)) { 21890568f49bSmrg CompositeWidget cw = (CompositeWidget) source; 2190a3bd7f05Smrg 2191444c061aSmrg for (i = 0; i < cw->composite.num_children; i++) { 2192a3bd7f05Smrg XtInstallAllAccelerators(destination, cw->composite.children[i]); 2193444c061aSmrg } 2194444c061aSmrg } 2195444c061aSmrg 2196444c061aSmrg /* Recurse down popup children */ 2197444c061aSmrg if (XtIsWidget(source)) { 2198444c061aSmrg for (i = 0; i < source->core.num_popups; i++) { 2199a3bd7f05Smrg XtInstallAllAccelerators(destination, source->core.popup_list[i]); 2200444c061aSmrg } 2201444c061aSmrg } 2202444c061aSmrg /* Finally, apply procedure to this widget */ 2203a3bd7f05Smrg XtInstallAccelerators(destination, source); 2204444c061aSmrg UNLOCK_PROCESS; 2205444c061aSmrg UNLOCK_APP(app); 2206444c061aSmrg} 2207444c061aSmrg 2208a3bd7f05Smrg#if 0 /* dead code */ 2209a3bd7f05Smrgstatic _XtTranslateOp 2210a3bd7f05Smrg_XtGetTMOperation(XtTranslations xlations) 2211444c061aSmrg{ 2212444c061aSmrg return ((xlations->hasBindings) 2213a3bd7f05Smrg ? ((ATranslations) xlations)->xlations->operation 2214a3bd7f05Smrg : xlations->operation); 2215444c061aSmrg} 2216444c061aSmrg#endif 2217444c061aSmrg 2218a3bd7f05Smrgvoid 2219a3bd7f05SmrgXtAugmentTranslations(Widget widget, XtTranslations new) 2220444c061aSmrg{ 2221444c061aSmrg Widget hookobj; 2222a3bd7f05Smrg 2223444c061aSmrg WIDGET_TO_APPCON(widget); 2224444c061aSmrg 2225444c061aSmrg LOCK_APP(app); 2226444c061aSmrg LOCK_PROCESS; 2227a3bd7f05Smrg (void) ComposeTranslations(widget, XtTableAugment, (Widget) NULL, new); 2228444c061aSmrg hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 2229444c061aSmrg if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 2230a3bd7f05Smrg XtChangeHookDataRec call_data; 2231444c061aSmrg 2232a3bd7f05Smrg call_data.type = XtHaugmentTranslations; 2233a3bd7f05Smrg call_data.widget = widget; 2234a3bd7f05Smrg XtCallCallbackList(hookobj, 2235a3bd7f05Smrg ((HookObject) hookobj)->hooks.changehook_callbacks, 2236a3bd7f05Smrg (XtPointer) &call_data); 2237444c061aSmrg } 2238444c061aSmrg UNLOCK_PROCESS; 2239444c061aSmrg UNLOCK_APP(app); 2240444c061aSmrg} 2241444c061aSmrg 2242a3bd7f05Smrgvoid 2243a3bd7f05SmrgXtOverrideTranslations(Widget widget, XtTranslations new) 2244444c061aSmrg{ 2245444c061aSmrg Widget hookobj; 2246a3bd7f05Smrg 2247444c061aSmrg WIDGET_TO_APPCON(widget); 2248444c061aSmrg 2249444c061aSmrg LOCK_APP(app); 2250444c061aSmrg LOCK_PROCESS; 2251a3bd7f05Smrg (void) ComposeTranslations(widget, XtTableOverride, (Widget) NULL, new); 2252444c061aSmrg hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 2253444c061aSmrg if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 2254a3bd7f05Smrg XtChangeHookDataRec call_data; 2255444c061aSmrg 2256a3bd7f05Smrg call_data.type = XtHoverrideTranslations; 2257a3bd7f05Smrg call_data.widget = widget; 2258a3bd7f05Smrg XtCallCallbackList(hookobj, 2259a3bd7f05Smrg ((HookObject) hookobj)->hooks.changehook_callbacks, 2260a3bd7f05Smrg (XtPointer) &call_data); 2261444c061aSmrg } 2262444c061aSmrg UNLOCK_PROCESS; 2263444c061aSmrg UNLOCK_APP(app); 2264444c061aSmrg} 2265444c061aSmrg 2266a3bd7f05Smrgvoid 2267a3bd7f05Smrg_XtMergeTranslations(Widget widget, 2268a3bd7f05Smrg XtTranslations newXlations, 2269a3bd7f05Smrg _XtTranslateOp op) 2270444c061aSmrg{ 2271a3bd7f05Smrg if (!newXlations) { 2272a3bd7f05Smrg if (!widget->core.tm.translations) 2273a3bd7f05Smrg return; 2274a3bd7f05Smrg else { 2275a3bd7f05Smrg newXlations = widget->core.tm.translations; 2276a3bd7f05Smrg widget->core.tm.translations = NULL; 2277a3bd7f05Smrg } 2278a3bd7f05Smrg } 2279a3bd7f05Smrg (void) ComposeTranslations(widget, op, (Widget) NULL, newXlations); 2280444c061aSmrg} 2281444c061aSmrg 2282a3bd7f05Smrgvoid 2283a3bd7f05Smrg_XtUnmergeTranslations(Widget widget, XtTranslations xlations) 2284444c061aSmrg{ 2285a3bd7f05Smrg ComposeTranslations(widget, XtTableUnmerge, (Widget) NULL, xlations); 2286444c061aSmrg} 2287