~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/3rdparty/qmon/Xmt310/Xmt/MenuCvt.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Motif Tools Library, Version 3.1
 
3
 * $Id$
 
4
 * 
 
5
 * Written by David Flanagan.
 
6
 * Copyright (c) 1992-2001 by David Flanagan.
 
7
 * All Rights Reserved.  See the file COPYRIGHT for details.
 
8
 * This is open source software.  See the file LICENSE for details.
 
9
 * There is no warranty for this software.  See NO_WARRANTY for details.
 
10
 *
 
11
 * $Log$
 
12
 * Revision 1.1.1.1  2001/07/18 11:06:02  root
 
13
 * Initial checkin.
 
14
 *
 
15
 * Revision 1.2  2001/06/12 16:25:28  andre
 
16
 * *** empty log message ***
 
17
 *
 
18
 *
 
19
 */
 
20
 
 
21
#include <ctype.h>
 
22
#include <stdio.h>
 
23
#include <Xmt/Xmt.h>
 
24
#include <Xmt/MenuP.h>
 
25
#include <Xmt/ConvertersP.h>
 
26
#include <Xmt/Lexer.h>
 
27
 
 
28
/*
 
29
 * These are keywords and symbolic names for keywords, used by the lexer.
 
30
 */
 
31
static String keywords[] = {
 
32
    "Alt",
 
33
    "Button",
 
34
    "Ctrl",
 
35
    "DoubleLine",
 
36
    "Help",
 
37
    "Line",
 
38
    "Lock",
 
39
    "Meta",
 
40
    "Off",
 
41
    "On",
 
42
    "Pixmap",
 
43
    "Shift",
 
44
    "Submenu",
 
45
    "Tearoff",
 
46
    "Title",
 
47
    "Toggle"
 
48
};
 
49
    
 
50
#define ALT             0
 
51
#define BUTTON          1
 
52
#define CTRL            2
 
53
#define DOUBLELINE      3
 
54
#define HELP            4
 
55
#define LINE            5
 
56
#define LOCK            6
 
57
#define META            7
 
58
#define OFF             8
 
59
#define ON              9
 
60
#define PIXMAP          10
 
61
#define SHIFT           11
 
62
#define SUBMENU         12
 
63
#define TEAROFF         13
 
64
#define TITLE           14
 
65
#define TOGGLE          15
 
66
 
 
67
 
 
68
#if NeedFunctionPrototypes
 
69
static int ParseAccelerator(XmtLexer l, XmtMenuItem *item)
 
70
#else
 
71
static int ParseAccelerator(l, item)
 
72
XmtLexer l;
 
73
XmtMenuItem *item;
 
74
#endif
 
