~ubuntu-branches/ubuntu/quantal/openmotif/quantal

« back to all changes in this revision

Viewing changes to clients/mwm/WmResParse.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bauer
  • Date: 2010-06-23 12:12:31 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100623121231-u89gxdp51sg9wjj2
Tags: 2.3.0-1
* New Maintainer (Closes: #379258) 
* Acknowledge NMU changes
* New upstream release (Closes: #494375)
* Get rid of security patches as they are already part of new upstream
  release (00-xpmvuln.openmotif.patch, 342092-CVE-2005-3964.patch)
* Bump Standards to 3.8.4
* Added {misc:Depends} to make the package lintian cleaner
* Fix weak-library-dev-dependency by adding ${binary:Version}) for the
  -dev Package of openmotif
* Let package depend on autotools-dev to use newer autotools-helper-files
* Work around an autoconf-bug (Gentoo-Bug #1475)
* Added Client-side anti-aliased fonts support via XFT
* Added UTF-8 and UTF8_STRING atom support
* Ability to show text and pixmaps in Label, LabelGadget and all
  derived widgets
* Support of PNG/JPEG image formats in the same way as XPM is supported
* Increase FILE_OFFSET_BITS to 64 to show files >2GB in file-selector
  Idea taken from Magne Oestlyngen (Closes: #288537)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * @OPENGROUP_COPYRIGHT@
 
3
 * COPYRIGHT NOTICE
 
4
 * Copyright (c) 1989, 1990, 1991, 1992, 1993, 1994 Open Software Foundation, Inc. 
 
5
 * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 
6
 * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
 
7
 * the full copyright text.
 
8
 * 
 
9
 * This software is subject to an open license. It may only be
 
10
 * used on, with or for operating systems which are themselves open
 
11
 * source systems. You must contact The Open Group for a license
 
12
 * allowing distribution and sublicensing of this software on, with,
 
13
 * or for operating systems which are not Open Source programs.
 
14
 * 
 
15
 * See http://www.opengroup.org/openmotif/license for full
 
16
 * details of the license agreement. Any use, reproduction, or
 
17
 * distribution of the program constitutes recipient's acceptance of
 
18
 * this agreement.
 
19
 * 
 
20
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 
21
 * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
22
 * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 
23
 * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 
24
 * OR FITNESS FOR A PARTICULAR PURPOSE
 
25
 * 
 
26
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 
27
 * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 
28
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
29
 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
 
30
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 
32
 * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
 
33
 * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 
34
 * POSSIBILITY OF SUCH DAMAGES.
 
35
*/ 
 
36
/* 
 
37
 * Motif Release 1.2.4
 
38
*/ 
 
39
#ifdef HAVE_CONFIG_H
 
40
#include <config.h>
 
41
#endif
 
42
 
 
43
 
 
44
#ifdef REV_INFO
 
45
#ifndef lint
 
46
static char rcsid[] = "$XConsortium: WmResParse.c /main/9 1996/11/01 10:17:34 drk $"
 
47
#endif
 
48
#endif
 
49
/*
 
50
 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 Hewlett-Packard Company
 
51
 * (c) Copyright 1993, 1994 International Business Machines Corp.
 
52
 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
 
53
 * (c) Copyright 1993, 1994 Novell, Inc.
 
54
 */
 
55
/*
 
56
 * (c) Copyright 1987, 1988 DIGITAL EQUIPMENT CORPORATION */
 
57
/*
 
58
 * (c) Copyright 1988 MASSACHUSETTS INSTITUTE OF TECHNOLOGY */
 
59
 
 
60
/*
 
61
 * Included Files:
 
62
 */
 
63
 
 
64
#include "WmGlobal.h"
 
65
#include "WmResNames.h"
 
66
#ifdef WSM
 
67
#include <Dt/UserMsg.h>
 
68
#include <Dt/Connect.h>
 
69
#include <Tt/tt_c.h>
 
70
#endif /* WSM */
 
71
#ifdef PANELIST
 
72
#include "WmParse.h"
 
73
#include "WmParseP.h"
 
74
#include "WmPanelP.h"
 
75
#endif /* PANELIST */
 
76
#include "WmResource.h"
 
77
 
 
78
#include <Xm/VirtKeysP.h>
 
79
 
 
80
#include <X11/cursorfont.h>
 
81
#include <X11/keysym.h>
 
82
#include <X11/Xatom.h>
 
83
#include <ctype.h>
 
84
 
 
85
#include <X11/Xlocale.h>
 
86
 
 
87
#ifndef NO_MULTIBYTE
 
88
#include <stdlib.h>
 
89
#endif
 
90
 
 
91
#ifdef MOTIF_ONE_DOT_ONE
 
92
#include <stdio.h>
 
93
#include <pwd.h>
 
94
#else
 
95
#include <Xm/XmP.h>             /* for XmeGetHomeDirName */
 
96
#endif
 
97
#ifdef WSM
 
98
#include <signal.h>
 
99
#endif /* WSM */
 
100
 
 
101
/* maximum string lengths */
 
102
 
 
103
#define MAX_KEYSYM_STRLEN    100
 
104
#define MAX_EVENTTYPE_STRLEN  20
 
105
#define MAX_MODIFIER_STRLEN   20
 
106
#define MAX_CONTEXT_STRLEN    20
 
107
#define MAX_GROUP_STRLEN      20
 
108
 
 
109
#ifdef min
 
110
#undef min
 
111
#endif
 
112
#define min(a,b)        ((a)>(b) ? (b) : (a))
 
113
 
 
114
#define MAXLINE     (MAXWMPATH+1)
 
115
 
 
116
#define MBBSIZ      4096
 
117
 
 
118
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
119
# define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD, mSpec)
 
120
#else
 
121
# define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD)
 
122
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
123
 
 
124
/*
 
125
 * include extern functions
 
126
 */
 
127
#include "WmResParse.h"
 
128
#ifdef WSM
 
129
#include "WmWrkspace.h"
 
130
#endif /* WSM */
 
131
#include "WmError.h"
 
132
#include "WmFunction.h"
 
133
#include "WmImage.h"
 
134
#include "WmXSMP.h"
 
135
 
 
136
#ifdef MOTIF_ONE_DOT_ONE
 
137
extern char   *getenv ();
 
138
#endif
 
139
#ifdef PANELIST
 
140
# include <errno.h>
 
141
# ifdef X_NOT_STDC_ENV
 
142
extern int errno;
 
143
# endif
 
144
# define HOME_DT_WMRC    "/.dt/dtwmrc"
 
145
# define LANG_DT_WMRC    "/dtwmrc"
 
146
# define SYS_DT_WMRC     CDE_CONFIGURATION_TOP "/sys.dtwmrc"
 
147
#endif /* PANELIST */
 
148
 
 
149
/*
 
150
 * Global Variables And Tables:
 
151
 */
 
152
static char cfileName[MAXWMPATH+1];
 
153
#ifdef WSM
 
154
#ifndef NO_MESSAGE_CATALOG
 
155
char * pWarningStringFile;
 
156
char * pWarningStringLine;
 
157
#else
 
158
char pWarningStringFile[] = "%s: %s on line %d of configuration file %s\n";
 
159
char pWarningStringLine[] = "%s: %s on line %d of specification string\n";
 
160
#endif
 
161
#define cfileP  (wmGD.pWmPB->pFile)
 
162
#define parseP  (wmGD.pWmPB->pchNext)
 
163
#define line    (wmGD.pWmPB->pchLine)
 
164
#define linec   (wmGD.pWmPB->lineNumber)
 
165
#else  /* WSM */
 
166
static FILE *cfileP = NULL;   /* fopen'ed configuration file or NULL */
 
167
static unsigned char  line[MAXLINE+1]; /* line buffer */
 
168
static int   linec = 0;       /* line counter for parser */
 
169
static unsigned char *parseP = NULL;   /* pointer to parse string */
 
170
#endif /* WSM */
 
171
 
 
172
 
 
173
typedef struct {
 
174
   char         *name;
 
175
   unsigned int  mask;
 
176
} MaskTableEntry;
 
177
 
 
178
static MaskTableEntry modifierStrings[] = {
 
179
 
 
180
    {"none",    None},
 
181
    {"ctrl",    ControlMask},
 
182
    {"shift",   ShiftMask},
 
183
    {"alt",     Mod1Mask},
 
184
    {"meta",    Mod1Mask},
 
185
    {"lock",    LockMask},
 
186
    {"mod1",    Mod1Mask},
 
187
    {"mod2",    Mod2Mask},
 
188
    {"mod3",    Mod3Mask},
 
189
    {"mod4",    Mod4Mask},
 
190
    {"mod5",    Mod5Mask},
 
191
    {NULL,      (unsigned int)NULL},
 
192
};
 
193
 
 
194
#define ALT_INDEX 3
 
195
#define META_INDEX 4
 
196
 
 
197
typedef struct {
 
198
   char         *event;
 
199
   unsigned int  eventType;
 
200
   Boolean       (*parseProc)();
 
201
   unsigned int  closure;
 
202
   Boolean       fClick;
 
203
} EventTableEntry;
 
204
 
 
205
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
206
 
 
207
# define CCI_USE_DEFAULT_NAME_TAG "DEFAULT_NAME"
 
208
 
 
209
String CCIEntryModifierNames[] = {
 
210
  "none",
 
211
  "inline",
 
212
  "cascade",
 
213
  "delimit",
 
214
  "delimit_inline",
 
215
  "delimit_cascade",
 
216
  "exclude"
 
217
};
 
218
 
 
219
typedef enum {
 
220
  NONE,             /* internal only. */
 
221
  INLINE,           /* not supported. */
 
222
  CASCADE,
 
223
  DELIMIT,
 
224
  DELIMIT_INLINE,   /* not supported. */
 
225
  DELIMIT_CASCADE,
 
226
  EXCLUDE
 
227
} CCIEntryModifier;
 
228
 
 
229
typedef struct _CCIFuncArg {
 
230
  CCIEntryModifier mod;
 
231
  String           cciEntry;
 
232
} CCIFuncArg;
 
233
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
234
 
 
235
#ifdef MOTIF_ONE_DOT_ONE
 
236
void GetHomeDirName(String  fileName);
 
237
#endif
 
238
#ifdef WSM
 
239
static String GetNetworkFileName (char *pchFile);
 
240
#endif /* WSM */
 
241
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
242
static MenuItem        *MakeSeparatorTemplate  (int);
 
243
static void ParseMenuItemName (unsigned char **linePP, MenuItem *menuItem);
 
244
static Boolean ParseClientCommand (unsigned char **linePP, MenuSpec *menuSpec,
 
245
                                   MenuItem *menuItem, unsigned char *string,
 
246
                                   Boolean *use_separators);
 
247
static void FixMenuItem (MenuSpec *menuSpec, MenuItem *menuItem);
 
248
static Boolean GetCCIModifier (String modString, CCIEntryModifier *mod);
 
249
static Boolean ParseWmFuncCCIArgs (unsigned char **linePP, 
 
250
                                   WmFunction wmFunction, String *pArgs);
 
251
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
252
FILE *FopenConfigFile (void);
 
253
void SaveMenuAccelerators (WmScreenData *pSD, MenuSpec *newMenuSpec);
 
254
static void ParseMenuSet (WmScreenData *pSD, unsigned char *lineP);
 
255
MenuItem *ParseMwmMenuStr (WmScreenData *pSD, unsigned char *menuStr);
 
256
static MenuItem *ParseMenuItems (WmScreenData *pSD
 
257
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
258
                                 , MenuSpec *menuSpec
 
259
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
260
                                );
 
261
static Boolean ParseWmLabel (WmScreenData *pSD, MenuItem *menuItem, 
 
262
                             unsigned char *string);
 
263
static void ParseWmMnemonic (unsigned char **linePP, MenuItem *menuItem);
 
264
static Boolean ParseWmAccelerator (unsigned char **linePP, MenuItem *menuItem);
 
265
int ParseWmFunction (unsigned char **linePP, unsigned int res_spec, 
 
266
                            WmFunction *pWmFunction);
 
267
#ifndef PANELIST
 
268
static Boolean ParseWmFuncMaybeStrArg (unsigned char **linePP, 
 
269
                                       WmFunction wmFunction, String *pArgs);
 
270
#endif /* PANELIST */
 
271
static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction,
 
272
                                 String *pArgs);
 
273
#ifndef PANELIST
 
274
static Boolean ParseWmFuncStrArg (unsigned char **linePP, 
 
275
                                  WmFunction wmFunction, String *pArgs);
 
276
#endif /* PANELIST */
 
277
void FreeMenuItem (MenuItem *menuItem);
 
278
static Boolean ParseWmFuncGrpArg (unsigned char **linePP, 
 
279
                                  WmFunction wmFunction, GroupArg *pGroup);
 
280
static Boolean ParseWmFuncNbrArg (unsigned char **linePP, 
 
281
                                  WmFunction wmFunction, 
 
282
                                  unsigned long *pNumber);
 
283
void ParseButtonStr (WmScreenData *pSD, unsigned char *buttonStr);
 
284
static void ParseButtonSet (WmScreenData *pSD, unsigned char *lineP);
 
285
static Boolean ParseContext (unsigned char **linePP, Context *context, 
 
286
                             Context *subContext);
 
287
void
 
288
ParseKeyStr (WmScreenData *pSD, unsigned char *keyStr);
 
289
static void ParseKeySet (WmScreenData *pSD, unsigned char *lineP);
 
290
Boolean ParseBtnEvent (unsigned char  **linePP,
 
291
                       unsigned int *eventType,
 
292
                       unsigned int *button,
 
293
                       unsigned int *state,
 
294
                       Boolean      *fClick);
 
295
Boolean ParseKeyEvent (unsigned char **linePP, unsigned int *eventType,
 
296
                       KeyCode *keyCode,  unsigned int *state);
 
297
static Boolean ParseEvent (unsigned char **linePP, EventTableEntry *table,
 
298
                           unsigned int *eventType, unsigned int *detail,
 
299
                           unsigned int *state, Boolean *fClick);
 
300
static Boolean ParseModifiers(unsigned char **linePP, unsigned int *state);
 
301
static Boolean LookupModifier (unsigned char *name, unsigned int *valueP);
 
302
static Boolean ParseEventType (unsigned char **linePP, EventTableEntry *table,
 
303
                               unsigned int *eventType, Cardinal *ix);
 
304
static Boolean ParseImmed (unsigned char **linePP, unsigned int closure,
 
305
                           unsigned int  *detail);
 
306
static Boolean ParseKeySym (unsigned char **linePP, unsigned int closure,
 
307
                            unsigned int *detail);
 
308
static unsigned int StrToNum(unsigned char *str);
 
309
static unsigned int StrToHex(unsigned char *str);
 
310
static unsigned int StrToOct(unsigned char *str);
 
311
void ScanAlphanumeric (unsigned char **linePP);
 
312
void ScanWhitespace(unsigned char  **linePP);
 
313
void ToLower (unsigned char  *string);
 
314
void
 
315
PWarning (char *message);
 
316
static void ProcessAccelText (unsigned char *startP, unsigned char *endP,
 
317
                              unsigned char *destP);
 
318
void ProcessCommandLine (int argc,  char *argv[]);
 
319
static void ParseScreensArgument (int argc, char *argv[], int *pArgnum,
 
320
                                  unsigned char *lineP);
 
321
void ProcessMotifBindings (void);
 
322
#ifdef PANELIST
 
323
static void ParseIncludeSet (WmScreenData *pSD, unsigned char *lineP);
 
324
static void ConfigStackInit (char *pchFileName);
 
325
static FILE *ConfigStackPush (unsigned char *pchFileName);
 
326
static void ConfigStackPop (void);
 
327
Boolean ParseWmFuncActionArg (unsigned char **linePP, 
 
328
                                  WmFunction wmFunction, String *pArgs);
 
329
static void PreprocessConfigFile (void);
 
330
#endif /* PANELIST */
 
331
 
 
332
static EventTableEntry buttonEvents[] = {
 
333
 
 
334
    {"btn1down",    ButtonPress,    ParseImmed,    SELECT_BUTTON,  FALSE},
 
335
    {"btn1up",      ButtonRelease,  ParseImmed,    SELECT_BUTTON,  FALSE},
 
336
    {"btn1click",   ButtonRelease,  ParseImmed,    SELECT_BUTTON,  TRUE},
 
337
    {"btn1click2",  ButtonPress,    ParseImmed,    SELECT_BUTTON,  TRUE},
 
338
    {"btn2down",    ButtonPress,    ParseImmed,    DMANIP_BUTTON,  FALSE},
 
339
    {"btn2up",      ButtonRelease,  ParseImmed,    DMANIP_BUTTON,  FALSE},
 
340
    {"btn2click",   ButtonRelease,  ParseImmed,    DMANIP_BUTTON,  TRUE},
 
341
    {"btn2click2",  ButtonPress,    ParseImmed,    DMANIP_BUTTON,  TRUE},
 
342
    {"btn3down",    ButtonPress,    ParseImmed,    BMENU_BUTTON,  FALSE},
 
343
    {"btn3up",      ButtonRelease,  ParseImmed,    BMENU_BUTTON,  FALSE},
 
344
    {"btn3click",   ButtonRelease,  ParseImmed,    BMENU_BUTTON,  TRUE},
 
345
    {"btn3click2",  ButtonPress,    ParseImmed,    BMENU_BUTTON,  TRUE},
 
346
    {"btn4down",    ButtonPress,    ParseImmed,    Button4,  FALSE},
 
347
    {"btn4up",      ButtonRelease,  ParseImmed,    Button4,  FALSE},
 
348
    {"btn4click",   ButtonRelease,  ParseImmed,    Button4,  TRUE},
 
349
    {"btn4click2",  ButtonPress,    ParseImmed,    Button4,  TRUE},
 
350
    {"btn5down",    ButtonPress,    ParseImmed,    Button5,  FALSE},
 
351
    {"btn5up",      ButtonRelease,  ParseImmed,    Button5,  FALSE},
 
352
    {"btn5click",   ButtonRelease,  ParseImmed,    Button5,  TRUE},
 
353
    {"btn5click2",  ButtonPress,    ParseImmed,    Button5,  TRUE},
 
354
    { NULL, (unsigned int)NULL, (Boolean(*)())NULL, (unsigned int)NULL, (Boolean)NULL}
 
355
};
 
356
 
 
357
 
 
358
static EventTableEntry keyEvents[] = {
 
359
 
 
360
    {"key",         KeyPress,    ParseKeySym,    0,  FALSE},
 
361
    { NULL, (unsigned int)NULL, (Boolean(*)())NULL, (unsigned int)NULL, (Boolean)NULL}
 
362
};
 
363
 
 
364
#ifdef PANELIST
 
365
typedef struct _ConfigFileStackEntry {
 
366
    char                *fileName;
 
367
    char                *tempName;
 
368
    char                *cppName;
 
369
    char                *wmgdConfigFile;
 
370
    long                offset;
 
371
    DtWmpParseBuf       *pWmPB;
 
372
    struct _ConfigFileStackEntry        *pIncluder;
 
373
    
 
374
} ConfigFileStackEntry;
 
375
 
 
376
static ConfigFileStackEntry *pConfigStack = NULL;
 
377
static ConfigFileStackEntry *pConfigStackTop = NULL;
 
378
 
 
379
#endif /* PANELIST */
 
380
 
 
381
unsigned int buttonModifierMasks[] = {
 
382
    0,
 
383
    SELECT_BUTTON_MASK,
 
384
    DMANIP_BUTTON_MASK,
 
385
    BMENU_BUTTON_MASK,
 
386
    Button4Mask,
 
387
    Button5Mask
 
388
};
 
389
 
 
390
/*
 
391
 * FUNCTION PARSER TABLE (function names must be in alphabetic order)
 
392
 */
 
393
 
 
394
typedef struct {
 
395
   char         * funcName;
 
396
   Context        greyedContext;
 
397
   unsigned int   resource;
 
398
   long           mgtMask;
 
399
   WmFunction     wmFunction;
 
400
   Boolean       (*parseProc)();
 
401
} FunctionTableEntry;
 
402
 
 
403
 
 
404
/*
 
405
 * NOTE: New functions MUST be added in ALPHABETICAL order.  A binary search
 
406
 *       is used to find the correct function name.
 
407
 */
 
408
 
 
409
FunctionTableEntry functionTable[] = {
 
410
#ifdef WSM
 
411
#ifdef PANELIST
 
412
    {"f.action",        0,
 
413
                        CRS_ANY,
 
414
                        0,
 
415
                        F_Action,
 
416
                        ParseWmFuncActionArg},
 
417
#else /* PANELIST */
 
418
    {"f.action",        0,
 
419
                        CRS_ANY,
 
420
                        0,
 
421
                        F_Action,
 
422
                        ParseWmFuncStrArg},
 
423
#endif  /* PANELIST */
 
424
#endif /* WSM */
 
425
    {"f.beep",          0,
 
426
                        CRS_ANY,
 
427
                        0,
 
428
                        F_Beep,
 
429
                        ParseWmFuncNoArg},
 
430
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
431
    {"f.cci",           0,
 
432
                        CRS_ANY,
 
433
                        0,
 
434
                        F_Nop,
 
435
                        ParseWmFuncCCIArgs},
 
436
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
437
    {"f.circle_down",   F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
438
                        CRS_ANY,
 
439
                        0,
 
440
                        F_Circle_Down,
 
441
                        ParseWmFuncGrpArg},
 
442
    {"f.circle_up",     F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
443
                        CRS_ANY,
 
444
                        0,
 
445
                        F_Circle_Up,
 
446
                        ParseWmFuncGrpArg},
 
447
#ifdef WSM
 
448
    {"f.create_workspace", 0,
 
449
                        CRS_ANY,
 
450
                        0,
 
451
                        F_CreateWorkspace,
 
452
                        ParseWmFuncNoArg},
 
453
    {"f.delete_workspace", 0,
 
454
                        CRS_ANY,
 
455
                        0,
 
456
                        F_DeleteWorkspace,
 
457
                        ParseWmFuncNoArg},
 
458
#endif /* WSM */
 
459
    {"f.exec",          0,
 
460
                        CRS_ANY,
 
461
                        0,
 
462
                        F_Exec,
 
463
                        ParseWmFuncStrArg},
 
464
    {"f.focus_color",   F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
465
                        CRS_ANY,
 
466
                        0,
 
467
                        F_Focus_Color,
 
468
                        ParseWmFuncNoArg},
 
469
    {"f.focus_key",     F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
470
                        CRS_ANY,
 
471
                        0,
 
472
                        F_Focus_Key,
 
473
                        ParseWmFuncNoArg},
 
474
#ifdef WSM
 
475
    {"f.goto_workspace", 0,
 
476
                        CRS_ANY,
 
477
                        0,
 
478
                        F_Goto_Workspace,
 
479
                        ParseWmFuncStrArg},
 
480
#endif /* WSM */
 
481
#ifdef WSM
 
482
    {"f.help",          0,
 
483
                        CRS_ANY,
 
484
                        0,
 
485
                        F_Help,
 
486
                        ParseWmFuncStrArg},  /* [helpvolume && helptopic] */
 
487
    {"f.help_mode",     0,
 
488
                        CRS_ANY,
 
489
                        0,
 
490
                        F_Help_Mode,
 
491
                        ParseWmFuncNoArg},  /* for now */
 
492
#endif /* WSM */
 
493
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
494
    {"f.invoke_command",
 
495
                        0, CRS_ANY,
 
496
                        0,
 
497
                        F_InvokeCommand,
 
498
                        ParseWmFuncStrArg},
 
499
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
500
    {"f.kill",          F_CONTEXT_ROOT,
 
501
                        CRS_ANY,
 
502
                        MWM_FUNC_CLOSE,
 
503
                        F_Kill,
 
504
                        ParseWmFuncNoArg},
 
505
    {"f.lower",         F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
506
                        CRS_ANY,
 
507
                        0,
 
508
                        F_Lower,
 
509
                        ParseWmFuncMaybeStrArg},
 
510
#ifdef WSM
 
511
    {"f.marquee_selection",     
 
512
                        F_CONTEXT_WINDOW|F_CONTEXT_ICON|F_SUBCONTEXT_IB_IICON,
 
513
                        CRS_ANY,
 
514
                        0,
 
515
                        F_Marquee_Selection,
 
516
                        ParseWmFuncNoArg},
 
517
#endif /* WSM */
 
518
    {"f.maximize",      F_CONTEXT_ROOT|F_CONTEXT_MAXIMIZE|
 
519
                                       F_SUBCONTEXT_IB_WICON,
 
520
                        CRS_ANY,
 
521
                        MWM_FUNC_MAXIMIZE,
 
522
                        F_Maximize,
 
523
                        ParseWmFuncNoArg},
 
524
    {"f.menu",          0,
 
525
                        CRS_ANY,
 
526
                        0,
 
527
                        F_Menu,
 
528
                        ParseWmFuncStrArg},
 
529
    {"f.minimize",      F_CONTEXT_ICON|F_CONTEXT_ROOT|F_SUBCONTEXT_IB_IICON,
 
530
                        CRS_ANY,
 
531
                        MWM_FUNC_MINIMIZE,
 
532
                        F_Minimize,
 
533
                        ParseWmFuncNoArg},
 
534
    {"f.move",          F_CONTEXT_ROOT,
 
535
                        CRS_ANY,
 
536
                        MWM_FUNC_MOVE,
 
537
                        F_Move,
 
538
                        ParseWmFuncNoArg},
 
539
    {"f.next_cmap",     0,
 
540
                        CRS_ANY,
 
541
                        0,
 
542
                        F_Next_Cmap,
 
543
                        ParseWmFuncNoArg},
 
544
    {"f.next_key",      0,
 
545
                        CRS_ANY,
 
546
                        0,
 
547
                        F_Next_Key,
 
548
                        ParseWmFuncGrpArg},
 
549
#ifdef WSM
 
550
    {"f.next_workspace",        0,
 
551
                        CRS_ANY,
 
552
                        0,
 
553
                        F_Next_Workspace,
 
554
                        ParseWmFuncNoArg},
 
555
#endif /* WSM */
 
556
    {"f.nop",           F_CONTEXT_ROOT|F_CONTEXT_ICON|F_CONTEXT_WINDOW|
 
557
                            F_SUBCONTEXT_IB_WICON | F_SUBCONTEXT_IB_IICON,
 
558
                        CRS_ANY,
 
559
                        0,
 
560
                        F_Nop,
 
561
                        ParseWmFuncNoArg},
 
562
    {"f.normalize",     F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON,
 
563
                        CRS_ANY,
 
564
                        0,
 
565
                        F_Normalize,
 
566
                        ParseWmFuncNoArg},
 
567
#ifdef PANELIST
 
568
    {"f.normalize_and_raise",
 
569
                        F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
 
570
                        CRS_ANY,
 
571
                        0,
 
572
                        F_Normalize_And_Raise,
 
573
                        ParseWmFuncMaybeStrArg},
 
574
#else /* PANELIST */
 
575
    {"f.normalize_and_raise",
 
576
                        F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
 
577
                        CRS_ANY,
 
578
                        0,
 
579
                        F_Normalize_And_Raise,
 
580
                        ParseWmFuncNoArg},
 
581
#endif /* PANELIST */
 
582
#ifdef WSM
 
583
    {"f.occupy_all", F_CONTEXT_ICONBOX|F_CONTEXT_ROOT,
 
584
                        CRS_ANY,
 
585
                        DtWM_FUNC_OCCUPY_WS,
 
586
                        F_AddToAllWorkspaces,
 
587
                        ParseWmFuncNoArg},
 
588
#endif /* WSM */
 
589
    {"f.pack_icons",    0,
 
590
                        CRS_ANY,
 
591
                        0,
 
592
                        F_Pack_Icons,
 
593
                        ParseWmFuncNoArg},
 
594
    {"f.pass_keys",     0,
 
595
                        CRS_ANY,
 
596
                        0,
 
597
                        F_Pass_Key,
 
598
                        ParseWmFuncNoArg},
 
599
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
600
    {"f.post_rmenu",    0,
 
601
                        CRS_KEY,
 
602
                        0,
 
603
                        F_Post_RMenu,
 
604
                        ParseWmFuncNoArg},
 
605
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
606
    {"f.post_wmenu",    0,
 
607
                        CRS_BUTTON|CRS_KEY,
 
608
                        0,
 
609
                        F_Post_SMenu,
 
610
                        ParseWmFuncNoArg},
 
611
    {"f.prev_cmap",     0,
 
612
                        CRS_ANY,
 
613
                        0,
 
614
                        F_Prev_Cmap,
 
615
                        ParseWmFuncNoArg},
 
616
    {"f.prev_key",      0,
 
617
                        CRS_ANY,
 
618
                        0,
 
619
                        F_Prev_Key,
 
620
                        ParseWmFuncGrpArg},
 
621
#ifdef WSM
 
622
    {"f.prev_workspace",        0,
 
623
                        CRS_ANY,
 
624
                        0,
 
625
                        F_Prev_Workspace,
 
626
                        ParseWmFuncNoArg},
 
627
#endif /* WSM */
 
628
    {"f.quit_mwm",      F_CONTEXT_ICON|F_CONTEXT_WINDOW,
 
629
                        CRS_ANY,
 
630
                        0,
 
631
                        F_Quit_Mwm,
 
632
                        ParseWmFuncNoArg},
 
633
    {"f.raise",         F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
634
                        CRS_ANY,
 
635
                        0,
 
636
                        F_Raise,
 
637
                        ParseWmFuncMaybeStrArg},
 
638
    {"f.raise_lower",   F_CONTEXT_ROOT |
 
639
                                F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
640
                        CRS_ANY,
 
641
                        0,
 
642
                        F_Raise_Lower,
 
643
                        ParseWmFuncNoArg},
 
644
    {"f.refresh",       0,
 
645
                        CRS_ANY,
 
646
                        0,
 
647
                        F_Refresh,
 
648
                        ParseWmFuncNoArg},
 
649
    {"f.refresh_win",   F_CONTEXT_ICON|F_CONTEXT_ROOT,
 
650
                        CRS_ANY,
 
651
                        0,
 
652
                        F_Refresh_Win,
 
653
                        ParseWmFuncNoArg},
 
654
#ifdef WSM
 
655
    {"f.remove",        F_CONTEXT_ROOT,
 
656
                        CRS_ANY,
 
657
                        DtWM_FUNC_OCCUPY_WS,
 
658
                        F_Remove,
 
659
                        ParseWmFuncNoArg},
 
660
#endif /* WSM */
 
661
    {"f.resize",        F_CONTEXT_ICON|F_CONTEXT_ROOT|
 
662
                                 F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
663
                        CRS_ANY,
 
664
                        MWM_FUNC_RESIZE,
 
665
                        F_Resize,
 
666
                        ParseWmFuncNoArg},
 
667
#ifdef WSM
 
668
    {"f.restart",       F_CONTEXT_ICON|F_CONTEXT_WINDOW,
 
669
                        CRS_ANY,
 
670
                        0,
 
671
                        F_Restart,
 
672
                        ParseWmFuncStrArg},
 
673
#else /* WSM */
 
674
    {"f.restart",       F_CONTEXT_ICON|F_CONTEXT_WINDOW,
 
675
                        CRS_ANY,
 
676
                        0,
 
677
                        F_Restart,
 
678
                        ParseWmFuncNoArg},
 
679
#endif /* WSM */
 
680
    {"f.restore",       F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON,
 
681
                        CRS_ANY,
 
682
                        0,
 
683
                        F_Restore,
 
684
                        ParseWmFuncNoArg},
 
685
    {"f.restore_and_raise",
 
686
                        F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
 
687
                        CRS_ANY,
 
688
                        0,
 
689
                        F_Restore_And_Raise,
 
690
                        ParseWmFuncNoArg},
 
691
    {"f.screen",        0,
 
692
                        CRS_ANY,
 
693
                        0,
 
694
                        F_Screen,
 
695
                        ParseWmFuncStrArg},
 
696
    {"f.send_msg",      F_CONTEXT_ROOT,
 
697
                        CRS_ANY,
 
698
                        0,
 
699
                        F_Send_Msg,
 
700
                        ParseWmFuncNbrArg},
 
701
    {"f.separator",     0,
 
702
                        CRS_MENU,
 
703
                        0,
 
704
                        F_Separator,
 
705
                        ParseWmFuncNoArg},
 
706
    {"f.set_behavior",  0,
 
707
                        CRS_ANY,
 
708
                        0,
 
709
                        F_Set_Behavior,
 
710
                        ParseWmFuncNoArg},
 
711
#ifdef WSM
 
712
    {"f.set_context",   0,
 
713
                        CRS_ANY,
 
714
                        0,
 
715
                        F_Set_Context,
 
716
                        ParseWmFuncNbrArg},
 
717
#endif /* WSM */
 
718
    {"f.title",         0,
 
719
                        CRS_MENU,
 
720
                        0,
 
721
                        F_Title,
 
722
                        ParseWmFuncNoArg},
 
723
#if defined(PANELIST)
 
724
    {"f.toggle_frontpanel", 0,
 
725
                        CRS_ANY,
 
726
                        0,
 
727
                        F_Toggle_Front_Panel,
 
728
                        ParseWmFuncNoArg},
 
729
 
 
730
    {"f.version",       0,
 
731
                        CRS_ANY,
 
732
                        0,
 
733
                        F_Version,
 
734
                        ParseWmFuncNoArg},
 
735
#endif /* PANELIST */
 
736
#ifdef WSM
 
737
 
 
738
#ifdef OLD
 
739
    {"f.workspace_presence",F_CONTEXT_ICON|F_CONTEXT_ROOT|F_CONTEXT_ICONBOX|
 
740
                            F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
 
741
#endif /* OLD */
 
742
    {"f.workspace_presence", F_CONTEXT_ROOT|F_CONTEXT_ICONBOX|
 
743
                        F_SUBCONTEXT_IB_WICON,
 
744
                        CRS_ANY,
 
745
                        DtWM_FUNC_OCCUPY_WS,
 
746
                        F_Workspace_Presence,
 
747
                        ParseWmFuncNoArg},
 
748
#endif /* WSM */
 
749
#if defined(DEBUG) && defined(WSM)
 
750
    {"f.zz_debug",      0,
 
751
                        CRS_ANY,
 
752
                        0,
 
753
                        F_ZZ_Debug,
 
754
                        ParseWmFuncStrArg},
 
755
#endif /* DEBUG */
 
756
};
 
757
 
 
758
/*
 
759
 * NOTE: New functions MUST be added in ALPHABETICAL order.  A binary search
 
760
 *       is used to find the correct function name.
 
761
 */
 
762
 
 
763
#define WMFUNCTIONTABLESIZE (sizeof(functionTable)/sizeof(functionTable[0]))
 
764
 
 
765
/*
 
766
 * Be sure to update these define, whenever adding/deleting a function.
 
767
 */
 
768
#ifdef WSM
 
769
# if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
770
#  define F_CCI_INDEX  2
 
771
# endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
772
int F_ACTION_INDEX;
 
773
int F_EXEC_INDEX;
 
774
int F_NOP_INDEX;
 
775
#else  /* WSM */
 
776
# if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
777
#  define F_CCI_INDEX  1
 
778
#  define F_EXEC_INDEX 4
 
779
#  define F_NOP_INDEX 16
 
780
# else
 
781
#  define F_EXEC_INDEX 3
 
782
#  define F_NOP_INDEX 14
 
783
# endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
784
#endif /* WSM */
 
785
#ifdef WSM
 
786
 
 
787
/******************************<->*************************************
 
788
 *
 
789
 *  void GetFunctionTableValues (int *execIndex, int *nopIndex, 
 
790
 *                               int *actionIndex)
 
791
 *
 
792
 *  Description:
 
793
 *  -----------
 
794
 *  This routine dynamically computes the size of the functionTable[],
 
795
 *  and the indices for key functions, such as f.exec, f.action, and
 
796
 *  f.nop
 
797
 *
 
798
 *  Inputs:
 
799
 *  ------
 
800
 *  We are setting the values of F_EXEC_INDEX, F_ACTION_INDEX, 
 
801
 *  and F_NOP_INDEX on a global level.  The addresses
 
802
 *  for same are passed in.
 
803
 * 
 
804
 *  Outputs:
 
805
 *  -------
 
806
 *
 
807
 *  Comments:
 
808
 *  --------
 
809
 *  This routine calls smaller routines for efficiency sake.
 
810
 *
 
811
 ******************************<->***********************************/
 
812
void
 
813
GetFunctionTableValues (int *execIndex, int *nopIndex,
 
814
                    int *actionIndex)
 
815
{
 
816
 
 
817
        GetExecIndex (WMFUNCTIONTABLESIZE, execIndex);
 
818
 
 
819
        GetActionIndex (WMFUNCTIONTABLESIZE, actionIndex);
 
820
 
 
821
        GetNopIndex (WMFUNCTIONTABLESIZE, nopIndex);
 
822
 
 
823
} /* END OF FUNCTION GetFunctionTableValues */
 
824
 
 
825
 
 
826
 
 
827
/******************************<->*************************************
 
828
 *
 
829
 
 
830
 *
 
831
 *  Description:
 
832
 *  -----------
 
833
 
 
834
 *
 
835
 *  Inputs:
 
836
 *  ------
 
837
 
 
838
 *  Outputs:
 
839
 *  -------
 
840
 *
 
841
 *  Comments:
 
842
 *  --------
 
843
 *
 
844
 ******************************<->***********************************/
 
845
 
 
846
void
 
847
GetExecIndex (int tableSize, int *execIndex)
 
848
{
 
849
        int i;
 
850
 
 
851
        for (i = 0; i < (tableSize); i++)
 
852
        {
 
853
                if (!(strcmp ("f.exec", functionTable[i].funcName)))
 
854
                {
 
855
                        *execIndex = i;
 
856
                        return;
 
857
                }
 
858
                else
 
859
                {
 
860
                        *execIndex = 0;
 
861
                }
 
862
        }
 
863
} /* END OF FUNCTION GetExecIndex */
 
864
 
 
865
 
 
866
/******************************<->*************************************
 
867
 *
 
868
 
 
869
 *
 
870
 *  Description:
 
871
 *  -----------
 
872
 
 
873
 *
 
874
 *  Inputs:
 
875
 *  ------
 
876
 
 
877
 *  Outputs:
 
878
 *  -------
 
879
 *
 
880
 *  Comments:
 
881
 *  --------
 
882
 *
 
883
 ******************************<->***********************************/
 
884
 
 
885
 
 
886
void
 
887
GetActionIndex (int tableSize, int *actionIndex)
 
888
{
 
889
        int i;
 
890
 
 
891
        for (i = 0; i < (tableSize); i++)
 
892
        {
 
893
                if (!(strcmp ("f.action", functionTable[i].funcName)))
 
894
                {
 
895
                        *actionIndex = i;
 
896
                        return;
 
897
                }
 
898
                else
 
899
                {
 
900
                        *actionIndex = 0;
 
901
                }
 
902
        }
 
903
} /* END OF FUNCTION GetActionIndex */
 
904
 
 
905
 
 
906
 
 
907
/******************************<->*************************************
 
908
 *
 
909
 
 
910
 * 
 
911
 *  Description:
 
912
 *  -----------
 
913
 
 
914
 *
 
915
 *  Inputs:
 
916
 *  ------
 
917
 
 
918
 *  Outputs:
 
919
 *  -------
 
920
 *
 
921
 *  Comments:
 
922
 *  --------
 
923
 *
 
924
 ******************************<->***********************************/
 
925
void
 
926
GetNopIndex (int tableSize, int *nopIndex)
 
927
{
 
928
        int i;
 
929
 
 
930
        for (i = 0; i < (tableSize); i++)
 
931
        {
 
932
                if (!(strcmp ("f.nop", functionTable[i].funcName)))
 
933
                {
 
934
                        *nopIndex = i;
 
935
                        return;
 
936
                }
 
937
                else
 
938
                {
 
939
                        *nopIndex = 0;
 
940
                }
 
941
        }
 
942
} /* END OF FUNCTION GetNopIndex */
 
943
 
 
944
 
 
945
 
 
946
 
 
947
/*************************************<->*************************************
 
948
 *
 
949
 *  void
 
950
 *  WmDtGetHelpArgs ()
 
951
 *
 
952
 *
 
953
 *  Description:
 
954
 *  -----------
 
955
 *  Get Help Args
 
956
 
 
957
 *
 
958
 *  Inputs:
 
959
 *  ------
 
960
 
 
961
 * 
 
962
 *  Outputs:
 
963
 *  -------
 
964
 *
 
965
 *
 
966
 *  Comments:
 
967
 *  --------
 
968
 *  None.
 
969
 * 
 
970
 *************************************<->***********************************/
 
971
void
 
972
WmDtGetHelpArgs(char *args, 
 
973
                 unsigned char* volume, 
 
974
                 unsigned char* topic, 
 
975
                 int *argsCount)
 
976
{
 
977
    unsigned char *string;
 
978
    unsigned char *lineP;
 
979
 
 
980
    cfileP = NULL;
 
981
    linec = 0;
 
982
    parseP = (unsigned char*) args;
 
983
 
 
984
    if(GetNextLine () != NULL)
 
985
    {
 
986
        *argsCount = 0;
 
987
        lineP = line;
 
988
        if ((string = GetSmartSMString (&lineP)) != NULL)
 
989
        {
 
990
            *argsCount = *argsCount + 1;
 
991
            strcpy ((char*)topic, (char*)string);
 
992
        }
 
993
 
 
994
        if ((string = GetSmartSMString (&lineP)) != NULL)
 
995
        {
 
996
            *argsCount = *argsCount + 1;
 
997
            strcpy ((char*)volume, (char *)string);
 
998
        }
 
999
    }
 
1000
 
 
1001
} /* END OF FUNCTION WmDtGetHelpArgs */
 
1002
 
 
1003
 
 
1004
 
 
1005
 
 
1006
 
 
1007
/******************************<->*************************************
 
1008
 *
 
1009
 *  void
 
1010
 *  ParseDtSessionHints (pSD, property)
 
1011
 *
 
1012
 *
 
1013
 *  Description:
 
1014
 *  -----------
 
1015
 *  This function parses a DtSessionHints string and returns a list of 
 
1016
 *  DtSessionItems array.  The string should have the syntax:
 
1017
 *
 
1018
 
 
1019
 *
 
1020
 *
 
1021
 *  Inputs:
 
1022
 *  ------
 
1023
 *  line = (global) line buffer
 
1024
 *  pSD->rootWindow = default root window of display
 
1025
 *
 
1026
 * 
 
1027
 *  Outputs:
 
1028
 *  -------
 
1029
 *  Return = 
 
1030
 *
 
1031
 *
 
1032
 *  Comments:
 
1033
 *  --------
 
1034
 *  None.
 
1035
 * 
 
1036
 *************************************<->***********************************/
 
1037
 
 
1038
void 
 
1039
ParseDtSessionHints (WmScreenData *pSD, unsigned char *property)
 
1040
{
 
1041
 
 
1042
    cfileP = NULL;
 
1043
    linec = 0;
 
1044
    parseP = property;
 
1045
 
 
1046
    ParseSessionItems (pSD);
 
1047
 
 
1048
} /* END OF FUNCTION ParseDtSessionHints */
 
1049
 
 
1050
 
 
1051
/*************************************<->*************************************
 
1052
 *
 
1053
 *  FindDtSessionMatch(commandArgc, commandArgv, pCD, pSD, pWorkSpaceList,
 
1054
 *                      clientMachine)
 
1055
 *
 
1056
 *  Description:
 
1057
 *  -----------
 
1058
 *  Try to find a match for this client in the session hints.
 
1059
 *  Set up client-session data.
 
1060
 *
 
1061
 *
 
1062
 *  Inputs:
 
1063
 *  ------
 
1064
 *  commandArgc    -  argument count
 
1065
 *  commandArgv    -  WM_COMMAND argument vector
 
1066
 *  pCD            -  pointer to client data
 
1067
 *  pSD            -  pointer to screen data
 
1068
 *  pWorkspaceList -  pointer to a list of workspaces (to be returned)
 
1069
 *  clientMachine  -  string for -host option in session hints
 
1070
 *
 
1071
 *  Outputs:
 
1072
 *  -------
 
1073
 *  *pCD            -  client data (may be modified)
 
1074
 *  FindDtSessionMatch - returns True if a match for this client
 
1075
 *                        was found in the session hints.
 
1076
 *  *pWorkspaceList - list of workspaces this client should be put 
 
1077
 *                    into.  (needs to be freed)
 
1078
 *
 
1079
 *
 
1080
 *  Comments:
 
1081
 *  --------
 
1082
 *  Various pieces of client state (in pCD) are reset when a match
 
1083
 *     is found.
 
1084
 *
 
1085
 *  The caller must free *pWorkspaceList when done.
 
1086
 * 
 
1087
 *************************************<->***********************************/
 
1088
Boolean FindDtSessionMatch(int commandArgc, char **commandArgv,
 
1089
                            ClientData *pCD, WmScreenData *pSD,
 
1090
                            char **pWorkSpaceList, char *clientMachine)
 
1091
 
 
1092
{
 
1093
    int count, item;
 
1094
    int relCount;
 
1095
    int argNum;
 
1096
    SessionGeom *sessionGeom;
 
1097
 
 
1098
 
 
1099
    for (count = 0; count < pSD->totalSessionItems; count++)
 
1100
    {
 
1101
        if (!pSD->pDtSessionItems[count].processed &&
 
1102
            pSD->pDtSessionItems[count].commandArgc == commandArgc)
 
1103
        {
 
1104
            if ((clientMachine) &&
 
1105
                (pSD->pDtSessionItems[count].clientMachine) &&
 
1106
                (strcmp(clientMachine, 
 
1107
                        pSD->pDtSessionItems[count].clientMachine)))
 
1108
            {
 
1109
                /*
 
1110
                 * This item has clientMachine string but the 
 
1111
                 * clientMachine does not match.
 
1112
                 */
 
1113
                continue;
 
1114
            }
 
1115
            for (argNum = 0; argNum < commandArgc ; argNum++)
 
1116
            {
 
1117
                if(strcmp(commandArgv[argNum],
 
1118
                          pSD->pDtSessionItems[count].commandArgv[argNum]))
 
1119
 
 
1120
                {
 
1121
                    /*
 
1122
                     * One mismatch and we quit looking at this item.
 
1123
                     * Decrement argNum so a mismatch on the last item
 
1124
                     * will not look like a match below when comparing
 
1125
                     * argNum == commandArgc
 
1126
                     */
 
1127
                    argNum--;
 
1128
                    break;
 
1129
                }
 
1130
            }           
 
1131
            if (argNum == commandArgc)
 
1132
            {
 
1133
                /*
 
1134
                 * Made it through all strings so this is a match
 
1135
                 */
 
1136
                
 
1137
                pSD->pDtSessionItems[count].processed = True;
 
1138
                pSD->remainingSessionItems --;
 
1139
                pCD->clientFlags |= SM_LAUNCHED;
 
1140
                
 
1141
                /*
 
1142
                 * Free strings malloc'd for commandArgv for this item 
 
1143
                 */
 
1144
                
 
1145
                for (relCount = 0; relCount < commandArgc; relCount++)
 
1146
                {
 
1147
                    XtFree(pSD->pDtSessionItems[count].commandArgv[relCount]);
 
1148
                }
 
1149
                XtFree((char *)pSD->pDtSessionItems[count].commandArgv);
 
1150
 
 
1151
                if(pSD->pDtSessionItems[count].clientState)
 
1152
                {
 
1153
                    pCD->clientState =
 
1154
                        pSD->pDtSessionItems[count].clientState;
 
1155
                    pCD->clientFlags |= SM_CLIENT_STATE;
 
1156
                }
 
1157
                
 
1158
                if(pSD->pDtSessionItems[count].sessionGeom)
 
1159
                {
 
1160
                    sessionGeom = pSD->pDtSessionItems[count].sessionGeom;
 
1161
                    if (sessionGeom->flags & XValue)
 
1162
                    {
 
1163
                        pCD->clientX = sessionGeom->clientX;
 
1164
                        pCD->clientFlags |= SM_X;
 
1165
                    }
 
1166
                    if (sessionGeom->flags & YValue)
 
1167
                    {
 
1168
                        pCD->clientY = sessionGeom->clientY;
 
1169
                        pCD->clientFlags |= SM_Y;
 
1170
                    }
 
1171
                    if (sessionGeom->flags & WidthValue)
 
1172
                    {
 
1173
                        pCD->clientWidth = sessionGeom->clientWidth;
 
1174
                        pCD->clientFlags |= SM_WIDTH;
 
1175
                    }
 
1176
                    if (sessionGeom->flags & HeightValue)
 
1177
                    {
 
1178
                        pCD->clientHeight = sessionGeom->clientHeight;
 
1179
                        pCD->clientFlags |= SM_HEIGHT;
 
1180
                    }
 
1181
 
 
1182
                    /*
 
1183
                     * Free SessionGeom malloc'd space for this item 
 
1184
                     */
 
1185
                    
 
1186
                    XtFree((char *)pSD->pDtSessionItems[count].sessionGeom); 
 
1187
                }
 
1188
 
 
1189
                if(pSD->pDtSessionItems[count].clientMachine)
 
1190
                {
 
1191
                    /*
 
1192
                     * Free clientMachine malloc'd space for this item 
 
1193
                     */
 
1194
                    
 
1195
                    XtFree((char *)
 
1196
                           pSD->pDtSessionItems[count].clientMachine); 
 
1197
                    pSD->pDtSessionItems[count].clientMachine = NULL;
 
1198
                }
 
1199
                
 
1200
                
 
1201
                if(pSD->pDtSessionItems[count].workspaces)
 
1202
                {
 
1203
                    /*
 
1204
                     * The caller is responsible for freeing this
 
1205
                     * data.
 
1206
                     */
 
1207
                    *pWorkSpaceList = pSD->pDtSessionItems[count].workspaces;
 
1208
                }
 
1209
 
 
1210
 
 
1211
                if(pSD->remainingSessionItems == 0)
 
1212
                {
 
1213
                    /*
 
1214
                     * Free the whole pSD->pDtSessionHints structure 
 
1215
                     */
 
1216
                    XtFree((char *)pSD->pDtSessionItems);
 
1217
                }
 
1218
                
 
1219
                return (True);
 
1220
            }
 
1221
 
 
1222
        } /* not processed and argc's are the same */
 
1223
 
 
1224
    } /* for */
 
1225
    
 
1226
    return (False);
 
1227
    
 
1228
} /* END OF FUNCTION FindDtSessionMatch */
 
1229
 
 
1230
 
 
1231
 
 
1232
 
 
1233
 
 
1234
/*************************************<->*************************************
 
1235
 *
 
1236
 *  void
 
1237
 *  ParseSessionItems (pSD)
 
1238
 *
 
1239
 *
 
1240
 *  Description:
 
1241
 *  -----------
 
1242
 *  Parse session items
 
1243
 
 
1244
 *
 
1245
 *  Inputs:
 
1246
 *  ------
 
1247
 *  pSD    = pointer to screen data
 
1248
 *  cfileP = (global) file pointer to  NULL
 
1249
 *  line   = (global) line buffer
 
1250
 *  linec  = (global) line count
 
1251
 *  parseP = (global) parse string pointer if cfileP == NULL
 
1252
 *  pSD->rootWindow = default root window of display
 
1253
 
 
1254
 * 
 
1255
 *  Outputs:
 
1256
 *  -------
 
1257
 *  linec  = (global) line count incremented
 
1258
 *  parseP = (global) parse string pointer if cfileP == NULL
 
1259
 *
 
1260
 *
 
1261
 *  Comments:
 
1262
 *  --------
 
1263
 *  None.
 
1264
 * 
 
1265
 *************************************<->***********************************/
 
1266
 
 
1267
void
 
1268
ParseSessionItems (WmScreenData *pSD)
 
1269
{
 
1270
    unsigned char *string;
 
1271
    unsigned char *lineP;
 
1272
    int count;
 
1273
 
 
1274
    
 
1275
    /*
 
1276
     * Parse property string
 
1277
     */
 
1278
 
 
1279
    
 
1280
 
 
1281
    if(GetNextLine () != NULL)
 
1282
    {
 
1283
        pSD->totalSessionItems = atoi((char *)line);
 
1284
        pSD->remainingSessionItems = pSD->totalSessionItems;
 
1285
    }
 
1286
    
 
1287
 
 
1288
    if((pSD->totalSessionItems < 1) ||
 
1289
       !GetSessionHintsInfo(pSD, pSD->totalSessionItems))
 
1290
    {
 
1291
        /*
 
1292
         * No items or couldn't allocate space
 
1293
         */
 
1294
        return;
 
1295
    }
 
1296
    
 
1297
    count = 0;
 
1298
 
 
1299
    while ((count < pSD->totalSessionItems) && (GetNextLine () != NULL))
 
1300
    {
 
1301
 
 
1302
        lineP = line;
 
1303
        while ((string = GetSmartSMString (&lineP)) != NULL)
 
1304
        {
 
1305
            if (!strcmp((char *)string, "-geometry"))
 
1306
            {
 
1307
                /*
 
1308
                 * Parse geometry if it is present
 
1309
                 */
 
1310
                string = GetSmartSMString(&lineP);
 
1311
                ParseSessionGeometry (pSD, count, string);
 
1312
            }
 
1313
            
 
1314
            else if (!strcmp((char *)string, "-state"))
 
1315
            {
 
1316
                /*
 
1317
                 * Parse the state if it is present
 
1318
                 */
 
1319
                string = GetSmartSMString(&lineP);
 
1320
                ParseSessionClientState (pSD, count, string);
 
1321
            }
 
1322
 
 
1323
            else if (!strcmp((char *)string, "-workspaces"))        
 
1324
            {
 
1325
                /*
 
1326
                 * Parse the workspaces string if it is present
 
1327
                 */
 
1328
                string = GetSmartSMString(&lineP);
 
1329
                ParseSessionWorkspaces (pSD, count, string);
 
1330
            }       
 
1331
 
 
1332
            else if (!strcmp((char *)string, "-cmd"))       
 
1333
            {
 
1334
                /*
 
1335
                 * Parse the command string if it is present
 
1336
                 */
 
1337
                string = GetSmartSMString(&lineP);
 
1338
                ParseSessionCommand (pSD, count, &string);
 
1339
            }
 
1340
            
 
1341
            else if (!strcmp((char *)string, "-host"))      
 
1342
            {
 
1343
                /*
 
1344
                 * Parse the host string if it is present
 
1345
                 */
 
1346
                string = GetSmartSMString(&lineP);
 
1347
                ParseSessionHost (pSD, count, string);
 
1348
            }
 
1349
            
 
1350
        } /* while GetSmartSMString */
 
1351
        
 
1352
        count++;
 
1353
 
 
1354
    } /* while GetNextLine */
 
1355
    
 
1356
 
 
1357
 
 
1358
} /* END OF FUNCTION ParseSessionItems */
 
1359
 
 
1360
 
 
1361
 
 
1362
/*************************************<->*************************************
 
1363
 *
 
1364
 *  ParseSessionClientState (pSD, count, string);
 
1365
 *
 
1366
 *  Description:
 
1367
 *  -----------
 
1368
 *  Inputs:
 
1369
 *  ------
 
1370
 *  Outputs:
 
1371
 *  -------
 
1372
 *  Comments:
 
1373
 *  --------
 
1374
 *
 
1375
 *************************************<->***********************************/
 
1376
void ParseSessionClientState (WmScreenData *pSD, int count,
 
1377
                              unsigned char *string)
 
1378
 
 
1379
 
 
1380
 
 
1381
{
 
1382
 
 
1383
    if(!strcmp((char *)string, "NormalState"))
 
1384
    {
 
1385
        pSD->pDtSessionItems[count].clientState = NORMAL_STATE;
 
1386
    }
 
1387
    else if(!strcmp((char *)string, "IconicState"))
 
1388
    {
 
1389
        pSD->pDtSessionItems[count].clientState = MINIMIZED_STATE;
 
1390
    }
 
1391
    
 
1392
 
 
1393
} /* END OF FUNCTION ParseSessionClientState */
 
1394
 
 
1395
 
 
1396
/*************************************<->*************************************
 
1397
 *
 
1398
 *  ParseSessionGeometry (pSD, count, string)
 
1399
 *
 
1400
 *  Description:
 
1401
 *  -----------
 
1402
 *  Inputs:
 
1403
 *  ------
 
1404
 *  Outputs:
 
1405
 *  -------
 
1406
 *  Comments:
 
1407
 *  --------
 
1408
 *
 
1409
 *************************************<->***********************************/
 
1410
void ParseSessionGeometry (WmScreenData *pSD, int count,
 
1411
                           unsigned char *string)
 
1412
 
 
1413
{
 
1414
    SessionGeom *pTmpSessionGeom;
 
1415
    int mask /* = 0 */;
 
1416
    int X, Y, width, height;
 
1417
    X = Y = width = height = 0;
 
1418
    
 
1419
    /*
 
1420
     *  XParseGeometry
 
1421
     */
 
1422
 
 
1423
    mask = XParseGeometry((char *)string, &X, &Y, (unsigned int *)&width, 
 
1424
                          (unsigned int *)&height);
 
1425
    if (mask)
 
1426
    {
 
1427
        /*
 
1428
         * Allocate space for the geometry structure
 
1429
         */
 
1430
 
 
1431
        if ((pTmpSessionGeom = 
 
1432
             (SessionGeom *)XtMalloc (sizeof (SessionGeom))) == NULL)
 
1433
        {
 
1434
            Warning (((char *)GETMESSAGE(60, 1, "Insufficient memory for session geometry item")));
 
1435
            return;
 
1436
 
 
1437
        }
 
1438
 
 
1439
        pTmpSessionGeom->flags = mask;
 
1440
        pTmpSessionGeom->clientX = X;
 
1441
        pTmpSessionGeom->clientY = Y;
 
1442
        pTmpSessionGeom->clientWidth = width;
 
1443
        pTmpSessionGeom->clientHeight = height;
 
1444
 
 
1445
        pSD->pDtSessionItems[count].sessionGeom = pTmpSessionGeom;
 
1446
    }
 
1447
    
 
1448
} /* END OF FUNCTION  ParseSessionGeometry */
 
1449
 
 
1450
 
 
1451
/*************************************<->*************************************
 
1452
 *
 
1453
 * void
 
1454
 * ParseSessionWorkspaces (pSD, count, string)
 
1455
 *
 
1456
 *  Description:
 
1457
 *  -----------
 
1458
 *  Inputs:
 
1459
 *  ------
 
1460
 *  Outputs:
 
1461
 *  -------
 
1462
 *  Comments:
 
1463
 *  --------
 
1464
 *
 
1465
 *************************************<->***********************************/
 
1466
void ParseSessionWorkspaces (WmScreenData *pSD,  int count,
 
1467
                             unsigned char *string)
 
1468
 
 
1469
{
 
1470
 
 
1471
    /*
 
1472
     * Allocate space for the workspaces string
 
1473
     */
 
1474
 
 
1475
    if ((pSD->pDtSessionItems[count].workspaces =
 
1476
         (String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) == NULL)
 
1477
    {
 
1478
        Warning (((char *)GETMESSAGE(60, 2, "Insufficient memory for workspaces list in sesssion item")));
 
1479
        return;
 
1480
 
 
1481
    }
 
1482
 
 
1483
    strcpy(pSD->pDtSessionItems[count].workspaces, (char *)string);
 
1484
    
 
1485
} /* END OF FUNCTION ParseSessionWorkspaces */
 
1486
 
 
1487
 
 
1488
 
 
1489
/*************************************<->*************************************
 
1490
 *
 
1491
 * void
 
1492
 * ParseSessionCommand (pSD, count, string)
 
1493
 *
 
1494
 *  Description:
 
1495
 *  -----------
 
1496
 *  Inputs:
 
1497
 *  ------
 
1498
 *  Outputs:
 
1499
 *  -------
 
1500
 *  Comments:
 
1501
 *  --------
 
1502
 *
 
1503
 *************************************<->***********************************/
 
1504
void ParseSessionCommand (WmScreenData *pSD,  int count,
 
1505
                          unsigned char **commandString)
 
1506
{
 
1507
#define ARG_AMT 100
 
1508
    int xindex;
 
1509
    unsigned char **argv;
 
1510
    int  argc = 0;
 
1511
    int  iSizeArgv;
 
1512
    
 
1513
    unsigned char *string;
 
1514
    
 
1515
    argv = (unsigned char **) XtMalloc (ARG_AMT * sizeof(char *));
 
1516
    iSizeArgv = ARG_AMT;
 
1517
    
 
1518
    while ((string = GetSmartSMString (commandString)) != NULL)
 
1519
    {
 
1520
        /*
 
1521
         * Get pointers to strings in command line and count them
 
1522
         */
 
1523
        argv[argc] = string;
 
1524
        argc ++;
 
1525
 
 
1526
        if (argc >= iSizeArgv)
 
1527
        {
 
1528
            iSizeArgv += ARG_AMT;
 
1529
            argv = (unsigned char **) 
 
1530
                   XtRealloc ((char *)argv, (iSizeArgv * sizeof(char *)));
 
1531
        }
 
1532
    }
 
1533
    if ((pSD->pDtSessionItems[count].commandArgv =
 
1534
         (char **)XtMalloc ((argc) * sizeof(char * ))) == NULL)
 
1535
    {
 
1536
        /*
 
1537
         * Allocate space for saved argv
 
1538
         */
 
1539
        
 
1540
        Warning (((char *)GETMESSAGE(60, 3, "Insufficient memory for commandArgv array")));
 
1541
    }
 
1542
    else
 
1543
    {
 
1544
        pSD->pDtSessionItems[count].commandArgc = argc;
 
1545
        for (xindex = 0; xindex < argc ; xindex++)
 
1546
        {
 
1547
            if ((pSD->pDtSessionItems[count].commandArgv[xindex] =
 
1548
                 (String) XtMalloc
 
1549
                 ((unsigned int) (strlen((char *)argv[xindex]) + 1))) == NULL)
 
1550
            {
 
1551
                /*
 
1552
                 * Allocate space for the next command segment.
 
1553
                 */
 
1554
                Warning (((char *)GETMESSAGE(60, 4, "Insufficient memory for commandArgv item")));
 
1555
            }
 
1556
            else
 
1557
            {
 
1558
                strcpy(pSD->pDtSessionItems[count].commandArgv[xindex],
 
1559
                       (char *)argv[xindex]);
 
1560
            }
 
1561
        }
 
1562
    }
 
1563
 
 
1564
    XtFree ((char *) argv);
 
1565
    
 
1566
} /* END OF FUNCTION ParseSessionCommand */
 
1567
 
 
1568
 
 
1569
 
 
1570
/*************************************<->*************************************
 
1571
 *
 
1572
 * void
 
1573
 * ParseSessionHost (pSD, count, string)
 
1574
 *
 
1575
 *  Description:
 
1576
 *  -----------
 
1577
 *  Inputs:
 
1578
 *  ------
 
1579
 *  Outputs:
 
1580
 *  -------
 
1581
 *  Comments:
 
1582
 *  --------
 
1583
 *
 
1584
 *************************************<->***********************************/
 
1585
void ParseSessionHost (WmScreenData *pSD,  int count,
 
1586
                             unsigned char *string)
 
1587
 
 
1588
{
 
1589
 
 
1590
    /*
 
1591
     * Allocate space for the workspaces string
 
1592
     */
 
1593
 
 
1594
    if ((pSD->pDtSessionItems[count].clientMachine =
 
1595
         (String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) == 
 
1596
        NULL)
 
1597
    {
 
1598
        Warning (((char *)GETMESSAGE(60, 38, 
 
1599
                "Insufficient memory for host name in sesssion item")));
 
1600
        return;
 
1601
    }
 
1602
 
 
1603
    strcpy(pSD->pDtSessionItems[count].clientMachine, (char *)string);
 
1604
    
 
1605
} /* END OF FUNCTION ParseSessionHost */
 
1606
 
 
1607
 
 
1608
 
 
1609
/*************************************<->*************************************
 
1610
 *
 
1611
 *  GetSessionHintsInfo (pSD, numItems)
 
1612
 *
 
1613
 *  Description:
 
1614
 *  -----------
 
1615
 *  Inputs:
 
1616
 *  ------
 
1617
 *  Outputs:
 
1618
 *  -------
 
1619
 *  Comments:
 
1620
 *  --------
 
1621
 *
 
1622
 *************************************<->***********************************/
 
1623
Boolean GetSessionHintsInfo (WmScreenData *pSD, long numItems)
 
1624
 
 
1625
{
 
1626
   
 
1627
    if ((pSD->pDtSessionItems =
 
1628
         (DtSessionItem *)XtMalloc (numItems * sizeof (DtSessionItem)))
 
1629
        == NULL)
 
1630
    {
 
1631
        Warning (((char *)GETMESSAGE(60, 5, "Insufficient memory for Dt Session Hints")));
 
1632
        return(False);
 
1633
    }
 
1634
    
 
1635
    memset ((char *)pSD->pDtSessionItems, NULL,
 
1636
            numItems * sizeof (DtSessionItem));
 
1637
 
 
1638
    return(True);
 
1639
    
 
1640
    
 
1641
} /* END OF FUNCTION  GetSessionHintsInfo  */ 
 
1642
 
 
1643
 
 
1644
 
 
1645
 
 
1646
/*************************************<->*************************************
 
1647
 *
 
1648
 *  PeekAhead (currentChar, currentLev)
 
1649
 *
 
1650
 *
 
1651
 *  Description:
 
1652
 *  -----------
 
1653
 *  Returns a new level value if this is a new nesting level of quoted string
 
1654
 *  Otherwise it returns a zero
 
1655
 *
 
1656
 *
 
1657
 *  Inputs:
 
1658
 *  ------
 
1659
 *  currentChar = current position in the string
 
1660
 *  currentLev = current level of nesting
 
1661
 *
 
1662
 * 
 
1663
 *  Outputs:
 
1664
 *  -------
 
1665
 *  Returns either a new level of nesting or zero if the character is copied in
 
1666
 *
 
1667
 *
 
1668
 *  Comments:
 
1669
 *  --------
 
1670
 * 
 
1671
 *************************************<->***********************************/
 
1672
unsigned int PeekAhead(unsigned char *currentChar,
 
1673
                       unsigned int currentLev)
 
1674
 
 
1675
 
 
1676
{
 
1677
    Boolean             done = False;
 
1678
    unsigned int        tmpLev = 1;
 
1679
#ifndef NO_MULTIBYTE
 
1680
    unsigned int        chlen;
 
1681
 
 
1682
    while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
 
1683
           (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
 
1684
           && (done == False))
 
1685
    {
 
1686
        currentChar++;
 
1687
 
 
1688
        if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
 
1689
           ((*currentChar == '"') || (*currentChar == '\\')))
 
1690
        {
 
1691
            tmpLev++;
 
1692
            if(*currentChar == '"')
 
1693
            {
 
1694
                done = True;
 
1695
            }
 
1696
            else
 
1697
            {
 
1698
                currentChar++;
 
1699
            }
 
1700
        }
 
1701
    }
 
1702
#else
 
1703
    while((*currentChar != NULL) && (done == False) &&
 
1704
          ((*currentChar == '"') || (*currentChar == '\\')))
 
1705
    {
 
1706
        currentChar++;
 
1707
        if((*currentChar != NULL) &&
 
1708
           ((*currentChar == '"') || (*currentChar == '\\')))
 
1709
        {
 
1710
            tmpLev++;
 
1711
            if(*currentChar == '"')
 
1712
            {
 
1713
                done = True;
 
1714
            }
 
1715
            else
 
1716
            {
 
1717
                currentChar++;
 
1718
            }
 
1719
        }
 
1720
    }
 
1721
#endif /*NO_MULTIBYTE*/
 
1722
 
 
1723
    /*
 
1724
     * Figure out if this is truly a new level of nesting - else ignore it
 
1725
     * This section probably could do some error checking and return -1
 
1726
         * If so, change type of routine from unsigned int to int
 
1727
     */
 
1728
    if(done == True)
 
1729
    {
 
1730
        return(tmpLev);
 
1731
    }
 
1732
    else
 
1733
    {
 
1734
        return(0);
 
1735
    }
 
1736
} /* END OF FUNCTION PeekAhead */
 
1737
    
 
1738
    
 
1739
#endif /* WSM */
 
1740
 
 
1741
 
 
1742
 
 
1743
#ifdef MOTIF_ONE_DOT_ONE
 
1744
/*************************************<->*************************************
 
1745
 *
 
1746
 *  GetHomeDirName (fileName)
 
1747
 *
 
1748
 *  Description:
 
1749
 *  -----------
 
1750
 *  This function finds the "HOME" directory
 
1751
 *
 
1752
 *
 
1753
 *  Inputs:
 
1754
 *  ------
 
1755
 *  fileName 
 
1756
 *
 
1757
 *  Outputs:
 
1758
 *  -------
 
1759
 *  fileName
 
1760
 *
 
1761
 *  Comments:
 
1762
 *  --------
 
1763
 * 
 
1764
 *************************************<->***********************************/
 
1765
void GetHomeDirName(String  fileName)
 
1766
{
 
1767
        int uid;
 
1768
        struct passwd *pw;
 
1769
        char *ptr = NULL;
 
1770
 
 
1771
        if((ptr = getenv("HOME")) == NULL)
 
1772
        {
 
1773
            if((ptr = getenv("USER")) != NULL)
 
1774
            {
 
1775
                pw = getpwnam(ptr);
 
1776
            }
 
1777
            else
 
1778
            {
 
1779
                uid = getuid();
 
1780
                pw = getpwuid(uid);
 
1781
            }
 
1782
 
 
1783
            if (pw)
 
1784
            {
 
1785
                ptr = pw->pw_dir;
 
1786
            }
 
1787
            else
 
1788
            {
 
1789
                ptr = "";
 
1790
            }
 
1791
        }
 
1792
        strcpy(fileName, ptr);
 
1793
}
 
1794
#endif
 
1795
 
 
1796
 
 
1797
/*************************************<->*************************************
 
1798
 *
 
1799
 *  SyncModifierStrings (fileName)
 
1800
 *
 
1801
 *  Description:
 
1802
 *  -----------
 
1803
 *  This function updates modifierStrings table so that Mwm uses the correct
 
1804
 *  modifier to keysym mapping.  Specifically, fix up the Alt and Meta bindings.
 
1805
 *
 
1806
 *  Inputs:
 
1807
 *  ------
 
1808
 *  fileName 
 
1809
 *
 
1810
 *  Outputs:
 
1811
 *  -------
 
1812
 *  fileName
 
1813
 *
 
1814
 *  Comments:
 
1815
 *  --------
 
1816
 * 
 
1817
 *************************************<->***********************************/
 
1818
void SyncModifierStrings(void)
 
1819
{
 
1820
    XModifierKeymap *map;
 
1821
    int i, j, k = 0;
 
1822
 
 
1823
    map = XGetModifierMapping (DISPLAY);
 
1824
 
 
1825
    for (i = 0; i < 8; i++)
 
1826
    {
 
1827
        for (j = 0; j < map->max_keypermod; j++)
 
1828
        {
 
1829
            if (map->modifiermap[k])
 
1830
            {
 
1831
                KeySym ks = XKeycodeToKeysym(DISPLAY, map->modifiermap[k], 0);
 
1832
                char *nm = XKeysymToString(ks);
 
1833
 
 
1834
                /* Compare, ignoring the trailing '_L' or '_R' in keysym */
 
1835
                if (nm && !strncmp("Alt", nm, 3))
 
1836
                {
 
1837
                    modifierStrings[ALT_INDEX].mask = (1<<i);
 
1838
                }
 
1839
                else if (nm && !strncmp("Meta", nm, 4))
 
1840
                {
 
1841
                    modifierStrings[META_INDEX].mask = (1<<i);
 
1842
                }
 
1843
            }
 
1844
            k++;
 
1845
        }
 
1846
    }
 
1847
 
 
1848
    XFreeModifiermap(map);
 
1849
}
 
1850
 
 
1851
 
 
1852
 
 
1853
/*************************************<->*************************************
 
1854
 *
 
1855
 *  ProcessWmFile ()
 
1856
 *
 
1857
 *
 
1858
 *  Description:
 
1859
 *  -----------
 
1860
 *  This function reads the mwm resource description file and processes the
 
1861
 *  resources that are described.
 
1862
 *
 
1863
 *
 
1864
 *  Inputs:
 
1865
 *  ------
 
1866
 *  wmGD.bitmapDirectory = bitmapDirectory resource value
 
1867
 *  pSD->buttonBindings = buttonBindings resource value
 
1868
 *  wmGD.configFile = configuration file resource value
 
1869
 *  pSD->keyBindings = keyBindings resource value
 
1870
 *  wmGD.rootWindow = default root window of display
 
1871
 *  HOME = environment variable for home directory
 
1872
 *  functionTable = window manager function parse table
 
1873
 *
 
1874
 * 
 
1875
 *  Outputs:
 
1876
 *  -------
 
1877
 *  wmGD.buttonSpecs = list of button binding specifications
 
1878
 *  wmGD.keySpecs = list of key binding specification
 
1879
 *  wmGD.menuSpecs = list of menu specifications
 
1880
 * *wmGD.acceleratorMenuSpecs = initialized array of (MenuSpec *)
 
1881
 *  wmGD.acceleratorMenuCount = 0
 
1882
 *
 
1883
 *
 
1884
 *  Comments:
 
1885
 *  --------
 
1886
 * If there are more than MAXLINE characters on a line the excess characters
 
1887
 * are truncated.
 
1888
 * 
 
1889
 *************************************<->***********************************/
 
1890
#define MENU_SPEC       "menu"
 
1891
#define BUTTON_SPEC     "buttons"
 
1892
#define KEY_SPEC        "keys"
 
1893
#ifdef PANELIST
 
1894
#define FRONT_PANEL_SPEC DTWM_FP_PANEL_OLD
 
1895
#define DROP_EFFECTS_SPEC   DTWM_FP_DROP_EFFECTS
 
1896
#define PANEL_SPEC      DTWM_FP_PANEL
 
1897
#define BOX_SPEC        DTWM_FP_BOX
 
1898
#define CONTROL_SPEC    DTWM_FP_CONTROL
 
1899
#define INCLUDE_SPEC    DTWM_FP_INCLUDE
 
1900
#define ANIMATION_SPEC  DTWM_FP_ANIMATION
 
1901
#define SWITCH_SPEC     DTWM_FP_SWITCH
 
1902
 
 
1903
void ProcessWmFile (WmScreenData *pSD, Boolean bNested)
 
1904
 
 
1905
#else /* PANELIST */
 
1906
void ProcessWmFile (WmScreenData *pSD)
 
1907
#endif /* PANELIST */
 
1908
{
 
1909
    unsigned char *lineP;
 
1910
    unsigned char *string;
 
1911
    unsigned int   n;
 
1912
    MenuSpec      *menuSpec;
 
1913
#ifdef PANELIST
 
1914
    static Boolean conversionInProgress = False;
 
1915
    Arg args[10];
 
1916
    int argnum;
 
1917
 
 
1918
    if (!bNested)
 
1919
    {
 
1920
#endif /* PANELIST */
 
1921
 
 
1922
    /*
 
1923
     * Initialize global data values that are set based on data in
 
1924
     * the mwm resource description file.
 
1925
     */
 
1926
 
 
1927
    pSD->buttonSpecs = NULL;
 
1928
    pSD->keySpecs = NULL;
 
1929
    pSD->menuSpecs = NULL;
 
1930
 
 
1931
#ifdef WSM
 
1932
    /**** hhhhhhhhhhhh   ******/
 
1933
    GetFunctionTableValues (&F_EXEC_INDEX, &F_NOP_INDEX, &F_ACTION_INDEX);
 
1934
#endif /* WSM */
 
1935
    /*
 
1936
     * Find and parse the default system menu string, if it exists.
 
1937
     */
 
1938
 
 
1939
    cfileP = NULL;
 
1940
    linec = 0;
 
1941
    if (((parseP = (unsigned char *) builtinSystemMenu) != NULL) && 
 
1942
         (GetNextLine () != NULL))
 
1943
    {
 
1944
        lineP = line;
 
1945
        ParseMenuSet (pSD, lineP);
 
1946
    }
 
1947
 
 
1948
    linec = 0;
 
1949
    if (((parseP = (unsigned char *) builtinRootMenu) != NULL) && 
 
1950
         (GetNextLine () != NULL))
 
1951
    {
 
1952
        lineP = line;
 
1953
        ParseMenuSet (pSD, lineP);
 
1954
    }
 
1955
#ifdef PANELIST
 
1956
    if (wmGD.useFrontPanel &&  !wmGD.dtSD &&
 
1957
        (XDefaultScreen (wmGD.display) == pSD->screen))
 
1958
    {
 
1959
        wmGD.dtSD = pSD;  /* only one per display */
 
1960
    }
 
1961
#endif /* PANELIST */
 
1962
 
 
1963
    /*
 
1964
     * Find and associate a stream with the window manager resource 
 
1965
     *   description file.
 
1966
     */
 
1967
 
 
1968
    if ((cfileP = FopenConfigFile ()) == NULL)
 
1969
    {
 
1970
        if (!wmGD.useStandardBehavior)
 
1971
          Warning (((char *)GETMESSAGE(60, 6, "Cannot open configuration file")));
 
1972
        return;
 
1973
    }
 
1974
 
 
1975
#ifdef PANELIST 
 
1976
    }  /* end if (!bNested) */
 
1977
#endif /* PANELIST */
 
1978
    /*
 
1979
     * Parse the information in the configuration file.
 
1980
     * If there are more than MAXLINE characters on a line the excess are
 
1981
     *   truncated.
 
1982
     */
 
1983
 
 
1984
    linec = 0;
 
1985
    while ((GetNextLine () != NULL))  /* not EOF nor read error */
 
1986
    {
 
1987
        lineP = line;
 
1988
        if ((*line == '!') || (string = GetString (&lineP)) == NULL)
 
1989
        /* empty or comment line */
 
1990
        {
 
1991
            continue;
 
1992
        }
 
1993
 
 
1994
        ToLower (string);
 
1995
        if (!strcmp ((char *)string, MENU_SPEC))
 
1996
        {
 
1997
            ParseMenuSet (pSD, lineP);
 
1998
        }
 
1999
        else if (!strcmp ((char *) string, BUTTON_SPEC))
 
2000
        {
 
2001
            ParseButtonSet (pSD, lineP);
 
2002
        }
 
2003
        else if (!strcmp ((char *) string, KEY_SPEC))
 
2004
        {
 
2005
            ParseKeySet (pSD, lineP);
 
2006
        }
 
2007
#ifdef PANELIST
 
2008
        else if (!strcmp ((char *)string, INCLUDE_SPEC))
 
2009
        {
 
2010
            ParseIncludeSet (pSD, lineP);
 
2011
        }
 
2012
#endif /* PANELIST */
 
2013
    }
 
2014
 
 
2015
    fclose (cfileP);
 
2016
 
 
2017
    /*
 
2018
     * Create and initialize the pSD->acceleratorMenuSpecs array.
 
2019
     * This assumes we create pointers to MenuSpecs within ProcessWmFile().
 
2020
     * Set pSD->acceleratorMenuCount to 0.
 
2021
     */
 
2022
 
 
2023
    /* count the number of menu specifications */
 
2024
    n = 0;
 
2025
    menuSpec = pSD->menuSpecs;
 
2026
    while (menuSpec)
 
2027
    {
 
2028
        n++;
 
2029
        menuSpec = menuSpec->nextMenuSpec;
 
2030
    }
 
2031
 
 
2032
    /* allocate the array and initialize to zeros */
 
2033
    pSD->acceleratorMenuSpecs = NULL;
 
2034
    if (n)
 
2035
    {
 
2036
        pSD->acceleratorMenuSpecs = 
 
2037
            (MenuSpec **) XtCalloc (n, sizeof (MenuSpec *));
 
2038
        if (pSD->acceleratorMenuSpecs == NULL)
 
2039
        {
 
2040
            Warning (((char *)GETMESSAGE(60, 7, "Insufficient memory for menu accelerators")));
 
2041
        }
 
2042
    }
 
2043
    pSD->acceleratorMenuCount = 0;
 
2044
} /* END OF FUNCTION ProcessWmFile */
 
2045
 
 
2046
/**** This function stolen from Xt/Intrinsic.c ****/
 
2047
/* The implementation of this routine is operating system dependent */
 
2048
 
 
2049
static char *ExtractLocaleName(lang)
 
2050
    String      lang;
 
2051
{
 
2052
 
 
2053
#ifdef hpux      /* hpux-specific parsing of the locale string */
 
2054
#define MAXLOCALE       64      /* buffer size of locale name */
 
2055
 
 
2056
    char           *start;
 
2057
    char           *end;
 
2058
    int             len;
 
2059
    static char     buf[MAXLOCALE];
 
2060
 
 
2061
    /*  If lang has a substring ":<category>;", extract <category>
 
2062
     *  from the first such occurrence as the locale name.
 
2063
     */
 
2064
 
 
2065
    start = lang;
 
2066
    if (start = strchr (lang, ':')) {
 
2067
        start++;
 
2068
        if (end = strchr (start, ';')) {
 
2069
            len = end - start;
 
2070
            strncpy(buf, start, len);
 
2071
            *(buf + len) = '\0';
 
2072
            lang = buf;
 
2073
      }
 
2074
    }
 
2075
#endif  /* hpux */
 
2076
 
 
2077
    return lang;
 
2078
}
 
2079
 
 
2080
#ifdef WSM
 
2081
#define RC_CONFIG_SUBDIR                "/config/"
 
2082
#define RC_DEFAULT_CONFIG_SUBDIR        "/config/C"
 
2083
#endif /* WSM */
 
2084
 
 
2085
/*************************************<->*************************************
 
2086
 *
 
2087
 *  FopenConfigFile ()
 
2088
 *
 
2089
 *
 
2090
 *  Description:
 
2091
 *  -----------
 
2092
 *  This function searches for, opens, and associates a stream with the mwm 
 
2093
 *  resource description file,
 
2094
 *
 
2095
 *
 
2096
 *  Inputs:
 
2097
 *  ------
 
2098
 *  wmGD.configFile = configuration file resource value.
 
2099
 *  HOME = environment variable for home directory
 
2100
 *
 
2101
 *
 
2102
 *  Outputs:
 
2103
 *  -------
 
2104
 *  Return = If successful, a pointer to the FILE structure associated with 
 
2105
 *           the configuration file.  Otherwise, NULL.
 
2106
 *
 
2107
 *
 
2108
 *  Comments:
 
2109
 *  --------
 
2110
 *  None.
 
2111
 * 
 
2112
 *************************************<->***********************************/
 
2113
FILE *FopenConfigFile (void)
 
2114
{
 
2115
 
 
2116
    char    *LANG, *LANGp;
 
2117
    FILE    *fileP;
 
2118
 
 
2119
#ifndef MOTIF_ONE_DOT_ONE
 
2120
    char *homeDir = XmeGetHomeDirName();
 
2121
#endif
 
2122
#ifdef PANELIST
 
2123
    Boolean stackPushed;
 
2124
#endif /* PANELIST */
 
2125
 
 
2126
    /*
 
2127
     * Get the LANG environment variable
 
2128
     * make copy since another call to getenv will blast the value.
 
2129
     */
 
2130
    LANGp = setlocale(LC_CTYPE, NULL);
 
2131
 
 
2132
    /*
 
2133
     * setlocale not guaranteed to return $LANG -- extract
 
2134
     * something usable.
 
2135
     */
 
2136
    LANGp = ExtractLocaleName (LANGp);
 
2137
 
 
2138
    if ((LANGp == NULL) || (strlen(LANGp) == 0))
 
2139
      {
 
2140
         LANG = NULL;
 
2141
      }
 
2142
    else
 
2143
      {
 
2144
         if ((LANG = (char *) XtMalloc(strlen(LANGp) +1)) == NULL)
 
2145
           {
 
2146
              PWarning (((char *)GETMESSAGE(60, 41, "Insufficient memory to get LANG environment variable.")));
 
2147
              return(NULL);
 
2148
           }
 
2149
 
 
2150
         strcpy(LANG, LANGp);
 
2151
      }
 
2152
 
 
2153
 
 
2154
    /*
 
2155
     * To get a name for the file first look at the value of the configFile
 
2156
     * resource.  Interpret "~/.." as relative to the user's home directory.
 
2157
     * Use the LANG variable if set and .mwmrc is in $HOME/$LANG/.mwmrc  
 
2158
     */
 
2159
 
 
2160
#ifdef PANELIST
 
2161
    if (pConfigStackTop && pConfigStackTop->tempName)
 
2162
    {
 
2163
        fileP = fopen (pConfigStackTop->tempName, "r");
 
2164
        return (fileP);
 
2165
    }
 
2166
    stackPushed = (pConfigStackTop && (pConfigStackTop != pConfigStack));
 
2167
    fileP = NULL;
 
2168
    cfileName[0] = '\0';
 
2169
#endif /* PANELIST */
 
2170
    if ((wmGD.configFile != NULL) && (wmGD.configFile[0] != '\0'))
 
2171
    /* pointer to nonNULL string */
 
2172
    {
 
2173
        if ((wmGD.configFile[0] == '~') && (wmGD.configFile[1] == '/'))
 
2174
        /* handle "~/..." */
 
2175
        {
 
2176
#ifdef MOTIF_ONE_DOT_ONE
 
2177
            GetHomeDirName(cfileName);
 
2178
#else
 
2179
            strcpy (cfileName, homeDir);
 
2180
#endif
 
2181
            if (LANG != NULL)
 
2182
            {
 
2183
                strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
 
2184
                strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2185
            }
 
2186
            strncat(cfileName, &(wmGD.configFile[1]), MAXWMPATH-strlen(cfileName));
 
2187
            if ((fileP = fopen (cfileName, "r")) != NULL)
 
2188
            {
 
2189
                if (LANG != NULL) { 
 
2190
                    XtFree(LANG); 
 
2191
                    LANG = NULL; 
 
2192
                }
 
2193
#ifndef PANELIST
 
2194
                return (fileP);
 
2195
#endif /* PANELIST */
 
2196
            }
 
2197
            else
 
2198
            {
 
2199
                /* 
 
2200
                 * Just try $HOME/.mwmrc
 
2201
                 */
 
2202
#ifdef MOTIF_ONE_DOT_ONE
 
2203
                GetHomeDirName(cfileName);
 
2204
#else
 
2205
                strcpy (cfileName, homeDir);
 
2206
#endif
 
2207
                strncat(cfileName, &(wmGD.configFile[1]), 
 
2208
                        MAXWMPATH-strlen(cfileName));
 
2209
                if ((fileP = fopen (cfileName, "r")) != NULL)
 
2210
                {
 
2211
                  if (LANG != NULL) {
 
2212
                      XtFree(LANG);
 
2213
                      LANG = NULL;
 
2214
                  }
 
2215
#ifndef PANELIST
 
2216
                  return (fileP);
 
2217
#endif /* PANELIST */
 
2218
                }
 
2219
            }
 
2220
 
 
2221
            
 
2222
        }
 
2223
        else
 
2224
        /* relative to current directory or absolute */
 
2225
        {
 
2226
#ifdef PANELIST
 
2227
            char *pch;
 
2228
 
 
2229
            pch = (char *) GetNetworkFileName (wmGD.configFile);
 
2230
 
 
2231
            if ((fileP = fopen (pch, "r")) != NULL)
 
2232
            {
 
2233
                strncpy (cfileName, pch, MAXWMPATH);
 
2234
            }
 
2235
            XtFree (pch);
 
2236
  
 
2237
          if ((fileP == NULL) && !stackPushed)
 
2238
          {
 
2239
#endif  /* PANELIST  */
 
2240
            if ((fileP = fopen (wmGD.configFile, "r")) != NULL)
 
2241
              {
 
2242
                if (LANG != NULL) {
 
2243
                    XtFree(LANG);
 
2244
                    LANG = NULL;
 
2245
                }
 
2246
                return(fileP);
 
2247
              }
 
2248
#ifdef PANELIST 
 
2249
          }
 
2250
          else if ((fileP == NULL) && stackPushed)
 
2251
          {
 
2252
                strcpy (cfileName, wmGD.configFile);
 
2253
          }
 
2254
#endif /* PANELIST */
 
2255
        }
 
2256
    }
 
2257
#ifdef PANELIST 
 
2258
  if ((fileP == NULL) && !stackPushed)
 
2259
  {
 
2260
#endif /* PANELIST */
 
2261
 
 
2262
    /*
 
2263
     * The configFile resource didn't do it for us.
 
2264
     * First try HOME_MWMRC, then try SYS_MWMRC .
 
2265
     */
 
2266
 
 
2267
#define HOME_MWMRC "/.mwmrc"
 
2268
#define SLASH_MWMRC "/system.mwmrc"
 
2269
 
 
2270
#ifdef MOTIF_ONE_DOT_ONE
 
2271
    GetHomeDirName(cfileName);
 
2272
#else
 
2273
    strcpy (cfileName, homeDir);
 
2274
#endif
 
2275
 
 
2276
#ifdef WSM
 
2277
    if (MwmBehavior)
 
2278
    {
 
2279
        /*
 
2280
         *
 
2281
         *  Looking for $HOME/$LANG/.mwmrc
 
2282
         *  --or--if $LANG is NULL
 
2283
         *  Looking for $HOME/.mwmrc
 
2284
         *
 
2285
         */
 
2286
        if (LANG != NULL)
 
2287
        {
 
2288
            strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
 
2289
            strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2290
        }
 
2291
        strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
 
2292
    }
 
2293
    else
 
2294
    {
 
2295
        /*
 
2296
         *
 
2297
         *  Looking for $HOME/.dt/$LANG/dtwmrc
 
2298
         *
 
2299
         *  --or--if $LANG is NULL--
 
2300
         *
 
2301
         *  Looking for $HOME/.dt/dtwmrc
 
2302
         *
 
2303
         */
 
2304
        strncat(cfileName, "/.dt/", MAXWMPATH-strlen(cfileName));
 
2305
 
 
2306
        if (LANG != NULL)
 
2307
        {
 
2308
            strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2309
        }
 
2310
        strncat(cfileName, LANG_DT_WMRC, MAXWMPATH - strlen(cfileName));
 
2311
    }
 
2312
#else /* WSM */
 
2313
    if (LANG != NULL)
 
2314
    {
 
2315
        strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
 
2316
        strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2317
    }
 
2318
    strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
 
2319
#endif /* WSM */
 
2320
    if ((fileP = fopen (cfileName, "r")) != NULL)
 
2321
    {
 
2322
        if (LANG != NULL) {
 
2323
            XtFree(LANG);
 
2324
            LANG = NULL;
 
2325
        }
 
2326
#ifndef PANELIST
 
2327
        return (fileP);
 
2328
#endif /* PANELIST */
 
2329
    }
 
2330
    else
 
2331
    {
 
2332
        /* 
 
2333
         * Just try $HOME/.mwmrc
 
2334
         */
 
2335
#ifdef MOTIF_ONE_DOT_ONE
 
2336
        GetHomeDirName(cfileName);
 
2337
#else
 
2338
    strcpy (cfileName, homeDir);
 
2339
#endif
 
2340
#ifdef WSM
 
2341
        if (MwmBehavior)
 
2342
        {
 
2343
            /* 
 
2344
             * Just try $HOME/.mwmrc
 
2345
             */
 
2346
            strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
 
2347
        }
 
2348
        else
 
2349
        {
 
2350
            /* 
 
2351
             * Just try $HOME/.dt/dtwmrc
 
2352
             */
 
2353
            strncat(cfileName, HOME_DT_WMRC, MAXWMPATH - strlen(cfileName));
 
2354
        }
 
2355
#else /* WSM */
 
2356
        strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
 
2357
#endif /* WSM */
 
2358
        if ((fileP = fopen (cfileName, "r")) != NULL)
 
2359
        {
 
2360
          if (LANG != NULL) {
 
2361
              XtFree(LANG);
 
2362
              LANG = NULL;
 
2363
          }
 
2364
#ifndef PANELIST
 
2365
          return (fileP);
 
2366
#endif /* PANELIST */
 
2367
        }
 
2368
    }
 
2369
#ifdef PANELIST
 
2370
  }
 
2371
 
 
2372
#define DTLIBDIR  CDE_INSTALLATION_TOP
 
2373
#define DTADMINDIR  CDE_CONFIGURATION_TOP
 
2374
#define SLASH_DT_WMRC "/sys.dtwmrc"
 
2375
 
 
2376
  if ((fileP == NULL) && !stackPushed)
 
2377
  {
 
2378
    /* 
 
2379
     * No home-based config file. Try the admin directory.
 
2380
     */
 
2381
    strcpy(cfileName, DTADMINDIR);
 
2382
    strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName));
 
2383
    strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2384
    strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
 
2385
 
 
2386
    if (((fileP = fopen (cfileName, "r")) == NULL) && LANG && *LANG)
 
2387
    {
 
2388
        /* Try it with no LANG */
 
2389
        strcpy(cfileName, DTADMINDIR);
 
2390
        strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName));
 
2391
        strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
 
2392
    }
 
2393
 
 
2394
    if ((fileP = fopen (cfileName, "r")) != NULL)
 
2395
    {
 
2396
      XtFree(LANG);
 
2397
      LANG = NULL;
 
2398
    }
 
2399
  }
 
2400
 
 
2401
  if ((fileP == NULL) && !stackPushed)
 
2402
  {
 
2403
#endif /* PANELIST */
 
2404
 
 
2405
#ifndef LIBDIR
 
2406
#define LIBDIR "/usr/lib/X11"
 
2407
#endif
 
2408
    if (LANG != NULL)
 
2409
    {
 
2410
#ifdef WSM
 
2411
        if (MwmBehavior)
 
2412
        {
 
2413
            strcpy(cfileName, LIBDIR);
 
2414
            strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
 
2415
            strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2416
            strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
 
2417
        }
 
2418
        else
 
2419
        {
 
2420
            strcpy(cfileName, DTLIBDIR);
 
2421
            strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName));
 
2422
            strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2423
            strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
 
2424
        }
 
2425
#else /* WSM */
 
2426
       /*
 
2427
        * Try /$LANG/system.mwmrc within the install tree
 
2428
        */
 
2429
        strcpy(cfileName, LIBDIR);
 
2430
        strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
 
2431
        strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
 
2432
        strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
 
2433
#endif /* WSM */
 
2434
        if ((fileP = fopen (cfileName, "r")) != NULL)
 
2435
        {
 
2436
          XtFree(LANG);
 
2437
          LANG = NULL;
 
2438
#ifndef PANELIST
 
2439
          return (fileP);
 
2440
#endif /* PANELIST */
 
2441
        }
 
2442
    }
 
