Bug Summary

File:TMaction.c
Location:line 776, column 17
Description:Access to field 'action_table' results in a dereference of a null pointer (loaded from variable 'app')

Annotated Source Code

1/*LINTLIBRARY*/
2
3/***********************************************************
4Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
5
6Permission is hereby granted, free of charge, to any person obtaining a
7copy of this software and associated documentation files (the "Software"),
8to deal in the Software without restriction, including without limitation
9the rights to use, copy, modify, merge, publish, distribute, sublicense,
10and/or sell copies of the Software, and to permit persons to whom the
11Software is furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice (including the next
14paragraph) shall be included in all copies or substantial portions of the
15Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23DEALINGS IN THE SOFTWARE.
24
25Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27 All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Digital not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45******************************************************************/
46
47/*
48
49Copyright 1987, 1988, 1998 The Open Group
50
51Permission to use, copy, modify, distribute, and sell this software and its
52documentation for any purpose is hereby granted without fee, provided that
53the above copyright notice appear in all copies and that both that
54copyright notice and this permission notice appear in supporting
55documentation.
56
57The above copyright notice and this permission notice shall be included in
58all copies or substantial portions of the Software.
59
60THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
64AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
65CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
66
67Except as contained in this notice, the name of The Open Group shall not be
68used in advertising or otherwise to promote the sale, use or other dealings
69in this Software without prior written authorization from The Open Group.
70
71*/
72
73/* TMaction.c -- maintains the state table of actions for the translation
74 * manager.
75 */
76
77#ifdef HAVE_CONFIG_H1
78#include <config.h>
79#endif
80#include "IntrinsicI.h"
81#include "StringDefs.h"
82
83#if defined(__STDC__1) && !defined(NORCONST)
84#define RConstconst const
85#else
86#define RConstconst /**/
87#endif
88
89static String XtNtranslationError = "translationError";
90
91typedef struct _CompiledAction{
92 XrmQuark signature;
93 XtActionProc proc;
94}CompiledAction, *CompiledActionTable;
95
96
97#define GetClassActions(wc)((wc->core_class.actions) ? (((TMClassCache)wc->core_class
.actions)->actions) : ((void*)0))
\
98 ((wc->core_class.actions) \
99? (((TMClassCache)wc->core_class.actions)->actions) \
100: NULL((void*)0))
101
102static CompiledActionTable CompileActionTable(
103 register RConstconst struct _XtActionsRec *actions,
104 register Cardinal count, /* may be 0 */
105 Boolean stat, /* if False, copy before compiling in place */
106 Boolean perm) /* if False, use XrmStringToQuark */
107{
108 register CompiledActionTable cActions;
109 register int i;
110 CompiledAction hold;
111 CompiledActionTable cTableHold;
112 XrmQuark (*func)(_Xconstconst char*);
113
114 if (!count)
115 return (CompiledActionTable) NULL((void*)0);
116 func = (perm ? XrmPermStringToQuark : XrmStringToQuark);
117
118 if (! stat) {
119 cTableHold = cActions = (CompiledActionTable)
120 __XtMalloc(count * sizeof(CompiledAction));
121
122 for (i=count; --i >= 0; cActions++, actions++) {
123 cActions->proc = actions->proc;
124 cActions->signature = (*func)(actions->string);
125 }
126 } else {
127 cTableHold = (CompiledActionTable) actions;
128
129 for (i=count; --i >= 0; actions++)
130 ((CompiledActionTable) actions)->signature =
131 (*func)(actions->string);
132 }
133 cActions = cTableHold;
134
135 /* Insertion sort. Whatever sort is used, it must be stable. */
136 for (i=1; (Cardinal) i <= count - 1; i++) {
137 register Cardinal j;
138 hold = cActions[i];
139 j = i;
140 while (j && cActions[j-1].signature > hold.signature) {
141 cActions[j] = cActions[j-1];
142 j--;
143 }
144 cActions[j] = hold;
145 }
146
147 return cActions;
148}
149
150
151typedef struct _ActionListRec *ActionList;
152typedef struct _ActionListRec {
153 ActionList next;
154 CompiledActionTable table;
155 TMShortCard count;
156} ActionListRec;
157
158static void ReportUnboundActions(
159 XtTranslations xlations,
160 TMBindData bindData)
161{
162 TMSimpleStateTree stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[0];
163 Cardinal num_unbound = 0;
164 Cardinal num_params = 1;
165 char* message;
166 char messagebuf[1000];
167 String params[1];
168 register Cardinal num_chars = 0;
169 register Cardinal i, j;
170 XtActionProc *procs;
171
172 for (i=0; i < xlations->numStateTrees; i++) {
173 if (bindData->simple.isComplex)
174 procs = TMGetComplexBindEntry(bindData, i)((TMComplexBindProcs)&(((TMComplexBindData)bindData)->
bindTbl[i]))
->procs;
175 else
176 procs = TMGetSimpleBindEntry(bindData, i)((TMSimpleBindProcs)&(((TMSimpleBindData)bindData)->bindTbl
[i]))
->procs;
177
178 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[i];
179 for (j=0; j < stateTree->numQuarks; j++) {
180 if (procs[j] == NULL((void*)0)) {
181 String s = XrmQuarkToString(stateTree->quarkTbl[j]);
182 if (num_unbound != 0)
183 num_chars += 2;
184 num_chars += strlen(s);
185 num_unbound++;
186 }
187 }
188 }
189 if (num_unbound == 0)
190 return;
191 message = XtStackAlloc (num_chars + 1, messagebuf)((num_chars + 1) <= sizeof(messagebuf) ? (XtPointer)(messagebuf
) : XtMalloc((unsigned)(num_chars + 1)))
;
192 if (message != NULL((void*)0)) {
193 *message = '\0';
194 num_unbound = 0;
195 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[0];
196 for (i=0; i < xlations->numStateTrees; i++) {
197 if (bindData->simple.isComplex)
198 procs = TMGetComplexBindEntry(bindData, i)((TMComplexBindProcs)&(((TMComplexBindData)bindData)->
bindTbl[i]))
->procs;
199 else
200 procs = TMGetSimpleBindEntry(bindData, i)((TMSimpleBindProcs)&(((TMSimpleBindData)bindData)->bindTbl
[i]))
->procs;
201
202 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[i];
203 for (j=0; j < stateTree->numQuarks; j++) {
204 if (procs[j] == NULL((void*)0)) {
205 String s = XrmQuarkToString(stateTree->quarkTbl[j]);
206 if (num_unbound != 0)
207 (void) strcat(message, ", ");
208 (void) strcat(message, s);
209 num_unbound++;
210 }
211 }
212 }
213 message[num_chars] = '\0';
214 params[0] = message;
215 XtWarningMsg(XtNtranslationError,"unboundActions",XtCXtToolkitError,
216 "Actions not found: %s",
217 params, &num_params);
218 XtStackFree (message, messagebuf){ if ((message) != ((XtPointer)(messagebuf))) XtFree(message)
; }
;
219 }
220}
221
222
223static CompiledAction *SearchActionTable(
224 XrmQuark signature,
225 CompiledActionTable actionTable,
226 Cardinal numActions)
227{
228 register int i, left, right;
229
230 left = 0;
231 right = numActions - 1;
232 while (left <= right) {
233 i = (left + right) >> 1;
234 if (signature < actionTable[i].signature)
235 right = i - 1;
236 else if (signature > actionTable[i].signature)
237 left = i + 1;
238 else {
239 while (i && actionTable[i - 1].signature == signature)
240 i--;
241 return &actionTable[i];
242 }
243 }
244 return (CompiledAction *) NULL((void*)0);
245}
246
247static int BindActions(
248 TMSimpleStateTree stateTree,
249 XtActionProc *procs,
250 CompiledActionTable compiledActionTable,
251 TMShortCard numActions,
252 Cardinal *ndxP)
253{
254 register int unbound = stateTree->numQuarks - *ndxP;
255 CompiledAction* action;
256 register Cardinal ndx;
257 register Boolean savedNdx = False0;
258
259 for (ndx = *ndxP; ndx < stateTree->numQuarks; ndx++) {
260 if (procs[ndx] == NULL((void*)0)) {
261 /* attempt to bind it */
262 XrmQuark q = stateTree->quarkTbl[ndx];
263
264 action = SearchActionTable(q, compiledActionTable, numActions);
265 if (action) {
266 procs[ndx] = action->proc;
267 unbound--;
268 } else if (!savedNdx) {
269 *ndxP= ndx;
270 savedNdx = True1;
271 }
272 } else {
273 /* already bound, leave it alone */
274 unbound--;
275 }
276 }
277 return unbound;
278}
279
280typedef struct _TMBindCacheStatusRec{
281 unsigned int boundInClass:1;
282 unsigned int boundInHierarchy:1;
283 unsigned int boundInContext:1;
284 unsigned int notFullyBound:1;
285 unsigned int refCount:28;
286}TMBindCacheStatusRec, *TMBindCacheStatus;
287
288typedef struct _TMBindCacheRec{
289 struct _TMBindCacheRec *next;
290 TMBindCacheStatusRec status;
291 TMStateTree stateTree;
292#ifdef TRACE_TM
293 WidgetClass widgetClass;
294#endif /* TRACE_TM */
295 XtActionProc procs[1]; /* variable length */
296}TMBindCacheRec, *TMBindCache;
297
298typedef struct _TMClassCacheRec {
299 CompiledActionTable actions;
300 TMBindCacheRec *bindCache;
301}TMClassCacheRec, *TMClassCache;
302
303#define IsPureClassBind(bc)(bc->status.boundInClass && !(bc->status.boundInHierarchy
|| bc->status.boundInContext || bc->status.notFullyBound
))
\
304 (bc->status.boundInClass && \
305 !(bc->status.boundInHierarchy || \
306 bc->status.boundInContext || \
307 bc->status.notFullyBound))
308
309#define GetClassCache(w)((TMClassCache)w->core.widget_class->core_class.actions
)
\
310 ((TMClassCache)w->core.widget_class->core_class.actions)
311
312
313static int BindProcs(
314 Widget widget,
315 TMSimpleStateTree stateTree,
316 XtActionProc *procs,
317 TMBindCacheStatus bindStatus)
318{
319 register WidgetClass class;
320 register ActionList actionList;
321 int unbound = -1, newUnbound = -1;
322 Cardinal ndx = 0;
323 Widget w = widget;
324
325 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
326 do {
327 class = w->core.widget_class;
328 do {
329 if (class->core_class.actions != NULL((void*)0))
330 unbound =
331 BindActions(stateTree,
332 procs,
333 GetClassActions(class)((class->core_class.actions) ? (((TMClassCache)class->core_class
.actions)->actions) : ((void*)0))
,
334 class->core_class.num_actions,
335 &ndx);
336 class = class->core_class.superclass;
337 } while (unbound != 0 && class != NULL((void*)0));
338 if (unbound < (int)stateTree->numQuarks)
339 bindStatus->boundInClass = True1;
340 else
341 bindStatus->boundInClass = False0;
342 if (newUnbound == -1)
343 newUnbound = unbound;
344 w = XtParent(w)((w)->core.parent);
345 } while (unbound != 0 && w != NULL((void*)0));
346
347 if (newUnbound > unbound)
348 bindStatus->boundInHierarchy = True1;
349 else
350 bindStatus->boundInHierarchy = False0;
351
352 if (unbound) {
353 XtAppContext app = XtWidgetToApplicationContext(widget);
354 newUnbound = unbound;
355 for (actionList = app->action_table;
356 unbound != 0 && actionList != NULL((void*)0);
357 actionList = actionList->next) {
358 unbound = BindActions(stateTree,
359 procs,
360 actionList->table,
361 actionList->count,
362 &ndx);
363 }
364 if (newUnbound > unbound)
365 bindStatus->boundInContext = True1;
366 else
367 bindStatus->boundInContext = False0;
368
369 } else {
370 bindStatus->boundInContext = False0;
371 }
372 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
373 return unbound;
374}
375
376static XtActionProc *TryBindCache(
377 Widget widget,
378 TMStateTree stateTree)
379{
380 TMClassCache classCache;
381
382 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
383 classCache = GetClassCache(widget)((TMClassCache)widget->core.widget_class->core_class.actions
)
;
384
385 if (classCache == NULL((void*)0))
386 {
387 WidgetClass wc = XtClass(widget)((widget)->core.widget_class);
388
389 wc->core_class.actions = (XtActionList)
390 _XtInitializeActionData(NULL((void*)0), 0, True1);
391 }
392 else
393 {
394 TMBindCache bindCache =
395 (TMBindCache)(classCache->bindCache);
396 for (; bindCache; bindCache = bindCache->next)
397 {
398 if (IsPureClassBind(bindCache)(bindCache->status.boundInClass && !(bindCache->
status.boundInHierarchy || bindCache->status.boundInContext
|| bindCache->status.notFullyBound))
&&
399 (stateTree == bindCache->stateTree))
400 {
401 bindCache->status.refCount++;
402 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
403 return &bindCache->procs[0];
404 }
405 }
406 }
407 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
408 return NULL((void*)0);
409}
410
411
412
413/*
414 * The class record actions field will point to the bind cache header
415 * after this call is made out of coreClassPartInit.
416 */
417XtPointer _XtInitializeActionData(
418 register struct _XtActionsRec *actions,
419 register Cardinal count,
420 _XtBooleanBoolean inPlace)
421{
422 TMClassCache classCache;
423
424 classCache = XtNew(TMClassCacheRec)((TMClassCacheRec *) XtMalloc((unsigned) sizeof(TMClassCacheRec
)))
;
425 classCache->actions = CompileActionTable(actions, count, inPlace, True1);
426 classCache->bindCache = NULL((void*)0);
427 return (XtPointer)classCache;
428}
429
430
431#define TM_BIND_CACHE_REALLOC2 2
432
433static XtActionProc *EnterBindCache(
434 Widget w,
435 TMSimpleStateTree stateTree,
436 XtActionProc *procs,
437 TMBindCacheStatus bindStatus)
438{
439 TMClassCache classCache;
440 TMBindCache* bindCachePtr;
441 TMShortCard procsSize;
442 TMBindCache bindCache;
443
444 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
445 classCache = GetClassCache(w)((TMClassCache)w->core.widget_class->core_class.actions
)
;
446 bindCachePtr = &classCache->bindCache;
447 procsSize = stateTree->numQuarks * sizeof(XtActionProc);
448
449 for (bindCache = *bindCachePtr;
450 (*bindCachePtr);
451 bindCachePtr = &(*bindCachePtr)->next, bindCache = *bindCachePtr)
452 {
453 TMBindCacheStatus cacheStatus = &bindCache->status;
454
455 if ((bindStatus->boundInClass == cacheStatus->boundInClass) &&
456 (bindStatus->boundInHierarchy == cacheStatus->boundInHierarchy) &&
457 (bindStatus->boundInContext == cacheStatus->boundInContext) &&
458 (bindCache->stateTree == (TMStateTree)stateTree) &&
459 !XtMemcmp(&bindCache->procs[0], procs, procsSize)memcmp((char *) (&bindCache->procs[0]), (char *) (procs
), (int) (procsSize))
)
460 {
461 bindCache->status.refCount++;
462 break;
463 }
464 }
465 if (*bindCachePtr == NULL((void*)0))
466 {
467 *bindCachePtr =
468 bindCache = (TMBindCache)
469 __XtMalloc(sizeof(TMBindCacheRec) +
470 (procsSize - sizeof(XtActionProc)));
471 bindCache->next = NULL((void*)0);
472 bindCache->status = *bindStatus;
473 bindCache->status.refCount = 1;
474 bindCache->stateTree = (TMStateTree)stateTree;
475#ifdef TRACE_TM
476 bindCache->widgetClass = XtClass(w)((w)->core.widget_class);
477 if (_XtGlobalTM.numBindCache == _XtGlobalTM.bindCacheTblSize)
478 {
479 _XtGlobalTM.bindCacheTblSize += 16;
480 _XtGlobalTM.bindCacheTbl = (TMBindCache *)
481 XtRealloc((char *)_XtGlobalTM.bindCacheTbl,
482 ((_XtGlobalTM.bindCacheTblSize) *
483 sizeof(TMBindCache)));
484 }
485 _XtGlobalTM.bindCacheTbl[_XtGlobalTM.numBindCache++] = bindCache;
486#endif /* TRACE_TM */
487 XtMemmove((XtPointer)&bindCache->procs[0],if ((char *)((XtPointer)&bindCache->procs[0]) != (char
*)((XtPointer)procs)) { (void) memcpy((char *) ((XtPointer)&
bindCache->procs[0]), (char *) ((XtPointer)procs), (int) (
procsSize)); }
488 (XtPointer)procs, procsSize)if ((char *)((XtPointer)&bindCache->procs[0]) != (char
*)((XtPointer)procs)) { (void) memcpy((char *) ((XtPointer)&
bindCache->procs[0]), (char *) ((XtPointer)procs), (int) (
procsSize)); }
;
489 }
490 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
491 return &bindCache->procs[0];
492}
493
494static void RemoveFromBindCache(
495 Widget w,
496 XtActionProc *procs)
497{
498 TMClassCache classCache;
499 TMBindCache* bindCachePtr;
500 TMBindCache bindCache;
501 XtAppContext app = XtWidgetToApplicationContext (w);
502
503 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
504 classCache = GetClassCache(w)((TMClassCache)w->core.widget_class->core_class.actions
)
;
505 bindCachePtr = (TMBindCache *)&classCache->bindCache;
506
507 for (bindCache = *bindCachePtr;
508 *bindCachePtr;
509 bindCachePtr = &(*bindCachePtr)->next, bindCache = *bindCachePtr)
510 {
511 if (&bindCache->procs[0] == procs)
512 {
513 if (--bindCache->status.refCount == 0)
514 {
515#ifdef TRACE_TM
516 TMShortCard j;
517 Boolean found = False0;
518 TMBindCache *tbl = _XtGlobalTM.bindCacheTbl;
519
520 for (j = 0; j < _XtGlobalTM.numBindCache; j++) {
521 if (found)
522 tbl[j-1] = tbl[j];
523 if (tbl[j] == bindCache)
524 found = True1;
525 }
526 if (!found)
527 XtWarning("where's the action ??? ");
528 else
529 _XtGlobalTM.numBindCache--;
530#endif /* TRACE_TM */
531 *bindCachePtr = bindCache->next;
532 bindCache->next = app->free_bindings;
533 app->free_bindings = bindCache;
534 }
535 break;
536 }
537 }
538 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
539}
540
541/* ARGSUSED */
542static void RemoveAccelerators(
543 Widget widget,
544 XtPointer closure, XtPointer data)
545{
546 Widget destination = (Widget)closure;
547 TMComplexBindProcs bindProcs;
548 XtTranslations stackXlations[16];
549 XtTranslations *xlationsList, destXlations;
550 TMShortCard i, numXlations = 0;
551
552 if ((destXlations = destination->core.tm.translations) == NULL((void*)0)) {
553 XtAppWarningMsg(XtWidgetToApplicationContext(widget),
554 XtNtranslationError,"nullTable",XtCXtToolkitError,
555 "Can't remove accelerators from NULL table",
556 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
557 return;
558 }
559
560 xlationsList = (XtTranslations *)
561 XtStackAlloc((destXlations->numStateTrees * sizeof(XtTranslations)),(((destXlations->numStateTrees * sizeof(XtTranslations))) <=
sizeof(stackXlations) ? (XtPointer)(stackXlations) : XtMalloc
((unsigned)((destXlations->numStateTrees * sizeof(XtTranslations
)))))
562 stackXlations)(((destXlations->numStateTrees * sizeof(XtTranslations))) <=
sizeof(stackXlations) ? (XtPointer)(stackXlations) : XtMalloc
((unsigned)((destXlations->numStateTrees * sizeof(XtTranslations
)))))
;
563
564 for (i = 0, bindProcs = TMGetComplexBindEntry(destination->core.tm.proc_table, i)((TMComplexBindProcs)&(((TMComplexBindData)destination->
core.tm.proc_table)->bindTbl[i]))
;
565 i < destXlations->numStateTrees;
566 i++, bindProcs++) {
567 if (bindProcs->widget == widget) {
568 /*
569 * if it's being destroyed don't do all the work
570 */
571 if (destination->core.being_destroyed) {
572 bindProcs->procs = NULL((void*)0);
573 }
574 else
575 xlationsList[numXlations] = bindProcs->aXlations;
576 numXlations++;
577 }
578 }
579
580 if (numXlations == 0)
581 XtAppWarningMsg(XtWidgetToApplicationContext(widget),
582 XtNtranslationError,"nullTable",XtCXtToolkitError,
583 "Tried to remove nonexistent accelerators",
584 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
585 else {
586 if (!destination->core.being_destroyed)
587 for (i = 0; i < numXlations; i++)
588 _XtUnmergeTranslations(destination, xlationsList[i]);
589 }
590 XtStackFree((char *)xlationsList, stackXlations){ if (((char *)xlationsList) != ((XtPointer)(stackXlations)))
XtFree((char *)xlationsList); }
;
591}
592
593void _XtBindActions(
594 Widget widget,
595 XtTM tm)
596{
597 XtTranslations xlations = tm->translations;
598 TMSimpleStateTree stateTree;
599 int globalUnbound = 0;
600 Cardinal i;
601 TMBindData bindData = (TMBindData)tm->proc_table;
602 TMSimpleBindProcs simpleBindProcs = NULL((void*)0);
603 TMComplexBindProcs complexBindProcs = NULL((void*)0);
604 XtActionProc *newProcs;
605 Widget bindWidget;
606
607 if ((xlations == NULL((void*)0)) || widget->core.being_destroyed)
608 return;
609
610 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[0];
611
612 for (i = 0; i < xlations->numStateTrees; i++)
613 {
614 stateTree = (TMSimpleStateTree)xlations->stateTreeTbl[i];
615 if (bindData->simple.isComplex) {
616 complexBindProcs = TMGetComplexBindEntry(bindData, i)((TMComplexBindProcs)&(((TMComplexBindData)bindData)->
bindTbl[i]))
;
617 if (complexBindProcs->widget) {
618 bindWidget = complexBindProcs->widget;
619
620 if (bindWidget->core.destroy_callbacks != NULL((void*)0))
621 _XtAddCallbackOnce((InternalCallbackList *)
622 &bindWidget->core.destroy_callbacks,
623 RemoveAccelerators,
624 (XtPointer)widget);
625 else
626 _XtAddCallback((InternalCallbackList *)
627 &bindWidget->core.destroy_callbacks,
628 RemoveAccelerators,
629 (XtPointer)widget);
630 }
631 else
632 bindWidget = widget;
633 }
634 else {
635 simpleBindProcs = TMGetSimpleBindEntry(bindData, i)((TMSimpleBindProcs)&(((TMSimpleBindData)bindData)->bindTbl
[i]))
;
636 bindWidget = widget;
637 }
638 if ((newProcs =
639 TryBindCache(bindWidget,(TMStateTree)stateTree)) == NULL((void*)0))
640 {
641 XtActionProc *procs, stackProcs[256];
642 int localUnbound;
643 TMBindCacheStatusRec bcStatusRec;
644
645 procs = (XtActionProc *)
646 XtStackAlloc(stateTree->numQuarks * sizeof(XtActionProc),((stateTree->numQuarks * sizeof(XtActionProc)) <= sizeof
(stackProcs) ? (XtPointer)(stackProcs) : XtMalloc((unsigned)(
stateTree->numQuarks * sizeof(XtActionProc))))
647 stackProcs)((stateTree->numQuarks * sizeof(XtActionProc)) <= sizeof
(stackProcs) ? (XtPointer)(stackProcs) : XtMalloc((unsigned)(
stateTree->numQuarks * sizeof(XtActionProc))))
;
648 XtBZero((XtPointer)procs,memset((char *) ((XtPointer)procs),0,(int) (stateTree->numQuarks
* sizeof(XtActionProc)))
649 stateTree->numQuarks * sizeof(XtActionProc))memset((char *) ((XtPointer)procs),0,(int) (stateTree->numQuarks
* sizeof(XtActionProc)))
;
650
651 localUnbound = BindProcs(bindWidget,
652 stateTree,
653 procs,
654 &bcStatusRec);
655
656 if (localUnbound)
657 bcStatusRec.notFullyBound = True1;
658 else
659 bcStatusRec.notFullyBound = False0;
660
661 newProcs =
662 EnterBindCache(bindWidget,
663 stateTree,
664 procs,
665 &bcStatusRec);
666 XtStackFree((XtPointer)procs, (XtPointer)stackProcs){ if (((XtPointer)procs) != ((XtPointer)((XtPointer)stackProcs
))) XtFree((XtPointer)procs); }
;
667 globalUnbound += localUnbound;
668 }
669 if (bindData->simple.isComplex)
670 complexBindProcs->procs = newProcs;
671 else
672 simpleBindProcs->procs = newProcs;
673 }
674 if (globalUnbound)
675 ReportUnboundActions(xlations,
676 (TMBindData)tm->proc_table);
677}
678
679
680void _XtUnbindActions(
681 Widget widget,
682 XtTranslations xlations,
683 TMBindData bindData)
684{
685 Cardinal i;
686 Widget bindWidget;
687 XtActionProc *procs;
688
689 if ((xlations == NULL((void*)0)) || !XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
) return;
690
691 for (i = 0; i < xlations->numStateTrees; i++) {
692 if (bindData->simple.isComplex) {
693 TMComplexBindProcs complexBindProcs;
694
695 complexBindProcs = TMGetComplexBindEntry(bindData, i)((TMComplexBindProcs)&(((TMComplexBindData)bindData)->
bindTbl[i]))
;
696
697 if (complexBindProcs->widget) {
698 /*
699 * check for this being an accelerator binding whose
700 * source is gone ( set by RemoveAccelerators)
701 */
702 if (complexBindProcs->procs == NULL((void*)0))
703 continue;
704
705 XtRemoveCallback(complexBindProcs->widget,
706 XtNdestroyCallback((char*)&XtStrings[169]),
707 RemoveAccelerators,
708 (XtPointer)widget);
709 bindWidget = complexBindProcs->widget;
710 }
711 else
712 bindWidget = widget;
713 procs = complexBindProcs->procs;
714 complexBindProcs->procs = NULL((void*)0);
715 }
716 else {
717 TMSimpleBindProcs simpleBindProcs;
718 simpleBindProcs = TMGetSimpleBindEntry(bindData,i)((TMSimpleBindProcs)&(((TMSimpleBindData)bindData)->bindTbl
[i]))
;
719 procs = simpleBindProcs->procs;
720 simpleBindProcs->procs = NULL((void*)0);
721 bindWidget = widget;
722 }
723 RemoveFromBindCache(bindWidget, procs);
724 }
725}
726
727#ifdef notdef
728void _XtRemoveBindProcsByIndex(
729 Widget w,
730 TMBindData bindData,
731 TMShortCard ndx)
732{
733 TMShortCard i = ndx;
734 TMBindProcs bindProcs = (TMBindProcs)&bindData->bindTbl[0];
735
736 RemoveFromBindCache(bindProcs->widget ? bindProcs->widget : w,
737 bindProcs[i].procs);
738
739 for (; i < bindData->bindTblSize; i++)
740 bindProcs[i] = bindProcs[i+1];
741}
742#endif /* notdef */
743
744/*
745 * used to free all copied action tables, called from DestroyAppContext
746 */
747void _XtFreeActions(
748 ActionList actions)
749{
750 ActionList curr, next;
751
752 for (curr = actions; curr;) {
753 next = curr->next;
754 XtFree((char *)curr->table);
755 XtFree((char *)curr);
756 curr = next;
757 }
758}
759
760void XtAddActions(
761 XtActionList actions,
762 Cardinal num_actions)
763{
764 XtAppAddActions(_XtDefaultAppContext(), actions, num_actions);
765}
766
767void XtAppAddActions(
768 XtAppContext app,
769 XtActionList actions,
770 Cardinal num_actions)
771{
772 register ActionList rec;
773
774 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
775 rec = XtNew(ActionListRec)((ActionListRec *) XtMalloc((unsigned) sizeof(ActionListRec))
)
;
776 rec->next = app->action_table;
Access to field 'action_table' results in a dereference of a null pointer (loaded from variable 'app')
777 app->action_table = rec;
778 rec->table = CompileActionTable(actions, num_actions, False0, False0);
779 rec->count = num_actions;
780 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
781}
782
783void XtGetActionList(
784 WidgetClass widget_class,
785 XtActionList* actions_return,
786 Cardinal* num_actions_return)
787{
788 XtActionList list;
789 CompiledActionTable table;
790 int i;
791
792 *actions_return = NULL((void*)0);
793 *num_actions_return = 0;
794
795 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
796 if (! widget_class->core_class.class_inited) {
797 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
798 return;
799 }
800 if (! (widget_class->core_class.class_inited & WidgetClassFlag0x04)) {
801 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
802 return;
803 }
804 *num_actions_return = widget_class->core_class.num_actions;
805 if (*num_actions_return) {
806 list = *actions_return = (XtActionList)
807 __XtMalloc(*num_actions_return * sizeof(XtActionsRec));
808 table = GetClassActions(widget_class)((widget_class->core_class.actions) ? (((TMClassCache)widget_class
->core_class.actions)->actions) : ((void*)0))
;
809 if (table != NULL((void*)0)) {
810 for (i= (*num_actions_return); --i >= 0; list++, table++) {
811 list->string = XrmQuarkToString(table->signature);
812 list->proc = table->proc;
813 }
814 }
815 }
816 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
817}
818
819/***********************************************************************
820 *
821 * Pop-up and Grab stuff
822 *
823 ***********************************************************************/
824
825static Widget _XtFindPopup(
826 Widget widget,
827 String name)
828{
829 register Cardinal i;
830 register XrmQuark q;
831 register Widget w;
832
833 q = XrmStringToQuark(name);
834
835 for (w=widget; w != NULL((void*)0); w=w->core.parent)
836 for (i=0; i<w->core.num_popups; i++)
837 if (w->core.popup_list[i]->core.xrm_name == q)
838 return w->core.popup_list[i];
839
840 return NULL((void*)0);
841}
842
843void XtMenuPopupAction(
844 Widget widget,
845 XEvent *event,
846 String *params,
847 Cardinal *num_params)
848{
849 Boolean spring_loaded;
850 register Widget popup_shell;
851 XtAppContext app = XtWidgetToApplicationContext(widget);
852
853 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
854 if (*num_params != 1) {
855 XtAppWarningMsg(app,
856 "invalidParameters","xtMenuPopupAction",XtCXtToolkitError,
857 "MenuPopup wants exactly one argument",
858 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
859 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
860 return;
861 }
862
863 if (event->type == ButtonPress4)
864 spring_loaded = True1;
865 else if (event->type == KeyPress2 || event->type == EnterNotify7)
866 spring_loaded = False0;
867 else {
868 XtAppWarningMsg(app,
869 "invalidPopup","unsupportedOperation",XtCXtToolkitError,
870"Pop-up menu creation is only supported on ButtonPress, KeyPress or EnterNotify events.",
871 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
872 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
873 return;
874 }
875
876 popup_shell = _XtFindPopup(widget, params[0]);
877 if (popup_shell == NULL((void*)0)) {
878 XtAppWarningMsg(app,
879 "invalidPopup","xtMenuPopup",XtCXtToolkitError,
880 "Can't find popup widget \"%s\" in XtMenuPopup",
881 params, num_params);
882 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
883 return;
884 }
885
886 if (spring_loaded) _XtPopup(popup_shell, XtGrabExclusive, TRUE1);
887 else _XtPopup(popup_shell, XtGrabNonexclusive, FALSE0);
888 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
889}
890
891
892/*ARGSUSED*/
893static void _XtMenuPopdownAction(
894 Widget widget,
895 XEvent *event,
896 String *params,
897 Cardinal *num_params)
898{
899 Widget popup_shell;
900
901 if (*num_params == 0) {
902 XtPopdown(widget);
903 } else if (*num_params == 1) {
904 popup_shell = _XtFindPopup(widget, params[0]);
905 if (popup_shell == NULL((void*)0)) {
906 XtAppWarningMsg(XtWidgetToApplicationContext(widget),
907 "invalidPopup","xtMenuPopdown",XtCXtToolkitError,
908 "Can't find popup widget \"%s\" in XtMenuPopdown",
909 params, num_params);
910 return;
911 }
912 XtPopdown(popup_shell);
913 } else {
914 XtAppWarningMsg(XtWidgetToApplicationContext(widget),
915 "invalidParameters","xtMenuPopdown",XtCXtToolkitError,
916 "XtMenuPopdown called with num_params != 0 or 1",
917 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
918 }
919}
920
921static XtActionsRec RConstconst tmActions[] = {
922 {"XtMenuPopup", XtMenuPopupAction},
923 {"XtMenuPopdown", _XtMenuPopdownAction},
924 {"MenuPopup", XtMenuPopupAction}, /* old & obsolete */
925 {"MenuPopdown", _XtMenuPopdownAction}, /* ditto */
926#ifndef NO_MIT_HACKS
927 {"XtDisplayTranslations", _XtDisplayTranslations},
928 {"XtDisplayAccelerators", _XtDisplayAccelerators},
929 {"XtDisplayInstalledAccelerators", _XtDisplayInstalledAccelerators},
930#endif
931};
932
933
934void _XtPopupInitialize(
935 XtAppContext app)
936{
937 register ActionList rec;
938
939 /*
940 * The _XtGlobalTM.newMatchSemantics flag determines whether
941 * we support old or new matching
942 * behavior. This is mainly an issue of whether subsequent lhs will
943 * get pushed up in the match table if a lhs containing thier initial
944 * sequence has already been encountered. Currently inited to False;
945 */
946#ifdef NEW_TM
947 _XtGlobalTM.newMatchSemantics = True1;
948#else
949 _XtGlobalTM.newMatchSemantics = False0;
950#endif
951
952 rec = XtNew(ActionListRec)((ActionListRec *) XtMalloc((unsigned) sizeof(ActionListRec))
)
;
953 rec->next = app->action_table;
954 app->action_table = rec;
955 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
956 rec->table = CompileActionTable(tmActions, XtNumber(tmActions)((Cardinal) (sizeof(tmActions) / sizeof(tmActions[0]))), False0,
957 True1);
958 rec->count = XtNumber(tmActions)((Cardinal) (sizeof(tmActions) / sizeof(tmActions[0])));
959 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
960 _XtGrabInitialize(app);
961}
962
963
964void XtCallActionProc(
965 Widget widget,
966 _Xconstconst char* action,
967 XEvent *event,
968 String *params,
969 Cardinal num_params)
970{
971 CompiledAction* actionP;
972 XrmQuark q = XrmStringToQuark(action);
973 Widget w = widget;
974 XtAppContext app = XtWidgetToApplicationContext(widget);
975 ActionList actionList;
976 Cardinal i;
977
978 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
979 XtCheckSubclass(widget, coreWidgetClass,
980 "XtCallActionProc first argument is not a subclass of Core");
981 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
982 do {
983 WidgetClass class = XtClass(w)((w)->core.widget_class);
984 do {
985 if ((actionP = GetClassActions(class)((class->core_class.actions) ? (((TMClassCache)class->core_class
.actions)->actions) : ((void*)0))
) != NULL((void*)0))
986 for (i = 0;
987 i < class->core_class.num_actions;
988 i++, actionP++) {
989
990 if (actionP->signature == q) {
991 ActionHook hook = app->action_hook_list;
992 while (hook != NULL((void*)0)) {
993 (*hook->proc)( widget,
994 hook->closure,
995 (String)action,
996 event,
997 params,
998 &num_params
999 );
1000 hook= hook->next;
1001 }
1002 (*(actionP->proc))
1003 (widget, event, params, &num_params);
1004 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1005 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1006 return;
1007 }
1008 }
1009 class = class->core_class.superclass;
1010 } while (class != NULL((void*)0));
1011 w = XtParent(w)((w)->core.parent);
1012 } while (w != NULL((void*)0));
1013 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
1014
1015 for (actionList = app->action_table;
1016 actionList != NULL((void*)0);
1017 actionList = actionList->next) {
1018
1019 for (i = 0, actionP = actionList->table;
1020 i < actionList->count;
1021 i++, actionP++) {
1022 if (actionP->signature == q) {
1023 ActionHook hook = app->action_hook_list;
1024 while (hook != NULL((void*)0)) {
1025 (*hook->proc)( widget,
1026 hook->closure,
1027 (String)action,
1028 event,
1029 params,
1030 &num_params
1031 );
1032 hook= hook->next;
1033 }
1034 (*(actionP->proc))
1035 (widget, event, params, &num_params);
1036 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1037 return;
1038 }
1039 }
1040
1041 }
1042
1043 {
1044 String params[2];
1045 Cardinal num_params = 2;
1046 params[0] = (String)action;
1047 params[1] = XtName(widget);
1048 XtAppWarningMsg(app,
1049 "noActionProc", "xtCallActionProc", XtCXtToolkitError,
1050 "No action proc named \"%s\" is registered for widget \"%s\"",
1051 params, &num_params
1052 );
1053 }
1054 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1055}
1056
1057void _XtDoFreeBindings(
1058 XtAppContext app)
1059{
1060 TMBindCache bcp;
1061
1062 while (app->free_bindings) {
1063 bcp = app->free_bindings->next;
1064 XtFree ((char *) app->free_bindings);
1065 app->free_bindings = bcp;
1066 }
1067}