75
{
 
76
    int tok;
 
77
    char accel[200];
 
78
    char accel_label[200];
 
79
    
 
80
    accel[0] = '\0';
 
81
    accel_label[0] = '\0';
 
82
 
 
83
    while((XmtLexerGetToken(l) == XmtLexerKeyword) &&
 
84
          ((XmtLexerKeyValue(l) == CTRL) ||
 
85
           (XmtLexerKeyValue(l) == SHIFT) ||
 
86
           (XmtLexerKeyValue(l) == META) ||
 
87
           (XmtLexerKeyValue(l) == ALT) ||
 
88
           (XmtLexerKeyValue(l) == LOCK))) {
 
89
        strcat(accel, XmtLexerStrValue(l));
 
90
        strcat(accel_label, XmtLexerStrValue(l));
 
91
        XmtLexerConsumeToken(l);
 
92
        tok = XmtLexerGetToken(l);
 
93
        if (tok == XmtLexerPlus) {
 
94
            strcat(accel, " ");
 
95
            strcat(accel_label, "+");
 
96
            XmtLexerConsumeToken(l);
 
97
        }
 
98
        else if (tok == XmtLexerMinus) {
 
99
            strcat(accel, " ");
 
100
            strcat(accel_label, "-");
 
101
            XmtLexerConsumeToken(l);
 
102
        }
 
103
        else {
 
104
            XmtWarningMsg("XmtMenu", "missingPlus",
 
105
                          "item \"%s\": modifier name in accelerator must be followed by `+' or `-'",
 
106
                          item->label);
 
107
            goto error;
 
108
        }
 
109
    }
 
110
 
 
111
    strcat(accel, "<Key>");
 
112
    tok = XmtLexerGetToken(l);
 
113
 
 
114
    if ((tok == XmtLexerIdent) || (tok == XmtLexerString)) {
 
115
        char *sym = XmtLexerStrValue(l);
 
116
 
 
117
        if (isalnum(sym[0]))
 
118
            strcat(accel, sym);
 
119
        else {
 
120
            char buf[10];
 
121
            sprintf(buf, "%d", sym[0]);
 
122
            strcat(accel, buf);
 
123
        }
 
124
 
 
125
        strcat(accel_label, sym);
 
126
        XtFree(sym);
 
127
        XmtLexerConsumeToken(l);
 
128
    }
 
129
    else if (tok == XmtLexerInteger) {
 
130
        char buf[10];
 
131
        sprintf(buf, "%d", XmtLexerIntValue(l));
 
132
        strcat(accel, buf);
 
133
        strcat(accel_label, buf);
 
134
        XmtLexerConsumeToken(l);
 
135
    }
 
136
    else {
 
137
        XmtWarningMsg("XmtMenu", "missingKeysym",
 
138
                      "item \"%s\": accelerator is missing keysym",
 
139
                      item->label);
 
140
        goto error;
 
141
    }
 
142
    
 
143
    item->accelerator = XtNewString(accel);
 
144
    item->accelerator_label = XtNewString(accel_label);
 
145
    return 0;
 
146
 
 
147
 error:
 
148
    /* read forward until matching ']' */
 
149
    while(1) {
 
150
        tok = XmtLexerGetToken(l);
 
151
        if ((tok == XmtLexerRBracket) || (tok == XmtLexerEndOfString)) break;
 
152
        XmtLexerConsumeToken(l);
 
153
    }
 
154
    item->accelerator = item->accelerator_label = NULL;
 
155
    return 1;
 
156
}
 
157
 
 
158
#if NeedFunctionPrototypes
 
159
static void ParseLabelAndMnemonic(XmtLexer l, String *label,
 
160
                                  int look_for_mnemonic, char *mnemonic)
 
161
#else
 
162
static void ParseLabelAndMnemonic(l, label, look_for_mnemonic, mnemonic)
 
163
XmtLexer l;
 
164
String *label;
 
165
int look_for_mnemonic;
 
166
char *mnemonic;
 
167
#endif
 
168
{
 
169
    register int i;
 
170
    register char *c;
 
171
    
 
172
    if (XmtLexerGetToken(l) != XmtLexerString) return;
 
173
 
 
174
    if (look_for_mnemonic) {
 
175
        *label = XtMalloc(XmtLexerStrLength(l) + 1);
 
176
        *mnemonic = '\0';
 
177
        
 
178
        for(i=0, c = XmtLexerStrValue(l); *c != '\0'; c++) {
 
179
            if ((*c == '_') && (*mnemonic == '\0'))
 
180
                *mnemonic = *(c+1);
 
181
            else
 
182
                (*label)[i++] = *c;
 
183
        }
 
184
        (*label)[i] = '\0';
 
185
        
 
186
        XtFree(XmtLexerStrValue(l));
 
187
    }
 
188
    else {
 
189
        *label = XmtLexerStrValue(l);
 
190
        *mnemonic = '\0';
 
191
    }
 
192
 
 
193
    XmtLexerConsumeToken(l);
 
194
}    
 
