Bug Summary

File:TMstate.c
Location:line 2319, column 32
Description:Dereference of null pointer

Annotated Source Code

1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a
5copy of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation
7the rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice (including the next
12paragraph) shall be included in all copies or substantial portions of the
13Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25 All Rights Reserved
26
27Permission to use, copy, modify, and distribute this software and its
28documentation for any purpose and without fee is hereby granted,
29provided that the above copyright notice appear in all copies and that
30both that copyright notice and this permission notice appear in
31supporting documentation, and that the name of Digital not be
32used in advertising or publicity pertaining to distribution of the
33software without specific, written prior permission.
34
35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41SOFTWARE.
42
43******************************************************************/
44
45/*
46
47Copyright 1987, 1988, 1994, 1998 The Open Group
48
49Permission to use, copy, modify, distribute, and sell this software and its
50documentation for any purpose is hereby granted without fee, provided that
51the above copyright notice appear in all copies and that both that
52copyright notice and this permission notice appear in supporting
53documentation.
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65Except as contained in this notice, the name of The Open Group shall not be
66used in advertising or otherwise to promote the sale, use or other dealings
67in this Software without prior written authorization from The Open Group.
68
69*/
70
71/* TMstate.c -- maintains the state table of actions for the translation
72 * manager.
73 */
74/*LINTLIBRARY*/
75
76#ifdef HAVE_CONFIG_H1
77#include <config.h>
78#endif
79#include "IntrinsicI.h"
80
81#ifndef TM_NO_MATCH(-2)
82#define TM_NO_MATCH(-2) (-2)
83#endif /* TM_NO_MATCH */
84
85/* forward definitions */
86static StatePtr NewState(TMParseStateTree, TMShortCard, TMShortCard);
87
88
89static String XtNtranslationError = "translationError";
90
91#ifndef __EMX__
92TMGlobalRec _XtGlobalTM; /* initialized to zero K&R */
93#else
94TMGlobalRec _XtGlobalTM = {0};
95#endif
96
97#define MatchIncomingEvent(tmEvent, typeMatch, modMatch)(typeMatch->eventType == tmEvent->event.eventType &&
(typeMatch->matchEvent != ((void*)0)) && (*typeMatch
->matchEvent)(typeMatch, modMatch, tmEvent))
\
98 (typeMatch->eventType == tmEvent->event.eventType && \
99 (typeMatch->matchEvent != NULL((void*)0)) && \
100 (*typeMatch->matchEvent)(typeMatch, modMatch, tmEvent))
101
102
103#define NumStateTrees(xlations)((translateData->isSimple) ? 1 : (TMComplexXlations(xlations
))->numTrees)
\
104 ((translateData->isSimple) ? 1 : (TMComplexXlations(xlations))->numTrees)
105
106static TMShortCard GetBranchHead(
107 TMParseStateTree parseTree,
108 TMShortCard typeIndex,
109 TMShortCard modIndex,
110 Boolean isDummy)
111{
112#define TM_BRANCH_HEAD_TBL_ALLOC8 8
113#define TM_BRANCH_HEAD_TBL_REALLOC8 8
114
115 TMBranchHead branchHead = parseTree->branchHeadTbl;
116 TMShortCard newSize, i;
117
118 /*
119 * dummy is used as a place holder for later matching in old-style
120 * matching behavior. If there's already an entry we don't need
121 * another dummy.
122 */
123 if (isDummy) {
124 for (i = 0; i < parseTree->numBranchHeads; i++, branchHead++) {
125 if ((branchHead->typeIndex == typeIndex) &&
126 (branchHead->modIndex == modIndex))
127 return i;
128 }
129 }
130 if (parseTree->numBranchHeads == parseTree->branchHeadTblSize)
131 {
132 if (parseTree->branchHeadTblSize == 0)
133 parseTree->branchHeadTblSize += TM_BRANCH_HEAD_TBL_ALLOC8;
134 else
135 parseTree->branchHeadTblSize +=
136 TM_BRANCH_HEAD_TBL_REALLOC8;
137 newSize = (parseTree->branchHeadTblSize * sizeof(TMBranchHeadRec));
138 if (parseTree->isStackBranchHeads) {
139 TMBranchHead oldBranchHeadTbl = parseTree->branchHeadTbl;
140 parseTree->branchHeadTbl = (TMBranchHead) __XtMalloc(newSize);
141 XtMemmove(parseTree->branchHeadTbl, oldBranchHeadTbl, newSize)if ((char *)(parseTree->branchHeadTbl) != (char *)(oldBranchHeadTbl
)) { (void) memcpy((char *) (parseTree->branchHeadTbl), (char
*) (oldBranchHeadTbl), (int) (newSize)); }
;
142 parseTree->isStackBranchHeads = False0;
143 }
144 else {
145 parseTree->branchHeadTbl = (TMBranchHead)
146 XtRealloc((char *)parseTree->branchHeadTbl,
147 (parseTree->branchHeadTblSize *
148 sizeof(TMBranchHeadRec)));
149 }
150 }
151#ifdef TRACE_TM
152 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
153 _XtGlobalTM.numBranchHeads++;
154 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
155#endif /* TRACE_TM */
156 branchHead =
157 &parseTree->branchHeadTbl[parseTree->numBranchHeads++];
158 branchHead->typeIndex = typeIndex;
159 branchHead->modIndex = modIndex;
160 branchHead->more = 0;
161 branchHead->isSimple = True1;
162 branchHead->hasActions = False0;
163 branchHead->hasCycles = False0;
164 return parseTree->numBranchHeads-1;
165}
166
167TMShortCard _XtGetQuarkIndex(
168 TMParseStateTree parseTree,
169 XrmQuark quark)
170{
171#define TM_QUARK_TBL_ALLOC16 16
172#define TM_QUARK_TBL_REALLOC16 16
173 TMShortCard i = parseTree->numQuarks;
174
175 for (i=0; i < parseTree->numQuarks; i++)
176 if (parseTree->quarkTbl[i] == quark)
177 break;
178
179 if (i == parseTree->numQuarks)
180 {
181 if (parseTree->numQuarks == parseTree->quarkTblSize)
182 {
183 TMShortCard newSize;
184
185 if (parseTree->quarkTblSize == 0)
186 parseTree->quarkTblSize += TM_QUARK_TBL_ALLOC16;
187 else
188 parseTree->quarkTblSize += TM_QUARK_TBL_REALLOC16;
189 newSize = (parseTree->quarkTblSize * sizeof(XrmQuark));
190
191 if (parseTree->isStackQuarks) {
192 XrmQuark *oldquarkTbl = parseTree->quarkTbl;
193 parseTree->quarkTbl = (XrmQuark *) __XtMalloc(newSize);
194 XtMemmove(parseTree->quarkTbl, oldquarkTbl, newSize)if ((char *)(parseTree->quarkTbl) != (char *)(oldquarkTbl)
) { (void) memcpy((char *) (parseTree->quarkTbl), (char *)
(oldquarkTbl), (int) (newSize)); }
;
195 parseTree->isStackQuarks = False0;
196 }
197 else {
198 parseTree->quarkTbl = (XrmQuark *)
199 XtRealloc((char *)parseTree->quarkTbl,
200 (parseTree->quarkTblSize *
201 sizeof(XrmQuark)));
202 }
203 }
204 parseTree->quarkTbl[parseTree->numQuarks++] = quark;
205 }
206 return i;
207}
208
209/*
210 * Get an entry from the parseTrees complex branchHead tbl. If there's none
211 * there then allocate one
212 */
213/*ARGSUSED*/
214static TMShortCard GetComplexBranchIndex(
215 TMParseStateTree parseTree,
216 TMShortCard typeIndex,
217 TMShortCard modIndex)
218{
219#define TM_COMPLEXBRANCH_HEAD_TBL_ALLOC8 8
220#define TM_COMPLEXBRANCH_HEAD_TBL_REALLOC4 4
221
222 if (parseTree->numComplexBranchHeads == parseTree->complexBranchHeadTblSize) {
223 TMShortCard newSize;
224
225 if (parseTree->complexBranchHeadTblSize == 0)
226 parseTree->complexBranchHeadTblSize += TM_COMPLEXBRANCH_HEAD_TBL_ALLOC8;
227 else
228 parseTree->complexBranchHeadTblSize += TM_COMPLEXBRANCH_HEAD_TBL_REALLOC4;
229
230 newSize = (parseTree->complexBranchHeadTblSize * sizeof(StatePtr));
231
232 if (parseTree->isStackComplexBranchHeads) {
233 StatePtr *oldcomplexBranchHeadTbl
234 = parseTree->complexBranchHeadTbl;
235 parseTree->complexBranchHeadTbl = (StatePtr *) __XtMalloc(newSize);
236 XtMemmove(parseTree->complexBranchHeadTbl,if ((char *)(parseTree->complexBranchHeadTbl) != (char *)(
oldcomplexBranchHeadTbl)) { (void) memcpy((char *) (parseTree
->complexBranchHeadTbl), (char *) (oldcomplexBranchHeadTbl
), (int) (newSize)); }
237 oldcomplexBranchHeadTbl, newSize)if ((char *)(parseTree->complexBranchHeadTbl) != (char *)(
oldcomplexBranchHeadTbl)) { (void) memcpy((char *) (parseTree
->complexBranchHeadTbl), (char *) (oldcomplexBranchHeadTbl
), (int) (newSize)); }
;
238 parseTree->isStackComplexBranchHeads = False0;
239 }
240 else {
241 parseTree->complexBranchHeadTbl = (StatePtr *)
242 XtRealloc((char *)parseTree->complexBranchHeadTbl,
243 (parseTree->complexBranchHeadTblSize *
244 sizeof(StatePtr)));
245 }
246 }
247 parseTree->complexBranchHeadTbl[parseTree->numComplexBranchHeads++] = NULL((void*)0);
248 return parseTree->numComplexBranchHeads-1;
249}
250
251TMShortCard _XtGetTypeIndex(
252 Event *event)
253{
254 TMShortCard i, j = TM_TYPE_SEGMENT_SIZE16;
255 TMShortCard typeIndex = 0;
256 TMTypeMatch typeMatch;
257 TMTypeMatch segment = NULL((void*)0);
258
259 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
260 for (i = 0; i < _XtGlobalTM.numTypeMatchSegments; i++) {
261 segment = _XtGlobalTM.typeMatchSegmentTbl[i];
262 for (j = 0;
263 typeIndex < _XtGlobalTM.numTypeMatches && j < TM_TYPE_SEGMENT_SIZE16;
264 j++, typeIndex++)
265 {
266 typeMatch = &(segment[j]);
267 if (event->eventType == typeMatch->eventType &&
268 event->eventCode == typeMatch->eventCode &&
269 event->eventCodeMask == typeMatch->eventCodeMask &&
270 event->matchEvent == typeMatch->matchEvent) {
271 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
272 return typeIndex;
273 }
274 }
275 }
276
277 if (j == TM_TYPE_SEGMENT_SIZE16) {
278 if (_XtGlobalTM.numTypeMatchSegments == _XtGlobalTM.typeMatchSegmentTblSize) {
279 _XtGlobalTM.typeMatchSegmentTblSize += 4;
280 _XtGlobalTM.typeMatchSegmentTbl = (TMTypeMatch *)
281 XtRealloc((char *)_XtGlobalTM.typeMatchSegmentTbl,
282 (_XtGlobalTM.typeMatchSegmentTblSize * sizeof(TMTypeMatch)));
283 }
284 _XtGlobalTM.typeMatchSegmentTbl[_XtGlobalTM.numTypeMatchSegments++] =
285 segment = (TMTypeMatch)
286 __XtMalloc(TM_TYPE_SEGMENT_SIZE16 * sizeof(TMTypeMatchRec));
287 j = 0;
288 }
289 typeMatch = &segment[j];
290 typeMatch->eventType = event->eventType;
291 typeMatch->eventCode = event->eventCode;
292 typeMatch->eventCodeMask = event->eventCodeMask;
293 typeMatch->matchEvent = event->matchEvent;
294 _XtGlobalTM.numTypeMatches++;
295 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
296 return typeIndex;
297}
298
299static Boolean CompareLateModifiers(
300 LateBindingsPtr lateBind1P,
301 LateBindingsPtr lateBind2P)
302{
303 LateBindingsPtr late1P = lateBind1P;
304 LateBindingsPtr late2P = lateBind2P;
305
306 if (late1P != NULL((void*)0) || late2P != NULL((void*)0)) {
307 int i = 0;
308 int j = 0;
309 if (late1P != NULL((void*)0))
310 for (; late1P->keysym != NoSymbol0L; i++) late1P++;
311 if (late2P != NULL((void*)0))
312 for (; late2P->keysym != NoSymbol0L; j++) late2P++;
313 if (i != j) return FALSE0;
314 late1P--;
315 while (late1P >= lateBind1P) {
316 Boolean last = True1;
317 for (late2P = lateBind2P + i - 1;
318 late2P >= lateBind2P;
319 late2P--) {
320 if (late1P->keysym == late2P->keysym
321 && late1P->knot == late2P->knot) {
322 j--;
323 if (last) i--;
324 break;
325 }
326 last = False0;
327 }
328 late1P--;
329 }
330 if (j != 0) return FALSE0;
331 }
332 return TRUE1;
333}
334
335TMShortCard _XtGetModifierIndex(
336 Event *event)
337{
338 TMShortCard i, j = TM_MOD_SEGMENT_SIZE16;
339 TMShortCard modIndex = 0;
340 TMModifierMatch modMatch;
341 TMModifierMatch segment = NULL((void*)0);
342
343 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
344 for (i = 0; i < _XtGlobalTM.numModMatchSegments; i++) {
345 segment = _XtGlobalTM.modMatchSegmentTbl[i];
346 for (j = 0;
347 modIndex < _XtGlobalTM.numModMatches && j < TM_MOD_SEGMENT_SIZE16;
348 j++, modIndex++) {
349 modMatch = &(segment[j]);
350 if (event->modifiers == modMatch->modifiers &&
351 event->modifierMask == modMatch->modifierMask &&
352 event->standard == modMatch->standard &&
353 ((!event->lateModifiers && !modMatch->lateModifiers) ||
354 CompareLateModifiers(event->lateModifiers,
355 modMatch->lateModifiers))) {
356 /*
357 * if we found a match then we can free the parser's
358 * late modifiers. If there isn't a match we use the
359 * parser's copy
360 */
361 if (event->lateModifiers &&
362 --event->lateModifiers->ref_count == 0) {
363 XtFree((char *)event->lateModifiers);
364 event->lateModifiers = NULL((void*)0);
365 }
366 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
367 return modIndex;
368 }
369 }
370 }
371
372 if (j == TM_MOD_SEGMENT_SIZE16) {
373 if (_XtGlobalTM.numModMatchSegments == _XtGlobalTM.modMatchSegmentTblSize) {
374 _XtGlobalTM.modMatchSegmentTblSize += 4;
375 _XtGlobalTM.modMatchSegmentTbl = (TMModifierMatch *)
376 XtRealloc((char *)_XtGlobalTM.modMatchSegmentTbl,
377 (_XtGlobalTM.modMatchSegmentTblSize * sizeof(TMModifierMatch)));
378 }
379 _XtGlobalTM.modMatchSegmentTbl[_XtGlobalTM.numModMatchSegments++] =
380 segment = (TMModifierMatch)
381 __XtMalloc(TM_MOD_SEGMENT_SIZE16 * sizeof(TMModifierMatchRec));
382 j = 0;
383 }
384 modMatch = &segment[j];
385 modMatch->modifiers = event->modifiers;;
386 modMatch->modifierMask = event->modifierMask;
387 modMatch->standard = event->standard;
388 /*
389 * We use the parser's copy of the late binding array
390 */
391#ifdef TRACE_TM
392 if (event->lateModifiers)
393 _XtGlobalTM.numLateBindings++;
394#endif /* TRACE_TM */
395 modMatch->lateModifiers = event->lateModifiers;
396 _XtGlobalTM.numModMatches++;
397 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
398 return modIndex;
399}
400
401
402/*
403 * This is called from the SimpleStateHandler to match a stateTree
404 * entry to the event coming in
405 */
406static int MatchBranchHead(
407 TMSimpleStateTree stateTree,
408 int startIndex,
409 TMEventPtr event)
410{
411 TMBranchHead branchHead = &stateTree->branchHeadTbl[startIndex];
412 int i;
413
414 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
415 for (i = startIndex;
416 i < (int)stateTree->numBranchHeads;
417 i++, branchHead++)
418 {
419 TMTypeMatch typeMatch;
420 TMModifierMatch modMatch;
421
422 typeMatch = TMGetTypeMatch(branchHead->typeIndex)((TMTypeMatch) &((_XtGlobalTM.typeMatchSegmentTbl[((branchHead
->typeIndex) >> 4)])[(branchHead->typeIndex) &
15]))
;
423 modMatch = TMGetModifierMatch(branchHead->modIndex)((TMModifierMatch) &((_XtGlobalTM.modMatchSegmentTbl[(branchHead
->modIndex) >> 4])[(branchHead->modIndex) & 15
]))
;
424
425 if (MatchIncomingEvent(event, typeMatch, modMatch)(typeMatch->eventType == event->event.eventType &&
(typeMatch->matchEvent != ((void*)0)) && (*typeMatch
->matchEvent)(typeMatch, modMatch, event))
) {
426 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
427 return i;
428 }
429 }
430 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
431 return (TM_NO_MATCH(-2));
432}
433
434Boolean _XtRegularMatch(
435 TMTypeMatch typeMatch,
436 TMModifierMatch modMatch,
437 TMEventPtr eventSeq)
438{
439 Modifiers computed =0;
440 Modifiers computedMask =0;
441 Boolean resolved = TRUE1;
442 if (typeMatch->eventCode != (eventSeq->event.eventCode &
443 typeMatch->eventCodeMask)) return FALSE0;
444 if (modMatch->lateModifiers != NULL((void*)0))
445 resolved = _XtComputeLateBindings(eventSeq->xev->xany.display,
446 modMatch->lateModifiers,
447 &computed, &computedMask);
448 if (!resolved) return FALSE0;
449 computed |= modMatch->modifiers;
450 computedMask |= modMatch->modifierMask;
451
452 return ( (computed & computedMask) ==
453 (eventSeq->event.modifiers & computedMask));
454}
455
456/*ARGSUSED*/
457Boolean _XtMatchAtom(
458 TMTypeMatch typeMatch,
459 TMModifierMatch modMatch,
460 TMEventPtr eventSeq)
461{
462 Atom atom;
463
464 atom = XInternAtom(eventSeq->xev->xany.display,
465 XrmQuarkToString(typeMatch->eventCode),
466 False0);
467 return (atom == eventSeq->event.eventCode);
468}
469
470#define IsOn(vec,idx)((vec)[(idx)>>3] & (1 << ((idx) & 7))) ((vec)[(idx)>>3] & (1 << ((idx) & 7)))
471
472/*
473 * there are certain cases where you want to ignore the event and stay
474 * in the same state.
475 */
476static Boolean Ignore(
477 TMEventPtr event)
478{
479 Display *dpy;
480 XtPerDisplay pd;
481
482 if (event->event.eventType == MotionNotify6)
483 return TRUE1;
484 if (!(event->event.eventType == KeyPress2 ||
485 event->event.eventType == KeyRelease3))
486 return FALSE0;
487 dpy = event->xev->xany.display;
488 pd = _XtGetPerDisplay(dpy);
489 _InitializeKeysymTables(dpy, pd)if (pd->keysyms == ((void*)0)) _XtBuildKeysymTables(dpy, pd
)
;
490 return IsOn(pd->isModifier, event->event.eventCode)((pd->isModifier)[(event->event.eventCode)>>3] &
(1 << ((event->event.eventCode) & 7)))
? TRUE1 : FALSE0;
491}
492
493
494static void XEventToTMEvent(
495 XEvent *event,
496 TMEventPtr tmEvent)
497{
498 tmEvent->xev = event;
499 tmEvent->event.eventCodeMask = 0;
500 tmEvent->event.modifierMask = 0;
501 tmEvent->event.eventType = event->type;
502 tmEvent->event.lateModifiers = NULL((void*)0);
503 tmEvent->event.matchEvent = NULL((void*)0);
504 tmEvent->event.standard = FALSE0;
505
506 switch (event->type) {
507
508 case KeyPress2:
509 case KeyRelease3:
510 tmEvent->event.eventCode = event->xkey.keycode;
511 tmEvent->event.modifiers = event->xkey.state;
512 break;
513
514 case ButtonPress4:
515 case ButtonRelease5:
516 tmEvent->event.eventCode = event->xbutton.button;
517 tmEvent->event.modifiers = event->xbutton.state;
518 break;
519
520 case MotionNotify6:
521 tmEvent->event.eventCode = event->xmotion.is_hint;
522 tmEvent->event.modifiers = event->xmotion.state;
523 break;
524
525 case EnterNotify7:
526 case LeaveNotify8:
527 tmEvent->event.eventCode = event->xcrossing.mode;
528 tmEvent->event.modifiers = event->xcrossing.state;
529 break;
530
531 case PropertyNotify28:
532 tmEvent->event.eventCode = event->xproperty.atom;
533 tmEvent->event.modifiers = 0;
534 break;
535
536 case SelectionClear29:
537 tmEvent->event.eventCode = event->xselectionclear.selection;
538 tmEvent->event.modifiers = 0;
539 break;
540
541 case SelectionRequest30:
542 tmEvent->event.eventCode = event->xselectionrequest.selection;
543 tmEvent->event.modifiers = 0;
544 break;
545
546 case SelectionNotify31:
547 tmEvent->event.eventCode = event->xselection.selection;
548 tmEvent->event.modifiers = 0;
549 break;
550
551 case ClientMessage33:
552 tmEvent->event.eventCode = event->xclient.message_type;
553 tmEvent->event.modifiers = 0;
554 break;
555
556 case MappingNotify34:
557 tmEvent->event.eventCode = event->xmapping.request;
558 tmEvent->event.modifiers = 0;
559 break;
560
561 case FocusIn9:
562 case FocusOut10:
563 tmEvent->event.eventCode = event->xfocus.mode;
564 tmEvent->event.modifiers = 0;
565 break;
566
567 default:
568 tmEvent->event.eventCode = 0;
569 tmEvent->event.modifiers = 0;
570 break;
571 }
572}
573
574
575static unsigned long GetTime(
576 XtTM tm,
577 XEvent *event)
578{
579 switch (event->type) {
580
581 case KeyPress2:
582 case KeyRelease3:
583 return event->xkey.time;
584
585 case ButtonPress4:
586 case ButtonRelease5:
587 return event->xbutton.time;
588
589 default:
590 return tm->lastEventTime;
591
592 }
593
594}
595
596static void HandleActions(
597 Widget w,
598 XEvent *event,
599 TMSimpleStateTree stateTree,
600 Widget accelWidget,
601 XtActionProc *procs,
602 ActionRec *actions)
603{
604 ActionHook actionHookList;
605 Widget bindWidget;
606
607 bindWidget = accelWidget ? accelWidget : w;
608 if (accelWidget && !XtIsSensitive(accelWidget)((((Object)(accelWidget))->object.widget_class->core_class
.class_inited & 0x02) ? ((accelWidget)->core.sensitive
&& (accelWidget)->core.ancestor_sensitive) : 0)
&&
609 (event->type == KeyPress2 || event->type == KeyRelease3 ||
610 event->type == ButtonPress4 || event->type == ButtonRelease5 ||
611 event->type == MotionNotify6 || event->type == EnterNotify7 ||
612 event->type == LeaveNotify8 || event->type == FocusIn9 ||
613 event->type == FocusOut10))
614 return;
615
616 actionHookList = XtWidgetToApplicationContext(w)->action_hook_list;
617
618 while (actions != NULL((void*)0)) {
619 /* perform any actions */
620 if (procs[actions->idx] != NULL((void*)0)) {
621 if (actionHookList) {
622 ActionHook hook;
623 ActionHook next_hook;
624 String procName =
625 XrmQuarkToString(stateTree->quarkTbl[actions->idx] );
626
627 for (hook = actionHookList; hook != NULL((void*)0); ) {
628 /*
629 * Need to cache hook->next because the following action
630 * proc may free hook via XtRemoveActionHook making
631 * hook->next invalid upon return from the action proc.
632 */
633 next_hook = hook->next;
634 (*hook->proc)(bindWidget,
635 hook->closure,
636 procName,
637 event,
638 actions->params,
639 &actions->num_params
640 );
641 hook = next_hook;
642 }
643 }
644 (*(procs[actions->idx]))
645 (bindWidget, event,
646 actions->params, &actions->num_params );
647 }
648 actions = actions->next;
649 }
650}
651
652typedef struct {
653 unsigned int isCycleStart:1;
654 unsigned int isCycleEnd:1;
655 TMShortCard typeIndex;
656 TMShortCard modIndex;
657}MatchPairRec, *MatchPair;
658
659typedef struct TMContextRec{
660 TMShortCard numMatches;
661 TMShortCard maxMatches;
662 MatchPair matches;
663}TMContextRec, *TMContext;
664
665static TMContextRec contextCache[2];
666
667#define GetContextPtr(tm)((TMContext *)&(tm->current_state)) ((TMContext *)&(tm->current_state))
668
669#define TM_CONTEXT_MATCHES_ALLOC4 4
670#define TM_CONTEXT_MATCHES_REALLOC2 2
671
672static void PushContext(
673 TMContext *contextPtr,
674 StatePtr newState)
675{
676 TMContext context = *contextPtr;
677
678 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
679 if (context == NULL((void*)0))
680 {
681 if (contextCache[0].numMatches == 0)
682 context = &contextCache[0];
683 else if (contextCache[1].numMatches == 0)
684 context = &contextCache[1];
685 if (!context)
686 {
687 context = XtNew(TMContextRec)((TMContextRec *) XtMalloc((unsigned) sizeof(TMContextRec)));
688 context->matches = NULL((void*)0);
689 context->numMatches =
690 context->maxMatches = 0;
691 }
692 }
693 if (context->numMatches &&
694 context->matches[context->numMatches-1].isCycleEnd)
695 {
696 TMShortCard i;
697 for (i = 0;
698 i < context->numMatches &&
699 !(context->matches[i].isCycleStart);
700 i++){};
701 if (i < context->numMatches)
702 context->numMatches = i+1;
703#ifdef DEBUG
704 else
705 XtWarning("pushing cycle end with no cycle start");
706#endif /* DEBUG */
707 }
708 else
709 {
710 if (context->numMatches == context->maxMatches)
711 {
712 if (context->maxMatches == 0)
713 context->maxMatches += TM_CONTEXT_MATCHES_ALLOC4;
714 else
715 context->maxMatches += TM_CONTEXT_MATCHES_REALLOC2;
716 context->matches = (MatchPairRec *)
717 XtRealloc((char *)context->matches,
718 context->maxMatches * sizeof(MatchPairRec));
719 }
720 context->matches[context->numMatches].isCycleStart = newState->isCycleStart;
721 context->matches[context->numMatches].isCycleEnd = newState->isCycleEnd;
722 context->matches[context->numMatches].typeIndex = newState->typeIndex;
723 context->matches[context->numMatches++].modIndex = newState->modIndex;
724 *contextPtr = context;
725 }
726 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
727}
728
729static void FreeContext(
730 TMContext *contextPtr)
731{
732 TMContext context = NULL((void*)0);
733
734 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
735
736 if (&contextCache[0] == *contextPtr)
737 context = &contextCache[0];
738 else if (&contextCache[1] == *contextPtr)
739 context = &contextCache[1];
740
741 if (context)
742 context->numMatches = 0;
743 else if (*contextPtr)
744 {
745 if ((*contextPtr)->matches)
746 XtFree ((char *) ((*contextPtr)->matches));
747 XtFree((char *)*contextPtr);
748 }
749
750 *contextPtr = NULL((void*)0);
751 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
752}
753
754static int MatchExact(
755 TMSimpleStateTree stateTree,
756 int startIndex,
757 TMShortCard typeIndex,
758 TMShortCard modIndex)
759{
760 TMBranchHead branchHead = &(stateTree->branchHeadTbl[startIndex]);
761 int i;
762
763 for (i = startIndex;
764 i < (int)stateTree->numBranchHeads;
765 i++, branchHead++)
766 {
767 if ((branchHead->typeIndex == typeIndex) &&
768 (branchHead->modIndex == modIndex))
769 return i;
770 }
771 return (TM_NO_MATCH(-2));
772}
773
774
775
776static void HandleSimpleState(
777 Widget w,
778 XtTM tmRecPtr,
779 TMEventRec *curEventPtr)
780{
781 XtTranslations xlations = tmRecPtr->translations;
782 TMSimpleStateTree stateTree;
783 TMContext *contextPtr = GetContextPtr(tmRecPtr)((TMContext *)&(tmRecPtr->current_state));
784 TMShortCard i;
785 ActionRec *actions = NULL((void*)0);
786 Boolean matchExact = False0;
787 Boolean match = False0;
788 StatePtr complexMatchState = NULL((void*)0);
789 int currIndex;
790 TMShortCard typeIndex = 0, modIndex = 0;
791 int matchTreeIndex = TM_NO_MATCH(-2);
792
793 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
794 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[0];
795
796 for (i = 0;
797 ((!match || !complexMatchState) && (i < xlations->numStateTrees));
798 i++){
799 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[i];
800 currIndex = -1;
801 /*
802 * don't process this tree if we're only looking for a
803 * complexMatchState and there are no complex states
804 */
805 while (!(match && stateTree->isSimple) &&
806 ((!match || !complexMatchState) && (currIndex != TM_NO_MATCH(-2)))) {
807 currIndex++;
808 if (matchExact)
809 currIndex = MatchExact(stateTree,currIndex,typeIndex,modIndex);
810 else
811 currIndex = MatchBranchHead(stateTree,currIndex,curEventPtr);
812 if (currIndex != TM_NO_MATCH(-2)) {
813 TMBranchHead branchHead;
814 StatePtr currState;
815
816 branchHead = &stateTree->branchHeadTbl[currIndex];
817 if (branchHead->isSimple)
818 currState = NULL((void*)0);
819 else
820 currState = ((TMComplexStateTree)stateTree)
821 ->complexBranchHeadTbl[TMBranchMore(branchHead)(branchHead->more)];
822
823 /*
824 * first check for a complete match
825 */
826 if (!match) {
827 if (branchHead->hasActions) {
828 if (branchHead->isSimple) {
829 static ActionRec dummyAction;
830
831 dummyAction.idx = TMBranchMore(branchHead)(branchHead->more);
832 actions = &dummyAction;
833 }
834 else
835 actions = currState->actions;
836 tmRecPtr->lastEventTime =
837 GetTime(tmRecPtr, curEventPtr->xev);
838 FreeContext((TMContext
839 *)&tmRecPtr->current_state);
840 match = True1;
841 matchTreeIndex = i;
842 }
843 /*
844 * if it doesn't have actions and
845 * it's bc mode then it's a potential match node that is
846 * used to match later sequences.
847 */
848 if (!TMNewMatchSemantics()(_XtGlobalTM.newMatchSemantics) && !matchExact) {
849 matchExact = True1;
850 typeIndex = branchHead->typeIndex;
851 modIndex = branchHead->modIndex;
852 }
853 }
854 /*
855 * check for it being an event sequence which can be
856 * a future match
857 */
858 if (!branchHead->isSimple &&
859 !branchHead->hasActions &&
860 !complexMatchState)
861 complexMatchState = currState;
862 }
863 }
864 }
865 if (match)
866 {
867 TMBindData bindData = (TMBindData) tmRecPtr->proc_table;
868 XtActionProc *procs;
869 Widget accelWidget;
870
871 if (bindData->simple.isComplex) {
872 TMComplexBindProcs bindProcs =
873 TMGetComplexBindEntry(bindData, matchTreeIndex)((TMComplexBindProcs)&(((TMComplexBindData)bindData)->
bindTbl[matchTreeIndex]))
;
874 procs = bindProcs->procs;
875 accelWidget = bindProcs->widget;
876 }
877 else {
878 TMSimpleBindProcs bindProcs =
879 TMGetSimpleBindEntry(bindData, matchTreeIndex)((TMSimpleBindProcs)&(((TMSimpleBindData)bindData)->bindTbl
[matchTreeIndex]))
;
880 procs = bindProcs->procs;
881 accelWidget = NULL((void*)0);
882 }
883 HandleActions
884 (w,
885 curEventPtr->xev,
886 (TMSimpleStateTree)xlations->stateTreeTbl[matchTreeIndex],
887 accelWidget,
888 procs,
889 actions);
890 }
891 if (complexMatchState)
892 PushContext(contextPtr, complexMatchState);
893 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
894}
895
896static int MatchComplexBranch(
897 TMComplexStateTree stateTree,
898 int startIndex,
899 TMContext context,
900 StatePtr *leafStateRtn)
901{
902 TMShortCard i;
903
904 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
905 for (i = startIndex; i < stateTree->numComplexBranchHeads; i++)
906 {
907 StatePtr candState;
908 TMShortCard numMatches = context->numMatches;
909 MatchPair statMatch = context->matches;
910
911 for (candState = stateTree->complexBranchHeadTbl[i];
912 numMatches && candState;
913 numMatches--, statMatch++, candState = candState->nextLevel)
914 {
915 if ((statMatch->typeIndex != candState->typeIndex) ||
916 (statMatch->modIndex != candState->modIndex))
917 break;
918 }
919 if (numMatches == 0) {
920 *leafStateRtn = candState;
921 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
922 return i;
923 }
924 }
925 *leafStateRtn = NULL((void*)0);
926 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
927 return (TM_NO_MATCH(-2));
928}
929
930static StatePtr TryCurrentTree(
931 TMComplexStateTree *stateTreePtr,
932 XtTM tmRecPtr,
933 TMEventRec *curEventPtr)
934{
935 StatePtr candState = NULL((void*)0), matchState = NULL((void*)0);
936 TMContext *contextPtr = GetContextPtr(tmRecPtr)((TMContext *)&(tmRecPtr->current_state));
937 TMTypeMatch typeMatch;
938 TMModifierMatch modMatch;
939 int currIndex = -1;
940
941 /*
942 * we want the first sequence that both matches and has actions.
943 * we keep on looking till we find both
944 */
945 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
946 while ((currIndex =
947 MatchComplexBranch(*stateTreePtr,
948 ++currIndex,
949 (*contextPtr),
950 &candState))
951 != TM_NO_MATCH(-2)) {
952 if (candState != NULL((void*)0)) {
953 typeMatch = TMGetTypeMatch(candState->typeIndex)((TMTypeMatch) &((_XtGlobalTM.typeMatchSegmentTbl[((candState
->typeIndex) >> 4)])[(candState->typeIndex) &
15]))
;
954 modMatch = TMGetModifierMatch(candState->modIndex)((TMModifierMatch) &((_XtGlobalTM.modMatchSegmentTbl[(candState
->modIndex) >> 4])[(candState->modIndex) & 15
]))
;
955
956 /* does this state's index match? --> done */
957 if (MatchIncomingEvent(curEventPtr, typeMatch, modMatch)(typeMatch->eventType == curEventPtr->event.eventType &&
(typeMatch->matchEvent != ((void*)0)) && (*typeMatch
->matchEvent)(typeMatch, modMatch, curEventPtr))
)
958 {
959 if (candState->actions) {
960 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
961 return candState;
962 }
963 else
964 matchState = candState;
965 }
966 /* is this an event timer? */
967 if (typeMatch->eventType == _XtEventTimerEventType((TMLongCard)~0L)) {
968 StatePtr nextState = candState->nextLevel;
969
970 /* does the succeeding state match? */
971 if (nextState != NULL((void*)0)) {
972 TMTypeMatch nextTypeMatch;
973 TMModifierMatch nextModMatch;
974
975 nextTypeMatch = TMGetTypeMatch(nextState->typeIndex)((TMTypeMatch) &((_XtGlobalTM.typeMatchSegmentTbl[((nextState
->typeIndex) >> 4)])[(nextState->typeIndex) &
15]))
;
976 nextModMatch = TMGetModifierMatch(nextState->modIndex)((TMModifierMatch) &((_XtGlobalTM.modMatchSegmentTbl[(nextState
->modIndex) >> 4])[(nextState->modIndex) & 15
]))
;
977
978 /* is it within the timeout? */
979 if (MatchIncomingEvent(curEventPtr,(nextTypeMatch->eventType == curEventPtr->event.eventType
&& (nextTypeMatch->matchEvent != ((void*)0)) &&
(*nextTypeMatch->matchEvent)(nextTypeMatch, nextModMatch,
curEventPtr))
980 nextTypeMatch,(nextTypeMatch->eventType == curEventPtr->event.eventType
&& (nextTypeMatch->matchEvent != ((void*)0)) &&
(*nextTypeMatch->matchEvent)(nextTypeMatch, nextModMatch,
curEventPtr))
981 nextModMatch)(nextTypeMatch->eventType == curEventPtr->event.eventType
&& (nextTypeMatch->matchEvent != ((void*)0)) &&
(*nextTypeMatch->matchEvent)(nextTypeMatch, nextModMatch,
curEventPtr))
) {
982 XEvent *xev = curEventPtr->xev;
983 unsigned long time = GetTime(tmRecPtr, xev);
984 XtPerDisplay pd = _XtGetPerDisplay(xev->xany.display);
985 unsigned long delta = pd->multi_click_time;
986
987 if ((tmRecPtr->lastEventTime + delta) >= time) {
988 if (nextState->actions) {
989 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
990 return candState;
991 }
992 else
993 matchState = candState;
994 }
995 }
996 }
997 }
998 }
999 }
1000 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1001 return matchState;
1002}
1003
1004static void HandleComplexState(
1005 Widget w,
1006 XtTM tmRecPtr,
1007 TMEventRec *curEventPtr)
1008{
1009 XtTranslations xlations = tmRecPtr->translations;
1010 TMContext *contextPtr = GetContextPtr(tmRecPtr)((TMContext *)&(tmRecPtr->current_state));
1011 TMShortCard i, matchTreeIndex = 0;
1012 StatePtr matchState = NULL((void*)0), candState;
1013 TMComplexStateTree *stateTreePtr =
1014 (TMComplexStateTree *)&xlations->stateTreeTbl[0];
1015
1016 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1017 for (i = 0;
1018 i < xlations->numStateTrees;
1019 i++, stateTreePtr++) {
1020 /*
1021 * some compilers sign extend Boolean bit fields so test for
1022 * false |||
1023 */
1024 if (((*stateTreePtr)->isSimple == False0) &&
1025 (candState = TryCurrentTree(stateTreePtr,
1026 tmRecPtr,
1027 curEventPtr))) {
1028 if (!matchState || candState->actions) {
1029 matchTreeIndex = i;
1030 matchState = candState;
1031 if (candState->actions)
1032 break;
1033 }
1034 }
1035 }
1036 if (matchState == NULL((void*)0)){
1037 /* couldn't find it... */
1038 if (!Ignore(curEventPtr))
1039 {
1040 FreeContext(contextPtr);
1041 HandleSimpleState(w, tmRecPtr, curEventPtr);
1042 }
1043 }
1044 else {
1045 TMBindData bindData = (TMBindData) tmRecPtr->proc_table;
1046 XtActionProc *procs;
1047 Widget accelWidget;
1048 TMTypeMatch typeMatch;
1049
1050 typeMatch = TMGetTypeMatch(matchState->typeIndex)((TMTypeMatch) &((_XtGlobalTM.typeMatchSegmentTbl[((matchState
->typeIndex) >> 4)])[(matchState->typeIndex) &
15]))
;
1051
1052 PushContext(contextPtr, matchState);
1053 if (typeMatch->eventType == _XtEventTimerEventType((TMLongCard)~0L)) {
1054 matchState = matchState->nextLevel;
1055 PushContext(contextPtr, matchState);
1056 }
1057 tmRecPtr->lastEventTime = GetTime (tmRecPtr, curEventPtr->xev);
1058
1059 if (bindData->simple.isComplex) {
1060 TMComplexBindProcs bindProcs =
1061 TMGetComplexBindEntry(bindData, matchTreeIndex)((TMComplexBindProcs)&(((TMComplexBindData)bindData)->
bindTbl[matchTreeIndex]))
;
1062 procs = bindProcs->procs;
1063 accelWidget = bindProcs->widget;
1064 }
1065 else {
1066 TMSimpleBindProcs bindProcs =
1067 TMGetSimpleBindEntry(bindData, matchTreeIndex)((TMSimpleBindProcs)&(((TMSimpleBindData)bindData)->bindTbl
[matchTreeIndex]))
;
1068 procs = bindProcs->procs;
1069 accelWidget = NULL((void*)0);
1070 }
1071 HandleActions(w,
1072 curEventPtr->xev,
1073 (TMSimpleStateTree)
1074 xlations->stateTreeTbl[matchTreeIndex],
1075 accelWidget,
1076 procs,
1077 matchState->actions);
1078 }
1079 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1080}
1081
1082
1083void _XtTranslateEvent (
1084 Widget w,
1085 XEvent * event)
1086{
1087 XtTM tmRecPtr = &w->core.tm;
1088 TMEventRec curEvent;
1089 StatePtr current_state = tmRecPtr->current_state;
1090
1091 XEventToTMEvent (event, &curEvent);
1092
1093 if (! tmRecPtr->translations) {
1094 XtAppWarningMsg(XtWidgetToApplicationContext(w),
1095 XtNtranslationError,"nullTable",XtCXtToolkitError,
1096 "Can't translate event through NULL table",
1097 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1098 return ;
1099 }
1100 if (current_state == NULL((void*)0))
1101 HandleSimpleState(w, tmRecPtr, &curEvent);
1102 else
1103 HandleComplexState(w, tmRecPtr, &curEvent);
1104}
1105
1106
1107/*ARGSUSED*/
1108static StatePtr NewState(
1109 TMParseStateTree stateTree,
1110 TMShortCard typeIndex,
1111 TMShortCard modIndex)
1112{
1113 StatePtr state = XtNew(StateRec)((StateRec *) XtMalloc((unsigned) sizeof(StateRec)));
1114
1115#ifdef TRACE_TM
1116 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1117 _XtGlobalTM.numComplexStates++;
1118 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1119#endif /* TRACE_TM */
1120 state->typeIndex = typeIndex;
1121 state->modIndex = modIndex;
1122 state->nextLevel = NULL((void*)0);
1123 state->actions = NULL((void*)0);
1124 state->isCycleStart = state->isCycleEnd = False0;
1125 return state;
1126}
1127
1128/*
1129 * This routine is an iterator for state trees. If the func returns
1130 * true then iteration is over.
1131 */
1132void _XtTraverseStateTree(
1133 TMStateTree tree,
1134 _XtTraversalProc func,
1135 XtPointer data)
1136{
1137 TMComplexStateTree stateTree = (TMComplexStateTree)tree;
1138 TMBranchHead currBH;
1139 TMShortCard i;
1140 StateRec dummyStateRec, *dummyState = &dummyStateRec;
1141 ActionRec dummyActionRec, *dummyAction = &dummyActionRec;
1142 Boolean firstSimple = True1;
1143 StatePtr currState;
1144
1145 /* first traverse the complex states */
1146 if (stateTree->isSimple == False0)
1147 for (i = 0; i < stateTree->numComplexBranchHeads; i++) {
1148 currState = stateTree->complexBranchHeadTbl[i];
1149 for (; currState; currState = currState->nextLevel) {
1150 if (func(currState, data))
1151 return;
1152 if (currState->isCycleEnd)
1153 break;
1154 }
1155 }
1156
1157 /* now traverse the simple ones */
1158 for (i = 0, currBH = stateTree->branchHeadTbl;
1159 i < stateTree->numBranchHeads;
1160 i++, currBH++)
1161 {
1162 if (currBH->isSimple && currBH->hasActions)
1163 {
1164 if (firstSimple)
1165 {
1166 XtBZero((char *) dummyState, sizeof(StateRec))memset((char *) ((char *) dummyState),0,(int) (sizeof(StateRec
)))
;
1167 XtBZero((char *) dummyAction, sizeof(ActionRec))memset((char *) ((char *) dummyAction),0,(int) (sizeof(ActionRec
)))
;
1168 dummyState->actions = dummyAction;
1169 firstSimple = False0;
1170 }
1171 dummyState->typeIndex = currBH->typeIndex;
1172 dummyState->modIndex = currBH->modIndex;
1173 dummyAction->idx = currBH->more;
1174 if (func(dummyState, data))
1175 return;
1176 }
1177 }
1178}
1179
1180static EventMask EventToMask(
1181 TMTypeMatch typeMatch,
1182 TMModifierMatch modMatch)
1183{
1184 EventMask returnMask;
1185 unsigned long eventType = typeMatch->eventType;
1186
1187 if (eventType == MotionNotify6) {
1188 Modifiers modifierMask = modMatch->modifierMask;
1189 Modifiers tempMask;
1190
1191 returnMask = 0;
1192 if (modifierMask == 0) {
1193 if (modMatch->modifiers == AnyButtonMask(1L<<28))
1194 return ButtonMotionMask(1L<<13);
1195 else
1196 return PointerMotionMask(1L<<6);
1197 }
1198 tempMask = modifierMask &
1199 (Button1Mask(1<<8) | Button2Mask(1<<9) | Button3Mask(1<<10)
1200 | Button4Mask(1<<11) | Button5Mask(1<<12));
1201 if (tempMask == 0)
1202 return PointerMotionMask(1L<<6);
1203 if (tempMask & Button1Mask(1<<8))
1204 returnMask |= Button1MotionMask(1L<<8);
1205 if (tempMask & Button2Mask(1<<9))
1206 returnMask |= Button2MotionMask(1L<<9);
1207 if (tempMask & Button3Mask(1<<10))
1208 returnMask |= Button3MotionMask(1L<<10);
1209 if (tempMask & Button4Mask(1<<11))
1210 returnMask |= Button4MotionMask(1L<<11);
1211 if (tempMask & Button5Mask(1<<12))
1212 returnMask |= Button5MotionMask(1L<<12);
1213 return returnMask;
1214 }
1215 returnMask = _XtConvertTypeToMask(eventType);
1216 if (returnMask == (StructureNotifyMask(1L<<17)|SubstructureNotifyMask(1L<<19)))
1217 returnMask = StructureNotifyMask(1L<<17);
1218 return returnMask;
1219}
1220
1221/*ARGSUSED*/
1222static void DispatchMappingNotify(
1223 Widget widget, /* will be NULL from _RefreshMapping */
1224 XtPointer closure, /* real Widget */
1225 XtPointer call_data) /* XEvent* */
1226{
1227 _XtTranslateEvent( (Widget)closure, (XEvent*)call_data);
1228}
1229
1230
1231/*ARGSUSED*/
1232static void RemoveFromMappingCallbacks(
1233 Widget widget,
1234 XtPointer closure, /* target widget */
1235 XtPointer call_data)
1236{
1237 _XtRemoveCallback( &_XtGetPerDisplay(XtDisplay(widget)(((widget)->core.screen)->display))->mapping_callbacks,
1238 DispatchMappingNotify,
1239 closure
1240 );
1241}
1242
1243static Boolean AggregateEventMask(
1244 StatePtr state,
1245 XtPointer data)
1246{
1247 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1248 *((EventMask *)data) |= EventToMask(TMGetTypeMatch(state->typeIndex)((TMTypeMatch) &((_XtGlobalTM.typeMatchSegmentTbl[((state
->typeIndex) >> 4)])[(state->typeIndex) & 15]
))
,
1249 TMGetModifierMatch(state->modIndex)((TMModifierMatch) &((_XtGlobalTM.modMatchSegmentTbl[(state
->modIndex) >> 4])[(state->modIndex) & 15]))
);
1250 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1251 return False0;
1252}
1253
1254void _XtInstallTranslations(
1255 Widget widget)
1256{
1257 XtTranslations xlations;
1258 Cardinal i;
1259 TMStateTree stateTree;
1260 Boolean mappingNotifyInterest = False0;
1261
1262 xlations = widget->core.tm.translations;
1263 if (xlations == NULL((void*)0)) return;
1264
1265 /*
1266 * check for somebody stuffing the translations directly into the
1267 * instance structure. We will end up being called again out of
1268 * ComposeTranslations but we *should* have bindings by then
1269 */
1270 if (widget->core.tm.proc_table == NULL((void*)0)) {
1271 _XtMergeTranslations(widget, NULL((void*)0), XtTableReplace0);
1272 /*
1273 * if we're realized then we'll be called out of
1274 * ComposeTranslations
1275 */
1276 if (XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
)
1277 return;
1278 }
1279
1280 xlations->eventMask = 0;
1281 for (i = 0;
1282 i < xlations->numStateTrees;
1283 i++)
1284 {
1285 stateTree = xlations->stateTreeTbl[i];
1286 _XtTraverseStateTree(stateTree,
1287 AggregateEventMask,
1288 (XtPointer)&xlations->eventMask);
1289 mappingNotifyInterest |= stateTree->simple.mappingNotifyInterest;
1290 }
1291 /* double click needs to make sure that you have selected on both
1292 button down and up. */
1293
1294 if (xlations->eventMask & ButtonPressMask(1L<<2))
1295 xlations->eventMask |= ButtonReleaseMask(1L<<3);
1296 if (xlations->eventMask & ButtonReleaseMask(1L<<3))
1297 xlations->eventMask |= ButtonPressMask(1L<<2);
1298
1299 if (mappingNotifyInterest) {
1300 XtPerDisplay pd = _XtGetPerDisplay(XtDisplay(widget)(((widget)->core.screen)->display));
1301 if (pd->mapping_callbacks)
1302 _XtAddCallbackOnce(&(pd->mapping_callbacks),
1303 DispatchMappingNotify,
1304 (XtPointer)widget);
1305 else
1306 _XtAddCallback(&(pd->mapping_callbacks),
1307 DispatchMappingNotify,
1308 (XtPointer)widget);
1309
1310 if (widget->core.destroy_callbacks != NULL((void*)0))
1311 _XtAddCallbackOnce( (InternalCallbackList *)
1312 &widget->core.destroy_callbacks,
1313 RemoveFromMappingCallbacks,
1314 (XtPointer)widget
1315 );
1316 else
1317 _XtAddCallback((InternalCallbackList *)
1318 &widget->core.destroy_callbacks,
1319 RemoveFromMappingCallbacks,
1320 (XtPointer)widget
1321 );
1322 }
1323 _XtBindActions(widget, (XtTM)&widget->core.tm);
1324 _XtRegisterGrabs(widget);
1325}
1326
1327void _XtRemoveTranslations(
1328 Widget widget)
1329{
1330 Cardinal i;
1331 TMSimpleStateTree stateTree;
1332 Boolean mappingNotifyInterest = False0;
1333 XtTranslations xlations = widget->core.tm.translations;
1334
1335 if (xlations == NULL((void*)0))
1336 return;
1337
1338 for (i = 0;
1339 i < xlations->numStateTrees;
1340 i++)
1341 {
1342 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[i];
1343 mappingNotifyInterest |= stateTree->mappingNotifyInterest;
1344 }
1345 if (mappingNotifyInterest)
1346 RemoveFromMappingCallbacks(widget, (XtPointer)widget, NULL((void*)0));
1347}
1348
1349static void _XtUninstallTranslations(
1350 Widget widget)
1351{
1352 XtTranslations xlations = widget->core.tm.translations;
1353
1354 _XtUnbindActions(widget,
1355 xlations,
1356 (TMBindData)widget->core.tm.proc_table);
1357 _XtRemoveTranslations(widget);
1358 widget->core.tm.translations = NULL((void*)0);
1359 FreeContext((TMContext *)&widget->core.tm.current_state);
1360}
1361
1362void _XtDestroyTMData(
1363 Widget widget)
1364{
1365 TMComplexBindData cBindData;
1366
1367 _XtUninstallTranslations(widget);
1368
1369 if ((cBindData = (TMComplexBindData)widget->core.tm.proc_table)) {
1370 if (cBindData->isComplex) {
1371 ATranslations aXlations, nXlations;
1372
1373 nXlations = (ATranslations) cBindData->accel_context;
1374 while (nXlations){
1375 aXlations = nXlations;
1376 nXlations = nXlations->next;
1377 XtFree((char *)aXlations);
1378 }
1379 }
1380 XtFree((char *)cBindData);
1381 }
1382}
1383
1384/*** Public procedures ***/
1385
1386
1387void XtUninstallTranslations(
1388 Widget widget)
1389{
1390 EventMask oldMask;
1391 Widget hookobj;
1392 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1393
1394 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1395 if (! widget->core.tm.translations) {
1396 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1397 return;
1398 }
1399 oldMask = widget->core.tm.translations->eventMask;
1400 _XtUninstallTranslations(widget);
1401 if (XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
&& oldMask)
1402 XSelectInput(XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window),
1403 XtBuildEventMask(widget));
1404 hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)((((Object)(widget))->object.widget_class->core_class.class_inited
& 0x04) ? (widget)->core.screen->display : _XtIsHookObject
(widget) ? ((HookObject)(widget))->hooks.screen->display
: _XtWindowedAncestor(widget)->core.screen->display)
);
1405 if (XtHasCallbacks(hookobj, XtNchangeHook((char*)&XtStrings[2061])) == XtCallbackHasSome) {
1406 XtChangeHookDataRec call_data;
1407
1408 call_data.type = XtHuninstallTranslations((char*)&XtStrings[2445]);
1409 call_data.widget = widget;
1410 XtCallCallbackList(hookobj,
1411 ((HookObject)hookobj)->hooks.changehook_callbacks,
1412 (XtPointer)&call_data);
1413 }
1414 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1415}
1416
1417XtTranslations _XtCreateXlations(
1418 TMStateTree *stateTrees,
1419 TMShortCard numStateTrees,
1420 XtTranslations first,
1421 XtTranslations second)
1422{
1423 XtTranslations xlations;
1424 TMShortCard i;
1425
1426 xlations = (XtTranslations)
1427 __XtMalloc(sizeof(TranslationData) +
1428 (numStateTrees-1) * sizeof(TMStateTree));
1429#ifdef TRACE_TM
1430 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1431 if (_XtGlobalTM.numTms == _XtGlobalTM.tmTblSize) {
1432 _XtGlobalTM.tmTblSize += 16;
1433 _XtGlobalTM.tmTbl = (XtTranslations *)
1434 XtRealloc((char *)_XtGlobalTM.tmTbl,
1435 _XtGlobalTM.tmTblSize * sizeof(XtTranslations));
1436 }
1437 _XtGlobalTM.tmTbl[_XtGlobalTM.numTms++] = xlations;
1438 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1439#endif /* TRACE_TM */
1440
1441 xlations->composers[0] = first;
1442 xlations->composers[1] = second;
1443 xlations->hasBindings = False0;
1444 xlations->operation = XtTableReplace0;
1445
1446 for (i = 0;i < numStateTrees; i++)
1447 {
1448 xlations->stateTreeTbl[i] = (TMStateTree) stateTrees[i];
1449 stateTrees[i]->simple.refCount++;
1450 }
1451 xlations->numStateTrees = numStateTrees;
1452 xlations->eventMask = 0;
1453 return xlations;
1454}
1455
1456TMStateTree _XtParseTreeToStateTree(
1457 TMParseStateTree parseTree)
1458{
1459 TMSimpleStateTree simpleTree;
1460 unsigned int tableSize;
1461
1462 if (parseTree->numComplexBranchHeads) {
1463 TMComplexStateTree complexTree;
1464
1465 complexTree = XtNew(TMComplexStateTreeRec)((TMComplexStateTreeRec *) XtMalloc((unsigned) sizeof(TMComplexStateTreeRec
)))
;
1466 complexTree->isSimple = False0;
1467 tableSize = parseTree->numComplexBranchHeads * sizeof(StatePtr);
1468 complexTree->complexBranchHeadTbl = (StatePtr *)
1469 __XtMalloc(tableSize);
1470 XtMemmove(complexTree->complexBranchHeadTbl,if ((char *)(complexTree->complexBranchHeadTbl) != (char *
)(parseTree->complexBranchHeadTbl)) { (void) memcpy((char *
) (complexTree->complexBranchHeadTbl), (char *) (parseTree
->complexBranchHeadTbl), (int) (tableSize)); }
1471 parseTree->complexBranchHeadTbl, tableSize)if ((char *)(complexTree->complexBranchHeadTbl) != (char *
)(parseTree->complexBranchHeadTbl)) { (void) memcpy((char *
) (complexTree->complexBranchHeadTbl), (char *) (parseTree
->complexBranchHeadTbl), (int) (tableSize)); }
;
1472 complexTree->numComplexBranchHeads =
1473 parseTree->numComplexBranchHeads;
1474 simpleTree = (TMSimpleStateTree)complexTree;
1475 }
1476 else {
1477 simpleTree = XtNew(TMSimpleStateTreeRec)((TMSimpleStateTreeRec *) XtMalloc((unsigned) sizeof(TMSimpleStateTreeRec
)))
;
1478 simpleTree->isSimple = True1;
1479 }
1480 simpleTree->isAccelerator = parseTree->isAccelerator;
1481 simpleTree->refCount = 0;
1482 simpleTree->mappingNotifyInterest = parseTree->mappingNotifyInterest;
1483
1484 tableSize = parseTree->numBranchHeads * sizeof(TMBranchHeadRec);
1485 simpleTree->branchHeadTbl = (TMBranchHead)
1486 __XtMalloc(tableSize);
1487 XtMemmove(simpleTree->branchHeadTbl, parseTree->branchHeadTbl, tableSize)if ((char *)(simpleTree->branchHeadTbl) != (char *)(parseTree
->branchHeadTbl)) { (void) memcpy((char *) (simpleTree->
branchHeadTbl), (char *) (parseTree->branchHeadTbl), (int)
(tableSize)); }
;
1488 simpleTree->numBranchHeads = parseTree->numBranchHeads;
1489
1490 tableSize = parseTree->numQuarks * sizeof(XrmQuark);
1491 simpleTree->quarkTbl = (XrmQuark *) __XtMalloc(tableSize);
1492 XtMemmove(simpleTree->quarkTbl, parseTree->quarkTbl, tableSize)if ((char *)(simpleTree->quarkTbl) != (char *)(parseTree->
quarkTbl)) { (void) memcpy((char *) (simpleTree->quarkTbl)
, (char *) (parseTree->quarkTbl), (int) (tableSize)); }
;
1493 simpleTree->numQuarks = parseTree->numQuarks;
1494
1495 return (TMStateTree)simpleTree;
1496}
1497
1498static void FreeActions(
1499 ActionPtr actions)
1500{
1501 ActionPtr action;
1502 TMShortCard i;
1503 for (action = actions; action;) {
1504 ActionPtr nextAction = action->next;
1505 for (i = action->num_params; i;) {
1506 XtFree( action->params[--i] );
1507 }
1508 XtFree( (char*)action->params );
1509 XtFree((char*) action);
1510 action = nextAction;
1511 }
1512}
1513
1514/*ARGSUSED*/
1515static void AmbigActions(
1516 EventSeqPtr initialEvent,
1517 StatePtr *state,
1518 TMParseStateTree stateTree)
1519{
1520 String params[3];
1521 Cardinal numParams = 0;
1522
1523 params[numParams++] = _XtPrintEventSeq(initialEvent, NULL((void*)0));
1524 params[numParams++] = _XtPrintActions((*state)->actions,
1525 stateTree->quarkTbl);
1526 XtWarningMsg (XtNtranslationError,"oldActions",XtCXtToolkitError,
1527 "Previous entry was: %s %s", params, &numParams);
1528 XtFree((char *)params[0]);
1529 XtFree((char *)params[1]);
1530 numParams = 0;
1531 params[numParams++] = _XtPrintActions(initialEvent->actions,
1532 stateTree->quarkTbl);
1533 XtWarningMsg (XtNtranslationError,"newActions",XtCXtToolkitError,
1534 "New actions are:%s", params, &numParams);
1535 XtFree((char *)params[0]);
1536 XtWarningMsg (XtNtranslationError,"ambiguousActions",
1537 XtCXtToolkitError,
1538 "Overriding earlier translation manager actions.",
1539 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1540
1541 FreeActions((*state)->actions);
1542 (*state)->actions = NULL((void*)0);
1543}
1544
1545
1546void _XtAddEventSeqToStateTree(
1547 EventSeqPtr eventSeq,
1548 TMParseStateTree stateTree)
1549{
1550 StatePtr *state;
1551 EventSeqPtr initialEvent = eventSeq;
1552 TMBranchHead branchHead;
1553 TMShortCard idx, modIndex, typeIndex;
1554
1555 if (eventSeq == NULL((void*)0)) return;
1556
1557 /* note that all states in the event seq passed in start out null */
1558 /* we fill them in with the matching state as we traverse the list */
1559
1560 /*
1561 * We need to free the parser data structures !!!
1562 */
1563
1564 typeIndex = _XtGetTypeIndex(&eventSeq->event);
1565 modIndex = _XtGetModifierIndex(&eventSeq->event);
1566 idx = GetBranchHead(stateTree, typeIndex, modIndex, False0);
1567 branchHead = &stateTree->branchHeadTbl[idx];
1568
1569 /*
1570 * Need to check for pre-existing actions with same lhs |||
1571 */
1572
1573 /*
1574 * Check for optimized case. Don't assume that the eventSeq has actions.
1575 */
1576 if (!eventSeq->next &&
1577 eventSeq->actions &&
1578 !eventSeq->actions->next &&
1579 !eventSeq->actions->num_params)
1580 {
1581 if (eventSeq->event.eventType == MappingNotify34)
1582 stateTree->mappingNotifyInterest = True1;
1583 branchHead->hasActions = True1;
1584 branchHead->more = eventSeq->actions->idx;
1585 FreeActions(eventSeq->actions);
1586 eventSeq->actions = NULL((void*)0);
1587 return;
1588 }
1589
1590 branchHead->isSimple = False0;
1591 if (!eventSeq->next)
1592 branchHead->hasActions = True1;
1593 branchHead->more = GetComplexBranchIndex(stateTree, typeIndex, modIndex);
1594 state = &stateTree->complexBranchHeadTbl[TMBranchMore(branchHead)(branchHead->more)];
1595
1596 for (;;) {
1597 *state = NewState(stateTree, typeIndex, modIndex);
1598
1599 if (eventSeq->event.eventType == MappingNotify34)
1600 stateTree->mappingNotifyInterest = True1;
1601
1602 /* *state now points at state record matching event */
1603 eventSeq->state = *state;
1604
1605 if (eventSeq->actions != NULL((void*)0)) {
1606 if ((*state)->actions != NULL((void*)0))
1607 AmbigActions(initialEvent, state, stateTree);
1608 (*state)->actions = eventSeq->actions;
1609#ifdef TRACE_TM
1610 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)()
1611 _XtGlobalTM.numComplexActions++;
1612 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1613#endif /* TRACE_TM */
1614 }
1615
1616 if (((eventSeq = eventSeq->next) == NULL((void*)0)) || (eventSeq->state))
1617 break;
1618
1619 state = &(*state)->nextLevel;
1620 typeIndex = _XtGetTypeIndex(&eventSeq->event);
1621 modIndex = _XtGetModifierIndex(&eventSeq->event);
1622 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1623 if (!TMNewMatchSemantics()(_XtGlobalTM.newMatchSemantics)) {
1624 /*
1625 * force a potential empty entry into the branch head
1626 * table in order to emulate old matching behavior
1627 */
1628 (void) GetBranchHead(stateTree, typeIndex, modIndex, True1);
1629 }
1630 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1631 }
1632
1633 if (eventSeq && eventSeq->state) {
1634 /* we've been here before... must be a cycle in the event seq. */
1635 branchHead->hasCycles = True1;
1636 (*state)->nextLevel = eventSeq->state;
1637 eventSeq->state->isCycleStart = True1;
1638 (*state)->isCycleEnd = TRUE1;
1639 }
1640}
1641
1642
1643/*
1644 * Internal Converter for merging. Old and New must both be valid xlations
1645 */
1646
1647/*ARGSUSED*/
1648Boolean _XtCvtMergeTranslations(
1649 Display *dpy,
1650 XrmValuePtr args,
1651 Cardinal *num_args,
1652 XrmValuePtr from,
1653 XrmValuePtr to,
1654 XtPointer *closure_ret)
1655{
1656 XtTranslations first, second, xlations;
1657 TMStateTree *stateTrees, stackStateTrees[16];
1658 TMShortCard numStateTrees, i;
1659
1660 if (*num_args != 0)
1661 XtWarningMsg("invalidParameters","mergeTranslations",XtCXtToolkitError,
1662 "MergeTM to TranslationTable needs no extra arguments",
1663 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1664
1665 if (to->addr != NULL((void*)0) && to->size < sizeof(XtTranslations)) {
1666 to->size = sizeof(XtTranslations);
1667 return False0;
1668 }
1669
1670 first = ((TMConvertRec*)from->addr)->old;
1671 second = ((TMConvertRec*)from->addr)->new;
1672
1673 numStateTrees = first->numStateTrees + second->numStateTrees;
1674
1675 stateTrees = (TMStateTree *)
1676 XtStackAlloc(numStateTrees * sizeof(TMStateTree), stackStateTrees)((numStateTrees * sizeof(TMStateTree)) <= sizeof(stackStateTrees
) ? (XtPointer)(stackStateTrees) : XtMalloc((unsigned)(numStateTrees
* sizeof(TMStateTree))))
;
1677
1678 for (i = 0; i < first->numStateTrees; i++)
1679 stateTrees[i] = first->stateTreeTbl[i];
1680 for (i = 0; i < second->numStateTrees; i++)
1681 stateTrees[i + first->numStateTrees] = second->stateTreeTbl[i];
1682
1683 xlations = _XtCreateXlations(stateTrees, numStateTrees, first, second);
1684
1685 if (to->addr != NULL((void*)0)) {
1686 *(XtTranslations*)to->addr = xlations;
1687 }
1688 else {
1689 static XtTranslations staticStateTable;
1690 staticStateTable = xlations;
1691 to->addr= (XPointer)&staticStateTable;
1692 to->size = sizeof(XtTranslations);
1693 }
1694
1695 XtStackFree((XtPointer)stateTrees, (XtPointer)stackStateTrees){ if (((XtPointer)stateTrees) != ((XtPointer)((XtPointer)stackStateTrees
))) XtFree((XtPointer)stateTrees); }
;
1696 return True1;
1697}
1698
1699
1700static XtTranslations MergeThem(
1701 Widget dest,
1702 XtTranslations first,
1703 XtTranslations second)
1704{
1705 XtCacheRef cache_ref;
1706 static XrmQuark from_type = NULLQUARK((XrmQuark) 0), to_type;
1707 XrmValue from, to;
1708 TMConvertRec convert_rec;
1709 XtTranslations newTable;
1710
1711 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1712 if (from_type == NULLQUARK((XrmQuark) 0)) {
1713 from_type = XrmPermStringToQuark(_XtRStateTablePair"_XtStateTablePair");
1714 to_type = XrmPermStringToQuark(XtRTranslationTable((char*)&XtStrings[1841]));
1715 }
1716 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1717 from.addr = (XPointer)&convert_rec;
1718 from.size = sizeof(TMConvertRec);
1719 to.addr = (XPointer)&newTable;
1720 to.size = sizeof(XtTranslations);
1721 convert_rec.old = first;
1722 convert_rec.new = second;
1723
1724 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1725 if (! _XtConvert(dest, from_type, &from, to_type, &to, &cache_ref)) {
1726 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1727 return NULL((void*)0);
1728 }
1729 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1730
1731#ifndef REFCNT_TRANSLATIONS
1732
1733 if (cache_ref)
1734 XtAddCallback(dest, XtNdestroyCallback((char*)&XtStrings[169]),
1735 XtCallbackReleaseCacheRef, (XtPointer)cache_ref);
1736
1737#endif
1738
1739 return newTable;
1740}
1741
1742/*
1743 * Unmerge will recursively traverse the xlation compose tree and
1744 * generate a new xlation that is the result of all instances of
1745 * xlations being removed. It currently doesn't differentiate between
1746 * the potential that an xlation will be both an accelerator and
1747 * normal. This is not supported by the spec anyway.
1748 */
1749static XtTranslations UnmergeTranslations(
1750 Widget widget,
1751 XtTranslations xlations,
1752 XtTranslations unmergeXlations,
1753 TMShortCard currIndex,
1754 TMComplexBindProcs oldBindings,
1755 TMShortCard numOldBindings,
1756 TMComplexBindProcs newBindings,
1757 TMShortCard *numNewBindingsRtn)
1758
1759{
1760 XtTranslations first, second, result;
1761
1762 if (!xlations || (xlations == unmergeXlations))
1763 return NULL((void*)0);
1764
1765 if (xlations->composers[0]) {
1766 first = UnmergeTranslations(widget, xlations->composers[0],
1767 unmergeXlations, currIndex,
1768 oldBindings, numOldBindings,
1769 newBindings, numNewBindingsRtn);
1770 }
1771 else
1772 first = NULL((void*)0);
1773
1774 if (xlations->composers[1]) {
1775 second = UnmergeTranslations(widget, xlations->composers[1],
1776 unmergeXlations,
1777 currIndex +
1778 xlations->composers[0]->numStateTrees,
1779 oldBindings, numOldBindings,
1780 newBindings, numNewBindingsRtn);
1781 }
1782 else
1783 second = NULL((void*)0);
1784
1785 if (first || second) {
1786 if (first && second) {
1787 if ((first != xlations->composers[0]) ||
1788 (second != xlations->composers[1]))
1789 result = MergeThem(widget, first, second);
1790 else result = xlations;
1791 }
1792 else {
1793 if (first)
1794 result = first;
1795 else
1796 result = second;
1797 }
1798 } else { /* only update for leaf nodes */
1799 if (numOldBindings) {
1800 Cardinal i;
1801 for (i = 0; i < xlations->numStateTrees; i++) {
1802 if (xlations->stateTreeTbl[i]->simple.isAccelerator)
1803 newBindings[*numNewBindingsRtn] =
1804 oldBindings[currIndex + i];
1805 (*numNewBindingsRtn)++;
1806 }
1807 }
1808 result = xlations;
1809 }
1810 return result;
1811}
1812
1813typedef struct {
1814 XtTranslations xlations;
1815 TMComplexBindProcs bindings;
1816}MergeBindRec, *MergeBind;
1817
1818static XtTranslations MergeTranslations(
1819 Widget widget,
1820 XtTranslations oldXlations,
1821 XtTranslations newXlations,
1822 _XtTranslateOp operation,
1823 Widget source,
1824 TMComplexBindProcs oldBindings,
1825 TMComplexBindProcs newBindings,
1826 TMShortCard *numNewRtn)
1827{
1828 XtTranslations newTable = NULL((void*)0), xlations;
1829 TMComplexBindProcs bindings;
1830 TMShortCard i, j;
1831 TMStateTree *treePtr;
1832 TMShortCard numNew = *numNewRtn;
1833 MergeBindRec bindPair[2];
1834
1835 /* If the new translation has an accelerator context then pull it
1836 * off and pass it and the real xlations in to the caching merge
1837 * routine.
1838 */
1839 if (newXlations->hasBindings) {
1840 xlations = ((ATranslations) newXlations)->xlations;
1841 bindings = (TMComplexBindProcs)
1842 &((ATranslations) newXlations)->bindTbl[0];
1843 }
1844 else {
1845 xlations = newXlations;
1846 bindings = NULL((void*)0);
1847 }
1848 switch(operation) {
1849 case XtTableReplace0:
1850 newTable = bindPair[0].xlations = xlations;
1851 bindPair[0].bindings = bindings;
1852 bindPair[1].xlations = NULL((void*)0);
1853 bindPair[1].bindings = NULL((void*)0);
1854 break;
1855 case XtTableAugment1:
1856 bindPair[0].xlations = oldXlations;
1857 bindPair[0].bindings = oldBindings;
1858 bindPair[1].xlations = xlations;
1859 bindPair[1].bindings = bindings;
1860 newTable = NULL((void*)0);
1861 break;
1862 case XtTableOverride2:
1863 bindPair[0].xlations = xlations;
1864 bindPair[0].bindings = bindings;
1865 bindPair[1].xlations = oldXlations;
1866 bindPair[1].bindings = oldBindings;
1867 newTable = NULL((void*)0);
1868 break;
1869 }
1870 if (!newTable)
1871 newTable = MergeThem(widget, bindPair[0].xlations, bindPair[1].xlations);
1872
1873 for (i = 0, numNew = 0; i < 2; i++) {
1874 if (bindPair[i].xlations)
1875 for (j = 0; j < bindPair[i].xlations->numStateTrees; j++, numNew++) {
1876 if (bindPair[i].xlations->stateTreeTbl[j]->simple.isAccelerator) {
1877 if (bindPair[i].bindings)
1878 newBindings[numNew] = bindPair[i].bindings[j];
1879 else {
1880 newBindings[numNew].widget = source;
1881 newBindings[numNew].aXlations =
1882 bindPair[i].xlations;
1883 }
1884 }
1885 }
1886 }
1887 *numNewRtn = numNew;
1888 treePtr = &newTable->stateTreeTbl[0];
1889 for (i = 0; i < newTable->numStateTrees; i++, treePtr++)
1890 (*treePtr)->simple.refCount++;
1891 return newTable;
1892}
1893
1894static TMBindData MakeBindData(
1895 TMComplexBindProcs bindings,
1896 TMShortCard numBindings,
1897 TMBindData oldBindData)
1898{
1899 TMLongCard bytes;
1900 TMShortCard i;
1901 Boolean isComplex;
1902 TMBindData bindData;
1903
1904 if (numBindings == 0)
1905 return NULL((void*)0);
1906 for (i = 0; i < numBindings; i++)
1907 if (bindings[i].widget)
1908 break;
1909 isComplex = (i < numBindings);
1910 if (isComplex)
1911 bytes = (sizeof(TMComplexBindDataRec) +
1912 ((numBindings - 1) *
1913 sizeof(TMComplexBindProcsRec)));
1914 else
1915 bytes = (sizeof(TMSimpleBindDataRec) +
1916 ((numBindings - 1) *
1917 sizeof(TMSimpleBindProcsRec)));
1918
1919 bindData = (TMBindData) __XtCalloc(sizeof(char), bytes);
1920 bindData->simple.isComplex = isComplex;
1921 if (isComplex) {
1922 TMComplexBindData cBindData = (TMComplexBindData)bindData;
1923 /*
1924 * If there were any accelerator contexts in the old bindData
1925 * then propagate them to the new one.
1926 */
1927 if (oldBindData && oldBindData->simple.isComplex)
1928 cBindData->accel_context =
1929 ((TMComplexBindData) oldBindData)->accel_context;
1930 XtMemmove((char *)&cBindData->bindTbl[0], (char *)bindings,if ((char *)((char *)&cBindData->bindTbl[0]) != (char *
)((char *)bindings)) { (void) memcpy((char *) ((char *)&cBindData
->bindTbl[0]), (char *) ((char *)bindings), (int) (numBindings
* sizeof(TMComplexBindProcsRec))); }
1931 numBindings * sizeof(TMComplexBindProcsRec))if ((char *)((char *)&cBindData->bindTbl[0]) != (char *
)((char *)bindings)) { (void) memcpy((char *) ((char *)&cBindData
->bindTbl[0]), (char *) ((char *)bindings), (int) (numBindings
* sizeof(TMComplexBindProcsRec))); }
;
1932 }
1933 return bindData;
1934}
1935
1936/*
1937 * This routine is the central clearinghouse for merging translations
1938 * into a widget. It takes care of preping the action bindings for
1939 * realize time and calling the converter or doing a straight merge if
1940 * the destination is empty.
1941 */
1942static Boolean ComposeTranslations(
1943 Widget dest,
1944 _XtTranslateOp operation,
1945 Widget source,
1946 XtTranslations newXlations)
1947{
1948 XtTranslations newTable, oldXlations;
1949 XtTranslations accNewXlations;
1950 EventMask oldMask = 0;
1951 TMBindData bindData;
1952 TMComplexBindProcs oldBindings = NULL((void*)0);
1953 TMShortCard numOldBindings = 0, numNewBindings = 0, numBytes;
1954 TMComplexBindProcsRec stackBindings[16], *newBindings;
1955
1956 /*
1957 * how should we be handling the refcount decrement for the
1958 * replaced translation table ???
1959 */
1960 if (!newXlations)
1961 {
1962 XtAppWarningMsg(XtWidgetToApplicationContext(dest),
1963 XtNtranslationError,"nullTable",XtCXtToolkitError,
1964 "table to (un)merge must not be null",
1965 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
1966 return False0;
1967 }
1968
1969 accNewXlations = newXlations;
1970 newXlations = ((newXlations->hasBindings)
1971 ? ((ATranslations)newXlations)->xlations
1972 : newXlations);
1973
1974 if (!(oldXlations = dest->core.tm.translations))
1975 operation = XtTableReplace0;
1976
1977 /*
1978 * try to avoid generation of duplicate state trees. If the source
1979 * isn't simple (1 state Tree) then it's too much hassle
1980 */
1981 if (((operation == XtTableAugment1) ||
1982 (operation == XtTableOverride2)) &&
1983 (newXlations->numStateTrees == 1)) {
1984 Cardinal i;
1985 for (i = 0; i < oldXlations->numStateTrees; i++)
1986 if (oldXlations->stateTreeTbl[i] ==
1987 newXlations->stateTreeTbl[0])
1988 break;
1989 if (i < oldXlations->numStateTrees) {
1990 if (operation == XtTableAugment1) {
1991 /*
1992 * we don't need to do anything since it's already
1993 * there
1994 */
1995 return True1;
1996 }
1997 else {/* operation == XtTableOverride */
1998 /*
1999 * We'll get rid of the duplicate trees throughout the
2000 * and leave it with a pruned translation table. This
2001 * will only work if the same table has been merged
2002 * into this table (or one of it's composers
2003 */
2004 _XtUnmergeTranslations(dest, newXlations);
2005 /*
2006 * reset oldXlations so we're back in sync
2007 */
2008 if (!(oldXlations = dest->core.tm.translations))
2009 operation = XtTableReplace0;
2010 }
2011 }
2012 }
2013
2014 bindData = (TMBindData) dest->core.tm.proc_table;
2015 if (bindData) {
2016 numOldBindings = (oldXlations ? oldXlations->numStateTrees : 0);
2017 if (bindData->simple.isComplex)
2018 oldBindings = &((TMComplexBindData)bindData)->bindTbl[0];
2019 else
2020 oldBindings = (TMComplexBindProcs)
2021 (&((TMSimpleBindData)bindData)->bindTbl[0]);
2022 }
2023
2024 numBytes =(((oldXlations ? oldXlations->numStateTrees : 0)
2025 + newXlations->numStateTrees) * sizeof(TMComplexBindProcsRec));
2026 newBindings = (TMComplexBindProcs) XtStackAlloc(numBytes, stackBindings)((numBytes) <= sizeof(stackBindings) ? (XtPointer)(stackBindings
) : XtMalloc((unsigned)(numBytes)))
;
2027 XtBZero((char *)newBindings, numBytes)memset((char *) ((char *)newBindings),0,(int) (numBytes));
2028
2029 if (operation == XtTableUnmerge3) {
2030 newTable = UnmergeTranslations(dest,
2031 oldXlations,
2032 newXlations,
2033 0,
2034 oldBindings, numOldBindings,
2035 newBindings, &numNewBindings);
2036#ifdef DEBUG
2037 /* check for no match for unmerge */
2038 if (newTable == oldXlations) {
2039 XtWarning("attempt to unmerge invalid table");
2040 XtStackFree((char *)newBindings, (char *)stackBindings){ if (((char *)newBindings) != ((XtPointer)((char *)stackBindings
))) XtFree((char *)newBindings); }
;
2041 return(newTable != NULL((void*)0));
2042 }
2043#endif /* DEBUG */
2044 }
2045 else {
2046 newTable = MergeTranslations(dest,
2047 oldXlations,
2048 accNewXlations,
2049 operation,
2050 source,
2051 oldBindings,
2052 newBindings,
2053 &numNewBindings);
2054 }
2055 if (XtIsRealized(dest)((((((Object)(dest))->object.widget_class->core_class.class_inited
& 0x04) ? (dest) : _XtWindowedAncestor(dest)) ->core.
window) != 0L)
) {
2056 oldMask = 0;
2057 if (oldXlations)
2058 oldMask = oldXlations->eventMask;
2059 _XtUninstallTranslations(dest);
2060 }
2061
2062 dest->core.tm.proc_table =
2063 (XtActionProc *) MakeBindData(newBindings, numNewBindings, bindData);
2064
2065 if (bindData) XtFree((char *)bindData);
2066
2067 dest->core.tm.translations = newTable;
2068
2069 if (XtIsRealized(dest)((((((Object)(dest))->object.widget_class->core_class.class_inited
& 0x04) ? (dest) : _XtWindowedAncestor(dest)) ->core.
window) != 0L)
) {
2070 EventMask mask = 0;
2071 _XtInstallTranslations(dest);
2072 if (newTable)
2073 mask = newTable->eventMask;
2074 if (mask != oldMask)
2075 XSelectInput(XtDisplay(dest)(((dest)->core.screen)->display), XtWindow(dest)((dest)->core.window),
2076 XtBuildEventMask(dest));
2077 }
2078 XtStackFree((XtPointer)newBindings, (XtPointer)stackBindings){ if (((XtPointer)newBindings) != ((XtPointer)((XtPointer)stackBindings
))) XtFree((XtPointer)newBindings); }
;
2079 return(newTable != NULL((void*)0));
2080}
2081
2082/*
2083 * If a GetValues is done on a translation resource that contains
2084 * accelerators we need to return the accelerator context in addition
2085 * to the pure translations. Since this means returning memory that
2086 * the client controlls but we still own, we will track the "headers"
2087 * that we return (via a linked list pointed to from the bindData) and
2088 * free it at destroy time.
2089 */
2090XtTranslations _XtGetTranslationValue(
2091 Widget w)
2092{
2093 XtTM tmRecPtr = (XtTM) &w->core.tm;
2094 ATranslations *aXlationsPtr;
2095 TMComplexBindData cBindData = (TMComplexBindData) tmRecPtr->proc_table;
2096 XtTranslations xlations = tmRecPtr->translations;
2097
2098 if (!xlations || !cBindData || !cBindData->isComplex)
2099 return xlations;
2100
2101 /* Walk the list looking to see if we already have generated a
2102 * header for the currently installed translations. If we have,
2103 * just return that header. Otherwise create a new header.
2104 */
2105 for (aXlationsPtr = (ATranslations *) &cBindData->accel_context;
2106 *aXlationsPtr && (*aXlationsPtr)->xlations != xlations;
2107 aXlationsPtr = &(*aXlationsPtr)->next)
2108 ;
2109 if (*aXlationsPtr)
2110 return (XtTranslations) *aXlationsPtr;
2111 else {
2112 /* create a new aXlations context */
2113 ATranslations aXlations;
2114 Cardinal numBindings = xlations->numStateTrees;
2115
2116 (*aXlationsPtr) = aXlations = (ATranslations)
2117 __XtMalloc(sizeof(ATranslationData) +
2118 (numBindings - 1) * sizeof(TMComplexBindProcsRec));
2119
2120 aXlations->hasBindings = True1;
2121 aXlations->xlations = xlations;
2122 aXlations->next = NULL((void*)0);
2123 XtMemmove((char *) &aXlations->bindTbl[0],if ((char *)((char *) &aXlations->bindTbl[0]) != (char
*)((char *) &cBindData->bindTbl[0])) { (void) memcpy(
(char *) ((char *) &aXlations->bindTbl[0]), (char *) (
(char *) &cBindData->bindTbl[0]), (int) (numBindings *
sizeof(TMComplexBindProcsRec))); }
2124 (char *) &cBindData->bindTbl[0],if ((char *)((char *) &aXlations->bindTbl[0]) != (char
*)((char *) &cBindData->bindTbl[0])) { (void) memcpy(
(char *) ((char *) &aXlations->bindTbl[0]), (char *) (
(char *) &cBindData->bindTbl[0]), (int) (numBindings *
sizeof(TMComplexBindProcsRec))); }
2125 numBindings * sizeof(TMComplexBindProcsRec))if ((char *)((char *) &aXlations->bindTbl[0]) != (char
*)((char *) &cBindData->bindTbl[0])) { (void) memcpy(
(char *) ((char *) &aXlations->bindTbl[0]), (char *) (
(char *) &cBindData->bindTbl[0]), (int) (numBindings *
sizeof(TMComplexBindProcsRec))); }
;
2126 return (XtTranslations) aXlations;
2127 }
2128}
2129
2130
2131/*ARGSUSED*/
2132static void RemoveStateTree(
2133 TMStateTree tree)
2134{
2135#ifdef REFCNT_TRANSLATIONS
2136 TMComplexStateTree stateTree = (TMComplexStateTree)tree;
2137
2138 if (--stateTree->refCount == 0) {
2139 /*
2140 * should we free/refcount the match recs ?
2141 */
2142 if (!stateTree->isSimple) {
2143 StatePtr currState, nextState;
2144 TMShortCard i;
2145 for (i = 0; i < stateTree->numComplexBranchHeads; i++) {
2146 currState =
2147 nextState =
2148 stateTree->complexBranchHeadTbl[i];
2149 for (; nextState;){
2150 FreeActions(currState->actions);
2151 currState->actions = NULL((void*)0);
2152 if (!currState->isCycleEnd)
2153 nextState = currState->nextLevel;
2154 else
2155 nextState = NULL((void*)0);
2156 XtFree( (char*)currState );
2157 }
2158 }
2159 XtFree((char*)stateTree->complexBranchHeadTbl);
2160 }
2161 XtFree((char*)stateTree->branchHeadTbl);
2162 XtFree((char*)stateTree);
2163 }
2164#endif /* REFCNT_TRANSLATIONS */
2165}
2166
2167void _XtRemoveStateTreeByIndex(
2168 XtTranslations xlations,
2169 TMShortCard i)
2170{
2171 TMStateTree *stateTrees = xlations->stateTreeTbl;
2172
2173 RemoveStateTree(stateTrees[i]);
2174 xlations->numStateTrees--;
2175
2176 for (; i < xlations->numStateTrees; i++)
2177 {
2178 stateTrees[i] = stateTrees[i+1];
2179 }
2180}
2181
2182/* ARGSUSED */
2183void _XtFreeTranslations(
2184 XtAppContext app,
2185 XrmValuePtr toVal,
2186 XtPointer closure,
2187 XrmValuePtr args,
2188 Cardinal *num_args)
2189{
2190 XtTranslations xlations;
2191 int i;
2192
2193 if (*num_args != 0)
2194 XtAppWarningMsg(app,
2195 "invalidParameters","freeTranslations",XtCXtToolkitError,
2196 "Freeing XtTranslations requires no extra arguments",
2197 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
2198
2199 xlations = *(XtTranslations*)toVal->addr;
2200 for (i = 0; i < (int)xlations->numStateTrees; i++)
2201 RemoveStateTree(xlations->stateTreeTbl[i]);
2202 XtFree((char *)xlations);
2203}
2204
2205/* The spec is not clear on when actions specified in accelerators are bound;
2206 * Bind them at Realize the same as translations
2207 */
2208void XtInstallAccelerators(
2209 Widget destination, Widget source)
2210{
2211 XtTranslations aXlations;
2212 _XtTranslateOp op;
2213 String buf;
2214 WIDGET_TO_APPCON(destination)XtAppContext app = (destination && _XtProcessLock ? XtWidgetToApplicationContext
(destination) : ((void*)0))
;
2215
2216 /*
2217 * test that it was parsed as an accelarator table. Even though
2218 * there doesn't need to be a distinction it makes life easier if
2219 * we honor the spec implication that aXlations is an accelerator
2220 */
2221 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
2222 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2223 if ((!XtIsWidget(source)(((Object)(source))->object.widget_class->core_class.class_inited
& 0x04)
) ||
2224 ((aXlations = source->core.accelerators) == NULL((void*)0)) ||
2225 (aXlations->stateTreeTbl[0]->simple.isAccelerator == False0)) {
2226 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2227 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
2228 return;
2229 }
2230
2231 aXlations = source->core.accelerators;
2232 op = aXlations->operation;
2233
2234 if (ComposeTranslations(destination, op, source, aXlations) &&
2235 (XtClass(source)((source)->core.widget_class)->core_class.display_accelerator != NULL((void*)0))) {
2236
2237 buf = _XtPrintXlations(destination, aXlations, source, False0);
2238 (*(XtClass(source)((source)->core.widget_class)->core_class.display_accelerator))(source,buf);
2239 XtFree(buf);
2240 }
2241 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2242 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
2243}
2244
2245void XtInstallAllAccelerators(
2246 Widget destination,
2247 Widget source)
2248{
2249 Cardinal i;
2250 CompositeWidget cw;
2251 WIDGET_TO_APPCON(destination)XtAppContext app = (destination && _XtProcessLock ? XtWidgetToApplicationContext
(destination) : ((void*)0))
;
2252
2253 /* Recurse down normal children */
2254 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
2255 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2256 if (XtIsComposite(source)(((Object)(source))->object.widget_class->core_class.class_inited
& 0x08)
) {
2257 cw = (CompositeWidget) source;
2258 for (i = 0; i < cw->composite.num_children; i++) {
2259 XtInstallAllAccelerators(destination,cw->composite.children[i]);
2260 }
2261 }
2262
2263 /* Recurse down popup children */
2264 if (XtIsWidget(source)(((Object)(source))->object.widget_class->core_class.class_inited
& 0x04)
) {
2265 for (i = 0; i < source->core.num_popups; i++) {
2266 XtInstallAllAccelerators(destination,source->core.popup_list[i]);
2267 }
2268 }
2269 /* Finally, apply procedure to this widget */
2270 XtInstallAccelerators(destination,source);
2271 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2272 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
2273}
2274
2275#if 0 /* dead code */
2276static _XtTranslateOp _XtGetTMOperation(
2277 XtTranslations xlations)
2278{
2279 return ((xlations->hasBindings)
2280 ? ((ATranslations)xlations)->xlations->operation
2281 : xlations->operation);
2282}
2283#endif
2284
2285void XtAugmentTranslations(
2286 Widget widget,
2287 XtTranslations new)
2288{
2289 Widget hookobj;
2290 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
2291
2292 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
2293 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
2294 (void)ComposeTranslations(widget, XtTableAugment1, (Widget)NULL((void*)0), new);
2295 hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)((((Object)(widget))->object.widget_class->core_class.class_inited
& 0x04) ? (widget)->core.screen->display : _XtIsHookObject
(widget) ? ((HookObject)(widget))->hooks.screen->display
: _XtWindowedAncestor(widget)->core.screen->display)
);
2296 if (XtHasCallbacks(hookobj, XtNchangeHook((char*)&XtStrings[2061])) == XtCallbackHasSome) {
2297 XtChangeHookDataRec call_data;
2298
2299 call_data.type = XtHaugmentTranslations((char*)&XtStrings[2400]);
2300 call_data.widget = widget;
2301 XtCallCallbackList(hookobj,
2302 ((HookObject)hookobj)->hooks.changehook_callbacks,
2303 (XtPointer)&call_data);
2304 }
2305 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2306 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
2307}
2308
2309void XtOverrideTranslations(
2310 Widget widget,
2311 XtTranslations new)
2312{
2313 Widget hookobj;
2314 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
2315
2316 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
2317 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1
Within the expansion of the macro 'LOCK_PROCESS':
a
Assuming '_XtProcessLock' is null
2318 (void) ComposeTranslations(widget, XtTableOverride2, (Widget)NULL((void*)0), new);
2319 hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)((((Object)(widget))->object.widget_class->core_class.class_inited
& 0x04) ? (widget)->core.screen->display : _XtIsHookObject
(widget) ? ((HookObject)(widget))->hooks.screen->display
: _XtWindowedAncestor(widget)->core.screen->display)
);
2
Within the expansion of the macro 'XtDisplayOfObject':
a
Dereference of null pointer
2320 if (XtHasCallbacks(hookobj, XtNchangeHook((char*)&XtStrings[2061])) == XtCallbackHasSome) {
2321 XtChangeHookDataRec call_data;
2322
2323 call_data.type = XtHoverrideTranslations((char*)&XtStrings[2422]);
2324 call_data.widget = widget;
2325 XtCallCallbackList(hookobj,
2326 ((HookObject)hookobj)->hooks.changehook_callbacks,
2327 (XtPointer)&call_data);
2328 }
2329 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
2330 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
2331}
2332
2333void _XtMergeTranslations(
2334 Widget widget,
2335 XtTranslations newXlations,
2336 _XtTranslateOp op)
2337{
2338 if (!newXlations){
2339 if (!widget->core.tm.translations)
2340 return;
2341 else {
2342 newXlations = widget->core.tm.translations;
2343 widget->core.tm.translations = NULL((void*)0);
2344 }
2345 }
2346 (void) ComposeTranslations(widget,
2347 op,
2348 (Widget)NULL((void*)0),
2349 newXlations);
2350}
2351
2352void _XtUnmergeTranslations(
2353 Widget widget,
2354 XtTranslations xlations)
2355{
2356 ComposeTranslations(widget, XtTableUnmerge3, (Widget)NULL((void*)0), xlations);
2357}