2443
 
 
2444
#ifdef PANELIST
 
2445
    if ((fileP == NULL) && !stackPushed)
 
2446
    {
 
2447
#endif /* PANELIST */
 
2448
#ifdef WSM
 
2449
    if (MwmBehavior)
 
2450
    {
 
2451
        strcpy(cfileName, LIBDIR);
 
2452
        strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
 
2453
#ifdef PANELIST
 
2454
        fileP = fopen (cfileName, "r");
 
2455
#else /* PANELIST */
 
2456
        return (fopen (cfileName, "r"));
 
2457
#endif /* PANELIST */
 
2458
    }
 
2459
    else
 
2460
    {
 
2461
        strcpy(cfileName, DTLIBDIR);
 
2462
        strncat(cfileName, RC_DEFAULT_CONFIG_SUBDIR, 
 
2463
                                        MAXWMPATH - strlen(cfileName));
 
2464
        strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
 
2465
#ifdef PANELIST
 
2466
        fileP = fopen (cfileName, "r");
 
2467
#else /* PANELIST */
 
2468
        return (fopen (cfileName, "r"));
 
2469
#endif /* PANELIST */
 
2470
    }
 
2471
#else /* WSM */
 
2472
    /*
 
2473
     * Try /system.mwmrc within the install tree
 
2474
     */
 
2475
    strcpy(cfileName, LIBDIR);
 
2476
    strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
 
2477
 
 
2478
    if (LANG != NULL) 
 
2479
    {
 
2480
       XtFree(LANG);
 
2481
       LANG = NULL;
 
2482
    }
 
2483
#ifdef PANELIST
 
2484
    strcpy(cfileName, cfileName);
 
2485
    fileP = fopen (cfileName, "r");
 
2486
#else /* PANELIST */
 
2487
    return (fopen (cfileName, "r"));
 
2488
#endif /* PANELIST */
 
2489
#endif /* WSM */
 
2490
#ifdef PANELIST
 
2491
    }
 