195
 
 
196
 
 
197
/*
 
198
 *
 
199
 * item:: [name] '-' '-'* ';'      // a separator
 
200
 *      | [name] '=' '='* ';'      // a double separator
 
201
 *      | [name] [type] flags* [label] [accelerator]
 
202
 *             [submenu] [symbol] callbacks
 
203
 * 
 
204
 * name::         ident ':'
 
205
 * type::         'Title' | 'Button' | 'Toggle' |
 
206
 *                    'Line' | 'DoubleLine' | 'Submenu'
 
207
 * flags::        'On' | 'Off' | 'Help' | 'Tearoff' | 'Pixmap'
 
208
 * label::        string-with-embedded-mnemonic [ '|' string ]
 
209
 * accelerator::  '[' (modifier ('+'|'-'))* keysym ']'
 
210
 * modifier::     'Ctrl' | 'Shift' | 'Meta' | 'Alt' | 'Lock'
 
211
 * keysym::       ident
 
212
 * submenu::      '-' '>' ident
 
213
 * symbol::       '$' ident
 
214
 * callbacks::    callback | '{' callback+ '}' | ';'
 
215
 * callback::     ident '(' [args] ')' ';'
 
216
 * args::         list-of-comma-separated-strings
 
217
 */
 
218
 
 
219
#if NeedFunctionPrototypes
 
220
static int ParseItem(Widget w, XmtLexer l, XmtMenuItem *item)
 
221
#else
 
222
static int ParseItem(w, l, item)
 
223
Widget w;
 
224
XmtLexer l;
 
225
XmtMenuItem *item;
 
226
#endif
 
