~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/lib/Xt/TMaction.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

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