2492
  }
 
2493
 
 
2494
    if (!fileP)
 
2495
    {
 
2496
        char *pch;
 
2497
 
 
2498
        /*
 
2499
         * handle "<host>:<path>" form of file name
 
2500
         */
 
2501
        pch = (char *) GetNetworkFileName (cfileName);
 
2502
        if ((fileP = fopen (cfileName, "r")) != NULL)
 
2503
        {
 
2504
            strncpy (cfileName, pch, MAXWMPATH);
 
2505
            XtFree (pch);
 
2506
        }
 
2507
 
 
2508
        /*
 
2509
         * Either not "<host>:<path>" form or there was a
 
2510
         * problem up above. This is the last attempt to 
 
2511
         * open something.
 
2512
         */
 
2513
        if (!fileP)
 
2514
        {
 
2515
            fileP = fopen (cfileName, "r");
 
2516
        }
 
2517
    }
 
2518
 
 
2519
    if (!pConfigStack)
 
2520
    {
 
2521
        ConfigStackInit (cfileName);
 
2522
    }
 
2523
 
 
2524
    if (wmGD.cppCommand && *wmGD.cppCommand)
 
2525
    {
 
2526
        /*
 
2527
         *  Run the file through the C-preprocessor
 
2528
         */
 
2529
        PreprocessConfigFile ();
 
2530
        if (pConfigStackTop->cppName)
 
2531
        {
 
2532
            /* open the result */
 
2533
            fileP = fopen (pConfigStackTop->cppName, "r");
 
2534
        }
 
2535
    }
 
2536
 
 
2537
    if (LANG != NULL) 
 
2538
    {
 
2539
        XtFree(LANG);
 
2540
        LANG = NULL;
 
2541
    }
 
2542
    return (fileP);
 
2543
#endif /* PANELIST */
 
2544
 
 
2545
} /* END OF FUNCTION FopenConfigFile */
 
2546
 
 
2547
 
 
2548
/*************************************<->*************************************
 
2549
 *
 
2550
 *  SaveMenuAccelerators (pSD, newMenuSpec)
 
2551
 *
 
2552
 *
 
2553
 *  Description:
 
2554
 *  -----------
 
2555
 *  This function saves the MenuSpec pointer in pSD->acceleratorMenuSpecs.
 
2556
 *
 
2557
 *
 
2558
 *  Inputs:
 
2559
 *  ------
 
2560
 *  newMenuSpec = pointer to MenuSpec to be saved.
 
2561
 *  pSD->acceleratorMenuSpecs = 
 
2562
 *  pSD->acceleratorMenuCount = 
 
2563
 *
 
2564
 *
 
2565
 *  Outputs:
 
2566
 *  -------
 
2567
 *  pSD->acceleratorMenuSpecs = possibly updated
 
2568
 *  pSD->acceleratorMenuCount = possibly updated
 
2569
 *
 
2570
 *
 
2571
 *  Comments:
 
2572
 *  --------
 
2573
 *  We assume only MenuSpecs created within ProcessWmFile() are to be saved.
 
2574
 *  Otherwise, we may cause override the limits of pSD->acceleratorMenuSpecs.
 
2575
 * 
 
2576
 *************************************<->***********************************/
 
2577
 
 
2578
void SaveMenuAccelerators (WmScreenData *pSD, MenuSpec *newMenuSpec)
 
2579
{
 
2580
    MenuSpec  **pMenuSpec;
 
2581
 
 
2582
    pMenuSpec = pSD->acceleratorMenuSpecs;
 
2583
 
 
2584
    if (pMenuSpec == NULL) 
 
2585
        return;
 
2586
 
 
2587
    while ((*pMenuSpec != NULL) && (*pMenuSpec != newMenuSpec))
 
2588
    {
 
2589
        pMenuSpec++;
 
2590
    }
 
2591
 
 
2592
    if (*pMenuSpec == NULL)
 
2593
    {
 
2594
        *pMenuSpec = newMenuSpec;
 
2595
        pSD->acceleratorMenuCount++;
 
2596
    }
 
2597
 
 
2598
} /* END OF FUNCTION SaveMenuAccelerators */
 
2599
 
 
2600
 
 
2601
/*************************************<->*************************************
 
2602
 *
 
2603
 *  ParseMenuSet (pSD, lineP)
 
2604
 *
 
2605
 *
 
2606
 *  Description:
 
2607
 *  -----------
 
2608
 *  Menu pane specification found.  Parse the following syntax:
 
2609
 *
 
2610
 *          v
 
2611
 *     Menu menu_pane_name
 
2612
 *     {
 
2613
 *       label  [mnemonic]  [accelerator]  function
 
2614
 *       label  [mnemonic]  [accelerator]  function
 
2615
 *                 ...
 
2616
 *       label  [mnemonic]  [accelerator]  function
 
2617
 *     }
 
2618
 *
 
2619
 *
 
2620
 *  Inputs:
 
2621
 *  ------
 
2622
 *  cfileP = (global) file pointer to fopened configuration file or NULL
 
2623
 *  lineP = pointer to menu name in line buffer
 
2624
 *  line   = (global) line buffer
 
2625
 *  linec  = (global) line count
 
2626
 *  parseP = (global) parse string pointer if cfileP == NULL
 
2627
 *  pSD->rootWindow = default root window of display
 
2628
 *  wmGD.bitmapDirectory = bitmapDirectory resource value
 
2629
 *  HOME = environment variable for home directory
 
2630
 *
 
2631
 * 
 
2632
 *  Outputs:
 
2633
 *  -------
 
2634
 *  linec  = (global) line count incremented
 
2635
 *  parseP = (global) parse string pointer if cfileP == NULL
 
2636
 *  pSD->menuSpecs = list of menu specifications
 
2637
 *
 
2638
 *
 
2639
 *  Comments:
 
2640
 *  --------
 
2641
 *  Skips unnamed menu specifications.
 
2642
 *  This means custom menu specifications can be distinguished by NULL name.
 
2643
 * 
 
2644
 *************************************<->***********************************/
 
2645
 
 
2646
static void ParseMenuSet (WmScreenData *pSD, unsigned char *lineP)
 
2647
{
 
2648
    unsigned char     *string;
 
2649
    MenuSpec *menuSpec;
 
2650
    
 
2651
    /*
 
2652
     * If menu name is NULL then skip this pane specification.
 
2653
     */
 
2654
 
 
2655
    if ((string = GetString (&lineP)) == NULL)
 
2656
    {
 
2657
        return;
 
2658
    }
 
2659
 
 
2660
    /*
 
2661
     * Allocate space for the menu specification structure.
 
2662
     */
 
2663
 
 
2664
    if ((menuSpec = (MenuSpec *)XtMalloc (sizeof (MenuSpec))) == NULL)
 
2665
    {
 
2666
        PWarning (((char *)GETMESSAGE(60, 9, "Insufficient memory for menu")));
 
2667
        return;
 
2668
    }
 
2669
    menuSpec->currentContext = 0;
 
2670
    menuSpec->menuWidget = NULL;
 
2671
    menuSpec->whichButton = SELECT_BUTTON;  /* Button1 selection default */
 
2672
    menuSpec->menuItems = NULL;
 
2673
    menuSpec->accelContext = 0;
 
2674
    menuSpec->accelKeySpecs = NULL;
 
2675
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
2676
    menuSpec->exclusions = NULL;
 
2677
    menuSpec->clientLocal = FALSE;
 
2678
    menuSpec->commandID = 0;
 
2679
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
2680
    menuSpec->nextMenuSpec = NULL;
 
2681
 
 
2682
    /*
 
2683
     * Allocate and fill space for the menu name.
 
2684
     */
 
2685
 
 
2686
    if ((menuSpec->name = 
 
2687
         (String)XtMalloc ((unsigned int) (strlen ((char *)string) + 1))) 
 
2688
         == NULL)
 
2689
    {
 
2690
        PWarning (((char *)GETMESSAGE(60, 10, "Insufficient memory for menu")));
 
2691
        XtFree ((char *)menuSpec);
 
2692
        return;
 
2693
    }
 
2694
    strcpy (menuSpec->name, (char *)string);
 
2695
 
 
2696
    /* 
 
2697
     * Add the empty structure to the head of the menu specification list.
 
2698
     */
 
2699
 
 
2700
    menuSpec->nextMenuSpec = pSD->menuSpecs;
 
2701
    pSD->menuSpecs = menuSpec;
 
2702
 
 
2703
    /*
 
2704
     * Require leading '{' on the next line.
 
2705
     */
 
2706
 
 
2707
    while ((GetNextLine () != NULL))  /* not EOF nor read error */
 
2708
    {
 
2709
        lineP = line;
 
2710
        ScanWhitespace(&lineP);
 
2711
 
 
2712
        if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
 
2713
        /* ignore empty or comment line */
 
2714
        {
 
2715
            continue;
 
2716
        }
 
2717
 
 
2718
        if (*lineP == '{')
 
2719
        /* found '{' */
 
2720
        {
 
2721
            break;
 
2722
        }
 
2723
 
 
2724
        /* not a '{' */
 
2725
        PWarning (((char *)GETMESSAGE(60, 11, "Expected '{' after menu name")));
 
2726
        return;
 
2727
    }
 
2728
 
 
2729
    /*
 
2730
     * Found leading "{" or EOF.
 
2731
     * Parse menu item specifications until "}" or EOF found.
 
2732
     */
 
2733
 
 
2734
    menuSpec->menuItems = PARSE_MENU_ITEMS (pSD, menuSpec);
 
2735
 
 
2736
} /* END OF FUNCTION ParseMenuSet */
 
2737
 
 
2738
 
 
2739
/*************************************<->*************************************
 
2740
 *
 
2741
 *  MenuItem *
 
2742
 *  ParseMwmMenuStr (pSD, menuStr)
 
2743
 *
 
2744
 *
 
2745
 *  Description:
 
2746
 *  -----------
 
2747
 *  This function parses a WMW_MENU string and returns a list of 
 
2748
 *  MenuItems structures.  The string should have the syntax:
 
2749
 *
 
2750
 *       label  [mnemonic]  [accelerator]  function
 
2751
 *       label  [mnemonic]  [accelerator]  function
 
2752
 *                 ...
 
2753
 *       label  [mnemonic]  [accelerator]  function
 
2754
 *
 
2755
 *
 
2756
 *  Inputs:
 
2757
 *  ------
 
2758
 *  line = (global) line buffer
 
2759
 *  pSD->rootWindow = default root window of display
 
2760
 *  wmGD.bitmapDirectory = bitmapDirectory resource value
 
2761
 *  HOME = environment variable for home directory
 
2762
 *  functionTable = window manager function parse table
 
2763
 *
 
2764
 * 
 
2765
 *  Outputs:
 
2766
 *  -------
 
2767
 *  Return = list of MenuItem structures or NULL
 
2768
 *
 
2769
 *
 
2770
 *  Comments:
 
2771
 *  --------
 
2772
 *  None.
 
2773
 * 
 
2774
 *************************************<->***********************************/
 
2775
 
 
2776
MenuItem *ParseMwmMenuStr (WmScreenData *pSD, unsigned char *menuStr)
 
2777
{
 
2778
 
 
2779
    cfileP = NULL;
 
2780
    linec = 0;
 
2781
    parseP = menuStr;
 
2782
 
 
2783
    return (PARSE_MENU_ITEMS (pSD, NULL));
 
2784
 
 
2785
} /* END OF FUNCTION ParseMwmMenuStr */
 
2786
 
 
2787
 
 
2788
/*************************************<->*************************************
 
2789
 *
 
2790
 *  static MenuItem *
 
2791
 *  ParseMenuItems (pSD, menuSpec)
 
2792
 *
 
2793
 *
 
2794
 *  Description:
 
2795
 *  -----------
 
2796
 *  Parse menu item specifications:
 
2797
 *
 
2798
 *       label  [mnemonic]  [accelerator]  function
 
2799
 *       label  [mnemonic]  [accelerator]  function
 
2800
 *                 ...
 
2801
 *       label  [mnemonic]  [accelerator]  function
 
2802
 *     [}]
 
2803
 *
 
2804
 *
 
2805
 *  Inputs:
 
2806
 *  ------
 
2807
 *  pSD    = pointer to screen data
 
2808
 *  cfileP = (global) file pointer to fopened configuration file or NULL
 
2809
 *  line   = (global) line buffer
 
2810
 *  linec  = (global) line count
 
2811
 *  parseP = (global) parse string pointer if cfileP == NULL
 
2812
 *  pSD->rootWindow = default root window of display
 
2813
 *  wmGD.bitmapDirectory = bitmapDirectory resource value
 
2814
 *  HOME = environment variable for home directory
 
2815
 *
 
2816
 * 
 
2817
 *  Outputs:
 
2818
 *  -------
 
2819
 *  linec  = (global) line count incremented
 
2820
 *  parseP = (global) parse string pointer if cfileP == NULL
 
2821
 *  Return = list of MenuItem structures or NULL
 
2822
 *
 
2823
 *
 
2824
 *  Comments:
 
2825
 *  --------
 
2826
 *  None.
 
2827
 * 
 
2828
 *************************************<->***********************************/
 
2829
 
 
2830
static MenuItem *ParseMenuItems (WmScreenData *pSD
 
2831
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
2832
                                 , MenuSpec *menuSpec
 
2833
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
2834
                                )
 
2835
{
 
2836
    unsigned char *string;
 
2837
    unsigned char *lineP;
 
2838
    MenuItem      *firstMenuItem;
 
2839
    MenuItem      *lastMenuItem;
 
2840
    MenuItem      *menuItem;
 
2841
    register int   ix;
 
2842
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
2843
    Boolean        use_separators = False;
 
2844
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
2845
    
 
2846
    /*
 
2847
     * Parse "label [mnemonic] [accelerator] function" or
 
2848
     *       "<client command>[.<client command>]*"
 
2849
     * lines until "}" or EOF found.
 
2850
     */
 
2851
 
 
2852
    firstMenuItem = lastMenuItem = NULL;
 
2853
    while ((GetNextLine () != NULL))
 
2854
    {
 
2855
        lineP = line;
 
2856
        if ((*line == '!') || (*line == '#') || (string = GetString (&lineP)) == NULL)
 
2857
        /* ignore empty or comment lines */
 
2858
        {
 
2859
            continue;
 
2860
        }
 
2861
        if (*string == '}')  /* finished with menu set. */
 
2862
        {
 
2863
            break;
 
2864
        }
 
2865
 
 
2866
        /*
 
2867
         * Allocate space for the menu item structure. 
 
2868
         */
 
2869
 
 
2870
        if ((menuItem = (MenuItem *)XtMalloc (sizeof (MenuItem))) == NULL)
 
2871
        {
 
2872
            PWarning (((char *)GETMESSAGE(60, 12, "Insufficient memory for menu item")));
 
2873
            continue;
 
2874
        }
 
2875
        menuItem->nextMenuItem = NULL;
 
2876
        menuItem->wmFunction = (WmFunction)NULL;
 
2877
        menuItem->wmFuncArgs = NULL;
 
2878
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
2879
        menuItem->clientCommandName = NULL;
 
2880
        menuItem->clientCommandID = 0;
 
2881
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
2882
 
 
2883
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
2884
        /*
 
2885
         * Is this a simple menu item label or is it a
 
2886
         * client command specification.
 
2887
         */
 
2888
 
 
2889
        if (IsClientCommand((String) string))
 
2890
        {
 
2891
            if (!ParseClientCommand(&lineP, menuSpec, menuItem, string,
 
2892
                                    &use_separators))
 
2893
            {
 
2894
                XtFree ((char *)menuItem);
 
2895
                continue;
 
2896
            }
 
2897
 
 
2898
            for (ix = 0; ix < WMFUNCTIONTABLESIZE - 1; ++ix)
 
2899
              if (functionTable[ix].wmFunction == F_InvokeCommand)
 
2900
                break;
 
2901
 
 
2902
            if (ix == WMFUNCTIONTABLESIZE - 1)
 
2903
            {
 
2904
                ix = F_NOP_INDEX;
 
2905
                menuItem->wmFunction = F_Nop;
 
2906
            }
 
2907
            else menuItem->wmFunction = F_InvokeCommand;
 
2908
        }
 
2909
        else /* It must be a menu item label */
 
2910
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
2911
        {
 
2912
            /*
 
2913
             * Parse the menu item label.
 
2914
             */
 
2915
            if (!ParseWmLabel (pSD, menuItem, string))
 
2916
            {
 
2917
                XtFree ((char *)menuItem);
 
2918
                continue;
 
2919
            }
 
2920
        }
 
2921
 
 
2922
        /*
 
2923
         * Parse any menu function mnemonic.
 
2924
         */
 
2925
 
 
2926
        ParseWmMnemonic (&lineP, menuItem);
 
2927
 
 
2928
        /*
 
2929
         * Parse any menu function accelerator.
 
2930
         */
 
2931
 
 
2932
        if (!ParseWmAccelerator (&lineP, menuItem))
 
2933
        {
 
2934
            FreeMenuItem (menuItem);
 
2935
            continue;
 
2936
        }
 
2937
        /*
 
2938
         * Parse the menu function name if this is not a client
 
2939
         * command. If it is a client command, then the wmFunction
 
2940
         * field should already be set, as well as the ix variable,
 
2941
         * but we do want to search for a menu item name that occupies
 
2942
         * the same place as the function does for normal menu items.
 
2943
         */
 
2944
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
2945
        if (menuItem->wmFunction != NULL)
 
2946
          ParseMenuItemName(&lineP, menuItem);
 
2947
        else
 
2948
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
2949
          ix = ParseWmFunction (&lineP, CRS_MENU, &menuItem->wmFunction);
 
2950
 
 
2951
        /*
 
2952
         * Determine context sensitivity and applicability mask.
 
2953
         */
 
2954
 
 
2955
        menuItem->greyedContext = functionTable[ix].greyedContext;
 
2956
        menuItem->mgtMask = functionTable[ix].mgtMask;
 
2957
#ifdef PANELIST
 
2958
        if ((menuItem->wmFunction == F_Toggle_Front_Panel) &&
 
2959
            ((wmGD.useFrontPanel == False) ||
 
2960
             (wmGD.dtSD != pSD)))
 
2961
        {
 
2962
            /*
 
2963
             * disallow this function if there's no front
 
2964
             * panel on this screen.
 
2965
             */
 
2966
            menuItem->greyedContext |= (F_CONTEXT_ALL           | 
 
2967
                                       F_SUBCONTEXT_IB_WICON    | 
 
2968
                                       F_SUBCONTEXT_IB_IICON);
 
2969
        }
 
2970
#endif /* PANELIST */
 
2971
 
 
2972
        /* 
 
2973
         * Apply the function argument parser.
 
2974
         */
 
2975
        if (!(*(functionTable [ix].parseProc)) 
 
2976
                   (&lineP, menuItem->wmFunction, &menuItem->wmFuncArgs))
 
2977
        {
 
2978
            FreeMenuItem (menuItem);
 
2979
            continue;  /* skip this menu item */
 
2980
        }
 
2981
 
 
2982
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
2983
        /*
 
2984
         * If we're working on the f.cci function, this will fix-up
 
2985
         * the menuItem entries so that it appears that we read-in
 
2986
         * an old-style client-command entry.  Eventually, the cci
 
2987
         * handling should be changed to make use of the wmFuncArgs.
 
2988
         * Note that if DEFAULT_NAME was specified as the label, it
 
2989
         * is first set to NULL.
 
2990
         * FixMenuItem needs menuSpec since this is when the EXCLUDE
 
2991
         * items are stored.
 
2992
         */
 
2993
        if (ix == F_CCI_INDEX)
 
2994
          {
 
2995
            CCIEntryModifier mod = ((CCIFuncArg *)menuItem->wmFuncArgs)->mod;
 
2996
 
 
2997
            /* first fix the label if needed. */
 
2998
            if (!strcmp(menuItem->label, CCI_USE_DEFAULT_NAME_TAG))
 
2999
              {
 
3000
                XtFree(menuItem->label);
 
3001
                menuItem->label = NULL;
 
3002
              }
 
3003
 
 
3004
            FixMenuItem(menuSpec, menuItem);
 
3005
 
 
3006
            if (mod == DELIMIT || mod == DELIMIT_CASCADE || mod == DELIMIT_INLINE)
 
3007
              use_separators = True;
 
3008
          }
 
3009
 
 
3010
        /*
 
3011
         * If this menu item is supposed to be wrapped in separators,
 
3012
         * then create a separator template before the menu item
 
3013
         */
 
3014
        if (use_separators)
 
3015
        {
 
3016
            MenuItem *separator = MakeSeparatorTemplate(TOP_SEPARATOR);
 
3017
            if (lastMenuItem != NULL) lastMenuItem->nextMenuItem = separator;
 
3018
            else                      firstMenuItem = separator;
 
3019
            lastMenuItem = separator;
 
3020
        }
 
3021
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
3022
 
 
3023
        /*
 
3024
         * Add this item to the menu specification.
 
3025
         */
 
3026
 
 
3027
        if (lastMenuItem != NULL)  /* not first */
 
3028
        {
 
3029
            lastMenuItem->nextMenuItem = menuItem;
 
3030
        }
 
3031
        else
 
3032
        {
 
3033
            firstMenuItem = menuItem;
 
3034
        }
 
3035
        lastMenuItem = menuItem;
 
3036
 
 
3037
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
3038
        /* If this menu item is supposed to be wrapped in separators
 
3039
         * then create a separator template after the menu item
 
3040
         */
 
3041
        if (use_separators)
 
3042
        {
 
3043
            MenuItem *separator = MakeSeparatorTemplate(BOTTOM_SEPARATOR);
 
3044
            if (lastMenuItem != NULL) lastMenuItem->nextMenuItem = separator;
 
3045
            else                      firstMenuItem = separator;
 
3046
            lastMenuItem = separator;
 
3047
        }
 
3048
 
 
3049
        use_separators = FALSE;
 
3050
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
3051
    }
 
3052
 
 
3053
    return (firstMenuItem);
 
3054
 
 
3055
} /* END OF FUNCTION ParseMenuItems */
 