227
{
 
228
    int tok;
 
229
    static XmtMenuItem null_item;  /* static memory; all fields NULL */
 
230
 
 
231
    /* initialize item structure */
 
232
    null_item.type = XmtMenuItemEnd;  /* undefined type, no flags */
 
233
    *item = null_item;
 
234
 
 
235
    /* parse item name */
 
236
    if (XmtLexerGetToken(l) == XmtLexerIdent) {
 
237
        item->name = XmtLexerStrValue(l);
 
238
        XmtLexerConsumeToken(l);
 
239
        if (XmtLexerGetToken(l) == XmtLexerColon)
 
240
           XmtLexerConsumeToken(l);
 
241
        else
 
242
            XmtWarningMsg("XmtMenu", "colonExpected",
 
243
                          "colon expected after item name %s.",
 
244
                          item->name);
 
245
    }
 
246
 
 
247
    /* parse separators as a special case */
 
248
    if (((tok = XmtLexerGetToken(l)) == XmtLexerMinus) ||
 
249
        (tok == XmtLexerEqual))   { /* a separator */
 
250
        if (tok == XmtLexerMinus) item->type = XmtMenuItemSeparator;
 
251
        else item->type = XmtMenuItemDoubleSeparator;
 
252
            
 
253
        while (((tok = XmtLexerGetToken(l)) == XmtLexerMinus) ||
 
254
               (tok == XmtLexerEqual))
 
255
            XmtLexerConsumeToken(l);
 
256
 
 
257
        if (tok == XmtLexerSemicolon) {
 
258
            XmtLexerConsumeToken(l);
 
259
            return 0;
 
260
        }
 
261
        else {
 
262
            XmtWarningMsg("XmtMenu", "semicolonAfterSeparator",
 
263
                          "semicolon expeced after separator.");
 
264
            goto error;
 
265
        }
 
266
    }
 
267
 
 
268
    /*
 
269
     * parse an optional type keyword.
 
270
     * We can set the type directly, because we know that no flags are set yet.
 
271
     */
 
272
    if (XmtLexerGetToken(l) == XmtLexerKeyword) {
 
273
        switch(XmtLexerKeyValue(l)) {
 
274
        case TITLE:      item->type = XmtMenuItemLabel; break;
 
275
        case BUTTON:     item->type = XmtMenuItemPushButton; break;
 
276
        case TOGGLE:     item->type = XmtMenuItemToggleButton; break;
 
277
        case LINE:       item->type = XmtMenuItemSeparator; break;
 
278
        case DOUBLELINE: item->type = XmtMenuItemDoubleSeparator; break;
 
279
        case SUBMENU:    item->type = XmtMenuItemCascadeButton; break;
 
280
        }
 
281
        /* if we set a type eat the token */
 
282
        if (item->type != XmtMenuItemEnd) XmtLexerConsumeToken(l);
 
283
    }
 
284
 
 
285
    /*
 
286
     * If the type is not set, assume it is a push button until
 
287
     * we find a flag or something else that indicates otherwise.
 
288
     */
 
289
    if (item->type == XmtMenuItemEnd)
 
290
        item->type = XmtMenuItemPushButton;
 
291
 
 
292
    /*
 
293
     * now that we're going to set flags, we've got to be
 
294
     * careful when setting the type.  Use this macro:
 
295
     */
 
296
#define SetType(item, value) ((item)->type = ((item)->type & ~0x7) | (value))
 
297
 
 
298
    /*
 
299
     * parse any flags that modify the type.
 
300
     */
 
301
    while (XmtLexerGetToken(l) == XmtLexerKeyword) {
 
302
        switch(XmtLexerKeyValue(l)) {
 
303
        case ON:
 
304
            SetType(item, XmtMenuItemToggleButton);
 
305
            item->type |= XmtMenuItemOn;
 
306
            break;
 
307
        case OFF: 
 
308
            SetType(item, XmtMenuItemToggleButton);
 
309
            item->type &= ~XmtMenuItemOn;
 
310
            break;
 
311
        case HELP:
 
312
            item->type |= XmtMenuItemHelp;
 
313
            break;
 
314
        case TEAROFF:
 
315
            item->type |= XmtMenuItemTearoff;
 
316
            break;
 
317
        case PIXMAP:
 
318
            item->type |= XmtMenuItemPixmap;
 
319
            break;
 
320
        default:
 
321
            XmtWarningMsg("XmtMenu", "unexpectedKeyword",
 
322
                          "item \"%s\": unexpected keyword \"%s\"",
 
323
                          (item->label)?item->label:"",
 
324
                          XmtLexerStrValue(l));
 
325
            break;
 
326
        }
 
327
        XmtLexerConsumeToken(l);
 
328
    }
 
329
    
 
330
    
 
331
    /* parse item label */
 
332
    if (XmtLexerGetToken(l) == XmtLexerString) {
 
333
        /* the item label string; figure out label and mnemonic  */
 
334
        ParseLabelAndMnemonic(l, &item->label,
 
335
                              !(item->type & XmtMenuItemPixmap),
 
336
                              &item->mnemonic);
 
337
        if (XmtLexerGetToken(l) == XmtLexerBar) {  /* alternate label */
 
338
            SetType(item, XmtMenuItemToggleButton);
 
339
            if (XmtLexerNextToken(l) != XmtLexerString) {
 
340
                XmtWarningMsg("XmtMenu", "missingLabel",
 
341
                              "item '%s': alternate label expected after '|'",
 
342
                              item->label);
 
343
            }
 
344
            else
 
345
                ParseLabelAndMnemonic(l, &item->alt_label,
 
346
                                      !(item->type & XmtMenuItemPixmap),
 
347
                                      &item->alt_mnemonic);
 
348
        }
 
349
    }
 
350
 
 
351
    /* parse item accelerator */
 
352
    if (XmtLexerGetToken(l) == XmtLexerLBracket) { /* an accelerator */
 
353
        XmtLexerConsumeToken(l);
 
354
        (void) ParseAccelerator(l, item);
 
355
        if (XmtLexerGetToken(l) == XmtLexerRBracket)
 
356
            XmtLexerConsumeToken(l);
 
357
        else
 
358
            XmtWarningMsg("XmtMenu", "missingRBracket",
 
359
                          "`]' expected at end of accelerator for item \"%s\"",
 
360
                          item->label);
 
361
    }
 
362
 
 
363
    /* parse optional arrow and submenu name */
 
364
    if (XmtLexerGetToken(l) == XmtLexerMinus) {
 
365
        SetType(item, XmtMenuItemCascadeButton);
 
366
        if (XmtLexerNextToken(l) == XmtLexerGreater)
 
367
            XmtLexerConsumeToken(l);
 
368
        if (XmtLexerGetToken(l) == XmtLexerIdent) {
 
369
            item->submenu_name = XmtLexerStrValue(l);
 
370
            XmtLexerConsumeToken(l);
 
371
        }
 
372
        else {
 
373
            XmtWarningMsg("XmtMenu", "missingSubmenuName",
 
374
                          "item \"%s\": submenu name expected after `->'.",
 
375
                          item->label);
 
376
            SetType(item, XmtMenuItemPushButton);
 
377
            goto error;
 
378
        }
 
379
    }
 
380
 
 
381
    /*
 
382
     * Parse an optional symbol name, to be used by toggle buttons
 
383
     */
 
384
    if (XmtLexerGetToken(l) == XmtLexerDollar) {
 
385
        if (XmtLexerNextToken(l) != XmtLexerIdent) {
 
386
            XmtWarningMsg("XmtMenu", "missingSymbol",
 
387
                          "item '%s': symbol name expected after '$'.",
 
388
                          item->label);
 
389
            goto error;
 
390
        }
 
391
        item->symbol_name = XmtLexerStrValue(l);
 
392
        XmtLexerConsumeToken(l);
 
393
    }
 
394
 
 
395
    /*
 
396
     * parse callbacks.
 
397
     * Expect an identifier, a '{' or a ';'.
 
398
     * To parse the callbacks, we extract the callback string from the
 
399
     * private insides of the lexer and invoke whatever string-to-callback
 
400
     * converter is registered.
 
401
     */
 
402
    tok = XmtLexerGetToken(l);
 
403
    if ((tok == XmtLexerIdent) || (tok == XmtLexerLBrace)) { /* a callback */
 
404
        char *callback_string;
 
405
        int len = 0;
 
406
        XrmValue from, to;
 
407
        Boolean stat = False;
 
408
        
 
409
        if (tok == XmtLexerIdent) { /* a single callback */
 
410
            /* back up by the length of the current identifier */
 
411
            l->c -= XmtLexerStrLength(l);
 
412
            XtFree(XmtLexerStrValue(l));
 
413
        
 
414
            /* scan forward just past an unquoted semicolon */
 
415
            tok = XmtLexerScan(l, ";", True);
 
416
            if (tok == XmtLexerString) {
 
417
                callback_string = XmtLexerStrValue(l);
 
418
                len = XmtLexerStrLength(l);
 
419
                XmtLexerConsumeToken(l);
 
420
            }
 
421
            else callback_string = NULL;
 
422
        }
 
423
        else {  /* a compound callback */
 
424
            XmtLexerConsumeToken(l);  /* eat the open brace */
 
425
            XmtLexerSkipWhite(l);     /* skip whitespace */
 
426
            /* scan forward to just before an unquoted close brace */
 
427
            tok = XmtLexerScan(l, "}", False);
 
428
            if (tok == XmtLexerString) {
 
429
                callback_string = XmtLexerStrValue(l);
 
430
                len = XmtLexerStrLength(l);
 
431
                XmtLexerConsumeToken(l);
 
432
            }
 
433
            else callback_string = NULL;
 
434
 
 
435
            /* Now get and eat the '}' token */
 
436
            XmtLexerNextToken(l);
 
437
            XmtLexerConsumeToken(l);
 
438
        }
 
439
 
 
440
        /* convert the string to an XtCallbackList */
 
441
        if (!callback_string) {
 
442
            XmtWarningMsg("XmtMenu", "badCallback",
 
443
                          "bad callback string for item '%s'",
 
444
                          item->label);
 
445
        }
 
446
        else {
 
447
#if 0
 
448
            /*
 
449
             * The ref counting on the callback converter somehow causes
 
450
             * a core dump when the Menu widget is destroyed.  So we don't
 
451
             * do it this way.
 
452
             */
 
453
            from.addr = callback_string;
 
454
            from.size = len + 1;
 
455
            to.addr = (XPointer) &item->callback;
 
456
            to.size = sizeof(XtCallbackList);
 
457
            stat = XtConvertAndStore(w, XtRString, &from, XtRCallback, &to);
 
458
#endif
 
459
            if (_XmtCallbackConverter == NULL) {
 
460
                XmtWarningMsg("XmtMenu", "noConverter",
 
461
                              "no String to XtCallbackList converter registered.\n\tCall XmtRegisterCallbackConverter().");
 
462
                stat = False;
 
463
            }
 
464
            else {
 
465
                XtCacheRef ref_return;
 
466
                /*
 
467
                 * Here we just call the converter directly.
 
468
                 * We ignore the returned cache reference.  This will only
 
469
                 * cause a memory leak if the menu is destroyed, and in
 
470
                 * that case, a memory leak is better than the core dump
 
471
                 * we had above.
 
472
                 */
 
473
                from.addr = (XPointer) callback_string;
 
474
                from.size = len + 1;
 
475
                to.addr = (XPointer) &item->callback;
 
476
                to.size = sizeof(XtCallbackList);
 
477
                stat = XtCallConverter(XtDisplay(w), _XmtCallbackConverter,
 
478
                                       NULL, 0,
 
479
                                       &from, &to, &ref_return);
 
480
            }
 
481
 
 
482
        }
 
483
        
 
484
        /* if conversion failed, a warning will already be issued */
 
485
        if (!callback_string || !stat) item->callback = NULL;
 
486
        
 
487
        /* set flag that says we have a XtCallbackList, not XtCallbackProc */
 
488
        item->type |= XmtMenuItemCallbackList;
 
489
        
 
490
        /* and free the callback string */
 
491
        XtFree(callback_string);
 
492
    }
 
493
    else if (tok == XmtLexerSemicolon) {  /* no callback at all */
 
494
        XmtLexerConsumeToken(l);
 
495
    }
 
496
    else {
 
497
        XmtWarningMsg("XmtMenu", "semicolonExpected",
 
498
                      "item \"%s\": semicolon expected at end of item description.",
 
499
                      item->label);
 
500
        goto error;
 
501
    }
 
502
    
 
503
    return 0;
 
504
 
 
505
 error:
 
506
    /* error recovery: free strings and read 'till `;' or end of string */
 
507
    XtFree(item->label);
 
508
    XtFree(item->accelerator);
 
509
    XtFree(item->accelerator_label);
 
510
    XtFree(item->name);
 
511
    XtFree(item->submenu_name);
 
512
    
 
513
    while(1) {
 
514
        tok = XmtLexerGetToken(l);
 
515
        if ((tok == XmtLexerSemicolon) || (tok == XmtLexerEndOfString)) break;
 
516
        XmtLexerConsumeToken(l);
 
517
    }
 
518
    XmtLexerConsumeToken(l);
 
519
    return 1;
 
520
}    
 
