mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
7812 lines
179 KiB
C
7812 lines
179 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
|
||
*/
|
||
#ifdef REV_INFO
|
||
#ifndef lint
|
||
static char rcsid[] = "$XConsortium: WmResParse.c /main/9 1996/11/01 10:17:34 drk $"
|
||
#endif
|
||
#endif
|
||
/*
|
||
* (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"
|
||
#ifdef WSM
|
||
#include <Dt/UserMsg.h>
|
||
#include <Dt/Connect.h>
|
||
#include <Tt/tt_c.h>
|
||
#endif /* WSM */
|
||
#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>
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
#include <stdlib.h>
|
||
#endif
|
||
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
#include <stdio.h>
|
||
#include <pwd.h>
|
||
#else
|
||
#include <Xm/XmP.h> /* for XmeGetHomeDirName */
|
||
#endif
|
||
#ifdef WSM
|
||
#include <signal.h>
|
||
#endif /* WSM */
|
||
|
||
/* 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
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
# define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD, mSpec)
|
||
#else
|
||
# define PARSE_MENU_ITEMS(pSD, mSpec) ParseMenuItems(pSD)
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
/*
|
||
* include extern functions
|
||
*/
|
||
#include "WmResParse.h"
|
||
#ifdef WSM
|
||
#include "WmWrkspace.h"
|
||
#endif /* WSM */
|
||
#include "WmError.h"
|
||
#include "WmFunction.h"
|
||
#include "WmImage.h"
|
||
#include "WmXSMP.h"
|
||
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
extern char *getenv ();
|
||
#endif
|
||
# 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];
|
||
#ifdef WSM
|
||
#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)
|
||
#else /* WSM */
|
||
static FILE *cfileP = NULL; /* fopen'ed configuration file or NULL */
|
||
static unsigned char line[MAXLINE+1]; /* line buffer */
|
||
static int linec = 0; /* line counter for parser */
|
||
static unsigned char *parseP = NULL; /* pointer to parse string */
|
||
#endif /* WSM */
|
||
|
||
|
||
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;
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
|
||
# define CCI_USE_DEFAULT_NAME_TAG "DEFAULT_NAME"
|
||
|
||
String CCIEntryModifierNames[] = {
|
||
"none",
|
||
"inline",
|
||
"cascade",
|
||
"delimit",
|
||
"delimit_inline",
|
||
"delimit_cascade",
|
||
"exclude"
|
||
};
|
||
|
||
typedef enum {
|
||
NONE, /* internal only. */
|
||
INLINE, /* not supported. */
|
||
CASCADE,
|
||
DELIMIT,
|
||
DELIMIT_INLINE, /* not supported. */
|
||
DELIMIT_CASCADE,
|
||
EXCLUDE
|
||
} CCIEntryModifier;
|
||
|
||
typedef struct _CCIFuncArg {
|
||
CCIEntryModifier mod;
|
||
String cciEntry;
|
||
} CCIFuncArg;
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
void GetHomeDirName(String fileName);
|
||
#endif
|
||
#ifdef WSM
|
||
static String GetNetworkFileName (char *pchFile);
|
||
#endif /* WSM */
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
static MenuItem *MakeSeparatorTemplate (int);
|
||
static void ParseMenuItemName (unsigned char **linePP, MenuItem *menuItem);
|
||
static Boolean ParseClientCommand (unsigned char **linePP, MenuSpec *menuSpec,
|
||
MenuItem *menuItem, unsigned char *string,
|
||
Boolean *use_separators);
|
||
static void FixMenuItem (MenuSpec *menuSpec, MenuItem *menuItem);
|
||
static Boolean GetCCIModifier (String modString, CCIEntryModifier *mod);
|
||
static Boolean ParseWmFuncCCIArgs (unsigned char **linePP,
|
||
WmFunction wmFunction, String *pArgs);
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
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
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
, MenuSpec *menuSpec
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
);
|
||
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[] = {
|
||
#ifdef WSM
|
||
{"f.action", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Action,
|
||
ParseWmFuncActionArg},
|
||
#endif /* WSM */
|
||
{"f.beep", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Beep,
|
||
ParseWmFuncNoArg},
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
{"f.cci", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Nop,
|
||
ParseWmFuncCCIArgs},
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.create_workspace", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_CreateWorkspace,
|
||
ParseWmFuncNoArg},
|
||
{"f.delete_workspace", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_DeleteWorkspace,
|
||
ParseWmFuncNoArg},
|
||
#endif /* WSM */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.goto_workspace", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Goto_Workspace,
|
||
ParseWmFuncStrArg},
|
||
#endif /* WSM */
|
||
#ifdef WSM
|
||
{"f.help", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Help,
|
||
ParseWmFuncStrArg}, /* [helpvolume && helptopic] */
|
||
{"f.help_mode", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Help_Mode,
|
||
ParseWmFuncNoArg}, /* for now */
|
||
#endif /* WSM */
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
{"f.invoke_command",
|
||
0, CRS_ANY,
|
||
0,
|
||
F_InvokeCommand,
|
||
ParseWmFuncStrArg},
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.marquee_selection",
|
||
F_CONTEXT_WINDOW|F_CONTEXT_ICON|F_SUBCONTEXT_IB_IICON,
|
||
CRS_ANY,
|
||
0,
|
||
F_Marquee_Selection,
|
||
ParseWmFuncNoArg},
|
||
#endif /* WSM */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.next_workspace", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Next_Workspace,
|
||
ParseWmFuncNoArg},
|
||
#endif /* WSM */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.occupy_all", F_CONTEXT_ICONBOX|F_CONTEXT_ROOT,
|
||
CRS_ANY,
|
||
DtWM_FUNC_OCCUPY_WS,
|
||
F_AddToAllWorkspaces,
|
||
ParseWmFuncNoArg},
|
||
#endif /* WSM */
|
||
{"f.pack_icons", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Pack_Icons,
|
||
ParseWmFuncNoArg},
|
||
{"f.pass_keys", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Pass_Key,
|
||
ParseWmFuncNoArg},
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
{"f.post_rmenu", 0,
|
||
CRS_KEY,
|
||
0,
|
||
F_Post_RMenu,
|
||
ParseWmFuncNoArg},
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.prev_workspace", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Prev_Workspace,
|
||
ParseWmFuncNoArg},
|
||
#endif /* WSM */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.remove", F_CONTEXT_ROOT,
|
||
CRS_ANY,
|
||
DtWM_FUNC_OCCUPY_WS,
|
||
F_Remove,
|
||
ParseWmFuncNoArg},
|
||
#endif /* WSM */
|
||
{"f.resize", F_CONTEXT_ICON|F_CONTEXT_ROOT|
|
||
F_SUBCONTEXT_IB_IICON|F_SUBCONTEXT_IB_WICON,
|
||
CRS_ANY,
|
||
MWM_FUNC_RESIZE,
|
||
F_Resize,
|
||
ParseWmFuncNoArg},
|
||
#ifdef WSM
|
||
{"f.restart", F_CONTEXT_ICON|F_CONTEXT_WINDOW,
|
||
CRS_ANY,
|
||
0,
|
||
F_Restart,
|
||
ParseWmFuncStrArg},
|
||
#else /* WSM */
|
||
{"f.restart", F_CONTEXT_ICON|F_CONTEXT_WINDOW,
|
||
CRS_ANY,
|
||
0,
|
||
F_Restart,
|
||
ParseWmFuncNoArg},
|
||
#endif /* WSM */
|
||
{"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},
|
||
#ifdef WSM
|
||
{"f.set_context", 0,
|
||
CRS_ANY,
|
||
0,
|
||
F_Set_Context,
|
||
ParseWmFuncNbrArg},
|
||
#endif /* WSM */
|
||
{"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 WSM
|
||
|
||
#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},
|
||
#endif /* WSM */
|
||
#if defined(DEBUG) && defined(WSM)
|
||
{"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.
|
||
*/
|
||
#ifdef WSM
|
||
# if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
# define F_CCI_INDEX 2
|
||
# endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
int F_ACTION_INDEX;
|
||
int F_EXEC_INDEX;
|
||
int F_NOP_INDEX;
|
||
#else /* WSM */
|
||
# if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
# define F_CCI_INDEX 1
|
||
# define F_EXEC_INDEX 4
|
||
# define F_NOP_INDEX 16
|
||
# else
|
||
# define F_EXEC_INDEX 3
|
||
# define F_NOP_INDEX 14
|
||
# endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
#endif /* WSM */
|
||
#ifdef WSM
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* 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;
|
||
#ifndef NO_MULTIBYTE
|
||
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++;
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
while((*currentChar != NULL) && (done == False) &&
|
||
((*currentChar == '"') || (*currentChar == '\\')))
|
||
{
|
||
currentChar++;
|
||
if((*currentChar != NULL) &&
|
||
((*currentChar == '"') || (*currentChar == '\\')))
|
||
{
|
||
tmpLev++;
|
||
if(*currentChar == '"')
|
||
{
|
||
done = True;
|
||
}
|
||
else
|
||
{
|
||
currentChar++;
|
||
}
|
||
}
|
||
}
|
||
#endif /*NO_MULTIBYTE*/
|
||
|
||
/*
|
||
* 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 */
|
||
|
||
|
||
#endif /* WSM */
|
||
|
||
|
||
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
/*************************************<->*************************************
|
||
*
|
||
* GetHomeDirName (fileName)
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function finds the "HOME" directory
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* fileName
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* fileName
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*************************************<->***********************************/
|
||
void GetHomeDirName(String fileName)
|
||
{
|
||
int uid;
|
||
struct passwd *pw;
|
||
char *ptr = NULL;
|
||
|
||
if((ptr = getenv("HOME")) == NULL)
|
||
{
|
||
if((ptr = getenv("USER")) != NULL)
|
||
{
|
||
pw = getpwnam(ptr);
|
||
}
|
||
else
|
||
{
|
||
uid = getuid();
|
||
pw = getpwuid(uid);
|
||
}
|
||
|
||
if (pw)
|
||
{
|
||
ptr = pw->pw_dir;
|
||
}
|
||
else
|
||
{
|
||
ptr = "";
|
||
}
|
||
}
|
||
strcpy(fileName, ptr);
|
||
}
|
||
#endif
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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;
|
||
|
||
#ifdef WSM
|
||
/**** hhhhhhhhhhhh ******/
|
||
GetFunctionTableValues (&F_EXEC_INDEX, &F_NOP_INDEX, &F_ACTION_INDEX);
|
||
#endif /* WSM */
|
||
/*
|
||
* 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(lang)
|
||
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;
|
||
}
|
||
|
||
#ifdef WSM
|
||
#define RC_CONFIG_SUBDIR "/config/"
|
||
#define RC_DEFAULT_CONFIG_SUBDIR "/config/C"
|
||
#endif /* WSM */
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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;
|
||
|
||
#ifndef MOTIF_ONE_DOT_ONE
|
||
char *homeDir = XmeGetHomeDirName();
|
||
#endif
|
||
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 "~/..." */
|
||
{
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
GetHomeDirName(cfileName);
|
||
#else
|
||
strcpy (cfileName, homeDir);
|
||
#endif
|
||
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
|
||
*/
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
GetHomeDirName(cfileName);
|
||
#else
|
||
strcpy (cfileName, homeDir);
|
||
#endif
|
||
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"
|
||
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
GetHomeDirName(cfileName);
|
||
#else
|
||
strcpy (cfileName, homeDir);
|
||
#endif
|
||
|
||
#ifdef WSM
|
||
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));
|
||
}
|
||
#else /* WSM */
|
||
if (LANG != NULL)
|
||
{
|
||
strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
|
||
strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
|
||
}
|
||
strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
|
||
#endif /* WSM */
|
||
if ((fileP = fopen (cfileName, "r")) != NULL)
|
||
{
|
||
if (LANG != NULL) {
|
||
XtFree(LANG);
|
||
LANG = NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Just try $HOME/.mwmrc
|
||
*/
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
GetHomeDirName(cfileName);
|
||
#else
|
||
strcpy (cfileName, homeDir);
|
||
#endif
|
||
#ifdef WSM
|
||
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));
|
||
}
|
||
#else /* WSM */
|
||
strncat(cfileName, HOME_MWMRC, MAXWMPATH - strlen(cfileName));
|
||
#endif /* WSM */
|
||
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)
|
||
{
|
||
#ifdef WSM
|
||
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));
|
||
}
|
||
#else /* WSM */
|
||
/*
|
||
* Try /$LANG/system.mwmrc within the install tree
|
||
*/
|
||
strcpy(cfileName, LIBDIR);
|
||
strncat(cfileName, "/", MAXWMPATH-strlen(cfileName));
|
||
strncat(cfileName, LANG, MAXWMPATH-strlen(cfileName));
|
||
strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
|
||
#endif /* WSM */
|
||
if ((fileP = fopen (cfileName, "r")) != NULL)
|
||
{
|
||
XtFree(LANG);
|
||
LANG = NULL;
|
||
}
|
||
}
|
||
|
||
if ((fileP == NULL) && !stackPushed)
|
||
{
|
||
#ifdef WSM
|
||
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");
|
||
}
|
||
#else /* WSM */
|
||
/*
|
||
* Try /system.mwmrc within the install tree
|
||
*/
|
||
strcpy(cfileName, LIBDIR);
|
||
strncat(cfileName, SLASH_MWMRC, MAXWMPATH - strlen(cfileName));
|
||
|
||
if (LANG != NULL)
|
||
{
|
||
XtFree(LANG);
|
||
LANG = NULL;
|
||
}
|
||
strcpy(cfileName, cfileName);
|
||
fileP = fopen (cfileName, "r");
|
||
#endif /* WSM */
|
||
}
|
||
}
|
||
|
||
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;
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
menuSpec->exclusions = NULL;
|
||
menuSpec->clientLocal = FALSE;
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
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
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
, MenuSpec *menuSpec
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
)
|
||
{
|
||
unsigned char *string;
|
||
unsigned char *lineP;
|
||
MenuItem *firstMenuItem;
|
||
MenuItem *lastMenuItem;
|
||
MenuItem *menuItem;
|
||
register int ix;
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
Boolean use_separators = False;
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
/*
|
||
* 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;
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
menuItem->clientCommandName = NULL;
|
||
menuItem->clientCommandID = 0;
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/*
|
||
* Is this a simple menu item label or is it a
|
||
* client command specification.
|
||
*/
|
||
|
||
if (IsClientCommand((String) string))
|
||
{
|
||
if (!ParseClientCommand(&lineP, menuSpec, menuItem, string,
|
||
&use_separators))
|
||
{
|
||
XtFree ((char *)menuItem);
|
||
continue;
|
||
}
|
||
|
||
for (ix = 0; ix < WMFUNCTIONTABLESIZE - 1; ++ix)
|
||
if (functionTable[ix].wmFunction == F_InvokeCommand)
|
||
break;
|
||
|
||
if (ix == WMFUNCTIONTABLESIZE - 1)
|
||
{
|
||
ix = F_NOP_INDEX;
|
||
menuItem->wmFunction = F_Nop;
|
||
}
|
||
else menuItem->wmFunction = F_InvokeCommand;
|
||
}
|
||
else /* It must be a menu item label */
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
{
|
||
/*
|
||
* 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.
|
||
*/
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
if (menuItem->wmFunction != NULL)
|
||
ParseMenuItemName(&lineP, menuItem);
|
||
else
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
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 */
|
||
}
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/*
|
||
* If we're working on the f.cci function, this will fix-up
|
||
* the menuItem entries so that it appears that we read-in
|
||
* an old-style client-command entry. Eventually, the cci
|
||
* handling should be changed to make use of the wmFuncArgs.
|
||
* Note that if DEFAULT_NAME was specified as the label, it
|
||
* is first set to NULL.
|
||
* FixMenuItem needs menuSpec since this is when the EXCLUDE
|
||
* items are stored.
|
||
*/
|
||
if (ix == F_CCI_INDEX)
|
||
{
|
||
CCIEntryModifier mod = ((CCIFuncArg *)menuItem->wmFuncArgs)->mod;
|
||
|
||
/* first fix the label if needed. */
|
||
if (!strcmp(menuItem->label, CCI_USE_DEFAULT_NAME_TAG))
|
||
{
|
||
XtFree(menuItem->label);
|
||
menuItem->label = NULL;
|
||
}
|
||
|
||
FixMenuItem(menuSpec, menuItem);
|
||
|
||
if (mod == DELIMIT || mod == DELIMIT_CASCADE || mod == DELIMIT_INLINE)
|
||
use_separators = True;
|
||
}
|
||
|
||
/*
|
||
* If this menu item is supposed to be wrapped in separators,
|
||
* then create a separator template before the menu item
|
||
*/
|
||
if (use_separators)
|
||
{
|
||
MenuItem *separator = MakeSeparatorTemplate(TOP_SEPARATOR);
|
||
if (lastMenuItem != NULL) lastMenuItem->nextMenuItem = separator;
|
||
else firstMenuItem = separator;
|
||
lastMenuItem = separator;
|
||
}
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
/*
|
||
* Add this item to the menu specification.
|
||
*/
|
||
|
||
if (lastMenuItem != NULL) /* not first */
|
||
{
|
||
lastMenuItem->nextMenuItem = menuItem;
|
||
}
|
||
else
|
||
{
|
||
firstMenuItem = menuItem;
|
||
}
|
||
lastMenuItem = menuItem;
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/* If this menu item is supposed to be wrapped in separators
|
||
* then create a separator template after the menu item
|
||
*/
|
||
if (use_separators)
|
||
{
|
||
MenuItem *separator = MakeSeparatorTemplate(BOTTOM_SEPARATOR);
|
||
if (lastMenuItem != NULL) lastMenuItem->nextMenuItem = separator;
|
||
else firstMenuItem = separator;
|
||
lastMenuItem = separator;
|
||
}
|
||
|
||
use_separators = FALSE;
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
}
|
||
|
||
return (firstMenuItem);
|
||
|
||
} /* END OF FUNCTION ParseMenuItems */
|
||
|
||
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/*************************************<->*************************************
|
||
*
|
||
* StoreExclusion (menuSpec, string)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Store the exclusion string in the menuspec. The list of exclusion
|
||
* strings are used to determine whether an insertion should be disallowed.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* menuSpec = the menu specification structure
|
||
* string = exclusion client command string
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = nothing
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
static void StoreExclusion (MenuSpec *menuSpec, String string)
|
||
{
|
||
MenuExclusion *exclusion;
|
||
|
||
exclusion = (MenuExclusion *)XtMalloc(sizeof(MenuExclusion));
|
||
exclusion->command_string = XtNewString(string);
|
||
|
||
/* We don't care what order the exclusions are in so stick it
|
||
at the head of the list because it is easier. */
|
||
exclusion->nextExclusion = menuSpec->exclusions;
|
||
menuSpec->exclusions = exclusion;
|
||
}
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* IsClientCommand (string)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Determine whether the string is a client command by the prefix
|
||
* characters.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* string = possible client command string
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = (Boolean) TRUE iff the string is a client command.
|
||
* Otherwise, FALSE is returned.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* This function simply checks what the first two or three characters of
|
||
* the string are. If they match the beginning of a client command
|
||
* specification, then TRUE is returned. This function does no go on to
|
||
* parse the rest of the specification. The legal client command beginning
|
||
* characters are:
|
||
*
|
||
* characters: meaning:
|
||
* -----------------------------------------------
|
||
* < simple client command beginning
|
||
* ->< forced cascade menu
|
||
* =< client command with separators
|
||
* ~< exclusion operator
|
||
*
|
||
* Assumes:
|
||
* --------
|
||
* There is no leading whitespace on the string
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
Boolean IsClientCommand (String string)
|
||
{
|
||
if ((mblen ((char *)string, MB_CUR_MAX) == 1 && *string == '<') ||
|
||
(strncmp(string, "-><", 3) == 0) ||
|
||
(strncmp(string, "=<", 2) == 0) ||
|
||
(strncmp(string, "=><", 3) == 0) ||
|
||
(strncmp(string, "~<", 2) == 0))
|
||
return(TRUE);
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* ParseClientCommand (linePP, menuSpec, menuitem, string, use_separators)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Parse the string and whatever is left of the line to verify whether
|
||
* correct syntax was used for a client command. Store the client command
|
||
* string in the menuitem, unless it is an exclusion. If it is an
|
||
* exclusion, then store the exclusion string in the menuSpec and return
|
||
* FALSE to indicate that the menuitem is no longer needed.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* linePP = pointer to current line buffer pointer.
|
||
* menuItem = pointer to MenuItem structure
|
||
* string = first token of client command
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = (Boolean) TRUE iff the line is a valid client command
|
||
* that can used to match insertions.
|
||
* Otherwise, FALSE is returned meaning that the client
|
||
* command had incorrect syntax or it was an exclusion, in
|
||
* which case any useful information was stored in the
|
||
* menuSpec.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* This function parses the entire line to determine if correct
|
||
* syntax was used for the client command. We assume at this point
|
||
* that the line is a client command. We are just syntax checking.
|
||
* If the syntax is correct, the client command is stored in the
|
||
* menuitem structure, in the "label" field.
|
||
*
|
||
* Valid syntax for a client command (single quoted characters are
|
||
* literals):
|
||
*
|
||
* modifier = { '->' | '=' | '~' }
|
||
* reference = '<' { name | '*' } '>'
|
||
* command = [ modifier ] reference [ { modifier | '.' } reference ]*
|
||
* name = alpha-numeric string, white space allowed
|
||
*
|
||
* Assumes:
|
||
* --------
|
||
* There is no leading whitespace on the string argument
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
enum { PRS_NO_STATE, PRS_BEGIN, PRS_MODIFIER, PRS_REFERENCE,
|
||
PRS_SEPARATOR, PRS_END, PRS_ERROR, PRS_MAX_STATES };
|
||
|
||
/* This table lists for each parse state, the legal states that can
|
||
be moved to. Each list must end with a PRS_NO_STATE value to
|
||
terminate the list. */
|
||
static int cmd_parse_table[PRS_END][PRS_END] =
|
||
{
|
||
/* PRS_NO_STATE */ { PRS_NO_STATE },
|
||
/* PRS_BEGIN */ { PRS_MODIFIER, PRS_REFERENCE, PRS_NO_STATE },
|
||
/* PRS_MODIFIER */ { PRS_REFERENCE, PRS_NO_STATE },
|
||
/* PRS_REFERENCE */ { PRS_SEPARATOR, PRS_END, PRS_NO_STATE },
|
||
/* PRS_SEPARATOR */ { PRS_REFERENCE, PRS_NO_STATE },
|
||
};
|
||
|
||
static Boolean ParseClientCommand (unsigned char **linePP, MenuSpec *menuSpec,
|
||
MenuItem *menuItem, unsigned char *string,
|
||
Boolean *use_separators)
|
||
{
|
||
int token, linelen, i;
|
||
int state = PRS_BEGIN;
|
||
String stream, unchanged_stream, exclusion_text;
|
||
Boolean return_val = FALSE;
|
||
Boolean exclusion = FALSE; /* this will be set to TRUE if the client
|
||
command was parsed to be an exclusion
|
||
command. */
|
||
|
||
/* Construct one input stream out of the string and the linePP that
|
||
we were given. */
|
||
linelen = strlen((char *)string) + strlen((char *)*linePP) + 1;
|
||
if ((unchanged_stream = stream = (String)
|
||
XtMalloc((unsigned int)(sizeof(unsigned char) * linelen))) == NULL)
|
||
{
|
||
PWarning (((char *)GETMESSAGE(60, 42,
|
||
"Insufficient memory for menu item label")));
|
||
return (FALSE);
|
||
}
|
||
strcpy(stream, (char *) string);
|
||
strcat(stream, " ");
|
||
strcat(stream, (char *) *linePP);
|
||
|
||
for (;;)
|
||
{
|
||
token = PRS_NO_STATE;
|
||
while (token == PRS_NO_STATE)
|
||
{
|
||
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
|
||
token = PRS_ERROR;
|
||
continue;
|
||
}
|
||
|
||
switch (*stream)
|
||
{
|
||
case '\0':
|
||
case '\n':
|
||
/* We've reached the end of the stream. Return the
|
||
PRS_END token. */
|
||
token = PRS_END;
|
||
break;
|
||
case '-':
|
||
/* This should be a cascade-force modifier */
|
||
++stream;
|
||
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
|
||
token = PRS_ERROR;
|
||
continue;
|
||
}
|
||
if (*stream == '>')
|
||
{
|
||
++stream; token = PRS_MODIFIER;
|
||
}
|
||
else token = PRS_ERROR;
|
||
break;
|
||
case '=':
|
||
/* This is either a separators modifier or
|
||
a combination separators and cascade-force
|
||
modifier */
|
||
++stream;
|
||
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
|
||
token = PRS_ERROR;
|
||
continue;
|
||
}
|
||
if (*stream == '>') ++stream;
|
||
token = PRS_MODIFIER;
|
||
*use_separators = TRUE;
|
||
break;
|
||
case '~':
|
||
/* This is a exclude-command modifier */
|
||
++stream; token = PRS_MODIFIER;
|
||
exclusion = TRUE;
|
||
/* Setup a pointer to the text following the ~ so
|
||
we can do matching later for exclusions. */
|
||
exclusion_text = stream;
|
||
break;
|
||
case '<':
|
||
/* Skip the open bracket */
|
||
++stream;
|
||
|
||
/* This should be the beginning of a reference. First
|
||
skip any leading whitespace. */
|
||
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
|
||
token = PRS_ERROR;
|
||
continue;
|
||
}
|
||
while (mblen ((char *)stream, MB_CUR_MAX) == 1 &&
|
||
(*stream == ' ' || *stream == '\t'))
|
||
++stream;
|
||
|
||
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
|
||
token = PRS_ERROR;
|
||
continue;
|
||
}
|
||
/* Now check for a reference name wild card or a
|
||
full reference name */
|
||
if (*stream == '*')
|
||
++stream;
|
||
else
|
||
{
|
||
while (mblen ((char *)stream, MB_CUR_MAX) == 1 &&
|
||
(isalnum(*stream) || *stream == ' ' ||
|
||
*stream == '\t' || *stream == '_' ))
|
||
++stream;
|
||
}
|
||
|
||
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
|
||
token = PRS_ERROR;
|
||
continue;
|
||
}
|
||
|
||
/* Now skip past any trailing white space */
|
||
while (mblen ((char *)stream, MB_CUR_MAX) == 1 &&
|
||
(*stream == ' ' || *stream == '\t'))
|
||
++stream;
|
||
|
||
if (mblen ((char *)stream, MB_CUR_MAX) > 1) {
|
||
token = PRS_ERROR;
|
||
continue;
|
||
}
|
||
/* At this point, we should be looking at the close
|
||
of the reference */
|
||
if (*stream == '>')
|
||
{
|
||
token = PRS_REFERENCE;
|
||
++stream;
|
||
}
|
||
else token = PRS_ERROR;
|
||
break;
|
||
case '.':
|
||
/* This is a reference separator */
|
||
++stream; token = PRS_SEPARATOR;
|
||
break;
|
||
case ' ':
|
||
case '\t':
|
||
/* The only place white space is allowed as at the
|
||
beginning of the line, after all the client command
|
||
text and within the delimiters of a REFERENCE. We
|
||
are guaranteed not to have whitespace at the
|
||
beginning of the line by the time this function is
|
||
called. Also, the REFERENCE parsing above handles
|
||
all white space internal to the client command. Therefore,
|
||
since we are seeing white space, we must be at the
|
||
end of the client command. */
|
||
token = PRS_END;
|
||
break;
|
||
default:
|
||
token = PRS_ERROR;
|
||
|
||
} /* end switch (*stream) */
|
||
} /* end while (token == PRS_NO_STATE) */
|
||
|
||
/* If we got an error then just return an error */
|
||
if (token == PRS_ERROR)
|
||
{
|
||
return_val = FALSE; break;
|
||
}
|
||
|
||
/* Check whether the token we got is a valid transition */
|
||
for (i = 0; cmd_parse_table[state][i] != PRS_NO_STATE; ++i)
|
||
{
|
||
if (token == cmd_parse_table[state][i])
|
||
{
|
||
/* It is a valid transition, so break out of the loop */
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* If i is not indexing the NO_STATE value in the parse_table,
|
||
then the parse succeeded. Check if the new state is PRS_END.
|
||
If so then we are done. If the state isn't the same as the
|
||
current token, then we hit a parse error. */
|
||
if (cmd_parse_table[state][i] != PRS_NO_STATE)
|
||
{
|
||
if (token == PRS_END)
|
||
{
|
||
return_val = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* parse error */
|
||
return_val = FALSE;
|
||
break;
|
||
}
|
||
|
||
/* The transition was valid so make the transition by
|
||
setting the state to be the current token. */
|
||
state = token;
|
||
|
||
} /* end for (;;) */
|
||
|
||
/* If the return_val is TRUE, then the parse succeeded and we
|
||
want to save the string we parsed into the label field of
|
||
the menu item. */
|
||
if (return_val == TRUE)
|
||
{
|
||
/* NULL terminate the string */
|
||
*stream = '\0';
|
||
|
||
/* Check whether this client command was an exclusion. If not,
|
||
then store the client command string in the menu item. */
|
||
if (exclusion == TRUE)
|
||
{
|
||
/* Since the command was an exclusion, store the command
|
||
string in the menuSpec and change the return value to
|
||
FALSE. */
|
||
StoreExclusion(menuSpec, exclusion_text);
|
||
return_val = FALSE;
|
||
}
|
||
else
|
||
{
|
||
menuItem->label = XtNewString(unchanged_stream);
|
||
menuItem->labelType = XmSTRING;
|
||
}
|
||
}
|
||
|
||
/* Free the string we allocated and return. */
|
||
XtFree((char *)unchanged_stream);
|
||
|
||
return(return_val);
|
||
}
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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 "@" */
|
||
#ifdef WSM
|
||
if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD,
|
||
(char *)string, True)) >= 0)
|
||
#else /* WSM */
|
||
if ((menuItem->labelBitmapIndex = GetBitmapIndex (pSD,
|
||
(char *)string)) >= 0)
|
||
#endif /* WSM */
|
||
{
|
||
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);
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
if (menuItem->labelType == XmSTRING &&
|
||
mnemonic != NULL &&
|
||
(ks = XStringToKeysym((char *)mnemonic)) != NoSymbol &&
|
||
strchr(menuItem->label, (char)(ks & 0xff)) != NULL)
|
||
{
|
||
menuItem->mnemonic = ks;
|
||
}
|
||
#else
|
||
if ((mnemonic != NULL) &&
|
||
(*mnemonic != '\0') &&
|
||
(menuItem->labelType == XmSTRING) &&
|
||
(strchr (menuItem->label, *mnemonic) != NULL))
|
||
/* valid mnemonic */
|
||
{
|
||
menuItem->mnemonic = *mnemonic;
|
||
}
|
||
#endif
|
||
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 */
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/* skip label name for client command */
|
||
((*lineP != '"') || (menuItem->wmFunction != F_InvokeCommand)) &&
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
(*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 */
|
||
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/*************************************<->*************************************
|
||
*
|
||
* ParseMenuItemName (linePP, menuItem)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Parse a user defined client command menu item
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* linePP = pointer to current line buffer pointer.
|
||
* menuItem = pointer to MenuItem structure
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* menuItem->label will have menu item name appended to it
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* This function attempts to find a menu item label string at the end
|
||
* of the client command specification line. A menu item label string
|
||
* must be delimited by double quotes. If found, the label string is
|
||
* appended to the menuItem->label field, after being reallocated to
|
||
* accommodate the new space requirement.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
static void ParseMenuItemName (unsigned char **linePP, MenuItem *menuItem)
|
||
{
|
||
unsigned char *lineP, *endquote;
|
||
int chlen;
|
||
|
||
/* Skip past any whitespace */
|
||
ScanWhitespace (linePP);
|
||
lineP = *linePP;
|
||
|
||
/* Look for a double quote */
|
||
if (mblen ((char *)lineP, MB_CUR_MAX) == 1 && *lineP == '"')
|
||
{
|
||
/* Move past the first quote. */
|
||
++lineP;
|
||
|
||
endquote = lineP;
|
||
|
||
/* Search for closing quote */
|
||
while (*endquote != '\0' &&
|
||
(chlen = mblen ((char *)endquote, MB_CUR_MAX)) > 0 &&
|
||
(chlen > 1 || *endquote != '"'))
|
||
{
|
||
/* If we ran off the end of the line, then just abort. Bad
|
||
syntax. */
|
||
if ((chlen == 1 && *endquote == '\n') || *endquote == '\0') return;
|
||
endquote += chlen;
|
||
}
|
||
if (chlen < 0) return; /* invalid character */
|
||
|
||
/* Well, we have a valid menu item name. Store it in the
|
||
client command name field. Don't include the double quotes. */
|
||
menuItem->clientCommandName =
|
||
XtMalloc(sizeof(char) * (endquote - lineP) + 1);
|
||
strncpy(menuItem->clientCommandName, (char *) lineP,
|
||
endquote - lineP);
|
||
menuItem->clientCommandName[strlen(menuItem->clientCommandName)+1] = '\0';
|
||
}
|
||
else
|
||
{
|
||
/* If there was no double quote, then just advance to the end
|
||
of the line. */
|
||
while (*lineP != '\0' &&
|
||
((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 1 ||
|
||
*lineP != '\n'))
|
||
lineP += chlen > 0 ? chlen : 1;
|
||
*linePP = lineP;
|
||
}
|
||
}
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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;
|
||
register 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;
|
||
#ifndef NO_MULTIBYTE
|
||
char *p;
|
||
wchar_t last;
|
||
char delim;
|
||
wchar_t wdelim;
|
||
int lastlen;
|
||
#endif
|
||
|
||
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 '&' .
|
||
*/
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
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
|
||
if ((wmFunction == F_Exec) && ((*pArgs)[len - 1] != '&'))
|
||
{
|
||
(*pArgs)[len] = '&';
|
||
(*pArgs)[len + 1] = '\0';
|
||
}
|
||
#endif
|
||
}
|
||
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 */
|
||
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/*************************************<->*************************************
|
||
*
|
||
* ParseWmFuncCCIArgs (linePP, wmFunction, pArgs)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Parses a Client-Command entry's arguments.
|
||
*
|
||
*
|
||
* 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:
|
||
* --------
|
||
* None.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
static Boolean ParseWmFuncCCIArgs (unsigned char **linePP,
|
||
WmFunction wmFunction, String *pArgs)
|
||
{
|
||
/*
|
||
* Format:
|
||
* cci_func_args:
|
||
* cci_entry
|
||
* modifier cci_entry_list
|
||
*
|
||
* cci_entry_list:
|
||
* cci_entry
|
||
* cci_entry . cci_entry
|
||
*
|
||
* cci_entry:
|
||
* '<' cci_label '>'
|
||
*
|
||
* cci_label:
|
||
* any combination of alpha and '_'
|
||
*/
|
||
|
||
CCIEntryModifier mod;
|
||
CCIFuncArg *cciArg;
|
||
unsigned char *string;
|
||
|
||
|
||
cciArg = XtNew(CCIFuncArg);
|
||
|
||
if ((string = GetString(linePP)) == NULL)
|
||
{
|
||
/* Error - no data for f.cci command. cci_entry_list is required. */
|
||
fprintf(stderr, "Incorrect format for f.cci command.\n");
|
||
return (FALSE);
|
||
}
|
||
else
|
||
{
|
||
/* check if no modifier was specified. */
|
||
if (string[0] == '<')
|
||
{
|
||
cciArg->mod = NONE;
|
||
cciArg->cciEntry = XtNewString((char*)string);
|
||
}
|
||
else
|
||
{
|
||
if (! GetCCIModifier((String)string, &mod))
|
||
{
|
||
cciArg->mod = NONE;
|
||
cciArg->cciEntry = XtNewString("");
|
||
}
|
||
else
|
||
{
|
||
cciArg->mod = mod;
|
||
|
||
if ((string = GetString(linePP)) == NULL)
|
||
{
|
||
/* Found a modifier, but there's no cci_entry_list. */
|
||
fprintf(stderr, "Incorrect format for f.cci command.\n");
|
||
return(FALSE);
|
||
}
|
||
else
|
||
{
|
||
cciArg->cciEntry = XtNewString((char*)string);
|
||
}
|
||
}
|
||
}
|
||
|
||
*pArgs = (String)cciArg;
|
||
}
|
||
|
||
return(TRUE);
|
||
} /* END OF FUNCTION ParseWmFuncCCIArgs */
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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;
|
||
}
|
||
#ifdef WSM
|
||
else if (!strcmp ("ifkey", (char *)ctxStr))
|
||
{
|
||
*context |= F_CONTEXT_IFKEY;
|
||
}
|
||
#endif /* WSM */
|
||
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;
|
||
#ifdef WSM
|
||
Boolean bBadKey;
|
||
#endif /* WSM */
|
||
|
||
/*
|
||
* 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.
|
||
*/
|
||
#ifdef WSM
|
||
bBadKey = False;
|
||
#endif /* WSM */
|
||
if (!ParseKeyEvent(&lineP,
|
||
&eventType,
|
||
&keySpec->keycode,
|
||
&keySpec->state))
|
||
{
|
||
#ifdef WSM
|
||
bBadKey = True;
|
||
#else /* WSM */
|
||
PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
|
||
XtFree ((char *)keySpec);
|
||
continue; /* skip this key specification */
|
||
#endif /* WSM */
|
||
}
|
||
|
||
/*
|
||
* Parse the key context.
|
||
* Here lineP points to the candidate context string.
|
||
*/
|
||
|
||
if (!ParseContext(&lineP, &keySpec->context,
|
||
&keySpec->subContext))
|
||
{
|
||
#ifdef WSM
|
||
if (bBadKey)
|
||
PWarning (((char *)GETMESSAGE(60, 27, "Invalid key specification")));
|
||
#endif /* WSM */
|
||
PWarning (((char *)GETMESSAGE(60, 28, "Invalid key context")));
|
||
XtFree ((char *)keySpec);
|
||
continue; /* skip this key specification */
|
||
}
|
||
#ifdef WSM
|
||
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;
|
||
#endif /* WSM */
|
||
|
||
|
||
/*
|
||
* 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 */
|
||
|
||
#ifndef WSM
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* GetNextLine ()
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns the next line from an fopened configuration file or a newline-
|
||
* embedded configuration string.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* 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
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* line = (global) next line
|
||
* linec = (global) line count incremented
|
||
* parseP = (global) parse string pointer incremented
|
||
* Return = line or NULL if file or string is exhausted.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* If there are more than MAXLINE characters on a line in the file cfileP the
|
||
* excess are truncated.
|
||
* Assumes the line buffer is long enough for any parse string line.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
unsigned char *
|
||
GetNextLine (void)
|
||
{
|
||
register unsigned char *string;
|
||
int len;
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
int chlen;
|
||
wchar_t last;
|
||
wchar_t wdelim;
|
||
char delim;
|
||
int lastlen;
|
||
#endif
|
||
|
||
if (cfileP != NULL)
|
||
/* read fopened file */
|
||
{
|
||
if ((string = (unsigned char *)
|
||
fgets ((char *)line, MAXLINE, cfileP)) != NULL)
|
||
{
|
||
#ifndef NO_MULTIBYTE
|
||
|
||
lastlen = 0;
|
||
while (*string &&
|
||
((len = mblen((char *)string, MB_CUR_MAX)) > 0))
|
||
{
|
||
mbtowc(&last, (char *)string, MB_CUR_MAX);
|
||
lastlen = len;
|
||
string += len;
|
||
}
|
||
delim = '\\';
|
||
mbtowc(&wdelim, &delim, MB_CUR_MAX);
|
||
if (lastlen == 1 && last == wdelim)
|
||
{
|
||
do
|
||
{
|
||
if (!fgets((char *)string, MAXLINE - (string - line), cfileP))
|
||
break;
|
||
|
||
lastlen = 0;
|
||
while (*string &&
|
||
((len = mblen((char *)string, MB_CUR_MAX)) > 0))
|
||
{
|
||
mbtowc(&last, (char *)string, MB_CUR_MAX);
|
||
lastlen = len;
|
||
string += len;
|
||
}
|
||
linec++;
|
||
}
|
||
while (lastlen == 1 && last == wdelim);
|
||
}
|
||
string = line;
|
||
#else
|
||
len = strlen((char *)string) - 2;
|
||
if ((len > 0) && string[len] == '\\')
|
||
{
|
||
do {
|
||
string = &string[len];
|
||
if (fgets((char *)string,
|
||
MAXLINE - (string-line), cfileP) == NULL)
|
||
break;
|
||
len = strlen((char *)string) - 2;
|
||
linec++;
|
||
} while ((len >= 0) && string[len] == '\\');
|
||
string = line;
|
||
}
|
||
#endif
|
||
}
|
||
}
|
||
else if ((parseP != NULL) && (*parseP != '\0'))
|
||
/* read parse string */
|
||
{
|
||
string = line;
|
||
#ifndef NO_MULTIBYTE
|
||
while ((*parseP != '\0') &&
|
||
((chlen = mblen ((char *)parseP, MB_CUR_MAX)) > 0) &&
|
||
(*parseP != '\n'))
|
||
/* copy all but NULL and newlines to line buffer */
|
||
{
|
||
while (chlen--)
|
||
{
|
||
*(string++) = *(parseP++);
|
||
}
|
||
}
|
||
#else
|
||
while ((*parseP != '\0') && (*parseP != '\n'))
|
||
/* copy all but end-of-line and newlines to line buffer */
|
||
{
|
||
*(string++) = *(parseP++);
|
||
}
|
||
#endif
|
||
*string = '\0';
|
||
if (*parseP == '\n')
|
||
{
|
||
parseP++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
string = NULL;
|
||
}
|
||
|
||
linec++;
|
||
return (string);
|
||
|
||
} /* END OF FUNCTION GetNextLine */
|
||
#endif /* WSM */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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)
|
||
{
|
||
register 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 */
|
||
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/*************************************<->*************************************
|
||
*
|
||
* GetCCIModifier (modString, mod)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Return the cci modifier corresponding to the specified string
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* modString = cci modifier string; may be null
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* mod = cci modifier.
|
||
* Return = (Boolean) true iff valid modifier string
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* None.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
static Boolean GetCCIModifier (String modString, CCIEntryModifier *mod)
|
||
{
|
||
CCIEntryModifier i;
|
||
|
||
|
||
if (modString != NULL)
|
||
{
|
||
ToLower (modString);
|
||
for (i=NONE; i<=EXCLUDE; i++)
|
||
{
|
||
if (!strcmp (CCIEntryModifierNames[i], modString))
|
||
{
|
||
*mod = i;
|
||
return (TRUE);
|
||
}
|
||
}
|
||
}
|
||
|
||
return (FALSE);
|
||
|
||
} /* END OF FUNCTION GetCCIModifier */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* FixMenuItem (menuSpec, menuItem)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Fix-up the menuItem so that it appears an old-style cci command was
|
||
* read from the .mwmrc file
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* menuItem = the menu item structure
|
||
* menuSpec = the menu specification structure
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* menuItem = the fixed-up menuitem
|
||
* menuSpec = the fixed-up menu specification structure if EXCLUDE found
|
||
* Return = nothing
|
||
*
|
||
* Comments:
|
||
* --------
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
static void FixMenuItem (MenuSpec *menuSpec, MenuItem *menuItem)
|
||
{
|
||
String tmp;
|
||
CCIFuncArg *cciArg;
|
||
|
||
|
||
if (menuItem == NULL)
|
||
return;
|
||
|
||
cciArg = (CCIFuncArg *)menuItem->wmFuncArgs;
|
||
|
||
menuItem->clientCommandName = menuItem->label;
|
||
menuItem->label = cciArg->cciEntry;
|
||
|
||
/*
|
||
* Fix-up the label to handle the modifier.
|
||
*/
|
||
|
||
switch (cciArg->mod)
|
||
{
|
||
case NONE:
|
||
break;
|
||
|
||
case INLINE:
|
||
break;
|
||
|
||
case CASCADE:
|
||
/* -> */
|
||
tmp = (String) XtMalloc(strlen(menuItem->label) + 3);
|
||
sprintf(tmp, "->%s", menuItem->label);
|
||
XtFree(menuItem->label);
|
||
menuItem->label = tmp;
|
||
break;
|
||
|
||
case DELIMIT:
|
||
/* = */
|
||
tmp = (String) XtMalloc(strlen(menuItem->label) + 2);
|
||
sprintf(tmp, "=%s", menuItem->label);
|
||
XtFree(menuItem->label);
|
||
menuItem->label = tmp;
|
||
break;
|
||
|
||
case DELIMIT_INLINE:
|
||
break;
|
||
|
||
case DELIMIT_CASCADE:
|
||
/* => */
|
||
tmp = (String) XtMalloc(strlen(menuItem->label) + 3);
|
||
sprintf(tmp, "=>%s", menuItem->label);
|
||
XtFree(menuItem->label);
|
||
menuItem->label = tmp;
|
||
break;
|
||
|
||
case EXCLUDE:
|
||
/* ~ */
|
||
StoreExclusion(menuSpec, menuItem->label);
|
||
|
||
tmp = (String) XtMalloc(strlen(menuItem->label) + 2);
|
||
sprintf(tmp, "~%s", menuItem->label);
|
||
XtFree(menuItem->label);
|
||
menuItem->label = tmp;
|
||
break;
|
||
}
|
||
}
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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];
|
||
register 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;
|
||
#ifndef NO_MULTIBYTE
|
||
int chlen;
|
||
#endif
|
||
|
||
ScanWhitespace (&lineP);
|
||
startP = lineP;
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
while (*lineP &&
|
||
((chlen = mblen ((char *)lineP, MB_CUR_MAX)) > 0) &&
|
||
((chlen > 1) ||
|
||
(!isspace (*lineP) && *lineP != ',' && *lineP != ':')))
|
||
{
|
||
/* Skip next character */
|
||
lineP += chlen;
|
||
}
|
||
#else
|
||
while (*lineP && !isspace (*lineP) && *lineP != ',' && *lineP != ':' )
|
||
{
|
||
/* Skip next character */
|
||
lineP++;
|
||
}
|
||
#endif
|
||
|
||
len = min (lineP - startP, MAX_KEYSYM_STRLEN);
|
||
(void) strncpy (keySymName, (char *)startP, len);
|
||
keySymName[len] = '\0';
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
if ((*detail = XStringToKeysym(keySymName)) == NoSymbol &&
|
||
(mblen (keySymName, MB_CUR_MAX) == 1))
|
||
#else
|
||
if ((*detail = XStringToKeysym(keySymName)) == NoSymbol)
|
||
#endif
|
||
{
|
||
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)
|
||
{
|
||
#ifndef NO_MULTIBYTE
|
||
int chlen;
|
||
|
||
while (*linePP &&
|
||
((chlen = mblen ((char *) *linePP, MB_CUR_MAX)) > 0) &&
|
||
((chlen > 1) || isalnum (**linePP)))
|
||
{
|
||
(*linePP) += chlen;
|
||
}
|
||
#else
|
||
while (*linePP && isalnum (**linePP))
|
||
{
|
||
(*linePP)++;
|
||
}
|
||
#endif
|
||
|
||
} /* END OF FUNCTION ScanAlphanumeric */
|
||
|
||
|
||
#ifndef WSM
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* ScanWhitespace(linePP)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Scan the string, skipping over all white space characters.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* linePP = nonNULL pointer to current line buffer pointer
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* linePP = nonNULL pointer to revised line buffer pointer
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Assumes linePP is nonNULL
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void ScanWhitespace(unsigned char **linePP)
|
||
{
|
||
#ifndef NO_MULTIBYTE
|
||
while (*linePP && (mblen ((char *)*linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
|
||
#else
|
||
while (*linePP && isspace (**linePP))
|
||
#endif
|
||
{
|
||
(*linePP)++;
|
||
}
|
||
|
||
} /* END OF FUNCTION ScanWhitespace */
|
||
#endif /* not WSM */
|
||
|
||
#ifndef WSM
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* ToLower (string)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Lower all characters in a string.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* string = NULL-terminated character string or NULL
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* string = NULL-terminated lower case character string or NULL
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* None.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
void ToLower (char *string)
|
||
{
|
||
char *pch = string;
|
||
#ifndef NO_MULTIBYTE
|
||
int chlen;
|
||
|
||
while (*pch && ((chlen = mblen (pch, MB_CUR_MAX)) > 0))
|
||
{
|
||
if ((chlen == 1) && (isupper (*pch)))
|
||
{
|
||
*pch = tolower(*pch);
|
||
}
|
||
pch += chlen;
|
||
}
|
||
#else
|
||
while (*pch != '\0')
|
||
{
|
||
if (isupper (*pch))
|
||
{
|
||
*pch = tolower(*pch);
|
||
}
|
||
pch++;
|
||
}
|
||
#endif
|
||
|
||
} /* END OF FUNCTION ToLower */
|
||
#endif /* WSM */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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)
|
||
{
|
||
|
||
#ifdef WSM
|
||
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);
|
||
#else /* WSM */
|
||
if (cfileP != NULL)
|
||
{
|
||
fprintf (stderr, ((char *)GETMESSAGE(60, 33, "%s: %s on line %d of configuration file %s\n")),
|
||
wmGD.mwmName, message, linec,
|
||
wmGD.configFile ? wmGD.configFile : cfileName);
|
||
}
|
||
else
|
||
{
|
||
fprintf (stderr, ((char *)GETMESSAGE(60, 34, "%s: %s on line %d of specification string\n")),
|
||
wmGD.mwmName, message, linec);
|
||
}
|
||
fflush (stderr);
|
||
#endif /* WSM */
|
||
|
||
|
||
} /* END OF FUNCTION PWarning */
|
||
|
||
#ifdef WSM
|
||
/*
|
||
* 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;
|
||
#ifndef NO_MULTIBYTE
|
||
int chlen;
|
||
#endif
|
||
|
||
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;
|
||
#ifndef NO_MULTIBYTE
|
||
while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
|
||
{
|
||
if ((chlen == 1) && (*pch1 == ' '))
|
||
{
|
||
break;
|
||
}
|
||
pch1 += chlen;
|
||
}
|
||
#else /* NO_MULTIBYTE */
|
||
while (*pch1 && (*pch1 != ' ')) pch1++;
|
||
#endif /* NO_MULTIBYTE */
|
||
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;
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
while (*pch1 && ((chlen = mblen ((char *)pch1, MB_CUR_MAX)) > 0))
|
||
{
|
||
if ((chlen == 1) && (*pch1 == ' '))
|
||
{
|
||
break;
|
||
}
|
||
pch1 += chlen;
|
||
}
|
||
#else /* NO_MULTIBYTE */
|
||
while (*pch1 && (*pch1 != ' ')) pch1++;
|
||
#endif /* NO_MULTIBYTE */
|
||
|
||
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;
|
||
}
|
||
|
||
#endif /* WSM */
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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)
|
||
{
|
||
#ifndef NO_MULTIBYTE
|
||
int chlen;
|
||
#endif
|
||
#ifdef WSM
|
||
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;
|
||
}
|
||
#endif /* WSM */
|
||
|
||
/*
|
||
* Copy modifiers
|
||
*/
|
||
|
||
ScanWhitespace (&startP);
|
||
|
||
while (*startP != '<')
|
||
{
|
||
if (*startP == '~')
|
||
{
|
||
*destP++ = *startP++;
|
||
}
|
||
#ifdef WSM
|
||
pchFirst = startP;
|
||
#endif /* WSM */
|
||
|
||
#ifndef NO_MULTIBYTE
|
||
while (*startP &&
|
||
(((chlen = mblen ((char *)startP, MB_CUR_MAX)) > 1)
|
||
|| isalnum (*startP)))
|
||
{
|
||
while (chlen--)
|
||
{
|
||
#ifdef WSM
|
||
startP++;
|
||
|
||
#else /* WSM */
|
||
*destP++ = *startP++;
|
||
#endif /* WSM */
|
||
}
|
||
}
|
||
#else
|
||
while (isalnum (*startP))
|
||
{
|
||
#ifdef WSM
|
||
startP++;
|
||
#else /* WSM */
|
||
*destP++ = *startP++;
|
||
#endif /* WSM */
|
||
}
|
||
#endif
|
||
#ifdef WSM
|
||
/* 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;
|
||
}
|
||
#endif /* WSM */
|
||
*destP++ = '+';
|
||
|
||
ScanWhitespace (&startP);
|
||
}
|
||
|
||
/*
|
||
* Skip the key event type.
|
||
*/
|
||
startP++; /* skip '<' */
|
||
while (*startP != '>')
|
||
{
|
||
#ifndef NO_MULTIBYTE
|
||
startP += mblen ((char *)startP, MB_CUR_MAX);
|
||
#else
|
||
startP++;
|
||
#endif
|
||
}
|
||
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;
|
||
#ifndef MOTIF_ONE_DOT_ONE
|
||
char *homeDir = XmeGetHomeDirName();
|
||
#else
|
||
FILE *fileP;
|
||
#endif
|
||
|
||
/*
|
||
* Look in the user's home directory for .motifbind
|
||
*/
|
||
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
GetHomeDirName(fileName);
|
||
#else
|
||
strcpy (fileName, homeDir);
|
||
#endif
|
||
strncat(fileName, "/", MAXWMPATH-strlen(fileName));
|
||
strncat(fileName, MOTIF_BINDINGS_FILE, MAXWMPATH-strlen(fileName));
|
||
|
||
#ifdef MOTIF_ONE_DOT_ONE
|
||
if ((fileP = fopen (fileName, "r")) != NULL)
|
||
{
|
||
unsigned char buffer[MBBSIZ];
|
||
int count;
|
||
Boolean first = True;
|
||
int mode = PropModeReplace;
|
||
Window propWindow;
|
||
|
||
/*
|
||
* Get the atom for the property.
|
||
*/
|
||
wmGD.xa_MOTIF_BINDINGS =
|
||
XInternAtom (DISPLAY, _XA_MOTIF_BINDINGS, False);
|
||
|
||
/*
|
||
* The property goes on the root window of screen zero
|
||
*/
|
||
propWindow = RootWindow(DISPLAY, 0);
|
||
|
||
/*
|
||
* Copy file contents to property on root window of screen 0.
|
||
*/
|
||
while ( (count=fread((char *) &buffer[0], 1, MBBSIZ, fileP)) > 0)
|
||
{
|
||
XChangeProperty (DISPLAY, propWindow, wmGD.xa_MOTIF_BINDINGS,
|
||
XA_STRING, 8, mode,
|
||
&buffer[0], count);
|
||
|
||
if (first)
|
||
{
|
||
first = False;
|
||
mode = PropModeAppend;
|
||
}
|
||
}
|
||
}
|
||
|
||
#else
|
||
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);
|
||
#endif
|
||
} /* 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 */
|
||
|
||
|
||
#ifdef WSM
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* 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 ***************************/
|
||
#endif /* WSM */
|
||
|
||
|
||
#if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
|
||
/*************************************<->*************************************
|
||
*
|
||
* SetGreyedContextAndMgtMask (menuItem, wmFunction)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function sets up the greyed context and management mask
|
||
* for a menu item based on the menu function passed in.
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* menuItem = the menu item to be set up
|
||
* wmFunction = the menu function to find in the function table
|
||
* to determine how to set up the relevant fields
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* The menuItem will have its greyed context and management mask fields
|
||
* set appropriately. If the given function cannot be found, the fields
|
||
* will be set to the appropriate values as if the function were F_Nop.
|
||
* Return = True if the function could be found. False otherwise.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
Boolean SetGreyedContextAndMgtMask (MenuItem *menuItem,
|
||
WmFunction wmFunction)
|
||
{
|
||
int ix;
|
||
|
||
for (ix = 0; ix < WMFUNCTIONTABLESIZE - 1; ++ix)
|
||
{
|
||
if (functionTable[ix].wmFunction == wmFunction)
|
||
{
|
||
/* Success! The function was found. Set up the
|
||
values and get the heck out of here. */
|
||
menuItem->greyedContext = functionTable[ix].greyedContext;
|
||
menuItem->mgtMask = functionTable[ix].mgtMask;
|
||
return(True);
|
||
}
|
||
}
|
||
|
||
/* We couldn't find the given command in the function table.
|
||
Set up the values as if the F_Nop function were found
|
||
and return False. */
|
||
menuItem->greyedContext = functionTable[F_NOP_INDEX].greyedContext;
|
||
menuItem->mgtMask = functionTable[F_NOP_INDEX].mgtMask;
|
||
return(False);
|
||
}
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* MakeSeparatorTemplate ()
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
*
|
||
*************************************<->***********************************/
|
||
static
|
||
MenuItem *MakeSeparatorTemplate (int position)
|
||
{
|
||
MenuItem *item;
|
||
|
||
item = (MenuItem *)XtMalloc(sizeof(MenuItem));
|
||
|
||
/* We use the labelType to determine where this separator is positioned
|
||
relative to the client command(s) it is surrounding, i.e. TOP or
|
||
BOTTOM */
|
||
item->labelType = position;
|
||
/* Make it look like a client command: */
|
||
item->label = XtNewString("<label-template>");
|
||
item->labelBitmapIndex = -1;
|
||
item->mnemonic = (KeySym) 0;
|
||
item->accelState = 0;
|
||
item->accelKeyCode = (KeyCode) NULL;
|
||
item->accelText = (String) NULL;
|
||
item->wmFunction = (WmFunction) F_Separator;
|
||
item->wmFuncArgs = (String) NULL;
|
||
item->greyedContext = 0;
|
||
item->mgtMask = 0;
|
||
item->clientCommandName = (String) NULL;
|
||
item->nextMenuItem = (MenuItem *) NULL;
|
||
|
||
return(item);
|
||
}
|
||
#endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
|