3056
 
 
3057
 
 
3058
 
 
3059
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
3060
/*************************************<->*************************************
 
3061
 *
 
3062
 *  StoreExclusion (menuSpec, string)
 
3063
 *
 
3064
 *
 
3065
 *  Description:
 
3066
 *  -----------
 
3067
 *  Store the exclusion string in the menuspec. The list of exclusion
 
3068
 *  strings are used to determine whether an insertion should be disallowed.
 
3069
 *
 
3070
 *
 
3071
 *  Inputs:
 
3072
 *  ------
 
3073
 *  menuSpec = the menu specification structure
 
3074
 *  string   = exclusion client command string
 
3075
 *
 
3076
 * 
 
3077
 *  Outputs:
 
3078
 *  -------
 
3079
 *  Return   = nothing
 
3080
 *
 
3081
 *  Comments:
 
3082
 *  --------
 
3083
 *
 
3084
 *************************************<->***********************************/
 
3085
 
 
3086
static void StoreExclusion (MenuSpec *menuSpec, String string)
 
3087
{
 
3088
    MenuExclusion *exclusion;
 
3089
 
 
3090
    exclusion = (MenuExclusion *)XtMalloc(sizeof(MenuExclusion));
 
3091
    exclusion->command_string = XtNewString(string);
 
3092
 
 
3093
    /* We don't care what order the exclusions are in so stick it
 
3094
       at the head of the list because it is easier. */
 
3095
    exclusion->nextExclusion = menuSpec->exclusions;
 
3096
    menuSpec->exclusions = exclusion;
 
3097
}
 
3098
 
 
3099
 
 
3100
/*************************************<->*************************************
 
3101
 *
 
3102
 *  IsClientCommand (string)
 
3103
 *
 
3104
 *
 
3105
 *  Description:
 
3106
 *  -----------
 
3107
 *  Determine whether the string is a client command by the prefix
 
3108
 *  characters.
 
3109
 *
 
3110
 *
 
3111
 *  Inputs:
 
3112
 *  ------
 
3113
 *  string   = possible client command string
 
3114
 *
 
3115
 * 
 
3116
 *  Outputs:
 
3117
 *  -------
 
3118
 *  Return   = (Boolean) TRUE iff the string is a client command.
 
3119
 *             Otherwise, FALSE is returned.
 
3120
 *
 
3121
 *
 
3122
 *  Comments:
 
3123
 *  --------
 
3124
 *  This function simply checks what the first two or three characters of
 
3125
 *  the string are. If they match the beginning of a client command
 
3126
 *  specification, then TRUE is returned. This function does no go on to
 
3127
 *  parse the rest of the specification. The legal client command beginning
 
3128
 *  characters are:
 
3129
 *
 
3130
 *              characters:     meaning:
 
3131
 *              -----------------------------------------------
 
3132
 *                  <           simple client command beginning
 
3133
 *                -><           forced cascade menu
 
3134
 *                 =<           client command with separators
 
3135
 *                 ~<           exclusion operator
 
3136
 * 
 
3137
 *  Assumes:
 
3138
 *  --------
 
3139
 *  There is no leading whitespace on the string
 
3140
 *
 
3141
 *************************************<->***********************************/
 
3142
 
 
3143
Boolean IsClientCommand (String string)
 
3144
{
 
3145
    if ((
 
3146
#ifndef NO_MULTIBYTE
 
3147
         mblen ((char *)string, MB_CUR_MAX) == 1 &&
 
3148
#endif
 
3149
         *string == '<') ||
 
3150
        (strncmp(string, "-><", 3) == 0) ||
 
3151
        (strncmp(string, "=<", 2) == 0)  ||
 
3152
        (strncmp(string, "=><", 3) == 0) ||
 
3153
        (strncmp(string, "~<", 2) == 0))
 
3154
      return(TRUE);
 
3155
 
 
3156
    return(FALSE);
 
3157
}
 
3158
 
 
3159
 
 
3160
/*************************************<->*************************************
 
3161
 *
 
3162
 *  ParseClientCommand (linePP, menuSpec, menuitem, string, use_separators)
 
3163
 *
 
3164
 *
 
3165
 *  Description:
 
3166
 *  -----------
 
3167
 *  Parse the string and whatever is left of the line to verify whether
 
3168
 *  correct syntax was used for a client command. Store the client command
 
3169
 *  string in the menuitem, unless it is an exclusion. If it is an
 
3170
 *  exclusion, then store the exclusion string in the menuSpec and return
 
3171
 *  FALSE to indicate that the menuitem is no longer needed.
 
3172
 *
 
3173
 *
 
3174
 *  Inputs:
 
3175
 *  ------
 
3176
 *  linePP   = pointer to current line buffer pointer.
 
3177
 *  menuItem = pointer to MenuItem structure
 
3178
 *  string   = first token of client command
 
3179
 *
 
3180
 * 
 
3181
 *  Outputs:
 
3182
 *  -------
 
3183
 *  Return   = (Boolean) TRUE iff the line is a valid client command 
 
3184
 *             that can used to match insertions.
 
3185
 *             Otherwise, FALSE is returned meaning that the client
 
3186
 *             command had incorrect syntax or it was an exclusion, in
 
3187
 *             which case any useful information was stored in the
 
3188
 *             menuSpec.
 
3189
 *
 
3190
 *
 
3191
 *  Comments:
 
3192
 *  --------
 
3193
 *  This function parses the entire line to determine if correct
 
3194
 *  syntax was used for the client command. We assume at this point
 
3195
 *  that the line is a client command. We are just syntax checking.
 
3196
 *  If the syntax is correct, the client command is stored in the
 
3197
 *  menuitem structure, in the "label" field.
 
3198
 *
 
3199
 *  Valid syntax for a client command (single quoted characters are
 
3200
 *  literals):
 
3201
 *
 
3202
 *  modifier  = { '->' | '=' | '~' }
 
3203
 *  reference = '<' { name | '*' } '>'
 
3204
 *  command   = [ modifier ] reference [ { modifier | '.' } reference ]*
 
3205
 *  name      = alpha-numeric string, white space allowed
 
3206
 *
 
3207
 *  Assumes:
 
3208
 *  --------
 
3209
 *  There is no leading whitespace on the string argument
 
3210
 *
 
3211
 *************************************<->***********************************/
 
3212
 
 
3213
enum { PRS_NO_STATE, PRS_BEGIN, PRS_MODIFIER, PRS_REFERENCE,
 
3214
       PRS_SEPARATOR, PRS_END, PRS_ERROR, PRS_MAX_STATES };
 
3215
 
 
3216
/* This table lists for each parse state, the legal states that can
 
3217
   be moved to. Each list must end with a PRS_NO_STATE value to 
 
3218
   terminate the list. */
 
3219
static int cmd_parse_table[PRS_END][PRS_END] =
 
3220
{
 
3221
  /* PRS_NO_STATE */  { PRS_NO_STATE },
 
3222
  /* PRS_BEGIN */     { PRS_MODIFIER, PRS_REFERENCE, PRS_NO_STATE },
 
3223
  /* PRS_MODIFIER */  { PRS_REFERENCE, PRS_NO_STATE },
 
3224
  /* PRS_REFERENCE */ { PRS_SEPARATOR, PRS_END, PRS_NO_STATE },
 
3225
  /* PRS_SEPARATOR */ { PRS_REFERENCE, PRS_NO_STATE },
 
3226
};
 
3227
 
 
3228
static Boolean ParseClientCommand (unsigned char **linePP, MenuSpec *menuSpec,
 
3229
                                   MenuItem *menuItem, unsigned char *string,
 
3230
                                   Boolean *use_separators)
 
3231
{
 
3232
    int token, linelen, i;
 
3233
    int state = PRS_BEGIN;
 
3234
    String stream, unchanged_stream, exclusion_text;
 
3235
    Boolean return_val = FALSE;
 
3236
    Boolean exclusion = FALSE; /* this will be set to TRUE if the client
 
3237
                                  command was parsed to be an exclusion
 
3238
                                  command. */
 
3239
 
 
3240
    /* Construct one input stream out of the string and the linePP that
 
3241
       we were given. */
 
3242
    linelen = strlen((char *)string) + strlen((char *)*linePP) + 1;
 
3243
    if ((unchanged_stream = stream = (String)
 
3244
         XtMalloc((unsigned int)(sizeof(unsigned char) * linelen))) == NULL)
 
3245
    {
 
3246
        PWarning (((char *)GETMESSAGE(60, 42,
 
3247
                    "Insufficient memory for menu item label")));
 
3248
        return (FALSE);
 
3249
    }
 
3250
    strcpy(stream, (char *) string);
 
3251
    strcat(stream, " ");
 
3252
    strcat(stream, (char *) *linePP);
 
3253
 
 
3254
    for (;;)
 
3255
    {
 
3256
        token = PRS_NO_STATE;
 
3257
        while (token == PRS_NO_STATE)
 
3258
        {
 
3259
#ifndef NO_MULTIBYTE
 
3260
            if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
 
3261
              token = PRS_ERROR;
 
3262
              continue;
 
3263
            }
 
3264
#endif
 
3265
 
 
3266
            switch (*stream)
 
3267
            {
 
3268
              case '\0':
 
3269
              case '\n':
 
3270
                /* We've reached the end of the stream. Return the
 
3271
                   PRS_END token. */
 
3272
                token = PRS_END;
 
3273
                break;
 
3274
              case '-':
 
3275
                /* This should be a cascade-force modifier */
 
3276
                ++stream;
 
3277
#ifndef NO_MULTIBYTE
 
3278
                if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
 
3279
                  token = PRS_ERROR;
 
3280
                  continue;
 
3281
                }
 
3282
#endif
 
3283
                if (*stream == '>')
 
3284
                {
 
3285
                    ++stream; token = PRS_MODIFIER;
 
3286
                }
 
3287
                else token = PRS_ERROR;
 
3288
                break;
 
3289
              case '=':
 
3290
                /* This is either a separators modifier or
 
3291
                   a combination separators and cascade-force
 
3292
                   modifier */
 
3293
                ++stream;
 
3294
#ifndef NO_MULTIBYTE
 
3295
                if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
 
3296
                  token = PRS_ERROR;
 
3297
                  continue;
 
3298
                }
 
3299
#endif
 
3300
                if (*stream == '>') ++stream;
 
3301
                token = PRS_MODIFIER;
 
3302
                *use_separators = TRUE;
 
3303
                break;
 
3304
              case '~':
 
3305
                /* This is a exclude-command modifier */
 
3306
                ++stream; token = PRS_MODIFIER;
 
3307
                exclusion = TRUE;
 
3308
                /* Setup a pointer to the text following the ~ so
 
3309
                   we can do matching later for exclusions. */
 
3310
                exclusion_text = stream;
 
3311
                break;
 
3312
              case '<':
 
3313
                /* Skip the open bracket */
 
3314
                ++stream;
 
3315
 
 
3316
                /* This should be the beginning of a reference. First
 
3317
                   skip any leading whitespace. */
 
3318
#ifndef NO_MULTIBYTE
 
3319
                if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
 
3320
                  token = PRS_ERROR;
 
3321
                  continue;
 
3322
                }
 
3323
#endif
 
3324
                while (
 
3325
#ifndef NO_MULTIBYTE
 
3326
                       mblen ((char *)stream, MB_CUR_MAX) == 1 &&
 
3327
#endif
 
3328
                       (*stream == ' ' || *stream == '\t')) 
 
3329
                  ++stream;
 
3330
 
 
3331
#ifndef NO_MULTIBYTE
 
3332
                if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
 
3333
                  token = PRS_ERROR;
 
3334
                  continue;
 
3335
                }
 
3336
#endif
 
3337
                /* Now check for a reference name wild card or a
 
3338
                   full reference name */
 
3339
                if (*stream == '*')
 
3340
                  ++stream;
 
3341
                else
 
3342
                {
 
3343
                    while (
 
3344
#ifndef NO_MULTIBYTE
 
3345
                           mblen ((char *)stream, MB_CUR_MAX) == 1 &&
 
3346
#endif
 
3347
                           (isalnum(*stream) || *stream == ' ' ||
 
3348
                            *stream == '\t'  || *stream == '_' ))
 
3349
                      ++stream;
 
3350
                }
 
3351
                
 
3352
#ifndef NO_MULTIBYTE
 
3353
                if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
 
3354
                  token = PRS_ERROR;
 
3355
                  continue;
 
3356
                }
 
3357
#endif
 
3358
 
 
3359
                /* Now skip past any trailing white space */
 
3360
                while (
 
3361
#ifndef NO_MULTIBYTE
 
3362
                       mblen ((char *)stream, MB_CUR_MAX) == 1 &&
 
3363
#endif
 
3364
                       (*stream == ' ' || *stream == '\t'))
 
3365
                  ++stream;
 
3366
 
 
3367
#ifndef NO_MULTIBYTE
 
3368
                if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
 
3369
                  token = PRS_ERROR;
 
3370
                  continue;
 
3371
                }
 
3372
#endif
 
3373
                /* At this point, we should be looking at the close
 
3374
                   of the reference */
 
3375
                if (*stream == '>')
 
3376
                {
 
3377
                    token = PRS_REFERENCE;
 
3378
                    ++stream;
 
3379
                }
 
3380
                else token = PRS_ERROR;
 
3381
                break;
 
3382
              case '.':
 
3383
                /* This is a reference separator */
 
3384
                ++stream; token = PRS_SEPARATOR;
 
3385
                break;
 
3386
              case ' ':
 
3387
              case '\t':
 
3388
                /* The only place white space is allowed as at the
 
3389
                   beginning of the line, after all the client command
 
3390
                   text and within the delimiters of a REFERENCE. We
 
3391
                   are guaranteed not to have whitespace at the 
 
3392
                   beginning of the line by the time this function is
 
3393
                   called. Also, the REFERENCE parsing above handles
 
3394
                   all white space internal to the client command. Therefore,
 
3395
                   since we are seeing white space, we must be at the
 
3396
                   end of the client command. */
 
3397
                token = PRS_END;
 
3398
                break;
 
3399
              default:
 
3400
                token = PRS_ERROR;
 
3401
 
 
3402
            } /* end switch (*stream) */
 
3403
        } /* end while (token == PRS_NO_STATE) */
 
3404
 
 
3405
        /* If we got an error then just return an error */
 
3406
        if (token == PRS_ERROR)
 
3407
        {
 
3408
            return_val = FALSE; break;
 
3409
        }
 
3410
        
 
3411
        /* Check whether the token we got is a valid transition */
 
3412
        for (i = 0; cmd_parse_table[state][i] != PRS_NO_STATE; ++i)
 
3413
        {
 
3414
            if (token == cmd_parse_table[state][i]) 
 
3415
            {
 
3416
                /* It is a valid transition, so break out of the loop */
 
3417
                break;
 
3418
            }
 
3419
        }
 
3420
        
 
3421
        /* If i is not indexing the NO_STATE value in the parse_table,
 
3422
           then the parse succeeded. Check if the new state is PRS_END.
 
3423
           If so then we are done. If the state isn't the same as the
 
3424
           current token, then we hit a parse error. */
 
3425
        if (cmd_parse_table[state][i] != PRS_NO_STATE)
 
3426
        {
 
3427
            if (token == PRS_END)
 
3428
            {
 
3429
                return_val = TRUE;
 
3430
                break;
 
3431
            }
 
3432
        }
 
3433
        else 
 
3434
        {
 
3435
            /* parse error */
 
3436
            return_val = FALSE;
 
3437
            break;
 
3438
        }
 
3439
        
 
3440
        /* The transition was valid so make the transition by
 
3441
           setting the state to be the current token. */
 
3442
        state = token; 
 
3443
 
 
3444
    } /* end for (;;) */
 
3445
 
 
3446
    /* If the return_val is TRUE, then the parse succeeded and we
 
3447
       want to save the string we parsed into the label field of
 
3448
       the menu item. */
 
3449
    if (return_val == TRUE)
 
3450
    {
 
3451
        /* NULL terminate the string */
 
3452
        *stream = '\0';
 
3453
 
 
3454
        /* Check whether this client command was an exclusion. If not,
 
3455
           then store the client command string in the menu item. */
 
3456
        if (exclusion == TRUE)
 
3457
        {
 
3458
            /* Since the command was an exclusion, store the command
 
3459
               string in the menuSpec and change the return value to
 
3460
               FALSE. */
 
3461
            StoreExclusion(menuSpec, exclusion_text);
 
3462
            return_val = FALSE;
 
3463
        }
 
3464
        else
 
3465
        {
 
3466
            menuItem->label = XtNewString(unchanged_stream);
 
3467
            menuItem->labelType = XmSTRING;
 
3468
        }
 
3469
    }
 
3470
 
 
3471
    /* Free the string we allocated and return. */
 
3472
    XtFree((char *)unchanged_stream);
 
3473
 
 
3474
    return(return_val);
 
3475
}
 
3476
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
3477
 
 
3478
 
 
3479
/*************************************<->*************************************
 
3480
 *
 
3481
 *  ParseWmLabel (pSD, menuItem, string)
 
3482
 *
 
3483
 *
 
3484
 *  Description:
 
3485
 *  -----------
 
3486
 *  Parse a menu label string.
 
3487
 *
 
3488
 *
 
3489
 *  Inputs:
 
3490
 *  ------
 
3491
 *  pSD      = pointer to screen data
 
3492
 *  menuItem = pointer to MenuItem structure
 
3493
 *  string   = label string
 
3494
 *
 
3495
 * 
 
3496
 *  Outputs:
 
3497
 *  -------
 
3498
 *  menuItem->label
 
3499
 *  menuItem->labelType
 
3500
 *  menuItem->labelBitmapCache
 
3501
 *  Return   = boolean, FALSE iff insufficient memory
 
3502
 *
 
3503
 *
 
3504
 *  Comments:
 
3505
 *  --------
 
3506
 * We have two label types:  XmSTRING and XmPIXMAP
 
3507
 * We allocate and fill the label field with string and set the type to 
 
3508
 * XmSTRING.  If string = "@<bitmap_file>", and <bitmap_file> contains a
 
3509
 * with which to build a label image we save the bitmap in the MenuItem 
 
3510
 * structure and set the type to XmPIXMAP.
 
3511
 * 
 
3512
 *************************************<->***********************************/
 
3513
 
 
3514
static Boolean ParseWmLabel (WmScreenData *pSD, MenuItem *menuItem, 
 
3515
                             unsigned char *string)
 
3516
{
 
3517
 
 
3518
    /*
 
3519
     * Allocate the label field and copy string.
 
3520
     */
 
3521
 
 
3522
    if ((menuItem->label = (String)
 
3523
        XtMalloc ((unsigned int)(strlen ((char *)string) + 1))) == NULL)
 
3524
    {
 
3525
        PWarning (((char *)GETMESSAGE(60, 13, "Insufficient memory for menu item")));
 
3526
        return (FALSE);
 
3527
    }
 
3528
 
 
3529
    strcpy (menuItem->label, (char *)string);
 
3530
    menuItem->labelType = XmSTRING;
 
3531
 
 
3532
    if (*string == '@')
 
3533
    /*
 
3534
     * Here:  string  = "@<bitmap file>"
 
3535
     * Try to find the label bitmap in the bitmap cache or read the label 
 
3536
     * bitmap file.
 
3537
     */
 
3538
    {
 
3539
        string++;  /* skip "@" */
 
3540
#ifdef WSM
 
3541
        if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD, 
 
3542
                                           (char *)string, True)) >= 0)
 
3543
#else /* WSM */
 
3544
        if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD, 
 
3545
                                               (char *)string)) >= 0)
 
3546
#endif /* WSM */
 
3547
        {
 
3548
            menuItem->labelType = XmPIXMAP;
 
3549
        }
 
3550
    }
 
3551
    return (TRUE);
 
3552
 
 
3553
} /* END OF FUNCTION ParseWmLabel */
 
3554
 
 
3555
 
 
3556
 
 
3557
/*************************************<->*************************************
 
3558
 *
 
3559
 *  ParseWmMnemonic (linePP, menuItem)
 
3560
 *
 
3561
 *
 
3562
 *  Description:
 
3563
 *  -----------
 
3564
 *  Parse an optional menu function mnemonic.
 
3565
 *
 
3566
 *
 
3567
 *  Inputs:
 
3568
 *  ------
 
3569
 *  linePP   = pointer to current line buffer pointer.
 
3570
 *  menuItem = pointer to MenuItem structure
 
3571
 *
 
3572
 * 
 
3573
 *  Outputs:
 
3574
 *  -------
 
3575
 *  linePP   = pointer to revised line buffer pointer.
 
3576
 *  menuItem->mnemonic = valid mnemonic character or NULL.
 
3577
 *
 
3578
 *
 
3579
 *  Comments:
 
3580
 *  --------
 
3581
 *  None.
 
3582
 * 
 
3583
 *************************************<->***********************************/
 
3584
 
 
3585
static void ParseWmMnemonic (unsigned char **linePP, MenuItem *menuItem)
 
3586
{
 
3587
    unsigned char *lineP = *linePP;
 
3588
    unsigned char *mnemonic;
 
3589
 
 
3590
    /*
 
3591
     * Skip leading white space.
 
3592
     */
 
3593
    ScanWhitespace (&lineP);
 
3594
    menuItem->mnemonic = (KeySym)NULL;
 
3595
 
 
3596
    if (*lineP == '_')
 
3597
    /* 
 
3598
     * We have a mnemonic specification. 
 
3599
     * Get the next string (we only use the first character).
 
3600
     * If no string exists, the labelType is not XmSTRING, or does not contain 
 
3601
     * the first character, then skip the string and return.
 
3602
     * Otherwise, accept the first character as a mnemonic.
 
3603
     */
 
3604
    {
 
3605
        KeySym ks;
 
3606
        lineP++;
 
3607
        mnemonic = GetString(&lineP);
 
3608
 
 
3609
#ifndef NO_MULTIBYTE
 
3610
        if (menuItem->labelType == XmSTRING &&
 
3611
            mnemonic != NULL &&
 
3612
            (ks = XStringToKeysym((char *)mnemonic)) != NoSymbol &&
 
3613
            strchr(menuItem->label, (char)(ks & 0xff)) != NULL)
 
3614
        {
 
3615
            menuItem->mnemonic = ks;
 
3616
        }
 
3617
#else
 
3618
        if ((mnemonic != NULL) &&
 
3619
            (*mnemonic != '\0') &&
 
3620
            (menuItem->labelType == XmSTRING) &&
 
3621
            (strchr (menuItem->label, *mnemonic) != NULL))
 
3622
        /* valid mnemonic */
 
3623
        {
 
3624
            menuItem->mnemonic = *mnemonic;
 
3625
        }
 
3626
#endif
 
3627
        else
 
3628
        {
 
3629
            PWarning (((char *)GETMESSAGE(60, 14, "Invalid mnemonic specification")));
 
3630
        }
 
3631
    }
 
3632
 
 
3633
    *linePP = lineP;  /* consume any string */
 
3634
 
 
3635
} /* END OF FUNCTION ParseWmMnemonic */
 
3636
 
 
3637
 
 
3638
/*************************************<->*************************************
 
3639
 *
 
3640
 *  ParseWmAccelerator (linePP, menuItem)
 
3641
 *
 
3642
 *
 
3643
 *  Description:
 
3644
 *  -----------
 
3645
 *  Parse an optional menu function accelerator.
 
3646
 *
 
3647
 *
 
3648
 *  Inputs:
 
3649
 *  ------
 
3650
 *  linePP   = pointer to current line buffer pointer.
 
3651
 *  menuItem = pointer to MenuItem structure
 
3652
 *
 
3653
 * 
 
3654
 *  Outputs:
 
3655
 *  -------
 
3656
 *  linePP   = pointer to revised line buffer pointer.
 
3657
 *  menuItem->accelText = pointer to an accelerator string or NULL.
 
3658
 *
 
3659
 *
 
3660
 *  Comments:
 
3661
 *  --------
 
3662
 *  None.
 
3663
 * 
 
3664
 *************************************<->***********************************/
 
3665
 
 
3666
static Boolean ParseWmAccelerator (unsigned char **linePP, MenuItem *menuItem)
 
3667
{
 
3668
    unsigned char *lineP;
 
3669
    String        string;
 
3670
    unsigned int  eventType;
 
3671
    unsigned int  state;
 
3672
    KeyCode       keycode;
 
3673
    Boolean       status;
 
3674
 
 
3675
    menuItem->accelState = 0;
 
3676
    menuItem->accelKeyCode = 0;
 
3677
    menuItem->accelText = NULL;
 
3678
    status = TRUE;
 
3679
 
 
3680
    /*
 
3681
     * If linePP contains NULL, then abort.
 
3682
     */
 
3683
    if (*linePP == (unsigned char *) NULL) return(FALSE);
 
3684
 
 
3685
    /*
 
3686
     * Skip leading white space.
 
3687
     */
 
3688
    ScanWhitespace (linePP);
 
3689
    lineP = *linePP;
 
3690
 
 
3691
    /*
 
3692
     * If the second character is not ".", and an accelerator specification 
 
3693
     * exists, then process and save the specification string.
 
3694
     */
 
3695
 
 
3696
    if ((*lineP != '\0') &&     /* something follows */
 
3697
        (*lineP != '!')  &&     /* skip if we have the ! WmFunction */
 
3698
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
3699
         /* skip label name for client command */
 
3700
        ((*lineP != '"') || (menuItem->wmFunction != F_InvokeCommand)) &&
 
3701
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
3702
        (*lineP != 'f')  &&
 
3703
        (*(lineP+1) != '.'))    /* skip if we have f.xxx WmFunction */
 
3704
    {
 
3705
        if (ParseKeyEvent(&lineP, &eventType, &keycode, &state))
 
3706
        {
 
3707
            if ((string = (String) XtMalloc 
 
3708
                 ((unsigned int) (lineP - *linePP + 1))) == NULL)
 
3709
            {
 
3710
                PWarning (((char *)GETMESSAGE(60, 15, "Insufficient memory for accelerator specification")));
 
3711
                status = FALSE;
 
3712
            }
 
3713
            else
 
3714
            /*
 
3715
             * Save the accelerator state and keycode.
 
3716
             * Process and save the accelerator text.
 
3717
             */
 
3718
            {
 
3719
                ProcessAccelText (*linePP, lineP, (unsigned char *) string);
 
3720
                menuItem->accelState = state;
 
3721
                menuItem->accelKeyCode = keycode;
 
3722
                menuItem->accelText = string;
 
3723
            }
 
3724
        }
 
3725
        else
 
3726
        {
 
3727
            PWarning (((char *)GETMESSAGE(60, 16, "Invalid accelerator specification")));
 
3728
            status = FALSE;
 
3729
        }
 
3730
 
 
3731
        *linePP = lineP;  /* consume the specification */
 
3732
    }
 
3733
 
 
3734
    return (status);
 
3735
 
 
3736
} /* END OF FUNCTION ParseWmAccelerator */
 
3737
 
 
3738
 
 
3739
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
3740
/*************************************<->*************************************
 
3741
 *
 
3742
 *  ParseMenuItemName (linePP, menuItem)
 
3743
 *
 
3744
 *
 
3745
 *  Description:
 
3746
 *  -----------
 
3747
 *  Parse a user defined client command menu item
 
3748
 *
 
3749
 *
 
3750
 *  Inputs:
 
3751
 *  ------
 
3752
 *  linePP   = pointer to current line buffer pointer.
 
3753
 *  menuItem = pointer to MenuItem structure
 
3754
 *
 
3755
 * 
 
3756
 *  Outputs:
 
3757
 *  -------
 
3758
 *  menuItem->label will have menu item name appended to it
 
3759
 *
 
3760
 *  Comments:
 
3761
 *  --------
 
3762
 *  This function attempts to find a menu item label string at the end
 
3763
 *  of the client command specification line. A menu item label string
 
3764
 *  must be delimited by double quotes. If found, the label string is
 
3765
 *  appended to the menuItem->label field, after being reallocated to
 
3766
 *  accommodate the new space requirement.
 
3767
 * 
 
3768
 *************************************<->***********************************/
 
3769
 
 
3770
static void ParseMenuItemName (unsigned char **linePP, MenuItem *menuItem)
 
3771
{
 
3772
    unsigned char *lineP, *endquote;
 
3773
#ifndef NO_MULTIBYTE
 
3774
    int chlen;
 
3775
#endif
 
3776
 
 
3777
    /* Skip past any whitespace */
 
3778
    ScanWhitespace (linePP);
 
3779
    lineP = *linePP;
 
3780
 
 
3781
    /* Look for a double quote */
 
3782
    if (
 
3783
#ifndef NO_MULTIBYTE
 
3784
        mblen ((char *)lineP, MB_CUR_MAX) == 1 &&
 
3785
#endif
 
3786
        *lineP == '"')
 
3787
    {
 
3788
        /* Move past the first quote. */
 
3789
        ++lineP;
 
3790
 
 
3791
        endquote = lineP;
 
3792
 
 
3793
        /* Search for closing quote */
 
3794
#ifndef NO_MULTIBYTE
 
3795
        while (*endquote != '\0' &&
 
3796
               (chlen = mblen ((char *)endquote, MB_CUR_MAX)) > 0 && 
 
3797
               (chlen > 1 || *endquote != '"'))
 
3798
        {
 
3799
            /* If we ran off the end of the line, then just abort. Bad
 
3800
               syntax. */
 
3801
            if ((chlen == 1 && *endquote == '\n') || *endquote == '\0') return;
 
3802
            endquote += chlen;
 
3803
        }
 
3804
        if (chlen < 0) return; /* invalid character */
 
3805
#else
 
3806
        while (*endquote != '\0' && *endquote != '"') {
 
3807
          if (*endquote == '\n' || *endquote == '\0') return;
 
3808
          endquote++;
 
3809
        }
 
3810
#endif
 
3811
 
 
3812
        /* Well, we have a valid menu item name. Store it in the 
 
3813
           client command name field. Don't include the double quotes. */
 
3814
        menuItem->clientCommandName =
 
3815
          XtMalloc(sizeof(char) * (endquote - lineP) + 1);
 
3816
        strncpy(menuItem->clientCommandName, (char *) lineP,
 
3817
                endquote - lineP);
 
3818
        menuItem->clientCommandName[strlen(menuItem->clientCommandName)+1] = '\0';
 
3819
    }
 
3820
    else
 
3821
    {
 
3822
        /* If there was no double quote, then just advance to the end
 
3823
           of the line. */
 
3824
#ifndef NO_MULTIBYTE
 
3825
        while (*lineP != '\0' && 
 
3826
               ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 1 ||
 
3827
                *lineP != '\n'))
 
3828
          lineP += chlen > 0 ? chlen : 1;
 
3829
#else
 
3830
        while (*lineP != '\0' && *lineP != '\n')
 
3831
          lineP++;
 
3832
#endif
 
3833
        *linePP = lineP;
 
3834
    }
 
3835
}
 
3836
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
3837
 
 
3838
 
 
3839
/*************************************<->*************************************
 
3840
 *
 
3841
 *  int
 
3842
 *  ParseWmFunction (linePP, res_spec, pWmFunction)
 
3843
 *
 
3844
 *
 
3845
 *  Description:
 
3846
 *  -----------
 
3847
 *  Parse a button, key, or menu function name and return its function table
 
3848
 *  index.
 
3849
 *
 
3850
 *
 
3851
 *  Inputs:
 
3852
 *  ------
 
3853
 *  linePP   = pointer to current line buffer pointer.
 
3854
 *  res_spec = resource specification type (key, button, or menu).
 
3855
 *  pWmFunction = pointer to window manager function destination.
 
3856
 *  functionTable = window manager function parse table
 
3857
 *
 
3858
 * 
 
3859
 *  Outputs:
 
3860
 *  -------
 
3861
 *  linePP   = pointer to revised line buffer pointer.
 
3862
 *  pWmFunction = pointer to parsed window manager function.
 
3863
 *  Return = function table index of parsed function.
 
3864
 *
 
3865
 *
 
3866
 *  Comments:
 
3867
 *  --------
 
3868
 *  Uses F_Nop if the function name or resource type is invalid.
 
3869
 * 
 
3870
 *************************************<->***********************************/
 
3871
 
 
3872
int ParseWmFunction (unsigned char **linePP, unsigned int res_spec, 
 
3873
                            WmFunction *pWmFunction)
 
3874
{
 
3875
    unsigned char *lineP = *linePP;
 
3876
    unsigned char *string;
 
3877
    register int  low, mid, high, cmp;
 
3878
 
 
3879
    /*
 
3880
     * Skip leading white space.
 
3881
     */
 
3882
    ScanWhitespace (&lineP);
 
3883
 
 
3884
    /* 
 
3885
     * Have function string (may be NULL or a comment).
 
3886
     * Handle the special case of '!' 
 
3887
     */
 
3888
 
 
3889
    if (*lineP == '!')
 
3890
    {
 
3891
        *linePP = ++lineP;
 
3892
        *pWmFunction = F_Exec;
 
3893
        return (F_EXEC_INDEX);
 
3894
    }
 
3895
 
 
3896
    /*
 
3897
     * Identify the function corresponding to the specified name.
 
3898
     * Try binary search of the window manager function parse table.
 
3899
     * Assume f.nop if the function and resource type cannot be matched.
 
3900
     * This handles NULL and comment strings, bad function names, and functions
 
3901
     *   in inappropriate resource sets.
 
3902
     */
 
3903
    string = GetString (&lineP);
 
3904
    *linePP = lineP;
 
3905
 
 
3906
    if (string != NULL)
 
3907
    {
 
3908
        ToLower (string);
 
3909
        low = 0;
 
3910
        high = WMFUNCTIONTABLESIZE - 1;
 
3911
 
 
3912
        while (low <= high)
 
3913
        {
 
3914
            mid = (low + high)/2;
 
3915
            cmp = strcmp (functionTable[mid].funcName, (char *)string);
 
3916
 
 
3917
            if (!cmp)
 
3918
            /*
 
3919
             * Function name match 
 
3920
             * Require proper resource type for the function.
 
3921
             */
 
3922
            {
 
3923
                if (res_spec & functionTable[mid].resource)
 
3924
                {
 
3925
                    *pWmFunction = functionTable[mid].wmFunction;
 
3926
                    return (mid);
 
3927
                }
 
3928
 
 
3929
                /* invalid resource:  use F_Nop */
 
3930
                break;
 
3931
            }
 
3932
 
 
3933
            /*
 
3934
             * Function name mismatch 
 
3935
             */
 
3936
            if (cmp > 0)
 
3937
            {
 
3938
                high = mid - 1;
 
3939
            }
 
3940
            else
 
3941
            {
 
3942
                low = mid + 1;
 
3943
            }
 
3944
        }
 
3945
    }
 
3946
 
 
3947
    /* 
 
3948
     * Not found:  assume f.nop
 
3949
     */
 
3950
    *pWmFunction = F_Nop;
 
3951
    return (F_NOP_INDEX);
 
3952
 
 
3953
} /* END OF FUNCTION ParseWmFunction */
 
3954
 
 
3955
 
 
3956
/*************************************<->*************************************
 
3957
 *
 
3958
 *  ParseWmFuncMaybeStrArg (linePP, wmFunction, pArgs)
 
3959
 *
 
3960
 *
 
3961
 *  Description:
 
3962
 *  -----------
 
3963
 *  Parses a window manager function with a null or string argument.
 
3964
 *
 
3965
 *
 
3966
 *  Inputs:
 
3967
 *  ------
 
3968
 *  linePP   = pointer to current line buffer pointer.
 
3969
 *  wmFunction = function (not used).
 
3970
 *  pArgs = pointer to argument destination.
 
3971
 *
 
3972
 * 
 
3973
 *  Outputs:
 
3974
 *  -------
 
3975
 *  linePP   = pointer to revised line buffer pointer.
 
3976
 *  pArgs    = pointer to parsed argument string.
 
3977
 *  Return   = FALSE iff insufficient memory
 
3978
 *
 
3979
 *
 
3980
 *  Comments:
 
3981
 *  --------
 
3982
 *  Only used to parse arguments for F_Lower, F_Raise, and F_Raise_Lower.
 
3983
 *  If it is used for any other function, be sure to change FreeMenuItem ()
 
3984
 *  accordingly.
 
3985
 * 
 
3986
 *************************************<->***********************************/
 
3987
 
 
3988
#ifndef PANELIST
 
3989
static
 
3990
#endif 
 
3991
Boolean ParseWmFuncMaybeStrArg (unsigned char **linePP, 
 
3992
                                       WmFunction wmFunction, String *pArgs)
 
3993
{
 
3994
    unsigned char *string = *linePP;
 
3995
    unsigned int  len;
 
3996
 
 
3997
    ScanWhitespace (&string);
 
3998
/*
 
3999
    if (*lineP == '-')
 
4000
    {
 
4001
        *linePP = ++lineP;
 
4002
        return (ParseWmFuncStrArg (linePP, wmFunction, pArgs));
 
4003
    }
 
4004
*/
 
4005
#ifdef PANELIST
 
4006
#if 0
 
4007
    else if (*lineP == '"' && *(lineP+1) == '-')
 
4008
    {
 
4009
        /* kill off '-' */
 
4010
        strcpy ((char *) (lineP+1), (char *) (lineP+2));
 
4011
        return (ParseWmFuncStrArg (linePP, wmFunction, pArgs));
 
4012
    }
 
4013
#endif
 
4014
#endif /* PANELIST */
 
4015
    if ((len = strlen ((char *)string)) != 0)
 
4016
    {
 
4017
        if ((*pArgs = (String)XtMalloc (len + 1)) == NULL)
 
4018
        {
 
4019
            PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory")));
 
4020
            return (FALSE);
 
4021
        }
 
4022
        strcpy (*pArgs, (char *)string);
 
4023
        return (TRUE);
 
4024
    }
 
4025
    else
 
4026
    /* Do ParseWmFuncNoArg () */
 
4027
    {
 
4028
        *pArgs = NULL;
 
4029
        return (TRUE);
 
4030
    }
 
4031
 
 
4032
} /* END OF FUNCTION ParseWmFuncMaybeStrArg */
 
4033
 
 
4034
 
 
4035
/*************************************<->*************************************
 
4036
 *
 
4037
 *  ParseWmFuncNoArg (linePP, wmFunction, pArgs)
 
4038
 *
 
4039
 *
 
4040
 *  Description:
 
4041
 *  -----------
 
4042
 *  Parses a window manager function null argument.
 
4043
 *
 
4044
 *
 
4045
 *  Inputs:
 
4046
 *  ------
 
4047
 *  linePP   = pointer to current line buffer pointer.
 
4048
 *  wmFunction = function (not used).
 
4049
 *  pArgs = pointer to argument destination.
 
4050
 *
 
4051
 * 
 
4052
 *  Outputs:
 
4053
 *  -------
 
4054
 *  linePP   = unchanged
 
4055
 *  pArgs    = NULL
 
4056
 *  Return   = TRUE
 
4057
 *
 
4058
 *
 
4059
 *  Comments:
 
4060
 *  --------
 
4061
 *  None.
 
4062
 * 
 
4063
 *************************************<->***********************************/
 
4064
 
 
4065
static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction,
 
4066
                                 String *pArgs)
 
4067
{
 
4068
 
 
4069
    *pArgs = NULL;
 
4070
    return (TRUE);
 
4071
 
 
4072
} /* END OF FUNCTION ParseWmFuncNoArg */
 