521
 
 
522
#if NeedFunctionPrototypes
 
523
Boolean XmtParseMenuString(Widget w, String str, XmtMenuItem **items_return)
 
524
#else
 
525
Boolean XmtParseMenuString(w, str, items_return)
 
526
Widget w;
 
527
String str;
 
528
XmtMenuItem **items_return;
 
529
#endif
 
530
{
 
531
    static XmtLexer l = NULL;
 
532
    XmtMenuItem *items;
 
533
    int num_items, max_items;
 
534
 
 
535
    if (l == NULL)
 
536
        l = XmtLexerCreate(keywords, XtNumber(keywords));
 
537
 
 
538
    XmtLexerInit(l, str);
 
539
 
 
540
    max_items = 8;
 
541
    num_items = 0;
 
542
    items = (XmtMenuItem *) XtMalloc(sizeof(XmtMenuItem) * max_items);
 
543
 
 
544
    while (XmtLexerGetToken(l) != XmtLexerEndOfString) {
 
545
        if (num_items == max_items) {
 
546
            max_items *= 2;
 
547
            items = (XmtMenuItem *) XtRealloc((char *) items,
 
548
                                              sizeof(XmtMenuItem) * max_items);
 
549
        }
 
550
        if (ParseItem(w, l, &items[num_items]) == 0) /* if no error */
 
551
            num_items++;
 
552
    }
 
553
 
 
554
    if (num_items == max_items) {
 
555
        max_items++;
 
556
        items = (XmtMenuItem *) XtRealloc((char *) items,
 
557
                                          sizeof(XmtMenuItem) * max_items);
 
558
    }
 
559
    items[num_items].type = XmtMenuItemEnd;  /* NULL-termination */
 
560
 
 
561
    *items_return = items;
 
562
    return True;
 
563
}
 
