2
* @OPENGROUP_COPYRIGHT@
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.
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.
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
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
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.
46
static char rcsid[] = "$XConsortium: WmResParse.c /main/9 1996/11/01 10:17:34 drk $"
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.
56
* (c) Copyright 1987, 1988 DIGITAL EQUIPMENT CORPORATION */
58
* (c) Copyright 1988 MASSACHUSETTS INSTITUTE OF TECHNOLOGY */
65
#include "WmResNames.h"
67
#include <Dt/UserMsg.h>
68
#include <Dt/Connect.h>
76
#include "WmResource.h"
78
#include <Xm/VirtKeysP.h>
80
#include <X11/cursorfont.h>
81
#include <X11/keysym.h>
82
#include <X11/Xatom.h>
85
#include <X11/Xlocale.h>
91
#ifdef MOTIF_ONE_DOT_ONE
95
#include <Xm/XmP.h> /* for XmeGetHomeDirName */
101
/* maximum string lengths */
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
112
#define min(a,b) ((a)>(b) ? (b) : (a))
114
#define MAXLINE (MAXWMPATH+1)
118
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
119
# define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD, mSpec)
121
# define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD)
122
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
125
* include extern functions
127
#include "WmResParse.h"
129
#include "WmWrkspace.h"
132
#include "WmFunction.h"
136
#ifdef MOTIF_ONE_DOT_ONE
137
extern char *getenv ();
141
# ifdef X_NOT_STDC_ENV
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 */
150
* Global Variables And Tables:
152
static char cfileName[MAXWMPATH+1];
154
#ifndef NO_MESSAGE_CATALOG
155
char * pWarningStringFile;
156
char * pWarningStringLine;
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";
161
#define cfileP (wmGD.pWmPB->pFile)
162
#define parseP (wmGD.pWmPB->pchNext)
163
#define line (wmGD.pWmPB->pchLine)
164
#define linec (wmGD.pWmPB->lineNumber)
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 */
178
static MaskTableEntry modifierStrings[] = {
181
{"ctrl", ControlMask},
182
{"shift", ShiftMask},
191
{NULL, (unsigned int)NULL},
199
unsigned int eventType;
200
Boolean (*parseProc)();
201
unsigned int closure;
205
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
207
# define CCI_USE_DEFAULT_NAME_TAG "DEFAULT_NAME"
209
String CCIEntryModifierNames[] = {
220
NONE, /* internal only. */
221
INLINE, /* not supported. */
224
DELIMIT_INLINE, /* not supported. */
229
typedef struct _CCIFuncArg {
230
CCIEntryModifier mod;
233
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
235
#ifdef MOTIF_ONE_DOT_ONE
236
void GetHomeDirName(String fileName);
239
static String GetNetworkFileName (char *pchFile);
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))
259
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
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);
268
static Boolean ParseWmFuncMaybeStrArg (unsigned char **linePP,
269
WmFunction wmFunction, String *pArgs);
270
#endif /* PANELIST */
271
static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction,
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);
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,
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);
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);
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 */
332
static EventTableEntry buttonEvents[] = {
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}
358
static EventTableEntry keyEvents[] = {
360
{"key", KeyPress, ParseKeySym, 0, FALSE},
361
{ NULL, (unsigned int)NULL, (Boolean(*)())NULL, (unsigned int)NULL, (Boolean)NULL}
365
typedef struct _ConfigFileStackEntry {
369
char *wmgdConfigFile;
371
DtWmpParseBuf *pWmPB;
372
struct _ConfigFileStackEntry *pIncluder;
374
} ConfigFileStackEntry;
376
static ConfigFileStackEntry *pConfigStack = NULL;
377
static ConfigFileStackEntry *pConfigStackTop = NULL;
379
#endif /* PANELIST */
381
unsigned int buttonModifierMasks[] = {
391
* FUNCTION PARSER TABLE (function names must be in alphabetic order)
396
Context greyedContext;
397
unsigned int resource;
399
WmFunction wmFunction;
400
Boolean (*parseProc)();
401
} FunctionTableEntry;
405
* NOTE: New functions MUST be added in ALPHABETICAL order. A binary search
406
* is used to find the correct function name.
409
FunctionTableEntry functionTable[] = {
416
ParseWmFuncActionArg},
423
#endif /* PANELIST */
430
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
436
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
437
{"f.circle_down", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
442
{"f.circle_up", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
448
{"f.create_workspace", 0,
453
{"f.delete_workspace", 0,
464
{"f.focus_color", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
469
{"f.focus_key", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
475
{"f.goto_workspace", 0,
486
ParseWmFuncStrArg}, /* [helpvolume && helptopic] */
491
ParseWmFuncNoArg}, /* for now */
493
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
499
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
500
{"f.kill", F_CONTEXT_ROOT,
505
{"f.lower", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
509
ParseWmFuncMaybeStrArg},
511
{"f.marquee_selection",
512
F_CONTEXT_WINDOW|F_CONTEXT_ICON|F_SUBCONTEXT_IB_IICON,
518
{"f.maximize", F_CONTEXT_ROOT|F_CONTEXT_MAXIMIZE|
519
F_SUBCONTEXT_IB_WICON,
529
{"f.minimize", F_CONTEXT_ICON|F_CONTEXT_ROOT|F_SUBCONTEXT_IB_IICON,
534
{"f.move", F_CONTEXT_ROOT,
550
{"f.next_workspace", 0,
556
{"f.nop", F_CONTEXT_ROOT|F_CONTEXT_ICON|F_CONTEXT_WINDOW|
557
F_SUBCONTEXT_IB_WICON | F_SUBCONTEXT_IB_IICON,
562
{"f.normalize", F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON,
568
{"f.normalize_and_raise",
569
F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
572
F_Normalize_And_Raise,
573
ParseWmFuncMaybeStrArg},
575
{"f.normalize_and_raise",
576
F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
579
F_Normalize_And_Raise,
581
#endif /* PANELIST */
583
{"f.occupy_all", F_CONTEXT_ICONBOX|F_CONTEXT_ROOT,
586
F_AddToAllWorkspaces,
599
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
605
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
622
{"f.prev_workspace", 0,
628
{"f.quit_mwm", F_CONTEXT_ICON|F_CONTEXT_WINDOW,
633
{"f.raise", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
637
ParseWmFuncMaybeStrArg},
638
{"f.raise_lower", F_CONTEXT_ROOT |
639
F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
649
{"f.refresh_win", F_CONTEXT_ICON|F_CONTEXT_ROOT,
655
{"f.remove", F_CONTEXT_ROOT,
661
{"f.resize", F_CONTEXT_ICON|F_CONTEXT_ROOT|
662
F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
668
{"f.restart", F_CONTEXT_ICON|F_CONTEXT_WINDOW,
674
{"f.restart", F_CONTEXT_ICON|F_CONTEXT_WINDOW,
680
{"f.restore", F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON,
685
{"f.restore_and_raise",
686
F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
696
{"f.send_msg", F_CONTEXT_ROOT,
706
{"f.set_behavior", 0,
723
#if defined(PANELIST)
724
{"f.toggle_frontpanel", 0,
727
F_Toggle_Front_Panel,
735
#endif /* PANELIST */
739
{"f.workspace_presence",F_CONTEXT_ICON|F_CONTEXT_ROOT|F_CONTEXT_ICONBOX|
740
F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
742
{"f.workspace_presence", F_CONTEXT_ROOT|F_CONTEXT_ICONBOX|
743
F_SUBCONTEXT_IB_WICON,
746
F_Workspace_Presence,
749
#if defined(DEBUG) && defined(WSM)
759
* NOTE: New functions MUST be added in ALPHABETICAL order. A binary search
760
* is used to find the correct function name.
763
#define WMFUNCTIONTABLESIZE (sizeof(functionTable)/sizeof(functionTable[0]))
766
* Be sure to update these define, whenever adding/deleting a function.
769
# if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
770
# define F_CCI_INDEX 2
771
# endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
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
781
# define F_EXEC_INDEX 3
782
# define F_NOP_INDEX 14
783
# endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
787
/******************************<->*************************************
789
* void GetFunctionTableValues (int *execIndex, int *nopIndex,
794
* This routine dynamically computes the size of the functionTable[],
795
* and the indices for key functions, such as f.exec, f.action, and
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.
809
* This routine calls smaller routines for efficiency sake.
811
******************************<->***********************************/
813
GetFunctionTableValues (int *execIndex, int *nopIndex,
817
GetExecIndex (WMFUNCTIONTABLESIZE, execIndex);
819
GetActionIndex (WMFUNCTIONTABLESIZE, actionIndex);
821
GetNopIndex (WMFUNCTIONTABLESIZE, nopIndex);
823
} /* END OF FUNCTION GetFunctionTableValues */
827
/******************************<->*************************************
844
******************************<->***********************************/
847
GetExecIndex (int tableSize, int *execIndex)
851
for (i = 0; i < (tableSize); i++)
853
if (!(strcmp ("f.exec", functionTable[i].funcName)))
863
} /* END OF FUNCTION GetExecIndex */
866
/******************************<->*************************************
883
******************************<->***********************************/
887
GetActionIndex (int tableSize, int *actionIndex)
891
for (i = 0; i < (tableSize); i++)
893
if (!(strcmp ("f.action", functionTable[i].funcName)))
903
} /* END OF FUNCTION GetActionIndex */
907
/******************************<->*************************************
924
******************************<->***********************************/
926
GetNopIndex (int tableSize, int *nopIndex)
930
for (i = 0; i < (tableSize); i++)
932
if (!(strcmp ("f.nop", functionTable[i].funcName)))
942
} /* END OF FUNCTION GetNopIndex */
947
/*************************************<->*************************************
970
*************************************<->***********************************/
972
WmDtGetHelpArgs(char *args,
973
unsigned char* volume,
974
unsigned char* topic,
977
unsigned char *string;
978
unsigned char *lineP;
982
parseP = (unsigned char*) args;
984
if(GetNextLine () != NULL)
988
if ((string = GetSmartSMString (&lineP)) != NULL)
990
*argsCount = *argsCount + 1;
991
strcpy ((char*)topic, (char*)string);
994
if ((string = GetSmartSMString (&lineP)) != NULL)
996
*argsCount = *argsCount + 1;
997
strcpy ((char*)volume, (char *)string);
1001
} /* END OF FUNCTION WmDtGetHelpArgs */
1007
/******************************<->*************************************
1010
* ParseDtSessionHints (pSD, property)
1015
* This function parses a DtSessionHints string and returns a list of
1016
* DtSessionItems array. The string should have the syntax:
1023
* line = (global) line buffer
1024
* pSD->rootWindow = default root window of display
1036
*************************************<->***********************************/
1039
ParseDtSessionHints (WmScreenData *pSD, unsigned char *property)
1046
ParseSessionItems (pSD);
1048
} /* END OF FUNCTION ParseDtSessionHints */
1051
/*************************************<->*************************************
1053
* FindDtSessionMatch(commandArgc, commandArgv, pCD, pSD, pWorkSpaceList,
1058
* Try to find a match for this client in the session hints.
1059
* Set up client-session data.
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
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)
1082
* Various pieces of client state (in pCD) are reset when a match
1085
* The caller must free *pWorkspaceList when done.
1087
*************************************<->***********************************/
1088
Boolean FindDtSessionMatch(int commandArgc, char **commandArgv,
1089
ClientData *pCD, WmScreenData *pSD,
1090
char **pWorkSpaceList, char *clientMachine)
1096
SessionGeom *sessionGeom;
1099
for (count = 0; count < pSD->totalSessionItems; count++)
1101
if (!pSD->pDtSessionItems[count].processed &&
1102
pSD->pDtSessionItems[count].commandArgc == commandArgc)
1104
if ((clientMachine) &&
1105
(pSD->pDtSessionItems[count].clientMachine) &&
1106
(strcmp(clientMachine,
1107
pSD->pDtSessionItems[count].clientMachine)))
1110
* This item has clientMachine string but the
1111
* clientMachine does not match.
1115
for (argNum = 0; argNum < commandArgc ; argNum++)
1117
if(strcmp(commandArgv[argNum],
1118
pSD->pDtSessionItems[count].commandArgv[argNum]))
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
1131
if (argNum == commandArgc)
1134
* Made it through all strings so this is a match
1137
pSD->pDtSessionItems[count].processed = True;
1138
pSD->remainingSessionItems --;
1139
pCD->clientFlags |= SM_LAUNCHED;
1142
* Free strings malloc'd for commandArgv for this item
1145
for (relCount = 0; relCount < commandArgc; relCount++)
1147
XtFree(pSD->pDtSessionItems[count].commandArgv[relCount]);
1149
XtFree((char *)pSD->pDtSessionItems[count].commandArgv);
1151
if(pSD->pDtSessionItems[count].clientState)
1154
pSD->pDtSessionItems[count].clientState;
1155
pCD->clientFlags |= SM_CLIENT_STATE;
1158
if(pSD->pDtSessionItems[count].sessionGeom)
1160
sessionGeom = pSD->pDtSessionItems[count].sessionGeom;
1161
if (sessionGeom->flags & XValue)
1163
pCD->clientX = sessionGeom->clientX;
1164
pCD->clientFlags |= SM_X;
1166
if (sessionGeom->flags & YValue)
1168
pCD->clientY = sessionGeom->clientY;
1169
pCD->clientFlags |= SM_Y;
1171
if (sessionGeom->flags & WidthValue)
1173
pCD->clientWidth = sessionGeom->clientWidth;
1174
pCD->clientFlags |= SM_WIDTH;
1176
if (sessionGeom->flags & HeightValue)
1178
pCD->clientHeight = sessionGeom->clientHeight;
1179
pCD->clientFlags |= SM_HEIGHT;
1183
* Free SessionGeom malloc'd space for this item
1186
XtFree((char *)pSD->pDtSessionItems[count].sessionGeom);
1189
if(pSD->pDtSessionItems[count].clientMachine)
1192
* Free clientMachine malloc'd space for this item
1196
pSD->pDtSessionItems[count].clientMachine);
1197
pSD->pDtSessionItems[count].clientMachine = NULL;
1201
if(pSD->pDtSessionItems[count].workspaces)
1204
* The caller is responsible for freeing this
1207
*pWorkSpaceList = pSD->pDtSessionItems[count].workspaces;
1211
if(pSD->remainingSessionItems == 0)
1214
* Free the whole pSD->pDtSessionHints structure
1216
XtFree((char *)pSD->pDtSessionItems);
1222
} /* not processed and argc's are the same */
1228
} /* END OF FUNCTION FindDtSessionMatch */
1234
/*************************************<->*************************************
1237
* ParseSessionItems (pSD)
1242
* Parse session items
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
1257
* linec = (global) line count incremented
1258
* parseP = (global) parse string pointer if cfileP == NULL
1265
*************************************<->***********************************/
1268
ParseSessionItems (WmScreenData *pSD)
1270
unsigned char *string;
1271
unsigned char *lineP;
1276
* Parse property string
1281
if(GetNextLine () != NULL)
1283
pSD->totalSessionItems = atoi((char *)line);
1284
pSD->remainingSessionItems = pSD->totalSessionItems;
1288
if((pSD->totalSessionItems < 1) ||
1289
!GetSessionHintsInfo(pSD, pSD->totalSessionItems))
1292
* No items or couldn't allocate space
1299
while ((count < pSD->totalSessionItems) && (GetNextLine () != NULL))
1303
while ((string = GetSmartSMString (&lineP)) != NULL)
1305
if (!strcmp((char *)string, "-geometry"))
1308
* Parse geometry if it is present
1310
string = GetSmartSMString(&lineP);
1311
ParseSessionGeometry (pSD, count, string);
1314
else if (!strcmp((char *)string, "-state"))
1317
* Parse the state if it is present
1319
string = GetSmartSMString(&lineP);
1320
ParseSessionClientState (pSD, count, string);
1323
else if (!strcmp((char *)string, "-workspaces"))
1326
* Parse the workspaces string if it is present
1328
string = GetSmartSMString(&lineP);
1329
ParseSessionWorkspaces (pSD, count, string);
1332
else if (!strcmp((char *)string, "-cmd"))
1335
* Parse the command string if it is present
1337
string = GetSmartSMString(&lineP);
1338
ParseSessionCommand (pSD, count, &string);
1341
else if (!strcmp((char *)string, "-host"))
1344
* Parse the host string if it is present
1346
string = GetSmartSMString(&lineP);
1347
ParseSessionHost (pSD, count, string);
1350
} /* while GetSmartSMString */
1354
} /* while GetNextLine */
1358
} /* END OF FUNCTION ParseSessionItems */
1362
/*************************************<->*************************************
1364
* ParseSessionClientState (pSD, count, string);
1375
*************************************<->***********************************/
1376
void ParseSessionClientState (WmScreenData *pSD, int count,
1377
unsigned char *string)
1383
if(!strcmp((char *)string, "NormalState"))
1385
pSD->pDtSessionItems[count].clientState = NORMAL_STATE;
1387
else if(!strcmp((char *)string, "IconicState"))
1389
pSD->pDtSessionItems[count].clientState = MINIMIZED_STATE;
1393
} /* END OF FUNCTION ParseSessionClientState */
1396
/*************************************<->*************************************
1398
* ParseSessionGeometry (pSD, count, string)
1409
*************************************<->***********************************/
1410
void ParseSessionGeometry (WmScreenData *pSD, int count,
1411
unsigned char *string)
1414
SessionGeom *pTmpSessionGeom;
1416
int X, Y, width, height;
1417
X = Y = width = height = 0;
1423
mask = XParseGeometry((char *)string, &X, &Y, (unsigned int *)&width,
1424
(unsigned int *)&height);
1428
* Allocate space for the geometry structure
1431
if ((pTmpSessionGeom =
1432
(SessionGeom *)XtMalloc (sizeof (SessionGeom))) == NULL)
1434
Warning (((char *)GETMESSAGE(60, 1, "Insufficient memory for session geometry item")));
1439
pTmpSessionGeom->flags = mask;
1440
pTmpSessionGeom->clientX = X;
1441
pTmpSessionGeom->clientY = Y;
1442
pTmpSessionGeom->clientWidth = width;
1443
pTmpSessionGeom->clientHeight = height;
1445
pSD->pDtSessionItems[count].sessionGeom = pTmpSessionGeom;
1448
} /* END OF FUNCTION ParseSessionGeometry */
1451
/*************************************<->*************************************
1454
* ParseSessionWorkspaces (pSD, count, string)
1465
*************************************<->***********************************/
1466
void ParseSessionWorkspaces (WmScreenData *pSD, int count,
1467
unsigned char *string)
1472
* Allocate space for the workspaces string
1475
if ((pSD->pDtSessionItems[count].workspaces =
1476
(String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) == NULL)
1478
Warning (((char *)GETMESSAGE(60, 2, "Insufficient memory for workspaces list in sesssion item")));
1483
strcpy(pSD->pDtSessionItems[count].workspaces, (char *)string);
1485
} /* END OF FUNCTION ParseSessionWorkspaces */
1489
/*************************************<->*************************************
1492
* ParseSessionCommand (pSD, count, string)
1503
*************************************<->***********************************/
1504
void ParseSessionCommand (WmScreenData *pSD, int count,
1505
unsigned char **commandString)
1509
unsigned char **argv;
1513
unsigned char *string;
1515
argv = (unsigned char **) XtMalloc (ARG_AMT * sizeof(char *));
1516
iSizeArgv = ARG_AMT;
1518
while ((string = GetSmartSMString (commandString)) != NULL)
1521
* Get pointers to strings in command line and count them
1523
argv[argc] = string;
1526
if (argc >= iSizeArgv)
1528
iSizeArgv += ARG_AMT;
1529
argv = (unsigned char **)
1530
XtRealloc ((char *)argv, (iSizeArgv * sizeof(char *)));
1533
if ((pSD->pDtSessionItems[count].commandArgv =
1534
(char **)XtMalloc ((argc) * sizeof(char * ))) == NULL)
1537
* Allocate space for saved argv
1540
Warning (((char *)GETMESSAGE(60, 3, "Insufficient memory for commandArgv array")));
1544
pSD->pDtSessionItems[count].commandArgc = argc;
1545
for (xindex = 0; xindex < argc ; xindex++)
1547
if ((pSD->pDtSessionItems[count].commandArgv[xindex] =
1549
((unsigned int) (strlen((char *)argv[xindex]) + 1))) == NULL)
1552
* Allocate space for the next command segment.
1554
Warning (((char *)GETMESSAGE(60, 4, "Insufficient memory for commandArgv item")));
1558
strcpy(pSD->pDtSessionItems[count].commandArgv[xindex],
1559
(char *)argv[xindex]);
1564
XtFree ((char *) argv);
1566
} /* END OF FUNCTION ParseSessionCommand */
1570
/*************************************<->*************************************
1573
* ParseSessionHost (pSD, count, string)
1584
*************************************<->***********************************/
1585
void ParseSessionHost (WmScreenData *pSD, int count,
1586
unsigned char *string)
1591
* Allocate space for the workspaces string
1594
if ((pSD->pDtSessionItems[count].clientMachine =
1595
(String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) ==
1598
Warning (((char *)GETMESSAGE(60, 38,
1599
"Insufficient memory for host name in sesssion item")));
1603
strcpy(pSD->pDtSessionItems[count].clientMachine, (char *)string);
1605
} /* END OF FUNCTION ParseSessionHost */
1609
/*************************************<->*************************************
1611
* GetSessionHintsInfo (pSD, numItems)
1622
*************************************<->***********************************/
1623
Boolean GetSessionHintsInfo (WmScreenData *pSD, long numItems)
1627
if ((pSD->pDtSessionItems =
1628
(DtSessionItem *)XtMalloc (numItems * sizeof (DtSessionItem)))
1631
Warning (((char *)GETMESSAGE(60, 5, "Insufficient memory for Dt Session Hints")));
1635
memset ((char *)pSD->pDtSessionItems, NULL,
1636
numItems * sizeof (DtSessionItem));
1641
} /* END OF FUNCTION GetSessionHintsInfo */
1646
/*************************************<->*************************************
1648
* PeekAhead (currentChar, currentLev)
1653
* Returns a new level value if this is a new nesting level of quoted string
1654
* Otherwise it returns a zero
1659
* currentChar = current position in the string
1660
* currentLev = current level of nesting
1665
* Returns either a new level of nesting or zero if the character is copied in
1671
*************************************<->***********************************/
1672
unsigned int PeekAhead(unsigned char *currentChar,
1673
unsigned int currentLev)
1677
Boolean done = False;
1678
unsigned int tmpLev = 1;
1679
#ifndef NO_MULTIBYTE
1682
while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
1683
(chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
1688
if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
1689
((*currentChar == '"') || (*currentChar == '\\')))
1692
if(*currentChar == '"')
1703
while((*currentChar != NULL) && (done == False) &&
1704
((*currentChar == '"') || (*currentChar == '\\')))
1707
if((*currentChar != NULL) &&
1708
((*currentChar == '"') || (*currentChar == '\\')))
1711
if(*currentChar == '"')
1721
#endif /*NO_MULTIBYTE*/
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
1736
} /* END OF FUNCTION PeekAhead */
1743
#ifdef MOTIF_ONE_DOT_ONE
1744
/*************************************<->*************************************
1746
* GetHomeDirName (fileName)
1750
* This function finds the "HOME" directory
1764
*************************************<->***********************************/
1765
void GetHomeDirName(String fileName)
1771
if((ptr = getenv("HOME")) == NULL)
1773
if((ptr = getenv("USER")) != NULL)
1792
strcpy(fileName, ptr);
1797
/*************************************<->*************************************
1799
* SyncModifierStrings (fileName)
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.
1817
*************************************<->***********************************/
1818
void SyncModifierStrings(void)
1820
XModifierKeymap *map;
1823
map = XGetModifierMapping (DISPLAY);
1825
for (i = 0; i < 8; i++)
1827
for (j = 0; j < map->max_keypermod; j++)
1829
if (map->modifiermap[k])
1831
KeySym ks = XKeycodeToKeysym(DISPLAY, map->modifiermap[k], 0);
1832
char *nm = XKeysymToString(ks);
1834
/* Compare, ignoring the trailing '_L' or '_R' in keysym */
1835
if (nm && !strncmp("Alt", nm, 3))
1837
modifierStrings[ALT_INDEX].mask = (1<<i);
1839
else if (nm && !strncmp("Meta", nm, 4))
1841
modifierStrings[META_INDEX].mask = (1<<i);
1848
XFreeModifiermap(map);
1853
/*************************************<->*************************************
1860
* This function reads the mwm resource description file and processes the
1861
* resources that are described.
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
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
1886
* If there are more than MAXLINE characters on a line the excess characters
1889
*************************************<->***********************************/
1890
#define MENU_SPEC "menu"
1891
#define BUTTON_SPEC "buttons"
1892
#define KEY_SPEC "keys"
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
1903
void ProcessWmFile (WmScreenData *pSD, Boolean bNested)
1905
#else /* PANELIST */
1906
void ProcessWmFile (WmScreenData *pSD)
1907
#endif /* PANELIST */
1909
unsigned char *lineP;
1910
unsigned char *string;
1914
static Boolean conversionInProgress = False;
1920
#endif /* PANELIST */
1923
* Initialize global data values that are set based on data in
1924
* the mwm resource description file.
1927
pSD->buttonSpecs = NULL;
1928
pSD->keySpecs = NULL;
1929
pSD->menuSpecs = NULL;
1932
/**** hhhhhhhhhhhh ******/
1933
GetFunctionTableValues (&F_EXEC_INDEX, &F_NOP_INDEX, &F_ACTION_INDEX);
1936
* Find and parse the default system menu string, if it exists.
1941
if (((parseP = (unsigned char *) builtinSystemMenu) != NULL) &&
1942
(GetNextLine () != NULL))
1945
ParseMenuSet (pSD, lineP);
1949
if (((parseP = (unsigned char *) builtinRootMenu) != NULL) &&
1950
(GetNextLine () != NULL))
1953
ParseMenuSet (pSD, lineP);
1956
if (wmGD.useFrontPanel && !wmGD.dtSD &&
1957
(XDefaultScreen (wmGD.display) == pSD->screen))
1959
wmGD.dtSD = pSD; /* only one per display */
1961
#endif /* PANELIST */
1964
* Find and associate a stream with the window manager resource
1968
if ((cfileP = FopenConfigFile ()) == NULL)
1970
if (!wmGD.useStandardBehavior)
1971
Warning (((char *)GETMESSAGE(60, 6, "Cannot open configuration file")));
1976
} /* end if (!bNested) */
1977
#endif /* PANELIST */
1979
* Parse the information in the configuration file.
1980
* If there are more than MAXLINE characters on a line the excess are
1985
while ((GetNextLine () != NULL)) /* not EOF nor read error */
1988
if ((*line == '!') || (string = GetString (&lineP)) == NULL)
1989
/* empty or comment line */
1995
if (!strcmp ((char *)string, MENU_SPEC))
1997
ParseMenuSet (pSD, lineP);
1999
else if (!strcmp ((char *) string, BUTTON_SPEC))
2001
ParseButtonSet (pSD, lineP);
2003
else if (!strcmp ((char *) string, KEY_SPEC))
2005
ParseKeySet (pSD, lineP);
2008
else if (!strcmp ((char *)string, INCLUDE_SPEC))
2010
ParseIncludeSet (pSD, lineP);
2012
#endif /* PANELIST */
2018
* Create and initialize the pSD->acceleratorMenuSpecs array.
2019
* This assumes we create pointers to MenuSpecs within ProcessWmFile().
2020
* Set pSD->acceleratorMenuCount to 0.
2023
/* count the number of menu specifications */
2025
menuSpec = pSD->menuSpecs;
2029
menuSpec = menuSpec->nextMenuSpec;
2032
/* allocate the array and initialize to zeros */
2033
pSD->acceleratorMenuSpecs = NULL;
2036
pSD->acceleratorMenuSpecs =
2037
(MenuSpec **) XtCalloc (n, sizeof (MenuSpec *));
2038
if (pSD->acceleratorMenuSpecs == NULL)
2040
Warning (((char *)GETMESSAGE(60, 7, "Insufficient memory for menu accelerators")));
2043
pSD->acceleratorMenuCount = 0;
2044
} /* END OF FUNCTION ProcessWmFile */
2046
/**** This function stolen from Xt/Intrinsic.c ****/
2047
/* The implementation of this routine is operating system dependent */
2049
static char *ExtractLocaleName(lang)
2053
#ifdef hpux /* hpux-specific parsing of the locale string */
2054
#define MAXLOCALE 64 /* buffer size of locale name */
2059
static char buf[MAXLOCALE];
2061
/* If lang has a substring ":<category>;", extract <category>
2062
* from the first such occurrence as the locale name.
2066
if (start = strchr (lang, ':')) {
2068
if (end = strchr (start, ';')) {
2070
strncpy(buf, start, len);
2071
*(buf + len) = '\0';
2081
#define RC_CONFIG_SUBDIR "/config/"
2082
#define RC_DEFAULT_CONFIG_SUBDIR "/config/C"
2085
/*************************************<->*************************************
2087
* FopenConfigFile ()
2092
* This function searches for, opens, and associates a stream with the mwm
2093
* resource description file,
2098
* wmGD.configFile = configuration file resource value.
2099
* HOME = environment variable for home directory
2104
* Return = If successful, a pointer to the FILE structure associated with
2105
* the configuration file. Otherwise, NULL.
2112
*************************************<->***********************************/
2113
FILE *FopenConfigFile (void)
2119
#ifndef MOTIF_ONE_DOT_ONE
2120
char *homeDir = XmeGetHomeDirName();
2123
Boolean stackPushed;
2124
#endif /* PANELIST */
2127
* Get the LANG environment variable
2128
* make copy since another call to getenv will blast the value.
2130
LANGp = setlocale(LC_CTYPE, NULL);
2133
* setlocale not guaranteed to return $LANG -- extract
2136
LANGp = ExtractLocaleName (LANGp);
2138
if ((LANGp == NULL) || (strlen(LANGp) == 0))
2144
if ((LANG = (char *) XtMalloc(strlen(LANGp) +1)) == NULL)
2146
PWarning (((char *)GETMESSAGE(60, 41, "Insufficient memory to get LANG environment variable.")));
2150
strcpy(LANG, LANGp);
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
2161
if (pConfigStackTop && pConfigStackTop->tempName)
2163
fileP = fopen (pConfigStackTop->tempName, "r");
2166
stackPushed = (pConfigStackTop && (pConfigStackTop != pConfigStack));
2168
cfileName[0] = '\0';
2169
#endif /* PANELIST */
2170
if ((wmGD.configFile != NULL) && (wmGD.configFile[0] != '\0'))
2171
/* pointer to nonNULL string */
2173
if ((wmGD.configFile[0] == '~') && (wmGD.configFile[1] == '/'))
2174
/* handle "~/..." */
2176
#ifdef MOTIF_ONE_DOT_ONE
2177
GetHomeDirName(cfileName);
2179
strcpy (cfileName, homeDir);
2183
strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
2184
strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
2186
strncat(cfileName, &(wmGD.configFile[1]), MAXWMPATH-strlen(cfileName));
2187
if ((fileP = fopen (cfileName, "r")) != NULL)
2195
#endif /* PANELIST */
2200
* Just try $HOME/.mwmrc
2202
#ifdef MOTIF_ONE_DOT_ONE
2203
GetHomeDirName(cfileName);
2205
strcpy (cfileName, homeDir);
2207
strncat(cfileName, &(wmGD.configFile[1]),
2208
MAXWMPATH-strlen(cfileName));
2209
if ((fileP = fopen (cfileName, "r")) != NULL)
2217
#endif /* PANELIST */
2224
/* relative to current directory or absolute */
2229
pch = (char *) GetNetworkFileName (wmGD.configFile);
2231
if ((fileP = fopen (pch, "r")) != NULL)
2233
strncpy (cfileName, pch, MAXWMPATH);
2237
if ((fileP == NULL) && !stackPushed)
2239
#endif /* PANELIST */
2240
if ((fileP = fopen (wmGD.configFile, "r")) != NULL)
2250
else if ((fileP == NULL) && stackPushed)
2252
strcpy (cfileName, wmGD.configFile);
2254
#endif /* PANELIST */
2258
if ((fileP == NULL) && !stackPushed)
2260
#endif /* PANELIST */
2263
* The configFile resource didn't do it for us.
2264
* First try HOME_MWMRC, then try SYS_MWMRC .
2267
#define HOME_MWMRC "/.mwmrc"
2268
#define SLASH_MWMRC "/system.mwmrc"
2270
#ifdef MOTIF_ONE_DOT_ONE
2271
GetHomeDirName(cfileName);
2273
strcpy (cfileName, homeDir);
2281
* Looking for $HOME/$LANG/.mwmrc
2282
* --or--if $LANG is NULL
2283
* Looking for $HOME/.mwmrc
2288
strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
2289
strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
2291
strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
2297
* Looking for $HOME/.dt/$LANG/dtwmrc
2299
* --or--if $LANG is NULL--
2301
* Looking for $HOME/.dt/dtwmrc
2304
strncat(cfileName, "/.dt/", MAXWMPATH-strlen(cfileName));
2308
strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
2310
strncat(cfileName, LANG_DT_WMRC, MAXWMPATH - strlen(cfileName));
2315
strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
2316
strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
2318
strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
2320
if ((fileP = fopen (cfileName, "r")) != NULL)
2328
#endif /* PANELIST */
2333
* Just try $HOME/.mwmrc
2335
#ifdef MOTIF_ONE_DOT_ONE
2336
GetHomeDirName(cfileName);
2338
strcpy (cfileName, homeDir);
2344
* Just try $HOME/.mwmrc
2346
strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
2351
* Just try $HOME/.dt/dtwmrc
2353
strncat(cfileName, HOME_DT_WMRC, MAXWMPATH - strlen(cfileName));
2356
strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
2358
if ((fileP = fopen (cfileName, "r")) != NULL)
2366
#endif /* PANELIST */
2372
#define DTLIBDIR CDE_INSTALLATION_TOP
2373
#define DTADMINDIR CDE_CONFIGURATION_TOP
2374
#define SLASH_DT_WMRC "/sys.dtwmrc"
2376
if ((fileP == NULL) && !stackPushed)
2379
* No home-based config file. Try the admin directory.
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));
2386
if (((fileP = fopen (cfileName, "r")) == NULL) && LANG && *LANG)
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));
2394
if ((fileP = fopen (cfileName, "r")) != NULL)
2401
if ((fileP == NULL) && !stackPushed)
2403
#endif /* PANELIST */
2406
#define LIBDIR "/usr/lib/X11"
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));
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));
2427
* Try /$LANG/system.mwmrc within the install tree
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));
2434
if ((fileP = fopen (cfileName, "r")) != NULL)
2440
#endif /* PANELIST */
2445
if ((fileP == NULL) && !stackPushed)
2447
#endif /* PANELIST */
2451
strcpy(cfileName, LIBDIR);
2452
strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
2454
fileP = fopen (cfileName, "r");
2455
#else /* PANELIST */
2456
return (fopen (cfileName, "r"));
2457
#endif /* PANELIST */
2461
strcpy(cfileName, DTLIBDIR);
2462
strncat(cfileName, RC_DEFAULT_CONFIG_SUBDIR,
2463
MAXWMPATH - strlen(cfileName));
2464
strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
2466
fileP = fopen (cfileName, "r");
2467
#else /* PANELIST */
2468
return (fopen (cfileName, "r"));
2469
#endif /* PANELIST */
2473
* Try /system.mwmrc within the install tree
2475
strcpy(cfileName, LIBDIR);
2476
strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
2484
strcpy(cfileName, cfileName);
2485
fileP = fopen (cfileName, "r");
2486
#else /* PANELIST */
2487
return (fopen (cfileName, "r"));
2488
#endif /* PANELIST */
2499
* handle "<host>:<path>" form of file name
2501
pch = (char *) GetNetworkFileName (cfileName);
2502
if ((fileP = fopen (cfileName, "r")) != NULL)
2504
strncpy (cfileName, pch, MAXWMPATH);
2509
* Either not "<host>:<path>" form or there was a
2510
* problem up above. This is the last attempt to
2515
fileP = fopen (cfileName, "r");
2521
ConfigStackInit (cfileName);
2524
if (wmGD.cppCommand && *wmGD.cppCommand)
2527
* Run the file through the C-preprocessor
2529
PreprocessConfigFile ();
2530
if (pConfigStackTop->cppName)
2532
/* open the result */
2533
fileP = fopen (pConfigStackTop->cppName, "r");
2543
#endif /* PANELIST */
2545
} /* END OF FUNCTION FopenConfigFile */
2548
/*************************************<->*************************************
2550
* SaveMenuAccelerators (pSD, newMenuSpec)
2555
* This function saves the MenuSpec pointer in pSD->acceleratorMenuSpecs.
2560
* newMenuSpec = pointer to MenuSpec to be saved.
2561
* pSD->acceleratorMenuSpecs =
2562
* pSD->acceleratorMenuCount =
2567
* pSD->acceleratorMenuSpecs = possibly updated
2568
* pSD->acceleratorMenuCount = possibly updated
2573
* We assume only MenuSpecs created within ProcessWmFile() are to be saved.
2574
* Otherwise, we may cause override the limits of pSD->acceleratorMenuSpecs.
2576
*************************************<->***********************************/
2578
void SaveMenuAccelerators (WmScreenData *pSD, MenuSpec *newMenuSpec)
2580
MenuSpec **pMenuSpec;
2582
pMenuSpec = pSD->acceleratorMenuSpecs;
2584
if (pMenuSpec == NULL)
2587
while ((*pMenuSpec != NULL) && (*pMenuSpec != newMenuSpec))
2592
if (*pMenuSpec == NULL)
2594
*pMenuSpec = newMenuSpec;
2595
pSD->acceleratorMenuCount++;
2598
} /* END OF FUNCTION SaveMenuAccelerators */
2601
/*************************************<->*************************************
2603
* ParseMenuSet (pSD, lineP)
2608
* Menu pane specification found. Parse the following syntax:
2611
* Menu menu_pane_name
2613
* label [mnemonic] [accelerator] function
2614
* label [mnemonic] [accelerator] function
2616
* label [mnemonic] [accelerator] function
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
2634
* linec = (global) line count incremented
2635
* parseP = (global) parse string pointer if cfileP == NULL
2636
* pSD->menuSpecs = list of menu specifications
2641
* Skips unnamed menu specifications.
2642
* This means custom menu specifications can be distinguished by NULL name.
2644
*************************************<->***********************************/
2646
static void ParseMenuSet (WmScreenData *pSD, unsigned char *lineP)
2648
unsigned char *string;
2652
* If menu name is NULL then skip this pane specification.
2655
if ((string = GetString (&lineP)) == NULL)
2661
* Allocate space for the menu specification structure.
2664
if ((menuSpec = (MenuSpec *)XtMalloc (sizeof (MenuSpec))) == NULL)
2666
PWarning (((char *)GETMESSAGE(60, 9, "Insufficient memory for menu")));
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;
2683
* Allocate and fill space for the menu name.
2686
if ((menuSpec->name =
2687
(String)XtMalloc ((unsigned int) (strlen ((char *)string) + 1)))
2690
PWarning (((char *)GETMESSAGE(60, 10, "Insufficient memory for menu")));
2691
XtFree ((char *)menuSpec);
2694
strcpy (menuSpec->name, (char *)string);
2697
* Add the empty structure to the head of the menu specification list.
2700
menuSpec->nextMenuSpec = pSD->menuSpecs;
2701
pSD->menuSpecs = menuSpec;
2704
* Require leading '{' on the next line.
2707
while ((GetNextLine () != NULL)) /* not EOF nor read error */
2710
ScanWhitespace(&lineP);
2712
if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
2713
/* ignore empty or comment line */
2725
PWarning (((char *)GETMESSAGE(60, 11, "Expected '{' after menu name")));
2730
* Found leading "{" or EOF.
2731
* Parse menu item specifications until "}" or EOF found.
2734
menuSpec->menuItems = PARSE_MENU_ITEMS (pSD, menuSpec);
2736
} /* END OF FUNCTION ParseMenuSet */
2739
/*************************************<->*************************************
2742
* ParseMwmMenuStr (pSD, menuStr)
2747
* This function parses a WMW_MENU string and returns a list of
2748
* MenuItems structures. The string should have the syntax:
2750
* label [mnemonic] [accelerator] function
2751
* label [mnemonic] [accelerator] function
2753
* label [mnemonic] [accelerator] function
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
2767
* Return = list of MenuItem structures or NULL
2774
*************************************<->***********************************/
2776
MenuItem *ParseMwmMenuStr (WmScreenData *pSD, unsigned char *menuStr)
2783
return (PARSE_MENU_ITEMS (pSD, NULL));
2785
} /* END OF FUNCTION ParseMwmMenuStr */
2788
/*************************************<->*************************************
2791
* ParseMenuItems (pSD, menuSpec)
2796
* Parse menu item specifications:
2798
* label [mnemonic] [accelerator] function
2799
* label [mnemonic] [accelerator] function
2801
* label [mnemonic] [accelerator] function
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
2819
* linec = (global) line count incremented
2820
* parseP = (global) parse string pointer if cfileP == NULL
2821
* Return = list of MenuItem structures or NULL
2828
*************************************<->***********************************/
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) */
2836
unsigned char *string;
2837
unsigned char *lineP;
2838
MenuItem *firstMenuItem;
2839
MenuItem *lastMenuItem;
2842
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2843
Boolean use_separators = False;
2844
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2847
* Parse "label [mnemonic] [accelerator] function" or
2848
* "<client command>[.<client command>]*"
2849
* lines until "}" or EOF found.
2852
firstMenuItem = lastMenuItem = NULL;
2853
while ((GetNextLine () != NULL))
2856
if ((*line == '!') || (*line == '#') || (string = GetString (&lineP)) == NULL)
2857
/* ignore empty or comment lines */
2861
if (*string == '}') /* finished with menu set. */
2867
* Allocate space for the menu item structure.
2870
if ((menuItem = (MenuItem *)XtMalloc (sizeof (MenuItem))) == NULL)
2872
PWarning (((char *)GETMESSAGE(60, 12, "Insufficient memory for menu item")));
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) */
2883
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2885
* Is this a simple menu item label or is it a
2886
* client command specification.
2889
if (IsClientCommand((String) string))
2891
if (!ParseClientCommand(&lineP, menuSpec, menuItem, string,
2894
XtFree ((char *)menuItem);
2898
for (ix = 0; ix < WMFUNCTIONTABLESIZE - 1; ++ix)
2899
if (functionTable[ix].wmFunction == F_InvokeCommand)
2902
if (ix == WMFUNCTIONTABLESIZE - 1)
2905
menuItem->wmFunction = F_Nop;
2907
else menuItem->wmFunction = F_InvokeCommand;
2909
else /* It must be a menu item label */
2910
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2913
* Parse the menu item label.
2915
if (!ParseWmLabel (pSD, menuItem, string))
2917
XtFree ((char *)menuItem);
2923
* Parse any menu function mnemonic.
2926
ParseWmMnemonic (&lineP, menuItem);
2929
* Parse any menu function accelerator.
2932
if (!ParseWmAccelerator (&lineP, menuItem))
2934
FreeMenuItem (menuItem);
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.
2944
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2945
if (menuItem->wmFunction != NULL)
2946
ParseMenuItemName(&lineP, menuItem);
2948
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2949
ix = ParseWmFunction (&lineP, CRS_MENU, &menuItem->wmFunction);
2952
* Determine context sensitivity and applicability mask.
2955
menuItem->greyedContext = functionTable[ix].greyedContext;
2956
menuItem->mgtMask = functionTable[ix].mgtMask;
2958
if ((menuItem->wmFunction == F_Toggle_Front_Panel) &&
2959
((wmGD.useFrontPanel == False) ||
2960
(wmGD.dtSD != pSD)))
2963
* disallow this function if there's no front
2964
* panel on this screen.
2966
menuItem->greyedContext |= (F_CONTEXT_ALL |
2967
F_SUBCONTEXT_IB_WICON |
2968
F_SUBCONTEXT_IB_IICON);
2970
#endif /* PANELIST */
2973
* Apply the function argument parser.
2975
if (!(*(functionTable [ix].parseProc))
2976
(&lineP, menuItem->wmFunction, &menuItem->wmFuncArgs))
2978
FreeMenuItem (menuItem);
2979
continue; /* skip this menu item */
2982
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
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
2993
if (ix == F_CCI_INDEX)
2995
CCIEntryModifier mod = ((CCIFuncArg *)menuItem->wmFuncArgs)->mod;
2997
/* first fix the label if needed. */
2998
if (!strcmp(menuItem->label, CCI_USE_DEFAULT_NAME_TAG))
3000
XtFree(menuItem->label);
3001
menuItem->label = NULL;
3004
FixMenuItem(menuSpec, menuItem);
3006
if (mod == DELIMIT || mod == DELIMIT_CASCADE || mod == DELIMIT_INLINE)
3007
use_separators = True;
3011
* If this menu item is supposed to be wrapped in separators,
3012
* then create a separator template before the menu item
3016
MenuItem *separator = MakeSeparatorTemplate(TOP_SEPARATOR);
3017
if (lastMenuItem != NULL) lastMenuItem->nextMenuItem = separator;
3018
else firstMenuItem = separator;
3019
lastMenuItem = separator;
3021
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3024
* Add this item to the menu specification.
3027
if (lastMenuItem != NULL) /* not first */
3029
lastMenuItem->nextMenuItem = menuItem;
3033
firstMenuItem = menuItem;
3035
lastMenuItem = menuItem;
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
3043
MenuItem *separator = MakeSeparatorTemplate(BOTTOM_SEPARATOR);
3044
if (lastMenuItem != NULL) lastMenuItem->nextMenuItem = separator;
3045
else firstMenuItem = separator;
3046
lastMenuItem = separator;
3049
use_separators = FALSE;
3050
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3053
return (firstMenuItem);
3055
} /* END OF FUNCTION ParseMenuItems */
3059
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
3060
/*************************************<->*************************************
3062
* StoreExclusion (menuSpec, string)
3067
* Store the exclusion string in the menuspec. The list of exclusion
3068
* strings are used to determine whether an insertion should be disallowed.
3073
* menuSpec = the menu specification structure
3074
* string = exclusion client command string
3084
*************************************<->***********************************/
3086
static void StoreExclusion (MenuSpec *menuSpec, String string)
3088
MenuExclusion *exclusion;
3090
exclusion = (MenuExclusion *)XtMalloc(sizeof(MenuExclusion));
3091
exclusion->command_string = XtNewString(string);
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;
3100
/*************************************<->*************************************
3102
* IsClientCommand (string)
3107
* Determine whether the string is a client command by the prefix
3113
* string = possible client command string
3118
* Return = (Boolean) TRUE iff the string is a client command.
3119
* Otherwise, FALSE is returned.
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
3130
* characters: meaning:
3131
* -----------------------------------------------
3132
* < simple client command beginning
3133
* ->< forced cascade menu
3134
* =< client command with separators
3135
* ~< exclusion operator
3139
* There is no leading whitespace on the string
3141
*************************************<->***********************************/
3143
Boolean IsClientCommand (String string)
3146
#ifndef NO_MULTIBYTE
3147
mblen ((char *)string, MB_CUR_MAX) == 1 &&
3150
(strncmp(string, "-><", 3) == 0) ||
3151
(strncmp(string, "=<", 2) == 0) ||
3152
(strncmp(string, "=><", 3) == 0) ||
3153
(strncmp(string, "~<", 2) == 0))
3160
/*************************************<->*************************************
3162
* ParseClientCommand (linePP, menuSpec, menuitem, string, use_separators)
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.
3176
* linePP = pointer to current line buffer pointer.
3177
* menuItem = pointer to MenuItem structure
3178
* string = first token of client command
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
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.
3199
* Valid syntax for a client command (single quoted characters are
3202
* modifier = { '->' | '=' | '~' }
3203
* reference = '<' { name | '*' } '>'
3204
* command = [ modifier ] reference [ { modifier | '.' } reference ]*
3205
* name = alpha-numeric string, white space allowed
3209
* There is no leading whitespace on the string argument
3211
*************************************<->***********************************/
3213
enum { PRS_NO_STATE, PRS_BEGIN, PRS_MODIFIER, PRS_REFERENCE,
3214
PRS_SEPARATOR, PRS_END, PRS_ERROR, PRS_MAX_STATES };
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] =
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 },
3228
static Boolean ParseClientCommand (unsigned char **linePP, MenuSpec *menuSpec,
3229
MenuItem *menuItem, unsigned char *string,
3230
Boolean *use_separators)
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
3240
/* Construct one input stream out of the string and the linePP that
3242
linelen = strlen((char *)string) + strlen((char *)*linePP) + 1;
3243
if ((unchanged_stream = stream = (String)
3244
XtMalloc((unsigned int)(sizeof(unsigned char) * linelen))) == NULL)
3246
PWarning (((char *)GETMESSAGE(60, 42,
3247
"Insufficient memory for menu item label")));
3250
strcpy(stream, (char *) string);
3251
strcat(stream, " ");
3252
strcat(stream, (char *) *linePP);
3256
token = PRS_NO_STATE;
3257
while (token == PRS_NO_STATE)
3259
#ifndef NO_MULTIBYTE
3260
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
3270
/* We've reached the end of the stream. Return the
3275
/* This should be a cascade-force modifier */
3277
#ifndef NO_MULTIBYTE
3278
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
3285
++stream; token = PRS_MODIFIER;
3287
else token = PRS_ERROR;
3290
/* This is either a separators modifier or
3291
a combination separators and cascade-force
3294
#ifndef NO_MULTIBYTE
3295
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
3300
if (*stream == '>') ++stream;
3301
token = PRS_MODIFIER;
3302
*use_separators = TRUE;
3305
/* This is a exclude-command modifier */
3306
++stream; token = PRS_MODIFIER;
3308
/* Setup a pointer to the text following the ~ so
3309
we can do matching later for exclusions. */
3310
exclusion_text = stream;
3313
/* Skip the open bracket */
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) {
3325
#ifndef NO_MULTIBYTE
3326
mblen ((char *)stream, MB_CUR_MAX) == 1 &&
3328
(*stream == ' ' || *stream == '\t'))
3331
#ifndef NO_MULTIBYTE
3332
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
3337
/* Now check for a reference name wild card or a
3338
full reference name */
3344
#ifndef NO_MULTIBYTE
3345
mblen ((char *)stream, MB_CUR_MAX) == 1 &&
3347
(isalnum(*stream) || *stream == ' ' ||
3348
*stream == '\t' || *stream == '_' ))
3352
#ifndef NO_MULTIBYTE
3353
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
3359
/* Now skip past any trailing white space */
3361
#ifndef NO_MULTIBYTE
3362
mblen ((char *)stream, MB_CUR_MAX) == 1 &&
3364
(*stream == ' ' || *stream == '\t'))
3367
#ifndef NO_MULTIBYTE
3368
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
3373
/* At this point, we should be looking at the close
3377
token = PRS_REFERENCE;
3380
else token = PRS_ERROR;
3383
/* This is a reference separator */
3384
++stream; token = PRS_SEPARATOR;
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. */
3402
} /* end switch (*stream) */
3403
} /* end while (token == PRS_NO_STATE) */
3405
/* If we got an error then just return an error */
3406
if (token == PRS_ERROR)
3408
return_val = FALSE; break;
3411
/* Check whether the token we got is a valid transition */
3412
for (i = 0; cmd_parse_table[state][i] != PRS_NO_STATE; ++i)
3414
if (token == cmd_parse_table[state][i])
3416
/* It is a valid transition, so break out of the loop */
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)
3427
if (token == PRS_END)
3440
/* The transition was valid so make the transition by
3441
setting the state to be the current token. */
3444
} /* end for (;;) */
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
3449
if (return_val == TRUE)
3451
/* NULL terminate the string */
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)
3458
/* Since the command was an exclusion, store the command
3459
string in the menuSpec and change the return value to
3461
StoreExclusion(menuSpec, exclusion_text);
3466
menuItem->label = XtNewString(unchanged_stream);
3467
menuItem->labelType = XmSTRING;
3471
/* Free the string we allocated and return. */
3472
XtFree((char *)unchanged_stream);
3476
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3479
/*************************************<->*************************************
3481
* ParseWmLabel (pSD, menuItem, string)
3486
* Parse a menu label string.
3491
* pSD = pointer to screen data
3492
* menuItem = pointer to MenuItem structure
3493
* string = label string
3499
* menuItem->labelType
3500
* menuItem->labelBitmapCache
3501
* Return = boolean, FALSE iff insufficient memory
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.
3512
*************************************<->***********************************/
3514
static Boolean ParseWmLabel (WmScreenData *pSD, MenuItem *menuItem,
3515
unsigned char *string)
3519
* Allocate the label field and copy string.
3522
if ((menuItem->label = (String)
3523
XtMalloc ((unsigned int)(strlen ((char *)string) + 1))) == NULL)
3525
PWarning (((char *)GETMESSAGE(60, 13, "Insufficient memory for menu item")));
3529
strcpy (menuItem->label, (char *)string);
3530
menuItem->labelType = XmSTRING;
3534
* Here: string = "@<bitmap file>"
3535
* Try to find the label bitmap in the bitmap cache or read the label
3539
string++; /* skip "@" */
3541
if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD,
3542
(char *)string, True)) >= 0)
3544
if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD,
3545
(char *)string)) >= 0)
3548
menuItem->labelType = XmPIXMAP;
3553
} /* END OF FUNCTION ParseWmLabel */
3557
/*************************************<->*************************************
3559
* ParseWmMnemonic (linePP, menuItem)
3564
* Parse an optional menu function mnemonic.
3569
* linePP = pointer to current line buffer pointer.
3570
* menuItem = pointer to MenuItem structure
3575
* linePP = pointer to revised line buffer pointer.
3576
* menuItem->mnemonic = valid mnemonic character or NULL.
3583
*************************************<->***********************************/
3585
static void ParseWmMnemonic (unsigned char **linePP, MenuItem *menuItem)
3587
unsigned char *lineP = *linePP;
3588
unsigned char *mnemonic;
3591
* Skip leading white space.
3593
ScanWhitespace (&lineP);
3594
menuItem->mnemonic = (KeySym)NULL;
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.
3607
mnemonic = GetString(&lineP);
3609
#ifndef NO_MULTIBYTE
3610
if (menuItem->labelType == XmSTRING &&
3612
(ks = XStringToKeysym((char *)mnemonic)) != NoSymbol &&
3613
strchr(menuItem->label, (char)(ks & 0xff)) != NULL)
3615
menuItem->mnemonic = ks;
3618
if ((mnemonic != NULL) &&
3619
(*mnemonic != '\0') &&
3620
(menuItem->labelType == XmSTRING) &&
3621
(strchr (menuItem->label, *mnemonic) != NULL))
3622
/* valid mnemonic */
3624
menuItem->mnemonic = *mnemonic;
3629
PWarning (((char *)GETMESSAGE(60, 14, "Invalid mnemonic specification")));
3633
*linePP = lineP; /* consume any string */
3635
} /* END OF FUNCTION ParseWmMnemonic */
3638
/*************************************<->*************************************
3640
* ParseWmAccelerator (linePP, menuItem)
3645
* Parse an optional menu function accelerator.
3650
* linePP = pointer to current line buffer pointer.
3651
* menuItem = pointer to MenuItem structure
3656
* linePP = pointer to revised line buffer pointer.
3657
* menuItem->accelText = pointer to an accelerator string or NULL.
3664
*************************************<->***********************************/
3666
static Boolean ParseWmAccelerator (unsigned char **linePP, MenuItem *menuItem)
3668
unsigned char *lineP;
3670
unsigned int eventType;
3675
menuItem->accelState = 0;
3676
menuItem->accelKeyCode = 0;
3677
menuItem->accelText = NULL;
3681
* If linePP contains NULL, then abort.
3683
if (*linePP == (unsigned char *) NULL) return(FALSE);
3686
* Skip leading white space.
3688
ScanWhitespace (linePP);
3692
* If the second character is not ".", and an accelerator specification
3693
* exists, then process and save the specification string.
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) */
3703
(*(lineP+1) != '.')) /* skip if we have f.xxx WmFunction */
3705
if (ParseKeyEvent(&lineP, &eventType, &keycode, &state))
3707
if ((string = (String) XtMalloc
3708
((unsigned int) (lineP - *linePP + 1))) == NULL)
3710
PWarning (((char *)GETMESSAGE(60, 15, "Insufficient memory for accelerator specification")));
3715
* Save the accelerator state and keycode.
3716
* Process and save the accelerator text.
3719
ProcessAccelText (*linePP, lineP, (unsigned char *) string);
3720
menuItem->accelState = state;
3721
menuItem->accelKeyCode = keycode;
3722
menuItem->accelText = string;
3727
PWarning (((char *)GETMESSAGE(60, 16, "Invalid accelerator specification")));
3731
*linePP = lineP; /* consume the specification */
3736
} /* END OF FUNCTION ParseWmAccelerator */
3739
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
3740
/*************************************<->*************************************
3742
* ParseMenuItemName (linePP, menuItem)
3747
* Parse a user defined client command menu item
3752
* linePP = pointer to current line buffer pointer.
3753
* menuItem = pointer to MenuItem structure
3758
* menuItem->label will have menu item name appended to it
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.
3768
*************************************<->***********************************/
3770
static void ParseMenuItemName (unsigned char **linePP, MenuItem *menuItem)
3772
unsigned char *lineP, *endquote;
3773
#ifndef NO_MULTIBYTE
3777
/* Skip past any whitespace */
3778
ScanWhitespace (linePP);
3781
/* Look for a double quote */
3783
#ifndef NO_MULTIBYTE
3784
mblen ((char *)lineP, MB_CUR_MAX) == 1 &&
3788
/* Move past the first quote. */
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 != '"'))
3799
/* If we ran off the end of the line, then just abort. Bad
3801
if ((chlen == 1 && *endquote == '\n') || *endquote == '\0') return;
3804
if (chlen < 0) return; /* invalid character */
3806
while (*endquote != '\0' && *endquote != '"') {
3807
if (*endquote == '\n' || *endquote == '\0') return;
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,
3818
menuItem->clientCommandName[strlen(menuItem->clientCommandName)+1] = '\0';
3822
/* If there was no double quote, then just advance to the end
3824
#ifndef NO_MULTIBYTE
3825
while (*lineP != '\0' &&
3826
((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 1 ||
3828
lineP += chlen > 0 ? chlen : 1;
3830
while (*lineP != '\0' && *lineP != '\n')
3836
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3839
/*************************************<->*************************************
3842
* ParseWmFunction (linePP, res_spec, pWmFunction)
3847
* Parse a button, key, or menu function name and return its function table
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
3861
* linePP = pointer to revised line buffer pointer.
3862
* pWmFunction = pointer to parsed window manager function.
3863
* Return = function table index of parsed function.
3868
* Uses F_Nop if the function name or resource type is invalid.
3870
*************************************<->***********************************/
3872
int ParseWmFunction (unsigned char **linePP, unsigned int res_spec,
3873
WmFunction *pWmFunction)
3875
unsigned char *lineP = *linePP;
3876
unsigned char *string;
3877
register int low, mid, high, cmp;
3880
* Skip leading white space.
3882
ScanWhitespace (&lineP);
3885
* Have function string (may be NULL or a comment).
3886
* Handle the special case of '!'
3892
*pWmFunction = F_Exec;
3893
return (F_EXEC_INDEX);
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.
3903
string = GetString (&lineP);
3910
high = WMFUNCTIONTABLESIZE - 1;
3914
mid = (low + high)/2;
3915
cmp = strcmp (functionTable[mid].funcName, (char *)string);
3919
* Function name match
3920
* Require proper resource type for the function.
3923
if (res_spec & functionTable[mid].resource)
3925
*pWmFunction = functionTable[mid].wmFunction;
3929
/* invalid resource: use F_Nop */
3934
* Function name mismatch
3948
* Not found: assume f.nop
3950
*pWmFunction = F_Nop;
3951
return (F_NOP_INDEX);
3953
} /* END OF FUNCTION ParseWmFunction */
3956
/*************************************<->*************************************
3958
* ParseWmFuncMaybeStrArg (linePP, wmFunction, pArgs)
3963
* Parses a window manager function with a null or string argument.
3968
* linePP = pointer to current line buffer pointer.
3969
* wmFunction = function (not used).
3970
* pArgs = pointer to argument destination.
3975
* linePP = pointer to revised line buffer pointer.
3976
* pArgs = pointer to parsed argument string.
3977
* Return = FALSE iff insufficient memory
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 ()
3986
*************************************<->***********************************/
3991
Boolean ParseWmFuncMaybeStrArg (unsigned char **linePP,
3992
WmFunction wmFunction, String *pArgs)
3994
unsigned char *string = *linePP;
3997
ScanWhitespace (&string);
4002
return (ParseWmFuncStrArg (linePP, wmFunction, pArgs));
4007
else if (*lineP == '"' && *(lineP+1) == '-')
4010
strcpy ((char *) (lineP+1), (char *) (lineP+2));
4011
return (ParseWmFuncStrArg (linePP, wmFunction, pArgs));
4014
#endif /* PANELIST */
4015
if ((len = strlen ((char *)string)) != 0)
4017
if ((*pArgs = (String)XtMalloc (len + 1)) == NULL)
4019
PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory")));
4022
strcpy (*pArgs, (char *)string);
4026
/* Do ParseWmFuncNoArg () */
4032
} /* END OF FUNCTION ParseWmFuncMaybeStrArg */
4035
/*************************************<->*************************************
4037
* ParseWmFuncNoArg (linePP, wmFunction, pArgs)
4042
* Parses a window manager function null argument.
4047
* linePP = pointer to current line buffer pointer.
4048
* wmFunction = function (not used).
4049
* pArgs = pointer to argument destination.
4054
* linePP = unchanged
4063
*************************************<->***********************************/
4065
static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction,
4072
} /* END OF FUNCTION ParseWmFuncNoArg */
4075
/*************************************<->*************************************
4077
* ParseWmFuncStrArg (linePP, wmFunction, pArgs)
4082
* Parses a window manager function string argument.
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.
4094
* linePP = pointer to revised line buffer pointer.
4095
* pArgs = pointer to parsed argument string.
4096
* Return = FALSE iff insufficient memory
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.
4106
*************************************<->***********************************/
4111
Boolean ParseWmFuncStrArg (unsigned char **linePP,
4112
WmFunction wmFunction, String *pArgs)
4114
unsigned char *string;
4116
#ifndef NO_MULTIBYTE
4124
if ((string = GetString (linePP)) != NULL)
4125
/* nonNULL string argument */
4127
len = strlen ((char *)string);
4128
if ((*pArgs = (String)XtMalloc (len + 2)) == NULL)
4130
PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory")));
4133
strcpy (*pArgs, (char *)string);
4136
* Insure that an argument for F_Exec ends in '&' .
4139
#ifndef NO_MULTIBYTE
4140
if ((wmFunction == F_Exec))
4145
((len = mblen(p, MB_CUR_MAX)) > 0))
4147
mbtowc(&last, p, MB_CUR_MAX);
4152
mbtowc(&wdelim, &delim, MB_CUR_MAX);
4153
if (lastlen == 1 && last != wdelim)
4160
if ((wmFunction == F_Exec) && ((*pArgs)[len - 1] != '&'))
4162
(*pArgs)[len] = '&';
4163
(*pArgs)[len + 1] = '\0';
4168
/* NULL string argument */
4175
} /* END OF FUNCTION ParseWmFuncStrArg */
4178
/*************************************<->*************************************
4180
* FreeMenuItem (menuItem)
4185
* This procedure destroys a MenuItem structure.
4190
* menuItem = to be destroyed.
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!
4204
*************************************<->***********************************/
4206
void FreeMenuItem (MenuItem *menuItem)
4208
if (menuItem->label != NULL)
4210
XtFree ((char *)menuItem->label);
4213
if (menuItem->accelText != NULL)
4215
XtFree ((char *)menuItem->accelText);
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.
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)))
4230
XtFree ((char *)menuItem->wmFuncArgs);
4233
if (menuItem->clientCommandName != NULL)
4235
XtFree ((char *) menuItem->clientCommandName);
4238
XtFree ((char *)menuItem);
4240
} /* END OF FUNCTION FreeMenuItem */
4244
/*************************************<->*************************************
4246
* ParseWmFuncGrpArg (linePP, wmFunction, pGroup)
4251
* Parses a window manager function group argument.
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.
4263
* linePP = pointer to revised line buffer pointer.
4264
* pGroup = pointer to parsed group argument.
4265
* Return = FALSE iff invalid group argument.
4270
* The only valid nonNULL arguments are "icon", "window", and "transient".
4272
*************************************<->***********************************/
4274
static Boolean ParseWmFuncGrpArg (unsigned char **linePP,
4275
WmFunction wmFunction, GroupArg *pGroup)
4277
unsigned char *lineP = *linePP;
4278
unsigned char *startP;
4279
unsigned char grpStr[MAX_GROUP_STRLEN+1];
4284
* Parse groups while each is followed by "|".
4291
* Skip whitespace and find next group string.
4294
ScanWhitespace (&lineP);
4296
ScanAlphanumeric (&lineP);
4297
if (startP == lineP)
4298
/* Group missing => use default or complain */
4302
PWarning (((char *)GETMESSAGE(60, 18, "Missing group specification")));
4307
*pGroup = F_GROUP_DEFAULT;
4313
* Found a group string; compare it with valid groups.
4316
len = min (lineP - startP, MAX_GROUP_STRLEN);
4317
(void) strncpy ((char *)grpStr, (char *)startP, len);
4321
if (!strcmp ("icon", (char *)grpStr))
4323
*pGroup |= F_GROUP_ICON;
4325
else if (!strcmp ("window", (char *)grpStr))
4327
*pGroup |= F_GROUP_WINDOW;
4329
else if (!strcmp ("transient", (char *)grpStr))
4331
*pGroup |= F_GROUP_TRANSIENT;
4334
/* Unknown group name */
4336
PWarning (((char *)GETMESSAGE(60, 19, "Invalid group specification")));
4341
* Continue processing until the line is exhausted.
4345
ScanWhitespace (&lineP);
4347
if (lineP == NULL || *lineP == '\0')
4351
else if (*lineP == '|')
4360
} /* END OF FUNCTION ParseWmFuncGrpArg */
4364
/*************************************<->*************************************
4366
* ParseWmFuncNbrArg (linePP, wmFunction, pNumber)
4371
* Parses a window manager function number argument.
4376
* linePP = pointer to current line buffer pointer.
4377
* wmFunction = function
4378
* pNumber = pointer to number argument destination.
4383
* linePP = pointer to revised line buffer pointer.
4384
* pNumber = pointer to parsed number argument.
4385
* Return = FALSE iff invalid number argument.
4392
*************************************<->***********************************/
4394
static Boolean ParseWmFuncNbrArg (unsigned char **linePP,
4395
WmFunction wmFunction,
4396
unsigned long *pNumber)
4400
val = StrToNum (GetString (linePP));
4403
PWarning (((char *)GETMESSAGE(60, 20, "Invalid number specification")));
4411
} /* END OF FUNCTION ParseWmFuncNbrArg */
4414
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
4415
/*************************************<->*************************************
4417
* ParseWmFuncCCIArgs (linePP, wmFunction, pArgs)
4422
* Parses a Client-Command entry's arguments.
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.
4434
* linePP = pointer to revised line buffer pointer.
4435
* pArgs = pointer to parsed argument string.
4436
* Return = FALSE iff insufficient memory
4443
*************************************<->***********************************/
4445
static Boolean ParseWmFuncCCIArgs (unsigned char **linePP,
4446
WmFunction wmFunction, String *pArgs)
4452
* modifier cci_entry_list
4456
* cci_entry . cci_entry
4462
* any combination of alpha and '_'
4465
CCIEntryModifier mod;
4467
unsigned char *string;
4470
cciArg = XtNew(CCIFuncArg);
4472
if ((string = GetString(linePP)) == NULL)
4474
/* Error - no data for f.cci command. cci_entry_list is required. */
4475
fprintf(stderr, "Incorrect format for f.cci command.\n");
4480
/* check if no modifier was specified. */
4481
if (string[0] == '<')
4484
cciArg->cciEntry = XtNewString((char*)string);
4488
if (! GetCCIModifier((String)string, &mod))
4491
cciArg->cciEntry = XtNewString("");
4497
if ((string = GetString(linePP)) == NULL)
4499
/* Found a modifier, but there's no cci_entry_list. */
4500
fprintf(stderr, "Incorrect format for f.cci command.\n");
4505
cciArg->cciEntry = XtNewString((char*)string);
4510
*pArgs = (String)cciArg;
4514
} /* END OF FUNCTION ParseWmFuncCCIArgs */
4515
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
4518
/*************************************<->*************************************
4525
* This function parses a button set specification string:
4529
* button context function
4530
* button context function
4532
* button context function
4539
* pSD->buttonBindings = buttonBindings resource value
4540
* functionTable = window manager function parse table
4545
* pSD->buttonSpecs = list of button binding specifications.
4550
* The button set specification name must match pSD->buttonBindings.
4552
*************************************<->***********************************/
4554
void ParseButtonStr (WmScreenData *pSD, unsigned char *buttonStr)
4556
unsigned char *lineP;
4560
if (((parseP = buttonStr) != NULL) && (GetNextLine () != NULL))
4563
ParseButtonSet (pSD, lineP);
4566
} /* END OF FUNCTION ParseButtonStr */
4569
/*************************************<->*************************************
4571
* ParseButtonSet (pSD, lineP)
4576
* Button set specification found. Parse the following syntax:
4579
* Buttons bindings_name
4581
* button context function
4582
* button context function
4584
* button context function
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
4598
* lineP = pointer to current character in line buffer
4599
* pSD->buttonSpecs = list of button binding specifications.
4604
* Skips unnamed button binding set and sets with names that don't match
4605
* the buttonBindings resource.
4606
* Skips bad button binding specifications.
4608
*************************************<->***********************************/
4610
static void ParseButtonSet (WmScreenData *pSD, unsigned char *lineP)
4612
unsigned char *string;
4613
ButtonSpec *buttonSpec;
4614
ButtonSpec *lastButtonSpec;
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.
4623
if (((string = GetString (&lineP)) == NULL) ||
4624
(pSD->buttonBindings == NULL) ||
4625
strcmp ((char *)string, pSD->buttonBindings))
4631
* Require leading '{' on the next line.
4633
while ((GetNextLine () != NULL)) /* not EOF nor read error */
4636
ScanWhitespace(&lineP);
4638
if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
4639
/* ignore empty or comment line */
4651
PWarning (((char *)GETMESSAGE(60, 21, "Expected '{' after button set name")));
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.
4662
lastButtonSpec = pSD->buttonSpecs;
4663
if (lastButtonSpec != NULL)
4665
while (lastButtonSpec->nextButtonSpec != NULL)
4667
lastButtonSpec = (lastButtonSpec->nextButtonSpec);
4672
* Parse "button context function" until "}" or EOF found.
4673
* Skips bad button binding specifications.
4676
while ((GetNextLine () != NULL)) /* not EOF nor read error */
4679
ScanWhitespace(&lineP);
4680
if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
4681
/* ignore empty or comment lines */
4685
if (*lineP == '}') /* finished with button set */
4691
* Allocate space for the button binding specification.
4693
if ((buttonSpec = (ButtonSpec *)XtMalloc (sizeof (ButtonSpec))) == NULL)
4695
PWarning (((char *)GETMESSAGE(60, 22, "Insufficient memory for button specification")));
4698
buttonSpec->wmFunction = (WmFunction)NULL;
4699
buttonSpec->wmFuncArgs = NULL;
4700
buttonSpec->nextButtonSpec = NULL;
4703
* Parse the button specification "button".
4706
if (!ParseBtnEvent(&lineP,
4707
&buttonSpec->eventType,
4708
&buttonSpec->button,
4710
&buttonSpec->click))
4712
PWarning (((char *)GETMESSAGE(60, 23, "Invalid button specification")));
4713
XtFree ((char *)buttonSpec);
4714
continue; /* skip this button specification */
4719
* Parse the button context.
4721
if (!ParseContext(&lineP, &buttonSpec->context,
4722
&buttonSpec->subContext))
4724
PWarning (((char *)GETMESSAGE(60, 24, "Invalid button context")));
4725
XtFree ((char *)buttonSpec);
4726
continue; /* skip this button specification */
4730
* Parse the button function and any arguments.
4733
ix = ParseWmFunction (&lineP, CRS_BUTTON, &buttonSpec->wmFunction);
4736
* remove any subContexts that don't apply to this function
4739
if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) &&
4740
(buttonSpec->subContext & F_SUBCONTEXT_IB_IICON))
4742
buttonSpec->subContext &= ~F_SUBCONTEXT_IB_IICON;
4745
if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) &&
4746
(buttonSpec->subContext & F_SUBCONTEXT_IB_WICON))
4748
buttonSpec->subContext &= ~F_SUBCONTEXT_IB_WICON;
4752
* Map Button3 menus to BMenu virtual button
4754
if (buttonSpec->button == Button3 &&
4755
(buttonSpec->wmFunction == F_Menu ||
4756
buttonSpec->wmFunction == F_Post_SMenu)) {
4758
buttonSpec->button = wmGD.bMenuButton;
4762
* Apply the function argument parser.
4764
if (!(*(functionTable [ix].parseProc))
4765
(&lineP, buttonSpec->wmFunction, &buttonSpec->wmFuncArgs))
4767
XtFree ((char *)buttonSpec);
4768
continue; /* skip this button specification */
4772
* Add the button specification to the button specification list.
4774
if (lastButtonSpec != NULL)
4775
/* a prior specification exists */
4777
lastButtonSpec->nextButtonSpec = buttonSpec;
4781
pSD->buttonSpecs = buttonSpec;
4783
lastButtonSpec = buttonSpec;
4786
} /* END OF FUNCTION ParseButtonSet */
4790
/*************************************<->*************************************
4792
* ParseContext (linePP, context, subContext)
4797
* Parses a general context string.
4802
* linePP = pointer to current line buffer pointer.
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
4816
*************************************<->***********************************/
4818
static Boolean ParseContext (unsigned char **linePP, Context *context,
4819
Context *subContext)
4821
unsigned char *lineP = *linePP;
4822
unsigned char *startP;
4823
unsigned char ctxStr[MAX_CONTEXT_STRLEN+1];
4827
* Parse contexts while each is followed by "|".
4835
* Skip whitespace and find next context string.
4837
ScanWhitespace (&lineP);
4839
ScanAlphanumeric (&lineP);
4840
if (startP == lineP)
4841
/* ERROR: Context missing */
4847
* Found nonNULL string; compare it with valid contexts.
4850
len = min(lineP - startP, MAX_CONTEXT_STRLEN);
4851
(void) strncpy ((char *)ctxStr, (char *)startP, len);
4855
if (!strcmp ("root", (char *)ctxStr))
4857
*context |= F_CONTEXT_ROOT;
4858
*subContext |= F_SUBCONTEXT_R_ALL;
4860
else if (!strcmp ("icon", (char *)ctxStr))
4862
*context |= (F_CONTEXT_ICON |
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 );
4870
else if (!strcmp ("window", (char *)ctxStr))
4872
*context |= F_CONTEXT_WINDOW;
4873
*subContext |= F_SUBCONTEXT_W_ALL;
4875
else if (!strcmp ("frame", (char *)ctxStr))
4877
*context |= F_CONTEXT_WINDOW;
4878
*subContext |= F_SUBCONTEXT_W_FRAME;
4880
else if (!strcmp ("title", (char *)ctxStr))
4882
*context |= F_CONTEXT_WINDOW;
4883
*subContext |= F_SUBCONTEXT_W_TITLE;
4885
else if (!strcmp ("border", (char *)ctxStr))
4887
*context |= F_CONTEXT_WINDOW;
4888
*subContext |= F_SUBCONTEXT_W_BORDER;
4890
else if (!strcmp ("app", (char *)ctxStr))
4892
*context |= F_CONTEXT_WINDOW;
4893
*subContext |= F_SUBCONTEXT_W_APP;
4896
else if (!strcmp ("ifkey", (char *)ctxStr))
4898
*context |= F_CONTEXT_IFKEY;
4902
/* Unknown context name */
4907
/* continue only if followed by '|' */
4908
ScanWhitespace (&lineP);
4919
} /* END OF FUNCTION ParseContext */
4922
/*************************************<->*************************************
4929
* This function parses a key set specification string:
4933
* key context function
4934
* key context function
4936
* key context function
4942
* pSD->keyBindings = keyBindings resource value
4943
* functionTable = window manager function parse table
4948
* pSD->keySpecs = list of key binding specification
4953
* The key set specification name must match pSD->keyBindings.
4955
*************************************<->***********************************/
4958
ParseKeyStr (WmScreenData *pSD, unsigned char *keyStr)
4960
unsigned char *lineP;
4964
if (((parseP = keyStr) != NULL) && (GetNextLine () != NULL))
4967
ParseKeySet (pSD, lineP);
4970
} /* END OF FUNCTION ParseKeyStr */
4974
/*************************************<->*************************************
4976
* ParseKeySet (pSD, lineP)
4981
* Key set specification found. Parse the following syntax:
4984
* Keys bindings_name
4986
* key context function
4987
* key context function
4989
* key context function
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
5003
* lineP = pointer to current character in line buffer
5004
* pSD->keySpecs = list of key binding specifications.
5009
* Skips unnamed key binding set and sets with names that don't match the
5010
* keyBindings resource.
5011
* Skips bad key binding specifications.
5013
*************************************<->***********************************/
5015
static void ParseKeySet (WmScreenData *pSD, unsigned char *lineP)
5017
unsigned char *string;
5019
KeySpec *lastKeySpec;
5020
unsigned int eventType;
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.
5032
if (((string = GetString (&lineP)) == NULL) ||
5033
(pSD->keyBindings == NULL) ||
5034
strcmp ((char *)string, pSD->keyBindings))
5040
* Require leading '{' on next line.
5042
while ((GetNextLine () != NULL)) /* not EOF nor read error */
5045
ScanWhitespace(&lineP);
5047
if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
5048
/* ignore empty or comment line */
5060
PWarning (((char *)GETMESSAGE(60, 25, "Expected '{' after key set name")));
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.
5071
lastKeySpec = pSD->keySpecs;
5072
if (lastKeySpec != NULL)
5074
while (lastKeySpec->nextKeySpec != NULL)
5076
lastKeySpec = (lastKeySpec->nextKeySpec);
5081
* Parse "key context function" until "}" or EOF found.
5082
* Skip bad key bindings.
5085
while ((GetNextLine () != NULL)) /* not EOF nor read error */
5088
ScanWhitespace (&lineP);
5089
if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
5090
/* ignore empty or comment lines */
5094
if (*lineP == '}') /* finished with key set */
5100
* Allocate space for the key specification.
5102
if ((keySpec = (KeySpec *)XtMalloc (sizeof (KeySpec))) == NULL)
5104
PWarning (((char *)GETMESSAGE(60, 26, "Insufficient memory for key specification")));
5108
keySpec->wmFunction = (WmFunction)NULL;
5109
keySpec->wmFuncArgs = NULL;
5110
keySpec->nextKeySpec = NULL;
5113
* Parse the key specification.
5118
if (!ParseKeyEvent(&lineP,
5126
PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
5127
XtFree ((char *)keySpec);
5128
continue; /* skip this key specification */
5133
* Parse the key context.
5134
* Here lineP points to the candidate context string.
5137
if (!ParseContext(&lineP, &keySpec->context,
5138
&keySpec->subContext))
5142
PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
5144
PWarning (((char *)GETMESSAGE(60, 28, "Invalid key context")));
5145
XtFree ((char *)keySpec);
5146
continue; /* skip this key specification */
5152
* Don't print an error message if this is a "hardware
5153
* available" binding.
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 */
5162
* This flag is only used for parsing, clear it so the
5163
* rest of the program doesn't see it.
5165
keySpec->context &= ~F_CONTEXT_IFKEY;
5170
* Parse the key function and any arguments.
5173
ix = ParseWmFunction (&lineP, CRS_KEY, &keySpec->wmFunction);
5176
* remove any subContexts that don't apply to this function
5178
if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) &&
5179
(keySpec->subContext & F_SUBCONTEXT_IB_IICON))
5181
keySpec->subContext &= ~F_SUBCONTEXT_IB_IICON;
5184
if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) &&
5185
(keySpec->subContext & F_SUBCONTEXT_IB_WICON))
5187
keySpec->subContext &= ~F_SUBCONTEXT_IB_WICON;
5191
* Apply the function argument parser.
5193
if (!(*(functionTable [ix].parseProc))
5194
(&lineP, keySpec->wmFunction, &keySpec->wmFuncArgs))
5196
XtFree ((char *)keySpec);
5197
continue; /* skip this key specification */
5201
* Add the key specification to the key specification list.
5203
if (lastKeySpec != NULL)
5204
/* a prior specification exists */
5206
lastKeySpec->nextKeySpec = keySpec;
5210
pSD->keySpecs = keySpec;
5212
lastKeySpec = keySpec;
5215
} /* END OF FUNCTION ParseKeySet */
5219
/*************************************<->*************************************
5226
* Returns the next line from an fopened configuration file or a newline-
5227
* embedded configuration string.
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
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.
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.
5252
*************************************<->***********************************/
5257
register unsigned char *string;
5260
#ifndef NO_MULTIBYTE
5269
/* read fopened file */
5271
if ((string = (unsigned char *)
5272
fgets ((char *)line, MAXLINE, cfileP)) != NULL)
5274
#ifndef NO_MULTIBYTE
5278
((len = mblen((char *)string, MB_CUR_MAX)) > 0))
5280
mbtowc(&last, (char *)string, MB_CUR_MAX);
5285
mbtowc(&wdelim, &delim, MB_CUR_MAX);
5286
if (lastlen == 1 && last == wdelim)
5290
if (!fgets((char *)string, MAXLINE - (string - line), cfileP))
5295
((len = mblen((char *)string, MB_CUR_MAX)) > 0))
5297
mbtowc(&last, (char *)string, MB_CUR_MAX);
5303
while (lastlen == 1 && last == wdelim);
5307
len = strlen((char *)string) - 2;
5308
if ((len > 0) && string[len] == '\\')
5311
string = &string[len];
5312
if (fgets((char *)string,
5313
MAXLINE - (string-line), cfileP) == NULL)
5315
len = strlen((char *)string) - 2;
5317
} while ((len >= 0) && string[len] == '\\');
5323
else if ((parseP != NULL) && (*parseP != '\0'))
5324
/* read parse string */
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 */
5334
while ((*parseP != '\0') &&
5335
((chlen = mblen ((char *)parseP, MB_CUR_MAX)) > 0) &&
5337
/* copy all but NULL and newlines to line buffer */
5341
*(string++) = *(parseP++);
5345
while ((*parseP != '\0') && (*parseP != '\n'))
5346
/* copy all but end-of-line and newlines to line buffer */
5348
*(string++) = *(parseP++);
5351
/* fix for bug 1127 */
5352
if(string) *string = '\0'; /* *string = '\0'; */
5353
if (*parseP == '\n')
5366
} /* END OF FUNCTION GetNextLine */
5372
/*************************************<->*************************************
5374
* GetStringC (linePP, SmBehavior)
5379
* Returns the next quoted or whitespace-terminated nonquoted string in the
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.
5388
* linePP = pointer to current line buffer pointer.
5389
* SmBehavior = flag that enables parsing session manager hints
5395
* linePP = pointer to revised line buffer pointer.
5401
* May alter the line buffer contents.
5402
* Handles quoted strings and characters, removing trailing whitespace from
5404
* Returns NULL string if the line is empty or is a comment.
5405
* Code stolen from dtmwm.
5407
*************************************<->***********************************/
5409
/*************************************<->*************************************
5411
* GetString (linePP)
5416
* Returns the next quoted or whitespace-terminated nonquoted string in the
5422
* linePP = pointer to current line buffer pointer.
5427
* linePP = pointer to revised line buffer pointer.
5433
* May alter the line buffer contents.
5434
* Handles quoted strings and characters, removing trailing whitespace from
5436
* Returns NULL string if the line is empty or is a comment.
5438
*************************************<->***********************************/
5442
unsigned char *GetStringC (unsigned char **linePP, Boolean SmBehavior)
5444
unsigned char *GetString (unsigned char **linePP)
5447
unsigned char *lineP = *linePP;
5448
unsigned char *endP;
5449
unsigned char *curP;
5450
unsigned char *lnwsP;
5452
unsigned int level = 0, checkLev, i, quoteLevel[10];
5454
#ifndef NO_MULTIBYTE
5457
/* get rid of leading white space */
5458
ScanWhitespace (&lineP);
5461
* Return NULL if line is empty, a comment, or invalid.
5466
((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
5467
((chlen == 1) && ((*lineP == '!') ||
5468
((!SmBehavior) && (*lineP == '#'))))
5473
((chlen = mblen ((char *)lineP, MB_CUR_MAX)) < 1) ||
5474
((chlen > 0) && ((*lineP == '!') || (*lineP == '#')))
5482
if ((chlen == 1) && (*lineP == '"'))
5486
quoteLevel[level] = 1;
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.
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.
5501
lnwsP = lineP++; /* lnwsP points to first '"' */
5502
curP = endP = lineP; /* other pointers point beyond */
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.
5512
if ((chlen == 1) && (*endP == '\\') &&
5513
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
5515
* copy first byte of quoted nonNULL character down.
5516
* point curP to next byte
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
5526
checkLev = PeekAhead((curP - 1), quoteLevel[level]);
5529
if(quoteLevel[level] <= checkLev)
5536
quoteLevel[level] = checkLev;
5539
for(i = 0;i < (checkLev - 2);i++)
5541
*endP++ = *curP++;curP++;
5556
/* Singlebyte character: character copy finished. */
5558
if (isspace (*endP))
5559
/* whitespace character: leave lnwsP unchanged. */
5564
/* non-whitespace character: point lnwsP to it. */
5570
/* Multibyte (nonwhitespace) character: point lnwsP to it.
5571
* Finish character byte copy.
5584
/* get rid of leading white space */
5585
ScanWhitespace (&lineP);
5588
/* Return NULL if line is empty, whitespace, or begins with a comment. */
5589
if ((lineP == NULL || *lineP == '\0') ||
5590
(!SmBehavior && (*lineP == '#')))
5592
/* Return NULL if line is empty, whitespace, or begins with a comment. */
5593
if ((lineP == NULL) || (*lineP == '\0') || (*lineP == '#'))
5604
quoteLevel[level] = 1;
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.
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.
5619
lnwsP = lineP++; /* lnwsP points to first '"' */
5620
curP = endP = lineP; /* other pointers point beyond */
5622
while ((*endP = *curP) && (*endP != '"'))
5623
/* haven't found matching quote yet */
5625
/* point curP to next character */
5627
if ((*endP == '\\') && (*curP != '\0'))
5628
/* shift quoted nonNULL character down and curP ahead */
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
5637
checkLev = PeekAhead((curP - 1), quoteLevel[level]);
5640
if(quoteLevel[level] <= checkLev)
5647
quoteLevel[level] = checkLev;
5650
for(i = 0;i < (checkLev - 2);i++)
5652
*endP++ = *curP++;curP++;
5665
if (isspace (*endP))
5666
/* whitespace character: leave lnwsP unchanged. */
5671
/* non-whitespace character: point lnwsP to it. */
5679
* Found matching quote or NULL.
5680
* NULL out any trailing whitespace.
5691
/* Unquoted string */
5694
* Find the end of the nonquoted string.
5695
* '\' quotes the next character.
5696
* Otherwise, whitespace, end-of-line, or '#' terminates the string.
5698
curP = endP = lineP;
5700
#ifndef NO_MULTIBYTE
5702
while ((*endP = *curP) &&
5703
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
5704
((chlen > 1) || (!isspace (*curP) &&
5705
(SmBehavior || (*curP != '#')))))
5707
while ((*endP = *curP) &&
5708
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0) &&
5709
((chlen > 1) || (!isspace (*curP) && (*curP != '#'))))
5711
/* Haven't found whitespace or '#' yet.
5712
* First byte of next character has been copied to endP.
5716
if ((chlen == 1) && (*endP == '\\') &&
5717
((chlen = mblen ((char *)curP, MB_CUR_MAX)) > 0))
5719
* copy first byte of quoted nonNULL character down.
5720
* point curP to next byte
5727
/* Multibyte character: finish character copy. */
5737
while ((*endP = *curP) && !isspace (*endP) &&
5738
(SmBehavior || (*endP != '#')))
5740
while ((*endP = *curP) && !isspace (*endP) && (*endP != '#'))
5743
/* point curP to next character */
5745
if ((*endP == '\\') && (*curP != '\0'))
5746
/* shift quoted nonNULL character down and curP ahead */
5756
* Three cases for *endP:
5757
* '#' --> write NULL over # and point to NULL
5759
* matching quote -> write end-of-line over char and point beyond
5760
* NULL -> point to NULL
5764
if (!SmBehavior && (*endP == '#'))
5769
*endP = '\0'; /* write '\0' over '#' */
5770
*linePP = endP; /* point to '\0' */
5772
else if (*endP != '\0')
5774
*endP = '\0'; /* write NULL over terminator */
5775
*linePP = ++curP; /* point beyond terminator */
5781
return ((unsigned char *)lineP);
5783
} /* END OF FUNCTION GetString */
5784
#endif /* PANELIST */
5788
/*************************************<->*************************************
5790
* ParseBtnEvent (linePP, eventType, button, state, fClick)
5795
* Parse a button event specification.
5800
* linePP = pointer to current line buffer pointer
5801
* buttonEvents = (global) button event parse table
5802
* modifierStrings = (global) modifier string/mask table
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?
5813
* Return = (Boolean) true iff valid button event specification
5820
*************************************<->***********************************/
5822
Boolean ParseBtnEvent (unsigned char **linePP,
5823
unsigned int *eventType,
5824
unsigned int *button,
5825
unsigned int *state,
5828
if (!ParseEvent (linePP, buttonEvents, eventType, button, state, fClick))
5834
* The following is a fix for an X11 deficiency in regards to
5835
* modifiers in grabs.
5837
if (*eventType == ButtonRelease)
5839
/* the button that is going up will always be in the modifiers... */
5840
*state |= buttonModifierMasks[*button];
5845
} /* END OF FUNCTION ParseBtnEvent */
5849
/*************************************<->*************************************
5851
* ParseKeyEvent (linePP, eventType, keyCode, state)
5856
* Parse a key event specification.
5861
* linePP = pointer to current line buffer pointer
5862
* keyEvents = (global) key event parse table
5863
* modifierStrings = (global) modifier string/mask table
5868
* linePP = pointer to revised line buffer pointer.
5869
* eventType = type of event
5870
* keyCode = parsed KeyCode
5871
* state = composite modifier mask
5873
* Return = (Boolean) true iff valid key event specification
5880
*************************************<->***********************************/
5882
Boolean ParseKeyEvent (unsigned char **linePP, unsigned int *eventType,
5883
KeyCode *keyCode, unsigned int *state)
5888
unsigned int keySym = 0;
5890
if (!ParseEvent (linePP, keyEvents, eventType, &keySym, state, &fClick))
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
5901
*keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym);
5905
if (keySym == XK_F9)
5909
else if (keySym == XK_F10)
5913
else if (keySym == XK_F11)
5917
else if (keySym == XK_F12)
5921
*keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym);
5924
return (*keyCode != 0);
5926
} /* END OF FUNCTION ParseKeyEvent */
5929
/*************************************<->*************************************
5931
* ParseEvent (linePP, table, eventType, detail, state, fClick)
5936
* Parse an event specification.
5941
* linePP = pointer to current line buffer pointer.
5942
* table = event parse table
5943
* modifierStrings = (global) modifier string/mask table
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
5954
* Return = (Boolean) true iff valid event specification
5960
*************************************<->***********************************/
5962
static Boolean ParseEvent (unsigned char **linePP, EventTableEntry *table,
5963
unsigned int *eventType, unsigned int *detail,
5964
unsigned int *state, Boolean *fClick)
5966
unsigned char *lineP = *linePP;
5970
/* Parse the modifiers */
5971
if (!ParseModifiers (&lineP, state) || *lineP != '<')
5975
lineP++; /* skip '<' */
5977
/* Parse the event type */
5978
if (!ParseEventType (&lineP, table, eventType, &ix) || *lineP != '>')
5982
lineP++; /* skip '>' */
5985
* Compute detail and fClick.
5986
* Status will be False for a invalid KeySym name.
5988
status = (*(table[ix].parseProc))(&lineP, table[ix].closure, detail);
5989
*fClick = table[ix].fClick;
5997
} /* END OF FUNCTION ParseEvent */
6001
/*************************************<->*************************************
6003
* ParseModifiers(linePP, state)
6008
* Parses a modifier specification.
6013
* linePP = pointer to current line buffer pointer.
6014
* modifierStrings = (global) modifier string/mask table
6019
* linePP = pointer to revised line buffer pointer.
6020
* state = composite modifier mask
6021
* Return = (Boolean) true iff valid modifier name
6026
* If successful, will be followed by NULL or '<'.
6028
*************************************<->***********************************/
6030
static Boolean ParseModifiers(unsigned char **linePP, unsigned int *state)
6032
unsigned char *lineP = *linePP;
6033
unsigned char *startP;
6034
unsigned char modStr[MAX_MODIFIER_STRLEN+1];
6036
unsigned int maskBit;
6042
* Parse modifiers until the event specifier is encountered.
6045
ScanWhitespace (&lineP);
6046
while ((*lineP != '\0') && (*lineP != '<'))
6059
ScanAlphanumeric (&lineP);
6060
if (startP == lineP)
6061
/* ERROR: Modifier or '<' missing */
6065
len = min(lineP - startP, MAX_MODIFIER_STRLEN);
6066
(void) strncpy ((char *)modStr, (char *)startP, len);
6069
if (!LookupModifier (modStr, &maskBit))
6070
/* Unknown modifier name */
6083
ScanWhitespace(&lineP);
6087
return (TRUE); /* must have '<' or NULL following */
6089
} /* END OF FUNCTION ParseModifiers */
6092
/*************************************<->*************************************
6094
* LookupModifier (name, valueP)
6099
* Return the modifier mask for the provided modifier name.
6104
* name = modifier string
6105
* modifierStrings = modifier string/mask table
6110
* valueP = modifier mask
6111
* Return = (Boolean) true iff valid modifier name
6118
*************************************<->***********************************/
6120
static Boolean LookupModifier (unsigned char *name, unsigned int *valueP)
6127
for (i=0; modifierStrings[i].name != NULL; i++)
6129
if (!strcmp (modifierStrings[i].name, (char *)name))
6131
*valueP = modifierStrings[i].mask;
6139
} /* END OF FUNCTION LookupModifier */
6142
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
6143
/*************************************<->*************************************
6145
* GetCCIModifier (modString, mod)
6150
* Return the cci modifier corresponding to the specified string
6155
* modString = cci modifier string; may be null
6160
* mod = cci modifier.
6161
* Return = (Boolean) true iff valid modifier string
6168
*************************************<->***********************************/
6170
static Boolean GetCCIModifier (String modString, CCIEntryModifier *mod)
6175
if (modString != NULL)
6177
ToLower ((unsigned char *)modString);
6178
for (i=NONE; i<=EXCLUDE; i++)
6180
if (!strcmp (CCIEntryModifierNames[i], modString))
6190
} /* END OF FUNCTION GetCCIModifier */
6193
/*************************************<->*************************************
6195
* FixMenuItem (menuSpec, menuItem)
6200
* Fix-up the menuItem so that it appears an old-style cci command was
6201
* read from the .mwmrc file
6206
* menuItem = the menu item structure
6207
* menuSpec = the menu specification structure
6212
* menuItem = the fixed-up menuitem
6213
* menuSpec = the fixed-up menu specification structure if EXCLUDE found
6219
*************************************<->***********************************/
6221
static void FixMenuItem (MenuSpec *menuSpec, MenuItem *menuItem)
6227
if (menuItem == NULL)
6230
cciArg = (CCIFuncArg *)menuItem->wmFuncArgs;
6232
menuItem->clientCommandName = menuItem->label;
6233
menuItem->label = cciArg->cciEntry;
6236
* Fix-up the label to handle the modifier.
6239
switch (cciArg->mod)
6249
tmp = (String) XtMalloc(strlen(menuItem->label) + 3);
6250
sprintf(tmp, "->%s", menuItem->label);
6251
XtFree(menuItem->label);
6252
menuItem->label = tmp;
6257
tmp = (String) XtMalloc(strlen(menuItem->label) + 2);
6258
sprintf(tmp, "=%s", menuItem->label);
6259
XtFree(menuItem->label);
6260
menuItem->label = tmp;
6263
case DELIMIT_INLINE:
6266
case DELIMIT_CASCADE:
6268
tmp = (String) XtMalloc(strlen(menuItem->label) + 3);
6269
sprintf(tmp, "=>%s", menuItem->label);
6270
XtFree(menuItem->label);
6271
menuItem->label = tmp;
6276
StoreExclusion(menuSpec, menuItem->label);
6278
tmp = (String) XtMalloc(strlen(menuItem->label) + 2);
6279
sprintf(tmp, "~%s", menuItem->label);
6280
XtFree(menuItem->label);
6281
menuItem->label = tmp;
6285
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
6288
/*************************************<->*************************************
6290
* ParseEventType(linePP, table, eventType, ix)
6295
* Parses the event type string.
6300
* linePP = pointer to current line buffer pointer.
6301
* table = event parse table
6306
* linePP = pointer to revised line buffer pointer.
6307
* eventType = type of event
6308
* ix = table index for matched event
6310
* Return = (Boolean) true iff valid event
6317
*************************************<->***********************************/
6319
static Boolean ParseEventType (unsigned char **linePP, EventTableEntry *table,
6320
unsigned int *eventType, Cardinal *ix)
6322
unsigned char *lineP = *linePP;
6323
unsigned char *startP = *linePP;
6324
unsigned char eventTypeStr[MAX_EVENTTYPE_STRLEN+1];
6327
/* Parse out the event string */
6328
ScanAlphanumeric (&lineP);
6331
* Attempt to match the parsed event against our supported event set.
6334
if (startP != lineP)
6336
len = min (lineP - startP, MAX_EVENTTYPE_STRLEN);
6337
(void) strncpy ((char *)eventTypeStr, (char *)startP, len);
6338
eventTypeStr[len] = '\0';
6339
ToLower (eventTypeStr);
6341
for (len = 0; table[len].event != NULL; len++)
6342
if (!strcmp (table[len].event, (char *)eventTypeStr))
6345
*eventType = table[*ix].eventType;
6351
/* Unknown event specified */
6354
} /* END OF FUNCTION ParseEventType */
6357
/*************************************<->*************************************
6359
* ParseImmed (linePP, closure, detail)
6364
* Button event detail procedure.
6370
* closure = table entry
6375
* detail = pointer to closure
6384
*************************************<->***********************************/
6386
static Boolean ParseImmed (unsigned char **linePP, unsigned int closure,
6387
unsigned int *detail)
6392
} /* END OF FUNCTION ParseImmed */
6395
/*************************************<->*************************************
6397
* ParseKeySym (linePP, closure, detail)
6402
* Key event detail procedure. Parses a KeySym string.
6407
* linePP = pointer to current line buffer pointer
6409
* closure = not used.
6414
* linePP = pointer to revised line buffer pointer
6415
* detail = pointer to parsed KeySym
6417
* Return = (Boolean) true iff valid KeySym string
6424
*************************************<->***********************************/
6426
static Boolean ParseKeySym (unsigned char **linePP, unsigned int closure,
6427
unsigned int *detail)
6429
unsigned char *lineP = *linePP;
6430
unsigned char *startP;
6431
char keySymName[MAX_KEYSYM_STRLEN+1];
6433
#ifndef NO_MULTIBYTE
6437
ScanWhitespace (&lineP);
6440
#ifndef NO_MULTIBYTE
6442
((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 0) &&
6444
(!isspace (*lineP) && *lineP != ',' && *lineP != ':')))
6446
/* Skip next character */
6450
while (*lineP && !isspace (*lineP) && *lineP != ',' && *lineP != ':' )
6452
/* Skip next character */
6457
len = min (lineP - startP, MAX_KEYSYM_STRLEN);
6458
(void) strncpy (keySymName, (char *)startP, len);
6459
keySymName[len] = '\0';
6461
#ifndef NO_MULTIBYTE
6462
if ((*detail = XStringToKeysym(keySymName)) == NoSymbol &&
6463
(mblen (keySymName, MB_CUR_MAX) == 1))
6465
if ((*detail = XStringToKeysym(keySymName)) == NoSymbol)
6468
if (!isdigit (keySymName[0]) ||
6469
((*detail = StrToNum ((unsigned char *)&keySymName[0])) == -1))
6478
} /* END OF FUNCTION ParseKeySym */
6482
/*************************************<->*************************************
6489
* Converts a string to an unsigned hexadecimal, decimal, or octal integer.
6494
* str = character string
6499
* Return = unsigned integer
6506
*************************************<->***********************************/
6508
static unsigned int StrToNum(unsigned char *str)
6511
unsigned int val = 0;
6516
if (*str == 'x' || *str == 'X')
6518
return (StrToHex(++str));
6520
return (StrToOct(str));
6523
while ((c = *str) != '\0')
6525
if ('0' <= c && c <= '9')
6538
} /* END OF FUNCTION StrToNum */
6542
/*************************************<->*************************************
6561
*************************************<->***********************************/
6563
static unsigned int StrToHex(unsigned char *str)
6566
unsigned int val = 0;
6568
while ((c = *str) != '\0')
6570
if ('0' <= c && c <= '9')
6574
else if ('a' <= c && c <= 'f')
6576
val = val*16+c-'a'+10;
6578
else if ('A' <= c && c <= 'F')
6580
val = val*16+c-'A'+10;
6591
} /* END OF FUNCTION StrToHex */
6595
/*************************************<->*************************************
6614
*************************************<->***********************************/
6616
static unsigned int StrToOct(unsigned char *str)
6619
unsigned int val = 0;
6621
while ((c = *str) != '\0')
6623
if ('0' <= c && c <= '7')
6636
} /* END OF FUNCTION StrToOct */
6640
/*************************************<->*************************************
6642
* ScanAlphanumeric (linePP)
6647
* Scan string until a non-alphanumeric character is encountered.
6652
* linePP = nonNULL pointer to current line buffer pointer
6657
* linePP = nonNULL pointer to revised line buffer pointer
6662
* Assumes linePP is nonNULL
6664
*************************************<->***********************************/
6666
void ScanAlphanumeric (unsigned char **linePP)
6668
#ifndef NO_MULTIBYTE
6672
((chlen = mblen ((char *) *linePP, MB_CUR_MAX)) > 0) &&
6673
((chlen > 1) || isalnum (**linePP)))
6678
while (*linePP && isalnum (**linePP))
6684
} /* END OF FUNCTION ScanAlphanumeric */
6689
/*************************************<->*************************************
6691
* ScanWhitespace(linePP)
6696
* Scan the string, skipping over all white space characters.
6701
* linePP = nonNULL pointer to current line buffer pointer
6706
* linePP = nonNULL pointer to revised line buffer pointer
6711
* Assumes linePP is nonNULL
6713
*************************************<->***********************************/
6715
void ScanWhitespace(unsigned char **linePP)
6717
#ifndef NO_MULTIBYTE
6718
while (*linePP && (mblen ((char *)*linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
6720
while (*linePP && isspace (**linePP))
6726
} /* END OF FUNCTION ScanWhitespace */
6727
#endif /* not WSM */
6731
/*************************************<->*************************************
6738
* Lower all characters in a string.
6743
* string = NULL-terminated character string or NULL
6748
* string = NULL-terminated lower case character string or NULL
6755
*************************************<->***********************************/
6757
void ToLower (unsigned char *string)
6759
unsigned char *pch = string;
6760
#ifndef NO_MULTIBYTE
6763
while (*pch && ((chlen = mblen ((char *)pch, MB_CUR_MAX)) > 0))
6765
if ((chlen == 1) && (isupper (*pch)))
6767
*pch = tolower(*pch);
6772
while (*pch != '\0')
6776
*pch = tolower(*pch);
6782
} /* END OF FUNCTION ToLower */
6786
/*************************************<->*************************************
6788
* PWarning (message)
6793
* This function lists a resource description parse message to stderr.
6798
* message = pointer to a message string
6799
* cfileP = (global) file pointer to fopened configuration file or NULL
6800
* linec = (global) line counter
6802
*************************************<->***********************************/
6805
PWarning (char *message)
6809
char pch[MAXWMPATH+1];
6813
sMessage = XtNewString ((String) message);
6816
if (pConfigStackTop->fileName)
6818
pchFile = pConfigStackTop->fileName;
6822
pchFile = wmGD.configFile;
6825
sprintf (pch, pWarningStringFile,
6826
GETMESSAGE(20,1,"Workspace Manager"),
6827
sMessage, linec, pchFile);
6831
sprintf (pch, pWarningStringLine,
6832
GETMESSAGE(20,1,"Workspace Manager"),
6835
_DtSimpleError (wmGD.mwmName, DtIgnore, NULL, pch, NULL);
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);
6846
fprintf (stderr, ((char *)GETMESSAGE(60, 34, "%s: %s on line %d of specification string\n")),
6847
wmGD.mwmName, message, linec);
6853
} /* END OF FUNCTION PWarning */
6857
* Key substitution table entry
6860
typedef struct _keySubs
6862
unsigned char * pchFrom;
6864
unsigned char * pchTo;
6868
/*************************************<->*************************************
6870
* InitKeySubs (ppKeySubs, pNumKeySubs)
6875
* Initialize key label substitutions used in acclerator text
6880
* ppKeySubs = ptr to key substitution table ptr
6881
* pNumKeySubs = ptr to number of key substitutions
6886
* *ppKeySubs = ptr to key substitution table
6887
* *pNumKeySubs = number of substitutions found
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
6895
*************************************<->***********************************/
6897
static void InitKeySubs (
6904
unsigned char *pch0;
6905
unsigned char *pch1;
6907
#ifndef NO_MULTIBYTE
6911
pch0 = (unsigned char *)GETMESSAGE(60, 40, "");
6913
if ((pch0 == NULL) || (*pch0 == '\0'))
6923
while (*pch0 != '\0')
6925
ScanWhitespace (&pch0);
6926
if (*pch0 == '\0') break;
6929
* allocate space for next key sub
6933
pKSret = (KeySub *) XtMalloc (1*sizeof(KeySub));
6937
pKSret = (KeySub *) XtRealloc ((char *)pKSret,
6938
(numKS+1)*sizeof(KeySub));
6940
pKS = &pKSret[numKS];
6942
/* get "from" string */
6944
#ifndef NO_MULTIBYTE
6945
while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
6947
if ((chlen == 1) && (*pch1 == ' '))
6953
#else /* NO_MULTIBYTE */
6954
while (*pch1 && (*pch1 != ' ')) pch1++;
6955
#endif /* NO_MULTIBYTE */
6956
pKS->lenFrom = pch1 - pch0;
6957
if (pKS->lenFrom < 1)
6964
pKS->pchFrom = (unsigned char *) XtMalloc (1+pKS->lenFrom);
6965
memcpy (pKS->pchFrom, pch0, pKS->lenFrom);
6966
pKS->pchFrom[pKS->lenFrom] = '\0';
6968
/* get "to" string */
6969
ScanWhitespace (&pch1);
6972
#ifndef NO_MULTIBYTE
6973
while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
6975
if ((chlen == 1) && (*pch1 == ' '))
6981
#else /* NO_MULTIBYTE */
6982
while (*pch1 && (*pch1 != ' ')) pch1++;
6983
#endif /* NO_MULTIBYTE */
6989
* Invalid format, "from" string with no "to" string.
6993
pKS->pchTo = (unsigned char *) XtMalloc (1+len);
6994
memcpy (pKS->pchTo, pch0, len);
6995
pKS->pchTo[len] = '\0';
6997
/* advance cursor */
7000
/* got one, bump the counter */
7004
*ppKeySubs = pKSret;
7005
*pNumKeySubs = numKS;
7010
/*************************************<->*************************************
7012
* ProcessAccelText (startP, endP, destP)
7017
* Process accelerator text and copy into string.
7022
* startP = pointer to start of valid accelerator specification
7023
* endP = pointer past end of accelerator specification
7024
* destP = pointer to destination buffer
7029
* Destination buffer has processed accelerator text.
7035
*************************************<->***********************************/
7037
static void ProcessAccelText (unsigned char *startP, unsigned char *endP,
7038
unsigned char *destP)
7040
#ifndef NO_MULTIBYTE
7044
static Boolean bAccelInit = False;
7045
static KeySub *pKeySub;
7046
static int numKeySubs;
7047
unsigned char * pchFirst;
7048
unsigned char * pchSub;
7054
InitKeySubs (&pKeySub, &numKeySubs);
7063
ScanWhitespace (&startP);
7065
while (*startP != '<')
7069
*destP++ = *startP++;
7075
#ifndef NO_MULTIBYTE
7077
(((chlen = mblen ((char *)startP, MB_CUR_MAX)) > 1)
7078
|| isalnum (*startP)))
7086
*destP++ = *startP++;
7091
while (isalnum (*startP))
7096
*destP++ = *startP++;
7101
/* find substitution */
7105
for (i=0; i<numKeySubs; i++)
7107
if ((pKeySub[i].lenFrom == startP-pchFirst) &&
7108
(!strncasecmp ((char *)pKeySub[i].pchFrom, (char *)pchFirst,
7109
pKeySub[i].lenFrom)))
7111
pchSub = pKeySub[i].pchTo;
7112
lenSub = strlen((char *)pchSub);
7118
if ((pchSub != NULL) && (lenSub > 0))
7120
memcpy (destP, pchSub, lenSub);
7125
memcpy (destP, pchFirst, startP-pchFirst);
7126
destP += startP-pchFirst;
7131
ScanWhitespace (&startP);
7135
* Skip the key event type.
7137
startP++; /* skip '<' */
7138
while (*startP != '>')
7140
#ifndef NO_MULTIBYTE
7141
startP += mblen ((char *)startP, MB_CUR_MAX);
7146
startP++; /* skip '>' */
7149
* Copy the KeySym string.
7152
ScanWhitespace (&startP);
7153
while (startP != endP)
7155
*destP++ = *startP++;
7159
} /* END OF FUNCTION ProcessAccelText */
7163
/*************************************<->*************************************
7165
* ProcessCommandLine (argc, argv)
7170
* This function looks for and processes mwm options in the command line
7174
* argc = argument count.
7175
* argv = argument vector.
7180
* Changes global data to based on command line options recognized
7183
*************************************<->***********************************/
7184
#define SCREENS_OPT "-screens"
7185
#define MULTI_SCREEN_OPT "-multiscreen"
7187
void ProcessCommandLine (int argc, char *argv[])
7189
unsigned char *string;
7191
unsigned char *lineP;
7193
for (argnum = 1; argnum < argc; argnum++)
7195
lineP = (unsigned char *) argv[argnum];
7196
if ((string = GetString (&lineP)) == NULL)
7197
/* empty or comment line */
7201
if (!strcmp((char *)string, MULTI_SCREEN_OPT))
7203
wmGD.multiScreen = True;
7204
wmGD.numScreens = ScreenCount (DISPLAY);
7206
else if (!strcmp((char *)string, SCREENS_OPT))
7208
argnum++; /* skip to next arg */
7209
ParseScreensArgument (argc, argv, &argnum, lineP);
7213
} /* END OF FUNCTION ProcessCommandLine */
7216
/*************************************<->*************************************
7218
* ParseScreensArgument (argc, argv, pArgnum, lineP)
7223
* This function processes the ``-screens'' command line argument
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
7235
* Changes global data to based on command line options recognized
7236
* + wmGD.screenNames
7238
* Assumes default screenNames are already in place
7240
*************************************<->***********************************/
7242
static void ParseScreensArgument (int argc, char *argv[], int *pArgnum,
7243
unsigned char *lineP)
7245
unsigned char *string;
7250
for (; (*pArgnum < argc) && (sNum < ScreenCount(DISPLAY));
7251
(*pArgnum)++, sNum++)
7253
lineP = (unsigned char *)argv[*pArgnum];
7254
if (*argv[*pArgnum] == '"')
7257
* if Quote, use GetString to strip it
7259
if ((string = GetString (&lineP)) == NULL)
7260
/* empty or comment line */
7267
string = (unsigned char *)argv[*pArgnum];
7270
/* another option, end of screens names */
7275
if (!(wmGD.screenNames[sNum] = (unsigned char *)
7276
XtRealloc ((char*)wmGD.screenNames[sNum],
7277
1 + strlen((char *)string))))
7279
Warning (((char *)GETMESSAGE(60, 31, "Insufficient memory for screen names")));
7280
ExitWM(WM_ERROR_EXIT_VALUE);
7284
strcpy((char *)wmGD.screenNames[sNum], (char *)string);
7292
* remaining screens (if any) get first name specified
7296
lastLen = 1 + strlen((char *)wmGD.screenNames[0]);
7297
for (; sNum < ScreenCount(DISPLAY); sNum++)
7299
if (!(wmGD.screenNames[sNum] = (unsigned char *)
7300
XtRealloc ((char*)wmGD.screenNames[sNum], lastLen)))
7302
Warning (((char *)GETMESSAGE(60, 32, "Insufficient memory for screen names")));
7303
ExitWM(WM_ERROR_EXIT_VALUE);
7307
strcpy((char *)wmGD.screenNames[sNum],
7308
(char *)wmGD.screenNames[0]);
7313
} /* END OF FUNCTION ParseScreensArgument */
7316
/*************************************<->*************************************
7318
* ProcessMotifBindings ()
7323
* This function is used retrieve the motif input bindings
7324
* and put them into a property on the root window.
7327
*************************************<->***********************************/
7328
void ProcessMotifBindings (void)
7330
char fileName[MAXWMPATH+1];
7331
char *bindings = NULL;
7332
#ifndef MOTIF_ONE_DOT_ONE
7333
char *homeDir = XmeGetHomeDirName();
7339
* Look in the user's home directory for .motifbind
7342
#ifdef MOTIF_ONE_DOT_ONE
7343
GetHomeDirName(fileName);
7345
strcpy (fileName, homeDir);
7347
strncat(fileName, "/", MAXWMPATH-strlen(fileName));
7348
strncat(fileName, MOTIF_BINDINGS_FILE, MAXWMPATH-strlen(fileName));
7350
#ifdef MOTIF_ONE_DOT_ONE
7351
if ((fileP = fopen (fileName, "r")) != NULL)
7353
unsigned char buffer[MBBSIZ];
7355
Boolean first = True;
7356
int mode = PropModeReplace;
7360
* Get the atom for the property.
7362
wmGD.xa_MOTIF_BINDINGS =
7363
XInternAtom (DISPLAY, _XA_MOTIF_BINDINGS, False);
7366
* The property goes on the root window of screen zero
7368
propWindow = RootWindow(DISPLAY, 0);
7371
* Copy file contents to property on root window of screen 0.
7373
while ( (count=fread((char *) &buffer[0], 1, MBBSIZ, fileP)) > 0)
7375
XChangeProperty (DISPLAY, propWindow, wmGD.xa_MOTIF_BINDINGS,
7382
mode = PropModeAppend;
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));
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));
7400
_XmVirtKeysLoadFallbackBindings (DISPLAY, &bindings);
7404
} /* END OF FUNCTION ProcessMotifBindings */
7408
/*************************************<->*************************************
7411
* ParseWmFunctionArg (linePP, ix, wmFunc, ppArg, sClientName)
7416
* Parse the function arguments for a window manager function.
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
7430
* *ppArg = arg to pass to window manager function when invoking.
7431
* Return = true on succes, false on some kind of parse error
7436
* functionTable (window manager function table) is indexed with ix
7437
* to get parsing info.
7439
* This function may malloc memory for the returned arg.
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.
7445
*************************************<->***********************************/
7448
ParseWmFunctionArg (
7449
unsigned char **linePP,
7456
unsigned char *lineP = *linePP;
7457
Boolean bValidArg = True;
7458
unsigned char *str = NULL;
7461
* If this is (possibly) a string argument, put it
7462
* in quotes so that it will be parsed properly.
7464
if ((functionTable[ix].parseProc == ParseWmFuncStrArg) ||
7465
(functionTable[ix].parseProc == ParseWmFuncMaybeStrArg))
7467
if (lineP && *lineP != '"')
7470
* not in quotes, repackage it, escaping the appropriate
7473
str = _DtWmParseMakeQuotedString (lineP);
7482
* Apply the function argument parser.
7484
if ((functionTable[ix].wmFunction != wmFunc) ||
7485
!(*(functionTable [ix].parseProc)) (&lineP, wmFunc, ppArg))
7491
* Add the exec parms if this is an f.action
7493
if ((wmFunc == F_Action) && ppArg && *ppArg)
7495
WmActionArg *pAP = (WmActionArg *) *ppArg;
7499
* allocate more than enough string space to copy
7500
* strings and intervening spaces.
7502
if (sClientName && *sClientName)
7504
/* length of: "name=" + sClientName + NULL */
7505
totLen += 5 + strlen(sClientName) + 1;
7507
if (sTitle && *sTitle)
7509
/* length of: "," + "title=" + sTitle + NULL */
7510
totLen += 1 + 6 + strlen(sTitle) + 1;
7515
pAP->szExecParms = (String) XtMalloc (totLen);
7516
/* start with empty string */
7517
pAP->szExecParms[0] = '\0';
7519
if (sClientName && *sClientName)
7521
strcat (pAP->szExecParms, "name=");
7522
strcat (pAP->szExecParms, sClientName);
7524
if (sTitle && *sTitle)
7526
if (pAP->szExecParms[0] != '\0')
7528
strcat (pAP->szExecParms, ",");
7530
strcat (pAP->szExecParms, "title=");
7531
strcat (pAP->szExecParms, sTitle);
7538
XtFree ((char *) str);
7543
} /* END OF FUNCTION ParseWmFunctionArg */
7546
/*************************************<->*************************************
7548
* SystemCmd (pchCmd)
7553
* This function fiddles with our signal handling and calls the
7554
* system() function to invoke a unix command.
7559
* pchCmd = string with the command we want to exec.
7567
* The system() command is touchy about the SIGCLD behavior. Restore
7568
* the default SIGCLD handler during the time we run system().
7570
*************************************<->***********************************/
7573
SystemCmd (char *pchCmd)
7575
struct sigaction sa;
7576
struct sigaction osa;
7578
(void) sigemptyset(&sa.sa_mask);
7580
sa.sa_handler = SIG_DFL;
7582
(void) sigaction (SIGCLD, &sa, &osa);
7586
(void) sigaction (SIGCLD, &osa, (struct sigaction *) 0);
7591
/*************************************<->*************************************
7593
* DeleteTempConfigFileIfAny ()
7598
* This function deletes the temporary config file used to process
7599
* old dtwmrc syntax.
7613
*************************************<->***********************************/
7616
DeleteTempConfigFileIfAny (void)
7618
char pchCmd[MAXWMPATH+1];
7620
if (pConfigStackTop->tempName)
7622
strcpy (pchCmd, "/bin/rm ");
7623
strcat (pchCmd, pConfigStackTop->tempName);
7625
XtFree ((char *) pConfigStackTop->tempName);
7626
pConfigStackTop->tempName = NULL;
7628
if (pConfigStackTop->cppName)
7630
strcpy (pchCmd, "/bin/rm ");
7631
strcat (pchCmd, pConfigStackTop->cppName);
7633
XtFree ((char *) pConfigStackTop->cppName);
7634
pConfigStackTop->cppName = NULL;
7639
/*************************************<->*************************************
7641
* ParseIncludeSet (pSD, lineP)
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
7659
* linec = (global) line count incremented
7660
* parseP = (global) parse string pointer if cfileP == NULL
7666
*************************************<->***********************************/
7668
static void ParseIncludeSet (WmScreenData *pSD, unsigned char *lineP)
7670
unsigned char *string;
7671
unsigned char *pchName;
7674
* Require leading '{' on the next line.
7677
while ((GetNextLine () != NULL)) /* not EOF nor read error */
7680
ScanWhitespace(&lineP);
7682
if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
7683
/* ignore empty or comment line */
7695
PWarning (((char *)GETMESSAGE(60, 37, "Expected '{'")));
7700
* Found leading "{" or EOF.
7701
* Parse include files until "}" or EOF found.
7703
while ((GetNextLine () != NULL))
7706
if ((*line == '!') || (string = GetString (&lineP)) == NULL)
7707
/* ignore empty or comment lines */
7711
if (*string == '}') /* finished with set. */
7715
pchName = _DtWmParseFilenameExpand (string);
7716
if (pchName && ConfigStackPush (pchName))
7718
ProcessWmFile (pSD, True /* nested */);
7720
XtFree ((char *) pchName);
7729
/*************************************<->*************************************
7731
* ConfigStackInit (pchFileName)
7736
* Initializes the config file processing stack
7740
* pchFileName = name of new file to start parsing
7749
*************************************<->***********************************/
7751
static void ConfigStackInit (char *pchFileName)
7754
pConfigStack = XtNew (ConfigFileStackEntry);
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;
7770
sprintf ((char *)wmGD.tmpBuffer,
7771
(char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"),
7773
Warning ((char *)wmGD.tmpBuffer);
7778
/*************************************<->*************************************
7780
* ConfigStackPush (pchFileName)
7785
* Open an included config file
7789
* pchFileName = name of new file to start parsing
7790
* wmGD.pWmPB = global parse buffer (pickle this)
7794
* wmGD.pWmPB = global parse buffer (new one for new file)
7795
* return = FILE * to open file or NULL
7801
*************************************<->***********************************/
7804
ConfigStackPush (unsigned char *pchFileName)
7806
ConfigFileStackEntry *pEntry;
7807
FILE *pNewFile = NULL;
7809
pEntry = XtNew (ConfigFileStackEntry);
7812
/* save off state of current config file */
7813
pConfigStackTop->offset = ftell (cfileP);
7814
pConfigStackTop->pWmPB = wmGD.pWmPB;
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;
7823
/* set globals for new config file */
7824
wmGD.pWmPB = _DtWmParseNewBuf ();
7825
wmGD.configFile = pEntry->wmgdConfigFile;
7827
/* put new entry onto stack */
7828
pEntry->pIncluder = pConfigStackTop;
7829
pConfigStackTop = pEntry;
7832
pNewFile = cfileP = FopenConfigFile();
7836
/* file open failed! back out */
7842
sprintf ((char *)wmGD.tmpBuffer,
7843
(char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"),
7845
Warning ((char *)wmGD.tmpBuffer);
7853
/*************************************<->*************************************
7864
* pchFileName = name of new file to start parsing
7865
* wmGD.pWmPB = global parse buffer (pickle this)
7869
* wmGD.pWmPB = global parse buffer (new one for new file)
7874
* assumes cfileP is closed already
7876
*************************************<->***********************************/
7878
static void ConfigStackPop (void)
7880
Boolean error = False;
7881
ConfigFileStackEntry *pPrev;
7882
char pchCmd[MAXWMPATH+1];
7884
if (pConfigStackTop != pConfigStack)
7886
pPrev = pConfigStackTop->pIncluder;
7888
_DtWmParseDestroyBuf (wmGD.pWmPB);
7889
if (pConfigStackTop->tempName)
7891
XtFree (pConfigStackTop->tempName);
7893
if (pConfigStackTop->cppName)
7895
strcpy (pchCmd, "/bin/rm ");
7896
strcat (pchCmd, pConfigStackTop->cppName);
7898
XtFree ((char *) pConfigStackTop->cppName);
7899
pConfigStackTop->cppName = NULL;
7901
if (pConfigStackTop->fileName)
7903
XtFree (pConfigStackTop->fileName);
7906
wmGD.pWmPB = pPrev->pWmPB;
7907
wmGD.configFile = pPrev->wmgdConfigFile;
7908
if (pPrev->tempName)
7910
cfileP = fopen (pPrev->tempName, "r");
7912
else if (pPrev->cppName)
7914
cfileP = fopen (pPrev->cppName, "r");
7918
cfileP = fopen (pPrev->fileName, "r");
7922
fseek (cfileP, pPrev->offset, 0);
7926
char msg[MAXWMPATH+1];
7928
sprintf(msg, ((char *)GETMESSAGE(60, 39,
7929
"Could not reopen configuration file %s")),
7934
XtFree ((char *)pConfigStackTop);
7935
pConfigStackTop = pPrev;
7940
/*************************************<->*************************************
7942
* ParseWmFuncActionArg (linePP, wmFunction, pArgs)
7947
* Parses a window manager f.action argument
7952
* linePP = pointer to current line buffer pointer.
7953
* wmFunction = function for which the argument string is intended.
7954
* pArgs = pointer to argument destination.
7959
* linePP = pointer to revised line buffer pointer.
7960
* pArgs = pointer to parsed argument.
7961
* Return = FALSE iff insufficient memory
7967
*************************************<->***********************************/
7969
Boolean ParseWmFuncActionArg (unsigned char **linePP,
7970
WmFunction wmFunction, String *pArgs)
7972
#define WM_ACTION_ARG_INCREMENT 5
7973
#define WM_ACTION_ARG_PAD 256
7974
unsigned char *string;
7979
pAP = XtNew (WmActionArg);
7980
if (pAP && (string = GetString (linePP)) != NULL)
7982
/* Got action name */
7983
pAP->actionName = XtNewString ((char *) string);
7985
/* Get action arguments, if any */
7986
if (pAP->aap = (DtActionArg *)
7987
XtMalloc (WM_ACTION_ARG_INCREMENT * sizeof (DtActionArg)))
7989
iArgSz = WM_ACTION_ARG_INCREMENT;
7992
while ((string = GetString (linePP)) != NULL)
7994
if (pAP->aap[pAP->numArgs].u.file.name = (char *)
7995
XtMalloc(1 + strlen((char *)string)))
7997
pAP->aap[pAP->numArgs].argClass = DtACTION_FILE;
7999
/* format the action argument */
8000
pch = pAP->aap[pAP->numArgs].u.file.name;
8003
* Expand environment variable
8005
if (string[0] == '$')
8007
string = (unsigned char *) getenv ((char *)&string[1]);
8015
* Make sure there's room for the new
8019
XtRealloc (pch, (1+strlen((char *)string)));
8020
pAP->aap[pAP->numArgs].u.file.name = pch;
8024
/* !!! No host name processing is done!!! */
8026
strcpy (pch, (char *)string);
8029
if (pAP->numArgs == iArgSz)
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)));
8038
break; /* out of memory */
8044
break; /* out of memory */
8049
pAP->szExecParms = NULL;
8050
*pArgs = (String) pAP;
8053
/* NULL string argument */
8060
} /* END OF FUNCTION ParseWmFuncActionArg */
8063
#endif /* PANELIST */
8066
/*************************************<->*************************************
8068
* PreprocessConfigFile (pSD)
8073
* This function runs the configuration file through the C
8079
* pSD = ptr to screen data
8088
*************************************<->***********************************/
8091
PreprocessConfigFile (void)
8093
#define CPP_NAME_SIZE ((L_tmpnam)+1)
8094
char pchCmd[MAXWMPATH+1];
8096
if (wmGD.cppCommand && *wmGD.cppCommand)
8099
* Generate a temp file name.
8101
pConfigStackTop->cppName = XtMalloc (CPP_NAME_SIZE * sizeof(char));
8102
if (pConfigStackTop->cppName)
8104
(void) tmpnam (pConfigStackTop->cppName);
8107
* Build up the command line.
8109
strcpy (pchCmd, wmGD.cppCommand);
8110
strcat (pchCmd, " ");
8111
strcat (pchCmd, pConfigStackTop->fileName);
8112
strcat (pchCmd, " ");
8113
strcat (pchCmd, pConfigStackTop->cppName);
8116
* Run the config file through the converter program
8117
* and send the output to a temp file.
8125
/*************************************<->*************************************
8127
* GetNetworkFileName (char *pchFile)
8132
* This function returns a local representation for a network
8138
* pchFile - pointer to file name of form [<host>:]<path>
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.
8148
* returned file name should be freed with XtFree().
8150
*************************************<->***********************************/
8153
GetNetworkFileName (char *pchFile)
8160
char *pchName = NULL;
8163
String sReturn = NULL;
8168
pch = strchr (pchFile, ':');
8173
* Expand special chars and find matching file.
8175
pchTok = (char **)shellscan (pchFile, &count, 0);
8177
if ((count == 1) || (count == 2))
8179
/* one match found */
8180
host_part = pchTok[0];
8184
/* several matches found, pick one */
8185
host_part = pchTok[1];
8192
if (host_part != NULL)
8194
pch = strchr (host_part, ':');
8198
* copy the string so we don't munge data
8201
host_part = sName = XtNewString ((String) host_part);
8202
pch = strchr (sName, ':');
8205
* separate the host and file parts of the
8214
* The colon went away. Hmm...
8216
file_part = host_part;
8221
#ifndef NO_MULTIBYTE
8222
(mblen(file_part, MB_CUR_MAX) == 1) &&
8223
(mblen(file_part+1, MB_CUR_MAX) == 1) &&
8225
(*file_part == '~') &&
8226
(*(file_part+1) == '/'))
8229
* Replace '~' with $HOME
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);
8237
pch += strlen (pch) + 1;
8238
strcpy (pch, homeDir);
8239
strcat (pch, file_part+1);
8248
* shellscan had a problem with the file name.
8249
* just operate on the name as-is.
8250
* temporarily replace ':' with a NULL
8252
host_part = sName = XtNewString ((String) pchFile);
8253
pch = strchr (sName, ':');
8255
host_part = pchFile;
8259
/* convert to canonical host/file name */
8261
tt_host_file_netfile (host_part, file_part);
8262
if (tt_pointer_error (netfile) == TT_OK)
8264
/* convert to local file name equivalent */
8265
pchName = tt_netfile_file (netfile);
8267
if (tt_pointer_error (pchName) == TT_OK)
8269
sReturn = XtNewString ((String) pchName);
8270
tt_free ((char *)pchName);
8277
XtFree ((char *)sName);
8281
if (sReturn == NULL)
8284
#ifndef NO_MULTIBYTE
8285
(mblen(pchFile, MB_CUR_MAX) == 1) &&
8286
(mblen(pchFile+1, MB_CUR_MAX) == 1) &&
8288
(*pchFile == '~') &&
8289
(*(pchFile+1) == '/'))
8292
* Replace '~' with $HOME
8294
homeDir = XmeGetHomeDirName();
8295
len = strlen (homeDir) + strlen (pchFile) + 1;
8296
sReturn = (char *) XtMalloc (len);
8297
strcpy (sReturn, homeDir);
8298
strcat (sReturn, pchFile+1);
8302
sReturn = XtNewString ((String) pchFile);
8308
/**************************** eof ***************************/
8312
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
8313
/*************************************<->*************************************
8315
* SetGreyedContextAndMgtMask (menuItem, wmFunction)
8320
* This function sets up the greyed context and management mask
8321
* for a menu item based on the menu function passed in.
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
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.
8336
*************************************<->***********************************/
8338
Boolean SetGreyedContextAndMgtMask (MenuItem *menuItem,
8339
WmFunction wmFunction)
8343
for (ix = 0; ix < WMFUNCTIONTABLESIZE - 1; ++ix)
8345
if (functionTable[ix].wmFunction == wmFunction)
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;
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;
8365
/*************************************<->*************************************
8367
* MakeSeparatorTemplate ()
8379
*************************************<->***********************************/
8381
MenuItem *MakeSeparatorTemplate (int position)
8385
item = (MenuItem *)XtMalloc(sizeof(MenuItem));
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
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;
8402
item->clientCommandName = (String) NULL;
8403
item->nextMenuItem = (MenuItem *) NULL;
8407
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */