/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC. * ALL RIGHTS RESERVED */ /* * Motif Release 1.2.4 */ /* * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 Hewlett-Packard Company * (c) Copyright 1993, 1994 International Business Machines Corp. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * (c) Copyright 1993, 1994 Novell, Inc. */ /* * (c) Copyright 1987, 1988 DIGITAL EQUIPMENT CORPORATION */ /* * (c) Copyright 1988 MASSACHUSETTS INSTITUTE OF TECHNOLOGY */ /* * Included Files: */ #include "WmGlobal.h" #include "WmResNames.h" #include
#include
#include #include "WmParse.h" #include "WmParseP.h" #include "WmPanelP.h" #include "WmResource.h" #include /* shellscan */ #include #include /* _XmVirtKeysLoadFileBindings, * _XmVirtKeysLoadFallbackBindings */ #include #include #include #include #include #include #include /* for XmeGetHomeDirName */ #include /* maximum string lengths */ #define MAX_KEYSYM_STRLEN 100 #define MAX_EVENTTYPE_STRLEN 20 #define MAX_MODIFIER_STRLEN 20 #define MAX_CONTEXT_STRLEN 20 #define MAX_GROUP_STRLEN 20 #define min(a,b) ((a)>(b) ? (b) : (a)) #define MAXLINE (MAXWMPATH+1) #define MBBSIZ 4096 #define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD) /* * include extern functions */ #include "WmResParse.h" #include "WmWrkspace.h" #include "WmError.h" #include "WmFunction.h" #include "WmImage.h" #include "WmXSMP.h" # include # ifdef X_NOT_STDC_ENV extern int errno; # endif # define HOME_DT_WMRC "/.dt/dtwmrc" # define LANG_DT_WMRC "/dtwmrc" # define SYS_DT_WMRC CDE_CONFIGURATION_TOP "/sys.dtwmrc" /* * Global Variables And Tables: */ static char cfileName[MAXWMPATH+1]; #ifndef NO_MESSAGE_CATALOG char * pWarningStringFile; char * pWarningStringLine; #else char pWarningStringFile[] = "%s: %s on line %d of configuration file %s\n"; char pWarningStringLine[] = "%s: %s on line %d of specification string\n"; #endif #define cfileP (wmGD.pWmPB->pFile) #define parseP (wmGD.pWmPB->pchNext) #define line (wmGD.pWmPB->pchLine) #define linec (wmGD.pWmPB->lineNumber) typedef struct { char *name; unsigned int mask; } MaskTableEntry; static MaskTableEntry modifierStrings[] = { {"none", None}, {"ctrl", ControlMask}, {"shift", ShiftMask}, {"alt", Mod1Mask}, {"meta", Mod1Mask}, {"lock", LockMask}, {"mod1", Mod1Mask}, {"mod2", Mod2Mask}, {"mod3", Mod3Mask}, {"mod4", Mod4Mask}, {"mod5", Mod5Mask}, {NULL, 0}, }; #define ALT_INDEX 3 #define META_INDEX 4 typedef struct { char *event; unsigned int eventType; Boolean (*parseProc)(); unsigned int closure; Boolean fClick; } EventTableEntry; static String GetNetworkFileName (char *pchFile); FILE *FopenConfigFile (void); void SaveMenuAccelerators (WmScreenData *pSD, MenuSpec *newMenuSpec); static void ParseMenuSet (WmScreenData *pSD, unsigned char *lineP); MenuItem *ParseMwmMenuStr (WmScreenData *pSD, unsigned char *menuStr); static MenuItem *ParseMenuItems (WmScreenData *pSD); static Boolean ParseWmLabel (WmScreenData *pSD, MenuItem *menuItem, unsigned char *string); static void ParseWmMnemonic (unsigned char **linePP, MenuItem *menuItem); static Boolean ParseWmAccelerator (unsigned char **linePP, MenuItem *menuItem); int ParseWmFunction (unsigned char **linePP, unsigned int res_spec, WmFunction *pWmFunction); static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction, String *pArgs); void FreeMenuItem (MenuItem *menuItem); static Boolean ParseWmFuncGrpArg (unsigned char **linePP, WmFunction wmFunction, GroupArg *pGroup); static Boolean ParseWmFuncNbrArg (unsigned char **linePP, WmFunction wmFunction, unsigned long *pNumber); void ParseButtonStr (WmScreenData *pSD, unsigned char *buttonStr); static void ParseButtonSet (WmScreenData *pSD, unsigned char *lineP); static Boolean ParseContext (unsigned char **linePP, Context *context, Context *subContext); void ParseKeyStr (WmScreenData *pSD, unsigned char *keyStr); static void ParseKeySet (WmScreenData *pSD, unsigned char *lineP); Boolean ParseBtnEvent (unsigned char **linePP, unsigned int *eventType, unsigned int *button, unsigned int *state, Boolean *fClick); Boolean ParseKeyEvent (unsigned char **linePP, unsigned int *eventType, KeyCode *keyCode, unsigned int *state); static Boolean ParseEvent (unsigned char **linePP, EventTableEntry *table, unsigned int *eventType, unsigned int *detail, unsigned int *state, Boolean *fClick); static Boolean ParseModifiers(unsigned char **linePP, unsigned int *state); static Boolean LookupModifier (unsigned char *name, unsigned int *valueP); static Boolean ParseEventType (unsigned char **linePP, EventTableEntry *table, unsigned int *eventType, Cardinal *ix); static Boolean ParseImmed (unsigned char **linePP, unsigned int closure, unsigned int *detail); static Boolean ParseKeySym (unsigned char **linePP, unsigned int closure, unsigned int *detail); static unsigned int StrToNum(unsigned char *str); static unsigned int StrToHex(unsigned char *str); static unsigned int StrToOct(unsigned char *str); void ScanAlphanumeric (unsigned char **linePP); void ScanWhitespace(unsigned char **linePP); void ToLower (char *string); void PWarning (char *message); static void ProcessAccelText (unsigned char *startP, unsigned char *endP, unsigned char *destP); void ProcessCommandLine (int argc, char *argv[]); static void ParseScreensArgument (int argc, char *argv[], int *pArgnum, unsigned char *lineP); void ProcessMotifBindings (void); static void ParseIncludeSet (WmScreenData *pSD, unsigned char *lineP); static void ConfigStackInit (char *pchFileName); static FILE *ConfigStackPush (unsigned char *pchFileName); static void ConfigStackPop (void); Boolean ParseWmFuncActionArg (unsigned char **linePP, WmFunction wmFunction, String *pArgs); static void PreprocessConfigFile (void); static EventTableEntry buttonEvents[] = { {"btn1down", ButtonPress, ParseImmed, SELECT_BUTTON, FALSE}, {"btn1up", ButtonRelease, ParseImmed, SELECT_BUTTON, FALSE}, {"btn1click", ButtonRelease, ParseImmed, SELECT_BUTTON, TRUE}, {"btn1click2", ButtonPress, ParseImmed, SELECT_BUTTON, TRUE}, {"btn2down", ButtonPress, ParseImmed, DMANIP_BUTTON, FALSE}, {"btn2up", ButtonRelease, ParseImmed, DMANIP_BUTTON, FALSE}, {"btn2click", ButtonRelease, ParseImmed, DMANIP_BUTTON, TRUE}, {"btn2click2", ButtonPress, ParseImmed, DMANIP_BUTTON, TRUE}, {"btn3down", ButtonPress, ParseImmed, BMENU_BUTTON, FALSE}, {"btn3up", ButtonRelease, ParseImmed, BMENU_BUTTON, FALSE}, {"btn3click", ButtonRelease, ParseImmed, BMENU_BUTTON, TRUE}, {"btn3click2", ButtonPress, ParseImmed, BMENU_BUTTON, TRUE}, {"btn4down", ButtonPress, ParseImmed, Button4, FALSE}, {"btn4up", ButtonRelease, ParseImmed, Button4, FALSE}, {"btn4click", ButtonRelease, ParseImmed, Button4, TRUE}, {"btn4click2", ButtonPress, ParseImmed, Button4, TRUE}, {"btn5down", ButtonPress, ParseImmed, Button5, FALSE}, {"btn5up", ButtonRelease, ParseImmed, Button5, FALSE}, {"btn5click", ButtonRelease, ParseImmed, Button5, TRUE}, {"btn5click2", ButtonPress, ParseImmed, Button5, TRUE}, { NULL, 0, (Boolean(*)())NULL, 0, FALSE} }; static EventTableEntry keyEvents[] = { {"key", KeyPress, ParseKeySym, 0, FALSE}, { NULL, 0, (Boolean(*)())NULL, 0, FALSE} }; typedef struct _ConfigFileStackEntry { char *fileName; char *tempName; char *cppName; char *wmgdConfigFile; long offset; DtWmpParseBuf *pWmPB; struct _ConfigFileStackEntry *pIncluder; } ConfigFileStackEntry; static ConfigFileStackEntry *pConfigStack = NULL; static ConfigFileStackEntry *pConfigStackTop = NULL; unsigned int buttonModifierMasks[] = { 0, SELECT_BUTTON_MASK, DMANIP_BUTTON_MASK, BMENU_BUTTON_MASK, Button4Mask, Button5Mask }; /* * FUNCTION PARSER TABLE (function names must be in alphabetic order) */ typedef struct { char * funcName; Context greyedContext; unsigned int resource; long mgtMask; WmFunction wmFunction; Boolean (*parseProc)(); } FunctionTableEntry; /* * NOTE: New functions MUST be added in ALPHABETICAL order. A binary search * is used to find the correct function name. */ FunctionTableEntry functionTable[] = { {"f.action", 0, CRS_ANY, 0, F_Action, ParseWmFuncActionArg}, {"f.beep", 0, CRS_ANY, 0, F_Beep, ParseWmFuncNoArg}, {"f.circle_down", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Circle_Down, ParseWmFuncGrpArg}, {"f.circle_up", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Circle_Up, ParseWmFuncGrpArg}, {"f.create_workspace", 0, CRS_ANY, 0, F_CreateWorkspace, ParseWmFuncNoArg}, {"f.delete_workspace", 0, CRS_ANY, 0, F_DeleteWorkspace, ParseWmFuncNoArg}, {"f.exec", 0, CRS_ANY, 0, F_Exec, ParseWmFuncStrArg}, {"f.focus_color", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Focus_Color, ParseWmFuncNoArg}, {"f.focus_key", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Focus_Key, ParseWmFuncNoArg}, {"f.goto_workspace", 0, CRS_ANY, 0, F_Goto_Workspace, ParseWmFuncStrArg}, {"f.help", 0, CRS_ANY, 0, F_Help, ParseWmFuncStrArg}, /* [helpvolume && helptopic] */ {"f.help_mode", 0, CRS_ANY, 0, F_Help_Mode, ParseWmFuncNoArg}, /* for now */ {"f.kill", F_CONTEXT_ROOT, CRS_ANY, MWM_FUNC_CLOSE, F_Kill, ParseWmFuncNoArg}, {"f.lower", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Lower, ParseWmFuncMaybeStrArg}, {"f.marquee_selection", F_CONTEXT_WINDOW|F_CONTEXT_ICON|F_SUBCONTEXT_IB_IICON, CRS_ANY, 0, F_Marquee_Selection, ParseWmFuncNoArg}, {"f.maximize", F_CONTEXT_ROOT|F_CONTEXT_MAXIMIZE| F_SUBCONTEXT_IB_WICON, CRS_ANY, MWM_FUNC_MAXIMIZE, F_Maximize, ParseWmFuncNoArg}, {"f.menu", 0, CRS_ANY, 0, F_Menu, ParseWmFuncStrArg}, {"f.minimize", F_CONTEXT_ICON|F_CONTEXT_ROOT|F_SUBCONTEXT_IB_IICON, CRS_ANY, MWM_FUNC_MINIMIZE, F_Minimize, ParseWmFuncNoArg}, {"f.move", F_CONTEXT_ROOT, CRS_ANY, MWM_FUNC_MOVE, F_Move, ParseWmFuncNoArg}, {"f.next_cmap", 0, CRS_ANY, 0, F_Next_Cmap, ParseWmFuncNoArg}, {"f.next_key", 0, CRS_ANY, 0, F_Next_Key, ParseWmFuncGrpArg}, {"f.next_workspace", 0, CRS_ANY, 0, F_Next_Workspace, ParseWmFuncNoArg}, {"f.nop", F_CONTEXT_ROOT|F_CONTEXT_ICON|F_CONTEXT_WINDOW| F_SUBCONTEXT_IB_WICON | F_SUBCONTEXT_IB_IICON, CRS_ANY, 0, F_Nop, ParseWmFuncNoArg}, {"f.normalize", F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Normalize, ParseWmFuncNoArg}, {"f.normalize_and_raise", F_CONTEXT_ROOT|F_CONTEXT_NORMAL, CRS_ANY, 0, F_Normalize_And_Raise, ParseWmFuncMaybeStrArg}, {"f.occupy_all", F_CONTEXT_ICONBOX|F_CONTEXT_ROOT, CRS_ANY, DtWM_FUNC_OCCUPY_WS, F_AddToAllWorkspaces, ParseWmFuncNoArg}, {"f.pack_icons", 0, CRS_ANY, 0, F_Pack_Icons, ParseWmFuncNoArg}, {"f.pass_keys", 0, CRS_ANY, 0, F_Pass_Key, ParseWmFuncNoArg}, {"f.post_wmenu", 0, CRS_BUTTON|CRS_KEY, 0, F_Post_SMenu, ParseWmFuncNoArg}, {"f.prev_cmap", 0, CRS_ANY, 0, F_Prev_Cmap, ParseWmFuncNoArg}, {"f.prev_key", 0, CRS_ANY, 0, F_Prev_Key, ParseWmFuncGrpArg}, {"f.prev_workspace", 0, CRS_ANY, 0, F_Prev_Workspace, ParseWmFuncNoArg}, {"f.quit_mwm", F_CONTEXT_ICON|F_CONTEXT_WINDOW, CRS_ANY, 0, F_Quit_Mwm, ParseWmFuncNoArg}, {"f.raise", F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Raise, ParseWmFuncMaybeStrArg}, {"f.raise_lower", F_CONTEXT_ROOT | F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Raise_Lower, ParseWmFuncNoArg}, {"f.refresh", 0, CRS_ANY, 0, F_Refresh, ParseWmFuncNoArg}, {"f.refresh_win", F_CONTEXT_ICON|F_CONTEXT_ROOT, CRS_ANY, 0, F_Refresh_Win, ParseWmFuncNoArg}, {"f.remove", F_CONTEXT_ROOT, CRS_ANY, DtWM_FUNC_OCCUPY_WS, F_Remove, ParseWmFuncNoArg}, {"f.resize", F_CONTEXT_ICON|F_CONTEXT_ROOT| F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, CRS_ANY, MWM_FUNC_RESIZE, F_Resize, ParseWmFuncNoArg}, {"f.restart", F_CONTEXT_ICON|F_CONTEXT_WINDOW, CRS_ANY, 0, F_Restart, ParseWmFuncStrArg}, {"f.restore", F_CONTEXT_ROOT|F_CONTEXT_NORMAL|F_SUBCONTEXT_IB_WICON, CRS_ANY, 0, F_Restore, ParseWmFuncNoArg}, {"f.restore_and_raise", F_CONTEXT_ROOT|F_CONTEXT_NORMAL, CRS_ANY, 0, F_Restore_And_Raise, ParseWmFuncNoArg}, {"f.screen", 0, CRS_ANY, 0, F_Screen, ParseWmFuncStrArg}, {"f.send_msg", F_CONTEXT_ROOT, CRS_ANY, 0, F_Send_Msg, ParseWmFuncNbrArg}, {"f.separator", 0, CRS_MENU, 0, F_Separator, ParseWmFuncNoArg}, {"f.set_behavior", 0, CRS_ANY, 0, F_Set_Behavior, ParseWmFuncNoArg}, {"f.set_context", 0, CRS_ANY, 0, F_Set_Context, ParseWmFuncNbrArg}, {"f.title", 0, CRS_MENU, 0, F_Title, ParseWmFuncNoArg}, {"f.toggle_frontpanel", 0, CRS_ANY, 0, F_Toggle_Front_Panel, ParseWmFuncNoArg}, {"f.version", 0, CRS_ANY, 0, F_Version, ParseWmFuncNoArg}, #ifdef OLD {"f.workspace_presence",F_CONTEXT_ICON|F_CONTEXT_ROOT|F_CONTEXT_ICONBOX| F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON, #endif /* OLD */ {"f.workspace_presence", F_CONTEXT_ROOT|F_CONTEXT_ICONBOX| F_SUBCONTEXT_IB_WICON, CRS_ANY, DtWM_FUNC_OCCUPY_WS, F_Workspace_Presence, ParseWmFuncNoArg}, #if defined(DEBUG) {"f.zz_debug", 0, CRS_ANY, 0, F_ZZ_Debug, ParseWmFuncStrArg}, #endif /* DEBUG */ }; /* * NOTE: New functions MUST be added in ALPHABETICAL order. A binary search * is used to find the correct function name. */ #define WMFUNCTIONTABLESIZE (sizeof(functionTable)/sizeof(functionTable[0])) /* * Be sure to update these define, whenever adding/deleting a function. */ int F_ACTION_INDEX; int F_EXEC_INDEX; int F_NOP_INDEX; /******************************<->************************************* * * void GetFunctionTableValues (int *execIndex, int *nopIndex, * int *actionIndex) * * Description: * ----------- * This routine dynamically computes the size of the functionTable[], * and the indices for key functions, such as f.exec, f.action, and * f.nop * * Inputs: * ------ * We are setting the values of F_EXEC_INDEX, F_ACTION_INDEX, * and F_NOP_INDEX on a global level. The addresses * for same are passed in. * * Outputs: * ------- * * Comments: * -------- * This routine calls smaller routines for efficiency sake. * ******************************<->***********************************/ void GetFunctionTableValues (int *execIndex, int *nopIndex, int *actionIndex) { GetExecIndex (WMFUNCTIONTABLESIZE, execIndex); GetActionIndex (WMFUNCTIONTABLESIZE, actionIndex); GetNopIndex (WMFUNCTIONTABLESIZE, nopIndex); } /* END OF FUNCTION GetFunctionTableValues */ /******************************<->************************************* * * * Description: * ----------- * * Inputs: * ------ * Outputs: * ------- * * Comments: * -------- * ******************************<->***********************************/ void GetExecIndex (int tableSize, int *execIndex) { int i; for (i = 0; i < (tableSize); i++) { if (!(strcmp ("f.exec", functionTable[i].funcName))) { *execIndex = i; return; } else { *execIndex = 0; } } } /* END OF FUNCTION GetExecIndex */ /******************************<->************************************* * * * Description: * ----------- * * Inputs: * ------ * Outputs: * ------- * * Comments: * -------- * ******************************<->***********************************/ void GetActionIndex (int tableSize, int *actionIndex) { int i; for (i = 0; i < (tableSize); i++) { if (!(strcmp ("f.action", functionTable[i].funcName))) { *actionIndex = i; return; } else { *actionIndex = 0; } } } /* END OF FUNCTION GetActionIndex */ /******************************<->************************************* * * * Description: * ----------- * * Inputs: * ------ * Outputs: * ------- * * Comments: * -------- * ******************************<->***********************************/ void GetNopIndex (int tableSize, int *nopIndex) { int i; for (i = 0; i < (tableSize); i++) { if (!(strcmp ("f.nop", functionTable[i].funcName))) { *nopIndex = i; return; } else { *nopIndex = 0; } } } /* END OF FUNCTION GetNopIndex */ /*************************************<->************************************* * * void * WmDtGetHelpArgs () * * * Description: * ----------- * Get Help Args * * Inputs: * ------ * * Outputs: * ------- * * * Comments: * -------- * None. * *************************************<->***********************************/ void WmDtGetHelpArgs(char *args, unsigned char* volume, unsigned char* topic, int *argsCount) { unsigned char *string; unsigned char *lineP; cfileP = NULL; linec = 0; parseP = (unsigned char*) args; if(GetNextLine () != NULL) { *argsCount = 0; lineP = line; if ((string = GetSmartSMString (&lineP)) != NULL) { *argsCount = *argsCount + 1; strcpy ((char*)topic, (char*)string); } if ((string = GetSmartSMString (&lineP)) != NULL) { *argsCount = *argsCount + 1; strcpy ((char*)volume, (char *)string); } } } /* END OF FUNCTION WmDtGetHelpArgs */ /******************************<->************************************* * * void * ParseDtSessionHints (pSD, property) * * * Description: * ----------- * This function parses a DtSessionHints string and returns a list of * DtSessionItems array. The string should have the syntax: * * * * Inputs: * ------ * line = (global) line buffer * pSD->rootWindow = default root window of display * * * Outputs: * ------- * Return = * * * Comments: * -------- * None. * *************************************<->***********************************/ void ParseDtSessionHints (WmScreenData *pSD, unsigned char *property) { cfileP = NULL; linec = 0; parseP = property; ParseSessionItems (pSD); } /* END OF FUNCTION ParseDtSessionHints */ /*************************************<->************************************* * * FindDtSessionMatch(commandArgc, commandArgv, pCD, pSD, pWorkSpaceList, * clientMachine) * * Description: * ----------- * Try to find a match for this client in the session hints. * Set up client-session data. * * * Inputs: * ------ * commandArgc - argument count * commandArgv - WM_COMMAND argument vector * pCD - pointer to client data * pSD - pointer to screen data * pWorkspaceList - pointer to a list of workspaces (to be returned) * clientMachine - string for -host option in session hints * * Outputs: * ------- * *pCD - client data (may be modified) * FindDtSessionMatch - returns True if a match for this client * was found in the session hints. * *pWorkspaceList - list of workspaces this client should be put * into. (needs to be freed) * * * Comments: * -------- * Various pieces of client state (in pCD) are reset when a match * is found. * * The caller must free *pWorkspaceList when done. * *************************************<->***********************************/ Boolean FindDtSessionMatch(int commandArgc, char **commandArgv, ClientData *pCD, WmScreenData *pSD, char **pWorkSpaceList, char *clientMachine) { int count; int relCount; int argNum; SessionGeom *sessionGeom; for (count = 0; count < pSD->totalSessionItems; count++) { if (!pSD->pDtSessionItems[count].processed && pSD->pDtSessionItems[count].commandArgc == commandArgc) { if ((clientMachine) && (pSD->pDtSessionItems[count].clientMachine) && (strcmp(clientMachine, pSD->pDtSessionItems[count].clientMachine))) { /* * This item has clientMachine string but the * clientMachine does not match. */ continue; } for (argNum = 0; argNum < commandArgc ; argNum++) { if(strcmp(commandArgv[argNum], pSD->pDtSessionItems[count].commandArgv[argNum])) { /* * One mismatch and we quit looking at this item. * Decrement argNum so a mismatch on the last item * will not look like a match below when comparing * argNum == commandArgc */ argNum--; break; } } if (argNum == commandArgc) { /* * Made it through all strings so this is a match */ pSD->pDtSessionItems[count].processed = True; pSD->remainingSessionItems --; pCD->clientFlags |= SM_LAUNCHED; /* * Free strings malloc'd for commandArgv for this item */ for (relCount = 0; relCount < commandArgc; relCount++) { XtFree(pSD->pDtSessionItems[count].commandArgv[relCount]); } XtFree((char *)pSD->pDtSessionItems[count].commandArgv); if(pSD->pDtSessionItems[count].clientState) { pCD->clientState = pSD->pDtSessionItems[count].clientState; pCD->clientFlags |= SM_CLIENT_STATE; } if(pSD->pDtSessionItems[count].sessionGeom) { sessionGeom = pSD->pDtSessionItems[count].sessionGeom; if (sessionGeom->flags & XValue) { pCD->clientX = sessionGeom->clientX; pCD->clientFlags |= SM_X; } if (sessionGeom->flags & YValue) { pCD->clientY = sessionGeom->clientY; pCD->clientFlags |= SM_Y; } if (sessionGeom->flags & WidthValue) { pCD->clientWidth = sessionGeom->clientWidth; pCD->clientFlags |= SM_WIDTH; } if (sessionGeom->flags & HeightValue) { pCD->clientHeight = sessionGeom->clientHeight; pCD->clientFlags |= SM_HEIGHT; } /* * Free SessionGeom malloc'd space for this item */ XtFree((char *)pSD->pDtSessionItems[count].sessionGeom); } if(pSD->pDtSessionItems[count].clientMachine) { /* * Free clientMachine malloc'd space for this item */ XtFree((char *) pSD->pDtSessionItems[count].clientMachine); pSD->pDtSessionItems[count].clientMachine = NULL; } if(pSD->pDtSessionItems[count].workspaces) { /* * The caller is responsible for freeing this * data. */ *pWorkSpaceList = pSD->pDtSessionItems[count].workspaces; } if(pSD->remainingSessionItems == 0) { /* * Free the whole pSD->pDtSessionHints structure */ XtFree((char *)pSD->pDtSessionItems); } return (True); } } /* not processed and argc's are the same */ } /* for */ return (False); } /* END OF FUNCTION FindDtSessionMatch */ /*************************************<->************************************* * * void * ParseSessionItems (pSD) * * * Description: * ----------- * Parse session items * * Inputs: * ------ * pSD = pointer to screen data * cfileP = (global) file pointer to NULL * line = (global) line buffer * linec = (global) line count * parseP = (global) parse string pointer if cfileP == NULL * pSD->rootWindow = default root window of display * * Outputs: * ------- * linec = (global) line count incremented * parseP = (global) parse string pointer if cfileP == NULL * * * Comments: * -------- * None. * *************************************<->***********************************/ void ParseSessionItems (WmScreenData *pSD) { unsigned char *string; unsigned char *lineP; int count; /* * Parse property string */ if(GetNextLine () != NULL) { pSD->totalSessionItems = atoi((char *)line); pSD->remainingSessionItems = pSD->totalSessionItems; } if((pSD->totalSessionItems < 1) || !GetSessionHintsInfo(pSD, pSD->totalSessionItems)) { /* * No items or couldn't allocate space */ return; } count = 0; while ((count < pSD->totalSessionItems) && (GetNextLine () != NULL)) { lineP = line; while ((string = GetSmartSMString (&lineP)) != NULL) { if (!strcmp((char *)string, "-geometry")) { /* * Parse geometry if it is present */ string = GetSmartSMString(&lineP); ParseSessionGeometry (pSD, count, string); } else if (!strcmp((char *)string, "-state")) { /* * Parse the state if it is present */ string = GetSmartSMString(&lineP); ParseSessionClientState (pSD, count, string); } else if (!strcmp((char *)string, "-workspaces")) { /* * Parse the workspaces string if it is present */ string = GetSmartSMString(&lineP); ParseSessionWorkspaces (pSD, count, string); } else if (!strcmp((char *)string, "-cmd")) { /* * Parse the command string if it is present */ string = GetSmartSMString(&lineP); ParseSessionCommand (pSD, count, &string); } else if (!strcmp((char *)string, "-host")) { /* * Parse the host string if it is present */ string = GetSmartSMString(&lineP); ParseSessionHost (pSD, count, string); } } /* while GetSmartSMString */ count++; } /* while GetNextLine */ } /* END OF FUNCTION ParseSessionItems */ /*************************************<->************************************* * * ParseSessionClientState (pSD, count, string); * * Description: * ----------- * Inputs: * ------ * Outputs: * ------- * Comments: * -------- * *************************************<->***********************************/ void ParseSessionClientState (WmScreenData *pSD, int count, unsigned char *string) { if(!strcmp((char *)string, "NormalState")) { pSD->pDtSessionItems[count].clientState = NORMAL_STATE; } else if(!strcmp((char *)string, "IconicState")) { pSD->pDtSessionItems[count].clientState = MINIMIZED_STATE; } } /* END OF FUNCTION ParseSessionClientState */ /*************************************<->************************************* * * ParseSessionGeometry (pSD, count, string) * * Description: * ----------- * Inputs: * ------ * Outputs: * ------- * Comments: * -------- * *************************************<->***********************************/ void ParseSessionGeometry (WmScreenData *pSD, int count, unsigned char *string) { SessionGeom *pTmpSessionGeom; int mask /* = 0 */; int X, Y, width, height; X = Y = width = height = 0; /* * XParseGeometry */ mask = XParseGeometry((char *)string, &X, &Y, (unsigned int *)&width, (unsigned int *)&height); if (mask) { /* * Allocate space for the geometry structure */ if ((pTmpSessionGeom = (SessionGeom *)XtMalloc (sizeof (SessionGeom))) == NULL) { Warning (((char *)GETMESSAGE(60, 1, "Insufficient memory for session geometry item"))); return; } pTmpSessionGeom->flags = mask; pTmpSessionGeom->clientX = X; pTmpSessionGeom->clientY = Y; pTmpSessionGeom->clientWidth = width; pTmpSessionGeom->clientHeight = height; pSD->pDtSessionItems[count].sessionGeom = pTmpSessionGeom; } } /* END OF FUNCTION ParseSessionGeometry */ /*************************************<->************************************* * * void * ParseSessionWorkspaces (pSD, count, string) * * Description: * ----------- * Inputs: * ------ * Outputs: * ------- * Comments: * -------- * *************************************<->***********************************/ void ParseSessionWorkspaces (WmScreenData *pSD, int count, unsigned char *string) { /* * Allocate space for the workspaces string */ if ((pSD->pDtSessionItems[count].workspaces = (String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) == NULL) { Warning (((char *)GETMESSAGE(60, 2, "Insufficient memory for workspaces list in session item"))); return; } strcpy(pSD->pDtSessionItems[count].workspaces, (char *)string); } /* END OF FUNCTION ParseSessionWorkspaces */ /*************************************<->************************************* * * void * ParseSessionCommand (pSD, count, string) * * Description: * ----------- * Inputs: * ------ * Outputs: * ------- * Comments: * -------- * *************************************<->***********************************/ void ParseSessionCommand (WmScreenData *pSD, int count, unsigned char **commandString) { #define ARG_AMT 100 int xindex; unsigned char **argv; int argc = 0; int iSizeArgv; unsigned char *string; argv = (unsigned char **) XtMalloc (ARG_AMT * sizeof(char *)); iSizeArgv = ARG_AMT; while ((string = GetSmartSMString (commandString)) != NULL) { /* * Get pointers to strings in command line and count them */ argv[argc] = string; argc ++; if (argc >= iSizeArgv) { iSizeArgv += ARG_AMT; argv = (unsigned char **) XtRealloc ((char *)argv, (iSizeArgv * sizeof(char *))); } } if ((pSD->pDtSessionItems[count].commandArgv = (char **)XtMalloc ((argc) * sizeof(char * ))) == NULL) { /* * Allocate space for saved argv */ Warning (((char *)GETMESSAGE(60, 3, "Insufficient memory for commandArgv array"))); } else { pSD->pDtSessionItems[count].commandArgc = argc; for (xindex = 0; xindex < argc ; xindex++) { if ((pSD->pDtSessionItems[count].commandArgv[xindex] = (String) XtMalloc ((unsigned int) (strlen((char *)argv[xindex]) + 1))) == NULL) { /* * Allocate space for the next command segment. */ Warning (((char *)GETMESSAGE(60, 4, "Insufficient memory for commandArgv item"))); } else { strcpy(pSD->pDtSessionItems[count].commandArgv[xindex], (char *)argv[xindex]); } } } XtFree ((char *) argv); } /* END OF FUNCTION ParseSessionCommand */ /*************************************<->************************************* * * void * ParseSessionHost (pSD, count, string) * * Description: * ----------- * Inputs: * ------ * Outputs: * ------- * Comments: * -------- * *************************************<->***********************************/ void ParseSessionHost (WmScreenData *pSD, int count, unsigned char *string) { /* * Allocate space for the workspaces string */ if ((pSD->pDtSessionItems[count].clientMachine = (String)XtMalloc ((unsigned int) (strlen((char *)string) + 1))) == NULL) { Warning (((char *)GETMESSAGE(60, 38, "Insufficient memory for host name in session item"))); return; } strcpy(pSD->pDtSessionItems[count].clientMachine, (char *)string); } /* END OF FUNCTION ParseSessionHost */ /*************************************<->************************************* * * GetSessionHintsInfo (pSD, numItems) * * Description: * ----------- * Inputs: * ------ * Outputs: * ------- * Comments: * -------- * *************************************<->***********************************/ Boolean GetSessionHintsInfo (WmScreenData *pSD, long numItems) { if ((pSD->pDtSessionItems = (DtSessionItem *)XtMalloc (numItems * sizeof (DtSessionItem))) == NULL) { Warning (((char *)GETMESSAGE(60, 5, "Insufficient memory for Dt Session Hints"))); return(False); } memset ((char *)pSD->pDtSessionItems, 0, numItems * sizeof (DtSessionItem)); return(True); } /* END OF FUNCTION GetSessionHintsInfo */ /*************************************<->************************************* * * PeekAhead (currentChar, currentLev) * * * Description: * ----------- * Returns a new level value if this is a new nesting level of quoted string * Otherwise it returns a zero * * * Inputs: * ------ * currentChar = current position in the string * currentLev = current level of nesting * * * Outputs: * ------- * Returns either a new level of nesting or zero if the character is copied in * * * Comments: * -------- * *************************************<->***********************************/ unsigned int PeekAhead(unsigned char *currentChar, unsigned int currentLev) { Boolean done = False; unsigned int tmpLev = 1; unsigned int chlen; while (((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\')) && (done == False)) { currentChar++; if(((chlen = mblen ((char *)currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))) { tmpLev++; if(*currentChar == '"') { done = True; } else { currentChar++; } } } /* * Figure out if this is truly a new level of nesting - else ignore it * This section probably could do some error checking and return -1 * If so, change type of routine from unsigned int to int */ if(done == True) { return(tmpLev); } else { return(0); } } /* END OF FUNCTION PeekAhead */ /*************************************<->************************************* * * SyncModifierStrings (fileName) * * Description: * ----------- * This function updates modifierStrings table so that Mwm uses the correct * modifier to keysym mapping. Specifically, fix up the Alt and Meta bindings. * * Inputs: * ------ * fileName * * Outputs: * ------- * fileName * * Comments: * -------- * *************************************<->***********************************/ void SyncModifierStrings(void) { XModifierKeymap *map; int i, j, k = 0; map = XGetModifierMapping (DISPLAY); for (i = 0; i < 8; i++) { for (j = 0; j < map->max_keypermod; j++) { if (map->modifiermap[k]) { KeySym ks = XkbKeycodeToKeysym(DISPLAY, map->modifiermap[k], 0, 0); char *nm = XKeysymToString(ks); /* Compare, ignoring the trailing '_L' or '_R' in keysym */ if (nm && !strncmp("Alt", nm, 3)) { modifierStrings[ALT_INDEX].mask = (1<************************************* * * ProcessWmFile () * * * Description: * ----------- * This function reads the mwm resource description file and processes the * resources that are described. * * * Inputs: * ------ * wmGD.bitmapDirectory = bitmapDirectory resource value * pSD->buttonBindings = buttonBindings resource value * wmGD.configFile = configuration file resource value * pSD->keyBindings = keyBindings resource value * wmGD.rootWindow = default root window of display * HOME = environment variable for home directory * functionTable = window manager function parse table * * * Outputs: * ------- * wmGD.buttonSpecs = list of button binding specifications * wmGD.keySpecs = list of key binding specification * wmGD.menuSpecs = list of menu specifications * *wmGD.acceleratorMenuSpecs = initialized array of (MenuSpec *) * wmGD.acceleratorMenuCount = 0 * * * Comments: * -------- * If there are more than MAXLINE characters on a line the excess characters * are truncated. * *************************************<->***********************************/ #define MENU_SPEC "menu" #define BUTTON_SPEC "buttons" #define KEY_SPEC "keys" #define FRONT_PANEL_SPEC DTWM_FP_PANEL_OLD #define DROP_EFFECTS_SPEC DTWM_FP_DROP_EFFECTS #define PANEL_SPEC DTWM_FP_PANEL #define BOX_SPEC DTWM_FP_BOX #define CONTROL_SPEC DTWM_FP_CONTROL #define INCLUDE_SPEC DTWM_FP_INCLUDE #define ANIMATION_SPEC DTWM_FP_ANIMATION #define SWITCH_SPEC DTWM_FP_SWITCH void ProcessWmFile (WmScreenData *pSD, Boolean bNested) { unsigned char *lineP; unsigned char *string; unsigned int n; MenuSpec *menuSpec; if (!bNested) { /* * Initialize global data values that are set based on data in * the mwm resource description file. */ pSD->buttonSpecs = NULL; pSD->keySpecs = NULL; pSD->menuSpecs = NULL; /**** hhhhhhhhhhhh ******/ GetFunctionTableValues (&F_EXEC_INDEX, &F_NOP_INDEX, &F_ACTION_INDEX); /* * Find and parse the default system menu string, if it exists. */ cfileP = NULL; linec = 0; if (((parseP = (unsigned char *) builtinSystemMenu) != NULL) && (GetNextLine () != NULL)) { lineP = line; ParseMenuSet (pSD, lineP); } linec = 0; if (((parseP = (unsigned char *) builtinRootMenu) != NULL) && (GetNextLine () != NULL)) { lineP = line; ParseMenuSet (pSD, lineP); } if (wmGD.useFrontPanel && !wmGD.dtSD && (XDefaultScreen (wmGD.display) == pSD->screen)) { wmGD.dtSD = pSD; /* only one per display */ } /* * Find and associate a stream with the window manager resource * description file. */ if ((cfileP = FopenConfigFile ()) == NULL) { if (!wmGD.useStandardBehavior) Warning (((char *)GETMESSAGE(60, 6, "Cannot open configuration file"))); return; } } /* end if (!bNested) */ /* * Parse the information in the configuration file. * If there are more than MAXLINE characters on a line the excess are * truncated. */ linec = 0; while ((GetNextLine () != NULL)) /* not EOF nor read error */ { lineP = line; if ((*line == '!') || (string = GetString (&lineP)) == NULL) /* empty or comment line */ { continue; } ToLower ((char *)string); if (!strcmp ((char *)string, MENU_SPEC)) { ParseMenuSet (pSD, lineP); } else if (!strcmp ((char *) string, BUTTON_SPEC)) { ParseButtonSet (pSD, lineP); } else if (!strcmp ((char *) string, KEY_SPEC)) { ParseKeySet (pSD, lineP); } else if (!strcmp ((char *)string, INCLUDE_SPEC)) { ParseIncludeSet (pSD, lineP); } } fclose (cfileP); /* * Create and initialize the pSD->acceleratorMenuSpecs array. * This assumes we create pointers to MenuSpecs within ProcessWmFile(). * Set pSD->acceleratorMenuCount to 0. */ /* count the number of menu specifications */ n = 0; menuSpec = pSD->menuSpecs; while (menuSpec) { n++; menuSpec = menuSpec->nextMenuSpec; } /* allocate the array and initialize to zeros */ pSD->acceleratorMenuSpecs = NULL; if (n) { pSD->acceleratorMenuSpecs = (MenuSpec **) XtCalloc (n, sizeof (MenuSpec *)); if (pSD->acceleratorMenuSpecs == NULL) { Warning (((char *)GETMESSAGE(60, 7, "Insufficient memory for menu accelerators"))); } } pSD->acceleratorMenuCount = 0; } /* END OF FUNCTION ProcessWmFile */ /**** This function stolen from Xt/Intrinsic.c ****/ /* The implementation of this routine is operating system dependent */ static char *ExtractLocaleName(String lang) { #ifdef hpux /* hpux-specific parsing of the locale string */ #define MAXLOCALE 64 /* buffer size of locale name */ char *start; char *end; int len; static char buf[MAXLOCALE]; /* If lang has a substring ":;", extract * from the first such occurrence as the locale name. */ start = lang; if (start = strchr (lang, ':')) { start++; if (end = strchr (start, ';')) { len = end - start; strncpy(buf, start, len); *(buf + len) = '\0'; lang = buf; } } #endif /* hpux */ return lang; } #define RC_CONFIG_SUBDIR "/config/" #define RC_DEFAULT_CONFIG_SUBDIR "/config/C" /*************************************<->************************************* * * FopenConfigFile () * * * Description: * ----------- * This function searches for, opens, and associates a stream with the mwm * resource description file, * * * Inputs: * ------ * wmGD.configFile = configuration file resource value. * HOME = environment variable for home directory * * * Outputs: * ------- * Return = If successful, a pointer to the FILE structure associated with * the configuration file. Otherwise, NULL. * * * Comments: * -------- * None. * *************************************<->***********************************/ FILE *FopenConfigFile (void) { char *LANG, *LANGp; FILE *fileP; char *homeDir = XmeGetHomeDirName(); Boolean stackPushed; /* * Get the LANG environment variable * make copy since another call to getenv will blast the value. */ LANGp = setlocale(LC_CTYPE, NULL); /* * setlocale not guaranteed to return $LANG -- extract * something usable. */ LANGp = ExtractLocaleName (LANGp); if ((LANGp == NULL) || (strlen(LANGp) == 0)) { LANG = NULL; } else { if ((LANG = (char *) XtMalloc(strlen(LANGp) +1)) == NULL) { PWarning (((char *)GETMESSAGE(60, 41, "Insufficient memory to get LANG environment variable."))); return(NULL); } strcpy(LANG, LANGp); } /* * To get a name for the file first look at the value of the configFile * resource. Interpret "~/.." as relative to the user's home directory. * Use the LANG variable if set and .mwmrc is in $HOME/$LANG/.mwmrc */ if (pConfigStackTop && pConfigStackTop->tempName) { fileP = fopen (pConfigStackTop->tempName, "r"); return (fileP); } stackPushed = (pConfigStackTop && (pConfigStackTop != pConfigStack)); fileP = NULL; cfileName[0] = '\0'; if ((wmGD.configFile != NULL) && (wmGD.configFile[0] != '\0')) /* pointer to nonNULL string */ { if ((wmGD.configFile[0] == '~') && (wmGD.configFile[1] == '/')) /* handle "~/..." */ { strcpy (cfileName, homeDir); if (LANG != NULL) { strncat(cfileName, "/", MAXWMPATH-strlen(cfileName)); strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName)); } strncat(cfileName, &(wmGD.configFile[1]), MAXWMPATH-strlen(cfileName)); if ((fileP = fopen (cfileName, "r")) != NULL) { if (LANG != NULL) { XtFree(LANG); LANG = NULL; } } else { /* * Just try $HOME/.mwmrc */ strcpy (cfileName, homeDir); strncat(cfileName, &(wmGD.configFile[1]), MAXWMPATH-strlen(cfileName)); if ((fileP = fopen (cfileName, "r")) != NULL) { if (LANG != NULL) { XtFree(LANG); LANG = NULL; } } } } else /* relative to current directory or absolute */ { char *pch; pch = (char *) GetNetworkFileName (wmGD.configFile); if ((fileP = fopen (pch, "r")) != NULL) { strncpy (cfileName, pch, MAXWMPATH); } XtFree (pch); if ((fileP == NULL) && !stackPushed) { if ((fileP = fopen (wmGD.configFile, "r")) != NULL) { if (LANG != NULL) { XtFree(LANG); LANG = NULL; } return(fileP); } } else if ((fileP == NULL) && stackPushed) { strcpy (cfileName, wmGD.configFile); } } } if ((fileP == NULL) && !stackPushed) { /* * The configFile resource didn't do it for us. * First try HOME_MWMRC, then try SYS_MWMRC . */ #define HOME_MWMRC "/.mwmrc" #define SLASH_MWMRC "/system.mwmrc" strcpy (cfileName, homeDir); if (MwmBehavior) { /* * * Looking for $HOME/$LANG/.mwmrc * --or--if $LANG is NULL * Looking for $HOME/.mwmrc * */ if (LANG != NULL) { strncat(cfileName, "/", MAXWMPATH-strlen(cfileName)); strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName)); } strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName)); } else { /* * * Looking for $HOME/.dt/$LANG/dtwmrc * * --or--if $LANG is NULL-- * * Looking for $HOME/.dt/dtwmrc * */ strncat(cfileName, "/.dt/", MAXWMPATH-strlen(cfileName)); if (LANG != NULL) { strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName)); } strncat(cfileName, LANG_DT_WMRC, MAXWMPATH - strlen(cfileName)); } if ((fileP = fopen (cfileName, "r")) != NULL) { if (LANG != NULL) { XtFree(LANG); LANG = NULL; } } else { /* * Just try $HOME/.mwmrc */ strcpy (cfileName, homeDir); if (MwmBehavior) { /* * Just try $HOME/.mwmrc */ strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName)); } else { /* * Just try $HOME/.dt/dtwmrc */ strncat(cfileName, HOME_DT_WMRC, MAXWMPATH - strlen(cfileName)); } if ((fileP = fopen (cfileName, "r")) != NULL) { if (LANG != NULL) { XtFree(LANG); LANG = NULL; } } } } #define DTLIBDIR CDE_INSTALLATION_TOP #define DTADMINDIR CDE_CONFIGURATION_TOP #define SLASH_DT_WMRC "/sys.dtwmrc" if ((fileP == NULL) && !stackPushed) { /* * No home-based config file. Try the admin directory. */ strcpy(cfileName, DTADMINDIR); strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName)); strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName)); strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName)); if (((fileP = fopen (cfileName, "r")) == NULL) && LANG && *LANG) { /* Try it with no LANG */ strcpy(cfileName, DTADMINDIR); strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName)); strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName)); } if ((fileP = fopen (cfileName, "r")) != NULL) { XtFree(LANG); LANG = NULL; } } if ((fileP == NULL) && !stackPushed) { #ifndef LIBDIR #define LIBDIR "/usr/lib/X11" #endif if (LANG != NULL) { if (MwmBehavior) { strcpy(cfileName, LIBDIR); strncat(cfileName, "/", MAXWMPATH-strlen(cfileName)); strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName)); strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName)); } else { strcpy(cfileName, DTLIBDIR); strncat(cfileName, RC_CONFIG_SUBDIR, MAXWMPATH-strlen(cfileName)); strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName)); strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName)); } if ((fileP = fopen (cfileName, "r")) != NULL) { XtFree(LANG); LANG = NULL; } } if ((fileP == NULL) && !stackPushed) { if (MwmBehavior) { strcpy(cfileName, LIBDIR); strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName)); fileP = fopen (cfileName, "r"); } else { strcpy(cfileName, DTLIBDIR); strncat(cfileName, RC_DEFAULT_CONFIG_SUBDIR, MAXWMPATH - strlen(cfileName)); strncat(cfileName, SLASH_DT_WMRC, MAXWMPATH - strlen(cfileName)); fileP = fopen (cfileName, "r"); } } } if (!fileP) { char *pch; /* * handle ":" form of file name */ pch = (char *) GetNetworkFileName (cfileName); if ((fileP = fopen (cfileName, "r")) != NULL) { strncpy (cfileName, pch, MAXWMPATH); XtFree (pch); } /* * Either not ":" form or there was a * problem up above. This is the last attempt to * open something. */ if (!fileP) { fileP = fopen (cfileName, "r"); } } if (!pConfigStack) { ConfigStackInit (cfileName); } if (wmGD.cppCommand && *wmGD.cppCommand) { /* * Run the file through the C-preprocessor */ PreprocessConfigFile (); if (pConfigStackTop && pConfigStackTop->cppName) { if(fileP) { fclose(fileP); } /* open the result */ fileP = fopen (pConfigStackTop->cppName, "r"); } } if (LANG != NULL) { XtFree(LANG); LANG = NULL; } return (fileP); } /* END OF FUNCTION FopenConfigFile */ /*************************************<->************************************* * * SaveMenuAccelerators (pSD, newMenuSpec) * * * Description: * ----------- * This function saves the MenuSpec pointer in pSD->acceleratorMenuSpecs. * * * Inputs: * ------ * newMenuSpec = pointer to MenuSpec to be saved. * pSD->acceleratorMenuSpecs = * pSD->acceleratorMenuCount = * * * Outputs: * ------- * pSD->acceleratorMenuSpecs = possibly updated * pSD->acceleratorMenuCount = possibly updated * * * Comments: * -------- * We assume only MenuSpecs created within ProcessWmFile() are to be saved. * Otherwise, we may cause override the limits of pSD->acceleratorMenuSpecs. * *************************************<->***********************************/ void SaveMenuAccelerators (WmScreenData *pSD, MenuSpec *newMenuSpec) { MenuSpec **pMenuSpec; pMenuSpec = pSD->acceleratorMenuSpecs; if (pMenuSpec == NULL) return; while ((*pMenuSpec != NULL) && (*pMenuSpec != newMenuSpec)) { pMenuSpec++; } if (*pMenuSpec == NULL) { *pMenuSpec = newMenuSpec; pSD->acceleratorMenuCount++; } } /* END OF FUNCTION SaveMenuAccelerators */ /*************************************<->************************************* * * ParseMenuSet (pSD, lineP) * * * Description: * ----------- * Menu pane specification found. Parse the following syntax: * * v * Menu menu_pane_name * { * label [mnemonic] [accelerator] function * label [mnemonic] [accelerator] function * ... * label [mnemonic] [accelerator] function * } * * * Inputs: * ------ * cfileP = (global) file pointer to fopened configuration file or NULL * lineP = pointer to menu name in line buffer * line = (global) line buffer * linec = (global) line count * parseP = (global) parse string pointer if cfileP == NULL * pSD->rootWindow = default root window of display * wmGD.bitmapDirectory = bitmapDirectory resource value * HOME = environment variable for home directory * * * Outputs: * ------- * linec = (global) line count incremented * parseP = (global) parse string pointer if cfileP == NULL * pSD->menuSpecs = list of menu specifications * * * Comments: * -------- * Skips unnamed menu specifications. * This means custom menu specifications can be distinguished by NULL name. * *************************************<->***********************************/ static void ParseMenuSet (WmScreenData *pSD, unsigned char *lineP) { unsigned char *string; MenuSpec *menuSpec; /* * If menu name is NULL then skip this pane specification. */ if ((string = GetString (&lineP)) == NULL) { return; } /* * Allocate space for the menu specification structure. */ if ((menuSpec = (MenuSpec *)XtMalloc (sizeof (MenuSpec))) == NULL) { PWarning (((char *)GETMESSAGE(60, 9, "Insufficient memory for menu"))); return; } menuSpec->currentContext = 0; menuSpec->menuWidget = NULL; menuSpec->whichButton = SELECT_BUTTON; /* Button1 selection default */ menuSpec->menuItems = NULL; menuSpec->accelContext = 0; menuSpec->accelKeySpecs = NULL; menuSpec->nextMenuSpec = NULL; /* * Allocate and fill space for the menu name. */ if ((menuSpec->name = (String)XtMalloc ((unsigned int) (strlen ((char *)string) + 1))) == NULL) { PWarning (((char *)GETMESSAGE(60, 10, "Insufficient memory for menu"))); XtFree ((char *)menuSpec); return; } strcpy (menuSpec->name, (char *)string); /* * Add the empty structure to the head of the menu specification list. */ menuSpec->nextMenuSpec = pSD->menuSpecs; pSD->menuSpecs = menuSpec; /* * Require leading '{' on the next line. */ while ((GetNextLine () != NULL)) /* not EOF nor read error */ { lineP = line; ScanWhitespace(&lineP); if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#')) /* ignore empty or comment line */ { continue; } if (*lineP == '{') /* found '{' */ { break; } /* not a '{' */ PWarning (((char *)GETMESSAGE(60, 11, "Expected '{' after menu name"))); return; } /* * Found leading "{" or EOF. * Parse menu item specifications until "}" or EOF found. */ menuSpec->menuItems = PARSE_MENU_ITEMS (pSD, menuSpec); } /* END OF FUNCTION ParseMenuSet */ /*************************************<->************************************* * * MenuItem * * ParseMwmMenuStr (pSD, menuStr) * * * Description: * ----------- * This function parses a WMW_MENU string and returns a list of * MenuItems structures. The string should have the syntax: * * label [mnemonic] [accelerator] function * label [mnemonic] [accelerator] function * ... * label [mnemonic] [accelerator] function * * * Inputs: * ------ * line = (global) line buffer * pSD->rootWindow = default root window of display * wmGD.bitmapDirectory = bitmapDirectory resource value * HOME = environment variable for home directory * functionTable = window manager function parse table * * * Outputs: * ------- * Return = list of MenuItem structures or NULL * * * Comments: * -------- * None. * *************************************<->***********************************/ MenuItem *ParseMwmMenuStr (WmScreenData *pSD, unsigned char *menuStr) { cfileP = NULL; linec = 0; parseP = menuStr; return (PARSE_MENU_ITEMS (pSD, NULL)); } /* END OF FUNCTION ParseMwmMenuStr */ /*************************************<->************************************* * * static MenuItem * * ParseMenuItems (pSD, menuSpec) * * * Description: * ----------- * Parse menu item specifications: * * label [mnemonic] [accelerator] function * label [mnemonic] [accelerator] function * ... * label [mnemonic] [accelerator] function * [}] * * * Inputs: * ------ * pSD = pointer to screen data * cfileP = (global) file pointer to fopened configuration file or NULL * line = (global) line buffer * linec = (global) line count * parseP = (global) parse string pointer if cfileP == NULL * pSD->rootWindow = default root window of display * wmGD.bitmapDirectory = bitmapDirectory resource value * HOME = environment variable for home directory * * * Outputs: * ------- * linec = (global) line count incremented * parseP = (global) parse string pointer if cfileP == NULL * Return = list of MenuItem structures or NULL * * * Comments: * -------- * None. * *************************************<->***********************************/ static MenuItem *ParseMenuItems (WmScreenData *pSD) { unsigned char *string; unsigned char *lineP; MenuItem *firstMenuItem; MenuItem *lastMenuItem; MenuItem *menuItem; int ix; /* * Parse "label [mnemonic] [accelerator] function" or * "[.]*" * lines until "}" or EOF found. */ firstMenuItem = lastMenuItem = NULL; while ((GetNextLine () != NULL)) { lineP = line; if ((*line == '!') || (*line == '#') || (string = GetString (&lineP)) == NULL) /* ignore empty or comment lines */ { continue; } if (*string == '}') /* finished with menu set. */ { break; } /* * Allocate space for the menu item structure. */ if ((menuItem = (MenuItem *)XtMalloc (sizeof (MenuItem))) == NULL) { PWarning (((char *)GETMESSAGE(60, 12, "Insufficient memory for menu item"))); continue; } menuItem->nextMenuItem = NULL; menuItem->wmFunction = (WmFunction)NULL; menuItem->wmFuncArgs = NULL; { /* * Parse the menu item label. */ if (!ParseWmLabel (pSD, menuItem, string)) { XtFree ((char *)menuItem); continue; } } /* * Parse any menu function mnemonic. */ ParseWmMnemonic (&lineP, menuItem); /* * Parse any menu function accelerator. */ if (!ParseWmAccelerator (&lineP, menuItem)) { XtFree ((char *)menuItem); continue; } /* * Parse the menu function name if this is not a client * command. If it is a client command, then the wmFunction * field should already be set, as well as the ix variable, * but we do want to search for a menu item name that occupies * the same place as the function does for normal menu items. */ ix = ParseWmFunction (&lineP, CRS_MENU, &menuItem->wmFunction); /* * Determine context sensitivity and applicability mask. */ menuItem->greyedContext = functionTable[ix].greyedContext; menuItem->mgtMask = functionTable[ix].mgtMask; if ((menuItem->wmFunction == F_Toggle_Front_Panel) && ((wmGD.useFrontPanel == False) || (wmGD.dtSD != pSD))) { /* * disallow this function if there's no front * panel on this screen. */ menuItem->greyedContext |= (F_CONTEXT_ALL | F_SUBCONTEXT_IB_WICON | F_SUBCONTEXT_IB_IICON); } /* * Apply the function argument parser. */ if (!(*(functionTable [ix].parseProc)) (&lineP, menuItem->wmFunction, &menuItem->wmFuncArgs)) { FreeMenuItem (menuItem); continue; /* skip this menu item */ } /* * Add this item to the menu specification. */ if (lastMenuItem != NULL) /* not first */ { lastMenuItem->nextMenuItem = menuItem; } else { firstMenuItem = menuItem; } lastMenuItem = menuItem; } return (firstMenuItem); } /* END OF FUNCTION ParseMenuItems */ /*************************************<->************************************* * * ParseWmLabel (pSD, menuItem, string) * * * Description: * ----------- * Parse a menu label string. * * * Inputs: * ------ * pSD = pointer to screen data * menuItem = pointer to MenuItem structure * string = label string * * * Outputs: * ------- * menuItem->label * menuItem->labelType * menuItem->labelBitmapCache * Return = boolean, FALSE iff insufficient memory * * * Comments: * -------- * We have two label types: XmSTRING and XmPIXMAP * We allocate and fill the label field with string and set the type to * XmSTRING. If string = "@", and contains a * with which to build a label image we save the bitmap in the MenuItem * structure and set the type to XmPIXMAP. * *************************************<->***********************************/ static Boolean ParseWmLabel (WmScreenData *pSD, MenuItem *menuItem, unsigned char *string) { /* * Allocate the label field and copy string. */ if ((menuItem->label = (String) XtMalloc ((unsigned int)(strlen ((char *)string) + 1))) == NULL) { PWarning (((char *)GETMESSAGE(60, 13, "Insufficient memory for menu item"))); return (FALSE); } strcpy (menuItem->label, (char *)string); menuItem->labelType = XmSTRING; if (*string == '@') /* * Here: string = "@" * Try to find the label bitmap in the bitmap cache or read the label * bitmap file. */ { string++; /* skip "@" */ if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD, (char *)string, True)) >= 0) { menuItem->labelType = XmPIXMAP; } } return (TRUE); } /* END OF FUNCTION ParseWmLabel */ /*************************************<->************************************* * * ParseWmMnemonic (linePP, menuItem) * * * Description: * ----------- * Parse an optional menu function mnemonic. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * menuItem = pointer to MenuItem structure * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * menuItem->mnemonic = valid mnemonic character or NULL. * * * Comments: * -------- * None. * *************************************<->***********************************/ static void ParseWmMnemonic (unsigned char **linePP, MenuItem *menuItem) { unsigned char *lineP = *linePP; unsigned char *mnemonic; /* * Skip leading white space. */ ScanWhitespace (&lineP); menuItem->mnemonic = (KeySym)NULL; if (*lineP == '_') /* * We have a mnemonic specification. * Get the next string (we only use the first character). * If no string exists, the labelType is not XmSTRING, or does not contain * the first character, then skip the string and return. * Otherwise, accept the first character as a mnemonic. */ { KeySym ks; lineP++; mnemonic = GetString(&lineP); if (menuItem->labelType == XmSTRING && mnemonic != NULL && (ks = XStringToKeysym((char *)mnemonic)) != NoSymbol && strchr(menuItem->label, (char)(ks & 0xff)) != NULL) { menuItem->mnemonic = ks; } else { PWarning (((char *)GETMESSAGE(60, 14, "Invalid mnemonic specification"))); } } *linePP = lineP; /* consume any string */ } /* END OF FUNCTION ParseWmMnemonic */ /*************************************<->************************************* * * ParseWmAccelerator (linePP, menuItem) * * * Description: * ----------- * Parse an optional menu function accelerator. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * menuItem = pointer to MenuItem structure * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * menuItem->accelText = pointer to an accelerator string or NULL. * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseWmAccelerator (unsigned char **linePP, MenuItem *menuItem) { unsigned char *lineP; String string; unsigned int eventType; unsigned int state; KeyCode keycode; Boolean status; menuItem->accelState = 0; menuItem->accelKeyCode = 0; menuItem->accelText = NULL; status = TRUE; /* * If linePP contains NULL, then abort. */ if (*linePP == (unsigned char *) NULL) return(FALSE); /* * Skip leading white space. */ ScanWhitespace (linePP); lineP = *linePP; /* * If the second character is not ".", and an accelerator specification * exists, then process and save the specification string. */ if ((*lineP != '\0') && /* something follows */ (*lineP != '!') && /* skip if we have the ! WmFunction */ (*lineP != 'f') && (*(lineP+1) != '.')) /* skip if we have f.xxx WmFunction */ { if (ParseKeyEvent(&lineP, &eventType, &keycode, &state)) { if ((string = (String) XtMalloc ((unsigned int) (lineP - *linePP + 1))) == NULL) { PWarning (((char *)GETMESSAGE(60, 15, "Insufficient memory for accelerator specification"))); status = FALSE; } else /* * Save the accelerator state and keycode. * Process and save the accelerator text. */ { ProcessAccelText (*linePP, lineP, (unsigned char *) string); menuItem->accelState = state; menuItem->accelKeyCode = keycode; menuItem->accelText = string; } } else { PWarning (((char *)GETMESSAGE(60, 16, "Invalid accelerator specification"))); status = FALSE; } *linePP = lineP; /* consume the specification */ } return (status); } /* END OF FUNCTION ParseWmAccelerator */ /*************************************<->************************************* * * int * ParseWmFunction (linePP, res_spec, pWmFunction) * * * Description: * ----------- * Parse a button, key, or menu function name and return its function table * index. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * res_spec = resource specification type (key, button, or menu). * pWmFunction = pointer to window manager function destination. * functionTable = window manager function parse table * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * pWmFunction = pointer to parsed window manager function. * Return = function table index of parsed function. * * * Comments: * -------- * Uses F_Nop if the function name or resource type is invalid. * *************************************<->***********************************/ int ParseWmFunction (unsigned char **linePP, unsigned int res_spec, WmFunction *pWmFunction) { unsigned char *lineP = *linePP; unsigned char *string; int low, mid, high, cmp; /* * Skip leading white space. */ ScanWhitespace (&lineP); /* * Have function string (may be NULL or a comment). * Handle the special case of '!' */ if (*lineP == '!') { *linePP = ++lineP; *pWmFunction = F_Exec; return (F_EXEC_INDEX); } /* * Identify the function corresponding to the specified name. * Try binary search of the window manager function parse table. * Assume f.nop if the function and resource type cannot be matched. * This handles NULL and comment strings, bad function names, and functions * in inappropriate resource sets. */ string = GetString (&lineP); *linePP = lineP; if (string != NULL) { ToLower ((char *)string); low = 0; high = WMFUNCTIONTABLESIZE - 1; while (low <= high) { mid = (low + high)/2; cmp = strcmp (functionTable[mid].funcName, (char *)string); if (!cmp) /* * Function name match * Require proper resource type for the function. */ { if (res_spec & functionTable[mid].resource) { *pWmFunction = functionTable[mid].wmFunction; return (mid); } /* invalid resource: use F_Nop */ break; } /* * Function name mismatch */ if (cmp > 0) { high = mid - 1; } else { low = mid + 1; } } } /* * Not found: assume f.nop */ *pWmFunction = F_Nop; return (F_NOP_INDEX); } /* END OF FUNCTION ParseWmFunction */ /*************************************<->************************************* * * ParseWmFuncMaybeStrArg (linePP, wmFunction, pArgs) * * * Description: * ----------- * Parses a window manager function with a null or string argument. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * wmFunction = function (not used). * pArgs = pointer to argument destination. * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * pArgs = pointer to parsed argument string. * Return = FALSE iff insufficient memory * * * Comments: * -------- * Only used to parse arguments for F_Lower, F_Raise, and F_Raise_Lower. * If it is used for any other function, be sure to change FreeMenuItem () * accordingly. * *************************************<->***********************************/ Boolean ParseWmFuncMaybeStrArg (unsigned char **linePP, WmFunction wmFunction, String *pArgs) { unsigned char *string = *linePP; unsigned int len; ScanWhitespace (&string); /* if (*lineP == '-') { *linePP = ++lineP; return (ParseWmFuncStrArg (linePP, wmFunction, pArgs)); } */ #if 0 else if (*lineP == '"' && *(lineP+1) == '-') { /* kill off '-' */ strcpy ((char *) (lineP+1), (char *) (lineP+2)); return (ParseWmFuncStrArg (linePP, wmFunction, pArgs)); } #endif if ((len = strlen ((char *)string)) != 0) { if ((*pArgs = (String)XtMalloc (len + 1)) == NULL) { PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory"))); return (FALSE); } strcpy (*pArgs, (char *)string); return (TRUE); } else /* Do ParseWmFuncNoArg () */ { *pArgs = NULL; return (TRUE); } } /* END OF FUNCTION ParseWmFuncMaybeStrArg */ /*************************************<->************************************* * * ParseWmFuncNoArg (linePP, wmFunction, pArgs) * * * Description: * ----------- * Parses a window manager function null argument. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * wmFunction = function (not used). * pArgs = pointer to argument destination. * * * Outputs: * ------- * linePP = unchanged * pArgs = NULL * Return = TRUE * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseWmFuncNoArg (unsigned char **linePP, WmFunction wmFunction, String *pArgs) { *pArgs = NULL; return (TRUE); } /* END OF FUNCTION ParseWmFuncNoArg */ /*************************************<->************************************* * * ParseWmFuncStrArg (linePP, wmFunction, pArgs) * * * Description: * ----------- * Parses a window manager function string argument. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * wmFunction = function for which the argument string is intended. * pArgs = pointer to argument string destination. * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * pArgs = pointer to parsed argument string. * Return = FALSE iff insufficient memory * * * Comments: * -------- * Insures that an argument for F_Exec() ends in '&' . * Only used to parse arguments for F_Exec, F_Menu, F_Lower, F_Raise, * F_Raise_Lower, and F_Screen. If it is used for any other function, be * sure to change FreeMenuItem () accordingly. * *************************************<->***********************************/ Boolean ParseWmFuncStrArg (unsigned char **linePP, WmFunction wmFunction, String *pArgs) { unsigned char *string; unsigned int len; char *p; wchar_t last; char delim; wchar_t wdelim; int lastlen; if ((string = GetString (linePP)) != NULL) /* nonNULL string argument */ { len = strlen ((char *)string); if ((*pArgs = (String)XtMalloc (len + 2)) == NULL) { PWarning (((char *)GETMESSAGE(60, 17, "Insufficient memory"))); return (FALSE); } strcpy (*pArgs, (char *)string); /* * Insure that an argument for F_Exec ends in '&' . */ if (wmFunction == F_Exec) { lastlen = 0; p = *pArgs; while (*p && ((len = mblen(p, MB_CUR_MAX)) > 0)) { mbtowc(&last, p, MB_CUR_MAX); lastlen = len; p += len; } delim = '&'; mbtowc(&wdelim, &delim, MB_CUR_MAX); if (lastlen == 1 && last != wdelim) { *p++ = '&'; *p = '\0'; } } } else /* NULL string argument */ { *pArgs = NULL; } return (TRUE); } /* END OF FUNCTION ParseWmFuncStrArg */ /*************************************<->************************************* * * FreeMenuItem (menuItem) * * * Description: * ----------- * This procedure destroys a MenuItem structure. * * * Inputs: * ------ * menuItem = to be destroyed. * * * Outputs: * ------- * None. * * * Comments: * -------- * Assumes that ParseWmFuncStrArg () has parsed a menu item's function * argument only for F_Exec, F_Menu, F_Lower, F_Raise, F_Raise_Lower, and * F_Screen. If it is used for other functions, be sure to include them here! * *************************************<->***********************************/ void FreeMenuItem (MenuItem *menuItem) { if (menuItem->label != NULL) { XtFree ((char *)menuItem->label); } if (menuItem->accelText != NULL) { XtFree ((char *)menuItem->accelText); } /* * If menuItem->wmFuncArgs is nonNULL, we assume that it is a string that * was malloc'ed in ParseWmFuncStrArg () and we free it now. */ if ((menuItem->wmFuncArgs != NULL) && ((menuItem->wmFunction == F_Exec) || (menuItem->wmFunction == F_Menu) || (menuItem->wmFunction == F_Lower) || (menuItem->wmFunction == F_Raise) || (menuItem->wmFunction == F_Raise_Lower) || (menuItem->wmFunction == F_Screen))) { XtFree ((char *)menuItem->wmFuncArgs); } XtFree ((char *)menuItem); } /* END OF FUNCTION FreeMenuItem */ /*************************************<->************************************* * * ParseWmFuncGrpArg (linePP, wmFunction, pGroup) * * * Description: * ----------- * Parses a window manager function group argument. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * wmFunction = function for which the group argument is intended. * pGroup = pointer to group argument destination. * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * pGroup = pointer to parsed group argument. * Return = FALSE iff invalid group argument. * * * Comments: * -------- * The only valid nonNULL arguments are "icon", "window", and "transient". * *************************************<->***********************************/ static Boolean ParseWmFuncGrpArg (unsigned char **linePP, WmFunction wmFunction, GroupArg *pGroup) { unsigned char *lineP = *linePP; unsigned char *startP; unsigned char grpStr[MAX_GROUP_STRLEN+1]; int len; /* * Parse groups while each is followed by "|". */ *pGroup = 0; while (1) { /* * Skip whitespace and find next group string. */ ScanWhitespace (&lineP); startP = lineP; ScanAlphanumeric (&lineP); if (startP == lineP) /* Group missing => use default or complain */ { if (*pGroup) { PWarning (((char *)GETMESSAGE(60, 18, "Missing group specification"))); return (FALSE); } else { *pGroup = F_GROUP_DEFAULT; break; } } /* * Found a group string; compare it with valid groups. */ len = min (lineP - startP, MAX_GROUP_STRLEN); (void) strncpy ((char *)grpStr, (char *)startP, len); grpStr[len] = '\0'; ToLower ((char *)grpStr); if (!strcmp ("icon", (char *)grpStr)) { *pGroup |= F_GROUP_ICON; } else if (!strcmp ("window", (char *)grpStr)) { *pGroup |= F_GROUP_WINDOW; } else if (!strcmp ("transient", (char *)grpStr)) { *pGroup |= F_GROUP_TRANSIENT; } else /* Unknown group name */ { PWarning (((char *)GETMESSAGE(60, 19, "Invalid group specification"))); return (FALSE); } /* * Continue processing until the line is exhausted. * Skip any '|' . */ ScanWhitespace (&lineP); if (lineP == NULL || *lineP == '\0') { break; } else if (*lineP == '|') { lineP++; } } *linePP = lineP; return (TRUE); } /* END OF FUNCTION ParseWmFuncGrpArg */ /*************************************<->************************************* * * ParseWmFuncNbrArg (linePP, wmFunction, pNumber) * * * Description: * ----------- * Parses a window manager function number argument. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * wmFunction = function * pNumber = pointer to number argument destination. * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * pNumber = pointer to parsed number argument. * Return = FALSE iff invalid number argument. * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseWmFuncNbrArg (unsigned char **linePP, WmFunction wmFunction, unsigned long *pNumber) { int val; val = StrToNum (GetString (linePP)); if (val == -1) { PWarning (((char *)GETMESSAGE(60, 20, "Invalid number specification"))); *pNumber = 0; return (FALSE); } *pNumber = val; return (TRUE); } /* END OF FUNCTION ParseWmFuncNbrArg */ /*************************************<->************************************* * * ParseButtonStr () * * * Description: * ----------- * This function parses a button set specification string: * * bindings_name * { * button context function * button context function * ... * button context function * } * * * * Inputs: * ------ * pSD->buttonBindings = buttonBindings resource value * functionTable = window manager function parse table * * * Outputs: * ------- * pSD->buttonSpecs = list of button binding specifications. * * * Comments: * -------- * The button set specification name must match pSD->buttonBindings. * *************************************<->***********************************/ void ParseButtonStr (WmScreenData *pSD, unsigned char *buttonStr) { unsigned char *lineP; cfileP = NULL; linec = 0; if (((parseP = buttonStr) != NULL) && (GetNextLine () != NULL)) { lineP = line; ParseButtonSet (pSD, lineP); } } /* END OF FUNCTION ParseButtonStr */ /*************************************<->************************************* * * ParseButtonSet (pSD, lineP) * * * Description: * ----------- * Button set specification found. Parse the following syntax: * * v * Buttons bindings_name * { * button context function * button context function * ... * button context function * } * * * Inputs: * ------ * cfileP = (global) file pointer to fopened configuration file or NULL * line = (global) line buffer * lineP = pointer to current character in line buffer * pSD->buttonBindings = buttonBindings resource value * * * Outputs: * ------- * lineP = pointer to current character in line buffer * pSD->buttonSpecs = list of button binding specifications. * * * Comments: * -------- * Skips unnamed button binding set and sets with names that don't match * the buttonBindings resource. * Skips bad button binding specifications. * *************************************<->***********************************/ static void ParseButtonSet (WmScreenData *pSD, unsigned char *lineP) { unsigned char *string; ButtonSpec *buttonSpec; ButtonSpec *lastButtonSpec; int ix; /* * Parse the button set bindings from the configuration file. * If either the button set name or buttonBindings resource is NULL or * they don't match, then skip this button specification. */ if (((string = GetString (&lineP)) == NULL) || (pSD->buttonBindings == NULL) || strcmp ((char *)string, pSD->buttonBindings)) { return; } /* * Require leading '{' on the next line. */ while ((GetNextLine () != NULL)) /* not EOF nor read error */ { lineP = line; ScanWhitespace(&lineP); if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#')) /* ignore empty or comment line */ { continue; } if (*lineP == '{') /* found '{' */ { break; } /* not a '{' */ PWarning (((char *)GETMESSAGE(60, 21, "Expected '{' after button set name"))); return; } /* * Found leading "{" or EOF. * Prepare to accumulate button bindings by finding the end of * the button specification list. * lastButtonSpec will be NULL only if no prior bindings exist. */ lastButtonSpec = pSD->buttonSpecs; if (lastButtonSpec != NULL) { while (lastButtonSpec->nextButtonSpec != NULL) { lastButtonSpec = (lastButtonSpec->nextButtonSpec); } } /* * Parse "button context function" until "}" or EOF found. * Skips bad button binding specifications. */ while ((GetNextLine () != NULL)) /* not EOF nor read error */ { lineP = line; ScanWhitespace(&lineP); if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#')) /* ignore empty or comment lines */ { continue; } if (*lineP == '}') /* finished with button set */ { break; } /* * Allocate space for the button binding specification. */ if ((buttonSpec = (ButtonSpec *)XtMalloc (sizeof (ButtonSpec))) == NULL) { PWarning (((char *)GETMESSAGE(60, 22, "Insufficient memory for button specification"))); continue; } buttonSpec->wmFunction = (WmFunction)NULL; buttonSpec->wmFuncArgs = NULL; buttonSpec->nextButtonSpec = NULL; /* * Parse the button specification "button". */ lineP = line; if (!ParseBtnEvent(&lineP, &buttonSpec->eventType, &buttonSpec->button, &buttonSpec->state, &buttonSpec->click)) { PWarning (((char *)GETMESSAGE(60, 23, "Invalid button specification"))); XtFree ((char *)buttonSpec); continue; /* skip this button specification */ } /* * Parse the button context. */ if (!ParseContext(&lineP, &buttonSpec->context, &buttonSpec->subContext)) { PWarning (((char *)GETMESSAGE(60, 24, "Invalid button context"))); XtFree ((char *)buttonSpec); continue; /* skip this button specification */ } /* * Parse the button function and any arguments. */ ix = ParseWmFunction (&lineP, CRS_BUTTON, &buttonSpec->wmFunction); /* * remove any subContexts that don't apply to this function */ if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) && (buttonSpec->subContext & F_SUBCONTEXT_IB_IICON)) { buttonSpec->subContext &= ~F_SUBCONTEXT_IB_IICON; } if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) && (buttonSpec->subContext & F_SUBCONTEXT_IB_WICON)) { buttonSpec->subContext &= ~F_SUBCONTEXT_IB_WICON; } /* * Map Button3 menus to BMenu virtual button */ if (buttonSpec->button == Button3 && (buttonSpec->wmFunction == F_Menu || buttonSpec->wmFunction == F_Post_SMenu)) { buttonSpec->button = wmGD.bMenuButton; } /* * Apply the function argument parser. */ if (!(*(functionTable [ix].parseProc)) (&lineP, buttonSpec->wmFunction, &buttonSpec->wmFuncArgs)) { XtFree ((char *)buttonSpec); continue; /* skip this button specification */ } /* * Add the button specification to the button specification list. */ if (lastButtonSpec != NULL) /* a prior specification exists */ { lastButtonSpec->nextButtonSpec = buttonSpec; } else { pSD->buttonSpecs = buttonSpec; } lastButtonSpec = buttonSpec; } } /* END OF FUNCTION ParseButtonSet */ /*************************************<->************************************* * * ParseContext (linePP, context, subContext) * * * Description: * ----------- * Parses a general context string. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * context = context field value * subContext = subContext field value * Return = (Boolean) true iff valid context string * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseContext (unsigned char **linePP, Context *context, Context *subContext) { unsigned char *lineP = *linePP; unsigned char *startP; unsigned char ctxStr[MAX_CONTEXT_STRLEN+1]; int len; /* * Parse contexts while each is followed by "|". */ *context = 0; *subContext = 0; while (1) { /* * Skip whitespace and find next context string. */ ScanWhitespace (&lineP); startP = lineP; ScanAlphanumeric (&lineP); if (startP == lineP) /* ERROR: Context missing */ { return (FALSE); } /* * Found nonNULL string; compare it with valid contexts. */ len = min(lineP - startP, MAX_CONTEXT_STRLEN); (void) strncpy ((char *)ctxStr, (char *)startP, len); ctxStr[len] = '\0'; ToLower ((char *)ctxStr); if (!strcmp ("root", (char *)ctxStr)) { *context |= F_CONTEXT_ROOT; *subContext |= F_SUBCONTEXT_R_ALL; } else if (!strcmp ("icon", (char *)ctxStr)) { *context |= (F_CONTEXT_ICON | F_CONTEXT_ICONBOX | F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON ); *subContext |= (F_SUBCONTEXT_I_ALL | F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON ); } else if (!strcmp ("window", (char *)ctxStr)) { *context |= F_CONTEXT_WINDOW; *subContext |= F_SUBCONTEXT_W_ALL; } else if (!strcmp ("frame", (char *)ctxStr)) { *context |= F_CONTEXT_WINDOW; *subContext |= F_SUBCONTEXT_W_FRAME; } else if (!strcmp ("title", (char *)ctxStr)) { *context |= F_CONTEXT_WINDOW; *subContext |= F_SUBCONTEXT_W_TITLE; } else if (!strcmp ("border", (char *)ctxStr)) { *context |= F_CONTEXT_WINDOW; *subContext |= F_SUBCONTEXT_W_BORDER; } else if (!strcmp ("app", (char *)ctxStr)) { *context |= F_CONTEXT_WINDOW; *subContext |= F_SUBCONTEXT_W_APP; } else if (!strcmp ("ifkey", (char *)ctxStr)) { *context |= F_CONTEXT_IFKEY; } else /* Unknown context name */ { return (FALSE); } /* continue only if followed by '|' */ ScanWhitespace (&lineP); if (*lineP != '|') { break; } lineP++; } *linePP = lineP; return (TRUE); } /* END OF FUNCTION ParseContext */ /*************************************<->************************************* * * ParseKeyStr () * * * Description: * ----------- * This function parses a key set specification string: * * bindings_name * { * key context function * key context function * ... * key context function * } * * * Inputs: * ------ * pSD->keyBindings = keyBindings resource value * functionTable = window manager function parse table * * * Outputs: * ------- * pSD->keySpecs = list of key binding specification * * * Comments: * -------- * The key set specification name must match pSD->keyBindings. * *************************************<->***********************************/ void ParseKeyStr (WmScreenData *pSD, unsigned char *keyStr) { unsigned char *lineP; cfileP = NULL; linec = 0; if (((parseP = keyStr) != NULL) && (GetNextLine () != NULL)) { lineP = line; ParseKeySet (pSD, lineP); } } /* END OF FUNCTION ParseKeyStr */ /*************************************<->************************************* * * ParseKeySet (pSD, lineP) * * * Description: * ----------- * Key set specification found. Parse the following syntax: * * v * Keys bindings_name * { * key context function * key context function * ... * key context function * } * * * Inputs: * ------ * cfileP = (global) file pointer to fopened configuration file or NULL * line = (global) line buffer * lineP = pointer to current character in line buffer * pSD->keyBindings = keyBindings resource value * * * Outputs: * ------- * lineP = pointer to current character in line buffer * pSD->keySpecs = list of key binding specifications. * * * Comments: * -------- * Skips unnamed key binding set and sets with names that don't match the * keyBindings resource. * Skips bad key binding specifications. * *************************************<->***********************************/ static void ParseKeySet (WmScreenData *pSD, unsigned char *lineP) { unsigned char *string; KeySpec *keySpec; KeySpec *lastKeySpec; unsigned int eventType; int ix; Boolean bBadKey; /* * Parse the key set bindings from the configuration file. * If either the key set name or keyBindings resource is NULL or they * don't match then skip this key specification. */ if (((string = GetString (&lineP)) == NULL) || (pSD->keyBindings == NULL) || strcmp ((char *)string, pSD->keyBindings)) { return; } /* * Require leading '{' on next line. */ while ((GetNextLine () != NULL)) /* not EOF nor read error */ { lineP = line; ScanWhitespace(&lineP); if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#')) /* ignore empty or comment line */ { continue; } if (*lineP == '{') /* found '{' */ { break; } /* not a '{' */ PWarning (((char *)GETMESSAGE(60, 25, "Expected '{' after key set name"))); return; } /* * Found leading "{" or EOF. * Prepare to accumulate key bindings by finding the end of * the key specification list. * lastKeySpec will be NULL only if no prior bindings exist. */ lastKeySpec = pSD->keySpecs; if (lastKeySpec != NULL) { while (lastKeySpec->nextKeySpec != NULL) { lastKeySpec = (lastKeySpec->nextKeySpec); } } /* * Parse "key context function" until "}" or EOF found. * Skip bad key bindings. */ while ((GetNextLine () != NULL)) /* not EOF nor read error */ { lineP = line; ScanWhitespace (&lineP); if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#')) /* ignore empty or comment lines */ { continue; } if (*lineP == '}') /* finished with key set */ { break; } /* * Allocate space for the key specification. */ if ((keySpec = (KeySpec *)XtMalloc (sizeof (KeySpec))) == NULL) { PWarning (((char *)GETMESSAGE(60, 26, "Insufficient memory for key specification"))); continue; } keySpec->wmFunction = (WmFunction)NULL; keySpec->wmFuncArgs = NULL; keySpec->nextKeySpec = NULL; /* * Parse the key specification. */ bBadKey = False; if (!ParseKeyEvent(&lineP, &eventType, &keySpec->keycode, &keySpec->state)) { bBadKey = True; } /* * Parse the key context. * Here lineP points to the candidate context string. */ if (!ParseContext(&lineP, &keySpec->context, &keySpec->subContext)) { if (bBadKey) PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification"))); PWarning (((char *)GETMESSAGE(60, 28, "Invalid key context"))); XtFree ((char *)keySpec); continue; /* skip this key specification */ } if (bBadKey) { /* * Don't print an error message if this is a "hardware * available" binding. */ if (!(keySpec->context & F_CONTEXT_IFKEY)) PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification"))); XtFree ((char *)keySpec); continue; /* skip this key specification */ } /* * This flag is only used for parsing, clear it so the * rest of the program doesn't see it. */ keySpec->context &= ~F_CONTEXT_IFKEY; /* * Parse the key function and any arguments. */ ix = ParseWmFunction (&lineP, CRS_KEY, &keySpec->wmFunction); /* * remove any subContexts that don't apply to this function */ if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_IICON) && (keySpec->subContext & F_SUBCONTEXT_IB_IICON)) { keySpec->subContext &= ~F_SUBCONTEXT_IB_IICON; } if ((functionTable[ix].greyedContext & F_SUBCONTEXT_IB_WICON) && (keySpec->subContext & F_SUBCONTEXT_IB_WICON)) { keySpec->subContext &= ~F_SUBCONTEXT_IB_WICON; } /* * Apply the function argument parser. */ if (!(*(functionTable [ix].parseProc)) (&lineP, keySpec->wmFunction, &keySpec->wmFuncArgs)) { XtFree ((char *)keySpec); continue; /* skip this key specification */ } /* * Add the key specification to the key specification list. */ if (lastKeySpec != NULL) /* a prior specification exists */ { lastKeySpec->nextKeySpec = keySpec; } else { pSD->keySpecs = keySpec; } lastKeySpec = keySpec; } } /* END OF FUNCTION ParseKeySet */ /*************************************<->************************************* * * ParseBtnEvent (linePP, eventType, button, state, fClick) * * * Description: * ----------- * Parse a button event specification. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer * buttonEvents = (global) button event parse table * modifierStrings = (global) modifier string/mask table * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * eventType = type of event * button = parsed button number * state = composite modifier mask * fClick = is click? * * Return = (Boolean) true iff valid button event specification * * * Comments: * -------- * None. * *************************************<->***********************************/ Boolean ParseBtnEvent (unsigned char **linePP, unsigned int *eventType, unsigned int *button, unsigned int *state, Boolean *fClick) { if (!ParseEvent (linePP, buttonEvents, eventType, button, state, fClick)) { return (FALSE); } /* * The following is a fix for an X11 deficiency in regards to * modifiers in grabs. */ if (*eventType == ButtonRelease) { /* the button that is going up will always be in the modifiers... */ *state |= buttonModifierMasks[*button]; } return (TRUE); } /* END OF FUNCTION ParseBtnEvent */ /*************************************<->************************************* * * ParseKeyEvent (linePP, eventType, keyCode, state) * * * Description: * ----------- * Parse a key event specification. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer * keyEvents = (global) key event parse table * modifierStrings = (global) modifier string/mask table * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * eventType = type of event * keyCode = parsed KeyCode * state = composite modifier mask * * Return = (Boolean) true iff valid key event specification * * * Comments: * -------- * None. * *************************************<->***********************************/ Boolean ParseKeyEvent (unsigned char **linePP, unsigned int *eventType, KeyCode *keyCode, unsigned int *state) { Boolean fClick; unsigned int keySym = 0; if (!ParseEvent (linePP, keyEvents, eventType, &keySym, state, &fClick)) { return (FALSE); } /* * Here keySym is a KeySym. Convert it to a KeyCode. * KeyCode will be set to 0 if keySym is not defined for any KeyCode * (e.g. 0x001). */ *keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym); if (*keyCode == 0) { if (keySym == XK_F9) { keySym = XK_KP_F1; } else if (keySym == XK_F10) { keySym = XK_KP_F2; } else if (keySym == XK_F11) { keySym = XK_KP_F3; } else if (keySym == XK_F12) { keySym = XK_KP_F4; } *keyCode = XKeysymToKeycode(DISPLAY, (KeySym) keySym); } return (*keyCode != 0); } /* END OF FUNCTION ParseKeyEvent */ /*************************************<->************************************* * * ParseEvent (linePP, table, eventType, detail, state, fClick) * * * Description: * ----------- * Parse an event specification. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * table = event parse table * modifierStrings = (global) modifier string/mask table * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * eventType = type of event * detail = dependent upon parse table detail procedure and closure * state = composite modifier mask * fClick = click flag * * Return = (Boolean) true iff valid event specification * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseEvent (unsigned char **linePP, EventTableEntry *table, unsigned int *eventType, unsigned int *detail, unsigned int *state, Boolean *fClick) { unsigned char *lineP = *linePP; Cardinal ix; Boolean status; /* Parse the modifiers */ if (!ParseModifiers (&lineP, state) || *lineP != '<') { return (FALSE); } lineP++; /* skip '<' */ /* Parse the event type */ if (!ParseEventType (&lineP, table, eventType, &ix) || *lineP != '>') { return (FALSE); } lineP++; /* skip '>' */ /* * Compute detail and fClick. * Status will be False for a invalid KeySym name. */ status = (*(table[ix].parseProc))(&lineP, table[ix].closure, detail); *fClick = table[ix].fClick; if (status) { *linePP = lineP; } return (status); } /* END OF FUNCTION ParseEvent */ /*************************************<->************************************* * * ParseModifiers(linePP, state) * * * Description: * ----------- * Parses a modifier specification. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * modifierStrings = (global) modifier string/mask table * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * state = composite modifier mask * Return = (Boolean) true iff valid modifier name * * * Comments: * -------- * If successful, will be followed by NULL or '<'. * *************************************<->***********************************/ static Boolean ParseModifiers(unsigned char **linePP, unsigned int *state) { unsigned char *lineP = *linePP; unsigned char *startP; unsigned char modStr[MAX_MODIFIER_STRLEN+1]; Boolean fNot; unsigned int maskBit; int len; *state = 0; /* * Parse modifiers until the event specifier is encountered. */ ScanWhitespace (&lineP); while ((*lineP != '\0') && (*lineP != '<')) { if (*lineP == '~') { fNot = TRUE; lineP++; } else { fNot = FALSE; } startP = lineP; ScanAlphanumeric (&lineP); if (startP == lineP) /* ERROR: Modifier or '<' missing */ { return (FALSE); } len = min(lineP - startP, MAX_MODIFIER_STRLEN); (void) strncpy ((char *)modStr, (char *)startP, len); modStr[len] = '\0'; if (!LookupModifier (modStr, &maskBit)) /* Unknown modifier name */ { return (FALSE); } if (fNot) { *state &= ~maskBit; } else { *state |= maskBit; } ScanWhitespace(&lineP); } *linePP = lineP; return (TRUE); /* must have '<' or NULL following */ } /* END OF FUNCTION ParseModifiers */ /*************************************<->************************************* * * LookupModifier (name, valueP) * * * Description: * ----------- * Return the modifier mask for the provided modifier name. * * * Inputs: * ------ * name = modifier string * modifierStrings = modifier string/mask table * * * Outputs: * ------- * valueP = modifier mask * Return = (Boolean) true iff valid modifier name * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean LookupModifier (unsigned char *name, unsigned int *valueP) { int i; if (name != NULL) { ToLower ((char *)name); for (i=0; modifierStrings[i].name != NULL; i++) { if (!strcmp (modifierStrings[i].name, (char *)name)) { *valueP = modifierStrings[i].mask; return (TRUE); } } } return (FALSE); } /* END OF FUNCTION LookupModifier */ /*************************************<->************************************* * * ParseEventType(linePP, table, eventType, ix) * * * Description: * ----------- * Parses the event type string. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * table = event parse table * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * eventType = type of event * ix = table index for matched event * * Return = (Boolean) true iff valid event * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseEventType (unsigned char **linePP, EventTableEntry *table, unsigned int *eventType, Cardinal *ix) { unsigned char *lineP = *linePP; unsigned char *startP = *linePP; unsigned char eventTypeStr[MAX_EVENTTYPE_STRLEN+1]; int len; /* Parse out the event string */ ScanAlphanumeric (&lineP); /* * Attempt to match the parsed event against our supported event set. */ if (startP != lineP) { len = min (lineP - startP, MAX_EVENTTYPE_STRLEN); (void) strncpy ((char *)eventTypeStr, (char *)startP, len); eventTypeStr[len] = '\0'; ToLower ((char *)eventTypeStr); for (len = 0; table[len].event != NULL; len++) if (!strcmp (table[len].event, (char *)eventTypeStr)) { *ix = len; *eventType = table[*ix].eventType; *linePP = lineP; return (TRUE); } } /* Unknown event specified */ return (FALSE); } /* END OF FUNCTION ParseEventType */ /*************************************<->************************************* * * ParseImmed (linePP, closure, detail) * * * Description: * ----------- * Button event detail procedure. * * * Inputs: * ------ * linePP = not used * closure = table entry * * * Outputs: * ------- * detail = pointer to closure * * Return = TRUE * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseImmed (unsigned char **linePP, unsigned int closure, unsigned int *detail) { *detail = closure; return (TRUE); } /* END OF FUNCTION ParseImmed */ /*************************************<->************************************* * * ParseKeySym (linePP, closure, detail) * * * Description: * ----------- * Key event detail procedure. Parses a KeySym string. * * * Inputs: * ------ * linePP = pointer to current line buffer pointer * * closure = not used. * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer * detail = pointer to parsed KeySym * * Return = (Boolean) true iff valid KeySym string * * * Comments: * -------- * None. * *************************************<->***********************************/ static Boolean ParseKeySym (unsigned char **linePP, unsigned int closure, unsigned int *detail) { unsigned char *lineP = *linePP; unsigned char *startP; char keySymName[MAX_KEYSYM_STRLEN+1]; int len; int chlen; ScanWhitespace (&lineP); startP = lineP; while (*lineP && ((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 0) && ((chlen > 1) || (!isspace (*lineP) && *lineP != ',' && *lineP != ':'))) { /* Skip next character */ lineP += chlen; } len = min (lineP - startP, MAX_KEYSYM_STRLEN); (void) strncpy (keySymName, (char *)startP, len); keySymName[len] = '\0'; if ((*detail = XStringToKeysym(keySymName)) == NoSymbol && (mblen (keySymName, MB_CUR_MAX) == 1)) { if (!isdigit (keySymName[0]) || ((*detail = StrToNum ((unsigned char *)&keySymName[0])) == -1)) { *detail = NoSymbol; return (FALSE); } } *linePP = lineP; return (TRUE); } /* END OF FUNCTION ParseKeySym */ /*************************************<->************************************* * * StrToNum(str) * * * Description: * ----------- * Converts a string to an unsigned hexadecimal, decimal, or octal integer. * * * Inputs: * ------ * str = character string * * * Outputs: * ------- * Return = unsigned integer * * * Comments: * -------- * None. * *************************************<->***********************************/ static unsigned int StrToNum(unsigned char *str) { unsigned char c; unsigned int val = 0; if (*str == '0') { str++; if (*str == 'x' || *str == 'X') { return (StrToHex(++str)); } return (StrToOct(str)); } while ((c = *str) != '\0') { if ('0' <= c && c <= '9') { val = val*10+c-'0'; } else { return (-1); } str++; } return (val); } /* END OF FUNCTION StrToNum */ /*************************************<->************************************* * * * * Description: * ----------- * * Inputs: * ------ * * * Outputs: * ------- * * Comments: * -------- * None. * *************************************<->***********************************/ static unsigned int StrToHex(unsigned char *str) { unsigned char c; unsigned int val = 0; while ((c = *str) != '\0') { if ('0' <= c && c <= '9') { val = val*16+c-'0'; } else if ('a' <= c && c <= 'f') { val = val*16+c-'a'+10; } else if ('A' <= c && c <= 'F') { val = val*16+c-'A'+10; } else { return (-1); } str++; } return (val); } /* END OF FUNCTION StrToHex */ /*************************************<->************************************* * * * * Description: * ----------- * * Inputs: * ------ * * * Outputs: * ------- * * Comments: * -------- * None. * *************************************<->***********************************/ static unsigned int StrToOct(unsigned char *str) { unsigned char c; unsigned int val = 0; while ((c = *str) != '\0') { if ('0' <= c && c <= '7') { val = val*8+c-'0'; } else { return (-1); } str++; } return (val); } /* END OF FUNCTION StrToOct */ /*************************************<->************************************* * * ScanAlphanumeric (linePP) * * * Description: * ----------- * Scan string until a non-alphanumeric character is encountered. * * * Inputs: * ------ * linePP = nonNULL pointer to current line buffer pointer * * * Outputs: * ------- * linePP = nonNULL pointer to revised line buffer pointer * * * Comments: * -------- * Assumes linePP is nonNULL * *************************************<->***********************************/ void ScanAlphanumeric (unsigned char **linePP) { int chlen; while (*linePP && ((chlen = mblen ((char *) *linePP, MB_CUR_MAX)) > 0) && ((chlen > 1) || isalnum (**linePP))) { (*linePP) += chlen; } } /* END OF FUNCTION ScanAlphanumeric */ /*************************************<->************************************* * * PWarning (message) * * * Description: * ----------- * This function lists a resource description parse message to stderr. * * * Inputs: * ------ * message = pointer to a message string * cfileP = (global) file pointer to fopened configuration file or NULL * linec = (global) line counter * *************************************<->***********************************/ void PWarning (char *message) { char pch[MAXWMPATH+1]; String sMessage; char *pchFile; sMessage = XtNewString ((String) message); if (cfileP != NULL) { if (pConfigStackTop->fileName) { pchFile = pConfigStackTop->fileName; } else { pchFile = wmGD.configFile; } sprintf (pch, pWarningStringFile, GETMESSAGE(20,1,"Workspace Manager"), sMessage, linec, pchFile); } else { sprintf (pch, pWarningStringLine, GETMESSAGE(20,1,"Workspace Manager"), sMessage, linec); } _DtSimpleError (wmGD.mwmName, DtIgnore, NULL, pch, NULL); XtFree (sMessage); } /* END OF FUNCTION PWarning */ /* * Key substitution table entry */ typedef struct _keySubs { unsigned char * pchFrom; int lenFrom; unsigned char * pchTo; } KeySub; /*************************************<->************************************* * * InitKeySubs (ppKeySubs, pNumKeySubs) * * * Description: * ----------- * Initialize key label substitutions used in acclerator text * * * Inputs: * ------ * ppKeySubs = ptr to key substitution table ptr * pNumKeySubs = ptr to number of key substitutions * * * Outputs: * ------- * *ppKeySubs = ptr to key substitution table * *pNumKeySubs = number of substitutions found * * Comments: * -------- * *ppKeySubs is allocated with XtMalloc in a complicated way. * If this ever needs to be freed, a function to free it needs to * be written. * *************************************<->***********************************/ static void InitKeySubs ( KeySub **ppKeySubs, int *pNumKeySubs) { int numKS; KeySub *pKS; KeySub *pKSret; unsigned char *pch0; unsigned char *pch1; int len; int chlen; pch0 = (unsigned char *)GETMESSAGE(60, 40, ""); if ((pch0 == NULL) || (*pch0 == '\0')) { *ppKeySubs = NULL; *pNumKeySubs = 0; return; } pKSret = NULL; numKS = 0; while (*pch0 != '\0') { ScanWhitespace (&pch0); if (*pch0 == '\0') break; /* * allocate space for next key sub */ if (pKSret == NULL) { pKSret = (KeySub *) XtMalloc (1*sizeof(KeySub)); } else { pKSret = (KeySub *) XtRealloc ((char *)pKSret, (numKS+1)*sizeof(KeySub)); } pKS = &pKSret[numKS]; /* get "from" string */ pch1 = pch0; while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0)) { if ((chlen == 1) && (*pch1 == ' ')) { break; } pch1 += chlen; } pKS->lenFrom = pch1 - pch0; if (pKS->lenFrom < 1) { /* * no "from" string */ break; } pKS->pchFrom = (unsigned char *) XtMalloc (1+pKS->lenFrom); memcpy (pKS->pchFrom, pch0, pKS->lenFrom); pKS->pchFrom[pKS->lenFrom] = '\0'; /* get "to" string */ ScanWhitespace (&pch1); pch0 = pch1; while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0)) { if ((chlen == 1) && (*pch1 == ' ')) { break; } pch1 += chlen; } len = pch1 - pch0; if (len < 1) { /* * Invalid format, "from" string with no "to" string. */ break; } pKS->pchTo = (unsigned char *) XtMalloc (1+len); memcpy (pKS->pchTo, pch0, len); pKS->pchTo[len] = '\0'; /* advance cursor */ pch0 = pch1; /* got one, bump the counter */ numKS++; } *ppKeySubs = pKSret; *pNumKeySubs = numKS; } /*************************************<->************************************* * * ProcessAccelText (startP, endP, destP) * * * Description: * ----------- * Process accelerator text and copy into string. * * * Inputs: * ------ * startP = pointer to start of valid accelerator specification * endP = pointer past end of accelerator specification * destP = pointer to destination buffer * * * Outputs: * ------- * Destination buffer has processed accelerator text. * * Comments: * -------- * None. * *************************************<->***********************************/ static void ProcessAccelText (unsigned char *startP, unsigned char *endP, unsigned char *destP) { int chlen; static Boolean bAccelInit = False; static KeySub *pKeySub; static int numKeySubs; unsigned char * pchFirst; unsigned char * pchSub; int lenSub; int i; if (!bAccelInit) { InitKeySubs (&pKeySub, &numKeySubs); bAccelInit = True; } /* * Copy modifiers */ ScanWhitespace (&startP); while (*startP != '<') { if (*startP == '~') { *destP++ = *startP++; } pchFirst = startP; while (*startP && (((chlen = mblen ((char *)startP, MB_CUR_MAX)) > 1) || isalnum (*startP))) { while (chlen--) { startP++; } } /* find substitution */ pchSub = NULL; lenSub = 0; for (i=0; i 0)) { memcpy (destP, pchSub, lenSub); destP += lenSub; } else { memcpy (destP, pchFirst, startP-pchFirst); destP += startP-pchFirst; } *destP++ = '+'; ScanWhitespace (&startP); } /* * Skip the key event type. */ startP++; /* skip '<' */ while (*startP != '>') { startP += mblen ((char *)startP, MB_CUR_MAX); } startP++; /* skip '>' */ /* * Copy the KeySym string. */ ScanWhitespace (&startP); while (startP != endP) { *destP++ = *startP++; } *destP = '\0'; } /* END OF FUNCTION ProcessAccelText */ /*************************************<->************************************* * * ProcessCommandLine (argc, argv) * * * Description: * ----------- * This function looks for and processes mwm options in the command line * * Inputs: * ------ * argc = argument count. * argv = argument vector. * * * Outputs: * ------- * Changes global data to based on command line options recognized * * *************************************<->***********************************/ #define SCREENS_OPT "-screens" #define MULTI_SCREEN_OPT "-multiscreen" void ProcessCommandLine (int argc, char *argv[]) { unsigned char *string; int argnum; unsigned char *lineP; for (argnum = 1; argnum < argc; argnum++) { lineP = (unsigned char *) argv[argnum]; if ((string = GetString (&lineP)) == NULL) /* empty or comment line */ { continue; } if (!strcmp((char *)string, MULTI_SCREEN_OPT)) { wmGD.multiScreen = True; wmGD.numScreens = ScreenCount (DISPLAY); } else if (!strcmp((char *)string, SCREENS_OPT)) { argnum++; /* skip to next arg */ ParseScreensArgument (argc, argv, &argnum, lineP); } } } /* END OF FUNCTION ProcessCommandLine */ /*************************************<->************************************* * * ParseScreensArgument (argc, argv, pArgnum, lineP) * * * Description: * ----------- * This function processes the ``-screens'' command line argument * * Inputs: * ------ * argc = argument count. * argv = argument vector. * pArgnum = pointer to argument number where processing left off * lineP = pointer into argv[*pArgnum] where processing left off * * * Outputs: * ------- * Changes global data to based on command line options recognized * + wmGD.screenNames * + wmGD.numScreens * Assumes default screenNames are already in place * *************************************<->***********************************/ static void ParseScreensArgument (int argc, char *argv[], int *pArgnum, unsigned char *lineP) { unsigned char *string; int sNum = 0; int lastLen; int nameCount = 0; for (; (*pArgnum < argc) && (sNum < ScreenCount(DISPLAY)); (*pArgnum)++, sNum++) { lineP = (unsigned char *)argv[*pArgnum]; if (*argv[*pArgnum] == '"') { /* * if Quote, use GetString to strip it */ if ((string = GetString (&lineP)) == NULL) /* empty or comment line */ { continue; } } else { string = (unsigned char *)argv[*pArgnum]; if (*string == '-') { /* another option, end of screens names */ break; } } if (!(wmGD.screenNames[sNum] = (unsigned char *) XtRealloc ((char*)wmGD.screenNames[sNum], 1 + strlen((char *)string)))) { Warning (((char *)GETMESSAGE(60, 31, "Insufficient memory for screen names"))); ExitWM(WM_ERROR_EXIT_VALUE); } else { strcpy((char *)wmGD.screenNames[sNum], (char *)string); nameCount++; } } (*pArgnum)--; /* * remaining screens (if any) get first name specified */ if (nameCount > 0) { lastLen = 1 + strlen((char *)wmGD.screenNames[0]); for (; sNum < ScreenCount(DISPLAY); sNum++) { if (!(wmGD.screenNames[sNum] = (unsigned char *) XtRealloc ((char*)wmGD.screenNames[sNum], lastLen))) { Warning (((char *)GETMESSAGE(60, 32, "Insufficient memory for screen names"))); ExitWM(WM_ERROR_EXIT_VALUE); } else { strcpy((char *)wmGD.screenNames[sNum], (char *)wmGD.screenNames[0]); } } } } /* END OF FUNCTION ParseScreensArgument */ /*************************************<->************************************* * * ProcessMotifBindings () * * * Description: * ----------- * This function is used retrieve the motif input bindings * and put them into a property on the root window. * * *************************************<->***********************************/ void ProcessMotifBindings (void) { char fileName[MAXWMPATH+1]; char *bindings = NULL; char *homeDir = XmeGetHomeDirName(); /* * Look in the user's home directory for .motifbind */ strcpy (fileName, homeDir); strncat(fileName, "/", MAXWMPATH-strlen(fileName)); strncat(fileName, MOTIF_BINDINGS_FILE, MAXWMPATH-strlen(fileName)); XDeleteProperty (DISPLAY, RootWindow (DISPLAY, 0), XInternAtom (DISPLAY, "_MOTIF_BINDINGS", False)); XDeleteProperty (DISPLAY, RootWindow (DISPLAY, 0), XInternAtom (DISPLAY, "_MOTIF_DEFAULT_BINDINGS", False)); if (_XmVirtKeysLoadFileBindings (fileName, &bindings) == True) { XChangeProperty (DISPLAY, RootWindow(DISPLAY, 0), XInternAtom (DISPLAY, "_MOTIF_BINDINGS", False), XA_STRING, 8, PropModeReplace, (unsigned char *)bindings, strlen(bindings)); } else { _XmVirtKeysLoadFallbackBindings (DISPLAY, &bindings); } XtFree (bindings); } /* END OF FUNCTION ProcessMotifBindings */ /*************************************<->************************************* * * void * ParseWmFunctionArg (linePP, ix, wmFunc, ppArg, sClientName) * * * Description: * ----------- * Parse the function arguments for a window manager function. * * * Inputs: * ------ * linePP = pointer to line buffer pointer (contains string arg). * ix = window manager function index (returned by ParseWmFunction) * pWmFunction = pointer to window manager function destination. * ppArg = ptr to argument pointer. * sClientName = string name of client * * * Outputs: * ------- * *ppArg = arg to pass to window manager function when invoking. * Return = true on succes, false on some kind of parse error * * * Comments: * -------- * functionTable (window manager function table) is indexed with ix * to get parsing info. * * This function may malloc memory for the returned arg. * * The sClientName is needed for starting some hpterm-based push_recall * clients. It needs to be passed into the action so the hpterm gets * named appropriately. * *************************************<->***********************************/ Boolean ParseWmFunctionArg ( unsigned char **linePP, int ix, WmFunction wmFunc, void **ppArg, String sClientName, String sTitle) { unsigned char *lineP = *linePP; Boolean bValidArg = True; unsigned char *str = NULL; /* * If this is (possibly) a string argument, put it * in quotes so that it will be parsed properly. */ if ((functionTable[ix].parseProc == ParseWmFuncStrArg) || (functionTable[ix].parseProc == ParseWmFuncMaybeStrArg)) { if (lineP && *lineP != '"') { /* * not in quotes, repackage it, escaping the appropriate * characters. */ str = _DtWmParseMakeQuotedString (lineP); if (str) { lineP = str; } } } /* * Apply the function argument parser. */ if ((functionTable[ix].wmFunction != wmFunc) || !(*(functionTable [ix].parseProc)) (&lineP, wmFunc, ppArg)) { bValidArg = False; } /* * Add the exec parms if this is an f.action */ if ((wmFunc == F_Action) && ppArg && *ppArg) { WmActionArg *pAP = (WmActionArg *) *ppArg; int totLen = 0; /* * allocate more than enough string space to copy * strings and intervening spaces. */ if (sClientName && *sClientName) { /* length of: "name=" + sClientName + NULL */ totLen += 5 + strlen(sClientName) + 1; } if (sTitle && *sTitle) { /* length of: "," + "title=" + sTitle + NULL */ totLen += 1 + 6 + strlen(sTitle) + 1; } if (totLen > 0) { pAP->szExecParms = (String) XtMalloc (totLen); /* start with empty string */ pAP->szExecParms[0] = '\0'; if (sClientName && *sClientName) { strcat (pAP->szExecParms, "name="); strcat (pAP->szExecParms, sClientName); } if (sTitle && *sTitle) { if (pAP->szExecParms[0] != '\0') { strcat (pAP->szExecParms, ","); } strcat (pAP->szExecParms, "title="); strcat (pAP->szExecParms, sTitle); } } } if (str) { XtFree ((char *) str); } return (bValidArg); } /* END OF FUNCTION ParseWmFunctionArg */ /*************************************<->************************************* * * SystemCmd (pchCmd) * * * Description: * ----------- * This function fiddles with our signal handling and calls the * system() function to invoke a unix command. * * * Inputs: * ------ * pchCmd = string with the command we want to exec. * * Outputs: * ------- * * * Comments: * -------- * The system() command is touchy about the SIGCLD behavior. Restore * the default SIGCLD handler during the time we run system(). * *************************************<->***********************************/ void SystemCmd (char *pchCmd) { struct sigaction sa; struct sigaction osa; (void) sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_DFL; (void) sigaction (SIGCHLD, &sa, &osa); system (pchCmd); (void) sigaction (SIGCHLD, &osa, (struct sigaction *) 0); } /*************************************<->************************************* * * DeleteTempConfigFileIfAny () * * * Description: * ----------- * This function deletes the temporary config file used to process * old dtwmrc syntax. * * * Inputs: * ------ * * * Outputs: * ------- * * * Comments: * -------- * *************************************<->***********************************/ void DeleteTempConfigFileIfAny (void) { char pchCmd[MAXWMPATH+1]; if (pConfigStackTop->tempName) { strcpy (pchCmd, "/bin/rm "); strcat (pchCmd, pConfigStackTop->tempName); SystemCmd (pchCmd); XtFree ((char *) pConfigStackTop->tempName); pConfigStackTop->tempName = NULL; } if (pConfigStackTop->cppName) { strcpy (pchCmd, "/bin/rm "); strcat (pchCmd, pConfigStackTop->cppName); SystemCmd (pchCmd); XtFree ((char *) pConfigStackTop->cppName); pConfigStackTop->cppName = NULL; } } /*************************************<->************************************* * * ParseIncludeSet (pSD, lineP) * * * Description: * ----------- * * * Inputs: * ------ * cfileP = (global) file pointer to fopened configuration file or NULL * lineP = pointer to line buffer * line = (global) line buffer * linec = (global) line count * parseP = (global) parse string pointer if cfileP == NULL * pSD->rootWindow = default root window of display * * Outputs: * ------- * linec = (global) line count incremented * parseP = (global) parse string pointer if cfileP == NULL * * * Comments: * -------- * *************************************<->***********************************/ static void ParseIncludeSet (WmScreenData *pSD, unsigned char *lineP) { unsigned char *string; unsigned char *pchName; /* * Require leading '{' on the next line. */ while ((GetNextLine () != NULL)) /* not EOF nor read error */ { lineP = line; ScanWhitespace(&lineP); if ((lineP == NULL) || (*line == '!') || (*lineP == '\0') || (*lineP == '#')) /* ignore empty or comment line */ { continue; } if (*lineP == '{') /* found '{' */ { break; } /* not a '{' */ PWarning (((char *)GETMESSAGE(60, 37, "Expected '{'"))); return; } /* * Found leading "{" or EOF. * Parse include files until "}" or EOF found. */ while ((GetNextLine () != NULL)) { lineP = line; if ((*line == '!') || (string = GetString (&lineP)) == NULL) /* ignore empty or comment lines */ { continue; } if (*string == '}') /* finished with set. */ { break; } pchName = _DtWmParseFilenameExpand (string); if (pchName && ConfigStackPush (pchName)) { ProcessWmFile (pSD, True /* nested */); ConfigStackPop (); XtFree ((char *) pchName); } } } /*************************************<->************************************* * * ConfigStackInit (pchFileName) * * * Description: * ----------- * Initializes the config file processing stack * * Inputs: * ------ * pchFileName = name of new file to start parsing * * Outputs: * ------- * * * Comments: * -------- * *************************************<->***********************************/ static void ConfigStackInit (char *pchFileName) { pConfigStack = XtNew (ConfigFileStackEntry); if (pConfigStack) { pConfigStackTop = pConfigStack; pConfigStackTop->fileName = XtNewString (pchFileName); pConfigStackTop->tempName = NULL; pConfigStackTop->cppName = NULL; pConfigStackTop->offset = 0; pConfigStackTop->pWmPB = wmGD.pWmPB; pConfigStackTop->wmgdConfigFile = wmGD.configFile; pConfigStackTop->pIncluder = NULL; } else { sprintf ((char *)wmGD.tmpBuffer, (char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"), pchFileName); Warning ((char *)wmGD.tmpBuffer); } } /*************************************<->************************************* * * ConfigStackPush (pchFileName) * * * Description: * ----------- * Open an included config file * * Inputs: * ------ * pchFileName = name of new file to start parsing * wmGD.pWmPB = global parse buffer (pickle this) * * Outputs: * ------- * wmGD.pWmPB = global parse buffer (new one for new file) * return = FILE * to open file or NULL * * * Comments: * -------- * *************************************<->***********************************/ static FILE * ConfigStackPush (unsigned char *pchFileName) { ConfigFileStackEntry *pEntry; FILE *pNewFile = NULL; pEntry = XtNew (ConfigFileStackEntry); if (pEntry) { /* save off state of current config file */ pConfigStackTop->offset = ftell (cfileP); pConfigStackTop->pWmPB = wmGD.pWmPB; fclose (cfileP); /* set up state of new config file */ pEntry->fileName = XtNewString ((char *)pchFileName); pEntry->tempName = NULL; pEntry->cppName = NULL; pEntry->wmgdConfigFile = (String) pEntry->fileName; /* set globals for new config file */ wmGD.pWmPB = _DtWmParseNewBuf (); wmGD.configFile = pEntry->wmgdConfigFile; /* put new entry onto stack */ pEntry->pIncluder = pConfigStackTop; pConfigStackTop = pEntry; /* open the file */ pNewFile = cfileP = FopenConfigFile(); if (!pNewFile) { /* file open failed! back out */ ConfigStackPop (); } } else { sprintf ((char *)wmGD.tmpBuffer, (char *)GETMESSAGE(60,36,"Insufficient memory to process included file: %s"), pchFileName); Warning ((char *)wmGD.tmpBuffer); } return (pNewFile); } /*************************************<->************************************* * * ConfigStackPop () * * * Description: * ----------- * * * Inputs: * ------ * pchFileName = name of new file to start parsing * wmGD.pWmPB = global parse buffer (pickle this) * * Outputs: * ------- * wmGD.pWmPB = global parse buffer (new one for new file) * * * Comments: * -------- * assumes cfileP is closed already * *************************************<->***********************************/ static void ConfigStackPop (void) { ConfigFileStackEntry *pPrev; char pchCmd[MAXWMPATH+1]; if (pConfigStackTop != pConfigStack) { pPrev = pConfigStackTop->pIncluder; _DtWmParseDestroyBuf (wmGD.pWmPB); if (pConfigStackTop->tempName) { XtFree (pConfigStackTop->tempName); } if (pConfigStackTop->cppName) { strcpy (pchCmd, "/bin/rm "); strcat (pchCmd, pConfigStackTop->cppName); SystemCmd (pchCmd); XtFree ((char *) pConfigStackTop->cppName); pConfigStackTop->cppName = NULL; } if (pConfigStackTop->fileName) { XtFree (pConfigStackTop->fileName); } wmGD.pWmPB = pPrev->pWmPB; wmGD.configFile = pPrev->wmgdConfigFile; if (pPrev->tempName) { cfileP = fopen (pPrev->tempName, "r"); } else if (pPrev->cppName) { cfileP = fopen (pPrev->cppName, "r"); } else { cfileP = fopen (pPrev->fileName, "r"); } if (cfileP) { fseek (cfileP, pPrev->offset, 0); } else { char msg[MAXWMPATH+1]; sprintf(msg, ((char *)GETMESSAGE(60, 39, "Could not reopen configuration file %s")), pPrev->fileName); Warning (msg); } XtFree ((char *)pConfigStackTop); pConfigStackTop = pPrev; } } /*************************************<->************************************* * * ParseWmFuncActionArg (linePP, wmFunction, pArgs) * * * Description: * ----------- * Parses a window manager f.action argument * * * Inputs: * ------ * linePP = pointer to current line buffer pointer. * wmFunction = function for which the argument string is intended. * pArgs = pointer to argument destination. * * * Outputs: * ------- * linePP = pointer to revised line buffer pointer. * pArgs = pointer to parsed argument. * Return = FALSE iff insufficient memory * * * Comments: * -------- * *************************************<->***********************************/ Boolean ParseWmFuncActionArg (unsigned char **linePP, WmFunction wmFunction, String *pArgs) { #define WM_ACTION_ARG_INCREMENT 5 #define WM_ACTION_ARG_PAD 256 unsigned char *string; char *pch; WmActionArg *pAP; int iArgSz; pAP = XtNew (WmActionArg); if (pAP && (string = GetString (linePP)) != NULL) { /* Got action name */ pAP->actionName = XtNewString ((char *) string); /* Get action arguments, if any */ if ((pAP->aap = (DtActionArg *) XtMalloc (WM_ACTION_ARG_INCREMENT * sizeof (DtActionArg)))) { iArgSz = WM_ACTION_ARG_INCREMENT; pAP->numArgs = 0; while ((string = GetString (linePP)) != NULL) { if ((pAP->aap[pAP->numArgs].u.file.name = (char *) XtMalloc(1 + strlen((char *)string)))) { pAP->aap[pAP->numArgs].argClass = DtACTION_FILE; /* format the action argument */ pch = pAP->aap[pAP->numArgs].u.file.name; /* * Expand environment variable */ if (string[0] == '$') { string = (unsigned char *) getenv ((char *)&string[1]); if (!string) { break; } else { /* * Make sure there's room for the new * string. */ pch = (char *) XtRealloc (pch, (1+strlen((char *)string))); pAP->aap[pAP->numArgs].u.file.name = pch; } } /* !!! No host name processing is done!!! */ strcpy (pch, (char *)string); pAP->numArgs++; if (pAP->numArgs == iArgSz) { /* need to increase our array space */ iArgSz += WM_ACTION_ARG_INCREMENT; pAP->aap = (DtActionArg *) XtRealloc((char *)pAP->aap, (iArgSz * sizeof (DtActionArg))); if (!pAP->aap) { break; /* out of memory */ } } } else { break; /* out of memory */ } } } pAP->szExecParms = NULL; *pArgs = (String) pAP; } else /* NULL string argument */ { *pArgs = NULL; } return (TRUE); } /* END OF FUNCTION ParseWmFuncActionArg */ /*************************************<->************************************* * * PreprocessConfigFile (pSD) * * * Description: * ----------- * This function runs the configuration file through the C * preprocessor * * * Inputs: * ------ * pSD = ptr to screen data * * Outputs: * ------- * * * Comments: * -------- * *************************************<->***********************************/ static void PreprocessConfigFile (void) { #define CPP_NAME_SIZE ((L_tmpnam)+1) char pchCmd[MAXWMPATH+1]; if (wmGD.cppCommand && *wmGD.cppCommand) { /* * Generate a temp file name. */ pConfigStackTop->cppName = XtMalloc (CPP_NAME_SIZE * sizeof(char)); if (pConfigStackTop->cppName) { (void) tmpnam (pConfigStackTop->cppName); /* * Build up the command line. */ strcpy (pchCmd, wmGD.cppCommand); strcat (pchCmd, " "); strcat (pchCmd, pConfigStackTop->fileName); strcat (pchCmd, " "); strcat (pchCmd, pConfigStackTop->cppName); /* * Run the config file through the converter program * and send the output to a temp file. */ SystemCmd (pchCmd); } } } /*************************************<->************************************* * * GetNetworkFileName (char *pchFile) * * * Description: * ----------- * This function returns a local representation for a network * file. * * * Inputs: * ------ * pchFile - pointer to file name of form [:] * * Return: * ------- * String - ptr to allocated string of local file name. If input * is not a network file, the a copy of pchFile is returned. * * * Comments: * -------- * returned file name should be freed with XtFree(). * *************************************<->***********************************/ static String GetNetworkFileName (char *pchFile) { char *pch; char *host_part; char *file_part; char *netfile; char *sName = NULL; char *pchName = NULL; int count; char **pchTok; String sReturn = NULL; char *homeDir; int len; pch = strchr (pchFile, ':'); if (pch) { /* * Expand special chars and find matching file. */ pchTok = (char **)shellscan (pchFile, &count, 0); if ((count == 1) || (count == 2)) { /* one match found */ host_part = pchTok[0]; } else if (count > 2) { /* several matches found, pick one */ host_part = pchTok[1]; } else { host_part = NULL; } if (host_part != NULL) { pch = strchr (host_part, ':'); if (pch) { /* * copy the string so we don't munge data * inside shellscan */ host_part = sName = XtNewString ((String) host_part); pch = strchr (sName, ':'); /* * separate the host and file parts of the * file name */ *pch = '\0'; file_part = pch+1; } else { /* * The colon went away. Hmm... */ file_part = host_part; host_part = NULL; } if ((mblen(file_part, MB_CUR_MAX) == 1) && (mblen(file_part+1, MB_CUR_MAX) == 1) && (*file_part == '~') && (*(file_part+1) == '/')) { /* * Replace '~' with $HOME */ homeDir = XmeGetHomeDirName(); len = strlen (host_part) + 1 + strlen (homeDir) + strlen (file_part) + 1; pch = (char *) XtMalloc (len); strcpy (pch, sName); host_part = pch; pch += strlen (pch) + 1; strcpy (pch, homeDir); strcat (pch, file_part+1); file_part = pch; XtFree (sName); sName = host_part; } } else { /* * shellscan had a problem with the file name. * just operate on the name as-is. * temporarily replace ':' with a NULL */ host_part = sName = XtNewString ((String) pchFile); pch = strchr (sName, ':'); *pch = '\0'; host_part = pchFile; file_part = pch+1; } /* convert to canonical host/file name */ netfile = (char *) tt_host_file_netfile (host_part, file_part); if (tt_pointer_error (netfile) == TT_OK) { /* convert to local file name equivalent */ pchName = tt_netfile_file (netfile); if (tt_pointer_error (pchName) == TT_OK) { sReturn = XtNewString ((String) pchName); tt_free ((char *)pchName); } tt_free (netfile); } if (sName) { XtFree ((char *)sName); } } if (sReturn == NULL) { if ((mblen(pchFile, MB_CUR_MAX) == 1) && (mblen(pchFile+1, MB_CUR_MAX) == 1) && (*pchFile == '~') && (*(pchFile+1) == '/')) { /* * Replace '~' with $HOME */ homeDir = XmeGetHomeDirName(); len = strlen (homeDir) + strlen (pchFile) + 1; sReturn = (char *) XtMalloc (len); strcpy (sReturn, homeDir); strcat (sReturn, pchFile+1); } else { sReturn = XtNewString ((String) pchFile); } } return (sReturn); } /**************************** eof ***************************/