564
 
 
565
 
 
566
/*ARGSUSED*/
 
567
#if NeedFunctionPrototypes
 
568
Boolean XmtConvertStringToXmtMenuItems(Display *dpy,
 
569
                                       XrmValuePtr args, Cardinal *num_args,
 
570
                                       XrmValuePtr from, XrmValuePtr to,
 
571
                                       XtPointer *closure_return)
 
572
#else
 
573
Boolean XmtConvertStringToXmtMenuItems(dpy, args, num_args,
 
574
                                       from, to, closure_return)
 
575
Display *dpy;
 
576
XrmValuePtr args;
 
577
Cardinal *num_args;
 
578
XrmValuePtr from;
 
579
XrmValuePtr to;
 
580
XtPointer *closure_return;
 
581
#endif
 
582
{
 
583
    String str = (String)from->addr;
 
584
    XmtMenuItem *value;
 
585
    Boolean status;
 
586
    Widget w = *((Widget *)args[0].addr);
 
587
 
 
588
    /* convert string to NULL-terminated array of XmtMenuItems */
 
589
    status = XmtParseMenuString(w, str, &value);
 
590
 
 
591
    if (status == False) return False;
 
592
 
 
593
    done(XmtMenuItem *, value);  /* a macro in ConvertersP.h */
 
594
}
 
