#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "userCmds.h"
#include "textBuf.h"
#include "text.h"
#include "nedit.h"
#include "preferences.h"
#include "window.h"
#include "menu.h"
#include "shell.h"
#include "macro.h"
#include "file.h"
#include "interpret.h"
#include "parse.h"
#include "../util/DialogF.h"
#include "../util/misc.h"
#include "../util/managedList.h"
#include "../util/nedit_malloc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/param.h>
#include <Xm/Xm.h>
#include <X11/keysym.h>
#include <X11/IntrinsicP.h>
#include <Xm/Text.h>
#include <Xm/Form.h>
#include <Xm/List.h>
#include <Xm/LabelG.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/SelectioB.h>
#include <Xm/RowColumn.h>
#include <Xm/CascadeB.h>
#include <Xm/MenuShell.h>
#include <inttypes.h>
#ifdef HAVE_DEBUG_H
#include "../debug.h"
#endif
#if XmVersion >=
1002
#define MENU_WIDGET(w) (XmGetPostedFromWidget(XtParent(w)))
#else
#define MENU_WIDGET(w) (w)
#endif
extern void _XmDismissTearOff(Widget w, XtPointer call, XtPointer x);
#define MAX_ITEMS_PER_MENU 400
#define UNKNOWN_LANGUAGE_MODE -
2
#define LEFT_MARGIN_POS 1
#define RIGHT_MARGIN_POS 99
#define LIST_RIGHT 45
#define SHELL_CMD_TOP 70
#define MACRO_CMD_TOP 40
enum dialogTypes {
SHELL_CMDS,
MACRO_CMDS,
BG_MENU_CMDS};
typedef struct {
char *name;
unsigned int modifiers;
KeySym keysym;
char mnemonic;
char input;
char output;
char repInput;
char saveFirst;
char loadAfter;
char *cmd;
} menuItemRec;
typedef struct {
int dialogType;
WindowInfo *window;
Widget nameTextW, accTextW, mneTextW, cmdTextW, saveFirstBtn;
Widget loadAfterBtn, selInpBtn, winInpBtn, eitherInpBtn, noInpBtn;
Widget repInpBtn, sameOutBtn, dlogOutBtn, winOutBtn, dlogShell;
Widget managedList;
menuItemRec **menuItemsList;
int nMenuItems;
} userCmdDialog;
typedef struct {
char *name;
Widget menuPane;
} menuTreeItem;
typedef struct {
char *usmiName;
int *usmiId;
int usmiIdLen;
} userSubMenuInfo;
typedef struct {
int usmcNbrOfMainMenuItems;
int usmcNbrOfSubMenus;
userSubMenuInfo *usmcInfo;
} userSubMenuCache;
typedef struct {
char *umiName;
int *umiId;
int umiIdLen;
Boolean umiIsDefault;
int umiNbrOfLanguageModes;
int *umiLanguageMode;
int umiDefaultIndex;
Boolean umiToBeManaged;
} userMenuInfo;
typedef struct {
int sumType;
Widget sumMenuPane;
int sumNbrOfListItems;
menuItemRec **sumItemList;
userMenuInfo **sumInfoList;
userSubMenuCache *sumSubMenus;
UserMenuList *sumMainMenuList;
Boolean *sumMenuCreated;
} selectedUserMenu;
static menuItemRec *ShellMenuItems[
MAX_ITEMS_PER_MENU];
static userMenuInfo *ShellMenuInfo[
MAX_ITEMS_PER_MENU];
static userSubMenuCache ShellSubMenus;
static int NShellMenuItems =
0;
static menuItemRec *MacroMenuItems[
MAX_ITEMS_PER_MENU];
static userMenuInfo *MacroMenuInfo[
MAX_ITEMS_PER_MENU];
static userSubMenuCache MacroSubMenus;
static int NMacroMenuItems =
0;
static menuItemRec *BGMenuItems[
MAX_ITEMS_PER_MENU];
static userMenuInfo *BGMenuInfo[
MAX_ITEMS_PER_MENU];
static userSubMenuCache BGSubMenus;
static int NBGMenuItems =
0;
static Widget ShellCmdDialog =
NULL;
static Widget MacroCmdDialog =
NULL;
static Widget BGMenuCmdDialog =
NULL;
static Widget MacroPasteReplayBtn =
NULL;
static Widget BGMenuPasteReplayBtn =
NULL;
static void editMacroOrBGMenu(WindowInfo *window,
int dialogType);
static void dimSelDepItemsInMenu(Widget menuPane, menuItemRec **menuList,
int nMenuItems,
int sensitive);
static void rebuildMenuOfAllWindows(
int menuType);
static void rebuildMenu(WindowInfo *window,
int menuType);
static Widget findInMenuTree(menuTreeItem *menuTree,
int nTreeEntries,
const char *hierName);
static char *copySubstring(
const char *string,
int length);
static Widget createUserMenuItem(Widget menuPane,
char *name, menuItemRec *f,
int index, XtCallbackProc cbRtn, XtPointer cbArg);
static Widget createUserSubMenu(Widget parent,
char *label, Widget *menuItem);
static void deleteMenuItems(Widget menuPane);
static void selectUserMenu(WindowInfo *window,
int menuType, selectedUserMenu *menu);
static void updateMenu(WindowInfo *window,
int menuType);
static void manageTearOffMenu(Widget menuPane);
static void resetManageMode(UserMenuList *list);
static void manageAllSubMenuWidgets(UserMenuListElement *subMenu);
static void unmanageAllSubMenuWidgets(UserMenuListElement *subMenu);
static void manageMenuWidgets(UserMenuList *list);
static void removeAccelFromMenuWidgets(UserMenuList *menuList);
static void assignAccelToMenuWidgets(UserMenuList *menuList, WindowInfo *window);
static void manageUserMenu(selectedUserMenu *menu, WindowInfo *window);
static void createMenuItems(WindowInfo *window, selectedUserMenu *menu);
static void okCB(Widget w, XtPointer clientData, XtPointer callData);
static void applyCB(Widget w, XtPointer clientData, XtPointer callData);
static void checkCB(Widget w, XtPointer clientData, XtPointer callData);
static int checkMacro(userCmdDialog *ucd);
static int checkMacroText(
char *macro, Widget errorParent, Widget errFocus);
static int applyDialogChanges(userCmdDialog *ucd);
static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
static void pasteReplayCB(Widget w, XtPointer clientData, XtPointer callData);
static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
static void accKeyCB(Widget w, XtPointer clientData, XKeyEvent *event);
static void sameOutCB(Widget w, XtPointer clientData, XtPointer callData);
static void shellMenuCB(Widget w, WindowInfo *window, XtPointer callData);
static void macroMenuCB(Widget w, WindowInfo *window, XtPointer callData);
static void bgMenuCB(Widget w, WindowInfo *window, XtPointer callData) ;
static void accFocusCB(Widget w, XtPointer clientData, XtPointer callData);
static void accLoseFocusCB(Widget w, XtPointer clientData,
XtPointer callData);
static void updateDialogFields(menuItemRec *f, userCmdDialog *ucd);
static menuItemRec *readDialogFields(userCmdDialog *ucd,
int silent);
static menuItemRec *copyMenuItemRec(menuItemRec *item);
static void freeMenuItemRec(menuItemRec *item);
static void *getDialogDataCB(
void *oldItem,
int explicitRequest,
int *abort,
void *cbArg);
static void setDialogDataCB(
void *item,
void *cbArg);
static void freeItemCB(
void *item);
static int dialogFieldsAreEmpty(userCmdDialog *ucd);
static void disableTextW(Widget textW);
static char *writeMenuItemString(menuItemRec **menuItems,
int nItems,
int listType);
static int loadMenuItemString(
char *inString, menuItemRec **menuItems,
int *nItems,
int listType);
static void generateAcceleratorString(
char *text,
unsigned int modifiers,
KeySym keysym);
static void genAccelEventName(
char *text,
unsigned int modifiers,
KeySym keysym);
static int parseAcceleratorString(
const char *string,
unsigned int *modifiers,
KeySym *keysym);
static int parseError(
const char *message);
static char *copyMacroToEnd(
char **inPtr);
static void addTerminatingNewline(
char **string);
static void parseMenuItemList(menuItemRec **itemList,
int nbrOfItems,
userMenuInfo **infoList, userSubMenuCache *subMenus);
static int getSubMenuDepth(
const char *menuName);
static userMenuInfo *parseMenuItemRec(menuItemRec *item);
static void parseMenuItemName(
char *menuItemName, userMenuInfo *info);
static void generateUserMenuId(userMenuInfo *info, userSubMenuCache *subMenus);
static userSubMenuInfo *findSubMenuInfo(userSubMenuCache *subMenus,
const char *hierName);
static char *stripLanguageMode(
const char *menuItemName);
static void setDefaultIndex(userMenuInfo **infoList,
int nbrOfItems,
int defaultIdx);
static void applyLangModeToUserMenuInfo(userMenuInfo **infoList,
int nbrOfItems,
int languageMode);
static int doesLanguageModeMatch(userMenuInfo *info,
int languageMode);
static void freeUserMenuInfoList(userMenuInfo **infoList,
int nbrOfItems);
static void freeUserMenuInfo(userMenuInfo *info);
static void allocSubMenuCache(userSubMenuCache *subMenus,
int nbrOfItems);
static void freeSubMenuCache(userSubMenuCache *subMenus);
static void allocUserMenuList(UserMenuList *list,
int nbrOfItems);
static void freeUserMenuList(UserMenuList *list);
static UserMenuListElement *allocUserMenuListElement(Widget menuItem,
char *accKeys);
static void freeUserMenuListElement(UserMenuListElement *element);
static UserMenuList *allocUserSubMenuList(
int nbrOfItems);
static void freeUserSubMenuList(UserMenuList *list);
void EditShellMenu(WindowInfo *window)
{
Widget form, accLabel, inpLabel, inpBox, outBox, outLabel;
Widget nameLabel, cmdLabel, okBtn, applyBtn, closeBtn;
userCmdDialog *ucd;
XmString s1;
int ac, i;
Arg args[
20];
if (ShellCmdDialog !=
NULL) {
RaiseDialogWindow(ShellCmdDialog);
return;
}
ucd = (userCmdDialog *)NEditMalloc(
sizeof(userCmdDialog));
ucd->window = window;
ucd->menuItemsList = (menuItemRec **)NEditMalloc(
sizeof(menuItemRec *) *
MAX_ITEMS_PER_MENU);
for (i=
0; i<NShellMenuItems; i++)
ucd->menuItemsList[i] = copyMenuItemRec(ShellMenuItems[i]);
ucd->nMenuItems = NShellMenuItems;
ucd->dialogType =
SHELL_CMDS;
ac =
0;
XtSetArg(args[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
XtSetArg(args[ac], XmNiconName,
"XNEdit Shell Menu"); ac++;
XtSetArg(args[ac], XmNtitle,
"Shell Menu"); ac++;
ucd->dlogShell = CreateWidget(TheAppShell,
"shellCommands",
topLevelShellWidgetClass, args, ac);
AddSmallIcon(ucd->dlogShell);
form = XtVaCreateManagedWidget(
"editShellCommands", xmFormWidgetClass,
ucd->dlogShell, XmNautoUnmanage, False,
XmNresizePolicy, XmRESIZE_NONE,
NULL);
ShellCmdDialog = ucd->dlogShell;
XtAddCallback(form, XmNdestroyCallback, destroyCB, ucd);
AddMotifCloseCallback(ucd->dlogShell, closeCB, ucd);
ac =
0;
XtSetArg(args[ac], XmNtopAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNtopPosition,
2); ac++;
XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNleftPosition,
LEFT_MARGIN_POS); ac++;
XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNrightPosition,
LIST_RIGHT-
1); ac++;
XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNbottomPosition,
SHELL_CMD_TOP); ac++;
ucd->managedList = CreateManagedList(form,
"list", args, ac,
(
void **)ucd->menuItemsList, &ucd->nMenuItems,
MAX_ITEMS_PER_MENU,
20, getDialogDataCB, ucd, setDialogDataCB, ucd, freeItemCB);
ucd->loadAfterBtn = XtVaCreateManagedWidget(
"loadAfterBtn",
xmToggleButtonWidgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Re-load file after executing command"),
XmNmnemonic,
'R',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNset, False,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
SHELL_CMD_TOP,
NULL);
XmStringFree(s1);
ucd->saveFirstBtn = XtVaCreateManagedWidget(
"saveFirstBtn",
xmToggleButtonWidgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Save file before executing command"),
XmNmnemonic,
'f',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNset, False,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->loadAfterBtn,
NULL);
XmStringFree(s1);
ucd->repInpBtn = XtVaCreateManagedWidget(
"repInpBtn",
xmToggleButtonWidgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Output replaces input"),
XmNmnemonic,
'f',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNset, False,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->saveFirstBtn,
NULL);
XmStringFree(s1);
outBox = XtVaCreateManagedWidget(
"outBox", xmRowColumnWidgetClass, form,
XmNpacking, XmPACK_TIGHT,
XmNorientation, XmHORIZONTAL,
XmNradioBehavior, True,
XmNradioAlwaysOne, True,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT +
2,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->repInpBtn,
XmNbottomOffset,
4,
NULL);
ucd->sameOutBtn = XtVaCreateManagedWidget(
"sameOutBtn",
xmToggleButtonWidgetClass, outBox,
XmNlabelString, s1=
MKSTRING(
"same document"),
XmNmnemonic,
'm',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, True,
NULL);
XmStringFree(s1);
XtAddCallback(ucd->sameOutBtn, XmNvalueChangedCallback, sameOutCB, ucd);
ucd->dlogOutBtn = XtVaCreateManagedWidget(
"dlogOutBtn",
xmToggleButtonWidgetClass, outBox,
XmNlabelString, s1=
MKSTRING(
"dialog"),
XmNmnemonic,
'g',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, False,
NULL);
XmStringFree(s1);
ucd->winOutBtn = XtVaCreateManagedWidget(
"winOutBtn", xmToggleButtonWidgetClass,
outBox,
XmNlabelString, s1=
MKSTRING(
"new document"),
XmNmnemonic,
'n',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, False,
NULL);
XmStringFree(s1);
outLabel = XtVaCreateManagedWidget(
"outLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Command Output (stdout/stderr):"),
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, outBox,
NULL);
XmStringFree(s1);
inpBox = XtVaCreateManagedWidget(
"inpBox", xmRowColumnWidgetClass, form,
XmNpacking, XmPACK_TIGHT,
XmNorientation, XmHORIZONTAL,
XmNradioBehavior, True,
XmNradioAlwaysOne, True,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT +
2,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, outLabel,
NULL);
ucd->selInpBtn = XtVaCreateManagedWidget(
"selInpBtn", xmToggleButtonWidgetClass,
inpBox,
XmNlabelString, s1=
MKSTRING(
"selection"),
XmNmnemonic,
's',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, True,
NULL);
XmStringFree(s1);
ucd->winInpBtn = XtVaCreateManagedWidget(
"winInpBtn",
xmToggleButtonWidgetClass, inpBox,
XmNlabelString, s1=
MKSTRING(
"document"),
XmNmnemonic,
'w',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, False,
NULL);
XmStringFree(s1);
ucd->eitherInpBtn = XtVaCreateManagedWidget(
"eitherInpBtn",
xmToggleButtonWidgetClass, inpBox,
XmNlabelString, s1=
MKSTRING(
"either"),
XmNmnemonic,
't',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, False,
NULL);
XmStringFree(s1);
ucd->noInpBtn = XtVaCreateManagedWidget(
"noInpBtn",
xmToggleButtonWidgetClass, inpBox,
XmNlabelString, s1=
MKSTRING(
"none"),
XmNmnemonic,
'o',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, False,
NULL);
XmStringFree(s1);
inpLabel = XtVaCreateManagedWidget(
"inpLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Command Input (stdin):"),
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, inpBox,
NULL);
XmStringFree(s1);
ucd->mneTextW = XtVaCreateManagedWidget(
"mne", xmTextWidgetClass, form,
XmNcolumns,
1,
XmNmaxLength,
1,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
RIGHT_MARGIN_POS-
10,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, inpLabel,
NULL);
RemapDeleteKey(ucd->mneTextW);
ucd->accTextW = XtVaCreateManagedWidget(
"acc", xmTextWidgetClass, form,
XmNcolumns,
12,
XmNmaxLength,
MAX_ACCEL_LEN-
1,
XmNcursorPositionVisible, False,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS-
15,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, inpLabel,
NULL);
XtAddEventHandler(ucd->accTextW, KeyPressMask, False,
(XtEventHandler)accKeyCB, ucd);
XtAddCallback(ucd->accTextW, XmNfocusCallback, accFocusCB, ucd);
XtAddCallback(ucd->accTextW, XmNlosingFocusCallback, accLoseFocusCB, ucd);
accLabel = XtVaCreateManagedWidget(
"accLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Accelerator"),
XmNmnemonic,
'l',
XmNuserData, ucd->accTextW,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
LIST_RIGHT +
24,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->mneTextW,
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"mneLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Mnemonic"),
XmNmnemonic,
'i',
XmNuserData, ucd->mneTextW,
XmNalignment, XmALIGNMENT_END,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT +
24,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->mneTextW,
NULL);
XmStringFree(s1);
ucd->nameTextW = XtVaCreateManagedWidget(
"name", xmTextWidgetClass, form,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, accLabel,
NULL);
RemapDeleteKey(ucd->nameTextW);
nameLabel = XtVaCreateManagedWidget(
"nameLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Menu Entry"),
XmNmnemonic,
'y',
XmNuserData, ucd->nameTextW,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->nameTextW,
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"nameNotes", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"(> for sub-menu, @ language mode)"),
XmNalignment, XmALIGNMENT_END,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, nameLabel,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->nameTextW,
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"topLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Select a shell menu item from the list at left.\n\
Select \"New\" to add a new command to the menu."),
XmNtopAttachment, XmATTACH_POSITION,
XmNtopPosition,
2,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, nameLabel,
NULL);
XmStringFree(s1);
cmdLabel = XtVaCreateManagedWidget(
"cmdLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Shell Command to Execute"),
XmNmnemonic,
'x',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNtopAttachment, XmATTACH_POSITION,
XmNtopPosition,
SHELL_CMD_TOP,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LEFT_MARGIN_POS,
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"cmdLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"(% expands to current filename, # to line number)"),
XmNalignment, XmALIGNMENT_END,
XmNmarginTop,
5,
XmNtopAttachment, XmATTACH_POSITION,
XmNtopPosition,
SHELL_CMD_TOP,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, cmdLabel,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
NULL);
XmStringFree(s1);
okBtn = XtVaCreateManagedWidget(
"ok",xmPushButtonWidgetClass,form,
XmNlabelString, s1=
MKSTRING(
"OK"),
XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
13,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
29,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
99,
NULL);
XtAddCallback(okBtn, XmNactivateCallback, okCB, ucd);
XmStringFree(s1);
applyBtn = XtVaCreateManagedWidget(
"apply",xmPushButtonWidgetClass,form,
XmNlabelString, s1=
MKSTRING(
"Apply"),
XmNmnemonic,
'A',
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
42,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
58,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
99,
NULL);
XtAddCallback(applyBtn, XmNactivateCallback, applyCB, ucd);
XmStringFree(s1);
closeBtn = XtVaCreateManagedWidget(
"close",
xmPushButtonWidgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Close"),
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
71,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
87,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
99,
NULL);
XtAddCallback(closeBtn, XmNactivateCallback, closeCB, ucd);
XmStringFree(s1);
ac =
0;
XtSetArg(args[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
XtSetArg(args[ac], XmNscrollHorizontal, False); ac++;
XtSetArg(args[ac], XmNwordWrap, True); ac++;
XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
XtSetArg(args[ac], XmNtopWidget, cmdLabel); ac++;
XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNleftPosition,
LEFT_MARGIN_POS); ac++;
XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNrightPosition,
RIGHT_MARGIN_POS); ac++;
XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
XtSetArg(args[ac], XmNbottomWidget, okBtn); ac++;
XtSetArg(args[ac], XmNbottomOffset,
5); ac++;
ucd->cmdTextW = XmCreateScrolledText(form,
"name", args, ac);
AddMouseWheelSupport(ucd->cmdTextW);
XtManageChild(ucd->cmdTextW);
MakeSingleLineTextW(ucd->cmdTextW);
RemapDeleteKey(ucd->cmdTextW);
XtVaSetValues(cmdLabel, XmNuserData, ucd->cmdTextW,
NULL);
disableTextW(ucd->accTextW);
updateDialogFields(
NULL, ucd);
XtVaSetValues(form, XmNdefaultButton, okBtn,
NULL);
XtVaSetValues(form, XmNcancelButton, closeBtn,
NULL);
AddDialogMnemonicHandler(form,
FALSE);
RealizeWithoutForcingPosition(ucd->dlogShell);
}
void EditMacroMenu(WindowInfo *window)
{
editMacroOrBGMenu(window,
MACRO_CMDS);
}
void EditBGMenu(WindowInfo *window)
{
editMacroOrBGMenu(window,
BG_MENU_CMDS);
}
static void editMacroOrBGMenu(WindowInfo *window,
int dialogType)
{
Widget form, accLabel, pasteReplayBtn;
Widget nameLabel, cmdLabel, okBtn, applyBtn, closeBtn;
userCmdDialog *ucd;
char *title;
XmString s1;
int ac, i;
Arg args[
20];
if (dialogType ==
MACRO_CMDS && MacroCmdDialog !=
NULL) {
RaiseDialogWindow(MacroCmdDialog);
return;
}
if (dialogType ==
BG_MENU_CMDS && BGMenuCmdDialog !=
NULL) {
RaiseDialogWindow(BGMenuCmdDialog);
return;
}
ucd = (userCmdDialog *)NEditMalloc(
sizeof(userCmdDialog));
ucd->window = window;
ucd->menuItemsList = (menuItemRec **)NEditMalloc(
sizeof(menuItemRec **) *
MAX_ITEMS_PER_MENU);
if (dialogType ==
MACRO_CMDS) {
for (i=
0; i<NMacroMenuItems; i++)
ucd->menuItemsList[i] = copyMenuItemRec(MacroMenuItems[i]);
ucd->nMenuItems = NMacroMenuItems;
}
else {
for (i=
0; i<NBGMenuItems; i++)
ucd->menuItemsList[i] = copyMenuItemRec(BGMenuItems[i]);
ucd->nMenuItems = NBGMenuItems;
}
ucd->dialogType = dialogType;
title = dialogType ==
MACRO_CMDS ?
"Macro Commands" :
"Window Background Menu";
ac =
0;
XtSetArg(args[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
XtSetArg(args[ac], XmNiconName, title); ac++;
XtSetArg(args[ac], XmNtitle, title); ac++;
ucd->dlogShell = CreateWidget(TheAppShell,
"macros",
topLevelShellWidgetClass, args, ac);
AddSmallIcon(ucd->dlogShell);
form = XtVaCreateManagedWidget(
"editMacroCommands", xmFormWidgetClass,
ucd->dlogShell, XmNautoUnmanage, False,
XmNresizePolicy, XmRESIZE_NONE,
NULL);
XtAddCallback(form, XmNdestroyCallback, destroyCB, ucd);
AddMotifCloseCallback(ucd->dlogShell, closeCB, ucd);
ac =
0;
XtSetArg(args[ac], XmNtopAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNtopPosition,
2); ac++;
XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNleftPosition,
LEFT_MARGIN_POS); ac++;
XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNrightPosition,
LIST_RIGHT-
1); ac++;
XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNbottomPosition,
MACRO_CMD_TOP); ac++;
ucd->managedList = CreateManagedList(form,
"list", args, ac,
(
void **)ucd->menuItemsList, &ucd->nMenuItems,
MAX_ITEMS_PER_MENU,
20,
getDialogDataCB, ucd, setDialogDataCB, ucd, freeItemCB);
ucd->selInpBtn = XtVaCreateManagedWidget(
"selInpBtn",
xmToggleButtonWidgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Requires Selection"),
XmNmnemonic,
'R',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginHeight,
0,
XmNset, False,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
MACRO_CMD_TOP,
NULL);
XmStringFree(s1);
ucd->mneTextW = XtVaCreateManagedWidget(
"mne", xmTextWidgetClass, form,
XmNcolumns,
1,
XmNmaxLength,
1,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
RIGHT_MARGIN_POS-
21-
5,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS-
21,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->selInpBtn,
XmNbottomOffset,
5,
NULL);
RemapDeleteKey(ucd->mneTextW);
ucd->accTextW = XtVaCreateManagedWidget(
"acc", xmTextWidgetClass, form,
XmNcolumns,
12,
XmNmaxLength,
MAX_ACCEL_LEN-
1,
XmNcursorPositionVisible, False,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS-
20-
10,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->selInpBtn,
XmNbottomOffset,
5,
NULL);
XtAddEventHandler(ucd->accTextW, KeyPressMask, False,
(XtEventHandler)accKeyCB, ucd);
XtAddCallback(ucd->accTextW, XmNfocusCallback, accFocusCB, ucd);
XtAddCallback(ucd->accTextW, XmNlosingFocusCallback, accLoseFocusCB, ucd);
accLabel = XtVaCreateManagedWidget(
"accLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Accelerator"),
XmNmnemonic,
'l',
XmNuserData, ucd->accTextW,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
LIST_RIGHT +
22,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->mneTextW,
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"mneLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Mnemonic"),
XmNmnemonic,
'i',
XmNuserData, ucd->mneTextW,
XmNalignment, XmALIGNMENT_END,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT +
22,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS-
21,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->mneTextW,
NULL);
XmStringFree(s1);
pasteReplayBtn = XtVaCreateManagedWidget(
"pasteReplay",
xmPushButtonWidgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Paste Learn/\nReplay Macro"),
XmNmnemonic,
'P',
XmNsensitive, GetReplayMacro() !=
NULL,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
RIGHT_MARGIN_POS-
20,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
MACRO_CMD_TOP,
NULL);
XtAddCallback(pasteReplayBtn, XmNactivateCallback,
pasteReplayCB, ucd);
XmStringFree(s1);
ucd->nameTextW = XtVaCreateManagedWidget(
"name", xmTextWidgetClass, form,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, accLabel,
NULL);
RemapDeleteKey(ucd->nameTextW);
nameLabel = XtVaCreateManagedWidget(
"nameLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Menu Entry"),
XmNmnemonic,
'y',
XmNuserData, ucd->nameTextW,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->nameTextW,
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"nameNotes", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"(> for sub-menu, @ language mode)"),
XmNalignment, XmALIGNMENT_END,
XmNmarginTop,
5,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, nameLabel,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, ucd->nameTextW,
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"topLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Select a macro menu item from the list at left.\n\
Select \"New\" to add a new command to the menu."),
XmNtopAttachment, XmATTACH_POSITION,
XmNtopPosition,
2,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LIST_RIGHT,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
RIGHT_MARGIN_POS,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, nameLabel,
NULL);
XmStringFree(s1);
cmdLabel = XtVaCreateManagedWidget(
"cmdLabel", xmLabelGadgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Macro Command to Execute"),
XmNmnemonic,
'x',
XmNalignment, XmALIGNMENT_BEGINNING,
XmNmarginTop,
5,
XmNtopAttachment, XmATTACH_POSITION,
XmNtopPosition,
MACRO_CMD_TOP,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
LEFT_MARGIN_POS,
NULL);
XmStringFree(s1);
okBtn = XtVaCreateManagedWidget(
"ok",xmPushButtonWidgetClass,form,
XmNlabelString, s1=
MKSTRING(
"OK"),
XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
8,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
23,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
99,
NULL);
XtAddCallback(okBtn, XmNactivateCallback, okCB, ucd);
XmStringFree(s1);
applyBtn = XtVaCreateManagedWidget(
"apply",xmPushButtonWidgetClass,form,
XmNlabelString, s1=
MKSTRING(
"Apply"),
XmNmnemonic,
'A',
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
31,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
46,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
99,
NULL);
XtAddCallback(applyBtn, XmNactivateCallback, applyCB, ucd);
XmStringFree(s1);
applyBtn = XtVaCreateManagedWidget(
"check",xmPushButtonWidgetClass,form,
XmNlabelString, s1=
MKSTRING(
"Check"),
XmNmnemonic,
'C',
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
54,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
69,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
99,
NULL);
XtAddCallback(applyBtn, XmNactivateCallback, checkCB, ucd);
XmStringFree(s1);
closeBtn = XtVaCreateManagedWidget(
"close",
xmPushButtonWidgetClass, form,
XmNlabelString, s1=
MKSTRING(
"Close"),
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition,
77,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition,
92,
XmNbottomAttachment, XmATTACH_POSITION,
XmNbottomPosition,
99,
NULL);
XtAddCallback(closeBtn, XmNactivateCallback, closeCB, ucd);
XmStringFree(s1);
ac =
0;
XtSetArg(args[ac], XmNeditMode, XmMULTI_LINE_EDIT); ac++;
XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
XtSetArg(args[ac], XmNtopWidget, cmdLabel); ac++;
XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNleftPosition,
LEFT_MARGIN_POS); ac++;
XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
XtSetArg(args[ac], XmNrightPosition,
RIGHT_MARGIN_POS); ac++;
XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
XtSetArg(args[ac], XmNbottomWidget, okBtn); ac++;
XtSetArg(args[ac], XmNbottomOffset,
5); ac++;
ucd->cmdTextW = XmCreateScrolledText(form,
"name", args, ac);
AddMouseWheelSupport(ucd->cmdTextW);
XtManageChild(ucd->cmdTextW);
RemapDeleteKey(ucd->cmdTextW);
XtVaSetValues(cmdLabel, XmNuserData, ucd->cmdTextW,
NULL);
disableTextW(ucd->accTextW);
updateDialogFields(
NULL, ucd);
XtVaSetValues(form, XmNdefaultButton, okBtn,
NULL);
XtVaSetValues(form, XmNcancelButton, closeBtn,
NULL);
AddDialogMnemonicHandler(form,
FALSE);
if (dialogType ==
MACRO_CMDS) {
MacroCmdDialog = ucd->dlogShell;
MacroPasteReplayBtn = pasteReplayBtn;
}
else {
BGMenuCmdDialog = ucd->dlogShell;
BGMenuPasteReplayBtn = pasteReplayBtn;
}
RealizeWithoutForcingPosition(ucd->dlogShell);
}
void UpdateUserMenus(WindowInfo *window)
{
if (!IsTopDocument(window))
return;
if (window->userMenuCache->umcLanguageMode != window->languageMode) {
updateMenu(window,
SHELL_CMDS);
updateMenu(window,
MACRO_CMDS);
window->userMenuCache->umcLanguageMode = window->languageMode;
}
if (window->userBGMenuCache.ubmcLanguageMode != window->languageMode) {
updateMenu(window,
BG_MENU_CMDS);
window->userBGMenuCache.ubmcLanguageMode = window->languageMode;
}
}
void DimPasteReplayBtns(
int sensitive)
{
if (MacroCmdDialog !=
NULL)
XtSetSensitive(MacroPasteReplayBtn, sensitive);
if (BGMenuCmdDialog !=
NULL)
XtSetSensitive(BGMenuPasteReplayBtn, sensitive);
}
void DimSelectionDepUserMenuItems(WindowInfo *window,
int sensitive)
{
if (!IsTopDocument(window))
return;
dimSelDepItemsInMenu(window->shellMenuPane, ShellMenuItems,
NShellMenuItems, sensitive);
dimSelDepItemsInMenu(window->macroMenuPane, MacroMenuItems,
NMacroMenuItems, sensitive);
dimSelDepItemsInMenu(window->bgMenuPane, BGMenuItems,
NBGMenuItems, sensitive);
}
static void dimSelDepItemsInMenu(Widget menuPane, menuItemRec **menuList,
int nMenuItems,
int sensitive)
{
WidgetList items;
Widget subMenu;
XtPointer userData;
int n, index;
Cardinal nItems;
XtVaGetValues(menuPane, XmNchildren, &items, XmNnumChildren, &nItems,
NULL);
for (n=
0; n<(
int)nItems; n++) {
XtVaGetValues(items[n], XmNuserData, &userData,
NULL);
if (userData != (XtPointer)
PERMANENT_MENU_ITEM) {
if (XtClass(items[n]) == xmCascadeButtonWidgetClass) {
XtVaGetValues(items[n], XmNsubMenuId, &subMenu,
NULL);
dimSelDepItemsInMenu(subMenu, menuList, nMenuItems, sensitive);
}
else {
index = (
int)(
intptr_t)userData -
10;
if (index <
0 || index >= nMenuItems)
return;
if (menuList[index]->input ==
FROM_SELECTION)
XtSetSensitive(items[n], sensitive);
}
}
}
}
void SetBGMenuUndoSensitivity(WindowInfo *window,
int sensitive)
{
if (window->bgMenuUndoItem !=
NULL)
SetSensitive(window, window->bgMenuUndoItem, sensitive);
}
void SetBGMenuRedoSensitivity(WindowInfo *window,
int sensitive)
{
if (window->bgMenuRedoItem !=
NULL)
SetSensitive(window, window->bgMenuRedoItem, sensitive);
}
char *WriteShellCmdsString(
void)
{
return writeMenuItemString(ShellMenuItems, NShellMenuItems,
SHELL_CMDS);
}
char *WriteMacroCmdsString(
void)
{
return writeMenuItemString(MacroMenuItems, NMacroMenuItems,
MACRO_CMDS);
}
char *WriteBGMenuCmdsString(
void)
{
return writeMenuItemString(BGMenuItems, NBGMenuItems,
BG_MENU_CMDS);
}
int LoadShellCmdsString(
char *inString)
{
return loadMenuItemString(inString, ShellMenuItems, &NShellMenuItems,
SHELL_CMDS);
}
int LoadMacroCmdsString(
char *inString)
{
return loadMenuItemString(inString, MacroMenuItems, &NMacroMenuItems,
MACRO_CMDS);
}
int LoadBGMenuCmdsString(
char *inString)
{
return loadMenuItemString(inString, BGMenuItems, &NBGMenuItems,
BG_MENU_CMDS);
}
void SetupUserMenuInfo(
void)
{
parseMenuItemList(ShellMenuItems, NShellMenuItems, ShellMenuInfo, &ShellSubMenus);
parseMenuItemList(MacroMenuItems, NMacroMenuItems, MacroMenuInfo, &MacroSubMenus);
parseMenuItemList(BGMenuItems , NBGMenuItems , BGMenuInfo , &BGSubMenus);
}
void UpdateUserMenuInfo(
void)
{
freeUserMenuInfoList(ShellMenuInfo, NShellMenuItems);
freeSubMenuCache(&ShellSubMenus);
parseMenuItemList(ShellMenuItems, NShellMenuItems, ShellMenuInfo, &ShellSubMenus);
freeUserMenuInfoList(MacroMenuInfo, NMacroMenuItems);
freeSubMenuCache(&MacroSubMenus);
parseMenuItemList(MacroMenuItems, NMacroMenuItems, MacroMenuInfo, &MacroSubMenus);
freeUserMenuInfoList(BGMenuInfo, NBGMenuItems);
freeSubMenuCache(&BGSubMenus);
parseMenuItemList(BGMenuItems, NBGMenuItems, BGMenuInfo, &BGSubMenus);
}
int DoNamedShellMenuCmd(WindowInfo *window,
const char *itemName,
int fromMacro)
{
int i;
for (i=
0; i<NShellMenuItems; i++) {
if (!strcmp(ShellMenuItems[i]->name, itemName)) {
if (ShellMenuItems[i]->output ==
TO_SAME_WINDOW &&
CheckReadOnly(window))
return False;
DoShellMenuCmd(window, ShellMenuItems[i]->cmd,
ShellMenuItems[i]->input, ShellMenuItems[i]->output,
ShellMenuItems[i]->repInput, ShellMenuItems[i]->saveFirst,
ShellMenuItems[i]->loadAfter, fromMacro);
return True;
}
}
return False;
}
int DoNamedMacroMenuCmd(WindowInfo *window,
const char *itemName)
{
int i;
for (i=
0; i<NMacroMenuItems; i++) {
if (!strcmp(MacroMenuItems[i]->name, itemName)) {
DoMacro(window, MacroMenuItems[i]->cmd,
"macro menu command");
return True;
}
}
return False;
}
int DoNamedBGMenuCmd(WindowInfo *window,
const char *itemName)
{
int i;
for (i=
0; i<NBGMenuItems; i++) {
if (!strcmp(BGMenuItems[i]->name, itemName)) {
DoMacro(window, BGMenuItems[i]->cmd,
"background menu macro");
return True;
}
}
return False;
}
void RebuildAllMenus(WindowInfo *window)
{
rebuildMenu(window,
SHELL_CMDS);
rebuildMenu(window,
MACRO_CMDS);
rebuildMenu(window,
BG_MENU_CMDS);
}
static void rebuildMenuOfAllWindows(
int menuType)
{
WindowInfo *w;
for (w=WindowList; w!=
NULL; w=w->next)
rebuildMenu(w, menuType);
}
static void rebuildMenu(WindowInfo *window,
int menuType)
{
selectedUserMenu menu;
if (menuType !=
BG_MENU_CMDS && !IsTopDocument(window))
return;
selectUserMenu(window, menuType, &menu);
if (!XmIsMenuShell(XtParent(menu.sumMenuPane)))
_XmDismissTearOff(XtParent(menu.sumMenuPane),
NULL,
NULL);
deleteMenuItems(menu.sumMenuPane);
freeUserMenuList(menu.sumMainMenuList);
*menu.sumMenuCreated = False;
updateMenu(window, menuType);
}
static void selectUserMenu(WindowInfo *window,
int menuType, selectedUserMenu *menu)
{
if (menuType ==
SHELL_CMDS) {
menu->sumMenuPane = window->shellMenuPane;
menu->sumNbrOfListItems = NShellMenuItems;
menu->sumItemList = ShellMenuItems;
menu->sumInfoList = ShellMenuInfo;
menu->sumSubMenus = &ShellSubMenus;
menu->sumMainMenuList = &window->userMenuCache->umcShellMenuList;
menu->sumMenuCreated = &window->userMenuCache->umcShellMenuCreated;
}
else if (menuType ==
MACRO_CMDS) {
menu->sumMenuPane = window->macroMenuPane;
menu->sumNbrOfListItems = NMacroMenuItems;
menu->sumItemList = MacroMenuItems;
menu->sumInfoList = MacroMenuInfo;
menu->sumSubMenus = &MacroSubMenus;
menu->sumMainMenuList = &window->userMenuCache->umcMacroMenuList;
menu->sumMenuCreated = &window->userMenuCache->umcMacroMenuCreated;
}
else {
menu->sumMenuPane = window->bgMenuPane;
menu->sumNbrOfListItems = NBGMenuItems;
menu->sumItemList = BGMenuItems;
menu->sumInfoList = BGMenuInfo;
menu->sumSubMenus = &BGSubMenus;
menu->sumMainMenuList = &window->userBGMenuCache.ubmcMenuList;
menu->sumMenuCreated = &window->userBGMenuCache.ubmcMenuCreated;
}
menu->sumType = menuType;
}
static void updateMenu(WindowInfo *window,
int menuType)
{
selectedUserMenu menu;
EnableWindowResourceDB(window);
selectUserMenu(window, menuType, &menu);
applyLangModeToUserMenuInfo(menu.sumInfoList, menu.sumNbrOfListItems,
window->languageMode);
if (!*menu.sumMenuCreated)
createMenuItems(window, &menu);
manageUserMenu(&menu, window);
if (menuType ==
BG_MENU_CMDS) {
SetBGMenuUndoSensitivity(window, XtIsSensitive(window->undoItem));
SetBGMenuRedoSensitivity(window, XtIsSensitive(window->redoItem));
}
DimSelectionDepUserMenuItems(window, window->buffer->primary.selected);
EnableDefaultColorProfileResourceDB(XtDisplay(window->mainWin));
}
static void manageTearOffMenu(Widget menuPane)
{
Dimension width, height, border;
XtVaGetValues(XtParent(menuPane), XmNborderWidth, &border,
NULL);
XtVaGetValues(menuPane, XmNwidth, &width, XmNheight, &height,
NULL);
XtResizeWidget(XtParent(menuPane), width, height, border);
XtManageChild(menuPane);
}
static void resetManageMode(UserMenuList *list)
{
int i;
UserMenuListElement *element;
for (i=
0; i<list->umlNbrItems; i ++) {
element = list->umlItems[i];
element->umlePrevManageMode = element->umleManageMode;
element->umleManageMode =
UMMM_UNMANAGE;
if (element->umleSubMenuList !=
NULL)
resetManageMode(element->umleSubMenuList);
}
}
static void manageAllSubMenuWidgets(UserMenuListElement *subMenu)
{
int i;
UserMenuList *subMenuList;
UserMenuListElement *element;
WidgetList widgetList;
Cardinal nWidgetListItems;
if (!XmIsMenuShell(XtParent(subMenu->umleSubMenuPane))) {
XtUnmanageChild(subMenu->umleSubMenuPane);
}
XtVaGetValues(subMenu->umleSubMenuPane,
XmNchildren, &widgetList,
XmNnumChildren, &nWidgetListItems,
NULL);
XtManageChildren(widgetList, nWidgetListItems);
subMenuList = subMenu->umleSubMenuList;
for (i=
0; i<subMenuList->umlNbrItems; i ++) {
element = subMenuList->umlItems[i];
if (element->umleSubMenuList !=
NULL) {
manageAllSubMenuWidgets(element);
}
}
XtManageChild(subMenu->umleMenuItem);
if (!XmIsMenuShell(XtParent(subMenu->umleSubMenuPane))) {
manageTearOffMenu(subMenu->umleSubMenuPane);
}
ShowHiddenTearOff(subMenu->umleSubMenuPane);
}
static void unmanageAllSubMenuWidgets(UserMenuListElement *subMenu)
{
int i;
Widget shell;
UserMenuList *subMenuList;
UserMenuListElement *element;
WidgetList widgetList;
Cardinal nWidgetListItems;
shell = XtParent(subMenu->umleSubMenuPane);
if (!XmIsMenuShell(shell)) {
XtUnmapWidget(shell);
}
XtVaGetValues(subMenu->umleSubMenuPane,
XmNchildren, &widgetList,
XmNnumChildren, &nWidgetListItems,
NULL);
XtUnmanageChildren(widgetList, nWidgetListItems);
subMenuList = subMenu->umleSubMenuList;
for (i=
0; i<subMenuList->umlNbrItems; i ++) {
element = subMenuList->umlItems[i];
if (element->umleSubMenuList !=
NULL) {
unmanageAllSubMenuWidgets(element);
}
}
XtUnmanageChild(subMenu->umleMenuItem);
}
static void manageMenuWidgets(UserMenuList *list)
{
int i;
UserMenuListElement *element;
for (i=
0; i<list->umlNbrItems; i ++) {
element = list->umlItems[i];
if (element->umlePrevManageMode != element->umleManageMode ||
element->umleManageMode ==
UMMM_MANAGE) {
if (element->umleManageMode ==
UMMM_MANAGE_ALL) {
manageAllSubMenuWidgets(element);
}
else if (element->umleManageMode ==
UMMM_MANAGE) {
if (element->umlePrevManageMode ==
UMMM_UNMANAGE ||
element->umlePrevManageMode ==
UMMM_UNMANAGE_ALL) {
XtManageChild(element->umleMenuItem);
}
if (element->umleSubMenuList !=
NULL) {
if (!XmIsMenuShell(XtParent(element->umleSubMenuPane))) {
XtUnmanageChild(element->umleSubMenuPane);
}
manageMenuWidgets(element->umleSubMenuList);
if (!XmIsMenuShell(XtParent(element->umleSubMenuPane))) {
manageTearOffMenu(element->umleSubMenuPane);
}
ShowHiddenTearOff(element->umleSubMenuPane);
}
}
else if (element->umleManageMode ==
UMMM_UNMANAGE_ALL){
unmanageAllSubMenuWidgets(element);
}
else {
XtUnmanageChild(element->umleMenuItem);
}
}
}
}
static void removeAccelFromMenuWidgets(UserMenuList *menuList)
{
int i;
UserMenuListElement *element;
for (i=
0; i<menuList->umlNbrItems; i ++) {
element = menuList->umlItems[i];
if (element->umleSubMenuList !=
NULL) {
removeAccelFromMenuWidgets(element->umleSubMenuList);
}
else if (element->umleAccKeys !=
NULL &&
element->umleManageMode ==
UMMM_UNMANAGE &&
element->umlePrevManageMode ==
UMMM_MANAGE) {
XtVaSetValues(element->umleMenuItem, XmNaccelerator,
NULL,
NULL);
}
}
}
static void assignAccelToMenuWidgets(UserMenuList *menuList, WindowInfo *window)
{
int i;
UserMenuListElement *element;
for (i=
0; i<menuList->umlNbrItems; i ++) {
element = menuList->umlItems[i];
if (element->umleSubMenuList !=
NULL) {
assignAccelToMenuWidgets(element->umleSubMenuList, window);
}
else if (element->umleAccKeys !=
NULL &&
element->umleManageMode ==
UMMM_MANAGE &&
element->umlePrevManageMode ==
UMMM_UNMANAGE) {
XtVaSetValues(element->umleMenuItem, XmNaccelerator,
element->umleAccKeys,
NULL);
if (!element->umleAccLockPatchApplied) {
UpdateAccelLockPatch(window->splitPane, element->umleMenuItem);
element->umleAccLockPatchApplied = True;
}
}
}
}
static void manageUserMenu(selectedUserMenu *menu, WindowInfo *window)
{
int n, i;
int *id;
Boolean currentLEisSubMenu;
userMenuInfo *info;
UserMenuList *menuList;
UserMenuListElement *currentLE;
UserMenuManageMode *mode;
resetManageMode(menu->sumMainMenuList);
for (n=
0; n<menu->sumNbrOfListItems; n++) {
info = menu->sumInfoList[n];
menuList = menu->sumMainMenuList;
id = info->umiId;
for (i=
0; i<info->umiIdLen; i ++) {
currentLE = menuList->umlItems[*id];
mode = ¤tLE->umleManageMode;
currentLEisSubMenu = (currentLE->umleSubMenuList !=
NULL);
if (info->umiToBeManaged) {
if (*mode ==
UMMM_UNMANAGE) {
if (currentLEisSubMenu) {
*mode =
UMMM_MANAGE_ALL;
}
else {
*mode =
UMMM_MANAGE;
}
}
else if (*mode ==
UMMM_UNMANAGE_ALL) {
*mode =
UMMM_MANAGE;
}
}
else {
if (*mode ==
UMMM_UNMANAGE) {
if (currentLEisSubMenu) {
*mode =
UMMM_UNMANAGE_ALL;
}
}
else if (*mode ==
UMMM_MANAGE_ALL) {
*mode =
UMMM_MANAGE;
}
}
menuList = currentLE->umleSubMenuList;
id ++;
}
}
if (!XmIsMenuShell(XtParent(menu->sumMenuPane)))
XtUnmanageChild(menu->sumMenuPane);
manageMenuWidgets(menu->sumMainMenuList);
removeAccelFromMenuWidgets(menu->sumMainMenuList);
assignAccelToMenuWidgets(menu->sumMainMenuList, window);
if (!XmIsMenuShell(XtParent(menu->sumMenuPane)))
manageTearOffMenu(menu->sumMenuPane);
}
static void createMenuItems(WindowInfo *window, selectedUserMenu *menu)
{
Widget btn, subPane, newSubPane;
int n;
menuItemRec *item;
menuTreeItem *menuTree;
int i, nTreeEntries, size;
char *hierName, *namePtr, *subMenuName, *subSep, *fullName;
int menuType = menu->sumType;
userMenuInfo *info;
userSubMenuCache *subMenus = menu->sumSubMenus;
userSubMenuInfo *subMenuInfo;
UserMenuList *menuList;
UserMenuListElement *currentLE;
int subMenuDepth;
char accKeysBuf[
MAX_ACCEL_LEN+
5];
char *accKeys;
size =
sizeof(menuTreeItem) * menu->sumNbrOfListItems;
menuTree = (menuTreeItem *)NEditMalloc(size);
nTreeEntries =
0;
window->bgMenuUndoItem =
NULL;
window->bgMenuRedoItem =
NULL;
allocUserMenuList(menu->sumMainMenuList, subMenus->usmcNbrOfMainMenuItems);
for (n=
0; n<menu->sumNbrOfListItems; n++) {
item = menu->sumItemList[n];
info = menu->sumInfoList[n];
menuList = menu->sumMainMenuList;
subMenuDepth =
0;
fullName = info->umiName;
namePtr = fullName;
subPane = menu->sumMenuPane;
for (;;) {
subSep = strchr(namePtr,
'>');
if (subSep ==
NULL) {
btn = createUserMenuItem(subPane, namePtr, item, n,
(XtCallbackProc)(menuType ==
SHELL_CMDS ? shellMenuCB :
(menuType ==
MACRO_CMDS ? macroMenuCB : bgMenuCB)),
(XtPointer)window);
if (menuType ==
BG_MENU_CMDS && !strcmp(item->cmd,
"undo()\n"))
window->bgMenuUndoItem = btn;
else if (menuType ==
BG_MENU_CMDS && !strcmp(item->cmd,
"redo()\n"))
window->bgMenuRedoItem = btn;
genAccelEventName(accKeysBuf, item->modifiers, item->keysym);
accKeys = item->keysym == NoSymbol ?
NULL : NEditStrdup(accKeysBuf);
menuList->umlItems[menuList->umlNbrItems ++] =
allocUserMenuListElement(btn, accKeys);
break;
}
hierName = copySubstring(fullName, subSep - fullName);
subMenuInfo = findSubMenuInfo(subMenus, hierName);
newSubPane = findInMenuTree(menuTree, nTreeEntries, hierName);
if (newSubPane ==
NULL) {
subMenuName = copySubstring(namePtr, subSep - namePtr);
newSubPane = createUserSubMenu(subPane, subMenuName, &btn);
NEditFree(subMenuName);
menuTree[nTreeEntries].name = hierName;
menuTree[nTreeEntries++].menuPane = newSubPane;
currentLE = allocUserMenuListElement(btn,
NULL);
menuList->umlItems[menuList->umlNbrItems ++] = currentLE;
currentLE->umleSubMenuPane = newSubPane;
currentLE->umleSubMenuList =
allocUserSubMenuList(subMenuInfo->usmiId[subMenuInfo->usmiIdLen]);
}
else {
currentLE = menuList->umlItems[subMenuInfo->usmiId[subMenuDepth]];
NEditFree(hierName);
}
subPane = newSubPane;
menuList = currentLE->umleSubMenuList;
subMenuDepth ++;
namePtr = subSep +
1;
}
}
*menu->sumMenuCreated = True;
for (i=
0; i<nTreeEntries; i++)
NEditFree(menuTree[i].name);
NEditFree(menuTree);
}
static Widget findInMenuTree(menuTreeItem *menuTree,
int nTreeEntries,
const char *hierName)
{
int i;
for (i=
0; i<nTreeEntries; i++)
if (!strcmp(hierName, menuTree[i].name))
return menuTree[i].menuPane;
return NULL;
}
static char *copySubstring(
const char *string,
int length)
{
char *retStr = (
char*)NEditMalloc(length +
1);
strncpy(retStr, string, length);
retStr[length] =
'\0';
return retStr;
}
static Widget createUserMenuItem(Widget menuPane,
char *name, menuItemRec *f,
int index, XtCallbackProc cbRtn, XtPointer cbArg)
{
XmString st1, st2;
char accText[
MAX_ACCEL_LEN];
Widget btn;
generateAcceleratorString(accText, f->modifiers, f->keysym);
st1=XmStringCreateSimple(name);
st2=XmStringCreateSimple(accText);
btn = XtVaCreateWidget(
"cmd", xmPushButtonWidgetClass, menuPane,
XmNlabelString, st1,
XmNacceleratorText, st2,
XmNmnemonic, f->mnemonic,
XmNuserData, (XtPointer)(
intptr_t)(index+
10),
NULL);
XtAddCallback(btn, XmNactivateCallback, cbRtn, cbArg);
XmStringFree(st1);
XmStringFree(st2);
return btn;
}
static Widget createUserSubMenu(Widget parent,
char *label, Widget *menuItem)
{
Widget menuPane;
XmString st1;
static Arg args[
1] = {{XmNuserData, (XtArgVal)
TEMPORARY_MENU_ITEM}};
menuPane = CreatePulldownMenu(parent,
"userPulldown", args,
1);
*menuItem = XtVaCreateWidget(
"userCascade", xmCascadeButtonWidgetClass, parent,
XmNlabelString, st1=XmStringCreateSimple(label),
XmNsubMenuId, menuPane, XmNuserData,
TEMPORARY_MENU_ITEM,
NULL);
XmStringFree(st1);
return menuPane;
}
static void deleteMenuItems(Widget menuPane)
{
WidgetList itemList, items;
Cardinal nItems;
Widget subMenuID;
XtPointer userData;
int n;
XtVaGetValues(menuPane, XmNchildren, &itemList,
XmNnumChildren, &nItems,
NULL);
items = (WidgetList)NEditMalloc(
sizeof(Widget) * nItems);
memcpy(items, itemList,
sizeof(Widget) * nItems);
for (n=
0; n<(
int)nItems; n++) {
XtVaGetValues(items[n], XmNuserData, &userData,
NULL);
if (userData != (XtPointer)
PERMANENT_MENU_ITEM) {
if (XtClass(items[n]) == xmCascadeButtonWidgetClass) {
XtVaGetValues(items[n], XmNsubMenuId, &subMenuID,
NULL);
if (!XmIsMenuShell(XtParent(subMenuID)))
_XmDismissTearOff(XtParent(subMenuID),
NULL,
NULL);
deleteMenuItems(subMenuID);
#if XmVersion <
2000
XtDestroyWidget(subMenuID);
#endif
}
else {
XtVaSetValues(items[n], XmNaccelerator,
NULL,
NULL);
}
XtDestroyWidget(items[n]);
}
}
NEditFree(items);
}
static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
if (ucd->dialogType ==
SHELL_CMDS)
ShellCmdDialog =
NULL;
else if (ucd->dialogType ==
MACRO_CMDS)
MacroCmdDialog =
NULL;
else
BGMenuCmdDialog =
NULL;
XtDestroyWidget(ucd->dlogShell);
}
static void okCB(Widget w, XtPointer clientData, XtPointer callData)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
if (!applyDialogChanges(ucd))
return;
if (ucd->dialogType ==
SHELL_CMDS)
ShellCmdDialog =
NULL;
else if (ucd->dialogType ==
MACRO_CMDS)
MacroCmdDialog =
NULL;
else
BGMenuCmdDialog =
NULL;
XtDestroyWidget(ucd->dlogShell);
}
static void applyCB(Widget w, XtPointer clientData, XtPointer callData)
{
applyDialogChanges((userCmdDialog *)clientData);
}
static void checkCB(Widget w, XtPointer clientData, XtPointer callData)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
if (checkMacro(ucd))
{
DialogF(
DF_INF, ucd->dlogShell,
1,
"Macro",
"Macro compiled without error",
"OK");
}
}
static int checkMacro(userCmdDialog *ucd)
{
menuItemRec *f;
f = readDialogFields(ucd, False);
if (f ==
NULL)
return False;
if (!checkMacroText(f->cmd, ucd->dlogShell, ucd->cmdTextW)) {
freeMenuItemRec(f);
return False;
}
return True;
}
static int checkMacroText(
char *macro, Widget errorParent, Widget errFocus)
{
Program *prog;
char *errMsg, *stoppedAt;
prog = ParseMacro(macro, &errMsg, &stoppedAt);
if (prog ==
NULL) {
if (errorParent !=
NULL) {
ParseError(errorParent, macro, stoppedAt,
"macro", errMsg);
XmTextSetInsertionPosition(errFocus, stoppedAt - macro);
XmProcessTraversal(errFocus, XmTRAVERSE_CURRENT);
}
return False;
}
FreeProgram(prog);
if (*stoppedAt !=
'\0') {
if (errorParent !=
NULL) {
ParseError(errorParent, macro, stoppedAt,
"macro",
"syntax error");
XmTextSetInsertionPosition(errFocus, stoppedAt - macro);
XmProcessTraversal(errFocus, XmTRAVERSE_CURRENT);
}
return False;
}
return True;
}
static int applyDialogChanges(userCmdDialog *ucd)
{
int i;
if (!UpdateManagedList(ucd->managedList, True))
return False;
if (ucd->dialogType ==
MACRO_CMDS)
if (!checkMacro(ucd))
return False;
if (ucd->dialogType ==
SHELL_CMDS) {
for (i=
0; i<NShellMenuItems; i++)
freeMenuItemRec(ShellMenuItems[i]);
freeUserMenuInfoList(ShellMenuInfo, NShellMenuItems);
freeSubMenuCache(&ShellSubMenus);
for (i=
0; i<ucd->nMenuItems; i++)
ShellMenuItems[i] = copyMenuItemRec(ucd->menuItemsList[i]);
NShellMenuItems = ucd->nMenuItems;
parseMenuItemList(ShellMenuItems, NShellMenuItems, ShellMenuInfo, &ShellSubMenus);
}
else if (ucd->dialogType ==
MACRO_CMDS) {
for (i=
0; i<NMacroMenuItems; i++)
freeMenuItemRec(MacroMenuItems[i]);
freeUserMenuInfoList(MacroMenuInfo, NMacroMenuItems);
freeSubMenuCache(&MacroSubMenus);
for (i=
0; i<ucd->nMenuItems; i++)
MacroMenuItems[i] = copyMenuItemRec(ucd->menuItemsList[i]);
NMacroMenuItems = ucd->nMenuItems;
parseMenuItemList(MacroMenuItems, NMacroMenuItems, MacroMenuInfo, &MacroSubMenus);
}
else {
for (i=
0; i<NBGMenuItems; i++)
freeMenuItemRec(BGMenuItems[i]);
freeUserMenuInfoList(BGMenuInfo, NBGMenuItems);
freeSubMenuCache(&BGSubMenus);
for (i=
0; i<ucd->nMenuItems; i++)
BGMenuItems[i] = copyMenuItemRec(ucd->menuItemsList[i]);
NBGMenuItems = ucd->nMenuItems;
parseMenuItemList(BGMenuItems, NBGMenuItems, BGMenuInfo, &BGSubMenus);
}
rebuildMenuOfAllWindows(ucd->dialogType);
MarkPrefsChanged();
return True;
}
static void pasteReplayCB(Widget w, XtPointer clientData, XtPointer callData)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
if (GetReplayMacro() ==
NULL)
return;
XmTextInsert(ucd->cmdTextW, XmTextGetInsertionPosition(ucd->cmdTextW),
GetReplayMacro());
}
static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
int i;
for (i=
0; i<ucd->nMenuItems; i++)
freeMenuItemRec(ucd->menuItemsList[i]);
NEditFree(ucd->menuItemsList);
NEditFree(ucd);
}
static void accFocusCB(Widget w, XtPointer clientData, XtPointer callData)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
RemoveDialogMnemonicHandler(XtParent(ucd->accTextW));
}
static void accLoseFocusCB(Widget w, XtPointer clientData, XtPointer callData)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
AddDialogMnemonicHandler(XtParent(ucd->accTextW),
FALSE);
}
static void accKeyCB(Widget w, XtPointer clientData, XKeyEvent *event)
{
userCmdDialog *ucd = (userCmdDialog *)clientData;
KeySym keysym = XLookupKeysym(event,
0);
char outStr[
MAX_ACCEL_LEN];
if (IsModifierKey(keysym))
return;
if (keysym == XK_Tab)
return;
if (event->state & ~(ShiftMask | LockMask | ControlMask | Mod1Mask |
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)) {
XBell(TheDisplay,
0);
return;
}
if (keysym == XK_Delete || keysym == XK_BackSpace) {
XmTextSetString(ucd->accTextW,
"");
return;
}
generateAcceleratorString(outStr, event->state, keysym);
if (strlen(outStr) ==
1) {
XBell(TheDisplay,
0);
return;
}
XmTextSetString(ucd->accTextW, outStr);
}
static void sameOutCB(Widget w, XtPointer clientData, XtPointer callData)
{
XtSetSensitive(((userCmdDialog *)clientData)->repInpBtn,
XmToggleButtonGetState(w));
}
static void shellMenuCB(Widget w, WindowInfo *window, XtPointer callData)
{
XtArgVal userData;
int index;
char *params[
1];
window = WidgetToWindow(
MENU_WIDGET(w));
XtVaGetValues(w, XmNuserData, &userData,
NULL);
index = (
int)userData -
10;
if (index <
0 || index >= NShellMenuItems)
return;
params[
0] = ShellMenuItems[index]->name;
XtCallActionProc(window->lastFocus,
"shell_menu_command",
((XmAnyCallbackStruct *)callData)->event, params,
1);
}
static void macroMenuCB(Widget w, WindowInfo *window, XtPointer callData)
{
XtArgVal userData;
int index;
char *params[
1];
window = WidgetToWindow(
MENU_WIDGET(w));
if (window->macroCmdData !=
NULL) {
XBell(TheDisplay,
0);
return;
}
XtVaGetValues(w, XmNuserData, &userData,
NULL);
index = (
int)userData -
10;
if (index <
0 || index >= NMacroMenuItems)
return;
params[
0] = MacroMenuItems[index]->name;
XtCallActionProc(window->lastFocus,
"macro_menu_command",
((XmAnyCallbackStruct *)callData)->event, params,
1);
}
static void bgMenuCB(Widget w, WindowInfo *window, XtPointer callData)
{
XtArgVal userData;
int index;
char *params[
1];
if (window->macroCmdData !=
NULL) {
XBell(TheDisplay,
0);
return;
}
XtVaGetValues(w, XmNuserData, &userData,
NULL);
index = (
int)userData -
10;
if (index <
0 || index >= NBGMenuItems)
return;
params[
0] = BGMenuItems[index]->name;
XtCallActionProc(window->lastFocus,
"bg_menu_command",
((XmAnyCallbackStruct *)callData)->event, params,
1);
}
static void updateDialogFields(menuItemRec *f, userCmdDialog *ucd)
{
char mneString[
2], accString[
MAX_ACCEL_LEN];
if (f ==
NULL) {
XmTextSetString(ucd->nameTextW,
"");
XmTextSetString(ucd->cmdTextW,
"");
XmTextSetString(ucd->accTextW,
"");
XmTextSetString(ucd->mneTextW,
"");
if (ucd->dialogType ==
SHELL_CMDS) {
RadioButtonChangeState(ucd->selInpBtn, True, True);
RadioButtonChangeState(ucd->sameOutBtn, True, True);
RadioButtonChangeState(ucd->repInpBtn, False, False);
XtSetSensitive(ucd->repInpBtn, True);
RadioButtonChangeState(ucd->saveFirstBtn, False, False);
RadioButtonChangeState(ucd->loadAfterBtn, False, False);
}
}
else {
mneString[
0] = f->mnemonic;
mneString[
1] =
'\0';
generateAcceleratorString(accString, f->modifiers, f->keysym);
XmTextSetString(ucd->nameTextW, f->name);
XmTextSetString(ucd->cmdTextW, f->cmd);
XmTextSetString(ucd->accTextW, accString);
XmTextSetString(ucd->mneTextW, mneString);
RadioButtonChangeState(ucd->selInpBtn, f->input==
FROM_SELECTION, False);
if (ucd->dialogType ==
SHELL_CMDS) {
RadioButtonChangeState(ucd->winInpBtn, f->input ==
FROM_WINDOW,
False);
RadioButtonChangeState(ucd->eitherInpBtn, f->input ==
FROM_EITHER,
False);
RadioButtonChangeState(ucd->noInpBtn, f->input ==
FROM_NONE,
False);
RadioButtonChangeState(ucd->sameOutBtn, f->output==
TO_SAME_WINDOW,
False);
RadioButtonChangeState(ucd->winOutBtn, f->output==
TO_NEW_WINDOW,
False);
RadioButtonChangeState(ucd->dlogOutBtn, f->output==
TO_DIALOG,
False);
RadioButtonChangeState(ucd->repInpBtn, f->repInput, False);
XtSetSensitive(ucd->repInpBtn, f->output==
TO_SAME_WINDOW);
RadioButtonChangeState(ucd->saveFirstBtn, f->saveFirst, False);
RadioButtonChangeState(ucd->loadAfterBtn, f->loadAfter, False);
}
}
}
static menuItemRec *readDialogFields(userCmdDialog *ucd,
int silent)
{
char *nameText, *cmdText, *mneText, *accText;
menuItemRec *f;
nameText = XmTextGetString(ucd->nameTextW);
if (*nameText ==
'\0')
{
if (!silent)
{
DialogF(
DF_WARN, ucd->dlogShell,
1,
"Menu Entry",
"Please specify a name\nfor the menu item",
"OK");
XmProcessTraversal(ucd->nameTextW, XmTRAVERSE_CURRENT);
}
NEditFree(nameText);
return NULL;
}
if (strchr(nameText,
':'))
{
if (!silent)
{
DialogF(
DF_WARN, ucd->dlogShell,
1,
"Menu Entry",
"Menu item names may not\ncontain colon (:) characters",
"OK");
XmProcessTraversal(ucd->nameTextW, XmTRAVERSE_CURRENT);
}
NEditFree(nameText);
return NULL;
}
cmdText = XmTextGetString(ucd->cmdTextW);
if (cmdText ==
NULL || *cmdText ==
'\0')
{
if (!silent)
{
DialogF(
DF_WARN, ucd->dlogShell,
1,
"Command to Execute",
"Please specify %s to execute",
"OK",
ucd->dialogType ==
SHELL_CMDS
?
"shell command"
:
"macro command(s)");
XmProcessTraversal(ucd->cmdTextW, XmTRAVERSE_CURRENT);
}
NEditFree(nameText);
NEditFree(cmdText);
return NULL;
}
if (ucd->dialogType ==
MACRO_CMDS || ucd->dialogType ==
BG_MENU_CMDS) {
addTerminatingNewline(&cmdText);
if (!checkMacroText(cmdText, silent ?
NULL : ucd->dlogShell,
ucd->cmdTextW)) {
NEditFree(nameText);
NEditFree(cmdText);
return NULL;
}
}
f = (menuItemRec *)NEditMalloc(
sizeof(menuItemRec));
f->name = nameText;
f->cmd = cmdText;
if ((mneText = XmTextGetString(ucd->mneTextW)) !=
NULL) {
f->mnemonic = mneText==
NULL ?
'\0' : mneText[
0];
NEditFree(mneText);
if (f->mnemonic ==
':')
f->mnemonic =
'\0';
}
if ((accText = XmTextGetString(ucd->accTextW)) !=
NULL) {
parseAcceleratorString(accText, &f->modifiers, &f->keysym);
NEditFree(accText);
}
if (ucd->dialogType ==
SHELL_CMDS) {
if (XmToggleButtonGetState(ucd->selInpBtn))
f->input =
FROM_SELECTION;
else if (XmToggleButtonGetState(ucd->winInpBtn))
f->input =
FROM_WINDOW;
else if (XmToggleButtonGetState(ucd->eitherInpBtn))
f->input =
FROM_EITHER;
else
f->input =
FROM_NONE;
if (XmToggleButtonGetState(ucd->winOutBtn))
f->output =
TO_NEW_WINDOW;
else if (XmToggleButtonGetState(ucd->dlogOutBtn))
f->output =
TO_DIALOG;
else
f->output =
TO_SAME_WINDOW;
f->repInput = XmToggleButtonGetState(ucd->repInpBtn);
f->saveFirst = XmToggleButtonGetState(ucd->saveFirstBtn);
f->loadAfter = XmToggleButtonGetState(ucd->loadAfterBtn);
}
else {
f->input = XmToggleButtonGetState(ucd->selInpBtn) ?
FROM_SELECTION :
FROM_NONE;
f->output =
TO_SAME_WINDOW;
f->repInput = False;
f->saveFirst = False;
f->loadAfter = False;
}
return f;
}
static menuItemRec *copyMenuItemRec(menuItemRec *item)
{
menuItemRec *newItem;
newItem = (menuItemRec *)NEditMalloc(
sizeof(menuItemRec));
*newItem = *item;
newItem->name = (
char*)NEditMalloc(strlen(item->name)+
1);
strcpy(newItem->name, item->name);
newItem->cmd = (
char*)NEditMalloc(strlen(item->cmd)+
1);
strcpy(newItem->cmd, item->cmd);
return newItem;
}
static void freeMenuItemRec(menuItemRec *item)
{
NEditFree(item->name);
NEditFree(item->cmd);
NEditFree(item);
}
static void *getDialogDataCB(
void *oldItem,
int explicitRequest,
int *abort,
void *cbArg)
{
userCmdDialog *ucd = (userCmdDialog *)cbArg;
menuItemRec *currentFields;
if (oldItem ==
NULL && dialogFieldsAreEmpty(ucd))
return NULL;
currentFields = readDialogFields(ucd, True);
if (currentFields !=
NULL)
return (
void *)currentFields;
if (!explicitRequest)
{
if (DialogF(
DF_WARN, ucd->dlogShell,
2,
"Discard Entry",
"Discard incomplete entry\nfor current menu item?",
"Keep",
"Discard") ==
2)
{
return oldItem ==
NULL
?
NULL
: (
void *)copyMenuItemRec((menuItemRec *)oldItem);
}
}
readDialogFields(ucd, False);
*abort = True;
return NULL;
}
static void setDialogDataCB(
void *item,
void *cbArg)
{
updateDialogFields((menuItemRec *)item, (userCmdDialog *)cbArg);
}
static int dialogFieldsAreEmpty(userCmdDialog *ucd)
{
return TextWidgetIsBlank(ucd->nameTextW) &&
TextWidgetIsBlank(ucd->cmdTextW) &&
TextWidgetIsBlank(ucd->accTextW) &&
TextWidgetIsBlank(ucd->mneTextW) &&
(ucd->dialogType !=
SHELL_CMDS || (
XmToggleButtonGetState(ucd->selInpBtn) &&
XmToggleButtonGetState(ucd->sameOutBtn) &&
!XmToggleButtonGetState(ucd->repInpBtn) &&
!XmToggleButtonGetState(ucd->saveFirstBtn) &&
!XmToggleButtonGetState(ucd->loadAfterBtn)));
}
static void freeItemCB(
void *item)
{
freeMenuItemRec((menuItemRec *)item);
}
static void disableTextW(Widget textW)
{
static XtTranslations emptyTable =
NULL;
static char *emptyTranslations =
"\
<EnterWindow>: enter()\n\
<Btn1Down>: grab-focus()\n\
<Btn1Motion>: extend-adjust()\n\
<Btn1Up>: extend-end()\n\
Shift<Key>Tab: prev-tab-group()\n\
Ctrl<Key>Tab: next-tab-group()\n\
<Key>Tab: next-tab-group()\n\
<LeaveWindow>: leave()\n\
<FocusIn>: focusIn()\n\
<FocusOut>: focusOut()\n\
<Unmap>: unmap()\n";
if (emptyTable ==
NULL)
emptyTable = XtParseTranslationTable(emptyTranslations);
XtVaSetValues(textW, XmNtranslations, emptyTable,
NULL);
}
static char *writeMenuItemString(menuItemRec **menuItems,
int nItems,
int listType)
{
char *outStr, *outPtr, *c, accStr[
MAX_ACCEL_LEN];
menuItemRec *f;
int i, length;
length =
0;
for (i=
0; i<nItems; i++) {
f = menuItems[i];
generateAcceleratorString(accStr, f->modifiers, f->keysym);
length += strlen(f->name) *
2;
length += strlen(accStr);
length += strlen(f->cmd) *
6;
length +=
21;
}
length++;
outStr = (
char*)NEditMalloc(length);
outPtr = outStr;
*outPtr++ =
'\\';
*outPtr++ =
'\n';
for (i=
0; i<nItems; i++) {
f = menuItems[i];
generateAcceleratorString(accStr, f->modifiers, f->keysym);
*outPtr++ =
'\t';
for (c=f->name; *c!=
'\0'; ++c) {
if (*c ==
'\\') {
*outPtr++ =
'\\';
*outPtr++ =
'\\';
}
else if (*c ==
'\n') {
*outPtr++ =
'\\';
*outPtr++ =
'n';
}
else {
*outPtr++ = *c;
}
}
*outPtr++ =
':';
strcpy(outPtr, accStr);
outPtr += strlen(accStr);
*outPtr++ =
':';
if (f->mnemonic !=
'\0')
*outPtr++ = f->mnemonic;
*outPtr++ =
':';
if (listType ==
SHELL_CMDS) {
if (f->input ==
FROM_SELECTION)
*outPtr++ =
'I';
else if (f->input ==
FROM_WINDOW)
*outPtr++ =
'A';
else if (f->input ==
FROM_EITHER)
*outPtr++ =
'E';
if (f->output ==
TO_DIALOG)
*outPtr++ =
'D';
else if (f->output ==
TO_NEW_WINDOW)
*outPtr++ =
'W';
if (f->repInput)
*outPtr++ =
'X';
if (f->saveFirst)
*outPtr++ =
'S';
if (f->loadAfter)
*outPtr++ =
'L';
*outPtr++ =
':';
}
else {
if (f->input ==
FROM_SELECTION)
*outPtr++ =
'R';
*outPtr++ =
':';
*outPtr++ =
' ';
*outPtr++ =
'{';
}
*outPtr++ =
'\\';
*outPtr++ =
'n';
*outPtr++ =
'\\';
*outPtr++ =
'\n';
*outPtr++ =
'\t';
*outPtr++ =
'\t';
for (c=f->cmd; *c!=
'\0'; c++) {
if (*c ==
'\\') {
*outPtr++ =
'\\';
*outPtr++ =
'\\';
}
else if (*c ==
'\n') {
*outPtr++ =
'\\';
*outPtr++ =
'n';
*outPtr++ =
'\\';
*outPtr++ =
'\n';
*outPtr++ =
'\t';
*outPtr++ =
'\t';
}
else
*outPtr++ = *c;
}
if (listType ==
MACRO_CMDS || listType ==
BG_MENU_CMDS) {
if (*(outPtr-
1) ==
'\t') outPtr--;
*outPtr++ =
'}';
}
*outPtr++ =
'\\';
*outPtr++ =
'n';
*outPtr++ =
'\\';
*outPtr++ =
'\n';
}
--outPtr;
*--outPtr =
'\0';
return outStr;
}
static int loadMenuItemString(
char *inString, menuItemRec **menuItems,
int *nItems,
int listType)
{
menuItemRec *f;
char *cmdStr;
char *inPtr = inString;
char *nameStr, accStr[
MAX_ACCEL_LEN], mneChar;
KeySym keysym;
unsigned int modifiers;
int i, input, output, saveFirst, loadAfter, repInput;
int nameLen, accLen, mneLen, cmdLen;
for (;;) {
while (*inPtr ==
' ' || *inPtr ==
'\t')
inPtr++;
if (*inPtr ==
'\0') {
return True;
}
nameLen = strcspn(inPtr,
":");
if (nameLen ==
0)
return parseError(
"no name field");
nameStr = (
char*)NEditMalloc(nameLen+
1);
strncpy(nameStr, inPtr, nameLen);
nameStr[nameLen] =
'\0';
inPtr += nameLen;
if (*inPtr ==
'\0')
return parseError(
"end not expected");
inPtr++;
accLen = strcspn(inPtr,
":");
if (accLen >=
MAX_ACCEL_LEN)
return parseError(
"accelerator field too long");
strncpy(accStr, inPtr, accLen);
accStr[accLen] =
'\0';
inPtr += accLen;
if (*inPtr ==
'\0')
return parseError(
"end not expected");
inPtr++;
mneLen = strcspn(inPtr,
":");
if (mneLen >
1)
return parseError(
"mnemonic field too long");
if (mneLen ==
1)
mneChar = *inPtr++;
else
mneChar =
'\0';
inPtr++;
if (*inPtr ==
'\0')
return parseError(
"end not expected");
input =
FROM_NONE;
output =
TO_SAME_WINDOW;
repInput = False;
saveFirst = False;
loadAfter = False;
for (; *inPtr !=
':'; inPtr++) {
if (listType ==
SHELL_CMDS) {
if (*inPtr ==
'I')
input =
FROM_SELECTION;
else if (*inPtr ==
'A')
input =
FROM_WINDOW;
else if (*inPtr ==
'E')
input =
FROM_EITHER;
else if (*inPtr ==
'W')
output =
TO_NEW_WINDOW;
else if (*inPtr ==
'D')
output =
TO_DIALOG;
else if (*inPtr ==
'X')
repInput = True;
else if (*inPtr ==
'S')
saveFirst = True;
else if (*inPtr ==
'L')
loadAfter = True;
else
return parseError(
"unreadable flag field");
}
else {
if (*inPtr ==
'R')
input =
FROM_SELECTION;
else
return parseError(
"unreadable flag field");
}
}
inPtr++;
if (listType ==
SHELL_CMDS) {
if (*inPtr++ !=
'\n')
return parseError(
"command must begin with newline");
while (*inPtr ==
' ' || *inPtr ==
'\t')
inPtr++;
cmdLen = strcspn(inPtr,
"\n");
if (cmdLen ==
0)
return parseError(
"shell command field is empty");
cmdStr = (
char*)NEditMalloc(cmdLen+
1);
strncpy(cmdStr, inPtr, cmdLen);
cmdStr[cmdLen] =
'\0';
inPtr += cmdLen;
}
else {
cmdStr = copyMacroToEnd(&inPtr);
if (cmdStr ==
NULL)
return False;
}
while (*inPtr ==
' ' || *inPtr ==
'\t' || *inPtr ==
'\n')
inPtr++;
if (!parseAcceleratorString(accStr, &modifiers, &keysym))
return parseError(
"couldn''t read accelerator field");
f = (menuItemRec *)NEditMalloc(
sizeof(menuItemRec));
f->name = nameStr;
f->cmd = cmdStr;
f->mnemonic = mneChar;
f->modifiers = modifiers;
f->input = input;
f->output = output;
f->repInput = repInput;
f->saveFirst = saveFirst;
f->loadAfter = loadAfter;
f->keysym = keysym;
for (i=
0; i < *nItems; i++) {
if (!strcmp(menuItems[i]->name, f->name)) {
freeMenuItemRec(menuItems[i]);
menuItems[i] = f;
break;
}
}
if (i == *nItems)
menuItems[(*nItems)++] = f;
}
}
static int parseError(
const char *message)
{
fprintf(stderr,
"XNEdit: Parse error in user defined menu item, %s\n",
message);
return False;
}
static void generateAcceleratorString(
char *text,
unsigned int modifiers,
KeySym keysym)
{
char *shiftStr =
"", *ctrlStr =
"", *altStr =
"";
char *mod2Str =
"", *mod3Str =
"", *mod4Str =
"", *mod5Str =
"";
char keyName[
20];
Modifiers numLockMask = GetNumLockModMask(TheDisplay);
if (keysym == NoSymbol) {
*text =
'\0';
return;
}
if (modifiers & ShiftMask)
shiftStr =
"Shift+";
if (modifiers & ControlMask)
ctrlStr =
"Ctrl+";
if (modifiers & Mod1Mask)
altStr =
"Alt+";
if ((modifiers & Mod2Mask) && (Mod2Mask != numLockMask))
mod2Str =
"Mod2+";
if ((modifiers & Mod3Mask) && (Mod3Mask != numLockMask))
mod3Str =
"Mod3+";
if ((modifiers & Mod4Mask) && (Mod4Mask != numLockMask))
mod4Str =
"Mod4+";
if ((modifiers & Mod5Mask) && (Mod5Mask != numLockMask))
mod5Str =
"Mod5+";
strcpy(keyName, XKeysymToString(keysym));
*keyName = toupper(*keyName);
sprintf(text,
"%s%s%s%s%s%s%s%s", shiftStr, ctrlStr, altStr,
mod2Str, mod3Str, mod4Str, mod5Str, keyName);
}
static void genAccelEventName(
char *text,
unsigned int modifiers,
KeySym keysym)
{
char *shiftStr =
"", *lockStr =
"", *ctrlStr =
"", *altStr =
"";
char *mod2Str =
"", *mod3Str =
"", *mod4Str =
"", *mod5Str =
"";
if (keysym == NoSymbol) {
*text =
'\0';
return;
}
if (modifiers & ShiftMask)
shiftStr =
"Shift ";
if (modifiers & LockMask)
lockStr =
"Lock ";
if (modifiers & ControlMask)
ctrlStr =
"Ctrl ";
if (modifiers & Mod1Mask)
altStr =
"Alt ";
if (modifiers & Mod2Mask)
mod2Str =
"Mod2 ";
if (modifiers & Mod3Mask)
mod3Str =
"Mod3 ";
if (modifiers & Mod4Mask)
mod4Str =
"Mod4 ";
if (modifiers & Mod5Mask)
mod5Str =
"Mod5 ";
sprintf(text,
"%s%s%s%s%s%s%s%s<Key>%s",
shiftStr, lockStr, ctrlStr, altStr,
mod2Str, mod3Str, mod4Str, mod5Str,
XKeysymToString(keysym));
}
static int parseAcceleratorString(
const char *string,
unsigned int *modifiers,
KeySym *keysym)
{
int i, nFields, inputLength = strlen(string);
char fields[
10][
MAX_ACCEL_LEN];
if (inputLength ==
0) {
*modifiers =
0;
*keysym = NoSymbol;
return True;
}
if (inputLength >
MAX_ACCEL_LEN)
return False;
nFields = sscanf(string,
"%[^+]+%[^+]+%[^+]+%[^+]+%[^+]+%[^+]+%[^+]+%[^+]+%[^+]+%[^+]",
fields[
0], fields[
1], fields[
2], fields[
3], fields[
4], fields[
5],
fields[
6], fields[
7], fields[
8], fields[
9]);
if (nFields ==
0)
return False;
*keysym = XStringToKeysym(fields[nFields-
1]);
if (*keysym == NoSymbol) {
*fields[nFields-
1] = tolower(*fields[nFields-
1]);
*keysym = XStringToKeysym(fields[nFields-
1]);
if (*keysym == NoSymbol)
return False;
}
*modifiers =
0;
for (i=
0; i<nFields-
1; i++) {
if (!strcmp(fields[i],
"Shift"))
*modifiers |= ShiftMask;
else if (!strcmp(fields[i],
"Lock"))
*modifiers |= LockMask;
else if (!strcmp(fields[i],
"Ctrl"))
*modifiers |= ControlMask;
else if (!strcmp(fields[i],
"Alt"))
*modifiers |= Mod1Mask;
else if (!strcmp(fields[i],
"Mod2"))
*modifiers |= Mod2Mask;
else if (!strcmp(fields[i],
"Mod3"))
*modifiers |= Mod3Mask;
else if (!strcmp(fields[i],
"Mod4"))
*modifiers |= Mod4Mask;
else if (!strcmp(fields[i],
"Mod5"))
*modifiers |= Mod5Mask;
else
return False;
}
return True;
}
static char *copyMacroToEnd(
char **inPtr)
{
char *retStr, *errMsg, *stoppedAt, *p, *retPtr;
Program *prog;
*inPtr += strspn(*inPtr,
" \t\n");
if (**inPtr !=
'{') {
ParseError(
NULL, *inPtr, *inPtr-
1,
"macro menu item",
"expecting ''{''");
return NULL;
}
prog = ParseMacro(*inPtr, &errMsg, &stoppedAt);
if (prog ==
NULL) {
ParseError(
NULL, *inPtr, stoppedAt,
"macro menu item", errMsg);
return NULL;
}
FreeProgram(prog);
(*inPtr)++;
*inPtr += strspn(*inPtr,
" \t");
if (**inPtr ==
'\n') (*inPtr)++;
if (**inPtr ==
'\t') (*inPtr)++;
if (**inPtr ==
'\t') (*inPtr)++;
retPtr = retStr = (
char*)NEditMalloc(stoppedAt - *inPtr +
1);
for (p = *inPtr; p < stoppedAt -
1; p++) {
if (!strncmp(p,
"\n\t\t",
3)) {
*retPtr++ =
'\n';
p +=
2;
}
else
*retPtr++ = *p;
}
if (*(retPtr-
1) ==
'\t') retPtr--;
*retPtr =
'\0';
*inPtr = stoppedAt;
return retStr;
}
static void addTerminatingNewline(
char **string)
{
char *newString;
int length;
length = strlen(*string);
if ((*string)[length-
1] !=
'\n') {
newString = (
char*)NEditMalloc(length +
2);
strcpy(newString, *string);
newString[length] =
'\n';
newString[length+
1] =
'\0';
NEditFree(*string);
*string = newString;
}
}
UserMenuCache *CreateUserMenuCache(
void)
{
UserMenuCache *cache = (UserMenuCache *)NEditMalloc(
sizeof(UserMenuCache));
cache->umcLanguageMode = -
2;
cache->umcShellMenuCreated = False;
cache->umcMacroMenuCreated = False;
cache->umcShellMenuList.umlNbrItems =
0;
cache->umcShellMenuList.umlItems =
NULL;
cache->umcMacroMenuList.umlNbrItems =
0;
cache->umcMacroMenuList.umlItems =
NULL;
return cache;
}
void FreeUserMenuCache(UserMenuCache *cache)
{
freeUserMenuList(&cache->umcShellMenuList);
freeUserMenuList(&cache->umcMacroMenuList);
NEditFree(cache);
}
void InitUserBGMenuCache(UserBGMenuCache *cache)
{
cache->ubmcLanguageMode = -
2;
cache->ubmcMenuCreated = False;
cache->ubmcMenuList.umlNbrItems =
0;
cache->ubmcMenuList.umlItems =
NULL;
}
void FreeUserBGMenuCache(UserBGMenuCache *cache)
{
freeUserMenuList(&cache->ubmcMenuList);
}
static void parseMenuItemList(menuItemRec **itemList,
int nbrOfItems,
userMenuInfo **infoList, userSubMenuCache *subMenus)
{
int i;
userMenuInfo *info;
allocSubMenuCache(subMenus, nbrOfItems);
for (i=
0; i<nbrOfItems; i++) {
infoList[i] = parseMenuItemRec(itemList[i]);
generateUserMenuId(infoList[i], subMenus);
}
for (i=
0; i<nbrOfItems; i++) {
info = infoList[i];
if (info->umiIsDefault) {
setDefaultIndex(infoList, nbrOfItems, i);
}
}
}
static int getSubMenuDepth(
const char *menuName)
{
const char *subSep;
int depth =
0;
subSep = menuName;
while ((subSep = strchr(subSep,
'>')) !=
NULL ) {
depth ++;
subSep ++;
}
return depth;
}
static userMenuInfo *parseMenuItemRec(menuItemRec *item)
{
userMenuInfo *newInfo;
int subMenuDepth;
int idSize;
newInfo = (userMenuInfo *)NEditMalloc(
sizeof(userMenuInfo));
newInfo->umiName = stripLanguageMode(item->name);
subMenuDepth = getSubMenuDepth(newInfo->umiName);
idSize =
sizeof(
int)*(subMenuDepth+
1);
newInfo->umiId = (
int *)NEditMalloc(idSize);
memset(newInfo->umiId,
0,idSize);
newInfo->umiIdLen =
0;
newInfo->umiIsDefault = False;
newInfo->umiNbrOfLanguageModes =
0;
newInfo->umiLanguageMode =
NULL;
newInfo->umiDefaultIndex = -
1;
newInfo->umiToBeManaged = False;
parseMenuItemName(item->name, newInfo);
return newInfo;
}
static void parseMenuItemName(
char *menuItemName, userMenuInfo *info)
{
char *atPtr, *firstAtPtr, *endPtr;
char c;
int languageMode;
int langModes[
MAX_LANGUAGE_MODES];
int nbrLM =
0;
int size;
atPtr = firstAtPtr = strchr(menuItemName,
'@');
if (atPtr !=
NULL) {
if (!strcmp(atPtr+
1,
"*")) {
info->umiIsDefault = True;
return;
}
while (atPtr !=
NULL) {
for(endPtr=atPtr+
1; isalnum((
unsigned char)*endPtr) || *endPtr==
'_' ||
*endPtr==
'-' || *endPtr==
' ' || *endPtr==
'+' || *endPtr==
'$' ||
*endPtr==
'#'; endPtr++);
c = *endPtr;
*endPtr =
'\0';
languageMode = FindLanguageMode(atPtr+
1);
if (languageMode ==
PLAIN_LANGUAGE_MODE) {
langModes[nbrLM] =
UNKNOWN_LANGUAGE_MODE;
}
else {
langModes[nbrLM] = languageMode;
}
nbrLM ++;
*endPtr = c;
atPtr = strchr(endPtr,
'@');
}
if (nbrLM !=
0) {
info->umiNbrOfLanguageModes = nbrLM;
size =
sizeof(
int)*nbrLM;
info->umiLanguageMode = (
int *)NEditMalloc(size);
memcpy(info->umiLanguageMode, langModes, size);
}
}
}
static void generateUserMenuId(userMenuInfo *info, userSubMenuCache *subMenus)
{
int idSize;
char *hierName, *subSep;
int subMenuDepth =
0;
int *menuIdx = &subMenus->usmcNbrOfMainMenuItems;
userSubMenuInfo *curSubMenu;
subSep = info->umiName;
while ((subSep = strchr(subSep,
'>')) !=
NULL) {
hierName = copySubstring(info->umiName, subSep - info->umiName);
curSubMenu = findSubMenuInfo(subMenus, hierName);
if (curSubMenu ==
NULL) {
info->umiId[subMenuDepth] = *menuIdx;
(*menuIdx) ++;
curSubMenu = &subMenus->usmcInfo[subMenus->usmcNbrOfSubMenus];
subMenus->usmcNbrOfSubMenus ++;
curSubMenu->usmiName = hierName;
idSize =
sizeof(
int)*(subMenuDepth+
2);
curSubMenu->usmiId = (
int *)NEditMalloc(idSize);
memcpy(curSubMenu->usmiId, info->umiId, idSize);
curSubMenu->usmiIdLen = subMenuDepth+
1;
}
else {
NEditFree(hierName);
info->umiId[subMenuDepth] = curSubMenu->usmiId[subMenuDepth];
}
subMenuDepth ++;
menuIdx = &curSubMenu->usmiId[subMenuDepth];
subSep ++;
}
info->umiId[subMenuDepth] = *menuIdx;
info->umiIdLen = subMenuDepth +
1;
(*menuIdx) ++;
}
static userSubMenuInfo *findSubMenuInfo(userSubMenuCache *subMenus,
const char *hierName)
{
int i;
for (i=
0; i<subMenus->usmcNbrOfSubMenus; i++)
if (!strcmp(hierName, subMenus->usmcInfo[i].usmiName))
return &subMenus->usmcInfo[i];
return NULL;
}
static char *stripLanguageMode(
const char *menuItemName)
{
char *firstAtPtr;
firstAtPtr = strchr(menuItemName,
'@');
if (firstAtPtr ==
NULL)
return NEditStrdup(menuItemName);
else
return copySubstring(menuItemName, firstAtPtr-menuItemName);
}
static void setDefaultIndex(userMenuInfo **infoList,
int nbrOfItems,
int defaultIdx)
{
char *defaultMenuName = infoList[defaultIdx]->umiName;
int i;
userMenuInfo *info;
for (i=
0; i<nbrOfItems; i++) {
info = infoList[i];
if (!info->umiIsDefault && strcmp(info->umiName, defaultMenuName)==
0) {
info->umiDefaultIndex = defaultIdx;
}
}
}
static void applyLangModeToUserMenuInfo(userMenuInfo **infoList,
int nbrOfItems,
int languageMode)
{
int i;
userMenuInfo *info;
for (i=
0; i<nbrOfItems; i++) {
info = infoList[i];
info->umiToBeManaged =
(info->umiNbrOfLanguageModes ==
0 || info->umiIsDefault);
}
for (i=
0; i<nbrOfItems; i++) {
info = infoList[i];
if (info->umiNbrOfLanguageModes !=
0) {
if (doesLanguageModeMatch(info, languageMode)) {
info->umiToBeManaged = True;
if (info->umiDefaultIndex != -
1)
infoList[info->umiDefaultIndex]->umiToBeManaged = False;
}
}
}
}
static int doesLanguageModeMatch(userMenuInfo *info,
int languageMode)
{
int i;
for (i=
0; i<info->umiNbrOfLanguageModes; i++) {
if (info->umiLanguageMode[i] == languageMode)
return True;
}
return False;
}
static void freeUserMenuInfoList(userMenuInfo **infoList,
int nbrOfItems)
{
int i;
for (i=
0; i<nbrOfItems; i++) {
freeUserMenuInfo(infoList[i]);
}
}
static void freeUserMenuInfo(userMenuInfo *info)
{
NEditFree(info->umiName);
NEditFree(info->umiId);
if (info->umiNbrOfLanguageModes !=
0)
NEditFree(info->umiLanguageMode);
NEditFree(info);
}
static void allocSubMenuCache(userSubMenuCache *subMenus,
int nbrOfItems)
{
int size =
sizeof(userSubMenuInfo) * nbrOfItems;
subMenus->usmcNbrOfMainMenuItems =
0;
subMenus->usmcNbrOfSubMenus =
0;
subMenus->usmcInfo = (userSubMenuInfo *)NEditMalloc(size);
}
static void freeSubMenuCache(userSubMenuCache *subMenus)
{
int i;
for (i=
0; i<subMenus->usmcNbrOfSubMenus; i++) {
NEditFree(subMenus->usmcInfo[i].usmiName);
NEditFree(subMenus->usmcInfo[i].usmiId);
}
NEditFree(subMenus->usmcInfo);
}
static void allocUserMenuList(UserMenuList *list,
int nbrOfItems)
{
int size =
sizeof(UserMenuListElement *) * nbrOfItems;
list->umlNbrItems =
0;
list->umlItems = (UserMenuListElement **)NEditMalloc(size);
}
static void freeUserMenuList(UserMenuList *list)
{
int i;
for (i=
0; i<list->umlNbrItems; i++)
freeUserMenuListElement(list->umlItems[i]);
list->umlNbrItems =
0;
NEditFree(list->umlItems);
list->umlItems =
NULL;
}
static UserMenuListElement *allocUserMenuListElement(Widget menuItem,
char *accKeys)
{
UserMenuListElement *element;
element = (UserMenuListElement *)NEditMalloc(
sizeof(UserMenuListElement));
element->umleManageMode =
UMMM_UNMANAGE;
element->umlePrevManageMode =
UMMM_UNMANAGE;
element->umleAccKeys = accKeys;
element->umleAccLockPatchApplied = False;
element->umleMenuItem = menuItem;
element->umleSubMenuPane =
NULL;
element->umleSubMenuList =
NULL;
return element;
}
static void freeUserMenuListElement(UserMenuListElement *element)
{
if (element->umleSubMenuList !=
NULL)
freeUserSubMenuList(element->umleSubMenuList);
NEditFree(element->umleAccKeys);
NEditFree(element);
}
static UserMenuList *allocUserSubMenuList(
int nbrOfItems)
{
UserMenuList *list;
list = (UserMenuList *)NEditMalloc(
sizeof(UserMenuList));
allocUserMenuList(list, nbrOfItems);
return list;
}
static void freeUserSubMenuList(UserMenuList *list)
{
freeUserMenuList(list);
NEditFree(list);
}