2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC.
31 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 Hewlett-Packard Company
32 * (c) Copyright 1993, 1994 International Business Machines Corp.
33 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
34 * (c) Copyright 1993, 1994 Novell, Inc.
37 * (c) Copyright 1987, 1988 DIGITAL EQUIPMENT CORPORATION */
39 * (c) Copyright 1988 MASSACHUSETTS INSTITUTE OF TECHNOLOGY */
46 #include "WmResNames.h"
47 #include <Dt/UserMsg.h>
48 #include <Dt/Connect.h>
53 #include "WmResource.h"
55 #include <codelibs/shellutils.h> /* shellscan */
57 #include <Xm/VirtKeysP.h>
58 #include <Xm/XmPrivate.h> /* _XmVirtKeysLoadFileBindings,
59 * _XmVirtKeysLoadFallbackBindings */
62 #include <X11/cursorfont.h>
63 #include <X11/keysym.h>
64 #include <X11/Xatom.h>
71 #include <Xm/XmP.h> /* for XmeGetHomeDirName */
74 /* maximum string lengths */
76 #define MAX_KEYSYM_STRLEN 100
77 #define MAX_EVENTTYPE_STRLEN 20
78 #define MAX_MODIFIER_STRLEN 20
79 #define MAX_CONTEXT_STRLEN 20
80 #define MAX_GROUP_STRLEN 20
82 #define min(a,b) ((a)>(b) ? (b) : (a))
84 #define MAXLINE (MAXWMPATH+1)
88 #define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD)
91 * include extern functions
93 #include "WmResParse.h"
94 #include "WmWrkspace.h"
96 #include "WmFunction.h"
101 # ifdef X_NOT_STDC_ENV
104 # define HOME_DT_WMRC "/.dt/dtwmrc"
105 # define LANG_DT_WMRC "/dtwmrc"
106 # define SYS_DT_WMRC CDE_CONFIGURATION_TOP "/sys.dtwmrc"
109 * Global Variables And Tables:
111 static char cfileName[MAXWMPATH+1];
112 #ifndef NO_MESSAGE_CATALOG
113 char * pWarningStringFile;
114 char * pWarningStringLine;
116 char pWarningStringFile[] = "%s: %s on line %d of configuration file %s\n";
117 char pWarningStringLine[] = "%s: %s on line %d of specification string\n";
119 #define cfileP (wmGD.pWmPB->pFile)
120 #define parseP (wmGD.pWmPB->pchNext)
121 #define line (wmGD.pWmPB->pchLine)
122 #define linec (wmGD.pWmPB->lineNumber)
130 static MaskTableEntry modifierStrings[] = {
133 {"ctrl", ControlMask},
134 {"shift", ShiftMask},
151 unsigned int eventType;
152 Boolean (*parseProc)();
153 unsigned int closure;
157 static String GetNetworkFileName (char *pchFile);
158 FILE *FopenConfigFile (void);
159 void SaveMenuAccelerators (WmScreenData *pSD, MenuSpec *newMenuSpec);
160 static void ParseMenuSet (WmScreenData *pSD, unsigned char *lineP);
161 MenuItem *ParseMwmMenuStr (WmScreenData *pSD, unsigned char *menuStr);
162 static MenuItem *ParseMenuItems (WmScreenData *pSD);
163 static Boolean ParseWmLabel (WmScreenData *pSD, MenuItem *menuItem,
164 unsigned char *string);
165 static void ParseWmMnemonic (unsigned char **linePP, MenuItem *menuItem);
166 static Boolean ParseWmAccelerator (unsigned char **linePP, MenuItem *menuItem);
167 int ParseWmFunction (unsigned char **linePP, unsigned int res_spec,
168 WmFunction *pWmFunction);
169 static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction,
171 void FreeMenuItem (MenuItem *menuItem);
172 static Boolean ParseWmFuncGrpArg (unsigned char **linePP,
173 WmFunction wmFunction, GroupArg *pGroup);
174 static Boolean ParseWmFuncNbrArg (unsigned char **linePP,
175 WmFunction wmFunction,
176 unsigned long *pNumber);
177 void ParseButtonStr (WmScreenData *pSD, unsigned char *buttonStr);
178 static void ParseButtonSet (WmScreenData *pSD, unsigned char *lineP);
179 static Boolean ParseContext (unsigned char **linePP, Context *context,
180 Context *subContext);
182 ParseKeyStr (WmScreenData *pSD, unsigned char *keyStr);
183 static void ParseKeySet (WmScreenData *pSD, unsigned char *lineP);
184 Boolean ParseBtnEvent (unsigned char **linePP,
185 unsigned int *eventType,
186 unsigned int *button,
189 Boolean ParseKeyEvent (unsigned char **linePP, unsigned int *eventType,
190 KeyCode *keyCode, unsigned int *state);
191 static Boolean ParseEvent (unsigned char **linePP, EventTableEntry *table,
192 unsigned int *eventType, unsigned int *detail,
193 unsigned int *state, Boolean *fClick);
194 static Boolean ParseModifiers(unsigned char **linePP, unsigned int *state);
195 static Boolean LookupModifier (unsigned char *name, unsigned int *valueP);
196 static Boolean ParseEventType (unsigned char **linePP, EventTableEntry *table,
197 unsigned int *eventType, Cardinal *ix);
198 static Boolean ParseImmed (unsigned char **linePP, unsigned int closure,
199 unsigned int *detail);
200 static Boolean ParseKeySym (unsigned char **linePP, unsigned int closure,
201 unsigned int *detail);
202 static unsigned int StrToNum(unsigned char *str);
203 static unsigned int StrToHex(unsigned char *str);
204 static unsigned int StrToOct(unsigned char *str);
205 void ScanAlphanumeric (unsigned char **linePP);
206 void ScanWhitespace(unsigned char **linePP);
207 void ToLower (char *string);
209 PWarning (char *message);
210 static void ProcessAccelText (unsigned char *startP, unsigned char *endP,
211 unsigned char *destP);
212 void ProcessCommandLine (int argc, char *argv[]);
213 static void ParseScreensArgument (int argc, char *argv[], int *pArgnum,
214 unsigned char *lineP);
215 void ProcessMotifBindings (void);
216 static void ParseIncludeSet (WmScreenData *pSD, unsigned char *lineP);
217 static void ConfigStackInit (char *pchFileName);
218 static FILE *ConfigStackPush (unsigned char *pchFileName);
219 static void ConfigStackPop (void);
220 Boolean ParseWmFuncActionArg (unsigned char **linePP,
221 WmFunction wmFunction, String *pArgs);
222 static void PreprocessConfigFile (void);
224 static EventTableEntry buttonEvents[] = {
226 {"btn1down", ButtonPress, ParseImmed, SELECT_BUTTON, FALSE},
227 {"btn1up", ButtonRelease, ParseImmed, SELECT_BUTTON, FALSE},
228 {"btn1click", ButtonRelease, ParseImmed, SELECT_BUTTON, TRUE},
229 {"btn1click2", ButtonPress, ParseImmed, SELECT_BUTTON, TRUE},
230 {"btn2down", ButtonPress, ParseImmed, DMANIP_BUTTON, FALSE},
231 {"btn2up", ButtonRelease, ParseImmed, DMANIP_BUTTON, FALSE},
232 {"btn2click", ButtonRelease, ParseImmed, DMANIP_BUTTON, TRUE},
233 {"btn2click2", ButtonPress, ParseImmed, DMANIP_BUTTON, TRUE},
234 {"btn3down", ButtonPress, ParseImmed, BMENU_BUTTON, FALSE},
235 {"btn3up", ButtonRelease, ParseImmed, BMENU_BUTTON, FALSE},
236 {"btn3click", ButtonRelease, ParseImmed, BMENU_BUTTON, TRUE},
237 {"btn3click2", ButtonPress, ParseImmed, BMENU_BUTTON, TRUE},
238 {"btn4down", ButtonPress, ParseImmed, Button4, FALSE},
239 {"btn4up", ButtonRelease, ParseImmed, Button4, FALSE},
240 {"btn4click", ButtonRelease, ParseImmed, Button4, TRUE},
241 {"btn4click2", ButtonPress, ParseImmed, Button4, TRUE},
242 {"btn5down", ButtonPress, ParseImmed, Button5, FALSE},
243 {"btn5up", ButtonRelease, ParseImmed, Button5, FALSE},
244 {"btn5click", ButtonRelease, ParseImmed, Button5, TRUE},
245 {"btn5click2", ButtonPress, ParseImmed, Button5, TRUE},
246 { NULL, 0, (Boolean(*)())NULL, 0, FALSE}
250 static EventTableEntry keyEvents[] = {
252 {"key", KeyPress, ParseKeySym, 0, FALSE},
253 { NULL, 0, (Boolean(*)())NULL, 0, FALSE}
256 typedef struct _ConfigFileStackEntry {
260 char *wmgdConfigFile;
262 DtWmpParseBuf *pWmPB;
263 struct _ConfigFileStackEntry *pIncluder;
265 } ConfigFileStackEntry;
267 static ConfigFileStackEntry *pConfigStack = NULL;
268 static ConfigFileStackEntry *pConfigStackTop = NULL;
271 unsigned int buttonModifierMasks[] = {
281 * FUNCTION PARSER TABLE (function names must be in alphabetic order)
286 Context greyedContext;
287 unsigned int resource;
289 WmFunction wmFunction;
290 Boolean (*parseProc)();
291 } FunctionTableEntry;
295 * NOTE: New functions MUST be added in ALPHABETICAL order. A binary search
296 * is used to find the correct function name.
299 FunctionTableEntry functionTable[] = {
304 ParseWmFuncActionArg},
310 {"f.circle_down", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
315 {"f.circle_up", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
320 {"f.create_workspace", 0,
325 {"f.delete_workspace", 0,
335 {"f.focus_color", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
340 {"f.focus_key", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
345 {"f.goto_workspace", 0,
354 ParseWmFuncStrArg}, /* [helpvolume && helptopic] */
359 ParseWmFuncNoArg}, /* for now */
360 {"f.kill", F_CONTEXT_ROOT,
365 {"f.lower", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
369 ParseWmFuncMaybeStrArg},
370 {"f.marquee_selection",
371 F_CONTEXT_WINDOW|F_CONTEXT_ICON|F_SUBCONTEXT_IB_IICON,
376 {"f.maximize", F_CONTEXT_ROOT|F_CONTEXT_MAXIMIZE|
377 F_SUBCONTEXT_IB_WICON,
387 {"f.minimize", F_CONTEXT_ICON|F_CONTEXT_ROOT|F_SUBCONTEXT_IB_IICON,
392 {"f.move", F_CONTEXT_ROOT,
407 {"f.next_workspace", 0,
412 {"f.nop", F_CONTEXT_ROOT|F_CONTEXT_ICON|F_CONTEXT_WINDOW|
413 F_SUBCONTEXT_IB_WICON | F_SUBCONTEXT_IB_IICON,
418 {"f.normalize", F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON,
423 {"f.normalize_and_raise",
424 F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
427 F_Normalize_And_Raise,
428 ParseWmFuncMaybeStrArg},
429 {"f.occupy_all", F_CONTEXT_ICONBOX|F_CONTEXT_ROOT,
432 F_AddToAllWorkspaces,
459 {"f.prev_workspace", 0,
464 {"f.quit_mwm", F_CONTEXT_ICON|F_CONTEXT_WINDOW,
469 {"f.raise", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
473 ParseWmFuncMaybeStrArg},
474 {"f.raise_lower", F_CONTEXT_ROOT |
475 F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
485 {"f.refresh_win", F_CONTEXT_ICON|F_CONTEXT_ROOT,
490 {"f.remove", F_CONTEXT_ROOT,
495 {"f.resize", F_CONTEXT_ICON|F_CONTEXT_ROOT|
496 F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
501 {"f.restart", F_CONTEXT_ICON|F_CONTEXT_WINDOW,
506 {"f.restore", F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON,
511 {"f.restore_and_raise",
512 F_CONTEXT_ROOT|F_CONTEXT_NORMAL,
522 {"f.send_msg", F_CONTEXT_ROOT,
532 {"f.set_behavior", 0,
547 {"f.toggle_frontpanel", 0,
550 F_Toggle_Front_Panel,
560 {"f.workspace_presence",F_CONTEXT_ICON|F_CONTEXT_ROOT|F_CONTEXT_ICONBOX|
561 F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
563 {"f.workspace_presence", F_CONTEXT_ROOT|F_CONTEXT_ICONBOX|
564 F_SUBCONTEXT_IB_WICON,
567 F_Workspace_Presence,
579 * NOTE: New functions MUST be added in ALPHABETICAL order. A binary search
580 * is used to find the correct function name.
583 #define WMFUNCTIONTABLESIZE (sizeof(functionTable)/sizeof(functionTable[0]))
586 * Be sure to update these define, whenever adding/deleting a function.
592 /******************************<->*************************************
594 * void GetFunctionTableValues (int *execIndex, int *nopIndex,
599 * This routine dynamically computes the size of the functionTable[],
600 * and the indices for key functions, such as f.exec, f.action, and
605 * We are setting the values of F_EXEC_INDEX, F_ACTION_INDEX,
606 * and F_NOP_INDEX on a global level. The addresses
607 * for same are passed in.
614 * This routine calls smaller routines for efficiency sake.
616 ******************************<->***********************************/
618 GetFunctionTableValues (int *execIndex, int *nopIndex,
622 GetExecIndex (WMFUNCTIONTABLESIZE, execIndex);
624 GetActionIndex (WMFUNCTIONTABLESIZE, actionIndex);
626 GetNopIndex (WMFUNCTIONTABLESIZE, nopIndex);
628 } /* END OF FUNCTION GetFunctionTableValues */
632 /******************************<->*************************************
649 ******************************<->***********************************/
652 GetExecIndex (int tableSize, int *execIndex)
656 for (i = 0; i < (tableSize); i++)
658 if (!(strcmp ("f.exec", functionTable[i].funcName)))
668 } /* END OF FUNCTION GetExecIndex */
671 /******************************<->*************************************
688 ******************************<->***********************************/
692 GetActionIndex (int tableSize, int *actionIndex)
696 for (i = 0; i < (tableSize); i++)
698 if (!(strcmp ("f.action", functionTable[i].funcName)))
708 } /* END OF FUNCTION GetActionIndex */
712 /******************************<->*************************************
729 ******************************<->***********************************/
731 GetNopIndex (int tableSize, int *nopIndex)
735 for (i = 0; i < (tableSize); i++)
737 if (!(strcmp ("f.nop", functionTable[i].funcName)))
747 } /* END OF FUNCTION GetNopIndex */
752 /*************************************<->*************************************
775 *************************************<->***********************************/
777 WmDtGetHelpArgs(char *args,
778 unsigned char* volume,
779 unsigned char* topic,
782 unsigned char *string;
783 unsigned char *lineP;
787 parseP = (unsigned char*) args;
789 if(GetNextLine () != NULL)
793 if ((string = GetSmartSMString (&lineP)) != NULL)
795 *argsCount = *argsCount + 1;
796 strcpy ((char*)topic, (char*)string);
799 if ((string = GetSmartSMString (&lineP)) != NULL)
801 *argsCount = *argsCount + 1;
802 strcpy ((char*)volume, (char *)string);
806 } /* END OF FUNCTION WmDtGetHelpArgs */
812 /******************************<->*************************************
815 * ParseDtSessionHints (pSD, property)
820 * This function parses a DtSessionHints string and returns a list of
821 * DtSessionItems array. The string should have the syntax:
828 * line = (global) line buffer
829 * pSD->rootWindow = default root window of display
841 *************************************<->***********************************/
844 ParseDtSessionHints (WmScreenData *pSD, unsigned char *property)
851 ParseSessionItems (pSD);
853 } /* END OF FUNCTION ParseDtSessionHints */
856 /*************************************<->*************************************
858 * FindDtSessionMatch(commandArgc, commandArgv, pCD, pSD, pWorkSpaceList,
863 * Try to find a match for this client in the session hints.
864 * Set up client-session data.
869 * commandArgc - argument count
870 * commandArgv - WM_COMMAND argument vector
871 * pCD - pointer to client data
872 * pSD - pointer to screen data
873 * pWorkspaceList - pointer to a list of workspaces (to be returned)
874 * clientMachine - string for -host option in session hints
878 * *pCD - client data (may be modified)
879 * FindDtSessionMatch - returns True if a match for this client
880 * was found in the session hints.
881 * *pWorkspaceList - list of workspaces this client should be put
882 * into. (needs to be freed)
887 * Various pieces of client state (in pCD) are reset when a match
890 * The caller must free *pWorkspaceList when done.
892 *************************************<->***********************************/
893 Boolean FindDtSessionMatch(int commandArgc, char **commandArgv,
894 ClientData *pCD, WmScreenData *pSD,
895 char **pWorkSpaceList, char *clientMachine)
901 SessionGeom *sessionGeom;
904 for (count = 0; count < pSD->totalSessionItems; count++)
906 if (!pSD->pDtSessionItems[count].processed &&
907 pSD->pDtSessionItems[count].commandArgc == commandArgc)
909 if ((clientMachine) &&
910 (pSD->pDtSessionItems[count].clientMachine) &&
911 (strcmp(clientMachine,
912 pSD->pDtSessionItems[count].clientMachine)))
915 * This item has clientMachine string but the
916 * clientMachine does not match.
920 for (argNum = 0; argNum < commandArgc ; argNum++)
922 if(strcmp(commandArgv[argNum],
923 pSD->pDtSessionItems[count].commandArgv[argNum]))
927 * One mismatch and we quit looking at this item.
928 * Decrement argNum so a mismatch on the last item
929 * will not look like a match below when comparing
930 * argNum == commandArgc
936 if (argNum == commandArgc)
939 * Made it through all strings so this is a match
942 pSD->pDtSessionItems[count].processed = True;
943 pSD->remainingSessionItems --;
944 pCD->clientFlags |= SM_LAUNCHED;
947 * Free strings malloc'd for commandArgv for this item
950 for (relCount = 0; relCount < commandArgc; relCount++)
952 XtFree(pSD->pDtSessionItems[count].commandArgv[relCount]);
954 XtFree((char *)pSD->pDtSessionItems[count].commandArgv);
956 if(pSD->pDtSessionItems[count].clientState)
959 pSD->pDtSessionItems[count].clientState;
960 pCD->clientFlags |= SM_CLIENT_STATE;
963 if(pSD->pDtSessionItems[count].sessionGeom)
965 sessionGeom = pSD->pDtSessionItems[count].sessionGeom;
966 if (sessionGeom->flags & XValue)
968 pCD->clientX = sessionGeom->clientX;
969 pCD->clientFlags |= SM_X;
971 if (sessionGeom->flags & YValue)
973 pCD->clientY = sessionGeom->clientY;
974 pCD->clientFlags |= SM_Y;
976 if (sessionGeom->flags & WidthValue)
978 pCD->clientWidth = sessionGeom->clientWidth;
979 pCD->clientFlags |= SM_WIDTH;
981 if (sessionGeom->flags & HeightValue)
983 pCD->clientHeight = sessionGeom->clientHeight;
984 pCD->clientFlags |= SM_HEIGHT;
988 * Free SessionGeom malloc'd space for this item
991 XtFree((char *)pSD->pDtSessionItems[count].sessionGeom);
994 if(pSD->pDtSessionItems[count].clientMachine)
997 * Free clientMachine malloc'd space for this item
1001 pSD->pDtSessionItems[count].clientMachine);
1002 pSD->pDtSessionItems[count].clientMachine = NULL;
1006 if(pSD->pDtSessionItems[count].workspaces)
1009 * The caller is responsible for freeing this
1012 *pWorkSpaceList = pSD->pDtSessionItems[count].workspaces;
1016 if(pSD->remainingSessionItems == 0)
1019 * Free the whole pSD->pDtSessionHints structure
1021 XtFree((char *)pSD->pDtSessionItems);
1027 } /* not processed and argc's are the same */
1033 } /* END OF FUNCTION FindDtSessionMatch */
1039 /*************************************<->*************************************
1042 * ParseSessionItems (pSD)
1047 * Parse session items
1052 * pSD = pointer to screen data
1053 * cfileP = (global) file pointer to NULL
1054 * line = (global) line buffer
1055 * linec = (global) line count
1056 * parseP = (global) parse string pointer if cfileP == NULL
1057 * pSD->rootWindow = default root window of display
1062 * linec = (global) line count incremented
1063 * parseP = (global) parse string pointer if cfileP == NULL
1070 *************************************<->***********************************/
1073 ParseSessionItems (WmScreenData *pSD)
1075 unsigned char *string;
1076 unsigned char *lineP;
1081 * Parse property string
1086 if(GetNextLine () != NULL)
1088 pSD->totalSessionItems = atoi((char *)line);
1089 pSD->remainingSessionItems = pSD->totalSessionItems;
1093 if((pSD->totalSessionItems < 1) ||
1094 !GetSessionHintsInfo(pSD, pSD->totalSessionItems))
1097 * No items or couldn't allocate space
1104 while ((count < pSD->totalSessionItems) && (GetNextLine () != NULL))
1108 while ((string = GetSmartSMString (&lineP)) != NULL)
1110 if (!strcmp((char *)string, "-geometry"))
1113 * Parse geometry if it is present
1115 string = GetSmartSMString(&lineP);
1116 ParseSessionGeometry (pSD, count, string);
1119 else if (!strcmp((char *)string, "-state"))
1122 * Parse the state if it is present
1124 string = GetSmartSMString(&lineP);
1125 ParseSessionClientState (pSD, count, string);
1128 else if (!strcmp((char *)string, "-workspaces"))
1131 * Parse the workspaces string if it is present
1133 string = GetSmartSMString(&lineP);
1134 ParseSessionWorkspaces (pSD, count, string);
1137 else if (!strcmp((char *)string, "-cmd"))
1140 * Parse the command string if it is present
1142 string = GetSmartSMString(&lineP);
1143 ParseSessionCommand (pSD, count, &string);
1146 else if (!strcmp((char *)string, "-host"))
1149 * Parse the host string if it is present
1151 string = GetSmartSMString(&lineP);
1152 ParseSessionHost (pSD, count, string);
1155 } /* while GetSmartSMString */
1159 } /* while GetNextLine */
1163 } /* END OF FUNCTION ParseSessionItems */
1167 /*************************************<->*************************************
1169 * ParseSessionClientState (pSD, count, string);
1180 *************************************<->***********************************/
1181 void ParseSessionClientState (WmScreenData *pSD, int count,
1182 unsigned char *string)
1188 if(!strcmp((char *)string, "NormalState"))
1190 pSD->pDtSessionItems[count].clientState = NORMAL_STATE;
1192 else if(!strcmp((char *)string, "IconicState"))
1194 pSD->pDtSessionItems[count].clientState = MINIMIZED_STATE;
1198 } /* END OF FUNCTION ParseSessionClientState */
1201 /*************************************<->*************************************
1203 * ParseSessionGeometry (pSD, count, string)
1214 *************************************<->***********************************/
1215 void ParseSessionGeometry (WmScreenData *pSD, int count,
1216 unsigned char *string)
1219 SessionGeom *pTmpSessionGeom;
1221 int X, Y, width, height;
1222 X = Y = width = height = 0;
1228 mask = XParseGeometry((char *)string, &X, &Y, (unsigned int *)&width,
1229 (unsigned int *)&height);
1233 * Allocate space for the geometry structure
1236 if ((pTmpSessionGeom =
1237 (SessionGeom *)XtMalloc (sizeof (SessionGeom))) == NULL)
1239 Warning (((char *)GETMESSAGE(60, 1, "Insufficient memory for session geometry item")));
1244 pTmpSessionGeom->flags = mask;
1245 pTmpSessionGeom->clientX = X;
1246 pTmpSessionGeom->clientY = Y;
1247 pTmpSessionGeom->clientWidth = width;
1248 pTmpSessionGeom->clientHeight = height;
1250 pSD->pDtSessionItems[count].sessionGeom = pTmpSessionGeom;
1253 } /* END OF FUNCTION ParseSessionGeometry */
1256 /*************************************<->*************************************
1259 * ParseSessionWorkspaces (pSD, count, string)
1270 *************************************<->***********************************/
1271 void ParseSessionWorkspaces (WmScreenData *pSD, int count,
1272 unsigned char *string)
1277 * Allocate space for the workspaces string
1280 if ((pSD->pDtSessionItems[count].workspaces =
1281 (String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) == NULL)
1283 Warning (((char *)GETMESSAGE(60, 2, "Insufficient memory for workspaces list in session item")));
1288 strcpy(pSD->pDtSessionItems[count].workspaces, (char *)string);
1290 } /* END OF FUNCTION ParseSessionWorkspaces */
1294 /*************************************<->*************************************
1297 * ParseSessionCommand (pSD, count, string)
1308 *************************************<->***********************************/
1309 void ParseSessionCommand (WmScreenData *pSD, int count,
1310 unsigned char **commandString)
1314 unsigned char **argv;
1318 unsigned char *string;
1320 argv = (unsigned char **) XtMalloc (ARG_AMT * sizeof(char *));
1321 iSizeArgv = ARG_AMT;
1323 while ((string = GetSmartSMString (commandString)) != NULL)
1326 * Get pointers to strings in command line and count them
1328 argv[argc] = string;
1331 if (argc >= iSizeArgv)
1333 iSizeArgv += ARG_AMT;
1334 argv = (unsigned char **)
1335 XtRealloc ((char *)argv, (iSizeArgv * sizeof(char *)));
1338 if ((pSD->pDtSessionItems[count].commandArgv =
1339 (char **)XtMalloc ((argc) * sizeof(char * ))) == NULL)
1342 * Allocate space for saved argv
1345 Warning (((char *)GETMESSAGE(60, 3, "Insufficient memory for commandArgv array")));
1349 pSD->pDtSessionItems[count].commandArgc = argc;
1350 for (xindex = 0; xindex < argc ; xindex++)
1352 if ((pSD->pDtSessionItems[count].commandArgv[xindex] =
1354 ((unsigned int) (strlen((char *)argv[xindex]) + 1))) == NULL)
1357 * Allocate space for the next command segment.
1359 Warning (((char *)GETMESSAGE(60, 4, "Insufficient memory for commandArgv item")));
1363 strcpy(pSD->pDtSessionItems[count].commandArgv[xindex],
1364 (char *)argv[xindex]);
1369 XtFree ((char *) argv);
1371 } /* END OF FUNCTION ParseSessionCommand */
1375 /*************************************<->*************************************
1378 * ParseSessionHost (pSD, count, string)
1389 *************************************<->***********************************/
1390 void ParseSessionHost (WmScreenData *pSD, int count,
1391 unsigned char *string)
1396 * Allocate space for the workspaces string
1399 if ((pSD->pDtSessionItems[count].clientMachine =
1400 (String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) ==
1403 Warning (((char *)GETMESSAGE(60, 38,
1404 "Insufficient memory for host name in session item")));
1408 strcpy(pSD->pDtSessionItems[count].clientMachine, (char *)string);
1410 } /* END OF FUNCTION ParseSessionHost */
1414 /*************************************<->*************************************
1416 * GetSessionHintsInfo (pSD, numItems)
1427 *************************************<->***********************************/
1428 Boolean GetSessionHintsInfo (WmScreenData *pSD, long numItems)
1432 if ((pSD->pDtSessionItems =
1433 (DtSessionItem *)XtMalloc (numItems * sizeof (DtSessionItem)))
1436 Warning (((char *)GETMESSAGE(60, 5, "Insufficient memory for Dt Session Hints")));
1440 memset ((char *)pSD->pDtSessionItems, 0,
1441 numItems * sizeof (DtSessionItem));
1446 } /* END OF FUNCTION GetSessionHintsInfo */
1451 /*************************************<->*************************************
1453 * PeekAhead (currentChar, currentLev)
1458 * Returns a new level value if this is a new nesting level of quoted string
1459 * Otherwise it returns a zero
1464 * currentChar = current position in the string
1465 * currentLev = current level of nesting
1470 * Returns either a new level of nesting or zero if the character is copied in
1476 *************************************<->***********************************/
1477 unsigned int PeekAhead(unsigned char *currentChar,
1478 unsigned int currentLev)
1482 Boolean done = False;
1483 unsigned int tmpLev = 1;
1486 while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) &&
1487 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
1492 if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
1493 ((*currentChar == '"') || (*currentChar == '\\')))
1496 if(*currentChar == '"')
1508 * Figure out if this is truly a new level of nesting - else ignore it
1509 * This section probably could do some error checking and return -1
1510 * If so, change type of routine from unsigned int to int
1520 } /* END OF FUNCTION PeekAhead */
1523 /*************************************<->*************************************
1525 * SyncModifierStrings (fileName)
1529 * This function updates modifierStrings table so that Mwm uses the correct
1530 * modifier to keysym mapping. Specifically, fix up the Alt and Meta bindings.
1543 *************************************<->***********************************/
1544 void SyncModifierStrings(void)
1546 XModifierKeymap *map;
1549 map = XGetModifierMapping (DISPLAY);
1551 for (i = 0; i < 8; i++)
1553 for (j = 0; j < map->max_keypermod; j++)
1555 if (map->modifiermap[k])
1557 KeySym ks = XKeycodeToKeysym(DISPLAY, map->modifiermap[k], 0);
1558 char *nm = XKeysymToString(ks);
1560 /* Compare, ignoring the trailing '_L' or '_R' in keysym */
1561 if (nm && !strncmp("Alt", nm, 3))
1563 modifierStrings[ALT_INDEX].mask = (1<<i);
1565 else if (nm && !strncmp("Meta", nm, 4))
1567 modifierStrings[META_INDEX].mask = (1<<i);
1574 XFreeModifiermap(map);
1579 /*************************************<->*************************************
1586 * This function reads the mwm resource description file and processes the
1587 * resources that are described.
1592 * wmGD.bitmapDirectory = bitmapDirectory resource value
1593 * pSD->buttonBindings = buttonBindings resource value
1594 * wmGD.configFile = configuration file resource value
1595 * pSD->keyBindings = keyBindings resource value
1596 * wmGD.rootWindow = default root window of display
1597 * HOME = environment variable for home directory
1598 * functionTable = window manager function parse table
1603 * wmGD.buttonSpecs = list of button binding specifications
1604 * wmGD.keySpecs = list of key binding specification
1605 * wmGD.menuSpecs = list of menu specifications
1606 * *wmGD.acceleratorMenuSpecs = initialized array of (MenuSpec *)
1607 * wmGD.acceleratorMenuCount = 0
1612 * If there are more than MAXLINE characters on a line the excess characters
1615 *************************************<->***********************************/
1616 #define MENU_SPEC "menu"
1617 #define BUTTON_SPEC "buttons"
1618 #define KEY_SPEC "keys"
1619 #define FRONT_PANEL_SPEC DTWM_FP_PANEL_OLD
1620 #define DROP_EFFECTS_SPEC DTWM_FP_DROP_EFFECTS
1621 #define PANEL_SPEC DTWM_FP_PANEL
1622 #define BOX_SPEC DTWM_FP_BOX
1623 #define CONTROL_SPEC DTWM_FP_CONTROL
1624 #define INCLUDE_SPEC DTWM_FP_INCLUDE
1625 #define ANIMATION_SPEC DTWM_FP_ANIMATION
1626 #define SWITCH_SPEC DTWM_FP_SWITCH
1628 void ProcessWmFile (WmScreenData *pSD, Boolean bNested)
1631 unsigned char *lineP;
1632 unsigned char *string;
1640 * Initialize global data values that are set based on data in
1641 * the mwm resource description file.
1644 pSD->buttonSpecs = NULL;
1645 pSD->keySpecs = NULL;
1646 pSD->menuSpecs = NULL;
1648 /**** hhhhhhhhhhhh ******/
1649 GetFunctionTableValues (&F_EXEC_INDEX, &F_NOP_INDEX, &F_ACTION_INDEX);
1651 * Find and parse the default system menu string, if it exists.
1656 if (((parseP = (unsigned char *) builtinSystemMenu) != NULL) &&
1657 (GetNextLine () != NULL))
1660 ParseMenuSet (pSD, lineP);
1664 if (((parseP = (unsigned char *) builtinRootMenu) != NULL) &&
1665 (GetNextLine () != NULL))
1668 ParseMenuSet (pSD, lineP);
1670 if (wmGD.useFrontPanel && !wmGD.dtSD &&
1671 (XDefaultScreen (wmGD.display) == pSD->screen))
1673 wmGD.dtSD = pSD; /* only one per display */
1677 * Find and associate a stream with the window manager resource
1681 if ((cfileP = FopenConfigFile ()) == NULL)
1683 if (!wmGD.useStandardBehavior)
1684 Warning (((char *)GETMESSAGE(60, 6, "Cannot open configuration file")));
1688 } /* end if (!bNested) */
1690 * Parse the information in the configuration file.
1691 * If there are more than MAXLINE characters on a line the excess are
1696 while ((GetNextLine () != NULL)) /* not EOF nor read error */
1699 if ((*line == '!') || (string = GetString (&lineP)) == NULL)
1700 /* empty or comment line */
1705 ToLower ((char *)string);
1706 if (!strcmp ((char *)string, MENU_SPEC))
1708 ParseMenuSet (pSD, lineP);
1710 else if (!strcmp ((char *) string, BUTTON_SPEC))
1712 ParseButtonSet (pSD, lineP);
1714 else if (!strcmp ((char *) string, KEY_SPEC))
1716 ParseKeySet (pSD, lineP);
1718 else if (!strcmp ((char *)string, INCLUDE_SPEC))
1720 ParseIncludeSet (pSD, lineP);
1727 * Create and initialize the pSD->acceleratorMenuSpecs array.
1728 * This assumes we create pointers to MenuSpecs within ProcessWmFile().
1729 * Set pSD->acceleratorMenuCount to 0.
1732 /* count the number of menu specifications */
1734 menuSpec = pSD->menuSpecs;
1738 menuSpec = menuSpec->nextMenuSpec;
1741 /* allocate the array and initialize to zeros */
1742 pSD->acceleratorMenuSpecs = NULL;
1745 pSD->acceleratorMenuSpecs =
1746 (MenuSpec **) XtCalloc (n, sizeof (MenuSpec *));
1747 if (pSD->acceleratorMenuSpecs == NULL)
1749 Warning (((char *)GETMESSAGE(60, 7, "Insufficient memory for menu accelerators")));
1752 pSD->acceleratorMenuCount = 0;
1753 } /* END OF FUNCTION ProcessWmFile */
1755 /**** This function stolen from Xt/Intrinsic.c ****/
1756 /* The implementation of this routine is operating system dependent */
1758 static char *ExtractLocaleName(String lang)
1761 #ifdef hpux /* hpux-specific parsing of the locale string */
1762 #define MAXLOCALE 64 /* buffer size of locale name */
1767 static char buf[MAXLOCALE];
1769 /* If lang has a substring ":<category>;", extract <category>
1770 * from the first such occurrence as the locale name.
1774 if (start = strchr (lang, ':')) {
1776 if (end = strchr (start, ';')) {
1778 strncpy(buf, start, len);
1779 *(buf + len) = '\0';
1788 #define RC_CONFIG_SUBDIR "/config/"
1789 #define RC_DEFAULT_CONFIG_SUBDIR "/config/C"
1791 /*************************************<->*************************************
1793 * FopenConfigFile ()
1798 * This function searches for, opens, and associates a stream with the mwm
1799 * resource description file,
1804 * wmGD.configFile = configuration file resource value.
1805 * HOME = environment variable for home directory
1810 * Return = If successful, a pointer to the FILE structure associated with
1811 * the configuration file. Otherwise, NULL.
1818 *************************************<->***********************************/
1819 FILE *FopenConfigFile (void)
1825 char *homeDir = XmeGetHomeDirName();
1826 Boolean stackPushed;
1829 * Get the LANG environment variable
1830 * make copy since another call to getenv will blast the value.
1832 LANGp = setlocale(LC_CTYPE, NULL);
1835 * setlocale not guaranteed to return $LANG -- extract
1838 LANGp = ExtractLocaleName (LANGp);
1840 if ((LANGp == NULL) || (strlen(LANGp) == 0))
1846 if ((LANG = (char *) XtMalloc(strlen(LANGp) +1)) == NULL)
1848 PWarning (((char *)GETMESSAGE(60, 41, "Insufficient memory to get LANG environment variable.")));
1852 strcpy(LANG, LANGp);
1857 * To get a name for the file first look at the value of the configFile
1858 * resource. Interpret "~/.." as relative to the user's home directory.
1859 * Use the LANG variable if set and .mwmrc is in $HOME/$LANG/.mwmrc
1862 if (pConfigStackTop && pConfigStackTop->tempName)
1864 fileP = fopen (pConfigStackTop->tempName, "r");
1867 stackPushed = (pConfigStackTop && (pConfigStackTop != pConfigStack));
1869 cfileName[0] = '\0';
1871 if ((wmGD.configFile != NULL) && (wmGD.configFile[0] != '\0'))
1872 /* pointer to nonNULL string */
1874 if ((wmGD.configFile[0] == '~') && (wmGD.configFile[1] == '/'))
1875 /* handle "~/..." */
1877 strcpy (cfileName, homeDir);
1880 strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
1881 strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
1883 strncat(cfileName, &(wmGD.configFile[1]), MAXWMPATH-strlen(cfileName));
1884 if ((fileP = fopen (cfileName, "r")) != NULL)
1894 * Just try $HOME/.mwmrc
1896 strcpy (cfileName, homeDir);
1897 strncat(cfileName, &(wmGD.configFile[1]),
1898 MAXWMPATH-strlen(cfileName));
1899 if ((fileP = fopen (cfileName, "r")) != NULL)
1911 /* relative to current directory or absolute */
1915 pch = (char *) GetNetworkFileName (wmGD.configFile);
1917 if ((fileP = fopen (pch, "r")) != NULL)
1919 strncpy (cfileName, pch, MAXWMPATH);
1923 if ((fileP == NULL) && !stackPushed)
1925 if ((fileP = fopen (wmGD.configFile, "r")) != NULL)
1934 else if ((fileP == NULL) && stackPushed)
1936 strcpy (cfileName, wmGD.configFile);
1941 if ((fileP == NULL) && !stackPushed)
1945 * The configFile resource didn't do it for us.
1946 * First try HOME_MWMRC, then try SYS_MWMRC .
1949 #define HOME_MWMRC "/.mwmrc"
1950 #define SLASH_MWMRC "/system.mwmrc"
1952 strcpy (cfileName, homeDir);
1958 * Looking for $HOME/$LANG/.mwmrc
1959 * --or--if $LANG is NULL
1960 * Looking for $HOME/.mwmrc
1965 strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
1966 strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
1968 strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
1974 * Looking for $HOME/.dt/$LANG/dtwmrc
1976 * --or--if $LANG is NULL--
1978 * Looking for $HOME/.dt/dtwmrc
1981 strncat(cfileName, "/.dt/", MAXWMPATH-strlen(cfileName));
1985 strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
1987 strncat(cfileName, LANG_DT_WMRC, MAXWMPATH - strlen(cfileName));
1989 if ((fileP = fopen (cfileName, "r")) != NULL)
1999 * Just try $HOME/.mwmrc
2001 strcpy (cfileName, homeDir);
2005 * Just try $HOME/.mwmrc
2007 strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
2012 * Just try $HOME/.dt/dtwmrc
2014 strncat(cfileName, HOME_DT_WMRC, MAXWMPATH - strlen(cfileName));
2016 if ((fileP = fopen (cfileName, "r")) != NULL)
2026 #define DTLIBDIR CDE_INSTALLATION_TOP
2027 #define DTADMINDIR CDE_CONFIGURATION_TOP
2028 #define SLASH_DT_WMRC "/sys.dtwmrc"
2030 if ((fileP == NULL) && !stackPushed)
2033 * No home-based config file. Try the admin directory.
2035 strcpy(cfileName, DTADMINDIR);
2036 strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName));
2037 strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
2038 strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
2040 if (((fileP = fopen (cfileName, "r")) == NULL) && LANG && *LANG)
2042 /* Try it with no LANG */
2043 strcpy(cfileName, DTADMINDIR);
2044 strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName));
2045 strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
2048 if ((fileP = fopen (cfileName, "r")) != NULL)
2055 if ((fileP == NULL) && !stackPushed)
2059 #define LIBDIR "/usr/lib/X11"
2065 strcpy(cfileName, LIBDIR);
2066 strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
2067 strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
2068 strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
2072 strcpy(cfileName, DTLIBDIR);
2073 strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName));
2074 strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
2075 strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
2077 if ((fileP = fopen (cfileName, "r")) != NULL)
2084 if ((fileP == NULL) && !stackPushed)
2088 strcpy(cfileName, LIBDIR);
2089 strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
2090 fileP = fopen (cfileName, "r");
2094 strcpy(cfileName, DTLIBDIR);
2095 strncat(cfileName, RC_DEFAULT_CONFIG_SUBDIR,
2096 MAXWMPATH - strlen(cfileName));
2097 strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName));
2098 fileP = fopen (cfileName, "r");
2108 * handle "<host>:<path>" form of file name
2110 pch = (char *) GetNetworkFileName (cfileName);
2111 if ((fileP = fopen (cfileName, "r")) != NULL)
2113 strncpy (cfileName, pch, MAXWMPATH);
2118 * Either not "<host>:<path>" form or there was a
2119 * problem up above. This is the last attempt to
2124 fileP = fopen (cfileName, "r");
2130 ConfigStackInit (cfileName);
2133 if (wmGD.cppCommand && *wmGD.cppCommand)
2136 * Run the file through the C-preprocessor
2138 PreprocessConfigFile ();
2139 if (pConfigStackTop && pConfigStackTop->cppName)
2144 /* open the result */
2145 fileP = fopen (pConfigStackTop->cppName, "r");
2156 } /* END OF FUNCTION FopenConfigFile */
2159 /*************************************<->*************************************
2161 * SaveMenuAccelerators (pSD, newMenuSpec)
2166 * This function saves the MenuSpec pointer in pSD->acceleratorMenuSpecs.
2171 * newMenuSpec = pointer to MenuSpec to be saved.
2172 * pSD->acceleratorMenuSpecs =
2173 * pSD->acceleratorMenuCount =
2178 * pSD->acceleratorMenuSpecs = possibly updated
2179 * pSD->acceleratorMenuCount = possibly updated
2184 * We assume only MenuSpecs created within ProcessWmFile() are to be saved.
2185 * Otherwise, we may cause override the limits of pSD->acceleratorMenuSpecs.
2187 *************************************<->***********************************/
2189 void SaveMenuAccelerators (WmScreenData *pSD, MenuSpec *newMenuSpec)
2191 MenuSpec **pMenuSpec;
2193 pMenuSpec = pSD->acceleratorMenuSpecs;
2195 if (pMenuSpec == NULL)
2198 while ((*pMenuSpec != NULL) && (*pMenuSpec != newMenuSpec))
2203 if (*pMenuSpec == NULL)
2205 *pMenuSpec = newMenuSpec;
2206 pSD->acceleratorMenuCount++;
2209 } /* END OF FUNCTION SaveMenuAccelerators */
2212 /*************************************<->*************************************
2214 * ParseMenuSet (pSD, lineP)
2219 * Menu pane specification found. Parse the following syntax:
2222 * Menu menu_pane_name
2224 * label [mnemonic] [accelerator] function
2225 * label [mnemonic] [accelerator] function
2227 * label [mnemonic] [accelerator] function
2233 * cfileP = (global) file pointer to fopened configuration file or NULL
2234 * lineP = pointer to menu name in line buffer
2235 * line = (global) line buffer
2236 * linec = (global) line count
2237 * parseP = (global) parse string pointer if cfileP == NULL
2238 * pSD->rootWindow = default root window of display
2239 * wmGD.bitmapDirectory = bitmapDirectory resource value
2240 * HOME = environment variable for home directory
2245 * linec = (global) line count incremented
2246 * parseP = (global) parse string pointer if cfileP == NULL
2247 * pSD->menuSpecs = list of menu specifications
2252 * Skips unnamed menu specifications.
2253 * This means custom menu specifications can be distinguished by NULL name.
2255 *************************************<->***********************************/
2257 static void ParseMenuSet (WmScreenData *pSD, unsigned char *lineP)
2259 unsigned char *string;
2263 * If menu name is NULL then skip this pane specification.
2266 if ((string = GetString (&lineP)) == NULL)
2272 * Allocate space for the menu specification structure.
2275 if ((menuSpec = (MenuSpec *)XtMalloc (sizeof (MenuSpec))) == NULL)
2277 PWarning (((char *)GETMESSAGE(60, 9, "Insufficient memory for menu")));
2280 menuSpec->currentContext = 0;
2281 menuSpec->menuWidget = NULL;
2282 menuSpec->whichButton = SELECT_BUTTON; /* Button1 selection default */
2283 menuSpec->menuItems = NULL;
2284 menuSpec->accelContext = 0;
2285 menuSpec->accelKeySpecs = NULL;
2286 menuSpec->nextMenuSpec = NULL;
2289 * Allocate and fill space for the menu name.
2292 if ((menuSpec->name =
2293 (String)XtMalloc ((unsigned int) (strlen ((char *)string) + 1)))
2296 PWarning (((char *)GETMESSAGE(60, 10, "Insufficient memory for menu")));
2297 XtFree ((char *)menuSpec);
2300 strcpy (menuSpec->name, (char *)string);
2303 * Add the empty structure to the head of the menu specification list.
2306 menuSpec->nextMenuSpec = pSD->menuSpecs;
2307 pSD->menuSpecs = menuSpec;
2310 * Require leading '{' on the next line.
2313 while ((GetNextLine () != NULL)) /* not EOF nor read error */
2316 ScanWhitespace(&lineP);
2318 if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
2319 /* ignore empty or comment line */
2331 PWarning (((char *)GETMESSAGE(60, 11, "Expected '{' after menu name")));
2336 * Found leading "{" or EOF.
2337 * Parse menu item specifications until "}" or EOF found.
2340 menuSpec->menuItems = PARSE_MENU_ITEMS (pSD, menuSpec);
2342 } /* END OF FUNCTION ParseMenuSet */
2345 /*************************************<->*************************************
2348 * ParseMwmMenuStr (pSD, menuStr)
2353 * This function parses a WMW_MENU string and returns a list of
2354 * MenuItems structures. The string should have the syntax:
2356 * label [mnemonic] [accelerator] function
2357 * label [mnemonic] [accelerator] function
2359 * label [mnemonic] [accelerator] function
2364 * line = (global) line buffer
2365 * pSD->rootWindow = default root window of display
2366 * wmGD.bitmapDirectory = bitmapDirectory resource value
2367 * HOME = environment variable for home directory
2368 * functionTable = window manager function parse table
2373 * Return = list of MenuItem structures or NULL
2380 *************************************<->***********************************/
2382 MenuItem *ParseMwmMenuStr (WmScreenData *pSD, unsigned char *menuStr)
2389 return (PARSE_MENU_ITEMS (pSD, NULL));
2391 } /* END OF FUNCTION ParseMwmMenuStr */
2394 /*************************************<->*************************************
2397 * ParseMenuItems (pSD, menuSpec)
2402 * Parse menu item specifications:
2404 * label [mnemonic] [accelerator] function
2405 * label [mnemonic] [accelerator] function
2407 * label [mnemonic] [accelerator] function
2413 * pSD = pointer to screen data
2414 * cfileP = (global) file pointer to fopened configuration file or NULL
2415 * line = (global) line buffer
2416 * linec = (global) line count
2417 * parseP = (global) parse string pointer if cfileP == NULL
2418 * pSD->rootWindow = default root window of display
2419 * wmGD.bitmapDirectory = bitmapDirectory resource value
2420 * HOME = environment variable for home directory
2425 * linec = (global) line count incremented
2426 * parseP = (global) parse string pointer if cfileP == NULL
2427 * Return = list of MenuItem structures or NULL
2434 *************************************<->***********************************/
2436 static MenuItem *ParseMenuItems (WmScreenData *pSD)
2438 unsigned char *string;
2439 unsigned char *lineP;
2440 MenuItem *firstMenuItem;
2441 MenuItem *lastMenuItem;
2446 * Parse "label [mnemonic] [accelerator] function" or
2447 * "<client command>[.<client command>]*"
2448 * lines until "}" or EOF found.
2451 firstMenuItem = lastMenuItem = NULL;
2452 while ((GetNextLine () != NULL))
2455 if ((*line == '!') || (*line == '#') || (string = GetString (&lineP)) == NULL)
2456 /* ignore empty or comment lines */
2460 if (*string == '}') /* finished with menu set. */
2466 * Allocate space for the menu item structure.
2469 if ((menuItem = (MenuItem *)XtMalloc (sizeof (MenuItem))) == NULL)
2471 PWarning (((char *)GETMESSAGE(60, 12, "Insufficient memory for menu item")));
2474 menuItem->nextMenuItem = NULL;
2475 menuItem->wmFunction = (WmFunction)NULL;
2476 menuItem->wmFuncArgs = NULL;
2480 * Parse the menu item label.
2482 if (!ParseWmLabel (pSD, menuItem, string))
2484 XtFree ((char *)menuItem);
2490 * Parse any menu function mnemonic.
2493 ParseWmMnemonic (&lineP, menuItem);
2496 * Parse any menu function accelerator.
2499 if (!ParseWmAccelerator (&lineP, menuItem))
2501 XtFree ((char *)menuItem);
2505 * Parse the menu function name if this is not a client
2506 * command. If it is a client command, then the wmFunction
2507 * field should already be set, as well as the ix variable,
2508 * but we do want to search for a menu item name that occupies
2509 * the same place as the function does for normal menu items.
2511 ix = ParseWmFunction (&lineP, CRS_MENU, &menuItem->wmFunction);
2514 * Determine context sensitivity and applicability mask.
2517 menuItem->greyedContext = functionTable[ix].greyedContext;
2518 menuItem->mgtMask = functionTable[ix].mgtMask;
2519 if ((menuItem->wmFunction == F_Toggle_Front_Panel) &&
2520 ((wmGD.useFrontPanel == False) ||
2521 (wmGD.dtSD != pSD)))
2524 * disallow this function if there's no front
2525 * panel on this screen.
2527 menuItem->greyedContext |= (F_CONTEXT_ALL |
2528 F_SUBCONTEXT_IB_WICON |
2529 F_SUBCONTEXT_IB_IICON);
2533 * Apply the function argument parser.
2535 if (!(*(functionTable [ix].parseProc))
2536 (&lineP, menuItem->wmFunction, &menuItem->wmFuncArgs))
2538 FreeMenuItem (menuItem);
2539 continue; /* skip this menu item */
2543 * Add this item to the menu specification.
2546 if (lastMenuItem != NULL) /* not first */
2548 lastMenuItem->nextMenuItem = menuItem;
2552 firstMenuItem = menuItem;
2554 lastMenuItem = menuItem;
2557 return (firstMenuItem);
2559 } /* END OF FUNCTION ParseMenuItems */
2562 /*************************************<->*************************************
2564 * ParseWmLabel (pSD, menuItem, string)
2569 * Parse a menu label string.
2574 * pSD = pointer to screen data
2575 * menuItem = pointer to MenuItem structure
2576 * string = label string
2582 * menuItem->labelType
2583 * menuItem->labelBitmapCache
2584 * Return = boolean, FALSE iff insufficient memory
2589 * We have two label types: XmSTRING and XmPIXMAP
2590 * We allocate and fill the label field with string and set the type to
2591 * XmSTRING. If string = "@<bitmap_file>", and <bitmap_file> contains a
2592 * with which to build a label image we save the bitmap in the MenuItem
2593 * structure and set the type to XmPIXMAP.
2595 *************************************<->***********************************/
2597 static Boolean ParseWmLabel (WmScreenData *pSD, MenuItem *menuItem,
2598 unsigned char *string)
2602 * Allocate the label field and copy string.
2605 if ((menuItem->label = (String)
2606 XtMalloc ((unsigned int)(strlen ((char *)string) + 1))) == NULL)
2608 PWarning (((char *)GETMESSAGE(60, 13, "Insufficient memory for menu item")));
2612 strcpy (menuItem->label, (char *)string);
2613 menuItem->labelType = XmSTRING;
2617 * Here: string = "@<bitmap file>"
2618 * Try to find the label bitmap in the bitmap cache or read the label
2622 string++; /* skip "@" */
2623 if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD,
2624 (char *)string, True)) >= 0)
2626 menuItem->labelType = XmPIXMAP;
2631 } /* END OF FUNCTION ParseWmLabel */
2635 /*************************************<->*************************************
2637 * ParseWmMnemonic (linePP, menuItem)
2642 * Parse an optional menu function mnemonic.
2647 * linePP = pointer to current line buffer pointer.
2648 * menuItem = pointer to MenuItem structure
2653 * linePP = pointer to revised line buffer pointer.
2654 * menuItem->mnemonic = valid mnemonic character or NULL.
2661 *************************************<->***********************************/
2663 static void ParseWmMnemonic (unsigned char **linePP, MenuItem *menuItem)
2665 unsigned char *lineP = *linePP;
2666 unsigned char *mnemonic;
2669 * Skip leading white space.
2671 ScanWhitespace (&lineP);
2672 menuItem->mnemonic = (KeySym)NULL;
2676 * We have a mnemonic specification.
2677 * Get the next string (we only use the first character).
2678 * If no string exists, the labelType is not XmSTRING, or does not contain
2679 * the first character, then skip the string and return.
2680 * Otherwise, accept the first character as a mnemonic.
2685 mnemonic = GetString(&lineP);
2687 if (menuItem->labelType == XmSTRING &&
2689 (ks = XStringToKeysym((char *)mnemonic)) != NoSymbol &&
2690 strchr(menuItem->label, (char)(ks & 0xff)) != NULL)
2692 menuItem->mnemonic = ks;
2696 PWarning (((char *)GETMESSAGE(60, 14, "Invalid mnemonic specification")));
2700 *linePP = lineP; /* consume any string */
2702 } /* END OF FUNCTION ParseWmMnemonic */
2705 /*************************************<->*************************************
2707 * ParseWmAccelerator (linePP, menuItem)
2712 * Parse an optional menu function accelerator.
2717 * linePP = pointer to current line buffer pointer.
2718 * menuItem = pointer to MenuItem structure
2723 * linePP = pointer to revised line buffer pointer.
2724 * menuItem->accelText = pointer to an accelerator string or NULL.
2731 *************************************<->***********************************/
2733 static Boolean ParseWmAccelerator (unsigned char **linePP, MenuItem *menuItem)
2735 unsigned char *lineP;
2737 unsigned int eventType;
2742 menuItem->accelState = 0;
2743 menuItem->accelKeyCode = 0;
2744 menuItem->accelText = NULL;
2748 * If linePP contains NULL, then abort.
2750 if (*linePP == (unsigned char *) NULL) return(FALSE);
2753 * Skip leading white space.
2755 ScanWhitespace (linePP);
2759 * If the second character is not ".", and an accelerator specification
2760 * exists, then process and save the specification string.
2763 if ((*lineP != '\0') && /* something follows */
2764 (*lineP != '!') && /* skip if we have the ! WmFunction */
2766 (*(lineP+1) != '.')) /* skip if we have f.xxx WmFunction */
2768 if (ParseKeyEvent(&lineP, &eventType, &keycode, &state))
2770 if ((string = (String) XtMalloc
2771 ((unsigned int) (lineP - *linePP + 1))) == NULL)
2773 PWarning (((char *)GETMESSAGE(60, 15, "Insufficient memory for accelerator specification")));
2778 * Save the accelerator state and keycode.
2779 * Process and save the accelerator text.
2782 ProcessAccelText (*linePP, lineP, (unsigned char *) string);
2783 menuItem->accelState = state;
2784 menuItem->accelKeyCode = keycode;
2785 menuItem->accelText = string;
2790 PWarning (((char *)GETMESSAGE(60, 16, "Invalid accelerator specification")));
2794 *linePP = lineP; /* consume the specification */
2799 } /* END OF FUNCTION ParseWmAccelerator */
2801 /*************************************<->*************************************
2804 * ParseWmFunction (linePP, res_spec, pWmFunction)
2809 * Parse a button, key, or menu function name and return its function table
2815 * linePP = pointer to current line buffer pointer.
2816 * res_spec = resource specification type (key, button, or menu).
2817 * pWmFunction = pointer to window manager function destination.
2818 * functionTable = window manager function parse table
2823 * linePP = pointer to revised line buffer pointer.
2824 * pWmFunction = pointer to parsed window manager function.
2825 * Return = function table index of parsed function.
2830 * Uses F_Nop if the function name or resource type is invalid.
2832 *************************************<->***********************************/
2834 int ParseWmFunction (unsigned char **linePP, unsigned int res_spec,
2835 WmFunction *pWmFunction)
2837 unsigned char *lineP = *linePP;
2838 unsigned char *string;
2839 int low, mid, high, cmp;
2842 * Skip leading white space.
2844 ScanWhitespace (&lineP);
2847 * Have function string (may be NULL or a comment).
2848 * Handle the special case of '!'
2854 *pWmFunction = F_Exec;
2855 return (F_EXEC_INDEX);
2859 * Identify the function corresponding to the specified name.
2860 * Try binary search of the window manager function parse table.
2861 * Assume f.nop if the function and resource type cannot be matched.
2862 * This handles NULL and comment strings, bad function names, and functions
2863 * in inappropriate resource sets.
2865 string = GetString (&lineP);
2870 ToLower ((char *)string);
2872 high = WMFUNCTIONTABLESIZE - 1;
2876 mid = (low + high)/2;
2877 cmp = strcmp (functionTable[mid].funcName, (char *)string);
2881 * Function name match
2882 * Require proper resource type for the function.
2885 if (res_spec & functionTable[mid].resource)
2887 *pWmFunction = functionTable[mid].wmFunction;
2891 /* invalid resource: use F_Nop */
2896 * Function name mismatch
2910 * Not found: assume f.nop
2912 *pWmFunction = F_Nop;
2913 return (F_NOP_INDEX);
2915 } /* END OF FUNCTION ParseWmFunction */
2918 /*************************************<->*************************************
2920 * ParseWmFuncMaybeStrArg (linePP, wmFunction, pArgs)
2925 * Parses a window manager function with a null or string argument.
2930 * linePP = pointer to current line buffer pointer.
2931 * wmFunction = function (not used).
2932 * pArgs = pointer to argument destination.
2937 * linePP = pointer to revised line buffer pointer.
2938 * pArgs = pointer to parsed argument string.
2939 * Return = FALSE iff insufficient memory
2944 * Only used to parse arguments for F_Lower, F_Raise, and F_Raise_Lower.
2945 * If it is used for any other function, be sure to change FreeMenuItem ()
2948 *************************************<->***********************************/
2950 Boolean ParseWmFuncMaybeStrArg (unsigned char **linePP,
2951 WmFunction wmFunction, String *pArgs)
2953 unsigned char *string = *linePP;
2956 ScanWhitespace (&string);
2961 return (ParseWmFuncStrArg (linePP, wmFunction, pArgs));
2965 else if (*lineP == '"' && *(lineP+1) == '-')
2968 strcpy ((char *) (lineP+1), (char *) (lineP+2));
2969 return (ParseWmFuncStrArg (linePP, wmFunction, pArgs));
2972 if ((len = strlen ((char *)string)) != 0)
2974 if ((*pArgs = (String)XtMalloc (len + 1)) == NULL)
2976 PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory")));
2979 strcpy (*pArgs, (char *)string);
2983 /* Do ParseWmFuncNoArg () */
2989 } /* END OF FUNCTION ParseWmFuncMaybeStrArg */
2992 /*************************************<->*************************************
2994 * ParseWmFuncNoArg (linePP, wmFunction, pArgs)
2999 * Parses a window manager function null argument.
3004 * linePP = pointer to current line buffer pointer.
3005 * wmFunction = function (not used).
3006 * pArgs = pointer to argument destination.
3011 * linePP = unchanged
3020 *************************************<->***********************************/
3022 static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction,
3029 } /* END OF FUNCTION ParseWmFuncNoArg */
3032 /*************************************<->*************************************
3034 * ParseWmFuncStrArg (linePP, wmFunction, pArgs)
3039 * Parses a window manager function string argument.
3044 * linePP = pointer to current line buffer pointer.
3045 * wmFunction = function for which the argument string is intended.
3046 * pArgs = pointer to argument string destination.
3051 * linePP = pointer to revised line buffer pointer.
3052 * pArgs = pointer to parsed argument string.
3053 * Return = FALSE iff insufficient memory
3058 * Insures that an argument for F_Exec() ends in '&' .
3059 * Only used to parse arguments for F_Exec, F_Menu, F_Lower, F_Raise,
3060 * F_Raise_Lower, and F_Screen. If it is used for any other function, be
3061 * sure to change FreeMenuItem () accordingly.
3063 *************************************<->***********************************/
3065 Boolean ParseWmFuncStrArg (unsigned char **linePP,
3066 WmFunction wmFunction, String *pArgs)
3068 unsigned char *string;
3076 if ((string = GetString (linePP)) != NULL)
3077 /* nonNULL string argument */
3079 len = strlen ((char *)string);
3080 if ((*pArgs = (String)XtMalloc (len + 2)) == NULL)
3082 PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory")));
3085 strcpy (*pArgs, (char *)string);
3088 * Insure that an argument for F_Exec ends in '&' .
3091 if (wmFunction == F_Exec)
3096 ((len = mblen(p, MB_CUR_MAX)) > 0))
3098 mbtowc(&last, p, MB_CUR_MAX);
3103 mbtowc(&wdelim, &delim, MB_CUR_MAX);
3104 if (lastlen == 1 && last != wdelim)
3112 /* NULL string argument */
3119 } /* END OF FUNCTION ParseWmFuncStrArg */
3122 /*************************************<->*************************************
3124 * FreeMenuItem (menuItem)
3129 * This procedure destroys a MenuItem structure.
3134 * menuItem = to be destroyed.
3144 * Assumes that ParseWmFuncStrArg () has parsed a menu item's function
3145 * argument only for F_Exec, F_Menu, F_Lower, F_Raise, F_Raise_Lower, and
3146 * F_Screen. If it is used for other functions, be sure to include them here!
3148 *************************************<->***********************************/
3150 void FreeMenuItem (MenuItem *menuItem)
3152 if (menuItem->label != NULL)
3154 XtFree ((char *)menuItem->label);
3157 if (menuItem->accelText != NULL)
3159 XtFree ((char *)menuItem->accelText);
3163 * If menuItem->wmFuncArgs is nonNULL, we assume that it is a string that
3164 * was malloc'ed in ParseWmFuncStrArg () and we free it now.
3166 if ((menuItem->wmFuncArgs != NULL) &&
3167 ((menuItem->wmFunction == F_Exec) ||
3168 (menuItem->wmFunction == F_Menu) ||
3169 (menuItem->wmFunction == F_Lower) ||
3170 (menuItem->wmFunction == F_Raise) ||
3171 (menuItem->wmFunction == F_Raise_Lower) ||
3172 (menuItem->wmFunction == F_Screen)))
3174 XtFree ((char *)menuItem->wmFuncArgs);
3177 XtFree ((char *)menuItem);
3179 } /* END OF FUNCTION FreeMenuItem */
3183 /*************************************<->*************************************
3185 * ParseWmFuncGrpArg (linePP, wmFunction, pGroup)
3190 * Parses a window manager function group argument.
3195 * linePP = pointer to current line buffer pointer.
3196 * wmFunction = function for which the group argument is intended.
3197 * pGroup = pointer to group argument destination.
3202 * linePP = pointer to revised line buffer pointer.
3203 * pGroup = pointer to parsed group argument.
3204 * Return = FALSE iff invalid group argument.
3209 * The only valid nonNULL arguments are "icon", "window", and "transient".
3211 *************************************<->***********************************/
3213 static Boolean ParseWmFuncGrpArg (unsigned char **linePP,
3214 WmFunction wmFunction, GroupArg *pGroup)
3216 unsigned char *lineP = *linePP;
3217 unsigned char *startP;
3218 unsigned char grpStr[MAX_GROUP_STRLEN+1];
3223 * Parse groups while each is followed by "|".
3230 * Skip whitespace and find next group string.
3233 ScanWhitespace (&lineP);
3235 ScanAlphanumeric (&lineP);
3236 if (startP == lineP)
3237 /* Group missing => use default or complain */
3241 PWarning (((char *)GETMESSAGE(60, 18, "Missing group specification")));
3246 *pGroup = F_GROUP_DEFAULT;
3252 * Found a group string; compare it with valid groups.
3255 len = min (lineP - startP, MAX_GROUP_STRLEN);
3256 (void) strncpy ((char *)grpStr, (char *)startP, len);
3258 ToLower ((char *)grpStr);
3260 if (!strcmp ("icon", (char *)grpStr))
3262 *pGroup |= F_GROUP_ICON;
3264 else if (!strcmp ("window", (char *)grpStr))
3266 *pGroup |= F_GROUP_WINDOW;
3268 else if (!strcmp ("transient", (char *)grpStr))
3270 *pGroup |= F_GROUP_TRANSIENT;
3273 /* Unknown group name */
3275 PWarning (((char *)GETMESSAGE(60, 19, "Invalid group specification")));
3280 * Continue processing until the line is exhausted.
3284 ScanWhitespace (&lineP);
3286 if (lineP == NULL || *lineP == '\0')
3290 else if (*lineP == '|')
3299 } /* END OF FUNCTION ParseWmFuncGrpArg */
3303 /*************************************<->*************************************
3305 * ParseWmFuncNbrArg (linePP, wmFunction, pNumber)
3310 * Parses a window manager function number argument.
3315 * linePP = pointer to current line buffer pointer.
3316 * wmFunction = function
3317 * pNumber = pointer to number argument destination.
3322 * linePP = pointer to revised line buffer pointer.
3323 * pNumber = pointer to parsed number argument.
3324 * Return = FALSE iff invalid number argument.
3331 *************************************<->***********************************/
3333 static Boolean ParseWmFuncNbrArg (unsigned char **linePP,
3334 WmFunction wmFunction,
3335 unsigned long *pNumber)
3339 val = StrToNum (GetString (linePP));
3342 PWarning (((char *)GETMESSAGE(60, 20, "Invalid number specification")));
3350 } /* END OF FUNCTION ParseWmFuncNbrArg */
3352 /*************************************<->*************************************
3359 * This function parses a button set specification string:
3363 * button context function
3364 * button context function
3366 * button context function
3373 * pSD->buttonBindings = buttonBindings resource value
3374 * functionTable = window manager function parse table
3379 * pSD->buttonSpecs = list of button binding specifications.
3384 * The button set specification name must match pSD->buttonBindings.
3386 *************************************<->***********************************/
3388 void ParseButtonStr (WmScreenData *pSD, unsigned char *buttonStr)
3390 unsigned char *lineP;
3394 if (((parseP = buttonStr) != NULL) && (GetNextLine () != NULL))
3397 ParseButtonSet (pSD, lineP);
3400 } /* END OF FUNCTION ParseButtonStr */
3403 /*************************************<->*************************************
3405 * ParseButtonSet (pSD, lineP)
3410 * Button set specification found. Parse the following syntax:
3413 * Buttons bindings_name
3415 * button context function
3416 * button context function
3418 * button context function
3424 * cfileP = (global) file pointer to fopened configuration file or NULL
3425 * line = (global) line buffer
3426 * lineP = pointer to current character in line buffer
3427 * pSD->buttonBindings = buttonBindings resource value
3432 * lineP = pointer to current character in line buffer
3433 * pSD->buttonSpecs = list of button binding specifications.
3438 * Skips unnamed button binding set and sets with names that don't match
3439 * the buttonBindings resource.
3440 * Skips bad button binding specifications.
3442 *************************************<->***********************************/
3444 static void ParseButtonSet (WmScreenData *pSD, unsigned char *lineP)
3446 unsigned char *string;
3447 ButtonSpec *buttonSpec;
3448 ButtonSpec *lastButtonSpec;
3452 * Parse the button set bindings from the configuration file.
3453 * If either the button set name or buttonBindings resource is NULL or
3454 * they don't match, then skip this button specification.
3457 if (((string = GetString (&lineP)) == NULL) ||
3458 (pSD->buttonBindings == NULL) ||
3459 strcmp ((char *)string, pSD->buttonBindings))
3465 * Require leading '{' on the next line.
3467 while ((GetNextLine () != NULL)) /* not EOF nor read error */
3470 ScanWhitespace(&lineP);
3472 if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
3473 /* ignore empty or comment line */
3485 PWarning (((char *)GETMESSAGE(60, 21, "Expected '{' after button set name")));
3490 * Found leading "{" or EOF.
3491 * Prepare to accumulate button bindings by finding the end of
3492 * the button specification list.
3493 * lastButtonSpec will be NULL only if no prior bindings exist.
3496 lastButtonSpec = pSD->buttonSpecs;
3497 if (lastButtonSpec != NULL)
3499 while (lastButtonSpec->nextButtonSpec != NULL)
3501 lastButtonSpec = (lastButtonSpec->nextButtonSpec);
3506 * Parse "button context function" until "}" or EOF found.
3507 * Skips bad button binding specifications.
3510 while ((GetNextLine () != NULL)) /* not EOF nor read error */
3513 ScanWhitespace(&lineP);
3514 if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
3515 /* ignore empty or comment lines */
3519 if (*lineP == '}') /* finished with button set */
3525 * Allocate space for the button binding specification.
3527 if ((buttonSpec = (ButtonSpec *)XtMalloc (sizeof (ButtonSpec))) == NULL)
3529 PWarning (((char *)GETMESSAGE(60, 22, "Insufficient memory for button specification")));
3532 buttonSpec->wmFunction = (WmFunction)NULL;
3533 buttonSpec->wmFuncArgs = NULL;
3534 buttonSpec->nextButtonSpec = NULL;
3537 * Parse the button specification "button".
3540 if (!ParseBtnEvent(&lineP,
3541 &buttonSpec->eventType,
3542 &buttonSpec->button,
3544 &buttonSpec->click))
3546 PWarning (((char *)GETMESSAGE(60, 23, "Invalid button specification")));
3547 XtFree ((char *)buttonSpec);
3548 continue; /* skip this button specification */
3553 * Parse the button context.
3555 if (!ParseContext(&lineP, &buttonSpec->context,
3556 &buttonSpec->subContext))
3558 PWarning (((char *)GETMESSAGE(60, 24, "Invalid button context")));
3559 XtFree ((char *)buttonSpec);
3560 continue; /* skip this button specification */
3564 * Parse the button function and any arguments.
3567 ix = ParseWmFunction (&lineP, CRS_BUTTON, &buttonSpec->wmFunction);
3570 * remove any subContexts that don't apply to this function
3573 if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) &&
3574 (buttonSpec->subContext & F_SUBCONTEXT_IB_IICON))
3576 buttonSpec->subContext &= ~F_SUBCONTEXT_IB_IICON;
3579 if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) &&
3580 (buttonSpec->subContext & F_SUBCONTEXT_IB_WICON))
3582 buttonSpec->subContext &= ~F_SUBCONTEXT_IB_WICON;
3586 * Map Button3 menus to BMenu virtual button
3588 if (buttonSpec->button == Button3 &&
3589 (buttonSpec->wmFunction == F_Menu ||
3590 buttonSpec->wmFunction == F_Post_SMenu)) {
3592 buttonSpec->button = wmGD.bMenuButton;
3596 * Apply the function argument parser.
3598 if (!(*(functionTable [ix].parseProc))
3599 (&lineP, buttonSpec->wmFunction, &buttonSpec->wmFuncArgs))
3601 XtFree ((char *)buttonSpec);
3602 continue; /* skip this button specification */
3606 * Add the button specification to the button specification list.
3608 if (lastButtonSpec != NULL)
3609 /* a prior specification exists */
3611 lastButtonSpec->nextButtonSpec = buttonSpec;
3615 pSD->buttonSpecs = buttonSpec;
3617 lastButtonSpec = buttonSpec;
3620 } /* END OF FUNCTION ParseButtonSet */
3624 /*************************************<->*************************************
3626 * ParseContext (linePP, context, subContext)
3631 * Parses a general context string.
3636 * linePP = pointer to current line buffer pointer.
3640 * linePP = pointer to revised line buffer pointer.
3641 * context = context field value
3642 * subContext = subContext field value
3643 * Return = (Boolean) true iff valid context string
3650 *************************************<->***********************************/
3652 static Boolean ParseContext (unsigned char **linePP, Context *context,
3653 Context *subContext)
3655 unsigned char *lineP = *linePP;
3656 unsigned char *startP;
3657 unsigned char ctxStr[MAX_CONTEXT_STRLEN+1];
3661 * Parse contexts while each is followed by "|".
3669 * Skip whitespace and find next context string.
3671 ScanWhitespace (&lineP);
3673 ScanAlphanumeric (&lineP);
3674 if (startP == lineP)
3675 /* ERROR: Context missing */
3681 * Found nonNULL string; compare it with valid contexts.
3684 len = min(lineP - startP, MAX_CONTEXT_STRLEN);
3685 (void) strncpy ((char *)ctxStr, (char *)startP, len);
3687 ToLower ((char *)ctxStr);
3689 if (!strcmp ("root", (char *)ctxStr))
3691 *context |= F_CONTEXT_ROOT;
3692 *subContext |= F_SUBCONTEXT_R_ALL;
3694 else if (!strcmp ("icon", (char *)ctxStr))
3696 *context |= (F_CONTEXT_ICON |
3698 F_SUBCONTEXT_IB_IICON |
3699 F_SUBCONTEXT_IB_WICON );
3700 *subContext |= (F_SUBCONTEXT_I_ALL |
3701 F_SUBCONTEXT_IB_IICON |
3702 F_SUBCONTEXT_IB_WICON );
3704 else if (!strcmp ("window", (char *)ctxStr))
3706 *context |= F_CONTEXT_WINDOW;
3707 *subContext |= F_SUBCONTEXT_W_ALL;
3709 else if (!strcmp ("frame", (char *)ctxStr))
3711 *context |= F_CONTEXT_WINDOW;
3712 *subContext |= F_SUBCONTEXT_W_FRAME;
3714 else if (!strcmp ("title", (char *)ctxStr))
3716 *context |= F_CONTEXT_WINDOW;
3717 *subContext |= F_SUBCONTEXT_W_TITLE;
3719 else if (!strcmp ("border", (char *)ctxStr))
3721 *context |= F_CONTEXT_WINDOW;
3722 *subContext |= F_SUBCONTEXT_W_BORDER;
3724 else if (!strcmp ("app", (char *)ctxStr))
3726 *context |= F_CONTEXT_WINDOW;
3727 *subContext |= F_SUBCONTEXT_W_APP;
3729 else if (!strcmp ("ifkey", (char *)ctxStr))
3731 *context |= F_CONTEXT_IFKEY;
3734 /* Unknown context name */
3739 /* continue only if followed by '|' */
3740 ScanWhitespace (&lineP);
3751 } /* END OF FUNCTION ParseContext */
3754 /*************************************<->*************************************
3761 * This function parses a key set specification string:
3765 * key context function
3766 * key context function
3768 * key context function
3774 * pSD->keyBindings = keyBindings resource value
3775 * functionTable = window manager function parse table
3780 * pSD->keySpecs = list of key binding specification
3785 * The key set specification name must match pSD->keyBindings.
3787 *************************************<->***********************************/
3790 ParseKeyStr (WmScreenData *pSD, unsigned char *keyStr)
3792 unsigned char *lineP;
3796 if (((parseP = keyStr) != NULL) && (GetNextLine () != NULL))
3799 ParseKeySet (pSD, lineP);
3802 } /* END OF FUNCTION ParseKeyStr */
3806 /*************************************<->*************************************
3808 * ParseKeySet (pSD, lineP)
3813 * Key set specification found. Parse the following syntax:
3816 * Keys bindings_name
3818 * key context function
3819 * key context function
3821 * key context function
3827 * cfileP = (global) file pointer to fopened configuration file or NULL
3828 * line = (global) line buffer
3829 * lineP = pointer to current character in line buffer
3830 * pSD->keyBindings = keyBindings resource value
3835 * lineP = pointer to current character in line buffer
3836 * pSD->keySpecs = list of key binding specifications.
3841 * Skips unnamed key binding set and sets with names that don't match the
3842 * keyBindings resource.
3843 * Skips bad key binding specifications.
3845 *************************************<->***********************************/
3847 static void ParseKeySet (WmScreenData *pSD, unsigned char *lineP)
3849 unsigned char *string;
3851 KeySpec *lastKeySpec;
3852 unsigned int eventType;
3857 * Parse the key set bindings from the configuration file.
3858 * If either the key set name or keyBindings resource is NULL or they
3859 * don't match then skip this key specification.
3862 if (((string = GetString (&lineP)) == NULL) ||
3863 (pSD->keyBindings == NULL) ||
3864 strcmp ((char *)string, pSD->keyBindings))
3870 * Require leading '{' on next line.
3872 while ((GetNextLine () != NULL)) /* not EOF nor read error */
3875 ScanWhitespace(&lineP);
3877 if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
3878 /* ignore empty or comment line */
3890 PWarning (((char *)GETMESSAGE(60, 25, "Expected '{' after key set name")));
3895 * Found leading "{" or EOF.
3896 * Prepare to accumulate key bindings by finding the end of
3897 * the key specification list.
3898 * lastKeySpec will be NULL only if no prior bindings exist.
3901 lastKeySpec = pSD->keySpecs;
3902 if (lastKeySpec != NULL)
3904 while (lastKeySpec->nextKeySpec != NULL)
3906 lastKeySpec = (lastKeySpec->nextKeySpec);
3911 * Parse "key context function" until "}" or EOF found.
3912 * Skip bad key bindings.
3915 while ((GetNextLine () != NULL)) /* not EOF nor read error */
3918 ScanWhitespace (&lineP);
3919 if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
3920 /* ignore empty or comment lines */
3924 if (*lineP == '}') /* finished with key set */
3930 * Allocate space for the key specification.
3932 if ((keySpec = (KeySpec *)XtMalloc (sizeof (KeySpec))) == NULL)
3934 PWarning (((char *)GETMESSAGE(60, 26, "Insufficient memory for key specification")));
3938 keySpec->wmFunction = (WmFunction)NULL;
3939 keySpec->wmFuncArgs = NULL;
3940 keySpec->nextKeySpec = NULL;
3943 * Parse the key specification.
3946 if (!ParseKeyEvent(&lineP,
3955 * Parse the key context.
3956 * Here lineP points to the candidate context string.
3959 if (!ParseContext(&lineP, &keySpec->context,
3960 &keySpec->subContext))
3963 PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
3964 PWarning (((char *)GETMESSAGE(60, 28, "Invalid key context")));
3965 XtFree ((char *)keySpec);
3966 continue; /* skip this key specification */
3971 * Don't print an error message if this is a "hardware
3972 * available" binding.
3974 if (!(keySpec->context & F_CONTEXT_IFKEY))
3975 PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
3976 XtFree ((char *)keySpec);
3977 continue; /* skip this key specification */
3981 * This flag is only used for parsing, clear it so the
3982 * rest of the program doesn't see it.
3984 keySpec->context &= ~F_CONTEXT_IFKEY;
3988 * Parse the key function and any arguments.
3991 ix = ParseWmFunction (&lineP, CRS_KEY, &keySpec->wmFunction);
3994 * remove any subContexts that don't apply to this function
3996 if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) &&
3997 (keySpec->subContext & F_SUBCONTEXT_IB_IICON))
3999 keySpec->subContext &= ~F_SUBCONTEXT_IB_IICON;
4002 if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) &&
4003 (keySpec->subContext & F_SUBCONTEXT_IB_WICON))
4005 keySpec->subContext &= ~F_SUBCONTEXT_IB_WICON;
4009 * Apply the function argument parser.
4011 if (!(*(functionTable [ix].parseProc))
4012 (&lineP, keySpec->wmFunction, &keySpec->wmFuncArgs))
4014 XtFree ((char *)keySpec);
4015 continue; /* skip this key specification */
4019 * Add the key specification to the key specification list.
4021 if (lastKeySpec != NULL)
4022 /* a prior specification exists */
4024 lastKeySpec->nextKeySpec = keySpec;
4028 pSD->keySpecs = keySpec;
4030 lastKeySpec = keySpec;
4033 } /* END OF FUNCTION ParseKeySet */
4036 /*************************************<->*************************************
4038 * ParseBtnEvent (linePP, eventType, button, state, fClick)
4043 * Parse a button event specification.
4048 * linePP = pointer to current line buffer pointer
4049 * buttonEvents = (global) button event parse table
4050 * modifierStrings = (global) modifier string/mask table
4055 * linePP = pointer to revised line buffer pointer.
4056 * eventType = type of event
4057 * button = parsed button number
4058 * state = composite modifier mask
4059 * fClick = is click?
4061 * Return = (Boolean) true iff valid button event specification
4068 *************************************<->***********************************/
4070 Boolean ParseBtnEvent (unsigned char **linePP,
4071 unsigned int *eventType,
4072 unsigned int *button,
4073 unsigned int *state,
4076 if (!ParseEvent (linePP, buttonEvents, eventType, button, state, fClick))
4082 * The following is a fix for an X11 deficiency in regards to
4083 * modifiers in grabs.
4085 if (*eventType == ButtonRelease)
4087 /* the button that is going up will always be in the modifiers... */
4088 *state |= buttonModifierMasks[*button];
4093 } /* END OF FUNCTION ParseBtnEvent */
4097 /*************************************<->*************************************
4099 * ParseKeyEvent (linePP, eventType, keyCode, state)
4104 * Parse a key event specification.
4109 * linePP = pointer to current line buffer pointer
4110 * keyEvents = (global) key event parse table
4111 * modifierStrings = (global) modifier string/mask table
4116 * linePP = pointer to revised line buffer pointer.
4117 * eventType = type of event
4118 * keyCode = parsed KeyCode
4119 * state = composite modifier mask
4121 * Return = (Boolean) true iff valid key event specification
4128 *************************************<->***********************************/
4130 Boolean ParseKeyEvent (unsigned char **linePP, unsigned int *eventType,
4131 KeyCode *keyCode, unsigned int *state)
4136 unsigned int keySym = 0;
4138 if (!ParseEvent (linePP, keyEvents, eventType, &keySym, state, &fClick))
4144 * Here keySym is a KeySym. Convert it to a KeyCode.
4145 * KeyCode will be set to 0 if keySym is not defined for any KeyCode
4149 *keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym);
4153 if (keySym == XK_F9)
4157 else if (keySym == XK_F10)
4161 else if (keySym == XK_F11)
4165 else if (keySym == XK_F12)
4169 *keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym);
4172 return (*keyCode != 0);
4174 } /* END OF FUNCTION ParseKeyEvent */
4177 /*************************************<->*************************************
4179 * ParseEvent (linePP, table, eventType, detail, state, fClick)
4184 * Parse an event specification.
4189 * linePP = pointer to current line buffer pointer.
4190 * table = event parse table
4191 * modifierStrings = (global) modifier string/mask table
4196 * linePP = pointer to revised line buffer pointer.
4197 * eventType = type of event
4198 * detail = dependent upon parse table detail procedure and closure
4199 * state = composite modifier mask
4200 * fClick = click flag
4202 * Return = (Boolean) true iff valid event specification
4208 *************************************<->***********************************/
4210 static Boolean ParseEvent (unsigned char **linePP, EventTableEntry *table,
4211 unsigned int *eventType, unsigned int *detail,
4212 unsigned int *state, Boolean *fClick)
4214 unsigned char *lineP = *linePP;
4218 /* Parse the modifiers */
4219 if (!ParseModifiers (&lineP, state) || *lineP != '<')
4223 lineP++; /* skip '<' */
4225 /* Parse the event type */
4226 if (!ParseEventType (&lineP, table, eventType, &ix) || *lineP != '>')
4230 lineP++; /* skip '>' */
4233 * Compute detail and fClick.
4234 * Status will be False for a invalid KeySym name.
4236 status = (*(table[ix].parseProc))(&lineP, table[ix].closure, detail);
4237 *fClick = table[ix].fClick;
4245 } /* END OF FUNCTION ParseEvent */
4249 /*************************************<->*************************************
4251 * ParseModifiers(linePP, state)
4256 * Parses a modifier specification.
4261 * linePP = pointer to current line buffer pointer.
4262 * modifierStrings = (global) modifier string/mask table
4267 * linePP = pointer to revised line buffer pointer.
4268 * state = composite modifier mask
4269 * Return = (Boolean) true iff valid modifier name
4274 * If successful, will be followed by NULL or '<'.
4276 *************************************<->***********************************/
4278 static Boolean ParseModifiers(unsigned char **linePP, unsigned int *state)
4280 unsigned char *lineP = *linePP;
4281 unsigned char *startP;
4282 unsigned char modStr[MAX_MODIFIER_STRLEN+1];
4284 unsigned int maskBit;
4290 * Parse modifiers until the event specifier is encountered.
4293 ScanWhitespace (&lineP);
4294 while ((*lineP != '\0') && (*lineP != '<'))
4307 ScanAlphanumeric (&lineP);
4308 if (startP == lineP)
4309 /* ERROR: Modifier or '<' missing */
4313 len = min(lineP - startP, MAX_MODIFIER_STRLEN);
4314 (void) strncpy ((char *)modStr, (char *)startP, len);
4317 if (!LookupModifier (modStr, &maskBit))
4318 /* Unknown modifier name */
4331 ScanWhitespace(&lineP);
4335 return (TRUE); /* must have '<' or NULL following */
4337 } /* END OF FUNCTION ParseModifiers */
4340 /*************************************<->*************************************
4342 * LookupModifier (name, valueP)
4347 * Return the modifier mask for the provided modifier name.
4352 * name = modifier string
4353 * modifierStrings = modifier string/mask table
4358 * valueP = modifier mask
4359 * Return = (Boolean) true iff valid modifier name
4366 *************************************<->***********************************/
4368 static Boolean LookupModifier (unsigned char *name, unsigned int *valueP)
4374 ToLower ((char *)name);
4375 for (i=0; modifierStrings[i].name != NULL; i++)
4377 if (!strcmp (modifierStrings[i].name, (char *)name))
4379 *valueP = modifierStrings[i].mask;
4387 } /* END OF FUNCTION LookupModifier */
4389 /*************************************<->*************************************
4391 * ParseEventType(linePP, table, eventType, ix)
4396 * Parses the event type string.
4401 * linePP = pointer to current line buffer pointer.
4402 * table = event parse table
4407 * linePP = pointer to revised line buffer pointer.
4408 * eventType = type of event
4409 * ix = table index for matched event
4411 * Return = (Boolean) true iff valid event
4418 *************************************<->***********************************/
4420 static Boolean ParseEventType (unsigned char **linePP, EventTableEntry *table,
4421 unsigned int *eventType, Cardinal *ix)
4423 unsigned char *lineP = *linePP;
4424 unsigned char *startP = *linePP;
4425 unsigned char eventTypeStr[MAX_EVENTTYPE_STRLEN+1];
4428 /* Parse out the event string */
4429 ScanAlphanumeric (&lineP);
4432 * Attempt to match the parsed event against our supported event set.
4435 if (startP != lineP)
4437 len = min (lineP - startP, MAX_EVENTTYPE_STRLEN);
4438 (void) strncpy ((char *)eventTypeStr, (char *)startP, len);
4439 eventTypeStr[len] = '\0';
4440 ToLower ((char *)eventTypeStr);
4442 for (len = 0; table[len].event != NULL; len++)
4443 if (!strcmp (table[len].event, (char *)eventTypeStr))
4446 *eventType = table[*ix].eventType;
4452 /* Unknown event specified */
4455 } /* END OF FUNCTION ParseEventType */
4458 /*************************************<->*************************************
4460 * ParseImmed (linePP, closure, detail)
4465 * Button event detail procedure.
4471 * closure = table entry
4476 * detail = pointer to closure
4485 *************************************<->***********************************/
4487 static Boolean ParseImmed (unsigned char **linePP, unsigned int closure,
4488 unsigned int *detail)
4493 } /* END OF FUNCTION ParseImmed */
4496 /*************************************<->*************************************
4498 * ParseKeySym (linePP, closure, detail)
4503 * Key event detail procedure. Parses a KeySym string.
4508 * linePP = pointer to current line buffer pointer
4510 * closure = not used.
4515 * linePP = pointer to revised line buffer pointer
4516 * detail = pointer to parsed KeySym
4518 * Return = (Boolean) true iff valid KeySym string
4525 *************************************<->***********************************/
4527 static Boolean ParseKeySym (unsigned char **linePP, unsigned int closure,
4528 unsigned int *detail)
4530 unsigned char *lineP = *linePP;
4531 unsigned char *startP;
4532 char keySymName[MAX_KEYSYM_STRLEN+1];
4536 ScanWhitespace (&lineP);
4540 ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 0) &&
4542 (!isspace (*lineP) && *lineP != ',' && *lineP != ':')))
4544 /* Skip next character */
4548 len = min (lineP - startP, MAX_KEYSYM_STRLEN);
4549 (void) strncpy (keySymName, (char *)startP, len);
4550 keySymName[len] = '\0';
4552 if ((*detail = XStringToKeysym(keySymName)) == NoSymbol &&
4553 (mblen (keySymName, MB_CUR_MAX) == 1))
4555 if (!isdigit (keySymName[0]) ||
4556 ((*detail = StrToNum ((unsigned char *)&keySymName[0])) == -1))
4565 } /* END OF FUNCTION ParseKeySym */
4569 /*************************************<->*************************************
4576 * Converts a string to an unsigned hexadecimal, decimal, or octal integer.
4581 * str = character string
4586 * Return = unsigned integer
4593 *************************************<->***********************************/
4595 static unsigned int StrToNum(unsigned char *str)
4598 unsigned int val = 0;
4603 if (*str == 'x' || *str == 'X')
4605 return (StrToHex(++str));
4607 return (StrToOct(str));
4610 while ((c = *str) != '\0')
4612 if ('0' <= c && c <= '9')
4625 } /* END OF FUNCTION StrToNum */
4629 /*************************************<->*************************************
4648 *************************************<->***********************************/
4650 static unsigned int StrToHex(unsigned char *str)
4653 unsigned int val = 0;
4655 while ((c = *str) != '\0')
4657 if ('0' <= c && c <= '9')
4661 else if ('a' <= c && c <= 'f')
4663 val = val*16+c-'a'+10;
4665 else if ('A' <= c && c <= 'F')
4667 val = val*16+c-'A'+10;
4678 } /* END OF FUNCTION StrToHex */
4682 /*************************************<->*************************************
4701 *************************************<->***********************************/
4703 static unsigned int StrToOct(unsigned char *str)
4706 unsigned int val = 0;
4708 while ((c = *str) != '\0')
4710 if ('0' <= c && c <= '7')
4723 } /* END OF FUNCTION StrToOct */
4727 /*************************************<->*************************************
4729 * ScanAlphanumeric (linePP)
4734 * Scan string until a non-alphanumeric character is encountered.
4739 * linePP = nonNULL pointer to current line buffer pointer
4744 * linePP = nonNULL pointer to revised line buffer pointer
4749 * Assumes linePP is nonNULL
4751 *************************************<->***********************************/
4753 void ScanAlphanumeric (unsigned char **linePP)
4758 ((chlen = mblen ((char *) *linePP, MB_CUR_MAX)) > 0) &&
4759 ((chlen > 1) || isalnum (**linePP)))
4763 } /* END OF FUNCTION ScanAlphanumeric */
4769 /*************************************<->*************************************
4771 * PWarning (message)
4776 * This function lists a resource description parse message to stderr.
4781 * message = pointer to a message string
4782 * cfileP = (global) file pointer to fopened configuration file or NULL
4783 * linec = (global) line counter
4785 *************************************<->***********************************/
4788 PWarning (char *message)
4791 char pch[MAXWMPATH+1];
4795 sMessage = XtNewString ((String) message);
4798 if (pConfigStackTop->fileName)
4800 pchFile = pConfigStackTop->fileName;
4804 pchFile = wmGD.configFile;
4807 sprintf (pch, pWarningStringFile,
4808 GETMESSAGE(20,1,"Workspace Manager"),
4809 sMessage, linec, pchFile);
4813 sprintf (pch, pWarningStringLine,
4814 GETMESSAGE(20,1,"Workspace Manager"),
4817 _DtSimpleError (wmGD.mwmName, DtIgnore, NULL, pch, NULL);
4821 } /* END OF FUNCTION PWarning */
4824 * Key substitution table entry
4827 typedef struct _keySubs
4829 unsigned char * pchFrom;
4831 unsigned char * pchTo;
4835 /*************************************<->*************************************
4837 * InitKeySubs (ppKeySubs, pNumKeySubs)
4842 * Initialize key label substitutions used in acclerator text
4847 * ppKeySubs = ptr to key substitution table ptr
4848 * pNumKeySubs = ptr to number of key substitutions
4853 * *ppKeySubs = ptr to key substitution table
4854 * *pNumKeySubs = number of substitutions found
4858 * *ppKeySubs is allocated with XtMalloc in a complicated way.
4859 * If this ever needs to be freed, a function to free it needs to
4862 *************************************<->***********************************/
4864 static void InitKeySubs (
4871 unsigned char *pch0;
4872 unsigned char *pch1;
4876 pch0 = (unsigned char *)GETMESSAGE(60, 40, "");
4878 if ((pch0 == NULL) || (*pch0 == '\0'))
4888 while (*pch0 != '\0')
4890 ScanWhitespace (&pch0);
4891 if (*pch0 == '\0') break;
4894 * allocate space for next key sub
4898 pKSret = (KeySub *) XtMalloc (1*sizeof(KeySub));
4902 pKSret = (KeySub *) XtRealloc ((char *)pKSret,
4903 (numKS+1)*sizeof(KeySub));
4905 pKS = &pKSret[numKS];
4907 /* get "from" string */
4909 while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
4911 if ((chlen == 1) && (*pch1 == ' '))
4917 pKS->lenFrom = pch1 - pch0;
4918 if (pKS->lenFrom < 1)
4925 pKS->pchFrom = (unsigned char *) XtMalloc (1+pKS->lenFrom);
4926 memcpy (pKS->pchFrom, pch0, pKS->lenFrom);
4927 pKS->pchFrom[pKS->lenFrom] = '\0';
4929 /* get "to" string */
4930 ScanWhitespace (&pch1);
4933 while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
4935 if ((chlen == 1) && (*pch1 == ' '))
4946 * Invalid format, "from" string with no "to" string.
4950 pKS->pchTo = (unsigned char *) XtMalloc (1+len);
4951 memcpy (pKS->pchTo, pch0, len);
4952 pKS->pchTo[len] = '\0';
4954 /* advance cursor */
4957 /* got one, bump the counter */
4961 *ppKeySubs = pKSret;
4962 *pNumKeySubs = numKS;
4966 /*************************************<->*************************************
4968 * ProcessAccelText (startP, endP, destP)
4973 * Process accelerator text and copy into string.
4978 * startP = pointer to start of valid accelerator specification
4979 * endP = pointer past end of accelerator specification
4980 * destP = pointer to destination buffer
4985 * Destination buffer has processed accelerator text.
4991 *************************************<->***********************************/
4993 static void ProcessAccelText (unsigned char *startP, unsigned char *endP,
4994 unsigned char *destP)
4997 static Boolean bAccelInit = False;
4998 static KeySub *pKeySub;
4999 static int numKeySubs;
5000 unsigned char * pchFirst;
5001 unsigned char * pchSub;
5007 InitKeySubs (&pKeySub, &numKeySubs);
5015 ScanWhitespace (&startP);
5017 while (*startP != '<')
5021 *destP++ = *startP++;
5026 (((chlen = mblen ((char *)startP, MB_CUR_MAX)) > 1)
5027 || isalnum (*startP)))
5035 /* find substitution */
5039 for (i=0; i<numKeySubs; i++)
5041 if ((pKeySub[i].lenFrom == startP-pchFirst) &&
5042 (!strncasecmp ((char *)pKeySub[i].pchFrom, (char *)pchFirst,
5043 pKeySub[i].lenFrom)))
5045 pchSub = pKeySub[i].pchTo;
5046 lenSub = strlen((char *)pchSub);
5052 if ((pchSub != NULL) && (lenSub > 0))
5054 memcpy (destP, pchSub, lenSub);
5059 memcpy (destP, pchFirst, startP-pchFirst);
5060 destP += startP-pchFirst;
5064 ScanWhitespace (&startP);
5068 * Skip the key event type.
5070 startP++; /* skip '<' */
5071 while (*startP != '>')
5073 startP += mblen ((char *)startP, MB_CUR_MAX);
5075 startP++; /* skip '>' */
5078 * Copy the KeySym string.
5081 ScanWhitespace (&startP);
5082 while (startP != endP)
5084 *destP++ = *startP++;
5088 } /* END OF FUNCTION ProcessAccelText */
5092 /*************************************<->*************************************
5094 * ProcessCommandLine (argc, argv)
5099 * This function looks for and processes mwm options in the command line
5103 * argc = argument count.
5104 * argv = argument vector.
5109 * Changes global data to based on command line options recognized
5112 *************************************<->***********************************/
5113 #define SCREENS_OPT "-screens"
5114 #define MULTI_SCREEN_OPT "-multiscreen"
5116 void ProcessCommandLine (int argc, char *argv[])
5118 unsigned char *string;
5120 unsigned char *lineP;
5122 for (argnum = 1; argnum < argc; argnum++)
5124 lineP = (unsigned char *) argv[argnum];
5125 if ((string = GetString (&lineP)) == NULL)
5126 /* empty or comment line */
5130 if (!strcmp((char *)string, MULTI_SCREEN_OPT))
5132 wmGD.multiScreen = True;
5133 wmGD.numScreens = ScreenCount (DISPLAY);
5135 else if (!strcmp((char *)string, SCREENS_OPT))
5137 argnum++; /* skip to next arg */
5138 ParseScreensArgument (argc, argv, &argnum, lineP);
5142 } /* END OF FUNCTION ProcessCommandLine */
5145 /*************************************<->*************************************
5147 * ParseScreensArgument (argc, argv, pArgnum, lineP)
5152 * This function processes the ``-screens'' command line argument
5156 * argc = argument count.
5157 * argv = argument vector.
5158 * pArgnum = pointer to argument number where processing left off
5159 * lineP = pointer into argv[*pArgnum] where processing left off
5164 * Changes global data to based on command line options recognized
5165 * + wmGD.screenNames
5167 * Assumes default screenNames are already in place
5169 *************************************<->***********************************/
5171 static void ParseScreensArgument (int argc, char *argv[], int *pArgnum,
5172 unsigned char *lineP)
5174 unsigned char *string;
5179 for (; (*pArgnum < argc) && (sNum < ScreenCount(DISPLAY));
5180 (*pArgnum)++, sNum++)
5182 lineP = (unsigned char *)argv[*pArgnum];
5183 if (*argv[*pArgnum] == '"')
5186 * if Quote, use GetString to strip it
5188 if ((string = GetString (&lineP)) == NULL)
5189 /* empty or comment line */
5196 string = (unsigned char *)argv[*pArgnum];
5199 /* another option, end of screens names */
5204 if (!(wmGD.screenNames[sNum] = (unsigned char *)
5205 XtRealloc ((char*)wmGD.screenNames[sNum],
5206 1 + strlen((char *)string))))
5208 Warning (((char *)GETMESSAGE(60, 31, "Insufficient memory for screen names")));
5209 ExitWM(WM_ERROR_EXIT_VALUE);
5213 strcpy((char *)wmGD.screenNames[sNum], (char *)string);
5221 * remaining screens (if any) get first name specified
5225 lastLen = 1 + strlen((char *)wmGD.screenNames[0]);
5226 for (; sNum < ScreenCount(DISPLAY); sNum++)
5228 if (!(wmGD.screenNames[sNum] = (unsigned char *)
5229 XtRealloc ((char*)wmGD.screenNames[sNum], lastLen)))
5231 Warning (((char *)GETMESSAGE(60, 32, "Insufficient memory for screen names")));
5232 ExitWM(WM_ERROR_EXIT_VALUE);
5236 strcpy((char *)wmGD.screenNames[sNum],
5237 (char *)wmGD.screenNames[0]);
5242 } /* END OF FUNCTION ParseScreensArgument */
5245 /*************************************<->*************************************
5247 * ProcessMotifBindings ()
5252 * This function is used retrieve the motif input bindings
5253 * and put them into a property on the root window.
5256 *************************************<->***********************************/
5257 void ProcessMotifBindings (void)
5259 char fileName[MAXWMPATH+1];
5260 char *bindings = NULL;
5261 char *homeDir = XmeGetHomeDirName();
5264 * Look in the user's home directory for .motifbind
5267 strcpy (fileName, homeDir);
5268 strncat(fileName, "/", MAXWMPATH-strlen(fileName));
5269 strncat(fileName, MOTIF_BINDINGS_FILE, MAXWMPATH-strlen(fileName));
5271 XDeleteProperty (DISPLAY, RootWindow (DISPLAY, 0),
5272 XInternAtom (DISPLAY, "_MOTIF_BINDINGS", False));
5273 XDeleteProperty (DISPLAY, RootWindow (DISPLAY, 0),
5274 XInternAtom (DISPLAY, "_MOTIF_DEFAULT_BINDINGS", False));
5276 if (_XmVirtKeysLoadFileBindings (fileName, &bindings) == True) {
5277 XChangeProperty (DISPLAY, RootWindow(DISPLAY, 0),
5278 XInternAtom (DISPLAY, "_MOTIF_BINDINGS", False),
5279 XA_STRING, 8, PropModeReplace,
5280 (unsigned char *)bindings, strlen(bindings));
5283 _XmVirtKeysLoadFallbackBindings (DISPLAY, &bindings);
5286 } /* END OF FUNCTION ProcessMotifBindings */
5289 /*************************************<->*************************************
5292 * ParseWmFunctionArg (linePP, ix, wmFunc, ppArg, sClientName)
5297 * Parse the function arguments for a window manager function.
5302 * linePP = pointer to line buffer pointer (contains string arg).
5303 * ix = window manager function index (returned by ParseWmFunction)
5304 * pWmFunction = pointer to window manager function destination.
5305 * ppArg = ptr to argument pointer.
5306 * sClientName = string name of client
5311 * *ppArg = arg to pass to window manager function when invoking.
5312 * Return = true on succes, false on some kind of parse error
5317 * functionTable (window manager function table) is indexed with ix
5318 * to get parsing info.
5320 * This function may malloc memory for the returned arg.
5322 * The sClientName is needed for starting some hpterm-based push_recall
5323 * clients. It needs to be passed into the action so the hpterm gets
5324 * named appropriately.
5326 *************************************<->***********************************/
5329 ParseWmFunctionArg (
5330 unsigned char **linePP,
5337 unsigned char *lineP = *linePP;
5338 Boolean bValidArg = True;
5339 unsigned char *str = NULL;
5342 * If this is (possibly) a string argument, put it
5343 * in quotes so that it will be parsed properly.
5345 if ((functionTable[ix].parseProc == ParseWmFuncStrArg) ||
5346 (functionTable[ix].parseProc == ParseWmFuncMaybeStrArg))
5348 if (lineP && *lineP != '"')
5351 * not in quotes, repackage it, escaping the appropriate
5354 str = _DtWmParseMakeQuotedString (lineP);
5363 * Apply the function argument parser.
5365 if ((functionTable[ix].wmFunction != wmFunc) ||
5366 !(*(functionTable [ix].parseProc)) (&lineP, wmFunc, ppArg))
5372 * Add the exec parms if this is an f.action
5374 if ((wmFunc == F_Action) && ppArg && *ppArg)
5376 WmActionArg *pAP = (WmActionArg *) *ppArg;
5380 * allocate more than enough string space to copy
5381 * strings and intervening spaces.
5383 if (sClientName && *sClientName)
5385 /* length of: "name=" + sClientName + NULL */
5386 totLen += 5 + strlen(sClientName) + 1;
5388 if (sTitle && *sTitle)
5390 /* length of: "," + "title=" + sTitle + NULL */
5391 totLen += 1 + 6 + strlen(sTitle) + 1;
5396 pAP->szExecParms = (String) XtMalloc (totLen);
5397 /* start with empty string */
5398 pAP->szExecParms[0] = '\0';
5400 if (sClientName && *sClientName)
5402 strcat (pAP->szExecParms, "name=");
5403 strcat (pAP->szExecParms, sClientName);
5405 if (sTitle && *sTitle)
5407 if (pAP->szExecParms[0] != '\0')
5409 strcat (pAP->szExecParms, ",");
5411 strcat (pAP->szExecParms, "title=");
5412 strcat (pAP->szExecParms, sTitle);
5419 XtFree ((char *) str);
5424 } /* END OF FUNCTION ParseWmFunctionArg */
5427 /*************************************<->*************************************
5429 * SystemCmd (pchCmd)
5434 * This function fiddles with our signal handling and calls the
5435 * system() function to invoke a unix command.
5440 * pchCmd = string with the command we want to exec.
5448 * The system() command is touchy about the SIGCLD behavior. Restore
5449 * the default SIGCLD handler during the time we run system().
5451 *************************************<->***********************************/
5454 SystemCmd (char *pchCmd)
5456 struct sigaction sa;
5457 struct sigaction osa;
5459 (void) sigemptyset(&sa.sa_mask);
5461 sa.sa_handler = SIG_DFL;
5463 (void) sigaction (SIGCHLD, &sa, &osa);
5467 (void) sigaction (SIGCHLD, &osa, (struct sigaction *) 0);
5472 /*************************************<->*************************************
5474 * DeleteTempConfigFileIfAny ()
5479 * This function deletes the temporary config file used to process
5480 * old dtwmrc syntax.
5494 *************************************<->***********************************/
5497 DeleteTempConfigFileIfAny (void)
5499 char pchCmd[MAXWMPATH+1];
5501 if (pConfigStackTop->tempName)
5503 strcpy (pchCmd, "/bin/rm ");
5504 strcat (pchCmd, pConfigStackTop->tempName);
5506 XtFree ((char *) pConfigStackTop->tempName);
5507 pConfigStackTop->tempName = NULL;
5509 if (pConfigStackTop->cppName)
5511 strcpy (pchCmd, "/bin/rm ");
5512 strcat (pchCmd, pConfigStackTop->cppName);
5514 XtFree ((char *) pConfigStackTop->cppName);
5515 pConfigStackTop->cppName = NULL;
5520 /*************************************<->*************************************
5522 * ParseIncludeSet (pSD, lineP)
5531 * cfileP = (global) file pointer to fopened configuration file or NULL
5532 * lineP = pointer to line buffer
5533 * line = (global) line buffer
5534 * linec = (global) line count
5535 * parseP = (global) parse string pointer if cfileP == NULL
5536 * pSD->rootWindow = default root window of display
5540 * linec = (global) line count incremented
5541 * parseP = (global) parse string pointer if cfileP == NULL
5547 *************************************<->***********************************/
5549 static void ParseIncludeSet (WmScreenData *pSD, unsigned char *lineP)
5551 unsigned char *string;
5552 unsigned char *pchName;
5555 * Require leading '{' on the next line.
5558 while ((GetNextLine () != NULL)) /* not EOF nor read error */
5561 ScanWhitespace(&lineP);
5563 if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#'))
5564 /* ignore empty or comment line */
5576 PWarning (((char *)GETMESSAGE(60, 37, "Expected '{'")));
5581 * Found leading "{" or EOF.
5582 * Parse include files until "}" or EOF found.
5584 while ((GetNextLine () != NULL))
5587 if ((*line == '!') || (string = GetString (&lineP)) == NULL)
5588 /* ignore empty or comment lines */
5592 if (*string == '}') /* finished with set. */
5596 pchName = _DtWmParseFilenameExpand (string);
5597 if (pchName && ConfigStackPush (pchName))
5599 ProcessWmFile (pSD, True /* nested */);
5601 XtFree ((char *) pchName);
5610 /*************************************<->*************************************
5612 * ConfigStackInit (pchFileName)
5617 * Initializes the config file processing stack
5621 * pchFileName = name of new file to start parsing
5630 *************************************<->***********************************/
5632 static void ConfigStackInit (char *pchFileName)
5635 pConfigStack = XtNew (ConfigFileStackEntry);
5639 pConfigStackTop = pConfigStack;
5640 pConfigStackTop->fileName = XtNewString (pchFileName);
5641 pConfigStackTop->tempName = NULL;
5642 pConfigStackTop->cppName = NULL;
5643 pConfigStackTop->offset = 0;
5644 pConfigStackTop->pWmPB = wmGD.pWmPB;
5645 pConfigStackTop->wmgdConfigFile = wmGD.configFile;
5646 pConfigStackTop->pIncluder = NULL;
5651 sprintf ((char *)wmGD.tmpBuffer,
5652 (char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"),
5654 Warning ((char *)wmGD.tmpBuffer);
5659 /*************************************<->*************************************
5661 * ConfigStackPush (pchFileName)
5666 * Open an included config file
5670 * pchFileName = name of new file to start parsing
5671 * wmGD.pWmPB = global parse buffer (pickle this)
5675 * wmGD.pWmPB = global parse buffer (new one for new file)
5676 * return = FILE * to open file or NULL
5682 *************************************<->***********************************/
5685 ConfigStackPush (unsigned char *pchFileName)
5687 ConfigFileStackEntry *pEntry;
5688 FILE *pNewFile = NULL;
5690 pEntry = XtNew (ConfigFileStackEntry);
5693 /* save off state of current config file */
5694 pConfigStackTop->offset = ftell (cfileP);
5695 pConfigStackTop->pWmPB = wmGD.pWmPB;
5698 /* set up state of new config file */
5699 pEntry->fileName = XtNewString ((char *)pchFileName);
5700 pEntry->tempName = NULL;
5701 pEntry->cppName = NULL;
5702 pEntry->wmgdConfigFile = (String) pEntry->fileName;
5704 /* set globals for new config file */
5705 wmGD.pWmPB = _DtWmParseNewBuf ();
5706 wmGD.configFile = pEntry->wmgdConfigFile;
5708 /* put new entry onto stack */
5709 pEntry->pIncluder = pConfigStackTop;
5710 pConfigStackTop = pEntry;
5713 pNewFile = cfileP = FopenConfigFile();
5717 /* file open failed! back out */
5723 sprintf ((char *)wmGD.tmpBuffer,
5724 (char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"),
5726 Warning ((char *)wmGD.tmpBuffer);
5734 /*************************************<->*************************************
5745 * pchFileName = name of new file to start parsing
5746 * wmGD.pWmPB = global parse buffer (pickle this)
5750 * wmGD.pWmPB = global parse buffer (new one for new file)
5755 * assumes cfileP is closed already
5757 *************************************<->***********************************/
5759 static void ConfigStackPop (void)
5761 ConfigFileStackEntry *pPrev;
5762 char pchCmd[MAXWMPATH+1];
5764 if (pConfigStackTop != pConfigStack)
5766 pPrev = pConfigStackTop->pIncluder;
5768 _DtWmParseDestroyBuf (wmGD.pWmPB);
5769 if (pConfigStackTop->tempName)
5771 XtFree (pConfigStackTop->tempName);
5773 if (pConfigStackTop->cppName)
5775 strcpy (pchCmd, "/bin/rm ");
5776 strcat (pchCmd, pConfigStackTop->cppName);
5778 XtFree ((char *) pConfigStackTop->cppName);
5779 pConfigStackTop->cppName = NULL;
5781 if (pConfigStackTop->fileName)
5783 XtFree (pConfigStackTop->fileName);
5786 wmGD.pWmPB = pPrev->pWmPB;
5787 wmGD.configFile = pPrev->wmgdConfigFile;
5788 if (pPrev->tempName)
5790 cfileP = fopen (pPrev->tempName, "r");
5792 else if (pPrev->cppName)
5794 cfileP = fopen (pPrev->cppName, "r");
5798 cfileP = fopen (pPrev->fileName, "r");
5802 fseek (cfileP, pPrev->offset, 0);
5806 char msg[MAXWMPATH+1];
5808 sprintf(msg, ((char *)GETMESSAGE(60, 39,
5809 "Could not reopen configuration file %s")),
5814 XtFree ((char *)pConfigStackTop);
5815 pConfigStackTop = pPrev;
5820 /*************************************<->*************************************
5822 * ParseWmFuncActionArg (linePP, wmFunction, pArgs)
5827 * Parses a window manager f.action argument
5832 * linePP = pointer to current line buffer pointer.
5833 * wmFunction = function for which the argument string is intended.
5834 * pArgs = pointer to argument destination.
5839 * linePP = pointer to revised line buffer pointer.
5840 * pArgs = pointer to parsed argument.
5841 * Return = FALSE iff insufficient memory
5847 *************************************<->***********************************/
5849 Boolean ParseWmFuncActionArg (unsigned char **linePP,
5850 WmFunction wmFunction, String *pArgs)
5852 #define WM_ACTION_ARG_INCREMENT 5
5853 #define WM_ACTION_ARG_PAD 256
5854 unsigned char *string;
5859 pAP = XtNew (WmActionArg);
5860 if (pAP && (string = GetString (linePP)) != NULL)
5862 /* Got action name */
5863 pAP->actionName = XtNewString ((char *) string);
5865 /* Get action arguments, if any */
5866 if ((pAP->aap = (DtActionArg *)
5867 XtMalloc (WM_ACTION_ARG_INCREMENT * sizeof (DtActionArg))))
5869 iArgSz = WM_ACTION_ARG_INCREMENT;
5872 while ((string = GetString (linePP)) != NULL)
5874 if ((pAP->aap[pAP->numArgs].u.file.name = (char *)
5875 XtMalloc(1 + strlen((char *)string))))
5877 pAP->aap[pAP->numArgs].argClass = DtACTION_FILE;
5879 /* format the action argument */
5880 pch = pAP->aap[pAP->numArgs].u.file.name;
5883 * Expand environment variable
5885 if (string[0] == '$')
5887 string = (unsigned char *) getenv ((char *)&string[1]);
5895 * Make sure there's room for the new
5899 XtRealloc (pch, (1+strlen((char *)string)));
5900 pAP->aap[pAP->numArgs].u.file.name = pch;
5904 /* !!! No host name processing is done!!! */
5906 strcpy (pch, (char *)string);
5909 if (pAP->numArgs == iArgSz)
5911 /* need to increase our array space */
5912 iArgSz += WM_ACTION_ARG_INCREMENT;
5913 pAP->aap = (DtActionArg *)
5914 XtRealloc((char *)pAP->aap,
5915 (iArgSz * sizeof (DtActionArg)));
5918 break; /* out of memory */
5924 break; /* out of memory */
5929 pAP->szExecParms = NULL;
5930 *pArgs = (String) pAP;
5933 /* NULL string argument */
5940 } /* END OF FUNCTION ParseWmFuncActionArg */
5943 /*************************************<->*************************************
5945 * PreprocessConfigFile (pSD)
5950 * This function runs the configuration file through the C
5956 * pSD = ptr to screen data
5965 *************************************<->***********************************/
5968 PreprocessConfigFile (void)
5970 #define CPP_NAME_SIZE ((L_tmpnam)+1)
5971 char pchCmd[MAXWMPATH+1];
5973 if (wmGD.cppCommand && *wmGD.cppCommand)
5976 * Generate a temp file name.
5978 pConfigStackTop->cppName = XtMalloc (CPP_NAME_SIZE * sizeof(char));
5979 if (pConfigStackTop->cppName)
5981 (void) tmpnam (pConfigStackTop->cppName);
5984 * Build up the command line.
5986 strcpy (pchCmd, wmGD.cppCommand);
5987 strcat (pchCmd, " ");
5988 strcat (pchCmd, pConfigStackTop->fileName);
5989 strcat (pchCmd, " ");
5990 strcat (pchCmd, pConfigStackTop->cppName);
5993 * Run the config file through the converter program
5994 * and send the output to a temp file.
6002 /*************************************<->*************************************
6004 * GetNetworkFileName (char *pchFile)
6009 * This function returns a local representation for a network
6015 * pchFile - pointer to file name of form [<host>:]<path>
6019 * String - ptr to allocated string of local file name. If input
6020 * is not a network file, the a copy of pchFile is returned.
6025 * returned file name should be freed with XtFree().
6027 *************************************<->***********************************/
6030 GetNetworkFileName (char *pchFile)
6037 char *pchName = NULL;
6040 String sReturn = NULL;
6045 pch = strchr (pchFile, ':');
6050 * Expand special chars and find matching file.
6052 pchTok = (char **)shellscan (pchFile, &count, 0);
6054 if ((count == 1) || (count == 2))
6056 /* one match found */
6057 host_part = pchTok[0];
6061 /* several matches found, pick one */
6062 host_part = pchTok[1];
6069 if (host_part != NULL)
6071 pch = strchr (host_part, ':');
6075 * copy the string so we don't munge data
6078 host_part = sName = XtNewString ((String) host_part);
6079 pch = strchr (sName, ':');
6082 * separate the host and file parts of the
6091 * The colon went away. Hmm...
6093 file_part = host_part;
6097 if ((mblen(file_part, MB_CUR_MAX) == 1) &&
6098 (mblen(file_part+1, MB_CUR_MAX) == 1) &&
6099 (*file_part == '~') &&
6100 (*(file_part+1) == '/'))
6103 * Replace '~' with $HOME
6105 homeDir = XmeGetHomeDirName();
6106 len = strlen (host_part) + 1 +
6107 strlen (homeDir) + strlen (file_part) + 1;
6108 pch = (char *) XtMalloc (len);
6109 strcpy (pch, sName);
6111 pch += strlen (pch) + 1;
6112 strcpy (pch, homeDir);
6113 strcat (pch, file_part+1);
6122 * shellscan had a problem with the file name.
6123 * just operate on the name as-is.
6124 * temporarily replace ':' with a NULL
6126 host_part = sName = XtNewString ((String) pchFile);
6127 pch = strchr (sName, ':');
6129 host_part = pchFile;
6133 /* convert to canonical host/file name */
6135 tt_host_file_netfile (host_part, file_part);
6136 if (tt_pointer_error (netfile) == TT_OK)
6138 /* convert to local file name equivalent */
6139 pchName = tt_netfile_file (netfile);
6141 if (tt_pointer_error (pchName) == TT_OK)
6143 sReturn = XtNewString ((String) pchName);
6144 tt_free ((char *)pchName);
6151 XtFree ((char *)sName);
6155 if (sReturn == NULL)
6157 if ((mblen(pchFile, MB_CUR_MAX) == 1) &&
6158 (mblen(pchFile+1, MB_CUR_MAX) == 1) &&
6159 (*pchFile == '~') &&
6160 (*(pchFile+1) == '/'))
6163 * Replace '~' with $HOME
6165 homeDir = XmeGetHomeDirName();
6166 len = strlen (homeDir) + strlen (pchFile) + 1;
6167 sReturn = (char *) XtMalloc (len);
6168 strcpy (sReturn, homeDir);
6169 strcat (sReturn, pchFile+1);
6173 sReturn = XtNewString ((String) pchFile);
6179 /**************************** eof ***************************/