595
 
 
596
/* ARGSUSED */
 
597
#if NeedFunctionPrototypes
 
598
static void MenuItemsDestructor(XtAppContext app, XrmValue *to,
 
599
                                XtPointer converter_data,
 
600
                                XrmValue *args, Cardinal *num_args)
 
601
#else
 
602
static void MenuItemsDestructor(app, to, converter_data, args, num_args)
 
603
XtAppContext app;
 
604
XrmValue *to;
 
605
XtPointer converter_data;
 
606
XrmValue *args;
 
607
Cardinal *num_args;
 
608
#endif
 
609
{
 
610
    XmtMenuItem *items = *(XmtMenuItem **) to->addr;
 
611
    int i;
 
612
 
 
613
    for(i=0; items[i].type != XmtMenuItemEnd; i++) {
 
614
        XtFree(items[i].label);
 
615
        XtFree(items[i].accelerator);
 
616
        XtFree(items[i].accelerator_label);
 
617
        XtFree(items[i].name);
 
618
        XtFree(items[i].submenu_name);
 
619
    }
 
620
    XtFree((char *)items);
 
621
}
 
622
 
 
623
static XtConvertArgRec convert_args[] = {
 
624
  {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.self), sizeof(Widget)}
 
625
};
 
626
 
 
627
 
 
628
#if NeedFunctionPrototypes
 
629
void XmtRegisterMenuItemsConverter(void)
 
630
#else
 
631
void XmtRegisterMenuItemsConverter()
 
632
#endif
 
633
{
 
634
    static Boolean registered = False;
 
635
 
 
636
    if (!registered) {
 
637
        registered = True;
 
638
        XtSetTypeConverter(XmRString, XmtRXmtMenuItemList,
 
639
                           XmtConvertStringToXmtMenuItems,
 
640
                           convert_args, XtNumber(convert_args),
 
641
                           XtCacheNone, MenuItemsDestructor);
 
642
    }
 
643
}