4073
 
 
4074
 
 
4075
/*************************************<->*************************************
 
4076
 *
 
4077
 *  ParseWmFuncStrArg (linePP, wmFunction, pArgs)
 
4078
 *
 
4079
 *
 
4080
 *  Description:
 
4081
 *  -----------
 
4082
 *  Parses a window manager function string argument.
 
4083
 *
 
4084
 *
 
4085
 *  Inputs:
 
4086
 *  ------
 
4087
 *  linePP   = pointer to current line buffer pointer.
 
4088
 *  wmFunction = function for which the argument string is intended.
 
4089
 *  pArgs = pointer to argument string destination.
 
4090
 *
 
4091
 * 
 
4092
 *  Outputs:
 
4093
 *  -------
 
4094
 *  linePP   = pointer to revised line buffer pointer.
 
4095
 *  pArgs    = pointer to parsed argument string.
 
4096
 *  Return   = FALSE iff insufficient memory
 
4097
 *
 
4098
 *
 
4099
 *  Comments:
 
4100
 *  --------
 
4101
 *  Insures that an argument for F_Exec() ends in '&' .
 
4102
 *  Only used to parse arguments for F_Exec, F_Menu, F_Lower, F_Raise, 
 
4103
 *  F_Raise_Lower, and F_Screen.  If it is used for any other function, be
 
4104
 *  sure to change FreeMenuItem () accordingly.
 
4105
 * 
 
4106
 *************************************<->***********************************/
 
4107
 
 
4108
#ifndef PANELIST
 
4109
static
 
4110
#endif
 
4111
Boolean ParseWmFuncStrArg (unsigned char **linePP, 
 
4112
                                  WmFunction wmFunction, String *pArgs)
 
4113
{
 
4114
    unsigned char *string;
 
4115
    unsigned int  len;
 
4116
#ifndef NO_MULTIBYTE
 
4117
    char *p;
 
4118
    wchar_t last;
 
4119
    char delim;
 
4120
    wchar_t wdelim;
 
4121
    int lastlen;
 
4122
#endif
 
4123
 
 
4124
    if ((string = GetString (linePP)) != NULL)
 
4125
    /* nonNULL string argument */
 
4126
    {
 
4127
        len = strlen ((char *)string);
 
4128
        if ((*pArgs = (String)XtMalloc (len + 2)) == NULL)
 
4129
        {
 
4130
            PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory")));
 
4131
            return (FALSE);
 
4132
        }
 
4133
        strcpy (*pArgs, (char *)string);
 
4134
 
 
4135
        /*
 
4136
         *  Insure that an argument for F_Exec ends in '&' .
 
4137
         */
 
4138
 
 
4139
#ifndef NO_MULTIBYTE
 
4140
        if ((wmFunction == F_Exec))
 
4141
        {
 
4142
            lastlen = 0;
 
4143
            p = *pArgs;
 
4144
            while (*p &&
 
4145
                   ((len = mblen(p, MB_CUR_MAX)) > 0))
 
4146
            {
 
4147
                mbtowc(&last, p, MB_CUR_MAX);
 
4148
                lastlen = len;
 
4149
                p += len;
 
4150
            }
 
4151
            delim = '&';
 
4152
            mbtowc(&wdelim, &delim, MB_CUR_MAX);
 
4153
            if (lastlen == 1 && last != wdelim)
 
4154
            {
 
4155
                *p++ = '&';
 
4156
                *p   = '\0';
 
4157
            }
 
4158
        }
 
4159
#else
 
4160
        if ((wmFunction == F_Exec) && ((*pArgs)[len - 1] != '&'))
 
4161
        {
 
4162
            (*pArgs)[len] = '&';
 
4163
            (*pArgs)[len + 1] = '\0';
 
4164
        }
 
4165
#endif
 
4166
    }
 
4167
    else
 
4168
    /* NULL string argument */
 
4169
    {
 
4170
        *pArgs = NULL;
 
4171
    }
 
4172
 
 
4173
    return (TRUE);
 
4174
 
 
4175
} /* END OF FUNCTION ParseWmFuncStrArg */
 
4176
 
 
4177
 
 
4178
/*************************************<->*************************************
 
4179
 *
 
4180
 *  FreeMenuItem (menuItem)
 
4181
 *
 
4182
 *
 
4183
 *  Description:
 
4184
 *  -----------
 
4185
 *  This procedure destroys a MenuItem structure.
 
4186
 *
 
4187
 *
 
4188
 *  Inputs:
 
4189
 *  ------
 
4190
 *  menuItem = to be destroyed.
 
4191
 *
 
4192
 * 
 
4193
 *  Outputs:
 
4194
 *  -------
 
4195
 *  None.
 
4196
 *
 
4197
 *
 
4198
 *  Comments:
 
4199
 *  --------
 
4200
 *  Assumes that ParseWmFuncStrArg () has parsed a menu item's function
 
4201
 *  argument only for F_Exec, F_Menu, F_Lower, F_Raise, F_Raise_Lower, and
 
4202
 *  F_Screen. If it is used for other functions, be sure to include them here!
 
4203
 * 
 
4204
 *************************************<->***********************************/
 
4205
 
 
4206
void FreeMenuItem (MenuItem *menuItem)
 
4207
{
 
4208
    if (menuItem->label != NULL)
 
4209
    {
 
4210
        XtFree ((char *)menuItem->label);
 
4211
    }
 
4212
 
 
4213
    if (menuItem->accelText != NULL)
 
4214
    {
 
4215
        XtFree ((char *)menuItem->accelText);
 
4216
    }
 
4217
 
 
4218
    /*
 
4219
     * If menuItem->wmFuncArgs is nonNULL, we assume that it is a string that
 
4220
     * was malloc'ed in ParseWmFuncStrArg () and we free it now.
 
4221
     */
 
4222
    if ((menuItem->wmFuncArgs != NULL) &&
 
4223
        ((menuItem->wmFunction == F_Exec)  || 
 
4224
         (menuItem->wmFunction == F_Menu)  || 
 
4225
         (menuItem->wmFunction == F_Lower) || 
 
4226
         (menuItem->wmFunction == F_Raise) || 
 
4227
         (menuItem->wmFunction == F_Raise_Lower) ||
 
4228
         (menuItem->wmFunction == F_Screen)))
 
4229
    {
 
4230
        XtFree ((char *)menuItem->wmFuncArgs);
 
4231
    }
 
4232
 
 
4233
    if (menuItem->clientCommandName != NULL)
 
4234
    {
 
4235
        XtFree ((char *) menuItem->clientCommandName);
 
4236
    }
 
4237
 
 
4238
    XtFree ((char *)menuItem);
 
4239
 
 
4240
} /* END OF FUNCTION FreeMenuItem */
 
4241
 
 
4242
 
 
4243
 
 
4244
/*************************************<->*************************************
 
4245
 *
 
4246
 *  ParseWmFuncGrpArg (linePP, wmFunction, pGroup)
 
4247
 *
 
4248
 *
 
4249
 *  Description:
 
4250
 *  -----------
 
4251
 *  Parses a window manager function group argument.
 
4252
 *
 
4253
 *
 
4254
 *  Inputs:
 
4255
 *  ------
 
4256
 *  linePP   = pointer to current line buffer pointer.
 
4257
 *  wmFunction = function for which the group argument is intended.
 
4258
 *  pGroup = pointer to group argument destination.
 
4259
 *
 
4260
 * 
 
4261
 *  Outputs:
 
4262
 *  -------
 
4263
 *  linePP   = pointer to revised line buffer pointer.
 
4264
 *  pGroup    = pointer to parsed group argument.
 
4265
 *  Return   = FALSE iff invalid group argument.
 
4266
 *
 
4267
 *
 
4268
 *  Comments:
 
4269
 *  --------
 
4270
 *  The only valid nonNULL arguments are "icon", "window", and "transient".
 
4271
 * 
 
4272
 *************************************<->***********************************/
 
4273
 
 
4274
static Boolean ParseWmFuncGrpArg (unsigned char **linePP, 
 
4275
                                  WmFunction wmFunction, GroupArg *pGroup)
 
4276
{
 
4277
    unsigned char  *lineP = *linePP;
 
4278
    unsigned char  *startP;
 
4279
    unsigned char   grpStr[MAX_GROUP_STRLEN+1];
 
4280
    int    len;
 
4281
 
 
4282
 
 
4283
    /*
 
4284
     * Parse groups while each is followed by "|".
 
4285
     */
 
4286
 
 
4287
    *pGroup = 0;
 
4288
    while (1)
 
4289
    {
 
4290
        /* 
 
4291
         * Skip whitespace and find next group string.
 
4292
         */
 
4293
 
 
4294
        ScanWhitespace (&lineP);
 
4295
        startP = lineP;
 
4296
        ScanAlphanumeric (&lineP);
 
4297
        if (startP == lineP)
 
4298
        /* Group missing => use default or complain */
 
4299
        {
 
4300
            if (*pGroup)
 
4301
            {
 
4302
                PWarning (((char *)GETMESSAGE(60, 18, "Missing group specification")));
 
4303
                return (FALSE);
 
4304
            }
 
4305
            else
 
4306
            {
 
4307
                *pGroup = F_GROUP_DEFAULT;
 
4308
                break;
 
4309
            }
 
4310
        }
 
4311
 
 
4312
        /*
 
4313
         * Found a group string; compare it with valid groups.
 
4314
         */
 
4315
 
 
4316
        len = min (lineP - startP, MAX_GROUP_STRLEN);
 
4317
        (void) strncpy ((char *)grpStr, (char *)startP, len);
 
4318
        grpStr[len] = '\0';
 
4319
        ToLower (grpStr);
 
4320
 
 
4321
        if (!strcmp ("icon", (char *)grpStr))
 
4322
        {
 
4323
            *pGroup |= F_GROUP_ICON;
 
4324
        }
 
4325
        else if (!strcmp ("window", (char *)grpStr))
 
4326
        {
 
4327
            *pGroup |= F_GROUP_WINDOW;
 
4328
        }
 
4329
        else if (!strcmp ("transient", (char *)grpStr))
 
4330
        {
 
4331
            *pGroup |= F_GROUP_TRANSIENT;
 
4332
        }
 
4333
        else 
 
4334
        /* Unknown group name */
 
4335
        {
 
4336
            PWarning (((char *)GETMESSAGE(60, 19, "Invalid group specification")));
 
4337
            return (FALSE);
 
4338
        }
 
4339
 
 
4340
        /*
 
4341
         *  Continue processing until the line is exhausted.
 
4342
         *  Skip any '|' .
 
4343
         */
 
4344
 
 
4345
        ScanWhitespace (&lineP);
 
4346
 
 
4347
        if (lineP == NULL || *lineP == '\0')
 
4348
        {
 
4349
            break; 
 
4350
        }
 
4351
        else if (*lineP == '|')
 
4352
        {
 
4353
            lineP++;
 
4354
        }
 
4355
    }
 
4356
 
 
4357
    *linePP = lineP;
 
4358
    return (TRUE);
 
4359
 
 
4360
} /* END OF FUNCTION ParseWmFuncGrpArg */
 
4361
 
 
4362
 
 
4363
 
 
4364
/*************************************<->*************************************
 
4365
 *
 
4366
 *  ParseWmFuncNbrArg (linePP, wmFunction, pNumber)
 
4367
 *
 
4368
 *
 
4369
 *  Description:
 
4370
 *  -----------
 
4371
 *  Parses a window manager function number argument.
 
4372
 *
 
4373
 *
 
4374
 *  Inputs:
 
4375
 *  ------
 
4376
 *  linePP   = pointer to current line buffer pointer.
 
4377
 *  wmFunction = function 
 
4378
 *  pNumber = pointer to number argument destination.
 
4379
 *
 
4380
 * 
 
4381
 *  Outputs:
 
4382
 *  -------
 
4383
 *  linePP   = pointer to revised line buffer pointer.
 
4384
 *  pNumber  = pointer to parsed number argument.
 
4385
 *  Return   = FALSE iff invalid number argument.
 
4386
 *
 
4387
 *
 
4388
 *  Comments:
 
4389
 *  --------
 
4390
 *  None.
 
4391
 * 
 
4392
 *************************************<->***********************************/
 
4393
 
 
4394
static Boolean ParseWmFuncNbrArg (unsigned char **linePP, 
 
4395
                                  WmFunction wmFunction, 
 
4396
                                  unsigned long *pNumber)
 
4397
{
 
4398
    int  val;
 
4399
 
 
4400
    val = StrToNum (GetString (linePP));
 
4401
    if (val == -1)
 
4402
    {
 
4403
        PWarning (((char *)GETMESSAGE(60, 20, "Invalid number specification")));
 
4404
        *pNumber = 0;
 
4405
        return (FALSE);
 
4406
    }
 
4407
 
 
4408
    *pNumber = val;
 
4409
    return (TRUE);
 
4410
 
 
4411
} /* END OF FUNCTION ParseWmFuncNbrArg */
 
4412
 
 
4413
 
 
4414
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
4415
/*************************************<->*************************************
 
4416
 *
 
4417
 *  ParseWmFuncCCIArgs (linePP, wmFunction, pArgs)
 
4418
 *
 
4419
 *
 
4420
 *  Description:
 
4421
 *  -----------
 
4422
 *  Parses a Client-Command entry's arguments.
 
4423
 *
 
4424
 *
 
4425
 *  Inputs:
 
4426
 *  ------
 
4427
 *  linePP   = pointer to current line buffer pointer.
 
4428
 *  wmFunction = function for which the argument string is intended.
 
4429
 *  pArgs = pointer to argument string destination.
 
4430
 *
 
4431
 * 
 
4432
 *  Outputs:
 
4433
 *  -------
 
4434
 *  linePP   = pointer to revised line buffer pointer.
 
4435
 *  pArgs    = pointer to parsed argument string.
 
4436
 *  Return   = FALSE iff insufficient memory
 
4437
 *
 
4438
 *
 
4439
 *  Comments:
 
4440
 *  --------
 
4441
 *  None.
 
4442
 * 
 
4443
 *************************************<->***********************************/
 
4444
 
 
4445
static Boolean ParseWmFuncCCIArgs (unsigned char **linePP, 
 
4446
                                   WmFunction wmFunction, String *pArgs)
 
4447
{
 
4448
  /*
 
4449
   * Format:
 
4450
   *    cci_func_args:
 
4451
   *         cci_entry
 
4452
   *         modifier cci_entry_list
 
4453
   *
 
4454
   *    cci_entry_list:
 
4455
   *         cci_entry
 
4456
   *         cci_entry . cci_entry
 
4457
   *
 
4458
   *    cci_entry:
 
4459
   *         '<' cci_label '>'
 
4460
   *
 
4461
   *    cci_label:
 
4462
   *         any combination of alpha and '_'
 
4463
   */
 
4464
 
 
4465
  CCIEntryModifier  mod;
 
4466
  CCIFuncArg      *cciArg;
 
4467
  unsigned char   *string;
 
4468
 
 
4469
 
 
4470
  cciArg = XtNew(CCIFuncArg);
 
4471
 
 
4472
  if ((string = GetString(linePP)) == NULL)
 
4473
    {
 
4474
      /* Error - no data for f.cci command. cci_entry_list is required. */
 
4475
      fprintf(stderr, "Incorrect format for f.cci command.\n");
 
4476
      return (FALSE);
 
4477
    }
 
4478
  else
 
4479
    {
 
4480
      /* check if no modifier was specified. */
 
4481
      if (string[0] == '<')
 
4482
        {
 
4483
          cciArg->mod      = NONE;
 
4484
          cciArg->cciEntry = XtNewString((char*)string);
 
4485
        }
 
4486
      else
 
4487
        {
 
4488
          if (! GetCCIModifier((String)string, &mod))
 
4489
            {
 
4490
              cciArg->mod      = NONE;
 
4491
              cciArg->cciEntry = XtNewString("");
 
4492
            }
 
4493
          else
 
4494
            {
 
4495
              cciArg->mod = mod;
 
4496
 
 
4497
              if ((string = GetString(linePP)) == NULL)
 
4498
                {
 
4499
                  /* Found a modifier, but there's no cci_entry_list. */
 
4500
                  fprintf(stderr, "Incorrect format for f.cci command.\n");
 
4501
                  return(FALSE);
 
4502
                }
 
4503
              else
 
4504
                {
 
4505
                  cciArg->cciEntry = XtNewString((char*)string);
 
4506
                }
 
4507
            }
 
4508
        }
 
4509
 
 
4510
      *pArgs = (String)cciArg;
 
4511
    }
 
4512
 
 
4513
  return(TRUE);
 
4514
} /* END OF FUNCTION ParseWmFuncCCIArgs */
 
4515
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
4516
 
 
4517
 
 
4518
/*************************************<->*************************************
 
4519
 *
 
4520
 *  ParseButtonStr ()
 
4521
 *
 
4522
 *
 
4523
 *  Description:
 
4524
 *  -----------
 
4525
 *  This function parses a button set specification string:
 
4526
 *
 
4527
 *     bindings_name
 
4528
 *     {
 
4529
 *       button   context   function
 
4530
 *       button   context   function
 
4531
 *                 ...
 
4532
 *       button   context   function
 
4533
 *     }
 
4534
 *
 
4535
 *
 
4536
 *
 
4537
 *  Inputs:
 
4538
 *  ------
 
4539
 *  pSD->buttonBindings = buttonBindings resource value
 
4540
 *  functionTable = window manager function parse table
 
4541
 *
 
4542
 * 
 
4543
 *  Outputs:
 
4544
 *  -------
 
4545
 *  pSD->buttonSpecs = list of button binding specifications.
 
4546
 *
 
4547
 *
 
4548
 *  Comments:
 
4549
 *  --------
 
4550
 *  The button set specification name must match pSD->buttonBindings.
 
4551
 * 
 
4552
 *************************************<->***********************************/
 
4553
 
 
4554
void ParseButtonStr (WmScreenData *pSD, unsigned char *buttonStr)
 
4555
{
 
4556
    unsigned char *lineP;
 
4557
 
 
4558
    cfileP = NULL;
 
4559
    linec = 0;
 
4560
    if (((parseP = buttonStr) != NULL) && (GetNextLine () != NULL))
 
4561
    {
 
4562
        lineP = line;
 
4563
        ParseButtonSet (pSD, lineP);
 
4564
    }
 
4565
 
 
4566
} /* END OF FUNCTION ParseButtonStr */
 
4567
 
 
4568
 
 
4569
/*************************************<->*************************************
 
4570
 *
 
4571
 *  ParseButtonSet (pSD, lineP)
 
4572
 *
 
4573
 *
 
4574
 *  Description:
 
4575
 *  -----------
 
4576
 *  Button set specification found.  Parse the following syntax:
 
4577
 *
 
4578
 *             v
 
4579
 *     Buttons bindings_name
 
4580
 *     {
 
4581
 *       button   context   function
 
4582
 *       button   context   function
 
4583
 *                 ...
 
4584
 *       button   context   function
 
4585
 *     }
 
4586
 *
 
4587
 *
 
4588
 *  Inputs:
 
4589
 *  ------
 
4590
 *  cfileP = (global) file pointer to fopened configuration file or NULL
 
4591
 *  line =  (global) line buffer
 
4592
 *  lineP = pointer to current character in line buffer
 
4593
 *  pSD->buttonBindings = buttonBindings resource value
 
4594
 *
 
4595
 * 
 
4596
 *  Outputs:
 
4597
 *  -------
 
4598
 *  lineP = pointer to current character in line buffer
 
4599
 *  pSD->buttonSpecs = list of button binding specifications.
 
4600
 *
 
4601
 *
 
4602
 *  Comments:
 
4603
 *  --------
 
4604
 *  Skips unnamed button binding set and sets with names that don't match
 
4605
 *  the buttonBindings resource.
 
4606
 *  Skips bad button binding specifications.
 
4607
 * 
 
4608
 *************************************<->***********************************/
 
4609
 
 
4610
static void ParseButtonSet (WmScreenData *pSD, unsigned char *lineP)
 
4611
{
 
4612
    unsigned char *string;
 
4613
    ButtonSpec    *buttonSpec;
 
4614
    ButtonSpec    *lastButtonSpec;
 
4615
    int            ix;
 
4616
    
 
4617
    /*
 
4618
     * Parse the button set bindings from the configuration file.
 
4619
     * If either the button set name or buttonBindings resource is NULL or 
 
4620
     *   they don't match, then skip this button specification.
 
4621
     */
 
4622
 
 
4623
    if (((string = GetString (&lineP)) == NULL) ||
 
4624
        (pSD->buttonBindings == NULL) ||
 
4625
        strcmp ((char *)string, pSD->buttonBindings))
 
4626
    {
 
4627
        return;
 
4628
    }
 
4629
 
 
4630
    /* 
 
4631
     * Require leading '{' on the next line.
 
4632
     */
 
4633
    while ((GetNextLine () != NULL))  /* not EOF nor read error */
 
4634
    {
 
4635
        lineP = line;
 
4636
        ScanWhitespace(&lineP);
 
4637
 
 
4638
        if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
 
4639
        /* ignore empty or comment line */
 
4640
        {
 
4641
            continue;
 
4642
        }
 
4643
 
 
4644
        if (*lineP == '{')
 
4645
        /* found '{' */
 
4646
        {
 
4647
            break;
 
4648
        }
 
4649
 
 
4650
        /* not a '{' */
 
4651
        PWarning (((char *)GETMESSAGE(60, 21, "Expected '{' after button set name")));
 
4652
        return;
 
4653
    }
 
4654
 
 
4655
    /*
 
4656
     * Found leading "{" or EOF.
 
4657
     * Prepare to accumulate button bindings by finding the end of
 
4658
     *   the button specification list.
 
4659
     * lastButtonSpec will be NULL only if no prior bindings exist.
 
4660
     */
 
4661
 
 
4662
    lastButtonSpec = pSD->buttonSpecs;
 
4663
    if (lastButtonSpec != NULL)
 
4664
    {
 
4665
        while (lastButtonSpec->nextButtonSpec != NULL)
 
4666
        {
 
4667
            lastButtonSpec = (lastButtonSpec->nextButtonSpec);
 
4668
        }
 
4669
    }
 
4670
 
 
4671
    /*
 
4672
     * Parse "button context function"  until "}" or EOF found.
 
4673
     * Skips bad button binding specifications.
 
4674
     */
 
4675
 
 
4676
    while ((GetNextLine () != NULL))  /* not EOF nor read error */
 
4677
    {
 
4678
        lineP = line;
 
4679
        ScanWhitespace(&lineP);
 
4680
        if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
 
4681
        /* ignore empty or comment lines */
 
4682
        {
 
4683
            continue;
 
4684
        }
 
4685
        if (*lineP == '}')  /* finished with button set */
 
4686
        {
 
4687
            break;
 
4688
        }
 
4689
 
 
4690
        /*
 
4691
         * Allocate space for the button binding specification. 
 
4692
         */
 
4693
        if ((buttonSpec = (ButtonSpec *)XtMalloc (sizeof (ButtonSpec))) == NULL)
 
4694
        {
 
4695
            PWarning (((char *)GETMESSAGE(60, 22, "Insufficient memory for button specification")));
 
4696
            continue;
 
4697
        }
 
4698
        buttonSpec->wmFunction = (WmFunction)NULL;
 
4699
        buttonSpec->wmFuncArgs = NULL;
 
4700
        buttonSpec->nextButtonSpec = NULL;
 
4701
 
 
4702
        /*
 
4703
         * Parse the button specification "button".
 
4704
         */
 
4705
        lineP = line;
 
4706
        if (!ParseBtnEvent(&lineP,
 
4707
                           &buttonSpec->eventType,
 
4708
                           &buttonSpec->button,
 
4709
                           &buttonSpec->state,
 
4710
                           &buttonSpec->click))
 
4711
        {
 
4712
            PWarning (((char *)GETMESSAGE(60, 23, "Invalid button specification")));
 
4713
            XtFree ((char *)buttonSpec);
 
4714
            continue;  /* skip this button specification */
 
4715
        }
 
4716
 
 
4717
 
 
4718
        /*
 
4719
         * Parse the button context.
 
4720
         */
 
4721
        if (!ParseContext(&lineP, &buttonSpec->context, 
 
4722
                          &buttonSpec->subContext))
 
4723
        {
 
4724
            PWarning (((char *)GETMESSAGE(60, 24, "Invalid button context")));
 
4725
            XtFree ((char *)buttonSpec);
 
4726
            continue;  /* skip this button specification */
 
4727
        }
 
4728
 
 
4729
        /*
 
4730
         * Parse the button function and any arguments.
 
4731
         */
 
4732
 
 
4733
        ix = ParseWmFunction (&lineP, CRS_BUTTON, &buttonSpec->wmFunction);
 
4734
 
 
4735
        /*
 
4736
         * remove any subContexts that don't apply to this function
 
4737
         */
 
4738
 
 
4739
        if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) &&
 
4740
            (buttonSpec->subContext & F_SUBCONTEXT_IB_IICON))
 
4741
        {
 
4742
            buttonSpec->subContext &= ~F_SUBCONTEXT_IB_IICON;
 
4743
        }
 
4744
 
 
4745
        if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) &&
 
4746
            (buttonSpec->subContext & F_SUBCONTEXT_IB_WICON))
 
4747
        {
 
4748
            buttonSpec->subContext &= ~F_SUBCONTEXT_IB_WICON;
 
4749
        }
 
4750
 
 
4751
        /*
 
4752
         * Map Button3 menus to BMenu virtual button
 
4753
         */
 
4754
        if (buttonSpec->button == Button3 && 
 
4755
           (buttonSpec->wmFunction == F_Menu ||
 
4756
            buttonSpec->wmFunction == F_Post_SMenu)) {
 
4757
 
 
4758
            buttonSpec->button = wmGD.bMenuButton;
 
4759
        }
 
4760
 
 
4761
        /* 
 
4762
         * Apply the function argument parser.
 
4763
         */
 
4764
        if (!(*(functionTable [ix].parseProc)) 
 
4765
                   (&lineP, buttonSpec->wmFunction, &buttonSpec->wmFuncArgs))
 
4766
        {
 
4767
            XtFree ((char *)buttonSpec);
 
4768
            continue;  /* skip this button specification */
 
4769
        }
 
4770
 
 
4771
        /* 
 
4772
         * Add the button specification to the button specification list.
 
4773
         */
 
4774
        if (lastButtonSpec != NULL)
 
4775
        /* a prior specification exists */
 
4776
        {
 
4777
            lastButtonSpec->nextButtonSpec = buttonSpec;
 
4778
        }
 
4779
        else
 
4780
        {
 
4781
            pSD->buttonSpecs = buttonSpec;
 
4782
        }
 
4783
        lastButtonSpec = buttonSpec;
 
4784
    }
 
4785
 
 
4786
} /* END OF FUNCTION ParseButtonSet */
 
4787
 
 
4788
 
 
4789
 
 
4790
/*************************************<->*************************************
 
4791
 *
 
4792
 *  ParseContext (linePP, context, subContext)
 
4793
 *
 
4794
 *
 
4795
 *  Description:
 
4796
 *  -----------
 
4797
 *  Parses a general context string.
 
4798
 *
 
4799
 *
 
4800
 *  Inputs:
 
4801
 *  ------
 
4802
 *  linePP =  pointer to current line buffer pointer.
 
4803
 * 
 
4804
 *  Outputs:
 
4805
 *  -------
 
4806
 *  linePP =  pointer to revised line buffer pointer.
 
4807
 *  context =    context field value
 
4808
 *  subContext = subContext field value
 
4809
 *  Return = (Boolean) true iff valid context string
 
4810
 *
 
4811
 *
 
4812
 *  Comments:
 
4813
 *  --------
 
4814
 *  None.
 
4815
 * 
 
4816
 *************************************<->***********************************/
 
4817
 
 
4818
static Boolean ParseContext (unsigned char **linePP, Context *context, 
 
4819
                             Context *subContext)
 
4820
{
 
4821
    unsigned char   *lineP = *linePP;
 
4822
    unsigned char   *startP;
 
4823
    unsigned char    ctxStr[MAX_CONTEXT_STRLEN+1];
 
4824
    int     len;
 
4825
 
 
4826
    /*
 
4827
     * Parse contexts while each is followed by "|".
 
4828
     */
 
4829
 
 
4830
    *context = 0;
 
4831
    *subContext = 0;
 
4832
    while (1) {
 
4833
 
 
4834
        /* 
 
4835
         * Skip whitespace and find next context string.
 
4836
         */
 
4837
        ScanWhitespace (&lineP);
 
4838
        startP = lineP;
 
4839
        ScanAlphanumeric (&lineP);
 
4840
        if (startP == lineP)
 
4841
        /* ERROR: Context missing */
 
4842
        {
 
4843
           return (FALSE);
 
4844
        }
 
4845
 
 
4846
        /*
 
4847
         * Found nonNULL string; compare it with valid contexts.
 
4848
         */
 
4849
 
 
4850
        len = min(lineP - startP, MAX_CONTEXT_STRLEN);
 
4851
        (void) strncpy ((char *)ctxStr, (char *)startP, len);
 
4852
        ctxStr[len] = '\0';
 
4853
        ToLower (ctxStr);
 
4854
 
 
4855
        if (!strcmp ("root", (char *)ctxStr))
 
4856
        {
 
4857
            *context |= F_CONTEXT_ROOT;
 
4858
            *subContext |= F_SUBCONTEXT_R_ALL;
 
4859
        }
 
4860
        else if (!strcmp ("icon", (char *)ctxStr))
 
4861
        {
 
4862
            *context |= (F_CONTEXT_ICON        |
 
4863
                         F_CONTEXT_ICONBOX     |
 
4864
                         F_SUBCONTEXT_IB_IICON | 
 
4865
                         F_SUBCONTEXT_IB_WICON );
 
4866
            *subContext |= (F_SUBCONTEXT_I_ALL    | 
 
4867
                            F_SUBCONTEXT_IB_IICON | 
 
4868
                            F_SUBCONTEXT_IB_WICON );
 
4869
        }
 
4870
        else if (!strcmp ("window", (char *)ctxStr))
 
4871
        {
 
4872
            *context |= F_CONTEXT_WINDOW;
 
4873
            *subContext |= F_SUBCONTEXT_W_ALL;
 
4874
        }
 
4875
        else if (!strcmp ("frame", (char *)ctxStr))
 
4876
        {
 
4877
            *context |= F_CONTEXT_WINDOW;
 
4878
            *subContext |= F_SUBCONTEXT_W_FRAME;
 
4879
        }
 
4880
        else if (!strcmp ("title", (char *)ctxStr))
 
4881
        {
 
4882
            *context |= F_CONTEXT_WINDOW;
 
4883
            *subContext |= F_SUBCONTEXT_W_TITLE;
 
4884
        }
 
4885
        else if (!strcmp ("border", (char *)ctxStr))
 
4886
        {
 
4887
            *context |= F_CONTEXT_WINDOW;
 
4888
            *subContext |= F_SUBCONTEXT_W_BORDER;
 
4889
        }
 
4890
        else if (!strcmp ("app", (char *)ctxStr))
 
4891
        {
 
4892
            *context |= F_CONTEXT_WINDOW;
 
4893
            *subContext |= F_SUBCONTEXT_W_APP;
 
4894
        }
 
4895
#ifdef WSM
 
4896
        else if (!strcmp ("ifkey", (char *)ctxStr))
 
4897
        {
 
4898
            *context |= F_CONTEXT_IFKEY;
 
4899
        }
 
4900
#endif /* WSM */
 
4901
        else 
 
4902
        /* Unknown context name */
 
4903
        {
 
4904
           return (FALSE);
 
4905
        }
 
4906
 
 
4907
        /* continue only if followed by '|' */
 
4908
        ScanWhitespace (&lineP);
 
4909
        if (*lineP != '|')
 
4910
        {
 
4911
            break; 
 
4912
        }
 
4913
        lineP++;
 
4914
    }
 
4915
 
 
4916
    *linePP = lineP;
 
4917
    return (TRUE);
 
4918
 
 
4919
} /* END OF FUNCTION ParseContext */
 
4920
 
 
4921
 
 
4922
/*************************************<->*************************************
 
4923
 *
 
4924
 *  ParseKeyStr ()
 
4925
 *
 
4926
 *
 
4927
 *  Description:
 
4928
 *  -----------
 
4929
 *  This function parses a key set specification string:
 
4930
 *
 
4931
 *     bindings_name
 
4932
 *     {
 
4933
 *        key   context   function
 
4934
 *        key   context   function
 
4935
 *                     ...
 
4936
 *        key   context   function
 
4937
 *     }
 
4938
 *
 
4939
 *
 
4940
 *  Inputs:
 
4941
 *  ------
 
4942
 *  pSD->keyBindings = keyBindings resource value
 
4943
 *  functionTable = window manager function parse table
 
4944
 *
 
4945
 * 
 
4946
 *  Outputs:
 
4947
 *  -------
 
4948
 *  pSD->keySpecs = list of key binding specification
 
4949
 *
 
4950
 *
 
4951
 *  Comments:
 
4952
 *  --------
 
4953
 *  The key set specification name must match pSD->keyBindings.
 
4954
 * 
 
4955
 *************************************<->***********************************/
 
4956
 
 
4957
void
 
4958
ParseKeyStr (WmScreenData *pSD, unsigned char *keyStr)
 
4959
{
 
4960
    unsigned char *lineP;
 
4961
 
 
4962
    cfileP = NULL;
 
4963
    linec = 0;
 
4964
    if (((parseP = keyStr) != NULL) && (GetNextLine () != NULL))
 
4965
    {
 
4966
        lineP = line;
 
4967
        ParseKeySet (pSD, lineP);
 
4968
    }
 
4969
 
 
4970
} /* END OF FUNCTION ParseKeyStr */
 
4971
 
 
4972
 
 
4973
 
 
4974
/*************************************<->*************************************
 
4975
 *
 
4976
 *  ParseKeySet (pSD, lineP)
 
4977
 *
 
4978
 *
 
4979
 *  Description:
 
4980
 *  -----------
 
4981
 *  Key set specification found.  Parse the following syntax:
 
4982
 *
 
4983
 *          v
 
4984
 *     Keys bindings_name
 
4985
 *     {
 
4986
 *        key   context   function
 
4987
 *        key   context   function
 
4988
 *                     ...
 
4989
 *        key   context   function
 
4990
 *     }
 
4991
 *
 
4992
 *
 
4993
 *  Inputs:
 
4994
 *  ------
 
4995
 *  cfileP = (global) file pointer to fopened configuration file or NULL
 
4996
 *  line =  (global) line buffer
 
4997
 *  lineP = pointer to current character in line buffer
 
4998
 *  pSD->keyBindings = keyBindings resource value
 
4999
 *
 
5000
 * 
 
5001
 *  Outputs:
 
5002
 *  -------
 
5003
 *  lineP = pointer to current character in line buffer
 
5004
 *  pSD->keySpecs = list of key binding specifications.
 
5005
 *
 
5006
 *
 
5007
 *  Comments:
 
5008
 *  --------
 
5009
 *  Skips unnamed key binding set and sets with names that don't match the 
 
5010
 *  keyBindings resource.
 
5011
 *  Skips bad key binding specifications.
 
5012
 * 
 
5013
 *************************************<->***********************************/
 
5014
 
 
5015
static void ParseKeySet (WmScreenData *pSD, unsigned char *lineP)
 
5016
{
 
5017
    unsigned char         *string;
 
5018
    KeySpec      *keySpec;
 
5019
    KeySpec      *lastKeySpec;
 
5020
    unsigned int  eventType;
 
5021
    int           ix;
 
5022
#ifdef WSM
 
5023
    Boolean     bBadKey;
 
5024
#endif /* WSM */
 
5025
    
 
5026
    /*
 
5027
     * Parse the key set bindings from the configuration file.
 
5028
     * If either the key set name or keyBindings resource is NULL or they
 
5029
     *   don't match then skip this key specification.
 
5030
     */
 
5031
 
 
5032
    if (((string = GetString (&lineP)) == NULL) ||
 
5033
        (pSD->keyBindings == NULL) ||
 
5034
        strcmp ((char *)string, pSD->keyBindings))
 
5035
    {
 
5036
        return;
 
5037
    }
 
5038
 
 
5039
    /*
 
5040
     * Require leading '{' on next line.
 
5041
     */
 
5042
    while ((GetNextLine () != NULL))  /* not EOF nor read error */
 
5043
    {
 
5044
        lineP = line;
 
5045
        ScanWhitespace(&lineP);
 
5046
 
 
5047
        if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
 
5048
        /* ignore empty or comment line */
 
5049
        {
 
5050
            continue;
 
5051
        }
 
5052
 
 
5053
        if (*lineP == '{')
 
5054
        /* found '{' */
 
5055
        {
 
5056
            break;
 
5057
        }
 
5058
 
 
5059
        /* not a '{' */
 
5060
        PWarning (((char *)GETMESSAGE(60, 25, "Expected '{' after key set name")));
 
5061
        return;
 
5062
    }
 
5063
 
 
5064
    /*
 
5065
     * Found leading "{" or EOF.
 
5066
     * Prepare to accumulate key bindings by finding the end of
 
5067
     *   the key specification list.
 
5068
     * lastKeySpec will be NULL only if no prior bindings exist.
 
5069
     */
 
5070
 
 
5071
    lastKeySpec = pSD->keySpecs;
 
5072
    if (lastKeySpec != NULL)
 
5073
    {
 
5074
        while (lastKeySpec->nextKeySpec != NULL)
 
5075
        {
 
5076
            lastKeySpec = (lastKeySpec->nextKeySpec);
 
5077
        }
 
5078
    }
 
5079
 
 
5080
    /*
 
5081
     * Parse "key context function"  until "}" or EOF found.
 
5082
     * Skip bad key bindings.
 
5083
     */
 
5084
 
 
5085
    while ((GetNextLine () != NULL))  /* not EOF nor read error */
 
5086
    {
 
5087
        lineP = line;
 
5088
        ScanWhitespace (&lineP);
 
5089
        if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
 
5090
        /* ignore empty or comment lines */
 
5091
        {
 
5092
            continue;
 
5093
        }
 
5094
        if (*lineP == '}')  /* finished with key set */
 
5095
        {
 
5096
            break;
 
5097
        }
 
5098
 
 
5099
        /*
 
5100
         * Allocate space for the key specification.
 
5101
         */
 
5102
        if ((keySpec = (KeySpec *)XtMalloc (sizeof (KeySpec))) == NULL)
 
5103
        {
 
5104
            PWarning (((char *)GETMESSAGE(60, 26, "Insufficient memory for key specification")));
 
5105
            continue;
 
5106
        }
 
5107
 
 
5108
        keySpec->wmFunction = (WmFunction)NULL;
 
5109
        keySpec->wmFuncArgs = NULL;
 
5110
        keySpec->nextKeySpec = NULL;
 
5111
 
 
5112
        /*
 
5113
         * Parse the key specification.
 
5114
         */
 
5115
#ifdef WSM
 
5116
        bBadKey = False;
 
5117
#endif /* WSM */
 
5118
        if (!ParseKeyEvent(&lineP,
 
5119
                           &eventType,
 
5120
                           &keySpec->keycode,
 
5121
                           &keySpec->state))
 
5122
        {
 
5123
#ifdef WSM
 
5124
            bBadKey = True;
 
5125
#else /* WSM */
 
5126
            PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
 
5127
            XtFree ((char *)keySpec);
 
5128
            continue;  /* skip this key specification */
 
5129
#endif /* WSM */
 
5130
        }
 
5131
 
 
5132
        /*
 
5133
         * Parse the key context.
 
5134
         *   Here lineP points to the candidate context string.
 
5135
         */
 
5136
 
 
5137
        if (!ParseContext(&lineP, &keySpec->context, 
 
5138
                          &keySpec->subContext))
 
5139
        {
 
5140
#ifdef WSM
 
5141
            if (bBadKey)
 
5142
                PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
 
5143
#endif /* WSM */
 
5144
            PWarning (((char *)GETMESSAGE(60, 28, "Invalid key context")));
 
5145
            XtFree ((char *)keySpec);
 
5146
            continue;  /* skip this key specification */
 
5147
        }
 
5148
#ifdef WSM
 
5149
        if (bBadKey)
 
5150
        {
 
5151
            /*
 
5152
             * Don't print an error message if this is a "hardware
 
5153
             * available" binding.
 
5154
             */
 
5155
            if (!(keySpec->context & F_CONTEXT_IFKEY))
 
5156
                PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
 
5157
            XtFree ((char *)keySpec);
 
5158
            continue;  /* skip this key specification */
 
5159
        }
 
5160
 
 
5161
        /*
 
5162
         * This flag is only used for parsing, clear it so the
 
5163
         * rest of the program doesn't see it.
 
5164
         */
 
5165
        keySpec->context &= ~F_CONTEXT_IFKEY;
 
5166
#endif /* WSM */
 
5167
 
 
5168
 
 
5169
        /*
 
5170
         * Parse the key function and any arguments.
 
5171
         */
 
5172
 
 
5173
        ix = ParseWmFunction (&lineP, CRS_KEY, &keySpec->wmFunction);
 
5174
        
 
5175
        /*
 
5176
         * remove any subContexts that don't apply to this function
 
5177
         */
 
5178
        if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) &&
 
5179
            (keySpec->subContext & F_SUBCONTEXT_IB_IICON))
 
