#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "macro.h"
#include "textBuf.h"
#include "text.h"
#include "nedit.h"
#include "window.h"
#include "preferences.h"
#include "interpret.h"
#include "parse.h"
#include "search.h"
#include "server.h"
#include "shell.h"
#include "smartIndent.h"
#include "userCmds.h"
#include "selection.h"
#include "../util/rbTree.h"
#include "tags.h"
#include "calltips.h"
#include "../util/DialogF.h"
#include "../util/misc.h"
#include "../util/fileUtils.h"
#include "../util/utils.h"
#include "../util/getfiles.h"
#include "../util/filedialog.h"
#include "highlight.h"
#include "highlightData.h"
#include "rangeset.h"
#include "../util/nedit_malloc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef __MVS__
#include <sys/param.h>
#endif
#include <fcntl.h>
#include <inttypes.h>
#include <X11/Intrinsic.h>
#include <X11/keysym.h>
#include <Xm/Xm.h>
#include <Xm/CutPaste.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/LabelG.h>
#include <Xm/List.h>
#include <Xm/ToggleB.h>
#include <Xm/DialogS.h>
#include <Xm/MessageB.h>
#include <Xm/SelectioB.h>
#include <Xm/PushB.h>
#include <Xm/Text.h>
#include <Xm/Separator.h>
#ifdef HAVE_DEBUG_H
#include "../debug.h"
#endif
#define MAX_MACRO_ACTIONS 1024
#define MAX_ACTION_ARGS 40
#define BANNER_WAIT_TIME 6000
#define M_FAILURE(s)
do { *errMsg = s;
if (
1)
return False; }
while (
0)
#define M_STR_ALLOC_ASSERT(xDV)
do {
if (xDV.tag ==
STRING_TAG && !xDV.val.str.rep) { *errMsg =
"Failed to allocate value: %s";
return(False); } }
while (
0)
#define M_ARRAY_INSERT_FAILURE()
M_FAILURE(
"array element failed to insert: %s")
typedef struct {
XtIntervalId bannerTimeoutID;
XtWorkProcId continueWorkProcID;
char bannerIsUp;
char closeOnCompletion;
Program *program;
RestartData *context;
Widget dialog;
} macroCmdInfo;
typedef struct {
WindowInfo *forWindow;
char *lastCommand;
Widget shell, repeatText, lastCmdToggle;
Widget inSelToggle, toEndToggle;
} repeatDialog;
static void cancelLearn(
void);
static void runMacro(WindowInfo *window, Program *prog);
static void finishMacroCmdExecution(WindowInfo *window);
static void repeatOKCB(Widget w, XtPointer clientData, XtPointer callData);
static void repeatApplyCB(Widget w, XtPointer clientData, XtPointer callData);
static int doRepeatDialogAction(repeatDialog *rd, XEvent *event);
static void repeatCancelCB(Widget w, XtPointer clientData, XtPointer callData);
static void repeatDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
static void learnActionHook(Widget w, XtPointer clientData, String actionName,
XEvent *event, String *params, Cardinal *numParams);
static void lastActionHook(Widget w, XtPointer clientData, String actionName,
XEvent *event, String *params, Cardinal *numParams);
static char *actionToString(Widget w,
char *actionName, XEvent *event,
String *params, Cardinal numParams);
static int isMouseAction(
const char *action);
static int isRedundantAction(
const char *action);
static int isIgnoredAction(
const char *action);
static int readCheckMacroString(Widget dialogParent,
char *string,
WindowInfo *runWindow,
const char *errIn,
char **errPos);
static void bannerTimeoutProc(XtPointer clientData, XtIntervalId *id);
static Boolean continueWorkProc(XtPointer clientData);
static int escapeStringChars(
char *fromString,
char *toString);
static int escapedStringLength(
char *string);
static int lengthMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int minMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int maxMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int focusWindowMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int getRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int getCharacterMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int replaceRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int replaceSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int getSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int validNumberMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int replaceInStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int replaceSubstringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int readFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int writeFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int appendFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int writeOrAppendFile(
int append, WindowInfo *window,
DataValue *argList,
int nArgs, DataValue *result,
char **errMsg);
static int substringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int toupperMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int tolowerMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int stringToClipboardMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int clipboardToStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int searchMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int searchStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int setCursorPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int beepMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int selectMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int selectRectangleMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int tPrintMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int getenvMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int shellCmdMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int dialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static void dialogBtnCB(Widget w, XtPointer clientData, XtPointer callData);
static void dialogCloseCB(Widget w, XtPointer clientData, XtPointer callData);
#ifdef LESSTIF_VERSION
static void dialogEscCB(Widget w, XtPointer clientData, XEvent *event,
Boolean *cont);
#endif
static int stringDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static void stringDialogBtnCB(Widget w, XtPointer clientData,
XtPointer callData);
static void stringDialogCloseCB(Widget w, XtPointer clientData,
XtPointer callData);
#ifdef LESSTIF_VERSION
static void stringDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
Boolean *cont);
#endif
static int calltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int killCalltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int listDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static void listDialogBtnCB(Widget w, XtPointer clientData,
XtPointer callData);
static void listDialogCloseCB(Widget w, XtPointer clientData,
XtPointer callData);
#ifdef LESSTIF_VERSION
static void listDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
Boolean *cont);
#endif
static int stringCompareMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int splitMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int cursorMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int lineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int columnMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int fileNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int filePathMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int lengthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int selectionStartMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int selectionEndMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int selectionLeftMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int selectionRightMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int statisticsLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int incSearchLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int showLineNumbersMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int autoIndentMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int wrapTextMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int highlightSyntaxMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int makeBackupCopyMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int incBackupMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int showMatchingMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int overTypeModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int readOnlyMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int lockedMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int fileFormatMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int fontNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int fontNameItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int fontNameBoldMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int fontNameBoldItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int subscriptSepMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int minFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int maxFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int wrapMarginMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int topLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int numDisplayLinesMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int displayWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int activePaneMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int nPanesMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int emptyArrayMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int serverNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int tabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int emTabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int useTabsMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int modifiedMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int languageModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int calltipIDMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int readSearchArgs(DataValue *argList,
int nArgs,
int*searchDirection,
int *searchType,
int *wrap,
char **errMsg);
static int wrongNArgsErr(
char **errMsg);
static int tooFewArgsErr(
char **errMsg);
static int readIntArg(DataValue dv,
int *result,
char **errMsg);
static int readStringArg(DataValue dv,
char **result,
char *stringStorage,
char **errMsg);
static int rangesetListMV(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg);
static int versionMV(WindowInfo* window, DataValue* argList,
int nArgs,
DataValue* result,
char** errMsg);
static int rangesetCreateMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetDestroyMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetGetByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetAddMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetSubtractMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetInvertMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetInfoMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int rangesetIncludesPosMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg);
static int rangesetSetColorMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg);
static int rangesetSetNameMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg);
static int rangesetSetModeMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg);
static int fillPatternResult(DataValue *result,
char **errMsg, WindowInfo *window,
char *patternName, Boolean preallocatedPatternName, Boolean includeName,
char *styleName,
int bufferPos);
static int getPatternByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int getPatternAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int fillStyleResult(DataValue *result,
char **errMsg,
WindowInfo *window,
char *styleName, Boolean preallocatedStyleName,
Boolean includeName,
int patCode,
int bufferPos);
static int getStyleByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int getStyleAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg);
static int filenameDialogMS(WindowInfo* window, DataValue* argList,
int nArgs,
DataValue* result,
char** errMsg);
static BuiltInSubr MacroSubrs[] = {lengthMS, getRangeMS, tPrintMS,
dialogMS, stringDialogMS, replaceRangeMS, replaceSelectionMS,
setCursorPosMS, getCharacterMS, minMS, maxMS, searchMS,
searchStringMS, substringMS, replaceSubstringMS, readFileMS,
writeFileMS, appendFileMS, beepMS, getSelectionMS, validNumberMS,
replaceInStringMS, selectMS, selectRectangleMS, focusWindowMS,
shellCmdMS, stringToClipboardMS, clipboardToStringMS, toupperMS,
tolowerMS, listDialogMS, getenvMS,
stringCompareMS, splitMS, calltipMS, killCalltipMS,
rangesetCreateMS, rangesetDestroyMS,
rangesetAddMS, rangesetSubtractMS, rangesetInvertMS,
rangesetInfoMS, rangesetRangeMS, rangesetIncludesPosMS,
rangesetSetColorMS, rangesetSetNameMS, rangesetSetModeMS,
rangesetGetByNameMS,
getPatternByNameMS, getPatternAtPosMS,
getStyleByNameMS, getStyleAtPosMS, filenameDialogMS
};
#define N_MACRO_SUBRS (
sizeof MacroSubrs/
sizeof *MacroSubrs)
static const char *MacroSubrNames[
N_MACRO_SUBRS] = {
"length",
"get_range",
"t_print",
"dialog",
"string_dialog",
"replace_range",
"replace_selection",
"set_cursor_pos",
"get_character",
"min",
"max",
"search",
"search_string",
"substring",
"replace_substring",
"read_file",
"write_file",
"append_file",
"beep",
"get_selection",
"valid_number",
"replace_in_string",
"select",
"select_rectangle",
"focus_window",
"shell_command",
"string_to_clipboard",
"clipboard_to_string",
"toupper",
"tolower",
"list_dialog",
"getenv",
"string_compare",
"split",
"calltip",
"kill_calltip",
"rangeset_create",
"rangeset_destroy",
"rangeset_add",
"rangeset_subtract",
"rangeset_invert",
"rangeset_info",
"rangeset_range",
"rangeset_includes",
"rangeset_set_color",
"rangeset_set_name",
"rangeset_set_mode",
"rangeset_get_by_name",
"get_pattern_by_name",
"get_pattern_at_pos",
"get_style_by_name",
"get_style_at_pos",
"filename_dialog"
};
static BuiltInSubr SpecialVars[] = {cursorMV, lineMV, columnMV,
fileNameMV, filePathMV, lengthMV, selectionStartMV, selectionEndMV,
selectionLeftMV, selectionRightMV, wrapMarginMV, tabDistMV,
emTabDistMV, useTabsMV, languageModeMV, modifiedMV,
statisticsLineMV, incSearchLineMV, showLineNumbersMV,
autoIndentMV, wrapTextMV, highlightSyntaxMV,
makeBackupCopyMV, incBackupMV, showMatchingMV, matchSyntaxBasedMV,
overTypeModeMV, readOnlyMV, lockedMV, fileFormatMV,
fontNameMV, fontNameItalicMV,
fontNameBoldMV, fontNameBoldItalicMV, subscriptSepMV,
minFontWidthMV, maxFontWidthMV, topLineMV, numDisplayLinesMV,
displayWidthMV, activePaneMV, nPanesMV, emptyArrayMV,
serverNameMV, calltipIDMV,
rangesetListMV, versionMV
};
#define N_SPECIAL_VARS (
sizeof SpecialVars/
sizeof *SpecialVars)
static const char *SpecialVarNames[
N_SPECIAL_VARS] = {
"$cursor",
"$line",
"$column",
"$file_name",
"$file_path",
"$text_length",
"$selection_start",
"$selection_end",
"$selection_left",
"$selection_right",
"$wrap_margin",
"$tab_dist",
"$em_tab_dist",
"$use_tabs",
"$language_mode",
"$modified",
"$statistics_line",
"$incremental_search_line",
"$show_line_numbers",
"$auto_indent",
"$wrap_text",
"$highlight_syntax",
"$make_backup_copy",
"$incremental_backup",
"$show_matching",
"$match_syntax_based",
"$overtype_mode",
"$read_only",
"$locked",
"$file_format",
"$font_name",
"$font_name_italic",
"$font_name_bold",
"$font_name_bold_italic",
"$sub_sep",
"$min_font_width",
"$max_font_width",
"$top_line",
"$n_display_lines",
"$display_width",
"$active_pane",
"$n_panes",
"$empty_array",
"$server_name",
"$calltip_ID",
"$rangeset_list",
"$VERSION"
};
#define N_RETURN_GLOBALS 5
enum retGlobalSyms {
STRING_DIALOG_BUTTON,
SEARCH_END,
READ_STATUS,
SHELL_CMD_STATUS,
LIST_DIALOG_BUTTON};
static const char *ReturnGlobalNames[
N_RETURN_GLOBALS] = {
"$string_dialog_button",
"$search_end",
"$read_status",
"$shell_cmd_status",
"$list_dialog_button"};
static Symbol *ReturnGlobals[
N_RETURN_GLOBALS];
static char* IgnoredActions[] = {
"focusIn",
"focusOut"};
static const char* MouseActions[] = {
"grab_focus",
"extend_adjust",
"extend_start",
"extend_end",
"secondary_or_drag_adjust",
"secondary_adjust",
"secondary_or_drag_start",
"secondary_start",
"move_destination",
"move_to",
"move_to_or_end_drag",
"copy_to",
"copy_to_or_end_drag",
"exchange",
"process_bdrag",
"mouse_pan"};
static const char* RedundantActions[] = {
"open_dialog",
"save_as_dialog",
"revert_to_saved_dialog",
"include_file_dialog",
"load_macro_file_dialog",
"load_tags_file_dialog",
"find_dialog",
"replace_dialog",
"goto_line_number_dialog",
"mark_dialog",
"goto_mark_dialog",
"control_code_dialog",
"filter_selection_dialog",
"execute_command_dialog",
"repeat_dialog",
"start_incremental_find"};
static char *LastCommand =
NULL;
static char *ReplayMacro =
NULL;
static textBuffer *MacroRecordBuf =
NULL;
static XtActionHookId MacroRecordActionHook =
0;
static WindowInfo *MacroRecordWindow =
NULL;
static char ReplaceChars[] =
"\\\"ntbrfav";
static char EscapeChars[] =
"\\\"\n\t\b\r\f\a\v";
void RegisterMacroSubroutines(
void)
{
static DataValue subrPtr = {
NO_TAG, {
0}}, noValue = {
NO_TAG, {
0}};
unsigned i;
for (i=
0; i<
N_MACRO_SUBRS; i++) {
subrPtr.val.subr = MacroSubrs[i];
InstallSymbol(MacroSubrNames[i],
C_FUNCTION_SYM, subrPtr);
}
for (i=
0; i<
N_SPECIAL_VARS; i++) {
subrPtr.val.subr = SpecialVars[i];
InstallSymbol(SpecialVarNames[i],
PROC_VALUE_SYM, subrPtr);
}
for (i=
0; i<
N_RETURN_GLOBALS; i++)
ReturnGlobals[i] = InstallSymbol(ReturnGlobalNames[i],
GLOBAL_SYM,
noValue);
}
#define MAX_LEARN_MSG_LEN ((
2 *
MAX_ACCEL_LEN) +
60)
void BeginLearn(WindowInfo *window)
{
WindowInfo *win;
XmString s;
XmString xmFinish;
XmString xmCancel;
char *cFinish;
char *cCancel;
char message[
MAX_LEARN_MSG_LEN];
if (MacroRecordActionHook !=
0)
return;
for (win=WindowList; win!=
NULL; win=win->next) {
if (!IsTopDocument(win))
continue;
XtSetSensitive(win->learnItem, False);
}
SetSensitive(window, window->finishLearnItem, True);
XtVaSetValues(window->cancelMacroItem, XmNlabelString,
s=XmStringCreateSimple(
"Cancel Learn"),
NULL);
XmStringFree(s);
SetSensitive(window, window->cancelMacroItem, True);
MacroRecordWindow = window;
MacroRecordBuf = BufCreate();
MacroRecordActionHook =
XtAppAddActionHook(XtWidgetToApplicationContext(window->shell),
learnActionHook, window);
XtVaGetValues(window->finishLearnItem, XmNacceleratorText, &xmFinish,
NULL);
XtVaGetValues(window->cancelMacroItem, XmNacceleratorText, &xmCancel,
NULL);
cFinish = GetXmStringText(xmFinish);
cCancel = GetXmStringText(xmCancel);
XmStringFree(xmFinish);
XmStringFree(xmCancel);
if (cFinish[
0] ==
'\0') {
if (cCancel[
0] ==
'\0') {
strncpy(message,
"Learn Mode -- Use menu to finish or cancel",
MAX_LEARN_MSG_LEN);
message[
MAX_LEARN_MSG_LEN -
1] =
'\0';
}
else {
sprintf(message,
"Learn Mode -- Use menu to finish, press %s to cancel",
cCancel);
}
}
else {
if (cCancel[
0] ==
'\0') {
sprintf(message,
"Learn Mode -- Press %s to finish, use menu to cancel",
cFinish);
}
else {
sprintf(message,
"Learn Mode -- Press %s to finish, %s to cancel",
cFinish,
cCancel);
}
}
NEditFree(cFinish);
NEditFree(cCancel);
SetModeMessage(window, message);
}
void AddLastCommandActionHook(XtAppContext context)
{
XtAppAddActionHook(context, lastActionHook,
NULL);
}
void FinishLearn(
void)
{
WindowInfo *win;
if (MacroRecordActionHook ==
0)
return;
XtRemoveActionHook(MacroRecordActionHook);
MacroRecordActionHook =
0;
NEditFree(ReplayMacro);
ReplayMacro = BufGetAll(MacroRecordBuf);
BufFree(MacroRecordBuf);
for (win=WindowList; win!=
NULL; win=win->next) {
if (!IsTopDocument(win))
continue;
XtSetSensitive(win->learnItem, True);
}
if (IsTopDocument(MacroRecordWindow)) {
XtSetSensitive(MacroRecordWindow->finishLearnItem, False);
XtSetSensitive(MacroRecordWindow->cancelMacroItem, False);
}
for (win=WindowList; win!=
NULL; win=win->next) {
if (!IsTopDocument(win))
continue;
XtSetSensitive(win->replayItem, True);
}
DimPasteReplayBtns(True);
ClearModeMessage(MacroRecordWindow);
}
void CancelMacroOrLearn(WindowInfo *window)
{
if (MacroRecordActionHook !=
0)
cancelLearn();
else if (window->macroCmdData !=
NULL)
AbortMacroCommand(window);
}
static void cancelLearn(
void)
{
WindowInfo *win;
if (MacroRecordActionHook ==
0)
return;
XtRemoveActionHook(MacroRecordActionHook);
MacroRecordActionHook =
0;
BufFree(MacroRecordBuf);
for (win=WindowList; win!=
NULL; win=win->next) {
if (!IsTopDocument(win))
continue;
XtSetSensitive(win->learnItem, True);
}
if (IsTopDocument(MacroRecordWindow)) {
XtSetSensitive(MacroRecordWindow->finishLearnItem, False);
XtSetSensitive(MacroRecordWindow->cancelMacroItem, False);
}
ClearModeMessage(MacroRecordWindow);
}
void Replay(WindowInfo *window)
{
Program *prog;
char *errMsg, *stoppedAt;
if (ReplayMacro !=
NULL &&
ReplayMacro[
0] !=
0 &&
window->macroCmdData ==
NULL) {
prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt);
if (prog ==
NULL) {
fprintf(stderr,
"XNEdit internal error, learn/replay macro syntax error: %s\n",
errMsg);
return;
}
runMacro(window, prog);
}
}
void ReadMacroInitFile(WindowInfo *window)
{
const char* autoloadName = GetRCFileName(
AUTOLOAD_NM);
static int initFileLoaded = False;
if (autoloadName !=
NULL && !initFileLoaded)
{
ReadMacroFile(window, autoloadName, False);
initFileLoaded = True;
}
}
int ReadMacroFile(WindowInfo *window,
const char *fileName,
int warnNotExist)
{
int result;
char *fileString;
fileString = ReadAnyTextFile(fileName, True);
if (fileString ==
NULL){
if (errno !=
ENOENT || warnNotExist)
{
DialogF(
DF_ERR, window->shell,
1,
"Read Macro",
"Error reading macro file %s: %s",
"OK", fileName,
strerror(errno));
}
return False;
}
result = readCheckMacroString(window->shell, fileString, window, fileName,
NULL);
NEditFree(fileString);
return result;
}
int ReadMacroString(WindowInfo *window,
char *string,
const char *errIn)
{
return readCheckMacroString(window->shell, string, window, errIn,
NULL);
}
int CheckMacroString(Widget dialogParent,
char *string,
const char *errIn,
char **errPos)
{
return readCheckMacroString(dialogParent, string,
NULL, errIn, errPos);
}
static int readCheckMacroString(Widget dialogParent,
char *string,
WindowInfo *runWindow,
const char *errIn,
char **errPos)
{
char *stoppedAt, *inPtr, *namePtr, *errMsg;
char subrName[
MAX_SYM_LEN];
Program *prog;
Symbol *sym;
DataValue subrPtr;
Stack* progStack = (Stack*) NEditMalloc(
sizeof(Stack));
progStack->top =
NULL;
progStack->size =
0;
inPtr = string;
while (*inPtr !=
'\0') {
while (*inPtr==
' ' || *inPtr==
'\t' || *inPtr==
'\n'|| *inPtr==
'#') {
if (*inPtr ==
'#')
while (*inPtr !=
'\n' && *inPtr !=
'\0') inPtr++;
else
inPtr++;
}
if (*inPtr ==
'\0')
break;
if (!strncmp(inPtr,
"define",
6) && (inPtr[
6]==
' ' || inPtr[
6]==
'\t')) {
inPtr +=
6;
inPtr += strspn(inPtr,
" \t\n");
namePtr = subrName;
while ((namePtr < &subrName[
MAX_SYM_LEN -
1])
&& (isalnum((
unsigned char)*inPtr) || *inPtr ==
'_')) {
*namePtr++ = *inPtr++;
}
*namePtr =
'\0';
if (isalnum((
unsigned char)*inPtr) || *inPtr ==
'_') {
return ParseError(dialogParent, string, inPtr, errIn,
"subroutine name too long");
}
inPtr += strspn(inPtr,
" \t\n");
if (*inPtr !=
'{') {
if (errPos !=
NULL) *errPos = stoppedAt;
return ParseError(dialogParent, string, inPtr,
errIn,
"expected ''{''");
}
prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
if (prog ==
NULL) {
if (errPos !=
NULL) *errPos = stoppedAt;
return ParseError(dialogParent, string, stoppedAt,
errIn, errMsg);
}
if (runWindow !=
NULL) {
sym = LookupSymbol(subrName);
if (sym ==
NULL) {
subrPtr.val.prog = prog;
subrPtr.tag =
NO_TAG;
sym = InstallSymbol(subrName,
MACRO_FUNCTION_SYM, subrPtr);
}
else {
if (sym->type ==
MACRO_FUNCTION_SYM)
FreeProgram(sym->value.val.prog);
else
sym->type =
MACRO_FUNCTION_SYM;
sym->value.val.prog = prog;
}
}
inPtr = stoppedAt;
}
else {
prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
if (prog ==
NULL) {
if (errPos !=
NULL) {
*errPos = stoppedAt;
}
return ParseError(dialogParent, string, stoppedAt,
errIn, errMsg);
}
if (runWindow !=
NULL) {
XEvent nextEvent;
if (runWindow->macroCmdData ==
NULL) {
runMacro(runWindow, prog);
while (runWindow->macroCmdData !=
NULL) {
XtAppNextEvent(XtWidgetToApplicationContext(
runWindow->shell), &nextEvent);
ServerDispatchEvent(&nextEvent);
}
}
else {
Push(progStack, (
void*) prog);
}
}
inPtr = stoppedAt;
}
}
while (
NULL != (prog = (Program*) Pop(progStack))) {
RunMacroAsSubrCall(prog);
}
NEditFree(progStack);
return True;
}
static void runMacro(WindowInfo *window, Program *prog)
{
DataValue result;
char *errMsg;
int stat;
macroCmdInfo *cmdData;
XmString s;
if (window->macroCmdData !=
NULL) {
RunMacroAsSubrCall(prog);
return;
}
BeginWait(window->shell);
XtVaSetValues(window->cancelMacroItem, XmNlabelString,
s=XmStringCreateSimple(
"Cancel Macro"),
NULL);
XmStringFree(s);
SetSensitive(window, window->cancelMacroItem, True);
cmdData = (macroCmdInfo *)NEditMalloc(
sizeof(macroCmdInfo));
window->macroCmdData = cmdData;
cmdData->bannerIsUp = False;
cmdData->closeOnCompletion = False;
cmdData->program = prog;
cmdData->context =
NULL;
cmdData->continueWorkProcID =
0;
cmdData->dialog =
NULL;
cmdData->bannerTimeoutID = XtAppAddTimeOut(
XtWidgetToApplicationContext(window->shell),
BANNER_WAIT_TIME,
bannerTimeoutProc, window);
stat = ExecuteMacro(window, prog,
0,
NULL, &result, &cmdData->context,
&errMsg);
if (stat ==
MACRO_ERROR)
{
finishMacroCmdExecution(window);
DialogF(
DF_ERR, window->shell,
1,
"Macro Error",
"Error executing macro: %s",
"OK", errMsg);
return;
}
if (stat ==
MACRO_DONE) {
finishMacroCmdExecution(window);
return;
}
if (stat ==
MACRO_TIME_LIMIT) {
ResumeMacroExecution(window);
return;
}
}
void ResumeMacroExecution(WindowInfo *window)
{
macroCmdInfo *cmdData = (macroCmdInfo *)window->macroCmdData;
if (cmdData !=
NULL)
cmdData->continueWorkProcID = XtAppAddWorkProc(
XtWidgetToApplicationContext(window->shell),
continueWorkProc, window);
}
void AbortMacroCommand(WindowInfo *window)
{
if (window->macroCmdData ==
NULL)
return;
if (window->macroBlocking)
return;
if (window->shellCmdData !=
NULL)
AbortShellCommand(window);
FreeRestartData(((macroCmdInfo *)window->macroCmdData)->context);
finishMacroCmdExecution(window);
}
int MacroWindowCloseActions(WindowInfo *window)
{
macroCmdInfo *mcd, *cmdData = window->macroCmdData;
WindowInfo *w;
if (MacroRecordActionHook !=
0 && MacroRecordWindow == window) {
FinishLearn();
}
if (cmdData ==
NULL) {
for (w=WindowList; w!=
NULL; w=w->next) {
mcd = (macroCmdInfo *)w->macroCmdData;
if (w == MacroRunWindow() && MacroFocusWindow() == window)
SetMacroFocusWindow(MacroRunWindow());
else if (mcd !=
NULL && mcd->context->focusWindow == window)
mcd->context->focusWindow = mcd->context->runWindow;
}
return True;
}
if (window == MacroRunWindow()) {
cmdData->closeOnCompletion = True;
return False;
}
FreeRestartData(cmdData->context);
finishMacroCmdExecution(window);
return True;
}
static void finishMacroCmdExecution(WindowInfo *window)
{
macroCmdInfo *cmdData = window->macroCmdData;
int closeOnCompletion = cmdData->closeOnCompletion;
XmString s;
XClientMessageEvent event;
if (cmdData->bannerTimeoutID !=
0)
XtRemoveTimeOut(cmdData->bannerTimeoutID);
if (cmdData->continueWorkProcID !=
0)
XtRemoveWorkProc(cmdData->continueWorkProcID);
EndWait(window->shell);
XtVaSetValues(window->cancelMacroItem, XmNlabelString,
s=XmStringCreateSimple(
"Cancel Learn"),
NULL);
XmStringFree(s);
SetSensitive(window, window->cancelMacroItem, False);
if (cmdData->bannerIsUp)
ClearModeMessage(window);
if (cmdData->dialog !=
NULL)
XtDestroyWidget(XtParent(cmdData->dialog));
FreeProgram(cmdData->program);
NEditFree(cmdData);
window->macroCmdData =
NULL;
if (closeOnCompletion && !window->filenameSet && !window->fileChanged) {
CloseWindow(window);
window =
NULL;
}
SafeGC();
if (!closeOnCompletion) {
event.format =
8;
event.type = ClientMessage;
XSendEvent(XtDisplay(window->shell), XtWindow(window->shell), False,
NoEventMask, (XEvent *)&event);
}
}
void SafeGC(
void)
{
WindowInfo *win;
for (win=WindowList; win!=
NULL; win=win->next)
if (win->macroCmdData !=
NULL || InSmartIndentMacros(win))
return;
GarbageCollectStrings();
}
void DoMacro(WindowInfo *window,
const char *macro,
const char *errInName)
{
Program *prog;
char *errMsg, *stoppedAt, *tMacro;
int macroLen;
macroLen = strlen(macro);
tMacro = (
char*)NEditMalloc(strlen(macro)+
2);
strncpy(tMacro, macro, macroLen);
tMacro[macroLen] =
'\n';
tMacro[macroLen+
1] =
'\0';
prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
if (prog ==
NULL) {
ParseError(window->shell, tMacro, stoppedAt, errInName, errMsg);
NEditFree(tMacro);
return;
}
NEditFree(tMacro);
runMacro(window, prog);
}
char *GetReplayMacro(
void)
{
return ReplayMacro;
}
void RepeatDialog(WindowInfo *window)
{
Widget form, selBox, radioBox, timesForm;
repeatDialog *rd;
Arg selBoxArgs[
1];
char *lastCmdLabel, *parenChar;
XmString s1;
int cmdNameLen;
if (LastCommand ==
NULL)
{
DialogF(
DF_WARN, window->shell,
1,
"Repeat Macro",
"No previous commands or learn/\nreplay sequences to repeat",
"OK");
return;
}
rd = (repeatDialog *)NEditMalloc(
sizeof(repeatDialog));
rd->lastCommand = NEditStrdup(LastCommand);
parenChar = strchr(LastCommand,
'(');
if (parenChar ==
NULL)
return;
cmdNameLen = parenChar-LastCommand;
lastCmdLabel = (
char*)NEditMalloc(
16 + cmdNameLen);
strcpy(lastCmdLabel,
"Last Command (");
strncpy(&lastCmdLabel[
14], LastCommand, cmdNameLen);
strcpy(&lastCmdLabel[
14 + cmdNameLen],
")");
XtSetArg(selBoxArgs[
0], XmNautoUnmanage, False);
selBox = CreatePromptDialog(window->shell,
"repeat", selBoxArgs,
1);
rd->shell = XtParent(selBox);
XtAddCallback(rd->shell, XmNdestroyCallback, repeatDestroyCB, rd);
XtAddCallback(selBox, XmNokCallback, repeatOKCB, rd);
XtAddCallback(selBox, XmNapplyCallback, repeatApplyCB, rd);
XtAddCallback(selBox, XmNcancelCallback, repeatCancelCB, rd);
XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_APPLY_BUTTON));
XtVaSetValues(XtParent(selBox), XmNtitle,
"Repeat Macro",
NULL);
AddMotifCloseCallback(XtParent(selBox), repeatCancelCB, rd);
form = XtVaCreateManagedWidget(
"form", xmFormWidgetClass, selBox,
NULL);
radioBox = XtVaCreateManagedWidget(
"cmdSrc", xmRowColumnWidgetClass, form,
XmNradioBehavior, True,
XmNorientation, XmHORIZONTAL,
XmNpacking, XmPACK_TIGHT,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
NULL);
rd->lastCmdToggle = XtVaCreateManagedWidget(
"lastCmdToggle",
xmToggleButtonWidgetClass, radioBox, XmNset, True,
XmNlabelString, s1=XmStringCreateSimple(lastCmdLabel),
XmNmnemonic,
'C',
NULL);
XmStringFree(s1);
NEditFree(lastCmdLabel);
XtVaCreateManagedWidget(
"learnReplayToggle",
xmToggleButtonWidgetClass, radioBox, XmNset, False,
XmNlabelString,
s1=XmStringCreateSimple(
"Learn/Replay"),
XmNmnemonic,
'L',
XmNsensitive, ReplayMacro !=
NULL,
NULL);
XmStringFree(s1);
timesForm = XtVaCreateManagedWidget(
"form", xmFormWidgetClass, form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, radioBox,
XmNtopOffset,
10,
XmNleftAttachment, XmATTACH_FORM,
NULL);
radioBox = XtVaCreateManagedWidget(
"method", xmRowColumnWidgetClass,
timesForm,
XmNradioBehavior, True,
XmNorientation, XmHORIZONTAL,
XmNpacking, XmPACK_TIGHT,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
NULL);
rd->inSelToggle = XtVaCreateManagedWidget(
"inSelToggle",
xmToggleButtonWidgetClass, radioBox, XmNset, False,
XmNlabelString, s1=XmStringCreateSimple(
"In Selection"),
XmNmnemonic,
'I',
NULL);
XmStringFree(s1);
rd->toEndToggle = XtVaCreateManagedWidget(
"toEndToggle",
xmToggleButtonWidgetClass, radioBox, XmNset, False,
XmNlabelString, s1=XmStringCreateSimple(
"To End"),
XmNmnemonic,
'T',
NULL);
XmStringFree(s1);
XtVaCreateManagedWidget(
"nTimesToggle",
xmToggleButtonWidgetClass, radioBox, XmNset, True,
XmNlabelString, s1=XmStringCreateSimple(
"N Times"),
XmNmnemonic,
'N',
XmNset, True,
NULL);
XmStringFree(s1);
rd->repeatText = XtVaCreateManagedWidget(
"repeatText", xmTextWidgetClass,
timesForm,
XmNcolumns,
5,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, radioBox,
NULL);
RemapDeleteKey(rd->repeatText);
AddDialogMnemonicHandler(form,
FALSE);
#if XmVersion >=
1002
XtVaSetValues(form, XmNinitialFocus, timesForm,
NULL);
XtVaSetValues(timesForm, XmNinitialFocus, rd->repeatText,
NULL);
#endif
rd->forWindow = window;
ManageDialogCenteredOnPointer(selBox);
}
static void repeatOKCB(Widget w, XtPointer clientData, XtPointer callData)
{
repeatDialog *rd = (repeatDialog *)clientData;
if (doRepeatDialogAction(rd, ((XmAnyCallbackStruct *)callData)->event))
XtDestroyWidget(rd->shell);
}
static void repeatApplyCB(Widget w, XtPointer clientData, XtPointer callData)
{
doRepeatDialogAction((repeatDialog *)clientData,
((XmAnyCallbackStruct *)callData)->event);
}
static int doRepeatDialogAction(repeatDialog *rd, XEvent *event)
{
int nTimes;
char nTimesStr[
TYPE_INT_STR_SIZE(
int)];
char *params[
2];
if (XmToggleButtonGetState(rd->inSelToggle))
{
if (!rd->forWindow->buffer->primary.selected)
{
DialogF(
DF_WARN, rd->shell,
1,
"Repeat Macro",
"No selection in window to repeat within",
"OK");
XmProcessTraversal(rd->inSelToggle, XmTRAVERSE_CURRENT);
return False;
}
params[
0] =
"in_selection";
}
else if (XmToggleButtonGetState(rd->toEndToggle))
{
params[
0] =
"to_end";
}
else
{
if (GetIntTextWarn(rd->repeatText, &nTimes,
"number of times", True)
!=
TEXT_READ_OK)
{
XmProcessTraversal(rd->repeatText, XmTRAVERSE_CURRENT);
return False;
}
sprintf(nTimesStr,
"%d", nTimes);
params[
0] = nTimesStr;
}
if (XmToggleButtonGetState(rd->lastCmdToggle))
params[
1] = NEditStrdup(rd->lastCommand);
else {
if (ReplayMacro ==
NULL)
return False;
params[
1] = NEditStrdup(ReplayMacro);
}
XtCallActionProc(rd->forWindow->lastFocus,
"repeat_macro", event, params,
2);
NEditFree(params[
1]);
return True;
}
static void repeatCancelCB(Widget w, XtPointer clientData, XtPointer callData)
{
repeatDialog *rd = (repeatDialog *)clientData;
XtDestroyWidget(rd->shell);
}
static void repeatDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
{
repeatDialog *rd = (repeatDialog *)clientData;
NEditFree(rd->lastCommand);
NEditFree(rd);
}
void RepeatMacro(WindowInfo *window,
const char *command,
int how)
{
Program *prog;
char *errMsg, *stoppedAt, *loopMacro, *loopedCmd;
if (command ==
NULL)
return;
if (how ==
REPEAT_TO_END)
loopMacro =
"lastCursor=-1\nstartPos=$cursor\n\
while($cursor>=startPos&&$cursor!=lastCursor){\nlastCursor=$cursor\n%s\n}\n";
else if (how ==
REPEAT_IN_SEL)
loopMacro =
"selStart = $selection_start\nif (selStart == -1)\nreturn\n\
selEnd = $selection_end\nset_cursor_pos(selStart)\nselect(0,0)\n\
boundText = get_range(selEnd, selEnd+10)\n\
while($cursor >= selStart && $cursor < selEnd && \\\n\
get_range(selEnd, selEnd+10) == boundText) {\n\
startLength = $text_length\n%s\n\
selEnd += $text_length - startLength\n}\n";
else
loopMacro =
"for(i=0;i<%d;i++){\n%s\n}\n";
loopedCmd = (
char*)NEditMalloc(strlen(command) + strlen(loopMacro) +
25);
if (how ==
REPEAT_TO_END || how ==
REPEAT_IN_SEL)
sprintf(loopedCmd, loopMacro, command);
else
sprintf(loopedCmd, loopMacro, how, command);
prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt);
if (prog ==
NULL) {
fprintf(stderr,
"XNEdit internal error, repeat macro syntax wrong: %s\n",
errMsg);
return;
}
NEditFree(loopedCmd);
runMacro(window, prog);
}
static void learnActionHook(Widget w, XtPointer clientData, String actionName,
XEvent *event, String *params, Cardinal *numParams)
{
WindowInfo *window;
int i;
char *actionString;
for (window=WindowList; window!=
NULL; window=window->next) {
if (window->textArea == w)
break;
for (i=
0; i<window->nPanes; i++) {
if (window->textPanes[i] == w)
break;
}
if (i < window->nPanes)
break;
}
if (window ==
NULL || window != (WindowInfo *)clientData)
return;
if (isMouseAction(actionName)) {
XBell(XtDisplay(w),
0);
return;
}
actionString = actionToString(w, actionName, event, params, *numParams);
if (actionString !=
NULL) {
BufInsert(MacroRecordBuf, MacroRecordBuf->length, actionString);
NEditFree(actionString);
}
}
static void lastActionHook(Widget w, XtPointer clientData, String actionName,
XEvent *event, String *params, Cardinal *numParams)
{
WindowInfo *window;
int i;
char *actionString;
for (window=WindowList; window!=
NULL; window=window->next) {
if (window->textArea == w)
break;
for (i=
0; i<window->nPanes; i++) {
if (window->textPanes[i] == w)
break;
}
if (i < window->nPanes)
break;
}
if (window ==
NULL)
return;
if (!strcmp(actionName,
"repeat_macro"))
return;
actionString = actionToString(w, actionName, event, params, *numParams);
if (actionString !=
NULL) {
NEditFree(LastCommand);
LastCommand = actionString;
}
}
static char *actionToString(Widget w,
char *actionName, XEvent *event,
String *params, Cardinal numParams)
{
char chars[
512], *charList[
1], *outStr, *outPtr;
KeySym keysym;
int i, nChars, nParams, length, nameLength;
#ifndef NO_XMIM
int status;
#endif
if (isIgnoredAction(actionName) || isRedundantAction(actionName) ||
isMouseAction(actionName))
return NULL;
if (!strcmp(actionName,
"self_insert") ||
!strcmp(actionName,
"self-insert")) {
actionName =
"insert_string";
nChars = TextLookupString(w, (XKeyEvent *)event, chars,
511, &keysym, &status);
if (nChars ==
0 || status == XLookupNone ||
status == XLookupKeySym || status == XBufferOverflow)
return NULL;
chars[nChars] =
'\0';
charList[
0] = chars;
params = charList;
nParams =
1;
}
else
nParams = numParams;
nameLength = strlen(actionName);
length = nameLength +
3;
for (i=
0; i<nParams; i++) {
length += escapedStringLength(params[i] ? params[i] :
"") +
4;
}
outPtr = outStr = (
char*)NEditMalloc(length +
1);
strcpy(outPtr, actionName);
outPtr += nameLength;
*outPtr++ =
'(';
for (i=
0; i<nParams; i++) {
*outPtr++ =
'\"';
outPtr += escapeStringChars(params[i] ? params[i] :
"", outPtr);
*outPtr++ =
'\"'; *outPtr++ =
','; *outPtr++ =
' ';
}
if (nParams !=
0)
outPtr -=
2;
*outPtr++ =
')'; *outPtr++ =
'\n'; *outPtr++ =
'\0';
return outStr;
}
static int isMouseAction(
const char *action)
{
int i;
for (i=
0; i<(
int)XtNumber(MouseActions); i++)
if (!strcmp(action, MouseActions[i]))
return True;
return False;
}
static int isRedundantAction(
const char *action)
{
int i;
for (i=
0; i<(
int)XtNumber(RedundantActions); i++)
if (!strcmp(action, RedundantActions[i]))
return True;
return False;
}
static int isIgnoredAction(
const char *action)
{
int i;
for (i=
0; i<(
int)XtNumber(IgnoredActions); i++)
if (!strcmp(action, IgnoredActions[i]))
return True;
return False;
}
#define MAX_TIMEOUT_MSG_LEN (
MAX_ACCEL_LEN +
60)
static void bannerTimeoutProc(XtPointer clientData, XtIntervalId *id)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
XmString xmCancel;
char *cCancel =
"\0";
char message[
MAX_TIMEOUT_MSG_LEN];
cmdData->bannerIsUp = True;
XtVaGetValues(window->cancelMacroItem, XmNacceleratorText, &xmCancel,
NULL);
if (!XmStringEmpty(xmCancel))
{
cCancel = GetXmStringText(xmCancel);
XmStringFree(xmCancel);
}
if (cCancel[
0] ==
'\0') {
strncpy(message,
"Macro Command in Progress",
MAX_TIMEOUT_MSG_LEN);
message[
MAX_TIMEOUT_MSG_LEN -
1] =
'\0';
}
else {
sprintf(message,
"Macro Command in Progress -- Press %s to Cancel",
cCancel);
}
NEditFree(cCancel);
SetModeMessage(window, message);
cmdData->bannerTimeoutID =
0;
}
static Boolean continueWorkProc(XtPointer clientData)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
char *errMsg;
int stat;
DataValue result;
stat = ContinueMacro(cmdData->context, &result, &errMsg);
if (stat ==
MACRO_ERROR)
{
finishMacroCmdExecution(window);
DialogF(
DF_ERR, window->shell,
1,
"Macro Error",
"Error executing macro: %s",
"OK", errMsg);
return True;
}
else if (stat ==
MACRO_DONE)
{
finishMacroCmdExecution(window);
return True;
}
else if (stat ==
MACRO_PREEMPT)
{
cmdData->continueWorkProcID =
0;
return True;
}
if (stat !=
MACRO_TIME_LIMIT)
return True;
return False;
}
static int escapeStringChars(
char *fromString,
char *toString)
{
char *e, *c, *outPtr = toString;
for (c=fromString; *c!=
'\0'; c++) {
for (e=EscapeChars; *e!=
'\0'; e++) {
if (*c == *e) {
*outPtr++ =
'\\';
*outPtr++ = ReplaceChars[e-EscapeChars];
break;
}
}
if (*e ==
'\0')
*outPtr++ = *c;
}
*outPtr =
'\0';
return outPtr - toString;
}
static int escapedStringLength(
char *string)
{
char *c, *e;
int length =
0;
for (c=string; *c!=
'\0'; c++) {
for (e=EscapeChars; *e!=
'\0'; e++) {
if (*c == *e) {
length++;
break;
}
}
length++;
}
return length;
}
static int lengthMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *string, stringStorage[
TYPE_INT_STR_SIZE(
int)];
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
return False;
result->tag =
INT_TAG;
result->val.n = strlen(string);
return True;
}
static int minMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int minVal, value, i;
if (nArgs ==
1)
return tooFewArgsErr(errMsg);
if (!readIntArg(argList[
0], &minVal, errMsg))
return False;
for (i=
0; i<nArgs; i++) {
if (!readIntArg(argList[i], &value, errMsg))
return False;
minVal = value < minVal ? value : minVal;
}
result->tag =
INT_TAG;
result->val.n = minVal;
return True;
}
static int maxMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int maxVal, value, i;
if (nArgs ==
1)
return tooFewArgsErr(errMsg);
if (!readIntArg(argList[
0], &maxVal, errMsg))
return False;
for (i=
0; i<nArgs; i++) {
if (!readIntArg(argList[i], &value, errMsg))
return False;
maxVal = value > maxVal ? value : maxVal;
}
result->tag =
INT_TAG;
result->val.n = maxVal;
return True;
}
static int focusWindowMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
WindowInfo *w;
char fullname[
2*
MAXPATHLEN];
char normalizedString[
MAXPATHLEN];
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage, errMsg)) {
return False;
}
else if (!strcmp(string,
"last")) {
w = WindowList;
}
else if (!strcmp(string,
"next")) {
w = window->next;
}
else if (strlen(string) >=
MAXPATHLEN) {
*errMsg =
"Pathname too long in focus_window()";
return False;
}
else {
for (w=WindowList; w !=
NULL; w = w->next) {
snprintf(fullname,
sizeof(fullname),
"%s%s", w->path, w->filename);
if (!strcmp(string, fullname)) {
break;
}
}
if (w ==
NULL) {
strncpy(normalizedString, string,
MAXPATHLEN);
normalizedString[
MAXPATHLEN-
1] =
'\0';
if (
1 == NormalizePathname(normalizedString)) {
*errMsg =
"Pathname too long in focus_window()";
return False;
}
for (w=WindowList; w !=
NULL; w = w->next) {
snprintf(fullname,
sizeof(fullname),
"%s%s", w->path, w->filename);
if (!strcmp(normalizedString, fullname))
break;
}
}
}
if (w ==
NULL) {
result->tag =
STRING_TAG;
result->val.str.rep =
PERM_ALLOC_STR(
"");
result->val.str.len =
0;
return True;
}
SetMacroFocusWindow(w);
if (w->highlightSyntax && w->highlightData==
NULL)
StartHighlighting(w, False);
result->tag =
STRING_TAG;
size_t result_str_len = strlen(w->path)+strlen(w->filename)+
1;
AllocNString(&result->val.str, result_str_len);
snprintf(result->val.str.rep, result_str_len,
"%s%s", w->path, w->filename);
return True;
}
static int getRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int from, to;
textBuffer *buf = window->buffer;
char *rangeText;
if (nArgs !=
2)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &from, errMsg))
return False;
if (!readIntArg(argList[
1], &to, errMsg))
return False;
if (from <
0) from =
0;
if (from > buf->length) from = buf->length;
if (to <
0) to =
0;
if (to > buf->length) to = buf->length;
if (from > to) {
int temp = from; from = to; to = temp;}
result->tag =
STRING_TAG;
AllocNString(&result->val.str, to - from +
1);
rangeText = BufGetRange(buf, from, to);
BufUnsubstituteNullChars(rangeText, buf);
strcpy(result->val.str.rep, rangeText);
NEditFree(rangeText);
return True;
}
static int getCharacterMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int pos;
textBuffer *buf = window->buffer;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &pos, errMsg))
return False;
if (pos <
0) pos =
0;
if (pos > buf->length) pos = buf->length;
result->tag =
STRING_TAG;
AllocNString(&result->val.str,
2);
result->val.str.rep[
0] = BufGetCharacter(buf, pos);
BufUnsubstituteNullChars(result->val.str.rep, buf);
return True;
}
static int replaceRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int from, to;
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
textBuffer *buf = window->buffer;
if (nArgs !=
3)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &from, errMsg))
return False;
if (!readIntArg(argList[
1], &to, errMsg))
return False;
if (!readStringArg(argList[
2], &string, stringStorage, errMsg))
return False;
if (from <
0) from =
0;
if (from > buf->length) from = buf->length;
if (to <
0) to =
0;
if (to > buf->length) to = buf->length;
if (from > to) {
int temp = from; from = to; to = temp;}
if (
IS_ANY_LOCKED(window->lockReasons)) {
XBell(XtDisplay(window->shell),
0);
result->tag =
NO_TAG;
return True;
}
if (!BufSubstituteNullChars(string, strlen(string), window->buffer)) {
*errMsg =
"Too much binary data in file";
return False;
}
BufReplace(buf, from, to, string);
result->tag =
NO_TAG;
return True;
}
static int replaceSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
return False;
if (
IS_ANY_LOCKED(window->lockReasons)) {
XBell(XtDisplay(window->shell),
0);
result->tag =
NO_TAG;
return True;
}
if (!BufSubstituteNullChars(string, strlen(string), window->buffer)) {
*errMsg =
"Too much binary data in file";
return False;
}
BufReplaceSelected(window->buffer, string);
result->tag =
NO_TAG;
return True;
}
static int getSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *selText;
if (nArgs !=
0 && nArgs !=
1)
return wrongNArgsErr(errMsg);
if (nArgs ==
1) {
if (argList[
0].tag !=
STRING_TAG || strcmp(argList[
0].val.str.rep,
"any")) {
*errMsg =
"Unrecognized argument to %s";
return False;
}
selText = GetAnySelection(window);
if (selText ==
NULL)
selText = NEditStrdup(
"");
}
else {
selText = BufGetSelectionText(window->buffer);
BufUnsubstituteNullChars(selText, window->buffer);
}
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, selText);
NEditFree(selText);
return True;
}
static int validNumberMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *string, stringStorage[
TYPE_INT_STR_SIZE(
int)];
if (nArgs !=
1) {
return wrongNArgsErr(errMsg);
}
if (!readStringArg(argList[
0], &string, stringStorage, errMsg)) {
return False;
}
result->tag =
INT_TAG;
result->val.n = StringToNum(string,
NULL);
return True;
}
static int replaceSubstringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int from, to, length, replaceLen, outLen;
char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *string, *replStr;
if (nArgs !=
4)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage[
1], errMsg))
return False;
if (!readIntArg(argList[
1], &from, errMsg))
return False;
if (!readIntArg(argList[
2], &to, errMsg))
return False;
if (!readStringArg(argList[
3], &replStr, stringStorage[
1], errMsg))
return False;
length = strlen(string);
if (from <
0) from =
0;
if (from > length) from = length;
if (to <
0) to =
0;
if (to > length) to = length;
if (from > to) {
int temp = from; from = to; to = temp;}
replaceLen = strlen(replStr);
outLen = length - (to - from) + replaceLen;
result->tag =
STRING_TAG;
AllocNString(&result->val.str, outLen+
1);
strncpy(result->val.str.rep, string, from);
strncpy(&result->val.str.rep[from], replStr, replaceLen);
strncpy(&result->val.str.rep[from + replaceLen], &string[to], length - to);
return True;
}
static int substringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int from, to, length;
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
if (nArgs !=
2 && nArgs !=
3)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
return False;
if (!readIntArg(argList[
1], &from, errMsg))
return False;
length = to = strlen(string);
if (nArgs ==
3)
if (!readIntArg(argList[
2], &to, errMsg))
return False;
if (from <
0) from += length;
if (from <
0) from =
0;
if (from > length) from = length;
if (to <
0) to += length;
if (to <
0) to =
0;
if (to > length) to = length;
if (from > to) to = from;
result->tag =
STRING_TAG;
AllocNStringNCpy(&result->val.str, &string[from], to - from);
return True;
}
static int toupperMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int length;
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
return False;
length = strlen(string);
result->tag =
STRING_TAG;
AllocNString(&result->val.str, length +
1);
UpCaseString(result->val.str.rep, string);
return True;
}
static int tolowerMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int length;
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
return False;
length = strlen(string);
result->tag =
STRING_TAG;
AllocNString(&result->val.str, length +
1);
DownCaseString(result->val.str.rep, string);
return True;
}
static int stringToClipboardMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
long itemID =
0;
XmString s;
int stat;
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
return False;
result->tag =
NO_TAG;
stat = SpinClipboardStartCopy(TheDisplay, XtWindow(window->textArea),
s=XmStringCreateSimple(
"NEdit"), XtLastTimestampProcessed(TheDisplay),
window->textArea,
NULL, &itemID);
XmStringFree(s);
if (stat != ClipboardSuccess)
return True;
char *format =
"UTF8_STRING";
for(
int i=
0;i<
2;i++) {
(
void)SpinClipboardCopy(TheDisplay, XtWindow(window->textArea), itemID, format,
string, strlen(string),
0,
NULL);
format =
"STRING";
}
SpinClipboardEndCopy(TheDisplay, XtWindow(window->textArea), itemID);
return True;
}
static int clipboardToStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
unsigned long length, retLength;
long id =
0;
if (nArgs !=
0)
return wrongNArgsErr(errMsg);
char *format_name =
"UTF8_STRING";
int res = ClipboardNoData;
for(
int i=
0;i<
2;i++) {
res = SpinClipboardInquireLength(
TheDisplay,
XtWindow(window->shell),
format_name,
&length);
if(res == ClipboardSuccess) {
break;
}
format_name =
"STRING";
}
if (res != ClipboardSuccess) {
result->tag =
STRING_TAG;
result->val.str.rep =
PERM_ALLOC_STR(
"");
result->val.str.len =
0;
SpinClipboardUnlock(TheDisplay, XtWindow(window->shell));
return True;
}
result->tag =
STRING_TAG;
AllocNString(&result->val.str, (
int)length +
1);
if (SpinClipboardRetrieve(TheDisplay, XtWindow(window->shell), format_name,
result->val.str.rep, length, &retLength, &id) != ClipboardSuccess) {
retLength =
0;
SpinClipboardUnlock(TheDisplay, XtWindow(window->shell));
}
result->val.str.rep[retLength] =
'\0';
result->val.str.len = retLength;
return True;
}
static int readFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *name;
struct stat statbuf;
FILE *fp;
int readLen;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &name, stringStorage, errMsg))
return False;
if ((fp = fopen(name,
"r")) ==
NULL)
goto errorNoClose;
if (fstat(fileno(fp), &statbuf) !=
0)
goto error;
result->tag =
STRING_TAG;
AllocNString(&result->val.str, statbuf.st_size+
1);
readLen = fread(result->val.str.rep,
sizeof(
char), statbuf.st_size+
1, fp);
if (ferror(fp))
goto error;
if(!feof(fp)){
int chunkSize =
1024;
char *buffer;
buffer = (
char*)NEditMalloc(readLen *
sizeof(
char));
memcpy(buffer, result->val.str.rep, readLen *
sizeof(
char));
while (!feof(fp)){
buffer = NEditRealloc(buffer, (readLen+chunkSize)*
sizeof(
char));
readLen += fread(&buffer[readLen],
sizeof(
char), chunkSize, fp);
if (ferror(fp)){
NEditFree(buffer);
goto error;
}
}
AllocNString(&result->val.str, readLen +
1);
memcpy(result->val.str.rep, buffer, readLen *
sizeof(
char));
NEditFree(buffer);
}
fclose(fp);
ReturnGlobals[
READ_STATUS]->value.tag =
INT_TAG;
ReturnGlobals[
READ_STATUS]->value.val.n = True;
return True;
error:
fclose(fp);
errorNoClose:
ReturnGlobals[
READ_STATUS]->value.tag =
INT_TAG;
ReturnGlobals[
READ_STATUS]->value.val.n = False;
result->tag =
STRING_TAG;
result->val.str.rep =
PERM_ALLOC_STR(
"");
result->val.str.len =
0;
return True;
}
static int writeFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
return writeOrAppendFile(False, window, argList, nArgs, result, errMsg);
}
static int appendFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
return writeOrAppendFile(True, window, argList, nArgs, result, errMsg);
}
static int writeOrAppendFile(
int append, WindowInfo *window,
DataValue *argList,
int nArgs, DataValue *result,
char **errMsg)
{
char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *name, *string;
FILE *fp;
if (nArgs !=
2)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage[
1], errMsg))
return False;
if (!readStringArg(argList[
1], &name, stringStorage[
0], errMsg))
return False;
if ((fp = fopen(name, append ?
"a" :
"w")) ==
NULL) {
result->tag =
INT_TAG;
result->val.n = False;
return True;
}
fwrite(string,
sizeof(
char), strlen(string), fp);
if (ferror(fp)) {
fclose(fp);
result->tag =
INT_TAG;
result->val.n = False;
return True;
}
fclose(fp);
result->tag =
INT_TAG;
result->val.n = True;
return True;
}
static int searchMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
DataValue newArgList[
9];
if (nArgs >
8)
return wrongNArgsErr(errMsg);
newArgList[
0].tag =
STRING_TAG;
newArgList[
0].val.str.rep = (
char *)BufAsString(window->buffer);
newArgList[
0].val.str.len = window->buffer->length;
memcpy(&newArgList[
1], argList, nArgs *
sizeof(DataValue));
return searchStringMS(window, newArgList, nArgs+
1, result, errMsg);
}
static int searchStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int beginPos, wrap, direction, found = False, foundStart, foundEnd, type;
int skipSearch = False, len;
char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *string, *searchStr;
if (nArgs <
3)
return tooFewArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage[
0], errMsg))
return False;
if (!readStringArg(argList[
1], &searchStr, stringStorage[
1], errMsg))
return False;
if (!readIntArg(argList[
2], &beginPos, errMsg))
return False;
if (!readSearchArgs(&argList[
3], nArgs-
3, &direction, &type, &wrap, errMsg))
return False;
len = argList[
0].val.str.len;
if (beginPos > len) {
if (direction ==
SEARCH_FORWARD) {
if (wrap) {
beginPos =
0;
}
else {
found = False;
skipSearch = True;
}
}
else {
beginPos = len;
}
}
else if (beginPos <
0) {
if (direction ==
SEARCH_BACKWARD) {
if (wrap) {
beginPos = len;
}
else {
found = False;
skipSearch = True;
}
}
else {
beginPos =
0;
}
}
if (!skipSearch)
found = SearchString(string, searchStr, direction, type, wrap, beginPos,
&foundStart, &foundEnd,
NULL,
NULL, GetWindowDelimiters(window));
ReturnGlobals[
SEARCH_END]->value.tag =
INT_TAG;
ReturnGlobals[
SEARCH_END]->value.val.n = found ? foundEnd :
0;
result->tag =
INT_TAG;
result->val.n = found ? foundStart : -
1;
return True;
}
static int replaceInStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
3][
TYPE_INT_STR_SIZE(
int)], *string, *searchStr, *replaceStr;
char *argStr, *replacedStr;
int searchType =
SEARCH_LITERAL, copyStart, copyEnd;
int replacedLen, replaceEnd, force=False, i;
if (nArgs <
3 || nArgs >
5)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &string, stringStorage[
0], errMsg))
return False;
if (!readStringArg(argList[
1], &searchStr, stringStorage[
1], errMsg))
return False;
if (!readStringArg(argList[
2], &replaceStr, stringStorage[
2], errMsg))
return False;
for (i =
3; i < nArgs; i++) {
if (!readStringArg(argList[i], &argStr, stringStorage[
2], errMsg))
return False;
if (!StringToSearchType(argStr, &searchType)) {
if (!strcmp(argStr,
"copy")) {
force = True;
}
else {
*errMsg =
"unrecognized argument to %s";
return False;
}
}
}
replacedStr = ReplaceAllInString(string, searchStr, replaceStr, searchType,
©Start, ©End, &replacedLen, GetWindowDelimiters(window));
result->tag =
STRING_TAG;
if (replacedStr ==
NULL) {
if (force) {
if (argList[
0].tag ==
STRING_TAG) {
result->val.str.rep = argList[
0].val.str.rep;
result->val.str.len = argList[
0].val.str.len;
}
else {
AllocNStringCpy(&result->val.str, string);
}
}
else {
result->val.str.rep =
PERM_ALLOC_STR(
"");
result->val.str.len =
0;
}
}
else {
size_t remainder = strlen(&string[copyEnd]);
replaceEnd = copyStart + replacedLen;
AllocNString(&result->val.str, replaceEnd + remainder +
1);
strncpy(result->val.str.rep, string, copyStart);
strcpy(&result->val.str.rep[copyStart], replacedStr);
strcpy(&result->val.str.rep[replaceEnd], &string[copyEnd]);
NEditFree(replacedStr);
}
return True;
}
static int readSearchArgs(DataValue *argList,
int nArgs,
int *searchDirection,
int *searchType,
int *wrap,
char **errMsg)
{
int i;
char *argStr, stringStorage[
TYPE_INT_STR_SIZE(
int)];
*wrap = False;
*searchDirection =
SEARCH_FORWARD;
*searchType =
SEARCH_LITERAL;
for (i=
0; i<nArgs; i++) {
if (!readStringArg(argList[i], &argStr, stringStorage, errMsg))
return False;
else if (!strcmp(argStr,
"wrap"))
*wrap = True;
else if (!strcmp(argStr,
"nowrap"))
*wrap = False;
else if (!strcmp(argStr,
"backward"))
*searchDirection =
SEARCH_BACKWARD;
else if (!strcmp(argStr,
"forward"))
*searchDirection =
SEARCH_FORWARD;
else if (!StringToSearchType(argStr, searchType)) {
*errMsg =
"Unrecognized argument to %s";
return False;
}
}
return True;
}
static int setCursorPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int pos;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &pos, errMsg))
return False;
TextSetCursorPos(window->lastFocus, pos);
result->tag =
NO_TAG;
return True;
}
static int selectMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int start, end, startTmp;
if (nArgs !=
2)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &start, errMsg))
return False;
if (!readIntArg(argList[
1], &end, errMsg))
return False;
if (start > end) {
startTmp = start;
start = end;
end = startTmp;
}
if (start <
0) start =
0;
if (start > window->buffer->length) start = window->buffer->length;
if (end <
0) end =
0;
if (end > window->buffer->length) end = window->buffer->length;
BufSelect(window->buffer, start, end);
result->tag =
NO_TAG;
return True;
}
static int selectRectangleMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int start, end, left, right;
if (nArgs !=
4)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &start, errMsg))
return False;
if (!readIntArg(argList[
1], &end, errMsg))
return False;
if (!readIntArg(argList[
2], &left, errMsg))
return False;
if (!readIntArg(argList[
3], &right, errMsg))
return False;
BufRectSelect(window->buffer, start, end, left, right);
result->tag =
NO_TAG;
return True;
}
static int beepMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
if (nArgs !=
0)
return wrongNArgsErr(errMsg);
XBell(XtDisplay(window->shell),
0);
result->tag =
NO_TAG;
return True;
}
static int tPrintMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
int i;
if (nArgs ==
0)
return tooFewArgsErr(errMsg);
for (i=
0; i<nArgs; i++) {
if (!readStringArg(argList[i], &string, stringStorage, errMsg))
return False;
printf(
"%s%s", string, i==nArgs-
1 ?
"" :
" ");
}
fflush( stdout );
result->tag =
NO_TAG;
return True;
}
static int getenvMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
char *name;
char *value;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &name, stringStorage[
0], errMsg)) {
*errMsg =
"argument to %s must be a string";
return False;
}
value = getenv(name);
if (value ==
NULL)
value =
"";
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, value);
return True;
}
static int shellCmdMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *cmdString, *inputString;
if (nArgs !=
2)
return wrongNArgsErr(errMsg);
if (!readStringArg(argList[
0], &cmdString, stringStorage[
0], errMsg))
return False;
if (!readStringArg(argList[
1], &inputString, stringStorage[
1], errMsg))
return False;
if (MacroRunWindow()->macroCmdData ==
NULL) {
*errMsg =
"%s can''t be called from non-suspendable context";
return False;
}
ShellCmdToMacroString(window, cmdString, inputString);
result->tag =
INT_TAG;
result->val.n =
0;
return True;
}
void ReturnShellCommandOutput(WindowInfo *window,
const char *outText,
int status)
{
DataValue retVal;
macroCmdInfo *cmdData = window->macroCmdData;
if (cmdData ==
NULL)
return;
retVal.tag =
STRING_TAG;
AllocNStringCpy(&retVal.val.str, outText);
ModifyReturnedValue(cmdData->context, retVal);
ReturnGlobals[
SHELL_CMD_STATUS]->value.tag =
INT_TAG;
ReturnGlobals[
SHELL_CMD_STATUS]->value.val.n = status;
}
static int dialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
macroCmdInfo *cmdData;
char stringStorage[
TYPE_INT_STR_SIZE(
int)];
char btnStorage[
TYPE_INT_STR_SIZE(
int)];
char *btnLabel;
char *message;
Arg al[
20];
int ac;
Widget dialog, btn;
int i, nBtns;
XmString s1, s2;
window = MacroRunWindow();
cmdData = window->macroCmdData;
if (!cmdData) {
*errMsg =
"%s can''t be called from non-suspendable context";
return False;
}
if (nArgs ==
0) {
*errMsg =
"%s subroutine called with no arguments";
return False;
}
if (!readStringArg(argList[
0], &message, stringStorage, errMsg)) {
return False;
}
for (i=
1; i<nArgs; i++) {
if (!readStringArg(argList[i], &btnLabel, btnStorage, errMsg)) {
return False;
}
}
if (nArgs ==
1) {
btnLabel =
"OK";
nBtns =
1;
}
else {
nBtns = nArgs -
1;
argList++;
readStringArg(argList[
0], &btnLabel, btnStorage, errMsg);
}
ac =
0;
XtSetArg(al[ac], XmNtitle,
" "); ac++;
XtSetArg(al[ac], XmNmessageString, s1=
MKSTRING(message)); ac++;
XtSetArg(al[ac], XmNokLabelString, s2=XmStringCreateSimple(btnLabel)); ac++;
dialog = CreateMessageDialog(window->shell,
"macroDialog", al, ac);
if (
1 == nArgs)
{
XtVaSetValues(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
NULL);
}
XmStringFree(s1);
XmStringFree(s2);
AddMotifCloseCallback(XtParent(dialog), dialogCloseCB, window);
XtAddCallback(dialog, XmNokCallback, dialogBtnCB, window);
XtVaSetValues(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
XmNuserData, (XtPointer)
1,
NULL);
cmdData->dialog = dialog;
XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
XtAddCallback(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON),
XmNactivateCallback, dialogCloseCB, window);
for (i=
1; i<nBtns; i++) {
readStringArg(argList[i], &btnLabel, btnStorage, errMsg);
btn = XtVaCreateManagedWidget(
"mdBtn", xmPushButtonWidgetClass, dialog,
XmNlabelString, s1=XmStringCreateSimple(btnLabel),
XmNuserData, (XtPointer)(
intptr_t)(i+
1),
NULL);
XtAddCallback(btn, XmNactivateCallback, dialogBtnCB, window);
XmStringFree(s1);
}
#ifdef LESSTIF_VERSION
XtAddEventHandler(dialog, KeyPressMask, False, dialogEscCB,
(XtPointer)window);
XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
True, GrabModeAsync, GrabModeAsync);
#endif
ManageDialogCenteredOnPointer(dialog);
PreemptMacro();
result->tag =
INT_TAG;
result->val.n =
0;
return True;
}
static void dialogBtnCB(Widget w, XtPointer clientData, XtPointer callData)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
XtPointer userData;
DataValue retVal;
if (cmdData ==
NULL)
return;
if (XtClass(w) == xmPushButtonWidgetClass) {
XtVaGetValues(w, XmNuserData, &userData,
NULL);
retVal.val.n = (
int)(
intptr_t)userData;
}
else
retVal.val.n =
1;
retVal.tag =
INT_TAG;
ModifyReturnedValue(cmdData->context, retVal);
XtDestroyWidget(XtParent(cmdData->dialog));
cmdData->dialog =
NULL;
ResumeMacroExecution(window);
}
static void dialogCloseCB(Widget w, XtPointer clientData, XtPointer callData)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
DataValue retVal;
retVal.val.n =
0;
retVal.tag =
INT_TAG;
ModifyReturnedValue(cmdData->context, retVal);
XtDestroyWidget(XtParent(cmdData->dialog));
cmdData->dialog =
NULL;
ResumeMacroExecution(window);
}
#ifdef LESSTIF_VERSION
static void dialogEscCB(Widget w, XtPointer clientData, XEvent *event,
Boolean *cont)
{
if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
return;
if (clientData !=
NULL) {
dialogCloseCB(w, (WindowInfo *)clientData,
NULL);
}
*cont = False;
}
#endif
static int stringDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
macroCmdInfo *cmdData;
char stringStorage[
TYPE_INT_STR_SIZE(
int)];
char btnStorage[
TYPE_INT_STR_SIZE(
int)];
char *btnLabel;
char *message;
Widget dialog, btn;
int i, nBtns;
XmString s1, s2;
Arg al[
20];
int ac;
window = MacroRunWindow();
cmdData = window->macroCmdData;
if (!cmdData) {
*errMsg =
"%s can''t be called from non-suspendable context";
return False;
}
if (nArgs ==
0) {
*errMsg =
"%s subroutine called with no arguments";
return False;
}
if (!readStringArg(argList[
0], &message, stringStorage, errMsg)) {
return False;
}
for (i=
1; i<nArgs; i++) {
if (!readStringArg(argList[i], &btnLabel, stringStorage, errMsg)) {
return False;
}
}
if (nArgs ==
1) {
btnLabel =
"OK";
nBtns =
1;
}
else {
nBtns = nArgs -
1;
argList++;
readStringArg(argList[
0], &btnLabel, btnStorage, errMsg);
}
ac =
0;
XtSetArg(al[ac], XmNtitle,
" "); ac++;
XtSetArg(al[ac], XmNselectionLabelString, s1=
MKSTRING(message)); ac++;
XtSetArg(al[ac], XmNokLabelString, s2=XmStringCreateSimple(btnLabel)); ac++;
dialog = CreatePromptDialog(window->shell,
"macroStringDialog", al, ac);
if (
1 == nArgs)
{
XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
NULL);
}
XmStringFree(s1);
XmStringFree(s2);
AddMotifCloseCallback(XtParent(dialog), stringDialogCloseCB, window);
XtAddCallback(dialog, XmNokCallback, stringDialogBtnCB, window);
XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
XmNuserData, (XtPointer)
1,
NULL);
cmdData->dialog = dialog;
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
XtAddCallback(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON),
XmNactivateCallback, stringDialogCloseCB, window);
XtVaCreateWidget(
"x", xmSeparatorWidgetClass, dialog,
NULL);
for (i=
1; i<nBtns; i++) {
readStringArg(argList[i], &btnLabel, btnStorage, errMsg);
btn = XtVaCreateManagedWidget(
"mdBtn", xmPushButtonWidgetClass, dialog,
XmNlabelString, s1=XmStringCreateSimple(btnLabel),
XmNuserData, (XtPointer)(
intptr_t)(i+
1),
NULL);
XtAddCallback(btn, XmNactivateCallback, stringDialogBtnCB, window);
XmStringFree(s1);
}
#ifdef LESSTIF_VERSION
XtAddEventHandler(dialog, KeyPressMask, False, stringDialogEscCB,
(XtPointer)window);
XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
True, GrabModeAsync, GrabModeAsync);
#endif
ManageDialogCenteredOnPointer(dialog);
PreemptMacro();
result->tag =
INT_TAG;
result->val.n =
0;
return True;
}
static void stringDialogBtnCB(Widget w, XtPointer clientData,
XtPointer callData)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
XtPointer userData;
DataValue retVal;
char *text;
int btnNum;
if (cmdData ==
NULL)
return;
text = XmTextGetString(XmSelectionBoxGetChild(cmdData->dialog,
XmDIALOG_TEXT));
retVal.tag =
STRING_TAG;
AllocNStringCpy(&retVal.val.str, text);
NEditFree(text);
ModifyReturnedValue(cmdData->context, retVal);
if (XtClass(w) == xmPushButtonWidgetClass) {
XtVaGetValues(w, XmNuserData, &userData,
NULL);
btnNum = (
int)(
intptr_t)userData;
}
else
btnNum =
1;
ReturnGlobals[
STRING_DIALOG_BUTTON]->value.tag =
INT_TAG;
ReturnGlobals[
STRING_DIALOG_BUTTON]->value.val.n = btnNum;
XtDestroyWidget(XtParent(cmdData->dialog));
cmdData->dialog =
NULL;
ResumeMacroExecution(window);
}
static void stringDialogCloseCB(Widget w, XtPointer clientData,
XtPointer callData)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
DataValue retVal;
if (cmdData ==
NULL)
return;
retVal.tag =
STRING_TAG;
retVal.val.str.rep =
PERM_ALLOC_STR(
"");
retVal.val.str.len =
0;
ModifyReturnedValue(cmdData->context, retVal);
ReturnGlobals[
STRING_DIALOG_BUTTON]->value.tag =
INT_TAG;
ReturnGlobals[
STRING_DIALOG_BUTTON]->value.val.n =
0;
XtDestroyWidget(XtParent(cmdData->dialog));
cmdData->dialog =
NULL;
ResumeMacroExecution(window);
}
#ifdef LESSTIF_VERSION
static void stringDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
Boolean *cont)
{
if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
return;
if (clientData !=
NULL) {
stringDialogCloseCB(w, (WindowInfo *)clientData,
NULL);
}
*cont = False;
}
#endif
static int calltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
TYPE_INT_STR_SIZE(
int)], *tipText, *txtArg;
Boolean anchored = False, lookup = True;
int mode = -
1, i;
int anchorPos, hAlign =
TIP_LEFT, vAlign =
TIP_BELOW,
alignMode =
TIP_SLOPPY;
if (nArgs <
1) {
*errMsg =
"%s subroutine called with too few arguments";
return False;
}
if (nArgs >
6) {
*errMsg =
"%s subroutine called with too many arguments";
return False;
}
if (!readStringArg(argList[
0], &tipText, stringStorage, errMsg))
return False;
if (nArgs >
1) {
if (!readIntArg(argList[
1], &anchorPos, errMsg))
return False;
}
else {
anchorPos = -
1;
}
if (anchorPos >=
0) anchored = True;
for (i =
2; i < nArgs; ++i) {
if (!readStringArg(argList[i], &txtArg, stringStorage, errMsg)){
return False;
}
switch( txtArg[
0] ) {
case 'c':
if (strcmp(txtArg,
"center"))
goto bad_arg;
hAlign =
TIP_CENTER;
break;
case 'r':
if (strcmp(txtArg,
"right"))
goto bad_arg;
hAlign =
TIP_RIGHT;
break;
case 'a':
if (strcmp(txtArg,
"above"))
goto bad_arg;
vAlign =
TIP_ABOVE;
break;
case 's':
if (strcmp(txtArg,
"strict"))
goto bad_arg;
alignMode =
TIP_STRICT;
break;
case 't':
if (!strcmp(txtArg,
"tipText"))
mode = -
1;
else if (!strcmp(txtArg,
"tipKey"))
mode =
TIP;
else if (!strcmp(txtArg,
"tagKey"))
mode =
TIP_FROM_TAG;
else
goto bad_arg;
break;
default:
goto bad_arg;
}
}
result->tag =
INT_TAG;
if (mode <
0) lookup = False;
result->val.n = ShowTipString( window, tipText, anchored, anchorPos, lookup,
mode, hAlign, vAlign, alignMode );
return True;
bad_arg:
*errMsg =
"unrecognized argument to %s";
return False;
}
static int killCalltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int calltipID =
0;
if (nArgs >
1) {
*errMsg =
"%s subroutine called with too many arguments";
return False;
}
if (nArgs >
0) {
if (!readIntArg(argList[
0], &calltipID, errMsg))
return False;
}
KillCalltip( window, calltipID );
result->tag =
NO_TAG;
return True;
}
static int calltipIDMV(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = GetCalltipID(window,
0);
return True;
}
static int filenameDialogMS(WindowInfo* window, DataValue* argList,
int nArgs,
DataValue* result,
char** errMsg)
{
char stringStorage[
5][
TYPE_INT_STR_SIZE(
int)];
char* title =
"Choose Filename";
char* mode =
"exist";
char* defaultPath =
"";
char* filter =
"";
char* defaultName =
"";
char* orgDefaultPath;
char* orgFilter;
int gfnResult;
window = MacroRunWindow();
if (
NULL == window->macroCmdData) {
M_FAILURE(
"%s can''t be called from non-suspendable context");
}
if (nArgs >
0 && !readStringArg(argList[
0], &title, stringStorage[
0],
errMsg)) {
return False;
}
if (nArgs >
1 && !readStringArg(argList[
1], &mode, stringStorage[
1],
errMsg)) {
return False;
}
if (
0 != strcmp(mode,
"exist") &&
0 != strcmp(mode,
"new")) {
M_FAILURE(
"Invalid value for mode in %s");
}
if (nArgs >
2 && !readStringArg(argList[
2], &defaultPath, stringStorage[
2],
errMsg)) {
return False;
}
if (nArgs >
3 && !readStringArg(argList[
3], &filter, stringStorage[
3],
errMsg)) {
return False;
}
if (nArgs >
4 && !readStringArg(argList[
4], &defaultName, stringStorage[
4],
errMsg)) {
return False;
}
if (nArgs >
5) {
M_FAILURE(
"%s called with too many arguments. Expects at most 5 arguments.");
}
orgDefaultPath = GetFileDialogDefaultDirectory();
if (
'\0' != defaultPath[
0]) {
SetFileDialogDefaultDirectory(defaultPath);
}
else {
SetFileDialogDefaultDirectory(window->path);
}
orgFilter = FileDialogGetFilter();
if (
'\0' != filter[
0]) {
FileDialogSetFilter(filter);
}
window->macroBlocking = True;
FileSelection getfile = {
NULL,
NULL };
if (
0 == strcmp(mode,
"exist")) {
gfnResult = GetExistingFilename(window->shell, title, &getfile);
}
else {
gfnResult = GetNewFilename(window->shell, title, &getfile, defaultName);
}
window->macroBlocking = False;
SetFileDialogDefaultDirectory(orgDefaultPath);
FileDialogSetFilter(orgFilter);
NEditFree(orgDefaultPath);
NEditFree(orgFilter);
result->tag =
STRING_TAG;
if (
GFN_OK == gfnResult) {
if (!AllocNStringNCpy(&result->val.str, getfile.path,
MAXPATHLEN)) {
M_FAILURE(
"failed to allocate return value: %s");
}
NEditFree(getfile.path);
}
else {
result->val.str.rep =
PERM_ALLOC_STR(
"");
result->val.str.len =
0;
}
return True;
}
static int listDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
macroCmdInfo *cmdData;
char stringStorage[
TYPE_INT_STR_SIZE(
int)];
char textStorage[
TYPE_INT_STR_SIZE(
int)];
char btnStorage[
TYPE_INT_STR_SIZE(
int)];
char *btnLabel;
char *message, *text;
Widget dialog, btn;
int i, nBtns;
XmString s1, s2;
long nlines =
0;
char *p, *old_p, **text_lines, *tmp;
int tmp_len;
int n, is_last;
XmString *test_strings;
int tabDist;
Arg al[
20];
int ac;
window = MacroRunWindow();
cmdData = window->macroCmdData;
if (!cmdData) {
*errMsg =
"%s can''t be called from non-suspendable context";
return False;
}
if (nArgs <
2) {
*errMsg =
"%s subroutine called with no message, string or arguments";
return False;
}
if (!readStringArg(argList[
0], &message, stringStorage, errMsg))
return False;
if (!readStringArg(argList[
1], &text, textStorage, errMsg))
return False;
if (!text || text[
0] ==
'\0') {
*errMsg =
"%s subroutine called with empty list data";
return False;
}
for (i=
2; i<nArgs; i++)
if (!readStringArg(argList[i], &btnLabel, btnStorage, errMsg))
return False;
if (nArgs ==
2) {
btnLabel =
"OK";
nBtns =
1;
}
else {
nBtns = nArgs -
2;
argList +=
2;
readStringArg(argList[
0], &btnLabel, btnStorage, errMsg);
}
nlines =
1;
for (p = text; *p; p++)
if (*p ==
'\n')
nlines++;
test_strings = (XmString *) NEditMalloc(
sizeof(XmString) * nlines);
text_lines = (
char **)NEditMalloc(
sizeof(
char *) * (nlines +
1));
for (n =
0; n < nlines; n++) {
test_strings[n] = (XmString)
0;
text_lines[n] = (
char *)
0;
}
text_lines[n] = (
char *)
0;
tabDist = window->buffer->tabDist;
n =
0;
is_last =
0;
p = old_p = text;
tmp_len =
0;
tmp = (
char*)NEditMalloc(
1);
do {
is_last = (*p ==
'\0');
if (*p ==
'\n' || is_last) {
*p =
'\0';
if (strlen(old_p) >
0) {
char *s, *t;
int l;
text_lines[n] = (
char *)NEditMalloc(strlen(old_p) +
1);
strcpy(text_lines[n], old_p);
for (s = old_p, l =
0; *s; s++)
l += (*s ==
'\t') ? tabDist - (l % tabDist) :
1;
if (l > tmp_len)
tmp = (
char*)NEditRealloc(tmp, (tmp_len = l) +
1);
for (s = old_p, t = tmp, l =
0; *s; s++) {
if (*s ==
'\t') {
for (i = tabDist - (l % tabDist); i--; l++)
*t++ =
' ';
}
else {
*t++ = *s;
l++;
}
}
*t =
'\0';
test_strings[n] =
MKSTRING(tmp);
n++;
}
old_p = p +
1;
if (!is_last)
*p =
'\n';
}
p++;
}
while (!is_last);
NEditFree(tmp);
nlines = n;
if (nlines ==
0) {
test_strings[
0] =
MKSTRING(
"");
nlines =
1;
}
ac =
0;
XtSetArg(al[ac], XmNtitle,
" "); ac++;
XtSetArg(al[ac], XmNlistLabelString, s1=
MKSTRING(message)); ac++;
XtSetArg(al[ac], XmNlistItems, test_strings); ac++;
XtSetArg(al[ac], XmNlistItemCount, nlines); ac++;
XtSetArg(al[ac], XmNlistVisibleItemCount, (nlines >
10) ?
10 : nlines); ac++;
XtSetArg(al[ac], XmNokLabelString, s2=XmStringCreateSimple(btnLabel)); ac++;
dialog = CreateSelectionDialog(window->shell,
"macroListDialog", al, ac);
if (
2 == nArgs)
{
XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
NULL);
}
AddMotifCloseCallback(XtParent(dialog), listDialogCloseCB, window);
XtAddCallback(dialog, XmNokCallback, listDialogBtnCB, window);
XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
XmNuserData, (XtPointer)
1,
NULL);
XmStringFree(s1);
XmStringFree(s2);
cmdData->dialog = dialog;
while (n--)
XmStringFree(test_strings[n]);
NEditFree(test_strings);
XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_LIST),
XmNselectionPolicy, XmSINGLE_SELECT,
XmNuserData, (XtPointer)text_lines,
NULL);
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_APPLY_BUTTON));
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT));
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_SELECTION_LABEL));
XtAddCallback(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON),
XmNactivateCallback, listDialogCloseCB, window);
XtVaCreateWidget(
"x", xmSeparatorWidgetClass, dialog,
NULL);
for (i=
1; i<nBtns; i++) {
readStringArg(argList[i], &btnLabel, btnStorage, errMsg);
btn = XtVaCreateManagedWidget(
"mdBtn", xmPushButtonWidgetClass, dialog,
XmNlabelString, s1=XmStringCreateSimple(btnLabel),
XmNuserData, (XtPointer)(
intptr_t)(i+
1),
NULL);
XtAddCallback(btn, XmNactivateCallback, listDialogBtnCB, window);
XmStringFree(s1);
}
#ifdef LESSTIF_VERSION
XtAddEventHandler(dialog, KeyPressMask, False, listDialogEscCB,
(XtPointer)window);
XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
True, GrabModeAsync, GrabModeAsync);
#endif
ManageDialogCenteredOnPointer(dialog);
PreemptMacro();
result->tag =
INT_TAG;
result->val.n =
0;
return True;
}
static void listDialogBtnCB(Widget w, XtPointer clientData,
XtPointer callData)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
XtPointer userData;
DataValue retVal;
char *text;
char **text_lines;
int btnNum;
int n_sel, *seltable, sel_index =
0;
Widget theList;
size_t length;
if (cmdData ==
NULL)
return;
theList = XmSelectionBoxGetChild(cmdData->dialog, XmDIALOG_LIST);
XtVaGetValues(theList, XmNuserData, &text_lines,
NULL);
if (!XmListGetSelectedPos(theList, &seltable, &n_sel)) {
n_sel =
0;
}
else {
sel_index = seltable[
0] -
1;
NEditFree(seltable);
}
if (!n_sel) {
text = NEditStrdup(
"");
length =
0;
}
else {
length = strlen((
char *)text_lines[sel_index]);
text = NEditStrdup(text_lines[sel_index]);
}
for (sel_index =
0; text_lines[sel_index]; sel_index++)
NEditFree(text_lines[sel_index]);
NEditFree(text_lines);
retVal.tag =
STRING_TAG;
retVal.val.str.rep = text;
retVal.val.str.len = length;
ModifyReturnedValue(cmdData->context, retVal);
if (XtClass(w) == xmPushButtonWidgetClass) {
XtVaGetValues(w, XmNuserData, &userData,
NULL);
btnNum = (
int)(
intptr_t)userData;
}
else
btnNum =
1;
ReturnGlobals[
LIST_DIALOG_BUTTON]->value.tag =
INT_TAG;
ReturnGlobals[
LIST_DIALOG_BUTTON]->value.val.n = btnNum;
XtDestroyWidget(XtParent(cmdData->dialog));
cmdData->dialog =
NULL;
ResumeMacroExecution(window);
}
static void listDialogCloseCB(Widget w, XtPointer clientData,
XtPointer callData)
{
WindowInfo *window = (WindowInfo *)clientData;
macroCmdInfo *cmdData = window->macroCmdData;
DataValue retVal;
char **text_lines;
int sel_index;
Widget theList;
if (cmdData ==
NULL)
return;
theList = XmSelectionBoxGetChild(cmdData->dialog, XmDIALOG_LIST);
XtVaGetValues(theList, XmNuserData, &text_lines,
NULL);
for (sel_index =
0; text_lines[sel_index]; sel_index++)
NEditFree(text_lines[sel_index]);
NEditFree(text_lines);
retVal.tag =
STRING_TAG;
retVal.val.str.rep = NEditStrdup(
"");
retVal.val.str.len =
0;
ModifyReturnedValue(cmdData->context, retVal);
ReturnGlobals[
LIST_DIALOG_BUTTON]->value.tag =
INT_TAG;
ReturnGlobals[
LIST_DIALOG_BUTTON]->value.val.n =
0;
XtDestroyWidget(XtParent(cmdData->dialog));
cmdData->dialog =
NULL;
ResumeMacroExecution(window);
}
#ifdef LESSTIF_VERSION
static void listDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
Boolean *cont)
{
if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
return;
if (clientData !=
NULL) {
listDialogCloseCB(w, (WindowInfo *)clientData,
NULL);
}
*cont = False;
}
#endif
static int stringCompareMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
3][
TYPE_INT_STR_SIZE(
int)];
char *leftStr, *rightStr, *argStr;
int considerCase = True;
int i;
int compareResult;
if (nArgs <
2) {
return(wrongNArgsErr(errMsg));
}
if (!readStringArg(argList[
0], &leftStr, stringStorage[
0], errMsg))
return False;
if (!readStringArg(argList[
1], &rightStr, stringStorage[
1], errMsg))
return False;
for (i =
2; i < nArgs; ++i) {
if (!readStringArg(argList[i], &argStr, stringStorage[
2], errMsg))
return False;
else if (!strcmp(argStr,
"case"))
considerCase = True;
else if (!strcmp(argStr,
"nocase"))
considerCase = False;
else {
*errMsg =
"Unrecognized argument to %s";
return False;
}
}
if (considerCase) {
compareResult = strcmp(leftStr, rightStr);
compareResult = (compareResult >
0) ?
1 : ((compareResult <
0) ? -
1 :
0);
}
else {
compareResult = strcasecmp(leftStr, rightStr);
}
result->tag =
INT_TAG;
result->val.n = compareResult;
return True;
}
static int splitMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
3][
TYPE_INT_STR_SIZE(
int)];
char *sourceStr, *splitStr, *typeSplitStr;
int searchType, beginPos, foundStart, foundEnd, strLength, lastEnd;
int found, elementEnd, indexNum;
char indexStr[
TYPE_INT_STR_SIZE(
int)], *allocIndexStr;
DataValue element;
int elementLen;
if (nArgs <
2) {
return(wrongNArgsErr(errMsg));
}
if (!readStringArg(argList[
0], &sourceStr, stringStorage[
0], errMsg)) {
*errMsg =
"first argument must be a string: %s";
return(False);
}
if (!readStringArg(argList[
1], &splitStr, stringStorage[
1], errMsg)) {
splitStr =
NULL;
}
else {
if (splitStr[
0] ==
0) {
splitStr =
NULL;
}
}
if (splitStr ==
NULL) {
*errMsg =
"second argument must be a non-empty string: %s";
return(False);
}
if (nArgs >
2 && readStringArg(argList[
2], &typeSplitStr, stringStorage[
2], errMsg)) {
if (!StringToSearchType(typeSplitStr, &searchType)) {
*errMsg =
"unrecognized argument to %s";
return(False);
}
}
else {
searchType =
SEARCH_LITERAL;
}
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
beginPos =
0;
lastEnd =
0;
indexNum =
0;
strLength = strlen(sourceStr);
found =
1;
while (found && beginPos < strLength) {
sprintf(indexStr,
"%d", indexNum);
allocIndexStr = AllocString(strlen(indexStr) +
1);
if (!allocIndexStr) {
*errMsg =
"array element failed to allocate key: %s";
return(False);
}
strcpy(allocIndexStr, indexStr);
found = SearchString(sourceStr, splitStr,
SEARCH_FORWARD, searchType,
False, beginPos, &foundStart, &foundEnd,
NULL,
NULL, GetWindowDelimiters(window));
elementEnd = found ? foundStart : strLength;
elementLen = elementEnd - lastEnd;
element.tag =
STRING_TAG;
if (!AllocNStringNCpy(&element.val.str, &sourceStr[lastEnd], elementLen)) {
*errMsg =
"failed to allocate element value: %s";
return(False);
}
if (!ArrayInsert(result, allocIndexStr, &element)) {
M_ARRAY_INSERT_FAILURE();
}
if (found) {
if (foundStart == foundEnd) {
beginPos = foundEnd +
1;
}
else {
beginPos = foundEnd;
}
}
else {
beginPos = strLength;
}
lastEnd = foundEnd;
++indexNum;
}
if (found) {
sprintf(indexStr,
"%d", indexNum);
allocIndexStr = AllocString(strlen(indexStr) +
1);
if (!allocIndexStr) {
*errMsg =
"array element failed to allocate key: %s";
return(False);
}
strcpy(allocIndexStr, indexStr);
element.tag =
STRING_TAG;
if (lastEnd == strLength) {
element.val.str.rep =
PERM_ALLOC_STR(
"");
element.val.str.len =
0;
if (!ArrayInsert(result, allocIndexStr, &element)) {
M_ARRAY_INSERT_FAILURE();
}
}
else {
elementLen = strLength - lastEnd;
if (!AllocNStringNCpy(&element.val.str, &sourceStr[lastEnd], elementLen)) {
*errMsg =
"failed to allocate element value: %s";
return(False);
}
if (!ArrayInsert(result, allocIndexStr, &element)) {
M_ARRAY_INSERT_FAILURE();
}
found = SearchString(sourceStr, splitStr,
SEARCH_FORWARD,
searchType, False, strLength, &foundStart, &foundEnd,
NULL,
NULL, GetWindowDelimiters(window));
if (found) {
++indexNum;
sprintf(indexStr,
"%d", indexNum);
allocIndexStr = AllocString(strlen(indexStr) +
1);
if (!allocIndexStr) {
*errMsg =
"array element failed to allocate key: %s";
return(False);
}
strcpy(allocIndexStr, indexStr);
element.tag =
STRING_TAG;
element.val.str.rep =
PERM_ALLOC_STR(
"");
element.val.str.len =
0;
if (!ArrayInsert(result, allocIndexStr, &element)) {
M_ARRAY_INSERT_FAILURE();
}
}
}
}
return(True);
}
static int cursorMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = TextGetCursorPos(window->lastFocus);
return True;
}
static int lineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int line, cursorPos, colNum;
result->tag =
INT_TAG;
cursorPos = TextGetCursorPos(window->lastFocus);
if (!TextPosToLineAndCol(window->lastFocus, cursorPos, &line, &colNum))
line = BufCountLines(window->buffer,
0, cursorPos) +
1;
result->val.n = line;
return True;
}
static int columnMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
textBuffer *buf = window->buffer;
int cursorPos;
result->tag =
INT_TAG;
cursorPos = TextGetCursorPos(window->lastFocus);
result->val.n = BufCountDispChars(buf, BufStartOfLine(buf, cursorPos),
cursorPos);
return True;
}
static int fileNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, window->filename);
return True;
}
static int filePathMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, window->path);
return True;
}
static int lengthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->buffer->length;
return True;
}
static int selectionStartMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->buffer->primary.selected ?
window->buffer->primary.start : -
1;
return True;
}
static int selectionEndMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->buffer->primary.selected ?
window->buffer->primary.end : -
1;
return True;
}
static int selectionLeftMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
selection *sel = &window->buffer->primary;
result->tag =
INT_TAG;
result->val.n = sel->selected && sel->rectangular ? sel->rectStart : -
1;
return True;
}
static int selectionRightMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
selection *sel = &window->buffer->primary;
result->tag =
INT_TAG;
result->val.n = sel->selected && sel->rectangular ? sel->rectEnd : -
1;
return True;
}
static int wrapMarginMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int margin, nCols;
XtVaGetValues(window->textArea, textNcolumns, &nCols,
textNwrapMargin, &margin,
NULL);
result->tag =
INT_TAG;
result->val.n = margin ==
0 ? nCols : margin;
return True;
}
static int statisticsLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->showStats ?
1 :
0;
return True;
}
static int incSearchLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->showISearchLine ?
1 :
0;
return True;
}
static int showLineNumbersMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->showLineNumbers ?
1 :
0;
return True;
}
static int autoIndentMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *res =
NULL;
switch (window->indentStyle) {
case NO_AUTO_INDENT:
res =
PERM_ALLOC_STR(
"off");
break;
case AUTO_INDENT:
res =
PERM_ALLOC_STR(
"on");
break;
case SMART_INDENT:
res =
PERM_ALLOC_STR(
"smart");
break;
default:
*errMsg =
"Invalid indent style value encountered in %s";
return False;
break;
}
result->tag =
STRING_TAG;
result->val.str.rep = res;
result->val.str.len = strlen(res);
return True;
}
static int wrapTextMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *res =
NULL;
switch (window->wrapMode) {
case NO_WRAP:
res =
PERM_ALLOC_STR(
"none");
break;
case NEWLINE_WRAP:
res =
PERM_ALLOC_STR(
"auto");
break;
case CONTINUOUS_WRAP:
res =
PERM_ALLOC_STR(
"continuous");
break;
default:
*errMsg =
"Invalid wrap style value encountered in %s";
return False;
break;
}
result->tag =
STRING_TAG;
result->val.str.rep = res;
result->val.str.len = strlen(res);
return True;
}
static int highlightSyntaxMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->highlightSyntax ?
1 :
0;
return True;
}
static int makeBackupCopyMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->saveOldVersion ?
1 :
0;
return True;
}
static int incBackupMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->autoSave ?
1 :
0;
return True;
}
static int showMatchingMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *res =
NULL;
switch (window->showMatchingStyle) {
case NO_FLASH:
res =
PERM_ALLOC_STR(
NO_FLASH_STRING);
break;
case FLASH_DELIMIT:
res =
PERM_ALLOC_STR(
FLASH_DELIMIT_STRING);
break;
case FLASH_RANGE:
res =
PERM_ALLOC_STR(
FLASH_RANGE_STRING);
break;
default:
*errMsg =
"Invalid match flashing style value encountered in %s";
return False;
break;
}
result->tag =
STRING_TAG;
result->val.str.rep = res;
result->val.str.len = strlen(res);
return True;
}
static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->matchSyntaxBased ?
1 :
0;
return True;
}
static int overTypeModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->overstrike ?
1 :
0;
return True;
}
static int readOnlyMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = (
IS_ANY_LOCKED(window->lockReasons)) ?
1 :
0;
return True;
}
static int lockedMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = (
IS_USER_LOCKED(window->lockReasons)) ?
1 :
0;
return True;
}
static int fileFormatMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *res =
NULL;
switch (window->fileFormat) {
case UNIX_FILE_FORMAT:
res =
PERM_ALLOC_STR(
"unix");
break;
case DOS_FILE_FORMAT:
res =
PERM_ALLOC_STR(
"dos");
break;
case MAC_FILE_FORMAT:
res =
PERM_ALLOC_STR(
"macintosh");
break;
default:
*errMsg =
"Invalid linefeed style value encountered in %s";
return False;
}
result->tag =
STRING_TAG;
result->val.str.rep = res;
result->val.str.len = strlen(res);
return True;
}
static int fontNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, window->fontName);
return True;
}
static int fontNameItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, window->italicFontName);
return True;
}
static int fontNameBoldMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, window->boldFontName);
return True;
}
static int fontNameBoldItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, window->boldItalicFontName);
return True;
}
static int subscriptSepMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
result->val.str.rep =
PERM_ALLOC_STR(
ARRAY_DIM_SEP);
result->val.str.len = strlen(result->val.str.rep);
return True;
}
static int minFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = TextGetMinFontWidth(window->textArea, window->highlightSyntax);
return True;
}
static int maxFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = TextGetMaxFontWidth(window->textArea, window->highlightSyntax);
return True;
}
static int topLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = TextFirstVisibleLine(window->lastFocus);
return True;
}
static int numDisplayLinesMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = TextNumVisibleLines(window->lastFocus);
return True;
}
static int displayWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = TextVisibleWidth(window->lastFocus);
return True;
}
static int activePaneMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = WidgetToPaneIndex(window, window->lastFocus) +
1;
return True;
}
static int nPanesMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->nPanes +
1;
return True;
}
static int emptyArrayMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
ARRAY_TAG;
result->val.arrayPtr =
NULL;
return True;
}
static int serverNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, GetPrefServerName());
return True;
}
static int tabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->buffer->tabDist;
return True;
}
static int emTabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int dist;
XtVaGetValues(window->textArea, textNemulateTabs, &dist,
NULL);
result->tag =
INT_TAG;
result->val.n = dist;
return True;
}
static int useTabsMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->buffer->useTabs;
return True;
}
static int modifiedMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
result->tag =
INT_TAG;
result->val.n = window->fileChanged;
return True;
}
static int languageModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char *lmName = LanguageModeName(window->languageMode);
if (lmName ==
NULL)
lmName =
"Plain";
result->tag =
STRING_TAG;
AllocNStringCpy(&result->val.str, lmName);
return True;
}
static int rangesetListMV(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
RangesetTable *rangesetTable = window->buffer->rangesetTable;
unsigned char *rangesetList;
char *allocIndexStr;
char indexStr[
TYPE_INT_STR_SIZE(
int)] ;
int nRangesets, i;
DataValue element;
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
if (rangesetTable ==
NULL) {
return True;
}
rangesetList = RangesetGetList(rangesetTable);
nRangesets = strlen((
char*)rangesetList);
for(i =
0; i < nRangesets; i++) {
element.tag =
INT_TAG;
element.val.n = rangesetList[i];
sprintf(indexStr,
"%d", nRangesets - i -
1);
allocIndexStr = AllocString(strlen(indexStr) +
1);
if (allocIndexStr ==
NULL)
M_FAILURE(
"Failed to allocate array key in %s");
strcpy(allocIndexStr, indexStr);
if (!ArrayInsert(result, allocIndexStr, &element))
M_FAILURE(
"Failed to insert array element in %s");
}
return True;
}
static int versionMV(WindowInfo* window, DataValue* argList,
int nArgs,
DataValue* result,
char** errMsg)
{
static unsigned version =
NEDIT_VERSION *
1000 +
NEDIT_REVISION;
result->tag =
INT_TAG;
result->val.n = version;
return True;
}
static int rangesetCreateMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int label;
int i, nRangesetsRequired;
DataValue element;
char indexStr[
TYPE_INT_STR_SIZE(
int)], *allocIndexStr;
RangesetTable *rangesetTable = window->buffer->rangesetTable;
if (nArgs >
1)
return wrongNArgsErr(errMsg);
if (rangesetTable ==
NULL) {
window->buffer->rangesetTable = rangesetTable =
RangesetTableAlloc(window->buffer);
}
if (nArgs ==
0) {
label = RangesetCreate(rangesetTable);
result->tag =
INT_TAG;
result->val.n = label;
return True;
}
else {
if (!readIntArg(argList[
0], &nRangesetsRequired, errMsg))
return False;
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
if (nRangesetsRequired > nRangesetsAvailable(rangesetTable))
return True;
for (i =
0; i < nRangesetsRequired; i++) {
element.tag =
INT_TAG;
element.val.n = RangesetCreate(rangesetTable);
sprintf(indexStr,
"%d", i);
allocIndexStr = AllocString(strlen(indexStr) +
1);
if (!allocIndexStr) {
*errMsg =
"Array element failed to allocate key: %s";
return(False);
}
strcpy(allocIndexStr, indexStr);
ArrayInsert(result, allocIndexStr, &element);
}
return True;
}
}
static int rangesetDestroyMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
RangesetTable *rangesetTable = window->buffer->rangesetTable;
DataValue *array;
DataValue element;
char keyString[
TYPE_INT_STR_SIZE(
int)];
int deleteLabels[
N_RANGESETS];
int i, arraySize;
int label =
0;
if (nArgs !=
1) {
return wrongNArgsErr(errMsg);
}
if (argList[
0].tag ==
ARRAY_TAG) {
array = &argList[
0];
arraySize = ArraySize(array);
if (arraySize >
N_RANGESETS) {
M_FAILURE(
"Too many elements in array in %s");
}
for (i =
0; i < arraySize; i++) {
sprintf(keyString,
"%d", i);
if (!ArrayGet(array, keyString, &element)) {
M_FAILURE(
"Invalid key in array in %s");
}
if (!readIntArg(element, &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"Invalid rangeset label in array in %s");
}
deleteLabels[i] = label;
}
for (i =
0; i < arraySize; i++) {
RangesetForget(rangesetTable, deleteLabels[i]);
}
}
else {
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"Invalid rangeset label in %s");
}
if(rangesetTable !=
NULL) {
RangesetForget(rangesetTable, label);
}
}
result->tag =
NO_TAG;
return True;
}
static int rangesetGetByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
Rangeset *rangeset;
int label;
char *name, *rangeset_name;
RangesetTable *rangesetTable = window->buffer->rangesetTable;
unsigned char *rangesetList;
char *allocIndexStr;
char indexStr[
TYPE_INT_STR_SIZE(
int)] ;
int nRangesets, i, insertIndex =
0;
DataValue element;
if (nArgs !=
1) {
return wrongNArgsErr(errMsg);
}
if (!readStringArg(argList[
0], &name, stringStorage[
0], errMsg)) {
M_FAILURE(
"First parameter is not a name string in %s");
}
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
if (rangesetTable ==
NULL) {
return True;
}
rangesetList = RangesetGetList(rangesetTable);
nRangesets = strlen((
char *)rangesetList);
for (i =
0; i < nRangesets; ++i) {
label = rangesetList[i];
rangeset = RangesetFetch(rangesetTable, label);
if (rangeset) {
rangeset_name = RangesetGetName(rangeset);
if (strcmp(name, rangeset_name ? rangeset_name :
"") ==
0) {
element.tag =
INT_TAG;
element.val.n = label;
sprintf(indexStr,
"%d", insertIndex);
allocIndexStr = AllocString(strlen(indexStr) +
1);
if (allocIndexStr ==
NULL)
M_FAILURE(
"Failed to allocate array key in %s");
strcpy(allocIndexStr, indexStr);
if (!ArrayInsert(result, allocIndexStr, &element))
M_FAILURE(
"Failed to insert array element in %s");
++insertIndex;
}
}
}
return True;
}
static int rangesetAddMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
textBuffer *buffer = window->buffer;
RangesetTable *rangesetTable = buffer->rangesetTable;
Rangeset *targetRangeset, *sourceRangeset;
int start, end, isRect, rectStart, rectEnd, maxpos, index;
int label =
0;
if (nArgs <
1 || nArgs >
3)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
targetRangeset = RangesetFetch(rangesetTable, label);
if (targetRangeset ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
start = end = -
1;
if (nArgs ==
1) {
if (!BufGetSelectionPos(buffer, &start, &end,
&isRect, &rectStart, &rectEnd) || isRect) {
M_FAILURE(
"Selection missing or rectangular in call to %s");
}
if (!RangesetAddBetween(targetRangeset, start, end)) {
M_FAILURE(
"Failure to add selection in %s");
}
}
if (nArgs ==
2) {
if (!readIntArg(argList[
1], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"Second parameter is an invalid rangeset label in %s");
}
sourceRangeset = RangesetFetch(rangesetTable, label);
if (sourceRangeset ==
NULL) {
M_FAILURE(
"Second rangeset does not exist in %s");
}
RangesetAdd(targetRangeset, sourceRangeset);
}
if (nArgs ==
3) {
if (!readIntArg(argList[
1], &start, errMsg)) {
return False;
}
if (!readIntArg(argList[
2], &end, errMsg)) {
return False;
}
maxpos = buffer->length;
if (start <
0) start =
0;
if (start > maxpos) start = maxpos;
if (end <
0) end =
0;
if (end > maxpos) end = maxpos;
if (start > end) {
int temp = start; start = end; end = temp;}
if ((start != end) && !RangesetAddBetween(targetRangeset, start, end)) {
M_FAILURE(
"Failed to add range in %s");
}
}
if (nArgs !=
2 && start >=
0) {
start = (start + end) /
2;
index =
1 + RangesetFindRangeOfPos(targetRangeset, start, False);
}
else {
index =
0;
}
result->tag =
INT_TAG;
result->val.n = index;
return True;
}
static int rangesetSubtractMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
textBuffer *buffer = window->buffer;
RangesetTable *rangesetTable = buffer->rangesetTable;
Rangeset *targetRangeset, *sourceRangeset;
int start, end, isRect, rectStart, rectEnd, maxpos;
int label =
0;
if (nArgs <
1 || nArgs >
3) {
return wrongNArgsErr(errMsg);
}
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
targetRangeset = RangesetFetch(rangesetTable, label);
if (targetRangeset ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
if (nArgs ==
1) {
if (!BufGetSelectionPos(buffer, &start, &end, &isRect, &rectStart, &rectEnd)
|| isRect) {
M_FAILURE(
"Selection missing or rectangular in call to %s");
}
RangesetRemoveBetween(targetRangeset, start, end);
}
if (nArgs ==
2) {
if (!readIntArg(argList[
1], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"Second parameter is an invalid rangeset label in %s");
}
sourceRangeset = RangesetFetch(rangesetTable, label);
if (sourceRangeset ==
NULL) {
M_FAILURE(
"Second rangeset does not exist in %s");
}
RangesetRemove(targetRangeset, sourceRangeset);
}
if (nArgs ==
3) {
if (!readIntArg(argList[
1], &start, errMsg))
return False;
if (!readIntArg(argList[
2], &end, errMsg))
return False;
maxpos = buffer->length;
if (start <
0) start =
0;
if (start > maxpos) start = maxpos;
if (end <
0) end =
0;
if (end > maxpos) end = maxpos;
if (start > end) {
int temp = start; start = end; end = temp;}
RangesetRemoveBetween(targetRangeset, start, end);
}
result->tag =
NO_TAG;
return True;
}
static int rangesetInvertMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
RangesetTable *rangesetTable = window->buffer->rangesetTable;
Rangeset *rangeset;
int label =
0;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
rangeset = RangesetFetch(rangesetTable, label);
if (rangeset ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
if (RangesetInverse(rangeset) <
0) {
M_FAILURE(
"Problem inverting rangeset in %s");
}
result->tag =
NO_TAG;
return True;
}
static int rangesetInfoMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
RangesetTable *rangesetTable = window->buffer->rangesetTable;
Rangeset *rangeset =
NULL;
int count, defined;
char *color, *name, *mode;
DataValue element;
int label =
0;
if (nArgs !=
1)
return wrongNArgsErr(errMsg);
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable !=
NULL) {
rangeset = RangesetFetch(rangesetTable, label);
}
RangesetGetInfo(rangeset, &defined, &label, &count, &color, &name, &mode);
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
element.tag =
INT_TAG;
element.val.n = defined;
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"defined"), &element))
M_FAILURE(
"Failed to insert array element \"defined\" in %s");
element.tag =
INT_TAG;
element.val.n = count;
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"count"), &element))
M_FAILURE(
"Failed to insert array element \"count\" in %s");
element.tag =
STRING_TAG;
if (!AllocNStringCpy(&element.val.str, color))
M_FAILURE(
"Failed to allocate array value \"color\" in %s");
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"color"), &element))
M_FAILURE(
"Failed to insert array element \"color\" in %s");
element.tag =
STRING_TAG;
if (!AllocNStringCpy(&element.val.str, name))
M_FAILURE(
"Failed to allocate array value \"name\" in %s");
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"name"), &element)) {
M_FAILURE(
"Failed to insert array element \"name\" in %s");
}
element.tag =
STRING_TAG;
if (!AllocNStringCpy(&element.val.str, mode))
M_FAILURE(
"Failed to allocate array value \"mode\" in %s");
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"mode"), &element))
M_FAILURE(
"Failed to insert array element \"mode\" in %s");
return True;
}
static int rangesetRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
textBuffer *buffer = window->buffer;
RangesetTable *rangesetTable = buffer->rangesetTable;
Rangeset *rangeset;
int start, end, dummy, rangeIndex, ok;
DataValue element;
int label =
0;
if (nArgs <
1 || nArgs >
2) {
return wrongNArgsErr(errMsg);
}
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
ok = False;
rangeset = RangesetFetch(rangesetTable, label);
if (rangeset !=
NULL) {
if (nArgs ==
1) {
rangeIndex = RangesetGetNRanges(rangeset) -
1;
ok = RangesetFindRangeNo(rangeset,
0, &start, &dummy);
ok &= RangesetFindRangeNo(rangeset, rangeIndex, &dummy, &end);
rangeIndex = -
1;
}
else if (nArgs ==
2) {
if (!readIntArg(argList[
1], &rangeIndex, errMsg)) {
return False;
}
ok = RangesetFindRangeNo(rangeset, rangeIndex-
1, &start, &end);
}
}
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
if (!ok)
return True;
element.tag =
INT_TAG;
element.val.n = start;
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"start"), &element))
M_FAILURE(
"Failed to insert array element \"start\" in %s");
element.tag =
INT_TAG;
element.val.n = end;
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"end"), &element))
M_FAILURE(
"Failed to insert array element \"end\" in %s");
return True;
}
static int rangesetIncludesPosMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg)
{
textBuffer *buffer = window->buffer;
RangesetTable *rangesetTable = buffer->rangesetTable;
Rangeset *rangeset;
int pos, rangeIndex, maxpos;
int label =
0;
if (nArgs <
1 || nArgs >
2) {
return wrongNArgsErr(errMsg);
}
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
rangeset = RangesetFetch(rangesetTable, label);
if (rangeset ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
if (nArgs ==
1) {
pos = TextGetCursorPos(window->lastFocus);
}
else if (nArgs ==
2) {
if (!readIntArg(argList[
1], &pos, errMsg))
return False;
}
maxpos = buffer->length;
if (pos <
0 || pos > maxpos) {
rangeIndex =
0;
}
else {
rangeIndex = RangesetFindRangeOfPos(rangeset, pos, False) +
1;
}
result->tag =
INT_TAG;
result->val.n = rangeIndex;
return True;
}
static int rangesetSetColorMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg)
{
char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
textBuffer *buffer = window->buffer;
RangesetTable *rangesetTable = buffer->rangesetTable;
Rangeset *rangeset;
char *color_name;
int label =
0;
if (nArgs !=
2) {
return wrongNArgsErr(errMsg);
}
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
rangeset = RangesetFetch(rangesetTable, label);
if (rangeset ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
color_name =
"";
if (rangeset !=
NULL) {
if (!readStringArg(argList[
1], &color_name, stringStorage[
0], errMsg)) {
M_FAILURE(
"Second parameter is not a color name string in %s");
}
}
RangesetAssignColorName(rangeset, color_name);
result->tag =
NO_TAG;
return True;
}
static int rangesetSetNameMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg)
{
char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
textBuffer *buffer = window->buffer;
RangesetTable *rangesetTable = buffer->rangesetTable;
Rangeset *rangeset;
char *name;
int label =
0;
if (nArgs !=
2) {
return wrongNArgsErr(errMsg);
}
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
rangeset = RangesetFetch(rangesetTable, label);
if (rangeset ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
name =
"";
if (rangeset !=
NULL) {
if (!readStringArg(argList[
1], &name, stringStorage[
0], errMsg)) {
M_FAILURE(
"Second parameter is not a valid name string in %s");
}
}
RangesetAssignName(rangeset, name);
result->tag =
NO_TAG;
return True;
}
static int rangesetSetModeMS(WindowInfo *window, DataValue *argList,
int nArgs, DataValue *result,
char **errMsg)
{
char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
textBuffer *buffer = window->buffer;
RangesetTable *rangesetTable = buffer->rangesetTable;
Rangeset *rangeset;
char *update_fn_name;
int ok;
int label =
0;
if (nArgs <
1 || nArgs >
2) {
return wrongNArgsErr(errMsg);
}
if (!readIntArg(argList[
0], &label, errMsg)
|| !RangesetLabelOK(label)) {
M_FAILURE(
"First parameter is an invalid rangeset label in %s");
}
if (rangesetTable ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
rangeset = RangesetFetch(rangesetTable, label);
if (rangeset ==
NULL) {
M_FAILURE(
"Rangeset does not exist in %s");
}
update_fn_name =
"";
if (rangeset !=
NULL) {
if (nArgs ==
2) {
if (!readStringArg(argList[
1], &update_fn_name, stringStorage[
0], errMsg)) {
M_FAILURE(
"Second parameter is not a string in %s");
}
}
}
ok = RangesetChangeModifyResponse(rangeset, update_fn_name);
if (!ok) {
M_FAILURE(
"Second parameter is not a valid mode in %s");
}
result->tag =
NO_TAG;
return True;
}
static int fillStyleResult(DataValue *result,
char **errMsg,
WindowInfo *window,
char *styleName, Boolean preallocatedStyleName,
Boolean includeName,
int patCode,
int bufferPos)
{
DataValue
DV;
char colorValue[
20];
int r, g, b;
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
DV.tag =
STRING_TAG;
if (includeName) {
if (preallocatedStyleName) {
DV.val.str.rep = styleName;
DV.val.str.len = strlen(styleName);
}
else {
AllocNStringCpy(&
DV.val.str, styleName);
}
M_STR_ALLOC_ASSERT(
DV);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"style"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
}
AllocNStringCpy(&
DV.val.str, ColorOfNamedStyle(window->colorProfile, styleName));
M_STR_ALLOC_ASSERT(
DV);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"color"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
if (patCode) {
HighlightColorValueOfCode(window, patCode, &r, &g, &b);
sprintf(colorValue,
"#%02x%02x%02x", r/
256, g/
256, b/
256);
AllocNStringCpy(&
DV.val.str, colorValue);
M_STR_ALLOC_ASSERT(
DV);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"rgb"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
}
AllocNStringCpy(&
DV.val.str, BgColorOfNamedStyle(window->colorProfile, styleName));
M_STR_ALLOC_ASSERT(
DV);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"background"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
if (patCode) {
GetHighlightBGColorOfCode(window, patCode, &r, &g, &b);
sprintf(colorValue,
"#%02x%02x%02x", r/
256, g/
256, b/
256);
AllocNStringCpy(&
DV.val.str, colorValue);
M_STR_ALLOC_ASSERT(
DV);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"back_rgb"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
}
DV.tag =
INT_TAG;
DV.val.n = FontOfNamedStyleIsBold(window->colorProfile, styleName);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"bold"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
DV.val.n = FontOfNamedStyleIsItalic(window->colorProfile, styleName);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"italic"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
if (bufferPos >=
0) {
const char *styleNameNotUsed =
NULL;
DV.val.n = StyleLengthOfCodeFromPos(window, bufferPos, &styleNameNotUsed);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"extent"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
}
return True;
}
static int getStyleByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
char *styleName;
if (nArgs !=
1) {
return wrongNArgsErr(errMsg);
}
result->tag =
ARRAY_TAG;
result->val.arrayPtr =
NULL;
if (!readStringArg(argList[
0], &styleName, stringStorage[
0], errMsg)) {
M_FAILURE(
"First parameter is not a string in %s");
}
if (!NamedStyleExists(window->colorProfile, styleName)) {
return True;
}
return fillStyleResult(result, errMsg, window,
styleName, (argList[
0].tag ==
STRING_TAG), False,
0, -
1);
}
static int getStyleAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int patCode;
int bufferPos;
textBuffer *buf = window->buffer;
if (nArgs !=
1) {
return wrongNArgsErr(errMsg);
}
result->tag =
ARRAY_TAG;
result->val.arrayPtr =
NULL;
if (!readIntArg(argList[
0], &bufferPos, errMsg)) {
return False;
}
if ((bufferPos <
0) || (bufferPos >= buf->length)) {
return True;
}
patCode = HighlightCodeOfPos(window, bufferPos);
if (patCode ==
0) {
return True;
}
return fillStyleResult(result, errMsg, window,
HighlightStyleOfCode(window, patCode), False, True, patCode, bufferPos);
}
static int fillPatternResult(DataValue *result,
char **errMsg,
WindowInfo *window,
char *patternName, Boolean preallocatedPatternName,
Boolean includeName,
char* styleName,
int bufferPos)
{
DataValue
DV;
result->tag =
ARRAY_TAG;
result->val.arrayPtr = ArrayNew();
DV.tag =
STRING_TAG;
if (includeName) {
if (preallocatedPatternName) {
DV.val.str.rep = patternName;
DV.val.str.len = strlen(patternName);
}
else {
AllocNStringCpy(&
DV.val.str, patternName);
}
M_STR_ALLOC_ASSERT(
DV);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"pattern"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
}
AllocNStringCpy(&
DV.val.str, styleName);
M_STR_ALLOC_ASSERT(
DV);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"style"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
DV.tag =
INT_TAG;
if (bufferPos >=
0) {
int checkCode =
0;
DV.val.n = HighlightLengthOfCodeFromPos(window, bufferPos, &checkCode);
if (!ArrayInsert(result,
PERM_ALLOC_STR(
"extent"), &
DV)) {
M_ARRAY_INSERT_FAILURE();
}
}
return True;
}
static int getPatternByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
char *patternName =
NULL;
highlightPattern *pattern;
result->tag =
ARRAY_TAG;
result->val.arrayPtr =
NULL;
if (nArgs !=
1) {
return wrongNArgsErr(errMsg);
}
if (!readStringArg(argList[
0], &patternName, stringStorage[
0], errMsg)) {
M_FAILURE(
"First parameter is not a string in %s");
}
pattern = FindPatternOfWindow(window, patternName);
if (pattern ==
NULL) {
return True;
}
return fillPatternResult(result, errMsg, window, patternName,
(argList[
0].tag ==
STRING_TAG), False, pattern->style, -
1);
}
static int getPatternAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
DataValue *result,
char **errMsg)
{
int bufferPos = -
1;
textBuffer *buffer = window->buffer;
int patCode =
0;
result->tag =
ARRAY_TAG;
result->val.arrayPtr =
NULL;
if (nArgs !=
1) {
return wrongNArgsErr(errMsg);
}
if (!readIntArg(argList[
0], &bufferPos, errMsg)) {
return False;
}
if ((bufferPos <
0) || (bufferPos >= buffer->length)) {
return True;
}
patCode = HighlightCodeOfPos(window, bufferPos);
if (patCode ==
0) {
return True;
}
return fillPatternResult(result, errMsg, window,
HighlightNameOfCode(window, patCode), False, True,
HighlightStyleOfCode(window, patCode), bufferPos);
}
static int wrongNArgsErr(
char **errMsg)
{
*errMsg =
"Wrong number of arguments to function %s";
return False;
}
static int tooFewArgsErr(
char **errMsg)
{
*errMsg =
"Too few arguments to function %s";
return False;
}
static int readIntArg(DataValue dv,
int *result,
char **errMsg)
{
char *c;
if (dv.tag ==
INT_TAG) {
*result = dv.val.n;
return True;
}
else if (dv.tag ==
STRING_TAG) {
for (c=dv.val.str.rep; *c !=
'\0'; c++) {
if (!(isdigit((
unsigned char)*c) || *c ==
' ' || *c ==
'\t')) {
goto typeError;
}
}
sscanf(dv.val.str.rep,
"%d", result);
return True;
}
typeError:
*errMsg =
"%s called with non-integer argument";
return False;
}
static int readStringArg(DataValue dv,
char **result,
char *stringStorage,
char **errMsg)
{
if (dv.tag ==
STRING_TAG) {
*result = dv.val.str.rep;
return True;
}
else if (dv.tag ==
INT_TAG) {
sprintf(stringStorage,
"%d", dv.val.n);
*result = stringStorage;
return True;
}
*errMsg =
"%s called with unknown object";
return False;
}