6181 lines
139 KiB
C
6181 lines
139 KiB
C
/*
|
|
* 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 <Dt/UserMsg.h>
|
|
#include <Dt/Connect.h>
|
|
#include <Tt/tt_c.h>
|
|
#include "WmParse.h"
|
|
#include "WmParseP.h"
|
|
#include "WmPanelP.h"
|
|
#include "WmResource.h"
|
|
|
|
#include <codelibs/shellutils.h> /* shellscan */
|
|
|
|
#include <Xm/VirtKeysP.h>
|
|
#include <Xm/XmPrivate.h> /* _XmVirtKeysLoadFileBindings,
|
|
* _XmVirtKeysLoadFallbackBindings */
|
|
|
|
|
|
#include <X11/cursorfont.h>
|
|
#include <X11/keysym.h>
|
|
#include <X11/Xatom.h>
|
|
#include <ctype.h>
|
|
|
|
#include <locale.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <Xm/XmP.h> /* for XmeGetHomeDirName */
|
|
#include <signal.h>
|
|
|
|
/* 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 <errno.h>
|
|
# 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 = XKeycodeToKeysym(DISPLAY, map->modifiermap[k], 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<<i);
|
|
}
|
|
else if (nm && !strncmp("Meta", nm, 4))
|
|
{
|
|
modifierStrings[META_INDEX].mask = (1<<i);
|
|
}
|
|
}
|
|
k++;
|
|
}
|
|
}
|
|
|
|
XFreeModifiermap(map);
|
|
}
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* 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 ":<category>;", extract <category>
|
|
* 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 "<host>:<path>" form of file name
|
|
*/
|
|
pch = (char *) GetNetworkFileName (cfileName);
|
|
if ((fileP = fopen (cfileName, "r")) != NULL)
|
|
{
|
|
strncpy (cfileName, pch, MAXWMPATH);
|
|
XtFree (pch);
|
|
}
|
|
|
|
/*
|
|
* Either not "<host>:<path>" 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
|
|
* "<client command>[.<client command>]*"
|
|
* 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 = "@<bitmap_file>", and <bitmap_file> 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 = "@<bitmap file>"
|
|
* 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<numKeySubs; i++)
|
|
{
|
|
if ((pKeySub[i].lenFrom == startP-pchFirst) &&
|
|
(!strncasecmp ((char *)pKeySub[i].pchFrom, (char *)pchFirst,
|
|
pKeySub[i].lenFrom)))
|
|
{
|
|
pchSub = pKeySub[i].pchTo;
|
|
lenSub = strlen((char *)pchSub);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if ((pchSub != NULL) && (lenSub > 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 [<host>:]<path>
|
|
*
|
|
* 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 ***************************/
|
|
|