5180
        {
 
5181
            keySpec->subContext &= ~F_SUBCONTEXT_IB_IICON;
 
5182
        }
 
5183
 
 
5184
        if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) &&
 
5185
            (keySpec->subContext & F_SUBCONTEXT_IB_WICON))
 
5186
        {
 
5187
            keySpec->subContext &= ~F_SUBCONTEXT_IB_WICON;
 
5188
        }
 
5189
 
 
5190
        /* 
 
5191
         * Apply the function argument parser.
 
5192
         */
 
5193
        if (!(*(functionTable [ix].parseProc)) 
 
5194
                   (&lineP, keySpec->wmFunction, &keySpec->wmFuncArgs))
 
5195
        {
 
5196
            XtFree ((char *)keySpec);
 
5197
            continue;  /* skip this key specification */
 
5198
        }
 
5199
 
 
5200
        /* 
 
5201
         * Add the key specification to the key specification list. 
 
5202
         */
 
5203
        if (lastKeySpec != NULL)
 
5204
        /* a prior specification exists */
 
5205
        {
 
5206
            lastKeySpec->nextKeySpec = keySpec;
 
5207
        }
 
5208
        else
 
5209
        {
 
5210
            pSD->keySpecs = keySpec;
 
5211
        }
 
5212
        lastKeySpec = keySpec;
 
5213
    }
 
5214
 
 
5215
} /* END OF FUNCTION ParseKeySet */
 
5216
 
 
5217
#ifndef WSM
 
5218
 
 
5219
/*************************************<->*************************************
 
5220
 *
 
5221
 *  GetNextLine ()
 
5222
 *
 
5223
 *
 
5224
 *  Description:
 
5225
 *  -----------
 
5226
 *  Returns the next line from an fopened configuration file or a newline-
 
5227
 *  embedded configuration string.
 
5228
 *
 
5229
 *
 
5230
 *  Inputs:
 
5231
 *  ------
 
5232
 *  cfileP = (global) file pointer to fopened configuration file or NULL
 
5233
 *  line   = (global) line buffer
 
5234
 *  linec  = (global) line count
 
5235
 *  parseP = (global) parse string pointer if cfileP == NULL
 
5236
 *
 
5237
 * 
 
5238
 *  Outputs:
 
5239
 *  -------
 
5240
 *  line =    (global) next line 
 
5241
 *  linec =   (global) line count incremented
 
5242
 *  parseP =  (global) parse string pointer incremented
 
5243
 *  Return =  line or NULL if file or string is exhausted.
 
5244
 *
 
5245
 *
 
5246
 *  Comments:
 
5247
 *  --------
 
5248
 *  If there are more than MAXLINE characters on a line in the file cfileP the
 
5249
 *  excess are truncated.  
 
5250
 *  Assumes the line buffer is long enough for any parse string line.
 
5251
 * 
 
5252
 *************************************<->***********************************/
 
5253
 
 
5254
unsigned char *
 
5255
GetNextLine (void)
 
