TMstate.c revision 444c061a
1444c061aSmrg/* $Xorg: TMstate.c,v 1.6 2001/02/09 02:03:58 xorgcvs Exp $ */ 2444c061aSmrg 3444c061aSmrg/*********************************************************** 4444c061aSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, 5444c061aSmrgCopyright 1993 by Sun Microsystems, Inc. Mountain View, CA. 6444c061aSmrg 7444c061aSmrg All Rights Reserved 8444c061aSmrg 9444c061aSmrgPermission to use, copy, modify, and distribute this software and its 10444c061aSmrgdocumentation for any purpose and without fee is hereby granted, 11444c061aSmrgprovided that the above copyright notice appear in all copies and that 12444c061aSmrgboth that copyright notice and this permission notice appear in 13444c061aSmrgsupporting documentation, and that the names of Digital or Sun not be 14444c061aSmrgused in advertising or publicity pertaining to distribution of the 15444c061aSmrgsoftware without specific, written prior permission. 16444c061aSmrg 17444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 18444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 19444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 20444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 21444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 22444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23444c061aSmrgSOFTWARE. 24444c061aSmrg 25444c061aSmrgSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26444c061aSmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 27444c061aSmrgNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 28444c061aSmrgABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 29444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 30444c061aSmrgPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 31444c061aSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 32444c061aSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 33444c061aSmrg 34444c061aSmrg******************************************************************/ 35444c061aSmrg/* $XFree86: xc/lib/Xt/TMstate.c,v 1.8 2001/12/14 19:56:31 dawes Exp $ */ 36444c061aSmrg 37444c061aSmrg/* 38444c061aSmrg 39444c061aSmrgCopyright 1987, 1988, 1994, 1998 The Open Group 40444c061aSmrg 41444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its 42444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that 43444c061aSmrgthe above copyright notice appear in all copies and that both that 44444c061aSmrgcopyright notice and this permission notice appear in supporting 45444c061aSmrgdocumentation. 46444c061aSmrg 47444c061aSmrgThe above copyright notice and this permission notice shall be included in 48444c061aSmrgall copies or substantial portions of the Software. 49444c061aSmrg 50444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 54444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 55444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 56444c061aSmrg 57444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be 58444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings 59444c061aSmrgin this Software without prior written authorization from The Open Group. 60444c061aSmrg 61444c061aSmrg*/ 62444c061aSmrg 63444c061aSmrg/* TMstate.c -- maintains the state table of actions for the translation 64444c061aSmrg * manager. 65444c061aSmrg */ 66444c061aSmrg/*LINTLIBRARY*/ 67444c061aSmrg 68444c061aSmrg#ifdef HAVE_CONFIG_H 69444c061aSmrg#include <config.h> 70444c061aSmrg#endif 71444c061aSmrg#include "IntrinsicI.h" 72444c061aSmrg 73444c061aSmrg#ifndef TM_NO_MATCH 74444c061aSmrg#define TM_NO_MATCH (-2) 75444c061aSmrg#endif /* TM_NO_MATCH */ 76444c061aSmrg 77444c061aSmrg/* forward definitions */ 78444c061aSmrgstatic StatePtr NewState(TMParseStateTree, TMShortCard, TMShortCard); 79444c061aSmrg 80444c061aSmrg 81444c061aSmrgstatic String XtNtranslationError = "translationError"; 82444c061aSmrg 83444c061aSmrg#ifndef __EMX__ 84444c061aSmrgTMGlobalRec _XtGlobalTM; /* initialized to zero K&R */ 85444c061aSmrg#else 86444c061aSmrgTMGlobalRec _XtGlobalTM = {0}; 87444c061aSmrg#endif 88444c061aSmrg 89444c061aSmrg#define MatchIncomingEvent(tmEvent, typeMatch, modMatch) \ 90444c061aSmrg (typeMatch->eventType == tmEvent->event.eventType && \ 91444c061aSmrg (typeMatch->matchEvent != NULL) && \ 92444c061aSmrg (*typeMatch->matchEvent)(typeMatch, modMatch, tmEvent)) 93444c061aSmrg 94444c061aSmrg 95444c061aSmrg#define NumStateTrees(xlations) \ 96444c061aSmrg ((translateData->isSimple) ? 1 : (TMComplexXlations(xlations))->numTrees) 97444c061aSmrg 98444c061aSmrgstatic TMShortCard GetBranchHead( 99444c061aSmrg TMParseStateTree parseTree, 100444c061aSmrg TMShortCard typeIndex, 101444c061aSmrg TMShortCard modIndex, 102444c061aSmrg Boolean isDummy) 103444c061aSmrg{ 104444c061aSmrg#define TM_BRANCH_HEAD_TBL_ALLOC 8 105444c061aSmrg#define TM_BRANCH_HEAD_TBL_REALLOC 8 106444c061aSmrg 107444c061aSmrg TMBranchHead branchHead = parseTree->branchHeadTbl; 108444c061aSmrg TMShortCard newSize, i; 109444c061aSmrg 110444c061aSmrg /* 111444c061aSmrg * dummy is used as a place holder for later matching in old-style 112444c061aSmrg * matching behavior. If there's already an entry we don't need 113444c061aSmrg * another dummy. 114444c061aSmrg */ 115444c061aSmrg if (isDummy) { 116444c061aSmrg for (i = 0; i < parseTree->numBranchHeads; i++, branchHead++) { 117444c061aSmrg if ((branchHead->typeIndex == typeIndex) && 118444c061aSmrg (branchHead->modIndex == modIndex)) 119444c061aSmrg return i; 120444c061aSmrg } 121444c061aSmrg } 122444c061aSmrg if (parseTree->numBranchHeads == parseTree->branchHeadTblSize) 123444c061aSmrg { 124444c061aSmrg if (parseTree->branchHeadTblSize == 0) 125444c061aSmrg parseTree->branchHeadTblSize += TM_BRANCH_HEAD_TBL_ALLOC; 126444c061aSmrg else 127444c061aSmrg parseTree->branchHeadTblSize += 128444c061aSmrg TM_BRANCH_HEAD_TBL_REALLOC; 129444c061aSmrg newSize = (parseTree->branchHeadTblSize * sizeof(TMBranchHeadRec)); 130444c061aSmrg if (parseTree->isStackBranchHeads) { 131444c061aSmrg TMBranchHead oldBranchHeadTbl = parseTree->branchHeadTbl; 132444c061aSmrg parseTree->branchHeadTbl = (TMBranchHead) __XtMalloc(newSize); 133444c061aSmrg XtMemmove(parseTree->branchHeadTbl, oldBranchHeadTbl, newSize); 134444c061aSmrg parseTree->isStackBranchHeads = False; 135444c061aSmrg } 136444c061aSmrg else { 137444c061aSmrg parseTree->branchHeadTbl = (TMBranchHead) 138444c061aSmrg XtRealloc((char *)parseTree->branchHeadTbl, 139444c061aSmrg (parseTree->branchHeadTblSize * 140444c061aSmrg sizeof(TMBranchHeadRec))); 141444c061aSmrg } 142444c061aSmrg } 143444c061aSmrg#ifdef TRACE_TM 144444c061aSmrg LOCK_PROCESS; 145444c061aSmrg _XtGlobalTM.numBranchHeads++; 146444c061aSmrg UNLOCK_PROCESS; 147444c061aSmrg#endif /* TRACE_TM */ 148444c061aSmrg branchHead = 149444c061aSmrg &parseTree->branchHeadTbl[parseTree->numBranchHeads++]; 150444c061aSmrg branchHead->typeIndex = typeIndex; 151444c061aSmrg branchHead->modIndex = modIndex; 152444c061aSmrg branchHead->more = 0; 153444c061aSmrg branchHead->isSimple = True; 154444c061aSmrg branchHead->hasActions = False; 155444c061aSmrg branchHead->hasCycles = False; 156444c061aSmrg return parseTree->numBranchHeads-1; 157444c061aSmrg} 158444c061aSmrg 159444c061aSmrgTMShortCard _XtGetQuarkIndex( 160444c061aSmrg TMParseStateTree parseTree, 161444c061aSmrg XrmQuark quark) 162444c061aSmrg{ 163444c061aSmrg#define TM_QUARK_TBL_ALLOC 16 164444c061aSmrg#define TM_QUARK_TBL_REALLOC 16 165444c061aSmrg TMShortCard i = parseTree->numQuarks; 166444c061aSmrg 167444c061aSmrg for (i=0; i < parseTree->numQuarks; i++) 168444c061aSmrg if (parseTree->quarkTbl[i] == quark) 169444c061aSmrg break; 170444c061aSmrg 171444c061aSmrg if (i == parseTree->numQuarks) 172444c061aSmrg { 173444c061aSmrg if (parseTree->numQuarks == parseTree->quarkTblSize) 174444c061aSmrg { 175444c061aSmrg TMShortCard newSize; 176444c061aSmrg 177444c061aSmrg if (parseTree->quarkTblSize == 0) 178444c061aSmrg parseTree->quarkTblSize += TM_QUARK_TBL_ALLOC; 179444c061aSmrg else 180444c061aSmrg parseTree->quarkTblSize += TM_QUARK_TBL_REALLOC; 181444c061aSmrg newSize = (parseTree->quarkTblSize * sizeof(XrmQuark)); 182444c061aSmrg 183444c061aSmrg if (parseTree->isStackQuarks) { 184444c061aSmrg XrmQuark *oldquarkTbl = parseTree->quarkTbl; 185444c061aSmrg parseTree->quarkTbl = (XrmQuark *) __XtMalloc(newSize); 186444c061aSmrg XtMemmove(parseTree->quarkTbl, oldquarkTbl, newSize); 187444c061aSmrg parseTree->isStackQuarks = False; 188444c061aSmrg } 189444c061aSmrg else { 190444c061aSmrg parseTree->quarkTbl = (XrmQuark *) 191444c061aSmrg XtRealloc((char *)parseTree->quarkTbl, 192444c061aSmrg (parseTree->quarkTblSize * 193444c061aSmrg sizeof(XrmQuark))); 194444c061aSmrg } 195444c061aSmrg } 196444c061aSmrg parseTree->quarkTbl[parseTree->numQuarks++] = quark; 197444c061aSmrg } 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 */ 205444c061aSmrg/*ARGSUSED*/ 206444c061aSmrgstatic TMShortCard GetComplexBranchIndex( 207444c061aSmrg TMParseStateTree parseTree, 208444c061aSmrg TMShortCard typeIndex, 209444c061aSmrg TMShortCard modIndex) 210444c061aSmrg{ 211444c061aSmrg#define TM_COMPLEXBRANCH_HEAD_TBL_ALLOC 8 212444c061aSmrg#define TM_COMPLEXBRANCH_HEAD_TBL_REALLOC 4 213444c061aSmrg 214444c061aSmrg if (parseTree->numComplexBranchHeads == parseTree->complexBranchHeadTblSize) { 215444c061aSmrg TMShortCard newSize; 216444c061aSmrg 217444c061aSmrg if (parseTree->complexBranchHeadTblSize == 0) 218444c061aSmrg parseTree->complexBranchHeadTblSize += TM_COMPLEXBRANCH_HEAD_TBL_ALLOC; 219444c061aSmrg else 220444c061aSmrg parseTree->complexBranchHeadTblSize += TM_COMPLEXBRANCH_HEAD_TBL_REALLOC; 221444c061aSmrg 222444c061aSmrg newSize = (parseTree->complexBranchHeadTblSize * sizeof(StatePtr)); 223444c061aSmrg 224444c061aSmrg if (parseTree->isStackComplexBranchHeads) { 225444c061aSmrg StatePtr *oldcomplexBranchHeadTbl 226444c061aSmrg = parseTree->complexBranchHeadTbl; 227444c061aSmrg parseTree->complexBranchHeadTbl = (StatePtr *) __XtMalloc(newSize); 228444c061aSmrg XtMemmove(parseTree->complexBranchHeadTbl, 229444c061aSmrg oldcomplexBranchHeadTbl, newSize); 230444c061aSmrg parseTree->isStackComplexBranchHeads = False; 231444c061aSmrg } 232444c061aSmrg else { 233444c061aSmrg parseTree->complexBranchHeadTbl = (StatePtr *) 234444c061aSmrg XtRealloc((char *)parseTree->complexBranchHeadTbl, 235444c061aSmrg (parseTree->complexBranchHeadTblSize * 236444c061aSmrg sizeof(StatePtr))); 237444c061aSmrg } 238444c061aSmrg } 239444c061aSmrg parseTree->complexBranchHeadTbl[parseTree->numComplexBranchHeads++] = NULL; 240444c061aSmrg return parseTree->numComplexBranchHeads-1; 241444c061aSmrg} 242444c061aSmrg 243444c061aSmrgTMShortCard _XtGetTypeIndex( 244444c061aSmrg Event *event) 245444c061aSmrg{ 246444c061aSmrg TMShortCard i, j = TM_TYPE_SEGMENT_SIZE; 247444c061aSmrg TMShortCard typeIndex = 0; 248444c061aSmrg TMTypeMatch typeMatch; 249444c061aSmrg TMTypeMatch segment = NULL; 250444c061aSmrg 251444c061aSmrg LOCK_PROCESS; 252444c061aSmrg for (i = 0; i < _XtGlobalTM.numTypeMatchSegments; i++) { 253444c061aSmrg segment = _XtGlobalTM.typeMatchSegmentTbl[i]; 254444c061aSmrg for (j = 0; 255444c061aSmrg typeIndex < _XtGlobalTM.numTypeMatches && j < TM_TYPE_SEGMENT_SIZE; 256444c061aSmrg j++, typeIndex++) 257444c061aSmrg { 258444c061aSmrg typeMatch = &(segment[j]); 259444c061aSmrg if (event->eventType == typeMatch->eventType && 260444c061aSmrg event->eventCode == typeMatch->eventCode && 261444c061aSmrg event->eventCodeMask == typeMatch->eventCodeMask && 262444c061aSmrg event->matchEvent == typeMatch->matchEvent) { 263444c061aSmrg UNLOCK_PROCESS; 264444c061aSmrg return typeIndex; 265444c061aSmrg } 266444c061aSmrg } 267444c061aSmrg } 268444c061aSmrg 269444c061aSmrg if (j == TM_TYPE_SEGMENT_SIZE) { 270444c061aSmrg if (_XtGlobalTM.numTypeMatchSegments == _XtGlobalTM.typeMatchSegmentTblSize) { 271444c061aSmrg _XtGlobalTM.typeMatchSegmentTblSize += 4; 272444c061aSmrg _XtGlobalTM.typeMatchSegmentTbl = (TMTypeMatch *) 273444c061aSmrg XtRealloc((char *)_XtGlobalTM.typeMatchSegmentTbl, 274444c061aSmrg (_XtGlobalTM.typeMatchSegmentTblSize * sizeof(TMTypeMatch))); 275444c061aSmrg } 276444c061aSmrg _XtGlobalTM.typeMatchSegmentTbl[_XtGlobalTM.numTypeMatchSegments++] = 277444c061aSmrg segment = (TMTypeMatch) 278444c061aSmrg __XtMalloc(TM_TYPE_SEGMENT_SIZE * sizeof(TMTypeMatchRec)); 279444c061aSmrg j = 0; 280444c061aSmrg } 281444c061aSmrg typeMatch = &segment[j]; 282444c061aSmrg typeMatch->eventType = event->eventType; 283444c061aSmrg typeMatch->eventCode = event->eventCode; 284444c061aSmrg typeMatch->eventCodeMask = event->eventCodeMask; 285444c061aSmrg typeMatch->matchEvent = event->matchEvent; 286444c061aSmrg _XtGlobalTM.numTypeMatches++; 287444c061aSmrg UNLOCK_PROCESS; 288444c061aSmrg return typeIndex; 289444c061aSmrg} 290444c061aSmrg 291444c061aSmrgstatic Boolean CompareLateModifiers( 292444c061aSmrg LateBindingsPtr lateBind1P, 293444c061aSmrg LateBindingsPtr lateBind2P) 294444c061aSmrg{ 295444c061aSmrg LateBindingsPtr late1P = lateBind1P; 296444c061aSmrg LateBindingsPtr late2P = lateBind2P; 297444c061aSmrg 298444c061aSmrg if (late1P != NULL || late2P != NULL) { 299444c061aSmrg int i = 0; 300444c061aSmrg int j = 0; 301444c061aSmrg if (late1P != NULL) 302444c061aSmrg for (; late1P->keysym != NoSymbol; i++) late1P++; 303444c061aSmrg if (late2P != NULL) 304444c061aSmrg for (; late2P->keysym != NoSymbol; j++) late2P++; 305444c061aSmrg if (i != j) return FALSE; 306444c061aSmrg late1P--; 307444c061aSmrg while (late1P >= lateBind1P) { 308444c061aSmrg Boolean last = True; 309444c061aSmrg for (late2P = lateBind2P + i - 1; 310444c061aSmrg late2P >= lateBind2P; 311444c061aSmrg late2P--) { 312444c061aSmrg if (late1P->keysym == late2P->keysym 313444c061aSmrg && late1P->knot == late2P->knot) { 314444c061aSmrg j--; 315444c061aSmrg if (last) i--; 316444c061aSmrg break; 317444c061aSmrg } 318444c061aSmrg last = False; 319444c061aSmrg } 320444c061aSmrg late1P--; 321444c061aSmrg } 322444c061aSmrg if (j != 0) return FALSE; 323444c061aSmrg } 324444c061aSmrg return TRUE; 325444c061aSmrg} 326444c061aSmrg 327444c061aSmrgTMShortCard _XtGetModifierIndex( 328444c061aSmrg Event *event) 329444c061aSmrg{ 330444c061aSmrg TMShortCard i, j = TM_MOD_SEGMENT_SIZE; 331444c061aSmrg TMShortCard modIndex = 0; 332444c061aSmrg TMModifierMatch modMatch; 333444c061aSmrg TMModifierMatch segment = NULL; 334444c061aSmrg 335444c061aSmrg LOCK_PROCESS; 336444c061aSmrg for (i = 0; i < _XtGlobalTM.numModMatchSegments; i++) { 337444c061aSmrg segment = _XtGlobalTM.modMatchSegmentTbl[i]; 338444c061aSmrg for (j = 0; 339444c061aSmrg modIndex < _XtGlobalTM.numModMatches && j < TM_MOD_SEGMENT_SIZE; 340444c061aSmrg j++, modIndex++) { 341444c061aSmrg modMatch = &(segment[j]); 342444c061aSmrg if (event->modifiers == modMatch->modifiers && 343444c061aSmrg event->modifierMask == modMatch->modifierMask && 344444c061aSmrg event->standard == modMatch->standard && 345444c061aSmrg ((!event->lateModifiers && !modMatch->lateModifiers) || 346444c061aSmrg CompareLateModifiers(event->lateModifiers, 347444c061aSmrg modMatch->lateModifiers))) { 348444c061aSmrg /* 349444c061aSmrg * if we found a match then we can free the parser's 350444c061aSmrg * late modifiers. If there isn't a match we use the 351444c061aSmrg * parser's copy 352444c061aSmrg */ 353444c061aSmrg if (event->lateModifiers && 354444c061aSmrg --event->lateModifiers->ref_count == 0) { 355444c061aSmrg XtFree((char *)event->lateModifiers); 356444c061aSmrg event->lateModifiers = NULL; 357444c061aSmrg } 358444c061aSmrg UNLOCK_PROCESS; 359444c061aSmrg return modIndex; 360444c061aSmrg } 361444c061aSmrg } 362444c061aSmrg } 363444c061aSmrg 364444c061aSmrg if (j == TM_MOD_SEGMENT_SIZE) { 365444c061aSmrg if (_XtGlobalTM.numModMatchSegments == _XtGlobalTM.modMatchSegmentTblSize) { 366444c061aSmrg _XtGlobalTM.modMatchSegmentTblSize += 4; 367444c061aSmrg _XtGlobalTM.modMatchSegmentTbl = (TMModifierMatch *) 368444c061aSmrg XtRealloc((char *)_XtGlobalTM.modMatchSegmentTbl, 369444c061aSmrg (_XtGlobalTM.modMatchSegmentTblSize * sizeof(TMModifierMatch))); 370444c061aSmrg } 371444c061aSmrg _XtGlobalTM.modMatchSegmentTbl[_XtGlobalTM.numModMatchSegments++] = 372444c061aSmrg segment = (TMModifierMatch) 373444c061aSmrg __XtMalloc(TM_MOD_SEGMENT_SIZE * sizeof(TMModifierMatchRec)); 374444c061aSmrg j = 0; 375444c061aSmrg } 376444c061aSmrg modMatch = &segment[j]; 377444c061aSmrg modMatch->modifiers = event->modifiers;; 378444c061aSmrg modMatch->modifierMask = event->modifierMask; 379444c061aSmrg modMatch->standard = event->standard; 380444c061aSmrg /* 381444c061aSmrg * We use the parser's copy of the late binding array 382444c061aSmrg */ 383444c061aSmrg#ifdef TRACE_TM 384444c061aSmrg if (event->lateModifiers) 385444c061aSmrg _XtGlobalTM.numLateBindings++; 386444c061aSmrg#endif /* TRACE_TM */ 387444c061aSmrg modMatch->lateModifiers = event->lateModifiers; 388444c061aSmrg _XtGlobalTM.numModMatches++; 389444c061aSmrg UNLOCK_PROCESS; 390444c061aSmrg return modIndex; 391444c061aSmrg} 392444c061aSmrg 393444c061aSmrg 394444c061aSmrg/* 395444c061aSmrg * This is called from the SimpleStateHandler to match a stateTree 396444c061aSmrg * entry to the event coming in 397444c061aSmrg */ 398444c061aSmrgstatic int MatchBranchHead( 399444c061aSmrg TMSimpleStateTree stateTree, 400444c061aSmrg int startIndex, 401444c061aSmrg TMEventPtr event) 402444c061aSmrg{ 403444c061aSmrg TMBranchHead branchHead = &stateTree->branchHeadTbl[startIndex]; 404444c061aSmrg int i; 405444c061aSmrg 406444c061aSmrg LOCK_PROCESS; 407444c061aSmrg for (i = startIndex; 408444c061aSmrg i < (int)stateTree->numBranchHeads; 409444c061aSmrg i++, branchHead++) 410444c061aSmrg { 411444c061aSmrg TMTypeMatch typeMatch; 412444c061aSmrg TMModifierMatch modMatch; 413444c061aSmrg 414444c061aSmrg typeMatch = TMGetTypeMatch(branchHead->typeIndex); 415444c061aSmrg modMatch = TMGetModifierMatch(branchHead->modIndex); 416444c061aSmrg 417444c061aSmrg if (MatchIncomingEvent(event, typeMatch, modMatch)) { 418444c061aSmrg UNLOCK_PROCESS; 419444c061aSmrg return i; 420444c061aSmrg } 421444c061aSmrg } 422444c061aSmrg UNLOCK_PROCESS; 423444c061aSmrg return (TM_NO_MATCH); 424444c061aSmrg} 425444c061aSmrg 426444c061aSmrgBoolean _XtRegularMatch( 427444c061aSmrg TMTypeMatch typeMatch, 428444c061aSmrg TMModifierMatch modMatch, 429444c061aSmrg TMEventPtr eventSeq) 430444c061aSmrg{ 431444c061aSmrg Modifiers computed =0; 432444c061aSmrg Modifiers computedMask =0; 433444c061aSmrg Boolean resolved = TRUE; 434444c061aSmrg if (typeMatch->eventCode != (eventSeq->event.eventCode & 435444c061aSmrg typeMatch->eventCodeMask)) return FALSE; 436444c061aSmrg if (modMatch->lateModifiers != NULL) 437444c061aSmrg resolved = _XtComputeLateBindings(eventSeq->xev->xany.display, 438444c061aSmrg modMatch->lateModifiers, 439444c061aSmrg &computed, &computedMask); 440444c061aSmrg if (!resolved) return FALSE; 441444c061aSmrg computed |= modMatch->modifiers; 442444c061aSmrg computedMask |= modMatch->modifierMask; 443444c061aSmrg 444444c061aSmrg return ( (computed & computedMask) == 445444c061aSmrg (eventSeq->event.modifiers & computedMask)); 446444c061aSmrg} 447444c061aSmrg 448444c061aSmrg/*ARGSUSED*/ 449444c061aSmrgBoolean _XtMatchAtom( 450444c061aSmrg TMTypeMatch typeMatch, 451444c061aSmrg TMModifierMatch modMatch, 452444c061aSmrg TMEventPtr eventSeq) 453444c061aSmrg{ 454444c061aSmrg Atom atom; 455444c061aSmrg 456444c061aSmrg atom = XInternAtom(eventSeq->xev->xany.display, 457444c061aSmrg XrmQuarkToString(typeMatch->eventCode), 458444c061aSmrg False); 459444c061aSmrg return (atom == eventSeq->event.eventCode); 460444c061aSmrg} 461444c061aSmrg 462444c061aSmrg#define IsOn(vec,idx) ((vec)[(idx)>>3] & (1 << ((idx) & 7))) 463444c061aSmrg 464444c061aSmrg/* 465444c061aSmrg * there are certain cases where you want to ignore the event and stay 466444c061aSmrg * in the same state. 467444c061aSmrg */ 468444c061aSmrgstatic Boolean Ignore( 469444c061aSmrg TMEventPtr event) 470444c061aSmrg{ 471444c061aSmrg Display *dpy; 472444c061aSmrg XtPerDisplay pd; 473444c061aSmrg 474444c061aSmrg if (event->event.eventType == MotionNotify) 475444c061aSmrg return TRUE; 476444c061aSmrg if (!(event->event.eventType == KeyPress || 477444c061aSmrg event->event.eventType == KeyRelease)) 478444c061aSmrg return FALSE; 479444c061aSmrg dpy = event->xev->xany.display; 480444c061aSmrg pd = _XtGetPerDisplay(dpy); 481444c061aSmrg _InitializeKeysymTables(dpy, pd); 482444c061aSmrg return IsOn(pd->isModifier, event->event.eventCode) ? TRUE : FALSE; 483444c061aSmrg} 484444c061aSmrg 485444c061aSmrg 486444c061aSmrgstatic void XEventToTMEvent( 487444c061aSmrg XEvent *event, 488444c061aSmrg TMEventPtr tmEvent) 489444c061aSmrg{ 490444c061aSmrg tmEvent->xev = event; 491444c061aSmrg tmEvent->event.eventCodeMask = 0; 492444c061aSmrg tmEvent->event.modifierMask = 0; 493444c061aSmrg tmEvent->event.eventType = event->type; 494444c061aSmrg tmEvent->event.lateModifiers = NULL; 495444c061aSmrg tmEvent->event.matchEvent = NULL; 496444c061aSmrg tmEvent->event.standard = FALSE; 497444c061aSmrg 498444c061aSmrg switch (event->type) { 499444c061aSmrg 500444c061aSmrg case KeyPress: 501444c061aSmrg case KeyRelease: 502444c061aSmrg tmEvent->event.eventCode = event->xkey.keycode; 503444c061aSmrg tmEvent->event.modifiers = event->xkey.state; 504444c061aSmrg break; 505444c061aSmrg 506444c061aSmrg case ButtonPress: 507444c061aSmrg case ButtonRelease: 508444c061aSmrg tmEvent->event.eventCode = event->xbutton.button; 509444c061aSmrg tmEvent->event.modifiers = event->xbutton.state; 510444c061aSmrg break; 511444c061aSmrg 512444c061aSmrg case MotionNotify: 513444c061aSmrg tmEvent->event.eventCode = event->xmotion.is_hint; 514444c061aSmrg tmEvent->event.modifiers = event->xmotion.state; 515444c061aSmrg break; 516444c061aSmrg 517444c061aSmrg case EnterNotify: 518444c061aSmrg case LeaveNotify: 519444c061aSmrg tmEvent->event.eventCode = event->xcrossing.mode; 520444c061aSmrg tmEvent->event.modifiers = event->xcrossing.state; 521444c061aSmrg break; 522444c061aSmrg 523444c061aSmrg case PropertyNotify: 524444c061aSmrg tmEvent->event.eventCode = event->xproperty.atom; 525444c061aSmrg tmEvent->event.modifiers = 0; 526444c061aSmrg break; 527444c061aSmrg 528444c061aSmrg case SelectionClear: 529444c061aSmrg tmEvent->event.eventCode = event->xselectionclear.selection; 530444c061aSmrg tmEvent->event.modifiers = 0; 531444c061aSmrg break; 532444c061aSmrg 533444c061aSmrg case SelectionRequest: 534444c061aSmrg tmEvent->event.eventCode = event->xselectionrequest.selection; 535444c061aSmrg tmEvent->event.modifiers = 0; 536444c061aSmrg break; 537444c061aSmrg 538444c061aSmrg case SelectionNotify: 539444c061aSmrg tmEvent->event.eventCode = event->xselection.selection; 540444c061aSmrg tmEvent->event.modifiers = 0; 541444c061aSmrg break; 542444c061aSmrg 543444c061aSmrg case ClientMessage: 544444c061aSmrg tmEvent->event.eventCode = event->xclient.message_type; 545444c061aSmrg tmEvent->event.modifiers = 0; 546444c061aSmrg break; 547444c061aSmrg 548444c061aSmrg case MappingNotify: 549444c061aSmrg tmEvent->event.eventCode = event->xmapping.request; 550444c061aSmrg tmEvent->event.modifiers = 0; 551444c061aSmrg break; 552444c061aSmrg 553444c061aSmrg case FocusIn: 554444c061aSmrg case FocusOut: 555444c061aSmrg tmEvent->event.eventCode = event->xfocus.mode; 556444c061aSmrg tmEvent->event.modifiers = 0; 557444c061aSmrg break; 558444c061aSmrg 559444c061aSmrg default: 560444c061aSmrg tmEvent->event.eventCode = 0; 561444c061aSmrg tmEvent->event.modifiers = 0; 562444c061aSmrg break; 563444c061aSmrg } 564444c061aSmrg} 565444c061aSmrg 566444c061aSmrg 567444c061aSmrgstatic unsigned long GetTime( 568444c061aSmrg XtTM tm, 569444c061aSmrg XEvent *event) 570444c061aSmrg{ 571444c061aSmrg switch (event->type) { 572444c061aSmrg 573444c061aSmrg case KeyPress: 574444c061aSmrg case KeyRelease: 575444c061aSmrg return event->xkey.time; 576444c061aSmrg 577444c061aSmrg case ButtonPress: 578444c061aSmrg case ButtonRelease: 579444c061aSmrg return event->xbutton.time; 580444c061aSmrg 581444c061aSmrg default: 582444c061aSmrg return tm->lastEventTime; 583444c061aSmrg 584444c061aSmrg } 585444c061aSmrg 586444c061aSmrg} 587444c061aSmrg 588444c061aSmrgstatic void HandleActions( 589444c061aSmrg Widget w, 590444c061aSmrg XEvent *event, 591444c061aSmrg TMSimpleStateTree stateTree, 592444c061aSmrg Widget accelWidget, 593444c061aSmrg XtActionProc *procs, 594444c061aSmrg ActionRec *actions) 595444c061aSmrg{ 596444c061aSmrg ActionHook actionHookList; 597444c061aSmrg Widget bindWidget; 598444c061aSmrg 599444c061aSmrg bindWidget = accelWidget ? accelWidget : w; 600444c061aSmrg if (accelWidget && !XtIsSensitive(accelWidget) && 601444c061aSmrg (event->type == KeyPress || event->type == KeyRelease || 602444c061aSmrg event->type == ButtonPress || event->type == ButtonRelease || 603444c061aSmrg event->type == MotionNotify || event->type == EnterNotify || 604444c061aSmrg event->type == LeaveNotify || event->type == FocusIn || 605444c061aSmrg event->type == FocusOut)) 606444c061aSmrg return; 607444c061aSmrg 608444c061aSmrg actionHookList = XtWidgetToApplicationContext(w)->action_hook_list; 609444c061aSmrg 610444c061aSmrg while (actions != NULL) { 611444c061aSmrg /* perform any actions */ 612444c061aSmrg if (procs[actions->idx] != NULL) { 613444c061aSmrg if (actionHookList) { 614444c061aSmrg ActionHook hook; 615444c061aSmrg ActionHook next_hook; 616444c061aSmrg String procName = 617444c061aSmrg XrmQuarkToString(stateTree->quarkTbl[actions->idx] ); 618444c061aSmrg 619444c061aSmrg for (hook = actionHookList; hook != NULL; ) { 620444c061aSmrg /* 621444c061aSmrg * Need to cache hook->next because the following action 622444c061aSmrg * proc may free hook via XtRemoveActionHook making 623444c061aSmrg * hook->next invalid upon return from the action proc. 624444c061aSmrg */ 625444c061aSmrg next_hook = hook->next; 626444c061aSmrg (*hook->proc)(bindWidget, 627444c061aSmrg hook->closure, 628444c061aSmrg procName, 629444c061aSmrg event, 630444c061aSmrg actions->params, 631444c061aSmrg &actions->num_params 632444c061aSmrg ); 633444c061aSmrg hook = next_hook; 634444c061aSmrg } 635444c061aSmrg } 636444c061aSmrg (*(procs[actions->idx])) 637444c061aSmrg (bindWidget, event, 638444c061aSmrg actions->params, &actions->num_params ); 639444c061aSmrg } 640444c061aSmrg actions = actions->next; 641444c061aSmrg } 642444c061aSmrg} 643444c061aSmrg 644444c061aSmrgtypedef struct { 645444c061aSmrg unsigned int isCycleStart:1; 646444c061aSmrg unsigned int isCycleEnd:1; 647444c061aSmrg TMShortCard typeIndex; 648444c061aSmrg TMShortCard modIndex; 649444c061aSmrg}MatchPairRec, *MatchPair; 650444c061aSmrg 651444c061aSmrgtypedef struct TMContextRec{ 652444c061aSmrg TMShortCard numMatches; 653444c061aSmrg TMShortCard maxMatches; 654444c061aSmrg MatchPair matches; 655444c061aSmrg}TMContextRec, *TMContext; 656444c061aSmrg 657444c061aSmrgstatic 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 664444c061aSmrgstatic void PushContext( 665444c061aSmrg TMContext *contextPtr, 666444c061aSmrg StatePtr newState) 667444c061aSmrg{ 668444c061aSmrg TMContext context = *contextPtr; 669444c061aSmrg 670444c061aSmrg LOCK_PROCESS; 671444c061aSmrg if (context == NULL) 672444c061aSmrg { 673444c061aSmrg if (contextCache[0].numMatches == 0) 674444c061aSmrg context = &contextCache[0]; 675444c061aSmrg else if (contextCache[1].numMatches == 0) 676444c061aSmrg context = &contextCache[1]; 677444c061aSmrg if (!context) 678444c061aSmrg { 679444c061aSmrg context = XtNew(TMContextRec); 680444c061aSmrg context->matches = NULL; 681444c061aSmrg context->numMatches = 682444c061aSmrg context->maxMatches = 0; 683444c061aSmrg } 684444c061aSmrg } 685444c061aSmrg if (context->numMatches && 686444c061aSmrg context->matches[context->numMatches-1].isCycleEnd) 687444c061aSmrg { 688444c061aSmrg TMShortCard i; 689444c061aSmrg for (i = 0; 690444c061aSmrg i < context->numMatches && 691444c061aSmrg !(context->matches[i].isCycleStart); 692444c061aSmrg i++){}; 693444c061aSmrg if (i < context->numMatches) 694444c061aSmrg context->numMatches = i+1; 695444c061aSmrg#ifdef DEBUG 696444c061aSmrg else 697444c061aSmrg XtWarning("pushing cycle end with no cycle start"); 698444c061aSmrg#endif /* DEBUG */ 699444c061aSmrg } 700444c061aSmrg else 701444c061aSmrg { 702444c061aSmrg if (context->numMatches == context->maxMatches) 703444c061aSmrg { 704444c061aSmrg if (context->maxMatches == 0) 705444c061aSmrg context->maxMatches += TM_CONTEXT_MATCHES_ALLOC; 706444c061aSmrg else 707444c061aSmrg context->maxMatches += TM_CONTEXT_MATCHES_REALLOC; 708444c061aSmrg context->matches = (MatchPairRec *) 709444c061aSmrg XtRealloc((char *)context->matches, 710444c061aSmrg context->maxMatches * sizeof(MatchPairRec)); 711444c061aSmrg } 712444c061aSmrg context->matches[context->numMatches].isCycleStart = newState->isCycleStart; 713444c061aSmrg context->matches[context->numMatches].isCycleEnd = newState->isCycleEnd; 714444c061aSmrg context->matches[context->numMatches].typeIndex = newState->typeIndex; 715444c061aSmrg context->matches[context->numMatches++].modIndex = newState->modIndex; 716444c061aSmrg *contextPtr = context; 717444c061aSmrg } 718444c061aSmrg UNLOCK_PROCESS; 719444c061aSmrg} 720444c061aSmrg 721444c061aSmrgstatic void FreeContext( 722444c061aSmrg TMContext *contextPtr) 723444c061aSmrg{ 724444c061aSmrg TMContext context = NULL; 725444c061aSmrg 726444c061aSmrg LOCK_PROCESS; 727444c061aSmrg 728444c061aSmrg if (&contextCache[0] == *contextPtr) 729444c061aSmrg context = &contextCache[0]; 730444c061aSmrg else if (&contextCache[1] == *contextPtr) 731444c061aSmrg context = &contextCache[1]; 732444c061aSmrg 733444c061aSmrg if (context) 734444c061aSmrg context->numMatches = 0; 735444c061aSmrg else if (*contextPtr) 736444c061aSmrg { 737444c061aSmrg if ((*contextPtr)->matches) 738444c061aSmrg XtFree ((char *) ((*contextPtr)->matches)); 739444c061aSmrg XtFree((char *)*contextPtr); 740444c061aSmrg } 741444c061aSmrg 742444c061aSmrg *contextPtr = NULL; 743444c061aSmrg UNLOCK_PROCESS; 744444c061aSmrg} 745444c061aSmrg 746444c061aSmrgstatic int MatchExact( 747444c061aSmrg TMSimpleStateTree stateTree, 748444c061aSmrg int startIndex, 749444c061aSmrg TMShortCard typeIndex, 750444c061aSmrg TMShortCard modIndex) 751444c061aSmrg{ 752444c061aSmrg TMBranchHead branchHead = &(stateTree->branchHeadTbl[startIndex]); 753444c061aSmrg int i; 754444c061aSmrg 755444c061aSmrg for (i = startIndex; 756444c061aSmrg i < (int)stateTree->numBranchHeads; 757444c061aSmrg i++, branchHead++) 758444c061aSmrg { 759444c061aSmrg if ((branchHead->typeIndex == typeIndex) && 760444c061aSmrg (branchHead->modIndex == modIndex)) 761444c061aSmrg return i; 762444c061aSmrg } 763444c061aSmrg return (TM_NO_MATCH); 764444c061aSmrg} 765444c061aSmrg 766444c061aSmrg 767444c061aSmrg 768444c061aSmrgstatic void HandleSimpleState( 769444c061aSmrg Widget w, 770444c061aSmrg XtTM tmRecPtr, 771444c061aSmrg TMEventRec *curEventPtr) 772444c061aSmrg{ 773444c061aSmrg XtTranslations xlations = tmRecPtr->translations; 774444c061aSmrg TMSimpleStateTree stateTree; 775444c061aSmrg TMContext *contextPtr = GetContextPtr(tmRecPtr); 776444c061aSmrg TMShortCard i; 777444c061aSmrg ActionRec *actions = NULL; 778444c061aSmrg Boolean matchExact = False; 779444c061aSmrg Boolean match = False; 780444c061aSmrg StatePtr complexMatchState = NULL; 781444c061aSmrg int currIndex; 782444c061aSmrg TMShortCard typeIndex = 0, modIndex = 0; 783444c061aSmrg int matchTreeIndex = TM_NO_MATCH; 784444c061aSmrg 785444c061aSmrg LOCK_PROCESS; 786444c061aSmrg stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[0]; 787444c061aSmrg 788444c061aSmrg for (i = 0; 789444c061aSmrg ((!match || !complexMatchState) && (i < xlations->numStateTrees)); 790444c061aSmrg i++){ 791444c061aSmrg stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[i]; 792444c061aSmrg currIndex = -1; 793444c061aSmrg /* 794444c061aSmrg * don't process this tree if we're only looking for a 795444c061aSmrg * complexMatchState and there are no complex states 796444c061aSmrg */ 797444c061aSmrg while (!(match && stateTree->isSimple) && 798444c061aSmrg ((!match || !complexMatchState) && (currIndex != TM_NO_MATCH))) { 799444c061aSmrg currIndex++; 800444c061aSmrg if (matchExact) 801444c061aSmrg currIndex = MatchExact(stateTree,currIndex,typeIndex,modIndex); 802444c061aSmrg else 803444c061aSmrg currIndex = MatchBranchHead(stateTree,currIndex,curEventPtr); 804444c061aSmrg if (currIndex != TM_NO_MATCH) { 805444c061aSmrg TMBranchHead branchHead; 806444c061aSmrg StatePtr currState; 807444c061aSmrg 808444c061aSmrg branchHead = &stateTree->branchHeadTbl[currIndex]; 809444c061aSmrg if (branchHead->isSimple) 810444c061aSmrg currState = NULL; 811444c061aSmrg else 812444c061aSmrg currState = ((TMComplexStateTree)stateTree) 813444c061aSmrg ->complexBranchHeadTbl[TMBranchMore(branchHead)]; 814444c061aSmrg 815444c061aSmrg /* 816444c061aSmrg * first check for a complete match 817444c061aSmrg */ 818444c061aSmrg if (!match) { 819444c061aSmrg if (branchHead->hasActions) { 820444c061aSmrg if (branchHead->isSimple) { 821444c061aSmrg static ActionRec dummyAction; 822444c061aSmrg 823444c061aSmrg dummyAction.idx = TMBranchMore(branchHead); 824444c061aSmrg actions = &dummyAction; 825444c061aSmrg } 826444c061aSmrg else 827444c061aSmrg actions = currState->actions; 828444c061aSmrg tmRecPtr->lastEventTime = 829444c061aSmrg GetTime(tmRecPtr, curEventPtr->xev); 830444c061aSmrg FreeContext((TMContext 831444c061aSmrg *)&tmRecPtr->current_state); 832444c061aSmrg match = True; 833444c061aSmrg matchTreeIndex = i; 834444c061aSmrg } 835444c061aSmrg /* 836444c061aSmrg * if it doesn't have actions and 837444c061aSmrg * it's bc mode then it's a potential match node that is 838444c061aSmrg * used to match later sequences. 839444c061aSmrg */ 840444c061aSmrg if (!TMNewMatchSemantics() && !matchExact) { 841444c061aSmrg matchExact = True; 842444c061aSmrg typeIndex = branchHead->typeIndex; 843444c061aSmrg modIndex = branchHead->modIndex; 844444c061aSmrg } 845444c061aSmrg } 846444c061aSmrg /* 847444c061aSmrg * check for it being an event sequence which can be 848444c061aSmrg * a future match 849444c061aSmrg */ 850444c061aSmrg if (!branchHead->isSimple && 851444c061aSmrg !branchHead->hasActions && 852444c061aSmrg !complexMatchState) 853444c061aSmrg complexMatchState = currState; 854444c061aSmrg } 855444c061aSmrg } 856444c061aSmrg } 857444c061aSmrg if (match) 858444c061aSmrg { 859444c061aSmrg TMBindData bindData = (TMBindData) tmRecPtr->proc_table; 860444c061aSmrg XtActionProc *procs; 861444c061aSmrg Widget accelWidget; 862444c061aSmrg 863444c061aSmrg if (bindData->simple.isComplex) { 864444c061aSmrg TMComplexBindProcs bindProcs = 865444c061aSmrg TMGetComplexBindEntry(bindData, matchTreeIndex); 866444c061aSmrg procs = bindProcs->procs; 867444c061aSmrg accelWidget = bindProcs->widget; 868444c061aSmrg } 869444c061aSmrg else { 870444c061aSmrg TMSimpleBindProcs bindProcs = 871444c061aSmrg TMGetSimpleBindEntry(bindData, matchTreeIndex); 872444c061aSmrg procs = bindProcs->procs; 873444c061aSmrg accelWidget = NULL; 874444c061aSmrg } 875444c061aSmrg HandleActions 876444c061aSmrg (w, 877444c061aSmrg curEventPtr->xev, 878444c061aSmrg (TMSimpleStateTree)xlations->stateTreeTbl[matchTreeIndex], 879444c061aSmrg accelWidget, 880444c061aSmrg procs, 881444c061aSmrg actions); 882444c061aSmrg } 883444c061aSmrg if (complexMatchState) 884444c061aSmrg PushContext(contextPtr, complexMatchState); 885444c061aSmrg UNLOCK_PROCESS; 886444c061aSmrg} 887444c061aSmrg 888444c061aSmrgstatic int MatchComplexBranch( 889444c061aSmrg TMComplexStateTree stateTree, 890444c061aSmrg int startIndex, 891444c061aSmrg TMContext context, 892444c061aSmrg StatePtr *leafStateRtn) 893444c061aSmrg{ 894444c061aSmrg TMShortCard i; 895444c061aSmrg 896444c061aSmrg LOCK_PROCESS; 897444c061aSmrg for (i = startIndex; i < stateTree->numComplexBranchHeads; i++) 898444c061aSmrg { 899444c061aSmrg StatePtr candState; 900444c061aSmrg TMShortCard numMatches = context->numMatches; 901444c061aSmrg MatchPair statMatch = context->matches; 902444c061aSmrg 903444c061aSmrg for (candState = stateTree->complexBranchHeadTbl[i]; 904444c061aSmrg numMatches && candState; 905444c061aSmrg numMatches--, statMatch++, candState = candState->nextLevel) 906444c061aSmrg { 907444c061aSmrg if ((statMatch->typeIndex != candState->typeIndex) || 908444c061aSmrg (statMatch->modIndex != candState->modIndex)) 909444c061aSmrg break; 910444c061aSmrg } 911444c061aSmrg if (numMatches == 0) { 912444c061aSmrg *leafStateRtn = candState; 913444c061aSmrg UNLOCK_PROCESS; 914444c061aSmrg return i; 915444c061aSmrg } 916444c061aSmrg } 917444c061aSmrg *leafStateRtn = NULL; 918444c061aSmrg UNLOCK_PROCESS; 919444c061aSmrg return (TM_NO_MATCH); 920444c061aSmrg} 921444c061aSmrg 922444c061aSmrgstatic StatePtr TryCurrentTree( 923444c061aSmrg TMComplexStateTree *stateTreePtr, 924444c061aSmrg XtTM tmRecPtr, 925444c061aSmrg TMEventRec *curEventPtr) 926444c061aSmrg{ 927444c061aSmrg StatePtr candState = NULL, matchState = NULL; 928444c061aSmrg TMContext *contextPtr = GetContextPtr(tmRecPtr); 929444c061aSmrg TMTypeMatch typeMatch; 930444c061aSmrg TMModifierMatch modMatch; 931444c061aSmrg int currIndex = -1; 932444c061aSmrg 933444c061aSmrg /* 934444c061aSmrg * we want the first sequence that both matches and has actions. 935444c061aSmrg * we keep on looking till we find both 936444c061aSmrg */ 937444c061aSmrg LOCK_PROCESS; 938444c061aSmrg while ((currIndex = 939444c061aSmrg MatchComplexBranch(*stateTreePtr, 940444c061aSmrg ++currIndex, 941444c061aSmrg (*contextPtr), 942444c061aSmrg &candState)) 943444c061aSmrg != TM_NO_MATCH) { 944444c061aSmrg if (candState != NULL) { 945444c061aSmrg typeMatch = TMGetTypeMatch(candState->typeIndex); 946444c061aSmrg modMatch = TMGetModifierMatch(candState->modIndex); 947444c061aSmrg 948444c061aSmrg /* does this state's index match? --> done */ 949444c061aSmrg if (MatchIncomingEvent(curEventPtr, typeMatch, modMatch)) 950444c061aSmrg { 951444c061aSmrg if (candState->actions) { 952444c061aSmrg UNLOCK_PROCESS; 953444c061aSmrg return candState; 954444c061aSmrg } 955444c061aSmrg else 956444c061aSmrg matchState = candState; 957444c061aSmrg } 958444c061aSmrg /* is this an event timer? */ 959444c061aSmrg if (typeMatch->eventType == _XtEventTimerEventType) { 960444c061aSmrg StatePtr nextState = candState->nextLevel; 961444c061aSmrg 962444c061aSmrg /* does the succeeding state match? */ 963444c061aSmrg if (nextState != NULL) { 964444c061aSmrg TMTypeMatch nextTypeMatch; 965444c061aSmrg TMModifierMatch nextModMatch; 966444c061aSmrg 967444c061aSmrg nextTypeMatch = TMGetTypeMatch(nextState->typeIndex); 968444c061aSmrg nextModMatch = TMGetModifierMatch(nextState->modIndex); 969444c061aSmrg 970444c061aSmrg /* is it within the timeout? */ 971444c061aSmrg if (MatchIncomingEvent(curEventPtr, 972444c061aSmrg nextTypeMatch, 973444c061aSmrg nextModMatch)) { 974444c061aSmrg XEvent *xev = curEventPtr->xev; 975444c061aSmrg unsigned long time = GetTime(tmRecPtr, xev); 976444c061aSmrg XtPerDisplay pd = _XtGetPerDisplay(xev->xany.display); 977444c061aSmrg unsigned long delta = pd->multi_click_time; 978444c061aSmrg 979444c061aSmrg if ((tmRecPtr->lastEventTime + delta) >= time) { 980444c061aSmrg if (nextState->actions) { 981444c061aSmrg UNLOCK_PROCESS; 982444c061aSmrg return candState; 983444c061aSmrg } 984444c061aSmrg else 985444c061aSmrg matchState = candState; 986444c061aSmrg } 987444c061aSmrg } 988444c061aSmrg } 989444c061aSmrg } 990444c061aSmrg } 991444c061aSmrg } 992444c061aSmrg UNLOCK_PROCESS; 993444c061aSmrg return matchState; 994444c061aSmrg} 995444c061aSmrg 996444c061aSmrgstatic void HandleComplexState( 997444c061aSmrg Widget w, 998444c061aSmrg XtTM tmRecPtr, 999444c061aSmrg TMEventRec *curEventPtr) 1000444c061aSmrg{ 1001444c061aSmrg XtTranslations xlations = tmRecPtr->translations; 1002444c061aSmrg TMContext *contextPtr = GetContextPtr(tmRecPtr); 1003444c061aSmrg TMShortCard i, matchTreeIndex = 0; 1004444c061aSmrg StatePtr matchState = NULL, candState; 1005444c061aSmrg TMComplexStateTree *stateTreePtr = 1006444c061aSmrg (TMComplexStateTree *)&xlations->stateTreeTbl[0]; 1007444c061aSmrg 1008444c061aSmrg LOCK_PROCESS; 1009444c061aSmrg for (i = 0; 1010444c061aSmrg i < xlations->numStateTrees; 1011444c061aSmrg i++, stateTreePtr++) { 1012444c061aSmrg /* 1013444c061aSmrg * some compilers sign extend Boolean bit fields so test for 1014444c061aSmrg * false ||| 1015444c061aSmrg */ 1016444c061aSmrg if (((*stateTreePtr)->isSimple == False) && 1017444c061aSmrg (candState = TryCurrentTree(stateTreePtr, 1018444c061aSmrg tmRecPtr, 1019444c061aSmrg curEventPtr))) { 1020444c061aSmrg if (!matchState || candState->actions) { 1021444c061aSmrg matchTreeIndex = i; 1022444c061aSmrg matchState = candState; 1023444c061aSmrg if (candState->actions) 1024444c061aSmrg break; 1025444c061aSmrg } 1026444c061aSmrg } 1027444c061aSmrg } 1028444c061aSmrg if (matchState == NULL){ 1029444c061aSmrg /* couldn't find it... */ 1030444c061aSmrg if (!Ignore(curEventPtr)) 1031444c061aSmrg { 1032444c061aSmrg FreeContext(contextPtr); 1033444c061aSmrg HandleSimpleState(w, tmRecPtr, curEventPtr); 1034444c061aSmrg } 1035444c061aSmrg } 1036444c061aSmrg else { 1037444c061aSmrg TMBindData bindData = (TMBindData) tmRecPtr->proc_table; 1038444c061aSmrg XtActionProc *procs; 1039444c061aSmrg Widget accelWidget; 1040444c061aSmrg TMTypeMatch typeMatch; 1041444c061aSmrg 1042444c061aSmrg typeMatch = TMGetTypeMatch(matchState->typeIndex); 1043444c061aSmrg 1044444c061aSmrg PushContext(contextPtr, matchState); 1045444c061aSmrg if (typeMatch->eventType == _XtEventTimerEventType) { 1046444c061aSmrg matchState = matchState->nextLevel; 1047444c061aSmrg PushContext(contextPtr, matchState); 1048444c061aSmrg } 1049444c061aSmrg tmRecPtr->lastEventTime = GetTime (tmRecPtr, curEventPtr->xev); 1050444c061aSmrg 1051444c061aSmrg if (bindData->simple.isComplex) { 1052444c061aSmrg TMComplexBindProcs bindProcs = 1053444c061aSmrg TMGetComplexBindEntry(bindData, matchTreeIndex); 1054444c061aSmrg procs = bindProcs->procs; 1055444c061aSmrg accelWidget = bindProcs->widget; 1056444c061aSmrg } 1057444c061aSmrg else { 1058444c061aSmrg TMSimpleBindProcs bindProcs = 1059444c061aSmrg TMGetSimpleBindEntry(bindData, matchTreeIndex); 1060444c061aSmrg procs = bindProcs->procs; 1061444c061aSmrg accelWidget = NULL; 1062444c061aSmrg } 1063444c061aSmrg HandleActions(w, 1064444c061aSmrg curEventPtr->xev, 1065444c061aSmrg (TMSimpleStateTree) 1066444c061aSmrg xlations->stateTreeTbl[matchTreeIndex], 1067444c061aSmrg accelWidget, 1068444c061aSmrg procs, 1069444c061aSmrg matchState->actions); 1070444c061aSmrg } 1071444c061aSmrg UNLOCK_PROCESS; 1072444c061aSmrg} 1073444c061aSmrg 1074444c061aSmrg 1075444c061aSmrgvoid _XtTranslateEvent ( 1076444c061aSmrg Widget w, 1077444c061aSmrg XEvent * event) 1078444c061aSmrg{ 1079444c061aSmrg XtTM tmRecPtr = &w->core.tm; 1080444c061aSmrg TMEventRec curEvent; 1081444c061aSmrg StatePtr current_state = tmRecPtr->current_state; 1082444c061aSmrg 1083444c061aSmrg XEventToTMEvent (event, &curEvent); 1084444c061aSmrg 1085444c061aSmrg if (! tmRecPtr->translations) { 1086444c061aSmrg XtAppWarningMsg(XtWidgetToApplicationContext(w), 1087444c061aSmrg XtNtranslationError,"nullTable",XtCXtToolkitError, 1088444c061aSmrg "Can't translate event through NULL table", 1089444c061aSmrg (String *)NULL, (Cardinal *)NULL); 1090444c061aSmrg return ; 1091444c061aSmrg } 1092444c061aSmrg if (current_state == NULL) 1093444c061aSmrg HandleSimpleState(w, tmRecPtr, &curEvent); 1094444c061aSmrg else 1095444c061aSmrg HandleComplexState(w, tmRecPtr, &curEvent); 1096444c061aSmrg} 1097444c061aSmrg 1098444c061aSmrg 1099444c061aSmrg/*ARGSUSED*/ 1100444c061aSmrgstatic StatePtr NewState( 1101444c061aSmrg TMParseStateTree stateTree, 1102444c061aSmrg TMShortCard typeIndex, 1103444c061aSmrg TMShortCard modIndex) 1104444c061aSmrg{ 1105444c061aSmrg StatePtr state = XtNew(StateRec); 1106444c061aSmrg 1107444c061aSmrg#ifdef TRACE_TM 1108444c061aSmrg LOCK_PROCESS; 1109444c061aSmrg _XtGlobalTM.numComplexStates++; 1110444c061aSmrg UNLOCK_PROCESS; 1111444c061aSmrg#endif /* TRACE_TM */ 1112444c061aSmrg state->typeIndex = typeIndex; 1113444c061aSmrg state->modIndex = modIndex; 1114444c061aSmrg state->nextLevel = NULL; 1115444c061aSmrg state->actions = NULL; 1116444c061aSmrg state->isCycleStart = state->isCycleEnd = False; 1117444c061aSmrg return state; 1118444c061aSmrg} 1119444c061aSmrg 1120444c061aSmrg/* 1121444c061aSmrg * This routine is an iterator for state trees. If the func returns 1122444c061aSmrg * true then iteration is over. 1123444c061aSmrg */ 1124444c061aSmrgvoid _XtTraverseStateTree( 1125444c061aSmrg TMStateTree tree, 1126444c061aSmrg _XtTraversalProc func, 1127444c061aSmrg XtPointer data) 1128444c061aSmrg{ 1129444c061aSmrg TMComplexStateTree stateTree = (TMComplexStateTree)tree; 1130444c061aSmrg TMBranchHead currBH; 1131444c061aSmrg TMShortCard i; 1132444c061aSmrg StateRec dummyStateRec, *dummyState = &dummyStateRec; 1133444c061aSmrg ActionRec dummyActionRec, *dummyAction = &dummyActionRec; 1134444c061aSmrg Boolean firstSimple = True; 1135444c061aSmrg StatePtr currState; 1136444c061aSmrg 1137444c061aSmrg /* first traverse the complex states */ 1138444c061aSmrg if (stateTree->isSimple == False) 1139444c061aSmrg for (i = 0; i < stateTree->numComplexBranchHeads; i++) { 1140444c061aSmrg currState = stateTree->complexBranchHeadTbl[i]; 1141444c061aSmrg for (; currState; currState = currState->nextLevel) { 1142444c061aSmrg if (func(currState, data)) 1143444c061aSmrg return; 1144444c061aSmrg if (currState->isCycleEnd) 1145444c061aSmrg break; 1146444c061aSmrg } 1147444c061aSmrg } 1148444c061aSmrg 1149444c061aSmrg /* now traverse the simple ones */ 1150444c061aSmrg for (i = 0, currBH = stateTree->branchHeadTbl; 1151444c061aSmrg i < stateTree->numBranchHeads; 1152444c061aSmrg i++, currBH++) 1153444c061aSmrg { 1154444c061aSmrg if (currBH->isSimple && currBH->hasActions) 1155444c061aSmrg { 1156444c061aSmrg if (firstSimple) 1157444c061aSmrg { 1158444c061aSmrg XtBZero((char *) dummyState, sizeof(StateRec)); 1159444c061aSmrg XtBZero((char *) dummyAction, sizeof(ActionRec)); 1160444c061aSmrg dummyState->actions = dummyAction; 1161444c061aSmrg firstSimple = False; 1162444c061aSmrg } 1163444c061aSmrg dummyState->typeIndex = currBH->typeIndex; 1164444c061aSmrg dummyState->modIndex = currBH->modIndex; 1165444c061aSmrg dummyAction->idx = currBH->more; 1166444c061aSmrg if (func(dummyState, data)) 1167444c061aSmrg return; 1168444c061aSmrg } 1169444c061aSmrg } 1170444c061aSmrg} 1171444c061aSmrg 1172444c061aSmrgstatic EventMask EventToMask( 1173444c061aSmrg TMTypeMatch typeMatch, 1174444c061aSmrg TMModifierMatch modMatch) 1175444c061aSmrg{ 1176444c061aSmrg EventMask returnMask; 1177444c061aSmrg unsigned long eventType = typeMatch->eventType; 1178444c061aSmrg 1179444c061aSmrg if (eventType == MotionNotify) { 1180444c061aSmrg Modifiers modifierMask = modMatch->modifierMask; 1181444c061aSmrg Modifiers tempMask; 1182444c061aSmrg 1183444c061aSmrg returnMask = 0; 1184444c061aSmrg if (modifierMask == 0) { 1185444c061aSmrg if (modMatch->modifiers == AnyButtonMask) 1186444c061aSmrg return ButtonMotionMask; 1187444c061aSmrg else 1188444c061aSmrg return PointerMotionMask; 1189444c061aSmrg } 1190444c061aSmrg tempMask = modifierMask & 1191444c061aSmrg (Button1Mask | Button2Mask | Button3Mask 1192444c061aSmrg | Button4Mask | Button5Mask); 1193444c061aSmrg if (tempMask == 0) 1194444c061aSmrg return PointerMotionMask; 1195444c061aSmrg if (tempMask & Button1Mask) 1196444c061aSmrg returnMask |= Button1MotionMask; 1197444c061aSmrg if (tempMask & Button2Mask) 1198444c061aSmrg returnMask |= Button2MotionMask; 1199444c061aSmrg if (tempMask & Button3Mask) 1200444c061aSmrg returnMask |= Button3MotionMask; 1201444c061aSmrg if (tempMask & Button4Mask) 1202444c061aSmrg returnMask |= Button4MotionMask; 1203444c061aSmrg if (tempMask & Button5Mask) 1204444c061aSmrg returnMask |= Button5MotionMask; 1205444c061aSmrg return returnMask; 1206444c061aSmrg } 1207444c061aSmrg returnMask = _XtConvertTypeToMask(eventType); 1208444c061aSmrg if (returnMask == (StructureNotifyMask|SubstructureNotifyMask)) 1209444c061aSmrg returnMask = StructureNotifyMask; 1210444c061aSmrg return returnMask; 1211444c061aSmrg} 1212444c061aSmrg 1213444c061aSmrg/*ARGSUSED*/ 1214444c061aSmrgstatic void DispatchMappingNotify( 1215444c061aSmrg Widget widget, /* will be NULL from _RefreshMapping */ 1216444c061aSmrg XtPointer closure, /* real Widget */ 1217444c061aSmrg XtPointer call_data) /* XEvent* */ 1218444c061aSmrg{ 1219444c061aSmrg _XtTranslateEvent( (Widget)closure, (XEvent*)call_data); 1220444c061aSmrg} 1221444c061aSmrg 1222444c061aSmrg 1223444c061aSmrg/*ARGSUSED*/ 1224444c061aSmrgstatic void RemoveFromMappingCallbacks( 1225444c061aSmrg Widget widget, 1226444c061aSmrg XtPointer closure, /* target widget */ 1227444c061aSmrg XtPointer call_data) 1228444c061aSmrg{ 1229444c061aSmrg _XtRemoveCallback( &_XtGetPerDisplay(XtDisplay(widget))->mapping_callbacks, 1230444c061aSmrg DispatchMappingNotify, 1231444c061aSmrg closure 1232444c061aSmrg ); 1233444c061aSmrg} 1234444c061aSmrg 1235444c061aSmrgstatic Boolean AggregateEventMask( 1236444c061aSmrg StatePtr state, 1237444c061aSmrg XtPointer data) 1238444c061aSmrg{ 1239444c061aSmrg LOCK_PROCESS; 1240444c061aSmrg *((EventMask *)data) |= EventToMask(TMGetTypeMatch(state->typeIndex), 1241444c061aSmrg TMGetModifierMatch(state->modIndex)); 1242444c061aSmrg UNLOCK_PROCESS; 1243444c061aSmrg return False; 1244444c061aSmrg} 1245444c061aSmrg 1246444c061aSmrgvoid _XtInstallTranslations( 1247444c061aSmrg Widget widget) 1248444c061aSmrg{ 1249444c061aSmrg XtTranslations xlations; 1250444c061aSmrg Cardinal i; 1251444c061aSmrg TMStateTree stateTree; 1252444c061aSmrg Boolean mappingNotifyInterest = False; 1253444c061aSmrg 1254444c061aSmrg xlations = widget->core.tm.translations; 1255444c061aSmrg if (xlations == NULL) return; 1256444c061aSmrg 1257444c061aSmrg /* 1258444c061aSmrg * check for somebody stuffing the translations directly into the 1259444c061aSmrg * instance structure. We will end up being called again out of 1260444c061aSmrg * ComposeTranslations but we *should* have bindings by then 1261444c061aSmrg */ 1262444c061aSmrg if (widget->core.tm.proc_table == NULL) { 1263444c061aSmrg _XtMergeTranslations(widget, NULL, XtTableReplace); 1264444c061aSmrg /* 1265444c061aSmrg * if we're realized then we'll be called out of 1266444c061aSmrg * ComposeTranslations 1267444c061aSmrg */ 1268444c061aSmrg if (XtIsRealized(widget)) 1269444c061aSmrg return; 1270444c061aSmrg } 1271444c061aSmrg 1272444c061aSmrg xlations->eventMask = 0; 1273444c061aSmrg for (i = 0; 1274444c061aSmrg i < xlations->numStateTrees; 1275444c061aSmrg i++) 1276444c061aSmrg { 1277444c061aSmrg stateTree = xlations->stateTreeTbl[i]; 1278444c061aSmrg _XtTraverseStateTree(stateTree, 1279444c061aSmrg AggregateEventMask, 1280444c061aSmrg (XtPointer)&xlations->eventMask); 1281444c061aSmrg mappingNotifyInterest |= stateTree->simple.mappingNotifyInterest; 1282444c061aSmrg } 1283444c061aSmrg /* double click needs to make sure that you have selected on both 1284444c061aSmrg button down and up. */ 1285444c061aSmrg 1286444c061aSmrg if (xlations->eventMask & ButtonPressMask) 1287444c061aSmrg xlations->eventMask |= ButtonReleaseMask; 1288444c061aSmrg if (xlations->eventMask & ButtonReleaseMask) 1289444c061aSmrg xlations->eventMask |= ButtonPressMask; 1290444c061aSmrg 1291444c061aSmrg if (mappingNotifyInterest) { 1292444c061aSmrg XtPerDisplay pd = _XtGetPerDisplay(XtDisplay(widget)); 1293444c061aSmrg if (pd->mapping_callbacks) 1294444c061aSmrg _XtAddCallbackOnce(&(pd->mapping_callbacks), 1295444c061aSmrg DispatchMappingNotify, 1296444c061aSmrg (XtPointer)widget); 1297444c061aSmrg else 1298444c061aSmrg _XtAddCallback(&(pd->mapping_callbacks), 1299444c061aSmrg DispatchMappingNotify, 1300444c061aSmrg (XtPointer)widget); 1301444c061aSmrg 1302444c061aSmrg if (widget->core.destroy_callbacks != NULL) 1303444c061aSmrg _XtAddCallbackOnce( (InternalCallbackList *) 1304444c061aSmrg &widget->core.destroy_callbacks, 1305444c061aSmrg RemoveFromMappingCallbacks, 1306444c061aSmrg (XtPointer)widget 1307444c061aSmrg ); 1308444c061aSmrg else 1309444c061aSmrg _XtAddCallback((InternalCallbackList *) 1310444c061aSmrg &widget->core.destroy_callbacks, 1311444c061aSmrg RemoveFromMappingCallbacks, 1312444c061aSmrg (XtPointer)widget 1313444c061aSmrg ); 1314444c061aSmrg } 1315444c061aSmrg _XtBindActions(widget, (XtTM)&widget->core.tm); 1316444c061aSmrg _XtRegisterGrabs(widget); 1317444c061aSmrg} 1318444c061aSmrg 1319444c061aSmrgvoid _XtRemoveTranslations( 1320444c061aSmrg Widget widget) 1321444c061aSmrg{ 1322444c061aSmrg Cardinal i; 1323444c061aSmrg TMSimpleStateTree stateTree; 1324444c061aSmrg Boolean mappingNotifyInterest = False; 1325444c061aSmrg XtTranslations xlations = widget->core.tm.translations; 1326444c061aSmrg 1327444c061aSmrg if (xlations == NULL) 1328444c061aSmrg return; 1329444c061aSmrg 1330444c061aSmrg for (i = 0; 1331444c061aSmrg i < xlations->numStateTrees; 1332444c061aSmrg i++) 1333444c061aSmrg { 1334444c061aSmrg stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[i]; 1335444c061aSmrg mappingNotifyInterest |= stateTree->mappingNotifyInterest; 1336444c061aSmrg } 1337444c061aSmrg if (mappingNotifyInterest) 1338444c061aSmrg RemoveFromMappingCallbacks(widget, (XtPointer)widget, NULL); 1339444c061aSmrg} 1340444c061aSmrg 1341444c061aSmrgstatic void _XtUninstallTranslations( 1342444c061aSmrg Widget widget) 1343444c061aSmrg{ 1344444c061aSmrg XtTranslations xlations = widget->core.tm.translations; 1345444c061aSmrg 1346444c061aSmrg _XtUnbindActions(widget, 1347444c061aSmrg xlations, 1348444c061aSmrg (TMBindData)widget->core.tm.proc_table); 1349444c061aSmrg _XtRemoveTranslations(widget); 1350444c061aSmrg widget->core.tm.translations = NULL; 1351444c061aSmrg FreeContext((TMContext *)&widget->core.tm.current_state); 1352444c061aSmrg} 1353444c061aSmrg 1354444c061aSmrgvoid _XtDestroyTMData( 1355444c061aSmrg Widget widget) 1356444c061aSmrg{ 1357444c061aSmrg TMComplexBindData cBindData; 1358444c061aSmrg 1359444c061aSmrg _XtUninstallTranslations(widget); 1360444c061aSmrg 1361444c061aSmrg if ((cBindData = (TMComplexBindData)widget->core.tm.proc_table)) { 1362444c061aSmrg if (cBindData->isComplex) { 1363444c061aSmrg ATranslations aXlations, nXlations; 1364444c061aSmrg 1365444c061aSmrg nXlations = (ATranslations) cBindData->accel_context; 1366444c061aSmrg while (nXlations){ 1367444c061aSmrg aXlations = nXlations; 1368444c061aSmrg nXlations = nXlations->next; 1369444c061aSmrg XtFree((char *)aXlations); 1370444c061aSmrg } 1371444c061aSmrg } 1372444c061aSmrg XtFree((char *)cBindData); 1373444c061aSmrg } 1374444c061aSmrg} 1375444c061aSmrg 1376444c061aSmrg/*** Public procedures ***/ 1377444c061aSmrg 1378444c061aSmrg 1379444c061aSmrgvoid XtUninstallTranslations( 1380444c061aSmrg Widget widget) 1381444c061aSmrg{ 1382444c061aSmrg EventMask oldMask; 1383444c061aSmrg Widget hookobj; 1384444c061aSmrg WIDGET_TO_APPCON(widget); 1385444c061aSmrg 1386444c061aSmrg LOCK_APP(app); 1387444c061aSmrg if (! widget->core.tm.translations) { 1388444c061aSmrg UNLOCK_APP(app); 1389444c061aSmrg return; 1390444c061aSmrg } 1391444c061aSmrg oldMask = widget->core.tm.translations->eventMask; 1392444c061aSmrg _XtUninstallTranslations(widget); 1393444c061aSmrg if (XtIsRealized(widget) && oldMask) 1394444c061aSmrg XSelectInput(XtDisplay(widget), XtWindow(widget), 1395444c061aSmrg XtBuildEventMask(widget)); 1396444c061aSmrg hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 1397444c061aSmrg if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 1398444c061aSmrg XtChangeHookDataRec call_data; 1399444c061aSmrg 1400444c061aSmrg call_data.type = XtHuninstallTranslations; 1401444c061aSmrg call_data.widget = widget; 1402444c061aSmrg XtCallCallbackList(hookobj, 1403444c061aSmrg ((HookObject)hookobj)->hooks.changehook_callbacks, 1404444c061aSmrg (XtPointer)&call_data); 1405444c061aSmrg } 1406444c061aSmrg UNLOCK_APP(app); 1407444c061aSmrg} 1408444c061aSmrg 1409444c061aSmrgXtTranslations _XtCreateXlations( 1410444c061aSmrg TMStateTree *stateTrees, 1411444c061aSmrg TMShortCard numStateTrees, 1412444c061aSmrg XtTranslations first, 1413444c061aSmrg XtTranslations second) 1414444c061aSmrg{ 1415444c061aSmrg XtTranslations xlations; 1416444c061aSmrg TMShortCard i; 1417444c061aSmrg 1418444c061aSmrg xlations = (XtTranslations) 1419444c061aSmrg __XtMalloc(sizeof(TranslationData) + 1420444c061aSmrg (numStateTrees-1) * sizeof(TMStateTree)); 1421444c061aSmrg#ifdef TRACE_TM 1422444c061aSmrg LOCK_PROCESS; 1423444c061aSmrg if (_XtGlobalTM.numTms == _XtGlobalTM.tmTblSize) { 1424444c061aSmrg _XtGlobalTM.tmTblSize += 16; 1425444c061aSmrg _XtGlobalTM.tmTbl = (XtTranslations *) 1426444c061aSmrg XtRealloc((char *)_XtGlobalTM.tmTbl, 1427444c061aSmrg _XtGlobalTM.tmTblSize * sizeof(XtTranslations)); 1428444c061aSmrg } 1429444c061aSmrg _XtGlobalTM.tmTbl[_XtGlobalTM.numTms++] = xlations; 1430444c061aSmrg UNLOCK_PROCESS; 1431444c061aSmrg#endif /* TRACE_TM */ 1432444c061aSmrg 1433444c061aSmrg xlations->composers[0] = first; 1434444c061aSmrg xlations->composers[1] = second; 1435444c061aSmrg xlations->hasBindings = False; 1436444c061aSmrg xlations->operation = XtTableReplace; 1437444c061aSmrg 1438444c061aSmrg for (i = 0;i < numStateTrees; i++) 1439444c061aSmrg { 1440444c061aSmrg xlations->stateTreeTbl[i] = (TMStateTree) stateTrees[i]; 1441444c061aSmrg stateTrees[i]->simple.refCount++; 1442444c061aSmrg } 1443444c061aSmrg xlations->numStateTrees = numStateTrees; 1444444c061aSmrg xlations->eventMask = 0; 1445444c061aSmrg return xlations; 1446444c061aSmrg} 1447444c061aSmrg 1448444c061aSmrgTMStateTree _XtParseTreeToStateTree( 1449444c061aSmrg TMParseStateTree parseTree) 1450444c061aSmrg{ 1451444c061aSmrg TMSimpleStateTree simpleTree; 1452444c061aSmrg unsigned int tableSize; 1453444c061aSmrg 1454444c061aSmrg if (parseTree->numComplexBranchHeads) { 1455444c061aSmrg TMComplexStateTree complexTree; 1456444c061aSmrg 1457444c061aSmrg complexTree = XtNew(TMComplexStateTreeRec); 1458444c061aSmrg complexTree->isSimple = False; 1459444c061aSmrg tableSize = parseTree->numComplexBranchHeads * sizeof(StatePtr); 1460444c061aSmrg complexTree->complexBranchHeadTbl = (StatePtr *) 1461444c061aSmrg __XtMalloc(tableSize); 1462444c061aSmrg XtMemmove(complexTree->complexBranchHeadTbl, 1463444c061aSmrg parseTree->complexBranchHeadTbl, tableSize); 1464444c061aSmrg complexTree->numComplexBranchHeads = 1465444c061aSmrg parseTree->numComplexBranchHeads; 1466444c061aSmrg simpleTree = (TMSimpleStateTree)complexTree; 1467444c061aSmrg } 1468444c061aSmrg else { 1469444c061aSmrg simpleTree = XtNew(TMSimpleStateTreeRec); 1470444c061aSmrg simpleTree->isSimple = True; 1471444c061aSmrg } 1472444c061aSmrg simpleTree->isAccelerator = parseTree->isAccelerator; 1473444c061aSmrg simpleTree->refCount = 0; 1474444c061aSmrg simpleTree->mappingNotifyInterest = parseTree->mappingNotifyInterest; 1475444c061aSmrg 1476444c061aSmrg tableSize = parseTree->numBranchHeads * sizeof(TMBranchHeadRec); 1477444c061aSmrg simpleTree->branchHeadTbl = (TMBranchHead) 1478444c061aSmrg __XtMalloc(tableSize); 1479444c061aSmrg XtMemmove(simpleTree->branchHeadTbl, parseTree->branchHeadTbl, tableSize); 1480444c061aSmrg simpleTree->numBranchHeads = parseTree->numBranchHeads; 1481444c061aSmrg 1482444c061aSmrg tableSize = parseTree->numQuarks * sizeof(XrmQuark); 1483444c061aSmrg simpleTree->quarkTbl = (XrmQuark *) __XtMalloc(tableSize); 1484444c061aSmrg XtMemmove(simpleTree->quarkTbl, parseTree->quarkTbl, tableSize); 1485444c061aSmrg simpleTree->numQuarks = parseTree->numQuarks; 1486444c061aSmrg 1487444c061aSmrg return (TMStateTree)simpleTree; 1488444c061aSmrg} 1489444c061aSmrg 1490444c061aSmrgstatic void FreeActions( 1491444c061aSmrg ActionPtr actions) 1492444c061aSmrg{ 1493444c061aSmrg ActionPtr action; 1494444c061aSmrg TMShortCard i; 1495444c061aSmrg for (action = actions; action;) { 1496444c061aSmrg ActionPtr nextAction = action->next; 1497444c061aSmrg for (i = action->num_params; i;) { 1498444c061aSmrg XtFree( action->params[--i] ); 1499444c061aSmrg } 1500444c061aSmrg XtFree( (char*)action->params ); 1501444c061aSmrg XtFree((char*) action); 1502444c061aSmrg action = nextAction; 1503444c061aSmrg } 1504444c061aSmrg} 1505444c061aSmrg 1506444c061aSmrg/*ARGSUSED*/ 1507444c061aSmrgstatic void AmbigActions( 1508444c061aSmrg EventSeqPtr initialEvent, 1509444c061aSmrg StatePtr *state, 1510444c061aSmrg TMParseStateTree stateTree) 1511444c061aSmrg{ 1512444c061aSmrg String params[3]; 1513444c061aSmrg Cardinal numParams = 0; 1514444c061aSmrg 1515444c061aSmrg params[numParams++] = _XtPrintEventSeq(initialEvent, NULL); 1516444c061aSmrg params[numParams++] = _XtPrintActions((*state)->actions, 1517444c061aSmrg stateTree->quarkTbl); 1518444c061aSmrg XtWarningMsg (XtNtranslationError,"oldActions",XtCXtToolkitError, 1519444c061aSmrg "Previous entry was: %s %s", params, &numParams); 1520444c061aSmrg XtFree((char *)params[0]); 1521444c061aSmrg XtFree((char *)params[1]); 1522444c061aSmrg numParams = 0; 1523444c061aSmrg params[numParams++] = _XtPrintActions(initialEvent->actions, 1524444c061aSmrg stateTree->quarkTbl); 1525444c061aSmrg XtWarningMsg (XtNtranslationError,"newActions",XtCXtToolkitError, 1526444c061aSmrg "New actions are:%s", params, &numParams); 1527444c061aSmrg XtFree((char *)params[0]); 1528444c061aSmrg XtWarningMsg (XtNtranslationError,"ambiguousActions", 1529444c061aSmrg XtCXtToolkitError, 1530444c061aSmrg "Overriding earlier translation manager actions.", 1531444c061aSmrg (String *)NULL, (Cardinal *)NULL); 1532444c061aSmrg 1533444c061aSmrg FreeActions((*state)->actions); 1534444c061aSmrg (*state)->actions = NULL; 1535444c061aSmrg} 1536444c061aSmrg 1537444c061aSmrg 1538444c061aSmrgvoid _XtAddEventSeqToStateTree( 1539444c061aSmrg EventSeqPtr eventSeq, 1540444c061aSmrg TMParseStateTree stateTree) 1541444c061aSmrg{ 1542444c061aSmrg StatePtr *state; 1543444c061aSmrg EventSeqPtr initialEvent = eventSeq; 1544444c061aSmrg TMBranchHead branchHead; 1545444c061aSmrg TMShortCard idx, modIndex, typeIndex; 1546444c061aSmrg 1547444c061aSmrg if (eventSeq == NULL) return; 1548444c061aSmrg 1549444c061aSmrg /* note that all states in the event seq passed in start out null */ 1550444c061aSmrg /* we fill them in with the matching state as we traverse the list */ 1551444c061aSmrg 1552444c061aSmrg /* 1553444c061aSmrg * We need to free the parser data structures !!! 1554444c061aSmrg */ 1555444c061aSmrg 1556444c061aSmrg typeIndex = _XtGetTypeIndex(&eventSeq->event); 1557444c061aSmrg modIndex = _XtGetModifierIndex(&eventSeq->event); 1558444c061aSmrg idx = GetBranchHead(stateTree, typeIndex, modIndex, False); 1559444c061aSmrg branchHead = &stateTree->branchHeadTbl[idx]; 1560444c061aSmrg 1561444c061aSmrg /* 1562444c061aSmrg * Need to check for pre-existing actions with same lhs ||| 1563444c061aSmrg */ 1564444c061aSmrg 1565444c061aSmrg /* 1566444c061aSmrg * Check for optimized case. Don't assume that the eventSeq has actions. 1567444c061aSmrg */ 1568444c061aSmrg if (!eventSeq->next && 1569444c061aSmrg eventSeq->actions && 1570444c061aSmrg !eventSeq->actions->next && 1571444c061aSmrg !eventSeq->actions->num_params) 1572444c061aSmrg { 1573444c061aSmrg if (eventSeq->event.eventType == MappingNotify) 1574444c061aSmrg stateTree->mappingNotifyInterest = True; 1575444c061aSmrg branchHead->hasActions = True; 1576444c061aSmrg branchHead->more = eventSeq->actions->idx; 1577444c061aSmrg FreeActions(eventSeq->actions); 1578444c061aSmrg eventSeq->actions = NULL; 1579444c061aSmrg return; 1580444c061aSmrg } 1581444c061aSmrg 1582444c061aSmrg branchHead->isSimple = False; 1583444c061aSmrg if (!eventSeq->next) 1584444c061aSmrg branchHead->hasActions = True; 1585444c061aSmrg branchHead->more = GetComplexBranchIndex(stateTree, typeIndex, modIndex); 1586444c061aSmrg state = &stateTree->complexBranchHeadTbl[TMBranchMore(branchHead)]; 1587444c061aSmrg 1588444c061aSmrg for (;;) { 1589444c061aSmrg *state = NewState(stateTree, typeIndex, modIndex); 1590444c061aSmrg 1591444c061aSmrg if (eventSeq->event.eventType == MappingNotify) 1592444c061aSmrg stateTree->mappingNotifyInterest = True; 1593444c061aSmrg 1594444c061aSmrg /* *state now points at state record matching event */ 1595444c061aSmrg eventSeq->state = *state; 1596444c061aSmrg 1597444c061aSmrg if (eventSeq->actions != NULL) { 1598444c061aSmrg if ((*state)->actions != NULL) 1599444c061aSmrg AmbigActions(initialEvent, state, stateTree); 1600444c061aSmrg (*state)->actions = eventSeq->actions; 1601444c061aSmrg#ifdef TRACE_TM 1602444c061aSmrg LOCK_PROCESS 1603444c061aSmrg _XtGlobalTM.numComplexActions++; 1604444c061aSmrg UNLOCK_PROCESS; 1605444c061aSmrg#endif /* TRACE_TM */ 1606444c061aSmrg } 1607444c061aSmrg 1608444c061aSmrg if (((eventSeq = eventSeq->next) == NULL) || (eventSeq->state)) 1609444c061aSmrg break; 1610444c061aSmrg 1611444c061aSmrg state = &(*state)->nextLevel; 1612444c061aSmrg typeIndex = _XtGetTypeIndex(&eventSeq->event); 1613444c061aSmrg modIndex = _XtGetModifierIndex(&eventSeq->event); 1614444c061aSmrg LOCK_PROCESS; 1615444c061aSmrg if (!TMNewMatchSemantics()) { 1616444c061aSmrg /* 1617444c061aSmrg * force a potential empty entry into the branch head 1618444c061aSmrg * table in order to emulate old matching behavior 1619444c061aSmrg */ 1620444c061aSmrg (void) GetBranchHead(stateTree, typeIndex, modIndex, True); 1621444c061aSmrg } 1622444c061aSmrg UNLOCK_PROCESS; 1623444c061aSmrg } 1624444c061aSmrg 1625444c061aSmrg if (eventSeq && eventSeq->state) { 1626444c061aSmrg /* we've been here before... must be a cycle in the event seq. */ 1627444c061aSmrg branchHead->hasCycles = True; 1628444c061aSmrg (*state)->nextLevel = eventSeq->state; 1629444c061aSmrg eventSeq->state->isCycleStart = True; 1630444c061aSmrg (*state)->isCycleEnd = TRUE; 1631444c061aSmrg } 1632444c061aSmrg} 1633444c061aSmrg 1634444c061aSmrg 1635444c061aSmrg/* 1636444c061aSmrg * Internal Converter for merging. Old and New must both be valid xlations 1637444c061aSmrg */ 1638444c061aSmrg 1639444c061aSmrg/*ARGSUSED*/ 1640444c061aSmrgBoolean _XtCvtMergeTranslations( 1641444c061aSmrg Display *dpy, 1642444c061aSmrg XrmValuePtr args, 1643444c061aSmrg Cardinal *num_args, 1644444c061aSmrg XrmValuePtr from, 1645444c061aSmrg XrmValuePtr to, 1646444c061aSmrg XtPointer *closure_ret) 1647444c061aSmrg{ 1648444c061aSmrg XtTranslations first, second, xlations; 1649444c061aSmrg TMStateTree *stateTrees, stackStateTrees[16]; 1650444c061aSmrg TMShortCard numStateTrees, i; 1651444c061aSmrg 1652444c061aSmrg if (*num_args != 0) 1653444c061aSmrg XtWarningMsg("invalidParameters","mergeTranslations",XtCXtToolkitError, 1654444c061aSmrg "MergeTM to TranslationTable needs no extra arguments", 1655444c061aSmrg (String *)NULL, (Cardinal *)NULL); 1656444c061aSmrg 1657444c061aSmrg if (to->addr != NULL && to->size < sizeof(XtTranslations)) { 1658444c061aSmrg to->size = sizeof(XtTranslations); 1659444c061aSmrg return False; 1660444c061aSmrg } 1661444c061aSmrg 1662444c061aSmrg first = ((TMConvertRec*)from->addr)->old; 1663444c061aSmrg second = ((TMConvertRec*)from->addr)->new; 1664444c061aSmrg 1665444c061aSmrg numStateTrees = first->numStateTrees + second->numStateTrees; 1666444c061aSmrg 1667444c061aSmrg stateTrees = (TMStateTree *) 1668444c061aSmrg XtStackAlloc(numStateTrees * sizeof(TMStateTree), stackStateTrees); 1669444c061aSmrg 1670444c061aSmrg for (i = 0; i < first->numStateTrees; i++) 1671444c061aSmrg stateTrees[i] = first->stateTreeTbl[i]; 1672444c061aSmrg for (i = 0; i < second->numStateTrees; i++) 1673444c061aSmrg stateTrees[i + first->numStateTrees] = second->stateTreeTbl[i]; 1674444c061aSmrg 1675444c061aSmrg xlations = _XtCreateXlations(stateTrees, numStateTrees, first, second); 1676444c061aSmrg 1677444c061aSmrg if (to->addr != NULL) { 1678444c061aSmrg *(XtTranslations*)to->addr = xlations; 1679444c061aSmrg } 1680444c061aSmrg else { 1681444c061aSmrg static XtTranslations staticStateTable; 1682444c061aSmrg staticStateTable = xlations; 1683444c061aSmrg to->addr= (XPointer)&staticStateTable; 1684444c061aSmrg to->size = sizeof(XtTranslations); 1685444c061aSmrg } 1686444c061aSmrg 1687444c061aSmrg XtStackFree((XtPointer)stateTrees, (XtPointer)stackStateTrees); 1688444c061aSmrg return True; 1689444c061aSmrg} 1690444c061aSmrg 1691444c061aSmrg 1692444c061aSmrgstatic XtTranslations MergeThem( 1693444c061aSmrg Widget dest, 1694444c061aSmrg XtTranslations first, 1695444c061aSmrg XtTranslations second) 1696444c061aSmrg{ 1697444c061aSmrg XtCacheRef cache_ref; 1698444c061aSmrg static XrmQuark from_type = NULLQUARK, to_type; 1699444c061aSmrg XrmValue from, to; 1700444c061aSmrg TMConvertRec convert_rec; 1701444c061aSmrg XtTranslations newTable; 1702444c061aSmrg 1703444c061aSmrg LOCK_PROCESS; 1704444c061aSmrg if (from_type == NULLQUARK) { 1705444c061aSmrg from_type = XrmPermStringToQuark(_XtRStateTablePair); 1706444c061aSmrg to_type = XrmPermStringToQuark(XtRTranslationTable); 1707444c061aSmrg } 1708444c061aSmrg UNLOCK_PROCESS; 1709444c061aSmrg from.addr = (XPointer)&convert_rec; 1710444c061aSmrg from.size = sizeof(TMConvertRec); 1711444c061aSmrg to.addr = (XPointer)&newTable; 1712444c061aSmrg to.size = sizeof(XtTranslations); 1713444c061aSmrg convert_rec.old = first; 1714444c061aSmrg convert_rec.new = second; 1715444c061aSmrg 1716444c061aSmrg LOCK_PROCESS; 1717444c061aSmrg if (! _XtConvert(dest, from_type, &from, to_type, &to, &cache_ref)) { 1718444c061aSmrg UNLOCK_PROCESS; 1719444c061aSmrg return NULL; 1720444c061aSmrg } 1721444c061aSmrg UNLOCK_PROCESS; 1722444c061aSmrg 1723444c061aSmrg#ifndef REFCNT_TRANSLATIONS 1724444c061aSmrg 1725444c061aSmrg if (cache_ref) 1726444c061aSmrg XtAddCallback(dest, XtNdestroyCallback, 1727444c061aSmrg XtCallbackReleaseCacheRef, (XtPointer)cache_ref); 1728444c061aSmrg 1729444c061aSmrg#endif 1730444c061aSmrg 1731444c061aSmrg return newTable; 1732444c061aSmrg} 1733444c061aSmrg 1734444c061aSmrg/* 1735444c061aSmrg * Unmerge will recursively traverse the xlation compose tree and 1736444c061aSmrg * generate a new xlation that is the result of all instances of 1737444c061aSmrg * xlations being removed. It currently doesn't differentiate between 1738444c061aSmrg * the potential that an xlation will be both an accelerator and 1739444c061aSmrg * normal. This is not supported by the spec anyway. 1740444c061aSmrg */ 1741444c061aSmrgstatic XtTranslations UnmergeTranslations( 1742444c061aSmrg Widget widget, 1743444c061aSmrg XtTranslations xlations, 1744444c061aSmrg XtTranslations unmergeXlations, 1745444c061aSmrg TMShortCard currIndex, 1746444c061aSmrg TMComplexBindProcs oldBindings, 1747444c061aSmrg TMShortCard numOldBindings, 1748444c061aSmrg TMComplexBindProcs newBindings, 1749444c061aSmrg TMShortCard *numNewBindingsRtn) 1750444c061aSmrg 1751444c061aSmrg{ 1752444c061aSmrg XtTranslations first, second, result; 1753444c061aSmrg 1754444c061aSmrg if (!xlations || (xlations == unmergeXlations)) 1755444c061aSmrg return NULL; 1756444c061aSmrg 1757444c061aSmrg if (xlations->composers[0]) { 1758444c061aSmrg first = UnmergeTranslations(widget, xlations->composers[0], 1759444c061aSmrg unmergeXlations, currIndex, 1760444c061aSmrg oldBindings, numOldBindings, 1761444c061aSmrg newBindings, numNewBindingsRtn); 1762444c061aSmrg } 1763444c061aSmrg else 1764444c061aSmrg first = NULL; 1765444c061aSmrg 1766444c061aSmrg if (xlations->composers[1]) { 1767444c061aSmrg second = UnmergeTranslations(widget, xlations->composers[1], 1768444c061aSmrg unmergeXlations, 1769444c061aSmrg currIndex + 1770444c061aSmrg xlations->composers[0]->numStateTrees, 1771444c061aSmrg oldBindings, numOldBindings, 1772444c061aSmrg newBindings, numNewBindingsRtn); 1773444c061aSmrg } 1774444c061aSmrg else 1775444c061aSmrg second = NULL; 1776444c061aSmrg 1777444c061aSmrg if (first || second) { 1778444c061aSmrg if (first && second) { 1779444c061aSmrg if ((first != xlations->composers[0]) || 1780444c061aSmrg (second != xlations->composers[1])) 1781444c061aSmrg result = MergeThem(widget, first, second); 1782444c061aSmrg else result = xlations; 1783444c061aSmrg } 1784444c061aSmrg else { 1785444c061aSmrg if (first) 1786444c061aSmrg result = first; 1787444c061aSmrg else 1788444c061aSmrg result = second; 1789444c061aSmrg } 1790444c061aSmrg } else { /* only update for leaf nodes */ 1791444c061aSmrg if (numOldBindings) { 1792444c061aSmrg Cardinal i; 1793444c061aSmrg for (i = 0; i < xlations->numStateTrees; i++) { 1794444c061aSmrg if (xlations->stateTreeTbl[i]->simple.isAccelerator) 1795444c061aSmrg newBindings[*numNewBindingsRtn] = 1796444c061aSmrg oldBindings[currIndex + i]; 1797444c061aSmrg (*numNewBindingsRtn)++; 1798444c061aSmrg } 1799444c061aSmrg } 1800444c061aSmrg result = xlations; 1801444c061aSmrg } 1802444c061aSmrg return result; 1803444c061aSmrg} 1804444c061aSmrg 1805444c061aSmrgtypedef struct { 1806444c061aSmrg XtTranslations xlations; 1807444c061aSmrg TMComplexBindProcs bindings; 1808444c061aSmrg}MergeBindRec, *MergeBind; 1809444c061aSmrg 1810444c061aSmrgstatic XtTranslations MergeTranslations( 1811444c061aSmrg Widget widget, 1812444c061aSmrg XtTranslations oldXlations, 1813444c061aSmrg XtTranslations newXlations, 1814444c061aSmrg _XtTranslateOp operation, 1815444c061aSmrg Widget source, 1816444c061aSmrg TMComplexBindProcs oldBindings, 1817444c061aSmrg TMComplexBindProcs newBindings, 1818444c061aSmrg TMShortCard *numNewRtn) 1819444c061aSmrg{ 1820444c061aSmrg XtTranslations newTable = NULL, xlations; 1821444c061aSmrg TMComplexBindProcs bindings; 1822444c061aSmrg TMShortCard i, j; 1823444c061aSmrg TMStateTree *treePtr; 1824444c061aSmrg TMShortCard numNew = *numNewRtn; 1825444c061aSmrg MergeBindRec bindPair[2]; 1826444c061aSmrg 1827444c061aSmrg /* If the new translation has an accelerator context then pull it 1828444c061aSmrg * off and pass it and the real xlations in to the caching merge 1829444c061aSmrg * routine. 1830444c061aSmrg */ 1831444c061aSmrg if (newXlations->hasBindings) { 1832444c061aSmrg xlations = ((ATranslations) newXlations)->xlations; 1833444c061aSmrg bindings = (TMComplexBindProcs) 1834444c061aSmrg &((ATranslations) newXlations)->bindTbl[0]; 1835444c061aSmrg } 1836444c061aSmrg else { 1837444c061aSmrg xlations = newXlations; 1838444c061aSmrg bindings = NULL; 1839444c061aSmrg } 1840444c061aSmrg switch(operation) { 1841444c061aSmrg case XtTableReplace: 1842444c061aSmrg newTable = bindPair[0].xlations = xlations; 1843444c061aSmrg bindPair[0].bindings = bindings; 1844444c061aSmrg bindPair[1].xlations = NULL; 1845444c061aSmrg bindPair[1].bindings = NULL; 1846444c061aSmrg break; 1847444c061aSmrg case XtTableAugment: 1848444c061aSmrg bindPair[0].xlations = oldXlations; 1849444c061aSmrg bindPair[0].bindings = oldBindings; 1850444c061aSmrg bindPair[1].xlations = xlations; 1851444c061aSmrg bindPair[1].bindings = bindings; 1852444c061aSmrg newTable = NULL; 1853444c061aSmrg break; 1854444c061aSmrg case XtTableOverride: 1855444c061aSmrg bindPair[0].xlations = xlations; 1856444c061aSmrg bindPair[0].bindings = bindings; 1857444c061aSmrg bindPair[1].xlations = oldXlations; 1858444c061aSmrg bindPair[1].bindings = oldBindings; 1859444c061aSmrg newTable = NULL; 1860444c061aSmrg break; 1861444c061aSmrg } 1862444c061aSmrg if (!newTable) 1863444c061aSmrg newTable = MergeThem(widget, bindPair[0].xlations, bindPair[1].xlations); 1864444c061aSmrg 1865444c061aSmrg for (i = 0, numNew = 0; i < 2; i++) { 1866444c061aSmrg if (bindPair[i].xlations) 1867444c061aSmrg for (j = 0; j < bindPair[i].xlations->numStateTrees; j++, numNew++) { 1868444c061aSmrg if (bindPair[i].xlations->stateTreeTbl[j]->simple.isAccelerator) { 1869444c061aSmrg if (bindPair[i].bindings) 1870444c061aSmrg newBindings[numNew] = bindPair[i].bindings[j]; 1871444c061aSmrg else { 1872444c061aSmrg newBindings[numNew].widget = source; 1873444c061aSmrg newBindings[numNew].aXlations = 1874444c061aSmrg bindPair[i].xlations; 1875444c061aSmrg } 1876444c061aSmrg } 1877444c061aSmrg } 1878444c061aSmrg } 1879444c061aSmrg *numNewRtn = numNew; 1880444c061aSmrg treePtr = &newTable->stateTreeTbl[0]; 1881444c061aSmrg for (i = 0; i < newTable->numStateTrees; i++, treePtr++) 1882444c061aSmrg (*treePtr)->simple.refCount++; 1883444c061aSmrg return newTable; 1884444c061aSmrg} 1885444c061aSmrg 1886444c061aSmrgstatic TMBindData MakeBindData( 1887444c061aSmrg TMComplexBindProcs bindings, 1888444c061aSmrg TMShortCard numBindings, 1889444c061aSmrg TMBindData oldBindData) 1890444c061aSmrg{ 1891444c061aSmrg TMLongCard bytes; 1892444c061aSmrg TMShortCard i; 1893444c061aSmrg Boolean isComplex; 1894444c061aSmrg TMBindData bindData; 1895444c061aSmrg 1896444c061aSmrg if (numBindings == 0) 1897444c061aSmrg return NULL; 1898444c061aSmrg for (i = 0; i < numBindings; i++) 1899444c061aSmrg if (bindings[i].widget) 1900444c061aSmrg break; 1901444c061aSmrg isComplex = (i < numBindings); 1902444c061aSmrg if (isComplex) 1903444c061aSmrg bytes = (sizeof(TMComplexBindDataRec) + 1904444c061aSmrg ((numBindings - 1) * 1905444c061aSmrg sizeof(TMComplexBindProcsRec))); 1906444c061aSmrg else 1907444c061aSmrg bytes = (sizeof(TMSimpleBindDataRec) + 1908444c061aSmrg ((numBindings - 1) * 1909444c061aSmrg sizeof(TMSimpleBindProcsRec))); 1910444c061aSmrg 1911444c061aSmrg bindData = (TMBindData) __XtCalloc(sizeof(char), bytes); 1912444c061aSmrg bindData->simple.isComplex = isComplex; 1913444c061aSmrg if (isComplex) { 1914444c061aSmrg TMComplexBindData cBindData = (TMComplexBindData)bindData; 1915444c061aSmrg /* 1916444c061aSmrg * If there were any accelerator contexts in the old bindData 1917444c061aSmrg * then propagate them to the new one. 1918444c061aSmrg */ 1919444c061aSmrg if (oldBindData && oldBindData->simple.isComplex) 1920444c061aSmrg cBindData->accel_context = 1921444c061aSmrg ((TMComplexBindData) oldBindData)->accel_context; 1922444c061aSmrg XtMemmove((char *)&cBindData->bindTbl[0], (char *)bindings, 1923444c061aSmrg numBindings * sizeof(TMComplexBindProcsRec)); 1924444c061aSmrg } 1925444c061aSmrg return bindData; 1926444c061aSmrg} 1927444c061aSmrg 1928444c061aSmrg/* 1929444c061aSmrg * This routine is the central clearinghouse for merging translations 1930444c061aSmrg * into a widget. It takes care of preping the action bindings for 1931444c061aSmrg * realize time and calling the converter or doing a straight merge if 1932444c061aSmrg * the destination is empty. 1933444c061aSmrg */ 1934444c061aSmrgstatic Boolean ComposeTranslations( 1935444c061aSmrg Widget dest, 1936444c061aSmrg _XtTranslateOp operation, 1937444c061aSmrg Widget source, 1938444c061aSmrg XtTranslations newXlations) 1939444c061aSmrg{ 1940444c061aSmrg XtTranslations newTable, oldXlations; 1941444c061aSmrg XtTranslations accNewXlations; 1942444c061aSmrg EventMask oldMask = 0; 1943444c061aSmrg TMBindData bindData; 1944444c061aSmrg TMComplexBindProcs oldBindings = NULL; 1945444c061aSmrg TMShortCard numOldBindings = 0, numNewBindings = 0, numBytes; 1946444c061aSmrg TMComplexBindProcsRec stackBindings[16], *newBindings; 1947444c061aSmrg 1948444c061aSmrg /* 1949444c061aSmrg * how should we be handling the refcount decrement for the 1950444c061aSmrg * replaced translation table ??? 1951444c061aSmrg */ 1952444c061aSmrg if (!newXlations) 1953444c061aSmrg { 1954444c061aSmrg XtAppWarningMsg(XtWidgetToApplicationContext(dest), 1955444c061aSmrg XtNtranslationError,"nullTable",XtCXtToolkitError, 1956444c061aSmrg "table to (un)merge must not be null", 1957444c061aSmrg (String *)NULL, (Cardinal *)NULL); 1958444c061aSmrg return False; 1959444c061aSmrg } 1960444c061aSmrg 1961444c061aSmrg accNewXlations = newXlations; 1962444c061aSmrg newXlations = ((newXlations->hasBindings) 1963444c061aSmrg ? ((ATranslations)newXlations)->xlations 1964444c061aSmrg : newXlations); 1965444c061aSmrg 1966444c061aSmrg if (!(oldXlations = dest->core.tm.translations)) 1967444c061aSmrg operation = XtTableReplace; 1968444c061aSmrg 1969444c061aSmrg /* 1970444c061aSmrg * try to avoid generation of duplicate state trees. If the source 1971444c061aSmrg * isn't simple (1 state Tree) then it's too much hassle 1972444c061aSmrg */ 1973444c061aSmrg if (((operation == XtTableAugment) || 1974444c061aSmrg (operation == XtTableOverride)) && 1975444c061aSmrg (newXlations->numStateTrees == 1)) { 1976444c061aSmrg Cardinal i; 1977444c061aSmrg for (i = 0; i < oldXlations->numStateTrees; i++) 1978444c061aSmrg if (oldXlations->stateTreeTbl[i] == 1979444c061aSmrg newXlations->stateTreeTbl[0]) 1980444c061aSmrg break; 1981444c061aSmrg if (i < oldXlations->numStateTrees) { 1982444c061aSmrg if (operation == XtTableAugment) { 1983444c061aSmrg /* 1984444c061aSmrg * we don't need to do anything since it's already 1985444c061aSmrg * there 1986444c061aSmrg */ 1987444c061aSmrg return True; 1988444c061aSmrg } 1989444c061aSmrg else {/* operation == XtTableOverride */ 1990444c061aSmrg /* 1991444c061aSmrg * We'll get rid of the duplicate trees throughout the 1992444c061aSmrg * and leave it with a pruned translation table. This 1993444c061aSmrg * will only work if the same table has been merged 1994444c061aSmrg * into this table (or one of it's composers 1995444c061aSmrg */ 1996444c061aSmrg _XtUnmergeTranslations(dest, newXlations); 1997444c061aSmrg /* 1998444c061aSmrg * reset oldXlations so we're back in sync 1999444c061aSmrg */ 2000444c061aSmrg if (!(oldXlations = dest->core.tm.translations)) 2001444c061aSmrg operation = XtTableReplace; 2002444c061aSmrg } 2003444c061aSmrg } 2004444c061aSmrg } 2005444c061aSmrg 2006444c061aSmrg bindData = (TMBindData) dest->core.tm.proc_table; 2007444c061aSmrg if (bindData) { 2008444c061aSmrg numOldBindings = (oldXlations ? oldXlations->numStateTrees : 0); 2009444c061aSmrg if (bindData->simple.isComplex) 2010444c061aSmrg oldBindings = &((TMComplexBindData)bindData)->bindTbl[0]; 2011444c061aSmrg else 2012444c061aSmrg oldBindings = (TMComplexBindProcs) 2013444c061aSmrg (&((TMSimpleBindData)bindData)->bindTbl[0]); 2014444c061aSmrg } 2015444c061aSmrg 2016444c061aSmrg numBytes =(((oldXlations ? oldXlations->numStateTrees : 0) 2017444c061aSmrg + newXlations->numStateTrees) * sizeof(TMComplexBindProcsRec)); 2018444c061aSmrg newBindings = (TMComplexBindProcs) XtStackAlloc(numBytes, stackBindings); 2019444c061aSmrg XtBZero((char *)newBindings, numBytes); 2020444c061aSmrg 2021444c061aSmrg if (operation == XtTableUnmerge) { 2022444c061aSmrg newTable = UnmergeTranslations(dest, 2023444c061aSmrg oldXlations, 2024444c061aSmrg newXlations, 2025444c061aSmrg 0, 2026444c061aSmrg oldBindings, numOldBindings, 2027444c061aSmrg newBindings, &numNewBindings); 2028444c061aSmrg#ifdef DEBUG 2029444c061aSmrg /* check for no match for unmerge */ 2030444c061aSmrg if (newTable == oldXlations) { 2031444c061aSmrg XtWarning("attempt to unmerge invalid table"); 2032444c061aSmrg XtStackFree((char *)newBindings, (char *)stackBindings); 2033444c061aSmrg return(newTable != NULL); 2034444c061aSmrg } 2035444c061aSmrg#endif /* DEBUG */ 2036444c061aSmrg } 2037444c061aSmrg else { 2038444c061aSmrg newTable = MergeTranslations(dest, 2039444c061aSmrg oldXlations, 2040444c061aSmrg accNewXlations, 2041444c061aSmrg operation, 2042444c061aSmrg source, 2043444c061aSmrg oldBindings, 2044444c061aSmrg newBindings, 2045444c061aSmrg &numNewBindings); 2046444c061aSmrg } 2047444c061aSmrg if (XtIsRealized(dest)) { 2048444c061aSmrg oldMask = 0; 2049444c061aSmrg if (oldXlations) 2050444c061aSmrg oldMask = oldXlations->eventMask; 2051444c061aSmrg _XtUninstallTranslations(dest); 2052444c061aSmrg } 2053444c061aSmrg 2054444c061aSmrg dest->core.tm.proc_table = 2055444c061aSmrg (XtActionProc *) MakeBindData(newBindings, numNewBindings, bindData); 2056444c061aSmrg 2057444c061aSmrg if (bindData) XtFree((char *)bindData); 2058444c061aSmrg 2059444c061aSmrg dest->core.tm.translations = newTable; 2060444c061aSmrg 2061444c061aSmrg if (XtIsRealized(dest)) { 2062444c061aSmrg EventMask mask = 0; 2063444c061aSmrg _XtInstallTranslations(dest); 2064444c061aSmrg if (newTable) 2065444c061aSmrg mask = newTable->eventMask; 2066444c061aSmrg if (mask != oldMask) 2067444c061aSmrg XSelectInput(XtDisplay(dest), XtWindow(dest), 2068444c061aSmrg XtBuildEventMask(dest)); 2069444c061aSmrg } 2070444c061aSmrg XtStackFree((XtPointer)newBindings, (XtPointer)stackBindings); 2071444c061aSmrg return(newTable != NULL); 2072444c061aSmrg} 2073444c061aSmrg 2074444c061aSmrg/* 2075444c061aSmrg * If a GetValues is done on a translation resource that contains 2076444c061aSmrg * accelerators we need to return the accelerator context in addition 2077444c061aSmrg * to the pure translations. Since this means returning memory that 2078444c061aSmrg * the client controlls but we still own, we will track the "headers" 2079444c061aSmrg * that we return (via a linked list pointed to from the bindData) and 2080444c061aSmrg * free it at destroy time. 2081444c061aSmrg */ 2082444c061aSmrgXtTranslations _XtGetTranslationValue( 2083444c061aSmrg Widget w) 2084444c061aSmrg{ 2085444c061aSmrg XtTM tmRecPtr = (XtTM) &w->core.tm; 2086444c061aSmrg ATranslations *aXlationsPtr; 2087444c061aSmrg TMComplexBindData cBindData = (TMComplexBindData) tmRecPtr->proc_table; 2088444c061aSmrg XtTranslations xlations = tmRecPtr->translations; 2089444c061aSmrg 2090444c061aSmrg if (!xlations || !cBindData || !cBindData->isComplex) 2091444c061aSmrg return xlations; 2092444c061aSmrg 2093444c061aSmrg /* Walk the list looking to see if we already have generated a 2094444c061aSmrg * header for the currently installed translations. If we have, 2095444c061aSmrg * just return that header. Otherwise create a new header. 2096444c061aSmrg */ 2097444c061aSmrg for (aXlationsPtr = (ATranslations *) &cBindData->accel_context; 2098444c061aSmrg *aXlationsPtr && (*aXlationsPtr)->xlations != xlations; 2099444c061aSmrg aXlationsPtr = &(*aXlationsPtr)->next) 2100444c061aSmrg ; 2101444c061aSmrg if (*aXlationsPtr) 2102444c061aSmrg return (XtTranslations) *aXlationsPtr; 2103444c061aSmrg else { 2104444c061aSmrg /* create a new aXlations context */ 2105444c061aSmrg ATranslations aXlations; 2106444c061aSmrg Cardinal numBindings = xlations->numStateTrees; 2107444c061aSmrg 2108444c061aSmrg (*aXlationsPtr) = aXlations = (ATranslations) 2109444c061aSmrg __XtMalloc(sizeof(ATranslationData) + 2110444c061aSmrg (numBindings - 1) * sizeof(TMComplexBindProcsRec)); 2111444c061aSmrg 2112444c061aSmrg aXlations->hasBindings = True; 2113444c061aSmrg aXlations->xlations = xlations; 2114444c061aSmrg aXlations->next = NULL; 2115444c061aSmrg XtMemmove((char *) &aXlations->bindTbl[0], 2116444c061aSmrg (char *) &cBindData->bindTbl[0], 2117444c061aSmrg numBindings * sizeof(TMComplexBindProcsRec)); 2118444c061aSmrg return (XtTranslations) aXlations; 2119444c061aSmrg } 2120444c061aSmrg} 2121444c061aSmrg 2122444c061aSmrg 2123444c061aSmrg/*ARGSUSED*/ 2124444c061aSmrgstatic void RemoveStateTree( 2125444c061aSmrg TMStateTree tree) 2126444c061aSmrg{ 2127444c061aSmrg#ifdef REFCNT_TRANSLATIONS 2128444c061aSmrg TMComplexStateTree stateTree = (TMComplexStateTree)tree; 2129444c061aSmrg 2130444c061aSmrg if (--stateTree->refCount == 0) { 2131444c061aSmrg /* 2132444c061aSmrg * should we free/refcount the match recs ? 2133444c061aSmrg */ 2134444c061aSmrg if (!stateTree->isSimple) { 2135444c061aSmrg StatePtr currState, nextState; 2136444c061aSmrg TMShortCard i; 2137444c061aSmrg for (i = 0; i < stateTree->numComplexBranchHeads; i++) { 2138444c061aSmrg currState = 2139444c061aSmrg nextState = 2140444c061aSmrg stateTree->complexBranchHeadTbl[i]; 2141444c061aSmrg for (; nextState;){ 2142444c061aSmrg FreeActions(currState->actions); 2143444c061aSmrg currState->actions = NULL; 2144444c061aSmrg if (!currState->isCycleEnd) 2145444c061aSmrg nextState = currState->nextLevel; 2146444c061aSmrg else 2147444c061aSmrg nextState = NULL; 2148444c061aSmrg XtFree( (char*)currState ); 2149444c061aSmrg } 2150444c061aSmrg } 2151444c061aSmrg XtFree((char*)stateTree->complexBranchHeadTbl); 2152444c061aSmrg } 2153444c061aSmrg XtFree((char*)stateTree->branchHeadTbl); 2154444c061aSmrg XtFree((char*)stateTree); 2155444c061aSmrg } 2156444c061aSmrg#endif /* REFCNT_TRANSLATIONS */ 2157444c061aSmrg} 2158444c061aSmrg 2159444c061aSmrgvoid _XtRemoveStateTreeByIndex( 2160444c061aSmrg XtTranslations xlations, 2161444c061aSmrg TMShortCard i) 2162444c061aSmrg{ 2163444c061aSmrg TMStateTree *stateTrees = xlations->stateTreeTbl; 2164444c061aSmrg 2165444c061aSmrg RemoveStateTree(stateTrees[i]); 2166444c061aSmrg xlations->numStateTrees--; 2167444c061aSmrg 2168444c061aSmrg for (; i < xlations->numStateTrees; i++) 2169444c061aSmrg { 2170444c061aSmrg stateTrees[i] = stateTrees[i+1]; 2171444c061aSmrg } 2172444c061aSmrg} 2173444c061aSmrg 2174444c061aSmrg/* ARGSUSED */ 2175444c061aSmrgvoid _XtFreeTranslations( 2176444c061aSmrg XtAppContext app, 2177444c061aSmrg XrmValuePtr toVal, 2178444c061aSmrg XtPointer closure, 2179444c061aSmrg XrmValuePtr args, 2180444c061aSmrg Cardinal *num_args) 2181444c061aSmrg{ 2182444c061aSmrg XtTranslations xlations; 2183444c061aSmrg int i; 2184444c061aSmrg 2185444c061aSmrg if (*num_args != 0) 2186444c061aSmrg XtAppWarningMsg(app, 2187444c061aSmrg "invalidParameters","freeTranslations",XtCXtToolkitError, 2188444c061aSmrg "Freeing XtTranslations requires no extra arguments", 2189444c061aSmrg (String *)NULL, (Cardinal *)NULL); 2190444c061aSmrg 2191444c061aSmrg xlations = *(XtTranslations*)toVal->addr; 2192444c061aSmrg for (i = 0; i < (int)xlations->numStateTrees; i++) 2193444c061aSmrg RemoveStateTree(xlations->stateTreeTbl[i]); 2194444c061aSmrg XtFree((char *)xlations); 2195444c061aSmrg} 2196444c061aSmrg 2197444c061aSmrg/* The spec is not clear on when actions specified in accelerators are bound; 2198444c061aSmrg * Bind them at Realize the same as translations 2199444c061aSmrg */ 2200444c061aSmrgvoid XtInstallAccelerators( 2201444c061aSmrg Widget destination, Widget source) 2202444c061aSmrg{ 2203444c061aSmrg XtTranslations aXlations; 2204444c061aSmrg _XtTranslateOp op; 2205444c061aSmrg String buf; 2206444c061aSmrg WIDGET_TO_APPCON(destination); 2207444c061aSmrg 2208444c061aSmrg /* 2209444c061aSmrg * test that it was parsed as an accelarator table. Even though 2210444c061aSmrg * there doesn't need to be a distinction it makes life easier if 2211444c061aSmrg * we honor the spec implication that aXlations is an accelerator 2212444c061aSmrg */ 2213444c061aSmrg LOCK_APP(app); 2214444c061aSmrg LOCK_PROCESS; 2215444c061aSmrg if ((!XtIsWidget(source)) || 2216444c061aSmrg ((aXlations = source->core.accelerators) == NULL) || 2217444c061aSmrg (aXlations->stateTreeTbl[0]->simple.isAccelerator == False)) { 2218444c061aSmrg UNLOCK_PROCESS; 2219444c061aSmrg UNLOCK_APP(app); 2220444c061aSmrg return; 2221444c061aSmrg } 2222444c061aSmrg 2223444c061aSmrg aXlations = source->core.accelerators; 2224444c061aSmrg op = aXlations->operation; 2225444c061aSmrg 2226444c061aSmrg if (ComposeTranslations(destination, op, source, aXlations) && 2227444c061aSmrg (XtClass(source)->core_class.display_accelerator != NULL)) { 2228444c061aSmrg 2229444c061aSmrg buf = _XtPrintXlations(destination, aXlations, source, False); 2230444c061aSmrg (*(XtClass(source)->core_class.display_accelerator))(source,buf); 2231444c061aSmrg XtFree(buf); 2232444c061aSmrg } 2233444c061aSmrg UNLOCK_PROCESS; 2234444c061aSmrg UNLOCK_APP(app); 2235444c061aSmrg} 2236444c061aSmrg 2237444c061aSmrgvoid XtInstallAllAccelerators( 2238444c061aSmrg Widget destination, 2239444c061aSmrg Widget source) 2240444c061aSmrg{ 2241444c061aSmrg Cardinal i; 2242444c061aSmrg CompositeWidget cw; 2243444c061aSmrg WIDGET_TO_APPCON(destination); 2244444c061aSmrg 2245444c061aSmrg /* Recurse down normal children */ 2246444c061aSmrg LOCK_APP(app); 2247444c061aSmrg LOCK_PROCESS; 2248444c061aSmrg if (XtIsComposite(source)) { 2249444c061aSmrg cw = (CompositeWidget) source; 2250444c061aSmrg for (i = 0; i < cw->composite.num_children; i++) { 2251444c061aSmrg XtInstallAllAccelerators(destination,cw->composite.children[i]); 2252444c061aSmrg } 2253444c061aSmrg } 2254444c061aSmrg 2255444c061aSmrg /* Recurse down popup children */ 2256444c061aSmrg if (XtIsWidget(source)) { 2257444c061aSmrg for (i = 0; i < source->core.num_popups; i++) { 2258444c061aSmrg XtInstallAllAccelerators(destination,source->core.popup_list[i]); 2259444c061aSmrg } 2260444c061aSmrg } 2261444c061aSmrg /* Finally, apply procedure to this widget */ 2262444c061aSmrg XtInstallAccelerators(destination,source); 2263444c061aSmrg UNLOCK_PROCESS; 2264444c061aSmrg UNLOCK_APP(app); 2265444c061aSmrg} 2266444c061aSmrg 2267444c061aSmrg#if 0 /* dead code */ 2268444c061aSmrgstatic _XtTranslateOp _XtGetTMOperation( 2269444c061aSmrg XtTranslations xlations) 2270444c061aSmrg{ 2271444c061aSmrg return ((xlations->hasBindings) 2272444c061aSmrg ? ((ATranslations)xlations)->xlations->operation 2273444c061aSmrg : xlations->operation); 2274444c061aSmrg} 2275444c061aSmrg#endif 2276444c061aSmrg 2277444c061aSmrgvoid XtAugmentTranslations( 2278444c061aSmrg Widget widget, 2279444c061aSmrg XtTranslations new) 2280444c061aSmrg{ 2281444c061aSmrg Widget hookobj; 2282444c061aSmrg WIDGET_TO_APPCON(widget); 2283444c061aSmrg 2284444c061aSmrg LOCK_APP(app); 2285444c061aSmrg LOCK_PROCESS; 2286444c061aSmrg (void)ComposeTranslations(widget, XtTableAugment, (Widget)NULL, new); 2287444c061aSmrg hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 2288444c061aSmrg if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 2289444c061aSmrg XtChangeHookDataRec call_data; 2290444c061aSmrg 2291444c061aSmrg call_data.type = XtHaugmentTranslations; 2292444c061aSmrg call_data.widget = widget; 2293444c061aSmrg XtCallCallbackList(hookobj, 2294444c061aSmrg ((HookObject)hookobj)->hooks.changehook_callbacks, 2295444c061aSmrg (XtPointer)&call_data); 2296444c061aSmrg } 2297444c061aSmrg UNLOCK_PROCESS; 2298444c061aSmrg UNLOCK_APP(app); 2299444c061aSmrg} 2300444c061aSmrg 2301444c061aSmrgvoid XtOverrideTranslations( 2302444c061aSmrg Widget widget, 2303444c061aSmrg XtTranslations new) 2304444c061aSmrg{ 2305444c061aSmrg Widget hookobj; 2306444c061aSmrg WIDGET_TO_APPCON(widget); 2307444c061aSmrg 2308444c061aSmrg LOCK_APP(app); 2309444c061aSmrg LOCK_PROCESS; 2310444c061aSmrg (void) ComposeTranslations(widget, XtTableOverride, (Widget)NULL, new); 2311444c061aSmrg hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 2312444c061aSmrg if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 2313444c061aSmrg XtChangeHookDataRec call_data; 2314444c061aSmrg 2315444c061aSmrg call_data.type = XtHoverrideTranslations; 2316444c061aSmrg call_data.widget = widget; 2317444c061aSmrg XtCallCallbackList(hookobj, 2318444c061aSmrg ((HookObject)hookobj)->hooks.changehook_callbacks, 2319444c061aSmrg (XtPointer)&call_data); 2320444c061aSmrg } 2321444c061aSmrg UNLOCK_PROCESS; 2322444c061aSmrg UNLOCK_APP(app); 2323444c061aSmrg} 2324444c061aSmrg 2325444c061aSmrgvoid _XtMergeTranslations( 2326444c061aSmrg Widget widget, 2327444c061aSmrg XtTranslations newXlations, 2328444c061aSmrg _XtTranslateOp op) 2329444c061aSmrg{ 2330444c061aSmrg if (!newXlations){ 2331444c061aSmrg if (!widget->core.tm.translations) 2332444c061aSmrg return; 2333444c061aSmrg else { 2334444c061aSmrg newXlations = widget->core.tm.translations; 2335444c061aSmrg widget->core.tm.translations = NULL; 2336444c061aSmrg } 2337444c061aSmrg } 2338444c061aSmrg (void) ComposeTranslations(widget, 2339444c061aSmrg op, 2340444c061aSmrg (Widget)NULL, 2341444c061aSmrg newXlations); 2342444c061aSmrg} 2343444c061aSmrg 2344444c061aSmrgvoid _XtUnmergeTranslations( 2345444c061aSmrg Widget widget, 2346444c061aSmrg XtTranslations xlations) 2347444c061aSmrg{ 2348444c061aSmrg ComposeTranslations(widget, XtTableUnmerge, (Widget)NULL, xlations); 2349444c061aSmrg} 2350