5256
{
 
5257
    register unsigned char      *string;
 
5258
    int                         len;
 
5259
 
 
5260
#ifndef NO_MULTIBYTE
 
5261
    int   chlen;
 
5262
    wchar_t last;
 
5263
    wchar_t wdelim;
 
5264
    char delim;
 
5265
    int lastlen;
 
5266
#endif
 
5267
 
 
5268
    if (cfileP != NULL)
 
5269
    /* read fopened file */
 
5270
    {
 
5271
        if ((string = (unsigned char *) 
 
5272
                      fgets ((char *)line, MAXLINE, cfileP)) != NULL)
 
5273
        {
 
5274
#ifndef NO_MULTIBYTE
 
5275
 
 
5276
            lastlen = 0;
 
5277
            while (*string &&
 
5278
                   ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
 
5279
            {
 
5280
                mbtowc(&last, (char *)string, MB_CUR_MAX);
 
5281
                lastlen = len;
 
5282
                string += len;
 
5283
            }
 
5284
            delim = '\\';
 
5285
            mbtowc(&wdelim, &delim, MB_CUR_MAX);
 
5286
            if (lastlen == 1 && last == wdelim)
 
5287
            {
 
5288
                do
 
5289
                {
 
5290
                    if (!fgets((char *)string, MAXLINE - (string - line), cfileP))
 
5291
                        break;
 
5292
 
 
5293
                    lastlen = 0;
 
5294
                    while (*string &&
 
5295
                           ((len = mblen((char *)string, MB_CUR_MAX)) > 0))
 
5296
                    {
 
5297
                        mbtowc(&last, (char *)string, MB_CUR_MAX);
 
5298
                        lastlen = len;
 
5299
                        string += len;
 
5300
                    }
 
5301
                    linec++;
 
5302
                }
 
5303
                while (lastlen == 1 && last == wdelim);
 
5304
            }
 
5305
            string = line;
 
5306
#else
 
5307
            len = strlen((char *)string) - 2;
 
5308
            if ((len > 0) && string[len] == '\\')
 
5309
            {
 
5310
                do {
 
5311
                    string = &string[len];
 
5312
                    if (fgets((char *)string, 
 
5313
                              MAXLINE - (string-line), cfileP) == NULL)
 
5314
                       break;
 
5315
                    len = strlen((char *)string) - 2;
 
5316
                    linec++;
 
5317
                } while ((len >= 0) && string[len] == '\\');
 
5318
                string = line;
 
5319
            }
 
5320
#endif
 
5321
        }
 
5322
    }
 
5323
    else if ((parseP != NULL) && (*parseP != '\0'))
 
5324
    /* read parse string */
 
5325
    {
 
5326
        string = line;
 
5327
#ifndef NO_MULTIBYTE
 
5328
/* bug fix for #1127 */
 
5329
        /* check for chlen==-1. in the case we must set string to NULL 2001.06.14 XXXX */
 
5330
        chlen = mblen((char *)parseP, MB_CUR_MAX); /* 2001.06.14 XXXXX */
 
5331
        if(chlen==-1) string = NULL; /* 2001.06.14 XXXX */
 
5332
 
 
5333
 
 
5334
        while ((*parseP != '\0') &&
 
5335
               ((chlen = mblen ((char *)parseP, MB_CUR_MAX)) > 0) &&
 
5336
               (*parseP != '\n'))
 
5337
        /* copy all but NULL and newlines to line buffer */
 
5338
        {
 
5339
            while (chlen--)
 
5340
            {
 
5341
                *(string++) = *(parseP++);
 
5342
            }
 
5343
        }
 
5344
#else
 
5345
        while ((*parseP != '\0') && (*parseP != '\n'))
 
5346
        /* copy all but end-of-line and newlines to line buffer */
 
5347
        {
 
5348
            *(string++) = *(parseP++);
 
5349
    }
 
5350
#endif
 
5351
    /* fix for bug 1127 */
 
5352
    if(string) *string = '\0';          /* *string = '\0'; */
 
5353
        if (*parseP == '\n')
 
5354
        {
 
5355
            parseP++;
 
5356
        }
 
5357
    }
 
5358
    else
 
5359
    {
 
5360
        string = NULL;
 
5361
    }
 
5362
 
 
5363
    linec++;
 
5364
    return (string);
 
5365
 
 
5366
} /* END OF FUNCTION GetNextLine */
 
5367
#endif /* WSM */
 
5368
 
 
5369
#ifndef PANELIST
 
5370
 
 
5371
#ifdef WSM
 
5372
/*************************************<->*************************************
 
5373
 *
 
5374
 *  GetStringC (linePP, SmBehavior)
 
5375
 *
 
5376
 *
 
5377
 *  Description:
 
5378
 *  -----------
 
5379
 *  Returns the next quoted or whitespace-terminated nonquoted string in the
 
5380
 *  line buffer.
 
5381
 *  Additional functionality added to GetString in that anything in a
 
5382
 *  quoted string is considered sacred and nothing will be stripped from
 
5383
 *  the middle of a quoted string.
 
5384
 *
 
5385
 *
 
5386
 *  Inputs:
 
5387
 *  ------
 
5388
 *  linePP =  pointer to current line buffer pointer.
 
5389
 *  SmBehavior = flag that enables parsing session manager hints
 
5390
 *               if True.
 
5391
 *
 
5392
 * 
 
5393
 *  Outputs:
 
5394
 *  -------
 
5395
 *  linePP =  pointer to revised line buffer pointer.
 
5396
 *  Return =  string 
 
5397
 *
 
5398
 *
 
5399
 *  Comments:
 
5400
 *  --------
 
5401
 *  May alter the line buffer contents.
 
5402
 *  Handles quoted strings and characters, removing trailing whitespace from
 
5403
 *  quoted strings.
 
5404
 *  Returns NULL string if the line is empty or is a comment.
 
5405
 *  Code stolen from dtmwm.
 
5406
 * 
 
5407
 *************************************<->***********************************/
 
5408
#else /* WSM */
 
5409
/*************************************<->*************************************
 
5410
 *
 
5411
 *  GetString (linePP)
 
5412
 *
 
5413
 *
 
5414
 *  Description:
 
5415
 *  -----------
 
5416
 *  Returns the next quoted or whitespace-terminated nonquoted string in the
 
5417
 *  line buffer.
 
5418
 *
 
5419
 *
 
5420
 *  Inputs:
 
5421
 *  ------
 
5422
 *  linePP =  pointer to current line buffer pointer.
 
5423
 *
 
5424
 * 
 
5425
 *  Outputs:
 
5426
 *  -------
 
5427
 *  linePP =  pointer to revised line buffer pointer.
 
5428
 *  Return =  string 
 
5429
 *
 
5430
 *
 
5431
 *  Comments:
 
5432
 *  --------
 
5433
 *  May alter the line buffer contents.
 
5434
 *  Handles quoted strings and characters, removing trailing whitespace from
 
5435
 *  quoted strings.
 
5436
 *  Returns NULL string if the line is empty or is a comment.
 
5437
 * 
 
5438
 *************************************<->***********************************/
 
5439
#endif /* WSM */
 
5440
 
 
5441
#ifdef WSM
 
5442
unsigned char *GetStringC (unsigned char **linePP, Boolean SmBehavior)
 
5443
#else /* WSM */
 
5444
unsigned char *GetString (unsigned char **linePP)
 
5445
#endif /* WSM */
 
5446
{
 
5447
    unsigned char *lineP = *linePP;
 
5448
    unsigned char *endP;
 
5449
    unsigned char *curP;
 
5450
    unsigned char *lnwsP;
 
5451
#ifdef WSM
 
5452
    unsigned int  level = 0, checkLev, i, quoteLevel[10];
 
5453
#endif /* WSM */
 
5454
#ifndef NO_MULTIBYTE
 
5455
    int            chlen;
 
5456
 
 
5457
    /* get rid of leading white space */
 
5458
    ScanWhitespace (&lineP);
 
5459
 
 
5460
    /*
 
5461
     * Return NULL if line is empty, a comment, or invalid.
 
5462
     */
 
5463
#ifdef WSM
 
5464
    if (
 
5465
        *lineP == '\0' ||
 
5466
        ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
 
5467
        ((chlen == 1) && ((*lineP == '!') || 
 
5468
                          ((!SmBehavior) && (*lineP == '#'))))
 
5469
       )
 
5470
#else /* WSM */
 
5471
    if (
 
5472
        *lineP == '\0' ||
 
5473
        ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
 
5474
        ((chlen > 0) && ((*lineP == '!') || (*lineP == '#')))
 
5475
       )
 
5476
#endif /* WSM */
 
5477
    {
 
5478
        *linePP = lineP;
 
5479
        return (NULL);
 
5480
    }
 
5481
 
 
5482
    if ((chlen == 1) && (*lineP == '"'))
 
5483
    /* Quoted string */
 
5484
    {
 
5485
#ifdef WSM
 
5486
        quoteLevel[level] = 1;  
 
5487
#endif /* WSM */
 
5488
        /*
 
5489
         * Start beyond double quote and find the end of the quoted string.
 
5490
         * '\' quotes the next character.
 
5491
         * Otherwise,  matching double quote or NULL terminates the string.
 
5492
         *
 
5493
         * We use lnwsP to point to the last non-whitespace character in the
 
5494
         * quoted string.  When we have found the end of the quoted string,
 
5495
         * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
 
5496
         * This removes any trailing whitespace without overwriting the 
 
5497
         * matching quote, needed later.  If the quoted string was all 
 
5498
         * whitespace, then this will write a NULL at the beginning of the 
 
5499
         * string that will be returned -- OK.
 
5500
         */
 
5501
        lnwsP = lineP++;                /* lnwsP points to first '"' */
 
5502
        curP = endP = lineP;            /* other pointers point beyond */
 
5503
 
 
5504
        while ((*endP = *curP) &&
 
5505
               ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
 
5506
               ((chlen > 1) || (*curP != '"')))
 
5507
        /* Haven't found matching quote yet.
 
5508
         * First byte of next character has been copied to endP.
 
5509
         */
 
5510
        {
 
5511
            curP++;
 
5512
            if ((chlen == 1) && (*endP == '\\') && 
 
5513
                ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
 
5514
            /* character quote:
 
5515
             * copy first byte of quoted nonNULL character down.
 
5516
             * point curP to next byte
 
5517
             */
 
5518
            {
 
5519
#ifdef WSM
 
5520
                if (SmBehavior)
 
5521
                {
 
5522
                    /*
 
5523
                     * Check to see if this is a quoted quote - if it is
 
5524
                     * strip off a level - if not - it's sacred leave it alone
 
5525
                     */
 
5526
                    checkLev = PeekAhead((curP - 1), quoteLevel[level]);
 
5527
                    if(checkLev > 0)
 
5528
                    {
 
5529
                        if(quoteLevel[level] <= checkLev)
 
5530
                        {
 
5531
                            level--;
 
5532
                        }
 
5533
                        else
 
5534
                        {
 
5535
                            level++;
 
5536
                            quoteLevel[level] = checkLev;
 
5537
                        }
 
5538
                        
 
5539
                        for(i = 0;i < (checkLev - 2);i++)
 
5540
                        {
 
5541
                            *endP++ = *curP++;curP++;
 
5542
                        }
 
5543
                        *endP = *curP++;
 
5544
                    }
 
5545
                }
 
5546
                else 
 
5547
                {
 
5548
#endif /* WSM */
 
5549
                *endP = *curP++;
 
5550
#ifdef WSM
 
5551
                }
 
5552
#endif /* WSM */
 
5553
            }
 
5554
 
 
5555
            if (chlen == 1)
 
5556
            /* Singlebyte character:  character copy finished. */
 
5557
            {
 
5558
                if (isspace (*endP))
 
5559
                /* whitespace character:  leave lnwsP unchanged. */
 
5560
                {
 
5561
                    endP++;
 
5562
                }
 
5563
                else
 
5564
                /* non-whitespace character:  point lnwsP to it. */
 
5565
                {
 
5566
                    lnwsP = endP++;
 
5567
                }
 
5568
            }
 
5569
            else if (chlen > 1)
 
5570
            /* Multibyte (nonwhitespace) character:  point lnwsP to it.
 
5571
             * Finish character byte copy.
 
5572
             */
 
5573
            {
 
5574
                lnwsP = endP++;
 
5575
                while (--chlen)
 
5576
                {
 
5577
                    *endP++ = *curP++;
 
5578
                    lnwsP++;
 
5579
                }
 
5580
            }
 
5581
        }
 
5582
#else
 
5583
 
 
5584
    /* get rid of leading white space */
 
5585
    ScanWhitespace (&lineP);
 
5586
 
 
5587
#ifdef WSM
 
5588
    /* Return NULL if line is empty, whitespace, or begins with a comment. */
 
5589
    if ((lineP == NULL || *lineP == '\0') ||
 
5590
        (!SmBehavior && (*lineP == '#')))
 
5591
#else /* WSM */
 
5592
    /* Return NULL if line is empty, whitespace, or begins with a comment. */
 
5593
    if ((lineP == NULL) || (*lineP == '\0') || (*lineP == '#'))
 
5594
#endif /* WSM */
 
5595
    {
 
5596
        *linePP = lineP;
 
5597
        return (NULL);
 
5598
    }
 
5599
 
 
5600
    if (*lineP == '"')
 
5601
    /* Quoted string */
 
5602
    {
 
5603
#ifdef WSM
 
5604
        quoteLevel[level] = 1;  
 
5605
#endif /* WSM */
 
5606
        /*
 
5607
         * Start beyond double quote and find the end of the quoted string.
 
5608
         * '\' quotes the next character.
 
5609
         * Otherwise,  matching double quote or NULL terminates the string.
 
5610
         *
 
5611
         * We use lnwsP to point to the last non-whitespace character in the
 
5612
         * quoted string.  When we have found the end of the quoted string,
 
5613
         * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
 
5614
         * This removes any trailing whitespace without overwriting the 
 
5615
         * matching quote, needed later.  If the quoted string was all 
 
5616
         * whitespace, then this will write a NULL at the beginning of the 
 
5617
         * string that will be returned -- OK.
 
5618
         */
 
5619
        lnwsP = lineP++;                /* lnwsP points to first '"' */
 
5620
        curP = endP = lineP;            /* other pointers point beyond */
 
5621
 
 
5622
        while ((*endP = *curP) && (*endP != '"'))
 
5623
        /* haven't found matching quote yet */
 
5624
        {
 
5625
            /* point curP to next character */
 
5626
            curP++;
 
5627
            if ((*endP == '\\') && (*curP != '\0'))
 
5628
            /* shift quoted nonNULL character down and curP ahead */
 
5629
            {
 
5630
#ifdef WSM
 
5631
                if (SmBehavior)
 
5632
                {
 
5633
                    /*
 
5634
                     * Check to see if this is a quoted quote - if it is
 
5635
                     * strip off a level - if not - it's sacred leave it alone
 
5636
                     */
 
5637
                    checkLev = PeekAhead((curP - 1), quoteLevel[level]);
 
5638
                    if(checkLev > 0)
 
5639
                    {
 
5640
                        if(quoteLevel[level] <= checkLev)
 
5641
                        {
 
5642
                            level--;
 
5643
                        }
 
5644
                        else
 
5645
                        {
 
5646
                            level++;
 
5647
                            quoteLevel[level] = checkLev;
 
5648
                        }
 
5649
                        
 
5650
                        for(i = 0;i < (checkLev - 2);i++)
 
5651
                        {
 
5652
                            *endP++ = *curP++;curP++;
 
5653
                        }
 
5654
                        *endP = *curP++;
 
5655
                    }
 
5656
                }
 
5657
                else 
 
5658
                {
 
5659
#endif /* WSM */
 
5660
                *endP = *curP++;
 
5661
#ifdef WSM
 
5662
                }
 
5663
#endif /* WSM */
 
5664
            }
 
5665
            if (isspace (*endP))
 
5666
            /* whitespace character:  leave lnwsP unchanged. */
 
5667
            {
 
5668
                endP++;
 
5669
            }
 
5670
            else
 
5671
            /* non-whitespace character:  point lnwsP to it. */
 
5672
            {
 
5673
                lnwsP = endP++;
 
5674
            }
 
5675
        }
 
5676
#endif
 
5677
 
 
5678
        /*
 
5679
         *  Found matching quote or NULL.  
 
5680
         *  NULL out any trailing whitespace.
 
5681
         */
 
5682
 
 
5683
        lnwsP++;
 
5684
        if (lnwsP < endP)
 
5685
        {
 
5686
            *lnwsP = '\0';
 
5687
        }
 
5688
    }
 
5689
 
 
5690
    else
 
5691
    /* Unquoted string */
 
5692
    {
 
5693
        /* 
 
5694
         * Find the end of the nonquoted string.
 
5695
         * '\' quotes the next character.
 
5696
         * Otherwise,  whitespace, end-of-line, or '#' terminates the string.
 
5697
         */
 
5698
        curP = endP = lineP;
 
5699
 
 
5700
#ifndef NO_MULTIBYTE
 
5701
#ifdef WSM
 
5702
        while ((*endP = *curP) &&
 
5703
               ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
 
5704
               ((chlen > 1) || (!isspace (*curP) && 
 
5705
                                (SmBehavior || (*curP != '#')))))
 
5706
#else /* WSM */
 
5707
        while ((*endP = *curP) &&
 
5708
               ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
 
5709
               ((chlen > 1) || (!isspace (*curP) && (*curP != '#'))))
 
5710
#endif /* WSM */
 
5711
        /* Haven't found whitespace or '#' yet.
 
5712
         * First byte of next character has been copied to endP.
 
5713
         */
 
5714
        {
 
5715
            curP++;
 
5716
            if ((chlen == 1) && (*endP == '\\') && 
 
5717
                ((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
 
5718
            /* character quote:
 
5719
             * copy first byte of quoted nonNULL character down.
 
5720
             * point curP to next byte
 
5721
             */
 
5722
            {
 
5723
                *endP = *curP++;
 
5724
            }
 
5725
            endP++;
 
5726
            if (chlen > 1)
 
5727
            /* Multibyte character:  finish character copy. */
 
5728
            {
 
5729
                while (--chlen)
 
5730
                {
 
5731
                    *endP++ = *curP++;
 
5732
                }
 
5733
            }
 
5734
        }
 
5735
#else
 
5736
#ifdef WSM
 
5737
        while ((*endP = *curP) && !isspace (*endP) && 
 
5738
                                        (SmBehavior || (*endP != '#')))
 
5739
#else /* WSM */
 
5740
        while ((*endP = *curP) && !isspace (*endP) && (*endP != '#'))
 
5741
#endif /* WSM */
 
5742
        {
 
5743
            /* point curP to next character */
 
5744
            curP++;
 
5745
            if ((*endP == '\\') && (*curP != '\0'))
 
5746
            /* shift quoted nonNULL character down and curP ahead */
 
5747
            {
 
5748
                *endP = *curP++;
 
5749
            }
 
5750
            endP++;
 
5751
        }
 
5752
#endif
 
5753
    }
 
5754
 
 
5755
    /*
 
5756
     * Three cases for *endP:
 
5757
     *   '#' --> write NULL over # and point to NULL
 
5758
     *   whitespace or
 
5759
     *     matching quote -> write end-of-line over char and point beyond
 
5760
     *   NULL -> point to NULL 
 
5761
     */
 
5762
 
 
5763
#ifdef WSM
 
5764
    if (!SmBehavior && (*endP == '#'))
 
5765
#else /* WSM */
 
5766
    if (*endP == '#')
 
5767
#endif /* WSM */
 
5768
    {
 
5769
        *endP = '\0';       /* write '\0' over '#' */
 
5770
        *linePP = endP;     /* point to '\0' */
 
5771
    }
 
5772
    else if (*endP != '\0')
 
5773
    {
 
5774
        *endP = '\0';       /* write NULL over terminator */
 
5775
        *linePP = ++curP;   /* point beyond terminator */
 
5776
    }
 
5777
    else
 
5778
    {
 
5779
        *linePP = endP;
 
5780
    }
 
5781
    return ((unsigned char *)lineP);
 
5782
 
 
5783
} /* END OF FUNCTION GetString */
 
5784
#endif /* PANELIST */
 
5785
 
 
5786
 
 
5787
 
 
5788
/*************************************<->*************************************
 
5789
 *
 
5790
 *  ParseBtnEvent (linePP, eventType, button, state, fClick)
 
5791
 *
 
5792
 *
 
5793
 *  Description:
 
5794
 *  -----------
 
5795
 *  Parse a button event specification.
 
5796
 *
 
5797
 *
 
5798
 *  Inputs:
 
5799
 *  ------
 
5800
 *  linePP =          pointer to current line buffer pointer
 
5801
 *  buttonEvents =    (global) button event parse table
 
5802
 *  modifierStrings = (global) modifier string/mask table
 
5803
 *
 
5804
 * 
 
5805
 *  Outputs:
 
5806
 *  -------
 
5807
 *  linePP =    pointer to revised line buffer pointer.
 
5808
 *  eventType = type of event
 
5809
 *  button =    parsed button number
 
5810
 *  state =     composite modifier mask
 
5811
 *  fClick =    is click?
 
5812
 *
 
5813
 *  Return = (Boolean) true iff valid button event specification
 
5814
 * 
 
5815
 *
 
5816
 *  Comments:
 
5817
 *  --------
 
5818
 *  None.
 
5819
 * 
 
5820
 *************************************<->***********************************/
 
5821
 
 
5822
Boolean ParseBtnEvent (unsigned char  **linePP,
 
5823
                       unsigned int *eventType,
 
5824
                       unsigned int *button,
 
5825
                       unsigned int *state,
 
5826
                       Boolean      *fClick)
 
5827
{
 
5828
    if (!ParseEvent (linePP, buttonEvents, eventType, button, state, fClick))
 
5829
    {
 
5830
       return (FALSE);
 
5831
    }
 
5832
 
 
5833
    /* 
 
5834
     * The following is a fix for an X11 deficiency in regards to 
 
5835
     * modifiers in grabs.
 
5836
     */
 
5837
    if (*eventType == ButtonRelease)
 
5838
    {
 
5839
        /* the button that is going up will always be in the modifiers... */
 
5840
        *state |= buttonModifierMasks[*button];
 
5841
    }
 
5842
 
 
5843
    return (TRUE);
 
5844
 
 
5845
} /* END OF FUNCTION ParseBtnEvent */
 
5846
 
 
5847
 
 
5848
 
 
5849
/*************************************<->*************************************
 
5850
 *
 
5851
 *  ParseKeyEvent (linePP, eventType, keyCode, state)
 
5852
 *
 
5853
 *
 
5854
 *  Description:
 
5855
 *  -----------
 
5856
 *  Parse a key event specification.
 
5857
 *
 
5858
 *
 
5859
 *  Inputs:
 
5860
 *  ------
 
5861
 *  linePP =          pointer to current line buffer pointer
 
5862
 *  keyEvents =       (global) key event parse table
 
5863
 *  modifierStrings = (global) modifier string/mask table
 
5864
 *
 
5865
 * 
 
5866
 *  Outputs:
 
5867
 *  -------
 
5868
 *  linePP =    pointer to revised line buffer pointer.
 
5869
 *  eventType = type of event
 
5870
 *  keyCode =   parsed KeyCode
 
5871
 *  state =     composite modifier mask
 
5872
 *
 
5873
 *  Return = (Boolean) true iff valid key event specification
 
5874
 * 
 
5875
 *
 
5876
 *  Comments:
 
5877
 *  --------
 
5878
 *  None.
 
5879
 * 
 
5880
 *************************************<->***********************************/
 
5881
 
 
5882
Boolean ParseKeyEvent (unsigned char **linePP, unsigned int *eventType,
 
5883
                       KeyCode *keyCode,  unsigned int *state)
 
5884
 
 
5885
 
 
5886
{
 
5887
    Boolean      fClick;
 
5888
    unsigned int keySym = 0;
 
5889
 
 
5890
    if (!ParseEvent (linePP, keyEvents, eventType, &keySym, state, &fClick))
 
5891
    {
 
5892
       return (FALSE);
 
5893
    }
 
5894
 
 
5895
    /* 
 
5896
     * Here keySym is a KeySym.  Convert it to a KeyCode.
 
5897
     * KeyCode will be set to 0 if keySym is not defined for any KeyCode
 
5898
     *  (e.g. 0x001).
 
5899
     */
 
5900
 
 
5901
    *keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym);
 
5902
 
 
5903
    if (*keyCode == 0)
 
5904
    {
 
5905
        if (keySym == XK_F9)
 
5906
        {
 
5907
            keySym = XK_KP_F1;
 
5908
        }
 
5909
        else if (keySym == XK_F10)
 
5910
        {
 
5911
            keySym = XK_KP_F2;
 
5912
        }
 
5913
        else if (keySym == XK_F11)
 
5914
        {
 
5915
            keySym = XK_KP_F3;
 
5916
        }
 
5917
        else if (keySym == XK_F12)
 
5918
        {
 
5919
            keySym = XK_KP_F4;
 
5920
        }
 
5921
        *keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym);
 
5922
    }
 
5923
 
 
5924
    return (*keyCode != 0);
 
5925
 
 
5926
} /* END OF FUNCTION ParseKeyEvent */
 
5927
 
 
5928
 
 
5929
/*************************************<->*************************************
 
5930
 *
 
5931
 *  ParseEvent (linePP, table, eventType, detail, state, fClick)
 
5932
 *
 
5933
 *
 
5934
 *  Description:
 
5935
 *  -----------
 
5936
 *  Parse an event specification.
 
5937
 *
 
5938
 *
 
5939
 *  Inputs:
 
5940
 *  ------
 
5941
 *  linePP =          pointer to current line buffer pointer.
 
5942
 *  table =           event parse table
 
5943
 *  modifierStrings = (global) modifier string/mask table
 
5944
 *
 
5945
 * 
 
5946
 *  Outputs:
 
5947
 *  -------
 
5948
 *  linePP =    pointer to revised line buffer pointer.
 
5949
 *  eventType = type of event
 
5950
 *  detail =    dependent upon parse table detail procedure and closure
 
5951
 *  state =     composite modifier mask
 
5952
 *  fClick =    click flag
 
5953
 *
 
5954
 *  Return = (Boolean) true iff valid event specification
 
5955
 *
 
5956
 *  Comments:
 
5957
 *  --------
 
5958
 *  None.
 
5959
 * 
 
5960
 *************************************<->***********************************/
 
5961
 
 
5962
static Boolean ParseEvent (unsigned char **linePP, EventTableEntry *table,
 
5963
                           unsigned int *eventType, unsigned int *detail,
 
5964
                           unsigned int *state, Boolean *fClick)
 
5965
{
 
5966
    unsigned char    *lineP = *linePP;
 
5967
    Cardinal ix;
 
5968
    Boolean  status;
 
5969
 
 
5970
    /* Parse the modifiers */
 
5971
    if (!ParseModifiers (&lineP, state) || *lineP != '<')
 
5972
    {
 
5973
       return (FALSE);
 
5974
    }
 
5975
    lineP++;  /* skip '<' */
 
5976
 
 
5977
    /* Parse the event type */
 
5978
    if (!ParseEventType (&lineP, table, eventType, &ix) || *lineP != '>') 
 
5979
    {
 
5980
       return (FALSE);
 
5981
    }
 
5982
    lineP++;  /* skip '>' */
 
5983
 
 
5984
    /*
 
5985
     *  Compute detail and fClick.
 
5986
     *  Status will be False for a invalid KeySym name.
 
5987
     */
 
5988
    status = (*(table[ix].parseProc))(&lineP, table[ix].closure, detail);
 
5989
    *fClick = table[ix].fClick;
 
5990
 
 
5991
    if (status)
 
5992
    {
 
5993
        *linePP = lineP;
 
5994
    }
 
5995
    return (status);
 
5996
 
 
5997
} /* END OF FUNCTION ParseEvent */
 
5998
 
 
5999
 
 
6000
 
 
6001
/*************************************<->*************************************
 
6002
 *
 
6003
 *  ParseModifiers(linePP, state)
 
6004
 *
 
6005
 *
 
6006
 *  Description:
 
6007
 *  -----------
 
6008
 *  Parses a modifier specification.
 
6009
 *
 
6010
 *
 
6011
 *  Inputs:
 
6012
 *  ------
 
6013
 *  linePP = pointer to current line buffer pointer.
 
6014
 *  modifierStrings = (global) modifier string/mask table
 
6015
 *
 
6016
 * 
 
6017
 *  Outputs:
 
6018
 *  -------
 
6019
 *  linePP =    pointer to revised line buffer pointer.
 
6020
 *  state  = composite modifier mask
 
6021
 *  Return = (Boolean) true iff valid modifier name
 
6022
 *
 
6023
 *
 
6024
 *  Comments:
 
6025
 *  --------
 
6026
 *  If successful, will be followed by NULL or '<'.
 
6027
 * 
 
6028
 *************************************<->***********************************/
 
6029
 
 
6030
static Boolean ParseModifiers(unsigned char **linePP, unsigned int *state)
 
6031
{
 
6032
    unsigned char         *lineP = *linePP;
 
6033
    unsigned char         *startP;
 
6034
    unsigned char          modStr[MAX_MODIFIER_STRLEN+1];
 
6035
    Boolean       fNot;
 
6036
    unsigned int  maskBit;
 
6037
    int           len;
 
6038
 
 
6039
    *state = 0;
 
6040
 
 
6041
    /*
 
6042
     * Parse modifiers until the event specifier is encountered.
 
6043
     */
 
6044
 
 
6045
    ScanWhitespace (&lineP);
 
6046
    while ((*lineP != '\0') && (*lineP != '<'))
 
6047
    {
 
6048
        if (*lineP == '~') 
 
6049
        {
 
6050
            fNot = TRUE;
 
6051
            lineP++;
 
6052
        }
 
6053
        else 
 
6054
        {
 
6055
            fNot = FALSE;
 
6056
        }
 
6057
 
 
6058
        startP = lineP;
 
6059
        ScanAlphanumeric (&lineP);
 
6060
        if (startP == lineP)
 
6061
        /* ERROR: Modifier or '<' missing */
 
6062
        {
 
6063
            return (FALSE);
 
6064
        }
 
6065
        len = min(lineP - startP, MAX_MODIFIER_STRLEN);
 
6066
        (void) strncpy ((char *)modStr, (char *)startP, len);
 
6067
        modStr[len] = '\0';
 
6068
 
 
6069
        if (!LookupModifier (modStr, &maskBit))
 
6070
        /* Unknown modifier name */
 
6071
        {
 
6072
            return (FALSE);
 
6073
        }
 
6074
 
 
6075
        if (fNot) 
 
6076
        {
 
6077
            *state &= ~maskBit;
 
6078
        }
 
6079
        else 
 
6080
        {
 
6081
            *state |= maskBit;
 
6082
        }
 
6083
        ScanWhitespace(&lineP);
 
6084
    }
 
6085
 
 
6086
    *linePP = lineP;
 
6087
    return (TRUE);  /* must have '<' or NULL following */
 
6088
 
 
6089
} /* END OF FUNCTION ParseModifiers */
 
6090
 
 
6091
 
 
6092
/*************************************<->*************************************
 
6093
 *
 
6094
 *  LookupModifier (name, valueP)
 
6095
 *
 
6096
 *
 
6097
 *  Description:
 
6098
 *  -----------
 
6099
 *  Return the modifier mask for the provided modifier name.
 
6100
 *
 
6101
 *
 
6102
 *  Inputs:
 
6103
 *  ------
 
6104
 *  name = modifier string
 
6105
 *  modifierStrings = modifier string/mask table
 
6106
 *
 
6107
 * 
 
6108
 *  Outputs:
 
6109
 *  -------
 
6110
 *  valueP = modifier mask
 
6111
 *  Return = (Boolean) true iff valid modifier name
 
6112
 *
 
6113
 *
 
6114
 *  Comments:
 
6115
 *  --------
 
6116
 *  None.
 
6117
 * 
 
6118
 *************************************<->***********************************/
 
6119
 
 
6120
static Boolean LookupModifier (unsigned char *name, unsigned int *valueP)
 
6121
{
 
6122
    register int i;
 
6123
 
 
6124
    if (name != NULL)
 
6125
    {
 
6126
        ToLower (name);
 
6127
        for (i=0; modifierStrings[i].name != NULL; i++)
 
6128
        {
 
6129
            if (!strcmp (modifierStrings[i].name, (char *)name))
 
6130
            {
 
6131
                *valueP = modifierStrings[i].mask;
 
6132
                return (TRUE);
 
6133
            }
 
6134
        }
 
6135
    }
 
6136
 
 
6137
    return (FALSE);
 
6138
 
 
6139
} /* END OF FUNCTION LookupModifier */
 
6140
 
 
6141
 
 
6142
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
6143
/*************************************<->*************************************
 
6144
 *
 
6145
 *  GetCCIModifier (modString, mod)
 
6146
 *
 
6147
 *
 
6148
 *  Description:
 
6149
 *  -----------
 
6150
 *  Return the cci modifier corresponding to the specified string
 
6151
 *
 
6152
 *
 
6153
 *  Inputs:
 
6154
 *  ------
 
6155
 *  modString = cci modifier string; may be null
 
6156
 *
 
6157
 * 
 
6158
 *  Outputs:
 
6159
 *  -------
 
6160
 *  mod    = cci modifier.
 
6161
 *  Return = (Boolean) true iff valid modifier string
 
6162
 *
 
6163
 *
 
6164
 *  Comments:
 
6165
 *  --------
 
6166
 *  None.
 
6167
 * 
 
6168
 *************************************<->***********************************/
 
6169
 
 
6170
static Boolean GetCCIModifier (String modString, CCIEntryModifier *mod)
 
6171
{
 
6172
  CCIEntryModifier i;
 
6173
 
 
6174
 
 
6175
  if (modString != NULL)
 
6176
    {
 
6177
      ToLower ((unsigned char *)modString);
 
6178
      for (i=NONE; i<=EXCLUDE; i++)
 
6179
        {
 
6180
          if (!strcmp (CCIEntryModifierNames[i], modString))
 
6181
            {
 
6182
              *mod = i;
 
6183
              return (TRUE);
 
6184
            }
 
6185
        }
 
6186
    }
 
6187
 
 
6188
    return (FALSE);
 
6189
 
 
6190
} /* END OF FUNCTION GetCCIModifier */
 
6191
 
 
6192
 
 
6193
/*************************************<->*************************************
 
6194
 *
 
6195
 *  FixMenuItem (menuSpec, menuItem)
 
6196
 *
 
6197
 *
 
6198
 *  Description:
 
6199
 *  -----------
 
6200
 *  Fix-up the menuItem so that it appears an old-style cci command was
 
6201
 *  read from the .mwmrc file
 
6202
 *
 
6203
 *
 
6204
 *  Inputs:
 
6205
 *  ------
 
6206
 *  menuItem = the menu item structure
 
6207
 *  menuSpec = the menu specification structure
 
6208
 *
 
6209
 * 
 
6210
 *  Outputs:
 
6211
 *  -------
 
6212
 *  menuItem = the fixed-up menuitem
 
6213
 *  menuSpec = the fixed-up menu specification structure if EXCLUDE found
 
6214
 *  Return   = nothing
 
6215
 *
 
6216
 *  Comments:
 
6217
 *  --------
 
6218
 *
 
6219
 *************************************<->***********************************/
 
6220
 
 
6221
static void FixMenuItem (MenuSpec *menuSpec, MenuItem *menuItem)
 
6222
{
 
6223
  String      tmp;
 
6224
  CCIFuncArg *cciArg;
 
6225
  
 
6226
 
 
6227
  if (menuItem == NULL)
 
6228
    return;
 
6229
 
 
6230
  cciArg = (CCIFuncArg *)menuItem->wmFuncArgs;
 
6231
 
 
6232
  menuItem->clientCommandName = menuItem->label;
 
6233
  menuItem->label = cciArg->cciEntry;
 
6234
 
 
6235
  /*
 
6236
   * Fix-up the label to handle the modifier.
 
6237
   */
 
6238
 
 
6239
  switch (cciArg->mod)
 
6240
    {
 
6241
    case NONE:
 
6242
      break;
 
6243
 
 
6244
    case INLINE:
 
6245
      break;
 
6246
 
 
6247
    case CASCADE:
 
6248
      /* -> */
 
6249
      tmp = (String) XtMalloc(strlen(menuItem->label) + 3);
 
6250
      sprintf(tmp, "->%s", menuItem->label);
 
6251
      XtFree(menuItem->label);
 
6252
      menuItem->label = tmp;
 
6253
      break;
 
6254
 
 
6255
    case DELIMIT:
 
6256
      /* = */
 
6257
      tmp = (String) XtMalloc(strlen(menuItem->label) + 2);
 
6258
      sprintf(tmp, "=%s", menuItem->label);
 
6259
      XtFree(menuItem->label);
 
6260
      menuItem->label = tmp;
 
6261
      break;
 
6262
 
 
6263
    case DELIMIT_INLINE:
 
6264
      break;
 
6265
 
 
6266
    case DELIMIT_CASCADE:
 
6267
      /* => */
 
6268
      tmp = (String) XtMalloc(strlen(menuItem->label) + 3);
 
6269
      sprintf(tmp, "=>%s", menuItem->label);
 
6270
      XtFree(menuItem->label);
 
6271
      menuItem->label = tmp;
 
6272
      break;
 
6273
 
 
6274
    case EXCLUDE:
 
6275
      /* ~ */
 
6276
      StoreExclusion(menuSpec, menuItem->label);
 
6277
 
 
6278
      tmp = (String) XtMalloc(strlen(menuItem->label) + 2);
 
6279
      sprintf(tmp, "~%s", menuItem->label);
 
6280
      XtFree(menuItem->label);
 
6281
      menuItem->label = tmp;
 
6282
      break;
 
6283
    }
 
6284
}
 
6285
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
 
6286
 
 
6287
 
 
6288
/*************************************<->*************************************
 
6289
 *
 
6290
 *  ParseEventType(linePP, table, eventType, ix)
 
6291
 *
 
6292
 *
 
6293
 *  Description:
 
6294
 *  -----------
 
6295
 *  Parses the event type string.
 
6296
 *
 
6297
 *
 
6298
 *  Inputs:
 
6299
 *  ------
 
6300
 *  linePP = pointer to current line buffer pointer.
 
6301
 *  table =  event parse table
 
6302
 *
 
6303
 * 
 
6304
 *  Outputs:
 
6305
 *  -------
 
6306
 *  linePP = pointer to revised line buffer pointer.
 
6307
 *  eventType = type of event
 
6308
 *  ix = table index for matched event
 
6309
 *
 
6310
 *  Return = (Boolean) true iff valid event
 
6311
 *
 
6312
 *
 
6313
 *  Comments:
 
6314
 *  --------
 
6315
 *  None.
 
6316
 * 
 
6317
 *************************************<->***********************************/
 
6318
 
 
6319
static Boolean ParseEventType (unsigned char **linePP, EventTableEntry *table,
 
6320
                               unsigned int *eventType, Cardinal *ix)
 
6321
{
 
6322
    unsigned char *lineP = *linePP;
 
6323
    unsigned char *startP = *linePP;
 
6324
    unsigned char eventTypeStr[MAX_EVENTTYPE_STRLEN+1];
 
6325
    register int  len;
 
6326
 
 
6327
    /* Parse out the event string */
 
6328
    ScanAlphanumeric (&lineP);
 
6329
 
 
6330
    /*
 
6331
     * Attempt to match the parsed event against our supported event set.
 
6332
     */
 
6333
 
 
6334
    if (startP != lineP)
 
6335
    {
 
6336
        len = min (lineP - startP, MAX_EVENTTYPE_STRLEN);
 
6337
        (void) strncpy ((char *)eventTypeStr, (char *)startP, len);
 
6338
        eventTypeStr[len] = '\0';
 
6339
        ToLower (eventTypeStr);
 
6340
 
 
6341
        for (len = 0; table[len].event != NULL; len++)
 
6342
            if (!strcmp (table[len].event, (char *)eventTypeStr))
 
6343
            {
 
6344
               *ix = len;
 
6345
               *eventType = table[*ix].eventType;
 
6346
               *linePP = lineP;
 
6347
               return (TRUE); 
 
6348
            }
 
6349
    }
 
6350
 
 
6351
    /* Unknown event specified */
 
6352
    return (FALSE);
 
6353
 
 
6354
} /* END OF FUNCTION ParseEventType */
 
6355
 
 
6356
 
 
6357
/*************************************<->*************************************
 
6358
 *
 
6359
 *  ParseImmed (linePP, closure, detail)
 
6360
 *
 
6361
 *
 
6362
 *  Description:
 
6363
 *  -----------
 
6364
 *  Button event detail procedure.
 
6365
 *
 
6366
 *
 
6367
 *  Inputs:
 
6368
 *  ------
 
6369
 *  linePP =  not used
 
6370
 *  closure = table entry
 
6371
 *
 
6372
 * 
 
6373
 *  Outputs:
 
6374
 *  -------
 
6375
 *  detail = pointer to closure
 
6376
 *
 
6377
 *  Return = TRUE
 
6378
 *
 
6379
 *
 
6380
 *  Comments:
 
6381
 *  --------
 
6382
 *  None.
 
6383
 * 
 
6384
 *************************************<->***********************************/
 
6385
 
 
6386
static Boolean ParseImmed (unsigned char **linePP, unsigned int closure,
 
6387
                           unsigned int  *detail)
 
6388
{
 
6389
    *detail = closure;
 
6390
    return (TRUE);
 
6391
 
 
6392
} /* END OF FUNCTION ParseImmed */
 
6393
 
 
6394
 
 
6395
/*************************************<->*************************************
 
6396
 *
 
6397
 *  ParseKeySym (linePP, closure, detail)
 
6398
 *
 
6399
 *
 
6400
 *  Description:
 
6401
 *  -----------
 
6402
 *  Key event detail procedure.  Parses a KeySym string.
 
6403
 *
 
6404
 *
 
6405
 *  Inputs:
 
6406
 *  ------
 
6407
 *  linePP = pointer to current line buffer pointer
 
6408
 *
 
6409
 *  closure = not used.
 
6410
 *
 
6411
 * 
 
6412
 *  Outputs:
 
6413
 *  -------
 
6414
 *  linePP = pointer to revised line buffer pointer
 
6415
 *  detail = pointer to parsed KeySym
 
6416
 *
 
6417
 *  Return = (Boolean) true iff valid KeySym string
 
6418
 *
 
6419
 *
 
6420
 *  Comments:
 
6421
 *  --------
 
6422
 *  None.
 
6423
 * 
 
6424
 *************************************<->***********************************/
 
6425
 
 
6426
static Boolean ParseKeySym (unsigned char **linePP, unsigned int closure,
 
6427
                            unsigned int *detail)
 
6428
{
 
6429
    unsigned char *lineP = *linePP;
 
6430
    unsigned char *startP;
 
6431
    char           keySymName[MAX_KEYSYM_STRLEN+1];
 
6432
    int            len;
 
6433
#ifndef NO_MULTIBYTE
 
6434
    int            chlen;
 
6435
#endif
 
6436
 
 
6437
    ScanWhitespace (&lineP);
 
6438
    startP = lineP;
 
6439
 
 
6440
#ifndef NO_MULTIBYTE
 
6441
    while (*lineP &&
 
6442
           ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 0) &&
 
6443
           ((chlen > 1) ||
 
6444
           (!isspace (*lineP) && *lineP != ',' && *lineP != ':')))
 
6445
    {
 
6446
        /* Skip next character */
 
6447
        lineP += chlen;
 
6448
    }
 
6449
#else
 
6450
    while (*lineP && !isspace (*lineP) && *lineP != ',' && *lineP != ':' )
 
6451
    {
 
6452
        /* Skip next character */
 
6453
        lineP++;
 
6454
    }
 
6455
#endif
 
6456
 
 
6457
    len = min (lineP - startP, MAX_KEYSYM_STRLEN);
 
6458
    (void) strncpy (keySymName, (char *)startP, len);
 
6459
    keySymName[len] = '\0';
 
6460
 
 
6461
#ifndef NO_MULTIBYTE
 
6462
    if ((*detail = XStringToKeysym(keySymName)) == NoSymbol &&
 
6463
         (mblen (keySymName, MB_CUR_MAX) == 1))
 
6464
#else
 
6465
    if ((*detail = XStringToKeysym(keySymName)) == NoSymbol)
 
6466
#endif
 
6467
    {
 
6468
        if (!isdigit (keySymName[0]) ||
 
6469
            ((*detail = StrToNum ((unsigned char *)&keySymName[0])) == -1))
 
6470
        {
 
6471
            *detail = NoSymbol;
 
6472
            return (FALSE);
 
6473
        }
 
6474
    }
 
6475
    *linePP = lineP;
 
6476
    return (TRUE);
 
6477
 
 
6478
} /* END OF FUNCTION ParseKeySym */
 
6479
 
 
6480
 
 
6481
 
 
6482
/*************************************<->*************************************
 
6483
 *
 
6484
 *  StrToNum(str)
 
6485
 *
 
6486
 *
 
6487
 *  Description:
 
6488
 *  -----------
 
6489
 *  Converts a string to an unsigned hexadecimal, decimal, or octal integer.
 
6490
 *
 
6491
 *
 
6492
 *  Inputs:
 
6493
 *  ------
 
6494
 *  str = character string
 
6495
 *
 
6496
 * 
 
6497
 *  Outputs:
 
6498
 *  -------
 
6499
 *  Return = unsigned integer 
 
6500
 *
 
6501
 *
 
6502
 *  Comments:
 
6503
 *  --------
 
6504
 *  None.
 
6505
 * 
 
6506
 *************************************<->***********************************/
 
6507
 
 
6508
static unsigned int StrToNum(unsigned char *str)
 
6509
{
 
6510
    unsigned char c;
 
6511
    unsigned int  val = 0;
 
6512
 
 
6513
    if (*str == '0')
 
6514
    {
 
6515
        str++;
 
6516
        if (*str == 'x' || *str == 'X')
 
6517
        {
 
6518
            return (StrToHex(++str));
 
6519
        }
 
6520
        return (StrToOct(str));
 
6521
    }
 
6522
 
 
6523
    while ((c = *str) != '\0')
 
6524
    {
 
6525
        if ('0' <= c && c <= '9')
 
6526
        {
 
6527
            val = val*10+c-'0';
 
6528
        }
 
6529
        else
 
6530
        {
 
6531
            return (-1);
 
6532
        }
 
6533
        str++;
 
6534
    }
 
6535
 
 
6536
    return (val);
 
6537
 
 
6538
} /* END OF FUNCTION StrToNum */
 
6539
 
 
6540
 
 
6541
 
 
6542
/*************************************<->*************************************
 
6543
 *
 
6544
 
 
6545
 *
 
6546
 *
 
6547
 *  Description:
 
6548
 *  -----------
 
6549
 *
 
6550
 *  Inputs:
 
6551
 *  ------
 
6552
 *
 
6553
 * 
 
6554
 *  Outputs:
 
6555
 *  -------
 
6556
 *
 
6557
 *  Comments:
 
6558
 *  --------
 
6559
 *  None.
 
6560
 * 
 
6561
 *************************************<->***********************************/
 
6562
 
 
6563
static unsigned int StrToHex(unsigned char *str)
 
6564
{
 
6565
    unsigned char c;
 
6566
    unsigned int  val = 0;
 
6567
 
 
6568
    while ((c = *str) != '\0')
 
6569
    {
 
6570
        if ('0' <= c && c <= '9')
 
6571
        {
 
6572
            val = val*16+c-'0';
 
6573
        }
 
6574
        else if ('a' <= c && c <= 'f')
 
6575
        {
 
6576
            val = val*16+c-'a'+10;
 
6577
        }
 
6578
        else if ('A' <= c && c <= 'F')
 
6579
        {
 
6580
            val = val*16+c-'A'+10;
 
6581
        }
 
6582
        else
 
6583
        {
 
6584
            return (-1);
 
6585
        }
 
6586
        str++;
 
6587
    }
 
6588
 
 
6589
    return (val);
 
6590
 
 
6591
} /* END OF FUNCTION StrToHex */
 
6592
 
 
6593
 
 
6594
 
 
6595
/*************************************<->*************************************
 
6596
 *
 
6597
 
 
6598
 *
 
6599
 *
 
6600
 *  Description:
 
6601
 *  -----------
 
6602
 *
 
6603
 *  Inputs:
 
6604
 *  ------
 
6605
 *
 
6606
 * 
 
6607
 *  Outputs:
 
6608
 *  -------
 
6609
 *
 
6610
 *  Comments:
 
6611
 *  --------
 
6612
 *  None.
 
6613
 * 
 
6614
 *************************************<->***********************************/
 
6615
 
 
6616
static unsigned int StrToOct(unsigned char *str)
 
6617
{
 
6618
    unsigned char c;
 
6619
    unsigned int  val = 0;
 
6620
 
 
6621
    while ((c = *str) != '\0')
 
6622
    {
 
6623
        if ('0' <= c && c <= '7')
 
6624
        {
 
6625
            val = val*8+c-'0';
 
6626
        }
 
6627
        else
 
6628
        {
 
6629
            return (-1);
 
6630
        }
 
6631
        str++;
 
6632
    }
 
6633
 
 
6634
    return (val);
 
6635
 
 
6636
} /* END OF FUNCTION StrToOct */
 
6637
 
 
6638
 
 
6639
 
 
6640
/*************************************<->*************************************
 
6641
 *
 
6642
 *  ScanAlphanumeric (linePP)
 
6643
 *
 
6644
 *
 
6645
 *  Description:
 
6646
 *  -----------
 
6647
 *  Scan string until a non-alphanumeric character is encountered.
 
6648
 *
 
6649
 *
 
6650
 *  Inputs:
 
6651
 *  ------
 
6652
 *  linePP = nonNULL pointer to current line buffer pointer
 
6653
 *
 
6654
 * 
 
6655
 *  Outputs:
 
6656
 *  -------
 
6657
 *  linePP = nonNULL pointer to revised line buffer pointer
 
6658
 *
 
6659
 *
 
6660
 *  Comments:
 
6661
 *  --------
 
6662
 *  Assumes linePP is nonNULL
 
6663
 * 
 
6664
 *************************************<->***********************************/
 
6665
 
 
6666
void ScanAlphanumeric (unsigned char **linePP)
 
6667
{
 
6668
#ifndef NO_MULTIBYTE
 
6669
    int            chlen;
 
6670
 
 
6671
    while (*linePP &&
 
6672
           ((chlen = mblen ((char *) *linePP, MB_CUR_MAX)) > 0) &&
 
6673
           ((chlen > 1) || isalnum (**linePP)))
 
6674
    {
 
6675
        (*linePP) += chlen;
 
6676
    }
 
6677
#else
 
6678
    while (*linePP && isalnum (**linePP))
 
6679
    {
 
6680
        (*linePP)++;
 
6681
    }
 
6682
#endif
 
6683
 
 
6684
} /* END OF FUNCTION ScanAlphanumeric */
 
6685
 
 
6686
 
 
6687
#ifndef WSM
 
6688
 
 
6689
/*************************************<->*************************************
 
6690
 *
 
6691
 *  ScanWhitespace(linePP)
 
6692
 *
 
6693
 *
 
6694
 *  Description:
 
6695
 *  -----------
 
6696
 *  Scan the string, skipping over all white space characters.
 
6697
 *
 
6698
 *
 
6699
 *  Inputs:
 
6700
 *  ------
 
6701
 *  linePP = nonNULL pointer to current line buffer pointer
 
6702
 *
 
6703
 * 
 
6704
 *  Outputs:
 
6705
 *  -------
 
6706
 *  linePP = nonNULL pointer to revised line buffer pointer
 
6707
 *
 
6708
 *
 
6709
 *  Comments:
 
6710
 *  --------
 
6711
 *  Assumes linePP is nonNULL
 
6712
 * 
 
6713
 *************************************<->***********************************/
 
6714
 
 
6715
void ScanWhitespace(unsigned char  **linePP)
 
6716
{
 
6717
#ifndef NO_MULTIBYTE
 
6718
    while (*linePP && (mblen ((char *)*linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
 
6719
#else
 
6720
    while (*linePP && isspace (**linePP))
 
6721
#endif
 
6722
    {
 
6723
        (*linePP)++;
 
6724
    }
 
6725
 
 
6726
} /* END OF FUNCTION ScanWhitespace */
 
6727
#endif /* not WSM */
 
6728
 
 
6729
#ifndef WSM
 
6730
 
 
6731
/*************************************<->*************************************
 
6732
 *
 
6733
 *  ToLower (string)
 
6734
 *
 
6735
 *
 
6736
 *  Description:
 
6737
 *  -----------
 
6738
 *  Lower all characters in a string.
 
6739
 *
 
6740
 *
 
6741
 *  Inputs:
 
6742
 *  ------
 
6743
 *  string = NULL-terminated character string or NULL
 
6744
 *
 
6745
 * 
 
6746
 *  Outputs:
 
6747
 *  -------
 
6748
 *  string = NULL-terminated lower case character string or NULL
 
6749
 *
 
6750
 *
 
6751
 *  Comments:
 
6752
 *  --------
 
6753
 *  None.
 
6754
 * 
 
6755
 *************************************<->***********************************/
 
6756
 
 
6757
void ToLower (unsigned char  *string)
 
6758
{
 
6759
    unsigned char *pch = string;
 
6760
#ifndef NO_MULTIBYTE
 
6761
    int            chlen;
 
6762
 
 
6763
    while (*pch && ((chlen = mblen ((char *)pch, MB_CUR_MAX)) > 0))
 
6764
    {
 
6765
        if ((chlen == 1) && (isupper (*pch)))
 
6766
        {
 
6767
            *pch = tolower(*pch);
 
6768
        }
 
6769
        pch += chlen;
 
6770
    }
 
6771
#else
 
6772
    while (*pch != '\0')
 
6773
    {
 
6774
        if (isupper (*pch))
 
6775
        {
 
6776
            *pch = tolower(*pch);
 
6777
        }
 
6778
        pch++;
 
6779
    }
 
6780
#endif
 
6781
 
 
6782
} /* END OF FUNCTION ToLower */
 
6783
#endif  /* WSM */
 
6784
 
 
6785
 
 
6786
/*************************************<->*************************************
 
6787
 *
 
6788
 *  PWarning (message)
 
6789
 *
 
6790
 *
 
6791
 *  Description:
 
6792
 *  -----------
 
6793
 *  This function lists a resource description parse message to stderr.
 
6794
 *
 
6795
 *
 
6796
 *  Inputs:
 
6797
 *  ------
 
6798
 *  message = pointer to a message string
 
6799
 *  cfileP  = (global) file pointer to fopened configuration file or NULL
 
6800
 *  linec   = (global) line counter
 
6801
 * 
 
6802
 *************************************<->***********************************/
 
6803
 
 
6804
void
 
6805
PWarning (char *message)
 
6806
{
 
6807
 
 
6808
#ifdef WSM
 
6809
    char pch[MAXWMPATH+1];
 
6810
    String sMessage;
 
6811
    char *pchFile;
 
6812
 
 
6813
    sMessage = XtNewString ((String) message);
 
6814
    if (cfileP != NULL)
 
6815
    {
 
6816
        if (pConfigStackTop->fileName)
 
6817
        {
 
6818
            pchFile = pConfigStackTop->fileName;
 
6819
        }
 
6820
        else 
 
6821
        {
 
6822
            pchFile = wmGD.configFile;
 
6823
        }
 
6824
 
 
6825
        sprintf (pch, pWarningStringFile,
 
6826
                     GETMESSAGE(20,1,"Workspace Manager"), 
 
6827
                     sMessage, linec, pchFile);
 
6828
    }
 
6829
    else
 
6830
    {
 
6831
        sprintf (pch, pWarningStringLine,
 
6832
                     GETMESSAGE(20,1,"Workspace Manager"), 
 
6833
                     sMessage, linec);
 
6834
    }
 
6835
    _DtSimpleError (wmGD.mwmName, DtIgnore, NULL, pch, NULL);
 
6836
    XtFree (sMessage);
 
6837
#else /* WSM */
 
6838
    if (cfileP != NULL)
 
6839
    {
 
6840
        fprintf (stderr, ((char *)GETMESSAGE(60, 33, "%s: %s on line %d of configuration file %s\n")),
 
6841
                 wmGD.mwmName, message, linec,
 
6842
                 wmGD.configFile ? wmGD.configFile : cfileName);
 
6843
    }
 
6844
    else
 
6845
    {
 
6846
        fprintf (stderr, ((char *)GETMESSAGE(60, 34, "%s: %s on line %d of specification string\n")),
 
6847
                     wmGD.mwmName, message, linec);
 
6848
    }
 
6849
    fflush (stderr);
 
6850
#endif /* WSM */
 
6851
 
 
6852
 
 
6853
} /* END OF FUNCTION PWarning */
 
6854
 
 
6855
#ifdef WSM
 
6856
/*
 
6857
 * Key substitution table entry
 
6858
 */
 
6859
 
 
6860
typedef struct _keySubs
 
6861
{
 
6862
    unsigned char *     pchFrom;
 
6863
    int                 lenFrom;
 
6864
    unsigned char *     pchTo;
 
6865
} KeySub;
 
6866
 
 
6867
 
 
6868
/*************************************<->*************************************
 
6869
 *
 
6870
 *  InitKeySubs (ppKeySubs, pNumKeySubs)
 
6871
 *
 
6872
 *
 
6873
 *  Description:
 
6874
 *  -----------
 
6875
 *  Initialize key label substitutions used in acclerator text
 
6876
 *
 
6877
 *
 
6878
 *  Inputs:
 
6879
 *  ------
 
6880
 *  ppKeySubs   = ptr to key substitution table ptr
 
6881
 *  pNumKeySubs = ptr to number of key substitutions
 
6882
 *
 
6883
 * 
 
6884
 *  Outputs:
 
6885
 *  -------
 
6886
 *  *ppKeySubs          = ptr to key substitution table 
 
6887
 *  *pNumKeySubs        = number of substitutions found
 
6888
 *
 
6889
 *  Comments:
 
6890
 *  --------
 
6891
 *  *ppKeySubs is allocated with XtMalloc in a complicated way.
 
6892
 *  If this ever needs to be freed, a function to free it needs to
 
6893
 *  be written.
 
6894
 * 
 
6895
 *************************************<->***********************************/
 
6896
 
 
6897
static void InitKeySubs (
 
6898
    KeySub      **ppKeySubs,
 
6899
    int         *pNumKeySubs)
 
6900
{
 
6901
    int numKS;
 
6902
    KeySub *pKS;
 
6903
    KeySub *pKSret;
 
6904
    unsigned char *pch0;
 
6905
    unsigned char *pch1;
 
6906
    int len;
 
6907
#ifndef NO_MULTIBYTE
 
6908
    int         chlen;
 
6909
#endif 
 
6910
 
 
6911
    pch0 = (unsigned char *)GETMESSAGE(60, 40, "");
 
6912
 
 
6913
    if ((pch0 == NULL) || (*pch0 == '\0'))
 
6914
    {
 
6915
        *ppKeySubs = NULL;
 
6916
        *pNumKeySubs = 0;
 
6917
        return;
 
6918
    }
 
6919
 
 
6920
    pKSret = NULL;
 
6921
    numKS = 0;
 
6922
 
 
6923
    while (*pch0 != '\0')
 
6924
    {
 
6925
        ScanWhitespace (&pch0);
 
6926
        if (*pch0 == '\0') break;
 
6927
 
 
6928
        /* 
 
6929
         * allocate space for next key sub 
 
6930
         */
 
6931
        if (pKSret == NULL)
 
6932
        {
 
6933
            pKSret = (KeySub *) XtMalloc (1*sizeof(KeySub));
 
6934
        }
 
6935
        else
 
6936
        {
 
6937
            pKSret = (KeySub *) XtRealloc ((char *)pKSret, 
 
6938
                                           (numKS+1)*sizeof(KeySub));
 
6939
        }
 
6940
        pKS = &pKSret[numKS];
 
6941
 
 
6942
        /* get "from" string */
 
6943
        pch1 = pch0;
 
6944
#ifndef NO_MULTIBYTE
 
6945
        while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
 
6946
        {
 
6947
            if ((chlen == 1) && (*pch1 == ' '))
 
6948
            {
 
6949
                break;
 
6950
            }
 
6951
            pch1 += chlen;
 
6952
        }
 
6953
#else /* NO_MULTIBYTE */
 
6954
        while (*pch1 && (*pch1 != ' ')) pch1++;
 
6955
#endif /* NO_MULTIBYTE */
 
6956
        pKS->lenFrom = pch1 - pch0;
 
6957
        if (pKS->lenFrom < 1) 
 
6958
        {
 
6959
            /*
 
6960
             * no "from" string
 
6961
             */
 
6962
            break;
 
6963
        }
 
6964
        pKS->pchFrom = (unsigned char *) XtMalloc (1+pKS->lenFrom);
 
6965
        memcpy (pKS->pchFrom, pch0, pKS->lenFrom);
 
6966
        pKS->pchFrom[pKS->lenFrom] = '\0';
 
6967
 
 
6968
        /* get "to" string */
 
6969
        ScanWhitespace (&pch1);
 
6970
        pch0 = pch1;
 
6971
 
 
6972
#ifndef NO_MULTIBYTE
 
6973
        while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
 
6974
        {
 
6975
            if ((chlen == 1) && (*pch1 == ' '))
 
6976
            {
 
6977
                break;
 
6978
            }
 
6979
            pch1 += chlen;
 
6980
        }
 
6981
#else /* NO_MULTIBYTE */
 
6982
        while (*pch1 && (*pch1 != ' ')) pch1++;
 
6983
#endif /* NO_MULTIBYTE */
 
6984
 
 
6985
        len = pch1 - pch0;
 
6986
        if (len < 1)
 
6987
        {
 
6988
            /*
 
6989
             * Invalid format, "from" string with no "to" string.
 
6990
             */
 
6991
            break;
 
6992
        }
 
6993
        pKS->pchTo = (unsigned char *) XtMalloc (1+len);
 
6994
        memcpy (pKS->pchTo, pch0, len);
 
6995
        pKS->pchTo[len] = '\0';
 
6996
 
 
6997
        /* advance cursor */
 
6998
        pch0 = pch1;
 
6999
 
 
7000
        /* got one, bump the counter */
 
7001
        numKS++; 
 
7002
    }
 
7003
 
 
7004
    *ppKeySubs = pKSret;
 
7005
    *pNumKeySubs = numKS;
 
7006
}
 
7007
 
 
7008
#endif /* WSM */
 
7009
 
 
7010
/*************************************<->*************************************
 
7011
 *
 
7012
 *  ProcessAccelText (startP, endP, destP)
 
7013
 *
 
7014
 *
 
7015
 *  Description:
 
7016
 *  -----------
 
7017
 *  Process accelerator text and copy into string.
 
7018
 *
 
7019
 *
 
7020
 *  Inputs:
 
7021
 *  ------
 
7022
 *  startP = pointer to start of valid accelerator specification
 
7023
 *  endP =   pointer past end of accelerator specification
 
7024
 *  destP =  pointer to destination buffer
 
7025
 *
 
7026
 * 
 
7027
 *  Outputs:
 
7028
 *  -------
 
7029
 *  Destination buffer has processed accelerator text.
 
7030
 *
 
7031
 *  Comments:
 
7032
 *  --------
 
7033
 *  None.
 
7034
 * 
 
7035
 *************************************<->***********************************/
 
7036
 
 
7037
static void ProcessAccelText (unsigned char *startP, unsigned char *endP,
 
7038
                              unsigned char *destP)
 
7039
{
 
7040
#ifndef NO_MULTIBYTE
 
7041
    int   chlen;
 
7042
#endif
 
7043
#ifdef WSM
 
7044
    static Boolean      bAccelInit = False;
 
7045
    static KeySub       *pKeySub;
 
7046
    static int          numKeySubs;
 
7047
    unsigned char *     pchFirst;
 
7048
    unsigned char *     pchSub;
 
7049
    int                 lenSub;
 
7050
    int                 i;
 
7051
 
 
7052
    if (!bAccelInit)
 
7053
    {
 
7054
        InitKeySubs (&pKeySub, &numKeySubs);
 
7055
        bAccelInit = True;
 
7056
    }
 
7057
#endif /* WSM */
 
7058
 
 
7059
    /*
 
7060
     * Copy modifiers
 
7061
     */
 
7062
 
 
7063
    ScanWhitespace (&startP);
 
7064
 
 
7065
    while (*startP != '<')
 
7066
    {
 
7067
        if (*startP == '~') 
 
7068
        {
 
7069
            *destP++ = *startP++;
 
7070
        }
 
7071
#ifdef WSM
 
7072
        pchFirst = startP;
 
7073
#endif /* WSM */
 
7074
 
 
7075
#ifndef NO_MULTIBYTE
 
7076
        while (*startP &&
 
7077
               (((chlen = mblen ((char *)startP, MB_CUR_MAX)) > 1)
 
7078
                || isalnum (*startP)))
 
7079
        {
 
7080
            while (chlen--)
 
7081
            {
 
7082
#ifdef WSM
 
7083
                startP++;
 
7084
 
 
7085
#else /* WSM */
 
7086
                *destP++ = *startP++;
 
7087
#endif /* WSM */
 
7088
            }
 
7089
        }
 
7090
#else
 
7091
        while (isalnum (*startP))
 
7092
        {
 
7093
#ifdef WSM
 
7094
                startP++;
 
7095
#else /* WSM */
 
7096
            *destP++ = *startP++;
 
7097
#endif /* WSM */
 
7098
        }
 
7099
#endif
 
7100
#ifdef WSM
 
7101
        /* find substitution */
 
7102
        pchSub = NULL;
 
7103
        lenSub = 0;
 
7104
 
 
7105
        for (i=0; i<numKeySubs; i++)
 
7106
        {
 
7107
            if ((pKeySub[i].lenFrom == startP-pchFirst) &&
 
7108
                (!strncasecmp ((char *)pKeySub[i].pchFrom, (char *)pchFirst, 
 
7109
                                pKeySub[i].lenFrom)))
 
7110
            {
 
7111
                pchSub = pKeySub[i].pchTo;
 
7112
                lenSub = strlen((char *)pchSub);
 
7113
                break;
 
7114
            }
 
7115
 
 
7116
        }
 
7117
 
 
7118
        if ((pchSub != NULL) && (lenSub > 0))
 
7119
        {
 
7120
            memcpy (destP, pchSub, lenSub);
 
7121
            destP += lenSub;
 
7122
        }
 
7123
        else
 
7124
        {
 
7125
            memcpy (destP, pchFirst, startP-pchFirst);
 
7126
            destP += startP-pchFirst;
 
7127
        }
 
7128
#endif /* WSM */
 
7129
        *destP++ = '+';
 
7130
 
 
7131
        ScanWhitespace (&startP);
 
7132
    }
 
7133
 
 
7134
    /*
 
7135
     * Skip the key event type.
 
7136
     */
 
7137
    startP++;  /* skip '<' */
 
7138
    while (*startP != '>')
 
7139
    {
 
7140
#ifndef NO_MULTIBYTE
 
7141
        startP += mblen ((char *)startP, MB_CUR_MAX);
 
7142
#else
 
7143
        startP++;
 
7144
#endif
 
7145
    }
 
7146
    startP++;  /* skip '>' */
 
7147
 
 
7148
    /*
 
7149
     * Copy the KeySym string.
 
7150
     */
 
7151
 
 
7152
    ScanWhitespace (&startP);
 
7153
    while (startP != endP)
 
7154
    {
 
7155
        *destP++ = *startP++;
 
7156
    }
 
7157
    *destP = '\0';
 
7158
 
 
7159
} /* END OF FUNCTION ProcessAccelText */
 
7160
 
 
7161
 
 
7162
 
 
7163
/*************************************<->*************************************
 
7164
 *
 
7165
 *  ProcessCommandLine (argc, argv)
 
7166
 *
 
7167
 *
 
7168
 *  Description:
 
7169
 *  -----------
 
7170
 *  This function looks for and processes mwm options in the command line
 
7171
 *
 
7172
 *  Inputs:
 
7173
 *  ------
 
7174
 *  argc =   argument count.
 
7175
 *  argv =   argument vector.
 
7176
 *
 
7177
 * 
 
7178
 *  Outputs:
 
7179
 *  -------
 
7180
 *  Changes global data to based on command line options recognized
 
7181
 *
 
7182
 *
 
7183
 *************************************<->***********************************/
 
7184
#define SCREENS_OPT             "-screens"
 
7185
#define MULTI_SCREEN_OPT        "-multiscreen"
 
7186
 
 
7187
void ProcessCommandLine (int argc,  char *argv[])
 
7188
{
 
7189
    unsigned char *string;
 
7190
    int argnum;
 
7191
    unsigned char *lineP;
 
7192
 
 
7193
    for (argnum = 1; argnum < argc; argnum++)
 
7194
    {
 
7195
        lineP = (unsigned char *) argv[argnum];
 
7196
        if ((string = GetString (&lineP)) == NULL) 
 
7197
        /* empty or comment line */
 
7198
        {
 
7199
            continue;
 
7200
        }
 
7201
        if (!strcmp((char *)string, MULTI_SCREEN_OPT))
 
7202
        {
 
7203
            wmGD.multiScreen = True;
 
7204
            wmGD.numScreens = ScreenCount (DISPLAY);
 
7205
        }
 
7206
        else if (!strcmp((char *)string, SCREENS_OPT))
 
7207
        {
 
7208
            argnum++;           /* skip to next arg */
 
7209
            ParseScreensArgument (argc, argv, &argnum, lineP);
 
7210
        }
 
7211
    }
 
7212
 
 
7213
} /* END OF FUNCTION ProcessCommandLine */
 
7214
 
 
7215
 
 
7216
/*************************************<->*************************************
 
7217
 *
 
7218
 *  ParseScreensArgument (argc, argv, pArgnum, lineP)
 
7219
 *
 
7220
 *
 
7221
 *  Description:
 
7222
 *  -----------
 
7223
 *  This function processes the ``-screens'' command line argument
 
7224
 *
 
7225
 *  Inputs:
 
7226
 *  ------
 
7227
 *  argc =   argument count.
 
7228
 *  argv =   argument vector.
 
7229
 *  pArgnum = pointer to argument number where processing left off
 
7230
 *  lineP  = pointer into argv[*pArgnum] where processing left off
 
7231
 *
 
7232
 * 
 
7233
 *  Outputs:
 
7234
 *  -------
 
7235
 *  Changes global data to based on command line options recognized
 
7236
 *      + wmGD.screenNames
 
7237
 *      + wmGD.numScreens
 
7238
 *  Assumes default screenNames are already in place
 
7239
 *
 
7240
 *************************************<->***********************************/
 
7241
 
 
7242
static void ParseScreensArgument (int argc, char *argv[], int *pArgnum,
 
7243
                                  unsigned char *lineP)
 
7244
{
 
7245
    unsigned char *string;
 
7246
    int sNum = 0;
 
7247
    int lastLen;
 
7248
    int nameCount = 0;
 
7249
 
 
7250
    for (; (*pArgnum < argc) && (sNum < ScreenCount(DISPLAY)); 
 
7251
                                            (*pArgnum)++, sNum++)
 
7252
    {
 
7253
        lineP = (unsigned char *)argv[*pArgnum];
 
7254
        if (*argv[*pArgnum] == '"')
 
7255
        {
 
7256
            /*
 
7257
             * if Quote, use GetString to strip it
 
7258
             */
 
7259
            if ((string = GetString (&lineP)) == NULL) 
 
7260
                /* empty or comment line */
 
7261
            {
 
7262
                continue;
 
7263
            }
 
7264
        }
 
7265
        else 
 
7266
        {
 
7267
            string = (unsigned char *)argv[*pArgnum];
 
7268
            if (*string == '-')
 
7269
            {
 
7270
                /* another option, end of screens names */
 
7271
                break;
 
7272
            }
 
7273
        }
 
7274
        
 
7275
        if (!(wmGD.screenNames[sNum] = (unsigned char *) 
 
7276
              XtRealloc ((char*)wmGD.screenNames[sNum], 
 
7277
                         1 + strlen((char *)string))))
 
7278
        {
 
7279
            Warning (((char *)GETMESSAGE(60, 31, "Insufficient memory for screen names")));
 
7280
            ExitWM(WM_ERROR_EXIT_VALUE);
 
7281
        }
 
7282
        else 
 
7283
        {
 
7284
            strcpy((char *)wmGD.screenNames[sNum], (char *)string);
 
7285
            nameCount++;
 
7286
        }
 
7287
    }
 
7288
 
 
7289
    (*pArgnum)--;
 
7290
 
 
7291
    /*
 
7292
     * remaining screens (if any) get first name specified 
 
7293
     */
 
7294
    if (nameCount > 0)
 
7295
    {
 
7296
        lastLen = 1 + strlen((char *)wmGD.screenNames[0]);
 
7297
        for (; sNum < ScreenCount(DISPLAY); sNum++)
 
7298
        {
 
7299
            if (!(wmGD.screenNames[sNum] = (unsigned char *) 
 
7300
                XtRealloc ((char*)wmGD.screenNames[sNum], lastLen)))
 
7301
            {
 
7302
                Warning (((char *)GETMESSAGE(60, 32, "Insufficient memory for screen names")));
 
7303
                ExitWM(WM_ERROR_EXIT_VALUE);
 
7304
            }
 
7305
            else 
 
7306
            {
 
7307
                strcpy((char *)wmGD.screenNames[sNum], 
 
7308
                       (char *)wmGD.screenNames[0]);
 
7309
            }
 
7310
        }
 
7311
    }
 
7312
 
 
7313
} /* END OF FUNCTION ParseScreensArgument */
 
7314
 
 
7315
 
 
7316
/*************************************<->*************************************
 
7317
 *
 
7318
 *  ProcessMotifBindings ()
 
7319
 *
 
7320
 *
 
7321
 *  Description:
 
7322
 *  -----------
 
7323
 *  This function is used retrieve the motif input bindings
 
7324
 *  and put them into a property on the root window.
 
7325
 *
 
7326
 *
 
7327
 *************************************<->***********************************/
 
7328
void ProcessMotifBindings (void)
 
7329
{
 
7330
    char           fileName[MAXWMPATH+1];
 
7331
    char          *bindings = NULL;
 
7332
#ifndef MOTIF_ONE_DOT_ONE
 
7333
    char          *homeDir = XmeGetHomeDirName();
 
7334
#else
 
7335
    FILE          *fileP;
 
7336
#endif
 
7337
 
 
7338
    /*
 
7339
     *  Look in the user's home directory for .motifbind
 
7340
     */
 
7341
 
 
7342
#ifdef MOTIF_ONE_DOT_ONE
 
7343
    GetHomeDirName(fileName);
 
7344
#else
 
7345
    strcpy (fileName, homeDir);
 
7346
#endif
 
7347
    strncat(fileName, "/", MAXWMPATH-strlen(fileName));
 
7348
    strncat(fileName, MOTIF_BINDINGS_FILE, MAXWMPATH-strlen(fileName));
 
7349
 
 
7350
#ifdef MOTIF_ONE_DOT_ONE
 
7351
    if ((fileP = fopen (fileName, "r")) != NULL)
 
7352
    {
 
7353
        unsigned char   buffer[MBBSIZ];
 
7354
        int             count;
 
7355
        Boolean         first = True;
 
7356
        int             mode = PropModeReplace;
 
7357
        Window          propWindow;
 
7358
 
 
7359
        /*
 
7360
         * Get the atom for the property.
 
7361
         */
 
7362
        wmGD.xa_MOTIF_BINDINGS =
 
7363
                XInternAtom (DISPLAY, _XA_MOTIF_BINDINGS, False);
 
7364
 
 
7365
        /*
 
7366
         * The property goes on the root window of screen zero
 
7367
         */
 
7368
        propWindow = RootWindow(DISPLAY, 0);
 
7369
 
 
7370
        /*
 
7371
         * Copy file contents to property on root window of screen 0.
 
7372
         */
 
7373
        while ( (count=fread((char *) &buffer[0], 1, MBBSIZ, fileP)) > 0)
 
7374
        {
 
7375
            XChangeProperty (DISPLAY, propWindow, wmGD.xa_MOTIF_BINDINGS,
 
7376
                                XA_STRING, 8, mode,
 
7377
                                &buffer[0], count);
 
7378
 
 
7379
            if (first)
 
7380
            {
 
7381
                first = False;
 
7382
                mode = PropModeAppend;
 
7383
            }
 
7384
        }
 
7385
    }
 
7386
 
 
7387
#else
 
7388
    XDeleteProperty (DISPLAY, RootWindow (DISPLAY, 0),
 
7389
                XInternAtom (DISPLAY, "_MOTIF_BINDINGS", False));
 
7390
    XDeleteProperty (DISPLAY, RootWindow (DISPLAY, 0),
 
7391
                XInternAtom (DISPLAY, "_MOTIF_DEFAULT_BINDINGS", False));
 
7392
 
 
7393
    if (_XmVirtKeysLoadFileBindings (fileName, &bindings) == True) {
 
7394
        XChangeProperty (DISPLAY, RootWindow(DISPLAY, 0),
 
7395
                XInternAtom (DISPLAY, "_MOTIF_BINDINGS", False),
 
7396
                XA_STRING, 8, PropModeReplace,
 
7397
                (unsigned char *)bindings, strlen(bindings));
 
7398
    }
 
7399
    else {
 
7400
        _XmVirtKeysLoadFallbackBindings (DISPLAY, &bindings);
 
7401
    }
 
7402
    XtFree (bindings);
 
7403
#endif
 
7404
} /* END OF FUNCTION ProcessMotifBindings */
 
7405
 
 
7406
#ifdef PANELIST
 
7407
 
 
7408
/*************************************<->*************************************
 
7409
 *
 
7410
 *  void
 
7411
 *  ParseWmFunctionArg (linePP, ix, wmFunc, ppArg, sClientName)
 
7412
 *
 
7413
 *
 
7414
 *  Description:
 
7415
 *  -----------
 
7416
 *  Parse the function arguments for a window manager function.
 
7417
 *
 
7418
 *
 
7419
 *  Inputs:
 
7420
 *  ------
 
7421
 *  linePP   = pointer to line buffer pointer (contains string arg).
 
7422
 *  ix = window manager function index (returned by ParseWmFunction)
 
7423
 *  pWmFunction = pointer to window manager function destination.
 
7424
 *  ppArg = ptr to argument pointer.
 
7425
 *  sClientName = string name of client 
 
7426
 *
 
7427
 *
 
7428
 *  Outputs:
 
7429
 *  -------
 
7430
 *  *ppArg = arg to pass to window manager function when invoking.
 
7431
 *  Return = true on succes, false on some kind of parse error
 
7432
 *
 
7433
 *
 
7434
 *  Comments:
 
7435
 *  --------
 
7436
 *  functionTable (window manager function table) is indexed with ix
 
7437
 *  to get parsing info.
 
7438
 *
 
7439
 *  This function may malloc memory for the returned arg.
 
7440
 *
 
7441
 *  The sClientName is needed for starting some hpterm-based push_recall
 
7442
 *  clients. It needs to be passed into the action so the hpterm gets
 
7443
 *  named appropriately.
 
7444
 * 
 
7445
 *************************************<->***********************************/
 
7446
 
 
7447
Boolean
 
7448
ParseWmFunctionArg (
 
7449
                unsigned char **linePP,
 
7450
                int ix, 
 
7451
                WmFunction wmFunc, 
 
7452
                void **ppArg,
 
7453
                String sClientName,
 
7454
                String sTitle)
 
7455
{
 
7456
    unsigned char *lineP = *linePP;
 
7457
    Boolean bValidArg = True;
 
7458
    unsigned char *str = NULL;
 
7459
 
 
7460
    /*
 
7461
     * If this is (possibly) a string argument, put it 
 
7462
     * in quotes so that it will be parsed properly.
 
7463
     */
 
7464
    if ((functionTable[ix].parseProc == ParseWmFuncStrArg) ||
 
7465
        (functionTable[ix].parseProc == ParseWmFuncMaybeStrArg))
 
7466
    {
 
7467
        if (lineP && *lineP != '"')
 
7468
        {
 
7469
            /*
 
7470
             * not in quotes, repackage it, escaping the appropriate
 
7471
             * characters.
 
7472
             */
 
7473
            str = _DtWmParseMakeQuotedString (lineP);
 
7474
            if (str)
 
7475
            {
 
7476
                lineP = str;
 
7477
            }
 
7478
        }
 
7479
    }
 
7480
 
 
7481
    /* 
 
7482
     * Apply the function argument parser.
 
7483
     */
 
7484
    if ((functionTable[ix].wmFunction != wmFunc) ||
 
7485
        !(*(functionTable [ix].parseProc)) (&lineP, wmFunc, ppArg))
 
7486
    {
 
7487
        bValidArg = False;
 
7488
    }
 
7489
 
 
7490
    /*
 
7491
     * Add the exec parms if this is an f.action
 
7492
     */
 
7493
    if ((wmFunc == F_Action) && ppArg && *ppArg)
 
7494
    {
 
7495
        WmActionArg *pAP = (WmActionArg *) *ppArg;
 
7496
        int totLen = 0;
 
7497
 
 
7498
        /*
 
7499
         * allocate more than enough string space to copy 
 
7500
         * strings and intervening spaces.
 
7501
         */
 
7502
        if (sClientName && *sClientName)
 
7503
        {
 
7504
            /* length of: "name=" + sClientName + NULL */
 
7505
            totLen += 5 + strlen(sClientName) + 1;
 
7506
        }
 
7507
        if (sTitle && *sTitle)
 
7508
        {
 
7509
            /* length of: "," + "title=" + sTitle + NULL */
 
7510
            totLen += 1 + 6 + strlen(sTitle) + 1;
 
7511
        }
 
7512
 
 
7513
        if (totLen > 0)
 
7514
        {
 
7515
            pAP->szExecParms = (String) XtMalloc (totLen);
 
7516
            /* start with empty string */
 
7517
            pAP->szExecParms[0] = '\0'; 
 
7518
 
 
7519
            if (sClientName && *sClientName)
 
7520
            {
 
7521
                strcat (pAP->szExecParms, "name=");
 
7522
                strcat (pAP->szExecParms, sClientName);
 
7523
            }
 
7524
            if (sTitle && *sTitle)
 
7525
            {
 
7526
                if (pAP->szExecParms[0] != '\0')
 
7527
                {
 
7528
                    strcat (pAP->szExecParms, ",");
 
7529
                }
 
7530
                strcat (pAP->szExecParms, "title=");
 
7531
                strcat (pAP->szExecParms, sTitle);
 
7532
            }
 
7533
        }
 
7534
    }
 
7535
 
 
7536
    if (str)
 
7537
    {
 
7538
        XtFree ((char *) str);
 
7539
    }
 
7540
 
 
7541
    return (bValidArg);
 
7542
 
 
7543
} /* END OF FUNCTION ParseWmFunctionArg */
 
7544
 
 
7545
 
 
7546
/*************************************<->*************************************
 
7547
 *
 
7548
 *  SystemCmd (pchCmd)
 
7549
 *
 
7550
 *
 
7551
 *  Description:
 
7552
 *  -----------
 
7553
 *  This function fiddles with our signal handling and calls the
 
7554
 *  system() function to invoke a unix command.
 
7555
 *
 
7556
 *
 
7557
 *  Inputs:
 
7558
 *  ------
 
7559
 *  pchCmd = string with the command we want to exec.
 
7560
 *
 
7561
 *  Outputs:
 
7562
 *  -------
 
7563
 *
 
7564
 *
 
7565
 *  Comments:
 
7566
 *  --------
 
7567
 *  The system() command is touchy about the SIGCLD behavior. Restore
 
7568
 *  the default SIGCLD handler during the time we run system().
 
7569
 * 
 
7570
 *************************************<->***********************************/
 
7571
 
 
7572
void
 
7573
SystemCmd (char *pchCmd)
 
7574
{
 
7575
    struct sigaction sa;
 
7576
    struct sigaction osa;
 
7577
 
 
7578
    (void) sigemptyset(&sa.sa_mask);
 
7579
    sa.sa_flags = 0;
 
7580
    sa.sa_handler = SIG_DFL;
 
7581
 
 
7582
    (void) sigaction (SIGCLD, &sa, &osa);
 
7583
 
 
7584
    system (pchCmd);
 
7585
 
 
7586
    (void) sigaction (SIGCLD, &osa, (struct sigaction *) 0);
 
7587
}
 
7588
 
 
7589
 
 
7590
 
 
7591
/*************************************<->*************************************
 
7592
 *
 
7593
 *  DeleteTempConfigFileIfAny ()
 
7594
 *
 
7595
 *
 
7596
 *  Description:
 
7597
 *  -----------
 
7598
 *  This function deletes the temporary config file used to process 
 
7599
 *  old dtwmrc syntax.
 
7600
 *
 
7601
 *
 
7602
 *  Inputs:
 
7603
 *  ------
 
7604
 *
 
7605
 *
 
7606
 *  Outputs:
 
7607
 *  -------
 
7608
 *
 
7609
 *
 
7610
 *  Comments:
 
7611
 *  --------
 
7612
 * 
 
7613
 *************************************<->***********************************/
 
7614
 
 
7615
void
 
7616
DeleteTempConfigFileIfAny (void)
 
7617
{
 
7618
    char pchCmd[MAXWMPATH+1];
 
7619
 
 
7620
    if (pConfigStackTop->tempName)
 
7621
    {
 
7622
        strcpy (pchCmd, "/bin/rm ");
 
7623
        strcat (pchCmd, pConfigStackTop->tempName);
 
7624
        SystemCmd (pchCmd);
 
7625
        XtFree ((char *) pConfigStackTop->tempName);
 
7626
        pConfigStackTop->tempName = NULL;
 
7627
    }
 
7628
    if (pConfigStackTop->cppName)
 
7629
    {
 
7630
        strcpy (pchCmd, "/bin/rm ");
 
7631
        strcat (pchCmd, pConfigStackTop->cppName);
 
7632
        SystemCmd (pchCmd);
 
7633
        XtFree ((char *) pConfigStackTop->cppName);
 
7634
        pConfigStackTop->cppName = NULL;
 
7635
    }
 
7636
}
 
7637
 
 
7638
 
 
7639
/*************************************<->*************************************
 
7640
 *
 
7641
 *  ParseIncludeSet (pSD, lineP)
 
7642
 *
 
7643
 *
 
7644
 *  Description:
 
7645
 *  -----------
 
7646
 *
 
7647
 *
 
7648
 *  Inputs:
 
7649
 *  ------
 
7650
 *  cfileP = (global) file pointer to fopened configuration file or NULL
 
7651
 *  lineP = pointer to line buffer
 
7652
 *  line   = (global) line buffer
 
7653
 *  linec  = (global) line count
 
7654
 *  parseP = (global) parse string pointer if cfileP == NULL
 
7655
 *  pSD->rootWindow = default root window of display
 
7656
 * 
 
7657
 *  Outputs:
 
7658
 *  -------
 
7659
 *  linec  = (global) line count incremented
 
7660
 *  parseP = (global) parse string pointer if cfileP == NULL
 
7661
 *
 
7662
 *
 
7663
 *  Comments:
 
7664
 *  --------
 
7665
 * 
 
7666
 *************************************<->***********************************/
 
7667
 
 
7668
static void ParseIncludeSet (WmScreenData *pSD, unsigned char *lineP) 
 
7669
{
 
7670
    unsigned char     *string;
 
7671
    unsigned char     *pchName;
 
7672
 
 
7673
    /*
 
7674
     * Require leading '{' on the next line.
 
7675
     */
 
7676
 
 
7677
    while ((GetNextLine () != NULL))  /* not EOF nor read error */
 
7678
    {
 
7679
        lineP = line;
 
7680
        ScanWhitespace(&lineP);
 
7681
 
 
7682
        if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
 
7683
        /* ignore empty or comment line */
 
7684
        {
 
7685
            continue;
 
7686
        }
 
7687
 
 
7688
        if (*lineP == '{')
 
7689
        /* found '{' */
 
7690
        {
 
7691
            break;
 
7692
        }
 
7693
 
 
7694
        /* not a '{' */
 
7695
        PWarning (((char *)GETMESSAGE(60, 37, "Expected '{'")));
 
7696
        return;
 
7697
    }
 
7698
 
 
7699
    /*
 
7700
     * Found leading "{" or EOF.
 
7701
     * Parse include files until "}" or EOF found.
 
7702
     */
 
7703
    while ((GetNextLine () != NULL))
 
7704
    {
 
7705
        lineP = line;
 
7706
        if ((*line == '!') || (string = GetString (&lineP)) == NULL)
 
7707
        /* ignore empty or comment lines */
 
7708
        {
 
7709
            continue;
 
7710
        }
 
7711
        if (*string == '}')  /* finished with set. */
 
7712
        {
 
7713
            break;
 
7714
        }
 
7715
        pchName = _DtWmParseFilenameExpand (string);
 
7716
        if (pchName && ConfigStackPush (pchName))
 
7717
        {
 
7718
            ProcessWmFile (pSD, True /* nested */);
 
7719
            ConfigStackPop ();
 
7720
            XtFree ((char *) pchName);
 
7721
        }
 
7722
 
 
7723
    }
 
7724
 
 
7725
}
 
7726
 
 
7727
 
 
7728
 
 
7729
/*************************************<->*************************************
 
7730
 *
 
7731
 *  ConfigStackInit (pchFileName)
 
7732
 *
 
7733
 *
 
7734
 *  Description:
 
7735
 *  -----------
 
7736
 *  Initializes the config file processing stack
 
7737
 *
 
7738
 *  Inputs:
 
7739
 *  ------
 
7740
 *  pchFileName = name of new file to start parsing
 
7741
 * 
 
7742
 *  Outputs:
 
7743
 *  -------
 
7744
 *
 
7745
 *
 
7746
 *  Comments:
 
7747
 *  --------
 
7748
 * 
 
7749
 *************************************<->***********************************/
 
7750
 
 
7751
static void ConfigStackInit (char *pchFileName)
 
7752
{
 
7753
 
 
7754
    pConfigStack  = XtNew (ConfigFileStackEntry);
 
7755
 
 
7756
    if (pConfigStack)
 
7757
    {
 
7758
        pConfigStackTop = pConfigStack;
 
7759
        pConfigStackTop->fileName = XtNewString (pchFileName);
 
7760
        pConfigStackTop->tempName = NULL;
 
7761
        pConfigStackTop->cppName = NULL;
 
7762
        pConfigStackTop->offset = 0;
 
7763
        pConfigStackTop->pWmPB = wmGD.pWmPB;
 
7764
        pConfigStackTop->wmgdConfigFile = wmGD.configFile;
 
7765
        pConfigStackTop->pIncluder = NULL;
 
7766
 
 
7767
    }
 
7768
    else
 
7769
    {
 
7770
        sprintf ((char *)wmGD.tmpBuffer,
 
7771
            (char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"), 
 
7772
            pchFileName);
 
7773
        Warning ((char *)wmGD.tmpBuffer);
 
7774
    }
 
7775
}
 
7776
 
 
7777
 
 
7778
/*************************************<->*************************************
 
7779
 *
 
7780
 *  ConfigStackPush (pchFileName)
 
7781
 *
 
7782
 *
 
7783
 *  Description:
 
7784
 *  -----------
 
7785
 *  Open an included config file
 
7786
 *
 
7787
 *  Inputs:
 
7788
 *  ------
 
7789
 *  pchFileName = name of new file to start parsing
 
7790
 *  wmGD.pWmPB = global parse buffer (pickle this)
 
7791
 * 
 
7792
 *  Outputs:
 
7793
 *  -------
 
7794
 *  wmGD.pWmPB = global parse buffer (new one for new file)
 
7795
 *  return = FILE * to open file or NULL
 
7796
 *
 
7797
 *
 
7798
 *  Comments:
 
7799
 *  --------
 
7800
 * 
 
7801
 *************************************<->***********************************/
 
7802
 
 
7803
static FILE *
 
7804
ConfigStackPush (unsigned char *pchFileName)
 
7805
{
 
7806
    ConfigFileStackEntry *pEntry;
 
7807
    FILE *pNewFile = NULL;
 
7808
 
 
7809
    pEntry = XtNew (ConfigFileStackEntry);
 
7810
    if (pEntry)
 
7811
    {
 
7812
        /* save off state of current config file */
 
7813
        pConfigStackTop->offset = ftell (cfileP);
 
7814
        pConfigStackTop->pWmPB = wmGD.pWmPB;
 
7815
        fclose (cfileP);
 
7816
 
 
7817
        /* set up state of new config file */
 
7818
        pEntry->fileName = XtNewString ((char *)pchFileName);
 
7819
        pEntry->tempName = NULL;
 
7820
        pEntry->cppName = NULL;
 
7821
        pEntry->wmgdConfigFile = (String) pEntry->fileName;
 
7822
 
 
7823
        /* set globals for new config file */
 
7824
        wmGD.pWmPB = _DtWmParseNewBuf ();
 
7825
        wmGD.configFile = pEntry->wmgdConfigFile;
 
7826
 
 
7827
        /* put new entry onto stack */
 
7828
        pEntry->pIncluder = pConfigStackTop;
 
7829
        pConfigStackTop = pEntry;
 
7830
 
 
7831
        /* open the file */
 
7832
        pNewFile = cfileP = FopenConfigFile();
 
7833
 
 
7834
        if (!pNewFile)
 
7835
        {
 
7836
            /* file open failed! back out */
 
7837
            ConfigStackPop ();
 
7838
        }
 
7839
    }
 
7840
    else
 
7841
    {
 
7842
        sprintf ((char *)wmGD.tmpBuffer,
 
7843
            (char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"), 
 
7844
            pchFileName);
 
7845
        Warning ((char *)wmGD.tmpBuffer);
 
7846
    }
 
7847
 
 
7848
    return (pNewFile);
 
7849
}
 
7850
 
 
7851
 
 
7852
 
 
7853
/*************************************<->*************************************
 
7854
 *
 
7855
 *  ConfigStackPop ()
 
7856
 *
 
7857
 *
 
7858
 *  Description:
 
7859
 *  -----------
 
7860
 *
 
7861
 *
 
7862
 *  Inputs:
 
7863
 *  ------
 
7864
 *  pchFileName = name of new file to start parsing
 
7865
 *  wmGD.pWmPB = global parse buffer (pickle this)
 
7866
 * 
 
7867
 *  Outputs:
 
7868
 *  -------
 
7869
 *  wmGD.pWmPB = global parse buffer (new one for new file)
 
7870
 *
 
7871
 *
 
7872
 *  Comments:
 
7873
 *  --------
 
7874
 *  assumes cfileP is closed already
 
7875
 * 
 
7876
 *************************************<->***********************************/
 
7877
 
 
7878
static void ConfigStackPop (void)
 
7879
{
 
7880
    Boolean error = False;
 
7881
    ConfigFileStackEntry *pPrev;
 
7882
    char pchCmd[MAXWMPATH+1];
 
7883
 
 
7884
    if (pConfigStackTop != pConfigStack)
 
7885
    {
 
7886
        pPrev = pConfigStackTop->pIncluder;
 
7887
 
 
7888
        _DtWmParseDestroyBuf (wmGD.pWmPB);
 
7889
        if (pConfigStackTop->tempName)
 
7890
        {
 
7891
            XtFree (pConfigStackTop->tempName);
 
7892
        }
 
7893
        if (pConfigStackTop->cppName)
 
7894
        {
 
7895
            strcpy (pchCmd, "/bin/rm "); 
 
7896
            strcat (pchCmd, pConfigStackTop->cppName); 
 
7897
            SystemCmd (pchCmd);
 
7898
            XtFree ((char *) pConfigStackTop->cppName);
 
7899
            pConfigStackTop->cppName = NULL;
 
7900
        }
 
7901
        if (pConfigStackTop->fileName)
 
7902
        {
 
7903
            XtFree (pConfigStackTop->fileName);
 
7904
        }
 
7905
 
 
7906
        wmGD.pWmPB = pPrev->pWmPB;
 
7907
        wmGD.configFile = pPrev->wmgdConfigFile;
 
7908
        if (pPrev->tempName)
 
7909
        {
 
7910
            cfileP = fopen (pPrev->tempName, "r");
 
7911
        }
 
7912
        else if (pPrev->cppName)
 
7913
        {
 
7914
            cfileP = fopen (pPrev->cppName, "r");
 
7915
        }
 
7916
        else
 
7917
        {
 
7918
            cfileP = fopen (pPrev->fileName, "r");
 
7919
        }
 
7920
        if (cfileP) 
 
7921
        {
 
7922
            fseek (cfileP, pPrev->offset, 0);
 
7923
        }
 
7924
        else
 
7925
        {
 
7926
            char msg[MAXWMPATH+1];
 
7927
 
 
7928
            sprintf(msg, ((char *)GETMESSAGE(60, 39, 
 
7929
                            "Could not reopen configuration file %s")),
 
7930
                pPrev->fileName);
 
7931
            Warning (msg);
 
7932
        }
 
7933
 
 
7934
        XtFree ((char *)pConfigStackTop);
 
7935
        pConfigStackTop = pPrev;
 
7936
    }
 
7937
}
 
7938
 
 
7939
 
 
7940
/*************************************<->*************************************
 
7941
 *
 
7942
 *  ParseWmFuncActionArg (linePP, wmFunction, pArgs)
 
7943
 *
 
7944
 *
 
7945
 *  Description:
 
7946
 *  -----------
 
7947
 *  Parses a window manager f.action argument
 
7948
 *
 
7949
 *
 
7950
 *  Inputs:
 
7951
 *  ------
 
7952
 *  linePP   = pointer to current line buffer pointer.
 
7953
 *  wmFunction = function for which the argument string is intended.
 
7954
 *  pArgs = pointer to argument destination.
 
7955
 *
 
7956
 * 
 
7957
 *  Outputs:
 
7958
 *  -------
 
7959
 *  linePP   = pointer to revised line buffer pointer.
 
7960
 *  pArgs    = pointer to parsed argument.
 
7961
 *  Return   = FALSE iff insufficient memory
 
7962
 *
 
7963
 *
 
7964
 *  Comments:
 
7965
 *  --------
 
7966
 * 
 
7967
 *************************************<->***********************************/
 
7968
 
 
7969
Boolean ParseWmFuncActionArg (unsigned char **linePP, 
 
7970
                                  WmFunction wmFunction, String *pArgs)
 
7971
{
 
7972
#define WM_ACTION_ARG_INCREMENT 5
 
7973
#define WM_ACTION_ARG_PAD       256
 
7974
    unsigned char *string;
 
7975
    char *pch;
 
7976
    WmActionArg *pAP;
 
7977
    int iArgSz;
 
7978
 
 
7979
    pAP = XtNew (WmActionArg);
 
7980
    if (pAP && (string = GetString (linePP)) != NULL)
 
7981
    {
 
7982
        /* Got action name */
 
7983
        pAP->actionName = XtNewString ((char *) string);
 
7984
 
 
7985
        /* Get action arguments, if any */
 
7986
        if (pAP->aap = (DtActionArg *) 
 
7987
                XtMalloc (WM_ACTION_ARG_INCREMENT * sizeof (DtActionArg)))
 
7988
        {
 
7989
            iArgSz = WM_ACTION_ARG_INCREMENT;
 
7990
            pAP->numArgs = 0;
 
7991
 
 
7992
            while ((string = GetString (linePP)) != NULL)
 
7993
            {
 
7994
               if (pAP->aap[pAP->numArgs].u.file.name = (char *)
 
7995
                       XtMalloc(1 + strlen((char *)string)))
 
7996
               {
 
7997
                   pAP->aap[pAP->numArgs].argClass = DtACTION_FILE;
 
7998
 
 
7999
                   /* format the action argument */
 
8000
                   pch = pAP->aap[pAP->numArgs].u.file.name;
 
8001
 
 
8002
                   /* 
 
8003
                    * Expand environment variable
 
8004
                    */
 
8005
                   if (string[0] == '$')
 
8006
                   {
 
8007
                       string = (unsigned char *) getenv ((char *)&string[1]);
 
8008
                       if (!string)
 
8009
                       {
 
8010
                           break;
 
8011
                       }
 
8012
                       else
 
8013
                       {
 
8014
                           /*
 
8015
                            * Make sure there's room for the new
 
8016
                            * string.
 
8017
                            */
 
8018
                           pch = (char *) 
 
8019
                             XtRealloc (pch, (1+strlen((char *)string)));
 
8020
                           pAP->aap[pAP->numArgs].u.file.name = pch;
 
8021
                       }
 
8022
                   }
 
8023
 
 
8024
                   /* !!! No host name processing is done!!! */
 
8025
 
 
8026
                   strcpy (pch, (char *)string);
 
8027
 
 
8028
                   pAP->numArgs++;
 
8029
                   if (pAP->numArgs == iArgSz)
 
8030
                   {
 
8031
                       /* need to increase our array space */
 
8032
                       iArgSz += WM_ACTION_ARG_INCREMENT;
 
8033
                       pAP->aap = (DtActionArg *) 
 
8034
                           XtRealloc((char *)pAP->aap,
 
8035
                                     (iArgSz * sizeof (DtActionArg)));
 
8036
                       if (!pAP->aap)
 
8037
                       {
 
8038
                           break; /* out of memory */
 
8039
                       }
 
8040
                   }
 
8041
               }
 
8042
               else
 
8043
               {
 
8044
                   break; /* out of memory */
 
8045
               }
 
8046
            }
 
8047
 
 
8048
        }
 
8049
        pAP->szExecParms = NULL;
 
8050
        *pArgs = (String) pAP;
 
8051
    }
 
8052
    else
 
8053
    /* NULL string argument */
 
8054
    {
 
8055
        *pArgs = NULL;
 
8056
    }
 
8057
 
 
8058
    return (TRUE);
 
8059
 
 
8060
} /* END OF FUNCTION ParseWmFuncActionArg */
 
8061
 
 
8062
 
 
8063
#endif /* PANELIST */
 
8064
#ifdef WSM
 
8065
 
 
8066
/*************************************<->*************************************
 
8067
 *
 
8068
 *  PreprocessConfigFile (pSD)
 
8069
 *
 
8070
 *
 
8071
 *  Description:
 
8072
 *  -----------
 
8073
 *  This function runs the configuration file through the C
 
8074
 *  preprocessor
 
8075
 *
 
8076
 *
 
8077
 *  Inputs:
 
8078
 *  ------
 
8079
 *  pSD = ptr to screen data
 
8080
 *
 
8081
 *  Outputs:
 
8082
 *  -------
 
8083
 *
 
8084
 *
 
8085
 *  Comments:
 
8086
 *  --------
 
8087
 * 
 
8088
 *************************************<->***********************************/
 
8089
 
 
8090
static void
 
8091
PreprocessConfigFile (void)
 
8092
{
 
8093
#define CPP_NAME_SIZE   ((L_tmpnam)+1)
 
8094
    char pchCmd[MAXWMPATH+1];
 
8095
 
 
8096
    if (wmGD.cppCommand && *wmGD.cppCommand)
 
8097
    {
 
8098
        /*
 
8099
         * Generate a temp file name.
 
8100
         */
 
8101
        pConfigStackTop->cppName = XtMalloc (CPP_NAME_SIZE * sizeof(char));
 
8102
        if (pConfigStackTop->cppName)
 
8103
        {
 
8104
            (void) tmpnam (pConfigStackTop->cppName);
 
8105
 
 
8106
            /*
 
8107
             * Build up the command line.
 
8108
             */
 
8109
            strcpy (pchCmd, wmGD.cppCommand);
 
8110
            strcat (pchCmd, " ");
 
8111
            strcat (pchCmd, pConfigStackTop->fileName);
 
8112
            strcat (pchCmd, " ");
 
8113
            strcat (pchCmd, pConfigStackTop->cppName);
 
8114
 
 
8115
            /*
 
8116
             * Run the config file through the converter program
 
8117
             * and send the output to a temp file. 
 
8118
             */
 
8119
            SystemCmd (pchCmd);
 
8120
        }
 
8121
    }
 
8122
}
 
8123
 
 
8124
 
 
8125
/*************************************<->*************************************
 
8126
 *
 
8127
 *  GetNetworkFileName (char *pchFile)
 
8128
 *
 
8129
 *
 
8130
 *  Description:
 
8131
 *  -----------
 
8132
 *  This function returns a local representation for a network
 
8133
 *  file. 
 
8134
 *
 
8135
 *
 
8136
 *  Inputs:
 
8137
 *  ------
 
8138
 *  pchFile     - pointer to file name of form [<host>:]<path>
 
8139
 *
 
8140
 *  Return:
 
8141
 *  -------
 
8142
 *  String      - ptr to allocated string of local file name. If input
 
8143
 *                is not a network file, the a copy of pchFile is returned.
 
8144
 *
 
8145
 *
 
8146
 *  Comments:
 
8147
 *  --------
 
8148
 *  returned file name should be freed with XtFree().
 
8149
 * 
 
8150
 *************************************<->***********************************/
 
8151
 
 
8152
static String
 
8153
GetNetworkFileName (char *pchFile)
 
8154
{
 
8155
    char *pch;
 
8156
    char *host_part; 
 
8157
    char *file_part; 
 
8158
    char *netfile;
 
8159
    char *sName = NULL;
 
8160
    char *pchName = NULL;
 
8161
    int count;
 
8162
    char **pchTok;
 
8163
    String sReturn = NULL;
 
8164
    char *homeDir;
 
8165
    int len;
 
8166
 
 
8167
 
 
8168
    pch = strchr (pchFile, ':');
 
8169
 
 
8170
    if (pch)
 
8171
    {
 
8172
        /*
 
8173
         * Expand special chars and find matching file.
 
8174
         */
 
8175
        pchTok = (char **)shellscan (pchFile, &count, 0);
 
8176
 
 
8177
        if ((count == 1) || (count == 2))
 
8178
        {
 
8179
            /* one match found */
 
8180
            host_part = pchTok[0];
 
8181
        }
 
8182
        else if (count > 2)
 
8183
        {
 
8184
            /* several matches found, pick one */
 
8185
            host_part = pchTok[1];
 
8186
        }
 
8187
        else
 
8188
        {
 
8189
            host_part = NULL;
 
8190
        }
 
8191
 
 
8192
        if (host_part != NULL)
 
8193
        {
 
8194
            pch = strchr (host_part, ':');
 
8195
            if (pch)
 
8196
            {
 
8197
                /* 
 
8198
                 * copy the string so we don't munge data
 
8199
                 * inside shellscan 
 
8200
                 */
 
8201
                host_part = sName = XtNewString ((String) host_part);
 
8202
                pch = strchr (sName, ':');
 
8203
 
 
8204
                /*
 
8205
                 * separate the host and file parts of the
 
8206
                 * file name
 
8207
                 */
 
8208
                *pch = '\0';
 
8209
                file_part = pch+1;
 
8210
            }
 
8211
            else
 
8212
            {
 
8213
                /*
 
8214
                 * The colon went away. Hmm...
 
8215
                 */
 
8216
                file_part = host_part;
 
8217
                host_part = NULL;
 
8218
            }
 
8219
 
 
8220
            if (
 
8221
#ifndef NO_MULTIBYTE
 
8222
                (mblen(file_part, MB_CUR_MAX) == 1) && 
 
8223
                (mblen(file_part+1, MB_CUR_MAX) == 1) &&
 
8224
#endif
 
8225
                (*file_part == '~') &&
 
8226
                (*(file_part+1) == '/'))
 
8227
            {
 
8228
                /*
 
8229
                 * Replace '~' with $HOME
 
8230
                 */
 
8231
                homeDir = XmeGetHomeDirName();
 
8232
                len = strlen (host_part) + 1 +
 
8233
                      strlen (homeDir) + strlen (file_part) + 1;
 
8234
                pch = (char *) XtMalloc (len);
 
8235
                strcpy (pch, sName);
 
8236
                host_part = pch;
 
8237
                pch += strlen (pch) + 1;
 
8238
                strcpy (pch, homeDir);
 
8239
                strcat (pch, file_part+1);
 
8240
                file_part = pch;
 
8241
                XtFree (sName);
 
8242
                sName = host_part;
 
8243
            }
 
8244
        }
 
8245
        else
 
8246
        {
 
8247
            /*
 
8248
             * shellscan had a problem with the file name.
 
8249
             * just operate on the name as-is.
 
8250
             * temporarily replace ':' with a NULL 
 
8251
             */
 
8252
            host_part = sName = XtNewString ((String) pchFile);
 
8253
            pch = strchr (sName, ':');
 
8254
            *pch = '\0';
 
8255
            host_part = pchFile;
 
8256
            file_part = pch+1;
 
8257
        }
 
8258
 
 
8259
        /* convert to canonical host/file name */
 
8260
        netfile = (char *) 
 
8261
                    tt_host_file_netfile (host_part, file_part);
 
8262
        if (tt_pointer_error (netfile) == TT_OK)
 
8263
        {
 
8264
            /* convert to local file name equivalent */
 
8265
            pchName = tt_netfile_file (netfile);
 
8266
 
 
8267
            if (tt_pointer_error (pchName) == TT_OK)
 
8268
            {
 
8269
                sReturn = XtNewString ((String) pchName);
 
8270
                tt_free ((char *)pchName);
 
8271
            }
 
8272
            tt_free (netfile);
 
8273
        }
 
8274
 
 
8275
        if (sName)
 
8276
        {
 
8277
            XtFree ((char *)sName);
 
8278
        }
 
8279
    }
 
8280
 
 
8281
    if (sReturn == NULL)
 
8282
    {
 
8283
        if (
 
8284
#ifndef NO_MULTIBYTE
 
8285
            (mblen(pchFile, MB_CUR_MAX) == 1) && 
 
8286
            (mblen(pchFile+1, MB_CUR_MAX) == 1) &&
 
8287
#endif
 
8288
            (*pchFile == '~') &&
 
8289
            (*(pchFile+1) == '/'))
 
8290
        {
 
8291
            /*
 
8292
             * Replace '~' with $HOME
 
8293
             */
 
8294
            homeDir = XmeGetHomeDirName();
 
8295
            len = strlen (homeDir) + strlen (pchFile) + 1;
 
8296
            sReturn = (char *) XtMalloc (len);
 
8297
            strcpy (sReturn, homeDir);
 
8298
            strcat (sReturn, pchFile+1);
 
8299
        }
 
8300
        else
 
8301
        {
 
8302
            sReturn = XtNewString ((String) pchFile);
 
8303
        }
 
8304
    }
 
8305
 
 
8306
    return (sReturn);
 
8307
}
 
8308
/****************************   eof    ***************************/
 
8309
#endif /* WSM */
 
8310
 
 
8311
 
 
8312
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
 
8313
/*************************************<->*************************************
 
8314
 *
 
8315
 *  SetGreyedContextAndMgtMask (menuItem, wmFunction)
 
8316
 *
 
8317
 *
 
8318
 *  Description:
 
8319
 *  -----------
 
8320
 *  This function sets up the greyed context and management mask
 
8321
 *  for a menu item based on the menu function passed in.
 
8322
 *
 
8323
 *  Inputs:
 
8324
 *  ------
 
8325
 *  menuItem   = the menu item to be set up 
 
8326
 *  wmFunction = the menu function to find in the function table
 
8327
 *               to determine how to set up the relevant fields
 
8328
 * 
 
8329
 *  Outputs:
 
8330
 *  -------
 
8331
 *  The menuItem will have its greyed context and management mask fields
 
8332
 *  set appropriately. If the given function cannot be found, the fields
 
8333
 *  will be set to the appropriate values as if the function were F_Nop.
 
8334
 *  Return = True if the function could be found. False otherwise.
 
8335
 *
 
8336
 *************************************<->***********************************/
 
8337
 
 
8338
Boolean SetGreyedContextAndMgtMask (MenuItem *menuItem,
 
8339
                                    WmFunction wmFunction)
 
8340
{
 
8341
    int ix;
 
8342
 
 
8343
    for (ix = 0; ix < WMFUNCTIONTABLESIZE - 1; ++ix)
 
8344
    {
 
8345
        if (functionTable[ix].wmFunction == wmFunction)
 
8346
        {
 
8347
            /* Success! The function was found. Set up the
 
8348
               values and get the heck out of here. */
 
8349
            menuItem->greyedContext = functionTable[ix].greyedContext;
 
8350
            menuItem->mgtMask = functionTable[ix].mgtMask;
 
8351
            return(True);
 
8352
        }
 
8353
    }
 
8354
 
 
8355
    /* We couldn't find the given command in the function table.
 
8356
       Set up the values as if the F_Nop function were found
 
8357
       and return False. */
 
8358
    menuItem->greyedContext = functionTable[F_NOP_INDEX].greyedContext;
 
8359
    menuItem->mgtMask = functionTable[F_NOP_INDEX].mgtMask;
 
8360
    return(False);
 
8361
}
 
8362
 
 
8363
 
 
8364
 
 
8365
/*************************************<->*************************************
 
8366
 *
 
8367
 *  MakeSeparatorTemplate ()
 
8368
 *
 
8369
 *
 
8370
 *  Description:
 
8371
 *  -----------
 
8372
 *
 
8373
 *  Inputs:
 
8374
 *  ------
 
8375
 * 
 
8376
 *  Outputs:
 
8377
 *  -------
 
8378
 *
 
8379
 *************************************<->***********************************/
 
8380
static
 
8381
MenuItem *MakeSeparatorTemplate (int position)
 
8382
{
 
8383
    MenuItem *item;
 
8384
 
 
8385
    item = (MenuItem *)XtMalloc(sizeof(MenuItem));
 
8386
 
 
8387
    /* We use the labelType to determine where this separator is positioned
 
8388
       relative to the client command(s) it is surrounding, i.e. TOP or
 
8389
       BOTTOM */
 
8390
    item->labelType = position;
 
8391
    /* Make it look like a client command: */
 
8392
    item->label = XtNewString("<label-template>");
 
8393
    item->labelBitmapIndex = -1;
 
8394
    item->mnemonic = (KeySym) 0;
 
8395
    item->accelState = 0;
 
8396
    item->accelKeyCode = (KeyCode) 0;
 
8397
    item->accelText = (String) NULL;
 
8398
    item->wmFunction = (WmFunction) F_Separator;
 
8399
    item->wmFuncArgs = (String) NULL;
 
8400
    item->greyedContext = 0;
 
8401
    item->mgtMask = 0;
 
8402
    item->clientCommandName = (String) NULL;
 
8403
    item->nextMenuItem = (MenuItem *) NULL;
 
8404
 
 
8405
    return(item);
 
8406
}
 
8407
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */