1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #ifdef HAVE_CONFIG_H
31 #include "../config.h"
32 #endif
33
34 #include "macro.h"
35 #include "textBuf.h"
36 #include "text.h"
37 #include "nedit.h"
38 #include "window.h"
39 #include "preferences.h"
40 #include "interpret.h"
41 #include "parse.h"
42 #include "search.h"
43 #include "server.h"
44 #include "shell.h"
45 #include "smartIndent.h"
46 #include "userCmds.h"
47 #include "selection.h"
48 #include "../util/rbTree.h"
49 #include "tags.h"
50 #include "calltips.h"
51 #include "../util/DialogF.h"
52 #include "../util/misc.h"
53 #include "../util/fileUtils.h"
54 #include "../util/utils.h"
55 #include "../util/getfiles.h"
56 #include "../util/filedialog.h"
57 #include "highlight.h"
58 #include "highlightData.h"
59 #include "rangeset.h"
60 #include "../util/nedit_malloc.h"
61
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <ctype.h>
66 #include <errno.h>
67
68 #include <sys/types.h>
69 #include <sys/stat.h>
70 #ifndef __MVS__
71 #include <sys/param.h>
72 #endif
73 #include <fcntl.h>
74
75 #include <inttypes.h>
76
77 #include <X11/Intrinsic.h>
78 #include <X11/keysym.h>
79 #include <Xm/Xm.h>
80 #include <Xm/CutPaste.h>
81 #include <Xm/Form.h>
82 #include <Xm/RowColumn.h>
83 #include <Xm/LabelG.h>
84 #include <Xm/List.h>
85 #include <Xm/ToggleB.h>
86 #include <Xm/DialogS.h>
87 #include <Xm/MessageB.h>
88 #include <Xm/SelectioB.h>
89 #include <Xm/PushB.h>
90 #include <Xm/Text.h>
91 #include <Xm/Separator.h>
92
93 #ifdef HAVE_DEBUG_H
94 #include "../debug.h"
95 #endif
96
97
98
99 #define MAX_MACRO_ACTIONS 1024
100 #define MAX_ACTION_ARGS 40
101
102
103 #define BANNER_WAIT_TIME 6000
104
105
106
107 #define M_FAILURE(s)
do { *errMsg = s;
if (
1)
return False; }
while (
0)
108 #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)
109 #define M_ARRAY_INSERT_FAILURE()
M_FAILURE(
"array element failed to insert: %s")
110
111
112
113 typedef struct {
114 XtIntervalId bannerTimeoutID;
115 XtWorkProcId continueWorkProcID;
116 char bannerIsUp;
117 char closeOnCompletion;
118 Program *program;
119 RestartData *context;
120 Widget dialog;
121 } macroCmdInfo;
122
123
124 typedef struct {
125 WindowInfo *forWindow;
126 char *lastCommand;
127 Widget shell, repeatText, lastCmdToggle;
128 Widget inSelToggle, toEndToggle;
129 } repeatDialog;
130
131 static void cancelLearn(
void);
132 static void runMacro(WindowInfo *window, Program *prog);
133 static void finishMacroCmdExecution(WindowInfo *window);
134 static void repeatOKCB(Widget w, XtPointer clientData, XtPointer callData);
135 static void repeatApplyCB(Widget w, XtPointer clientData, XtPointer callData);
136 static int doRepeatDialogAction(repeatDialog *rd, XEvent *event);
137 static void repeatCancelCB(Widget w, XtPointer clientData, XtPointer callData);
138 static void repeatDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
139 static void learnActionHook(Widget w, XtPointer clientData, String actionName,
140 XEvent *event, String *params, Cardinal *numParams);
141 static void lastActionHook(Widget w, XtPointer clientData, String actionName,
142 XEvent *event, String *params, Cardinal *numParams);
143 static char *actionToString(Widget w,
char *actionName, XEvent *event,
144 String *params, Cardinal numParams);
145 static int isMouseAction(
const char *action);
146 static int isRedundantAction(
const char *action);
147 static int isIgnoredAction(
const char *action);
148 static int readCheckMacroString(Widget dialogParent,
char *string,
149 WindowInfo *runWindow,
const char *errIn,
char **errPos);
150 static void bannerTimeoutProc(XtPointer clientData, XtIntervalId *id);
151 static Boolean continueWorkProc(XtPointer clientData);
152 static int escapeStringChars(
char *fromString,
char *toString);
153 static int escapedStringLength(
char *string);
154 static int lengthMS(WindowInfo *window, DataValue *argList,
int nArgs,
155 DataValue *result,
char **errMsg);
156 static int minMS(WindowInfo *window, DataValue *argList,
int nArgs,
157 DataValue *result,
char **errMsg);
158 static int maxMS(WindowInfo *window, DataValue *argList,
int nArgs,
159 DataValue *result,
char **errMsg);
160 static int focusWindowMS(WindowInfo *window, DataValue *argList,
int nArgs,
161 DataValue *result,
char **errMsg);
162 static int getRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
163 DataValue *result,
char **errMsg);
164 static int getCharacterMS(WindowInfo *window, DataValue *argList,
int nArgs,
165 DataValue *result,
char **errMsg);
166 static int replaceRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
167 DataValue *result,
char **errMsg);
168 static int replaceSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
169 DataValue *result,
char **errMsg);
170 static int getSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
171 DataValue *result,
char **errMsg);
172 static int validNumberMS(WindowInfo *window, DataValue *argList,
int nArgs,
173 DataValue *result,
char **errMsg);
174 static int replaceInStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
175 DataValue *result,
char **errMsg);
176 static int replaceSubstringMS(WindowInfo *window, DataValue *argList,
int nArgs,
177 DataValue *result,
char **errMsg);
178 static int readFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
179 DataValue *result,
char **errMsg);
180 static int writeFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
181 DataValue *result,
char **errMsg);
182 static int appendFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
183 DataValue *result,
char **errMsg);
184 static int writeOrAppendFile(
int append, WindowInfo *window,
185 DataValue *argList,
int nArgs, DataValue *result,
char **errMsg);
186 static int substringMS(WindowInfo *window, DataValue *argList,
int nArgs,
187 DataValue *result,
char **errMsg);
188 static int toupperMS(WindowInfo *window, DataValue *argList,
int nArgs,
189 DataValue *result,
char **errMsg);
190 static int tolowerMS(WindowInfo *window, DataValue *argList,
int nArgs,
191 DataValue *result,
char **errMsg);
192 static int stringToClipboardMS(WindowInfo *window, DataValue *argList,
int nArgs,
193 DataValue *result,
char **errMsg);
194 static int clipboardToStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
195 DataValue *result,
char **errMsg);
196 static int searchMS(WindowInfo *window, DataValue *argList,
int nArgs,
197 DataValue *result,
char **errMsg);
198 static int searchStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
199 DataValue *result,
char **errMsg);
200 static int setCursorPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
201 DataValue *result,
char **errMsg);
202 static int beepMS(WindowInfo *window, DataValue *argList,
int nArgs,
203 DataValue *result,
char **errMsg);
204 static int selectMS(WindowInfo *window, DataValue *argList,
int nArgs,
205 DataValue *result,
char **errMsg);
206 static int selectRectangleMS(WindowInfo *window, DataValue *argList,
int nArgs,
207 DataValue *result,
char **errMsg);
208 static int tPrintMS(WindowInfo *window, DataValue *argList,
int nArgs,
209 DataValue *result,
char **errMsg);
210 static int getenvMS(WindowInfo *window, DataValue *argList,
int nArgs,
211 DataValue *result,
char **errMsg);
212 static int shellCmdMS(WindowInfo *window, DataValue *argList,
int nArgs,
213 DataValue *result,
char **errMsg);
214 static int dialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
215 DataValue *result,
char **errMsg);
216 static void dialogBtnCB(Widget w, XtPointer clientData, XtPointer callData);
217 static void dialogCloseCB(Widget w, XtPointer clientData, XtPointer callData);
218 #ifdef LESSTIF_VERSION
219 static void dialogEscCB(Widget w, XtPointer clientData, XEvent *event,
220 Boolean *cont);
221 #endif
222 static int stringDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
223 DataValue *result,
char **errMsg);
224 static void stringDialogBtnCB(Widget w, XtPointer clientData,
225 XtPointer callData);
226 static void stringDialogCloseCB(Widget w, XtPointer clientData,
227 XtPointer callData);
228 #ifdef LESSTIF_VERSION
229 static void stringDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
230 Boolean *cont);
231 #endif
232 static int calltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
233 DataValue *result,
char **errMsg);
234 static int killCalltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
235 DataValue *result,
char **errMsg);
236
237 static int listDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
238 DataValue *result,
char **errMsg);
239 static void listDialogBtnCB(Widget w, XtPointer clientData,
240 XtPointer callData);
241 static void listDialogCloseCB(Widget w, XtPointer clientData,
242 XtPointer callData);
243
244 #ifdef LESSTIF_VERSION
245 static void listDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
246 Boolean *cont);
247 #endif
248 static int stringCompareMS(WindowInfo *window, DataValue *argList,
int nArgs,
249 DataValue *result,
char **errMsg);
250 static int splitMS(WindowInfo *window, DataValue *argList,
int nArgs,
251 DataValue *result,
char **errMsg);
252
253
254
255
256 static int cursorMV(WindowInfo *window, DataValue *argList,
int nArgs,
257 DataValue *result,
char **errMsg);
258 static int lineMV(WindowInfo *window, DataValue *argList,
int nArgs,
259 DataValue *result,
char **errMsg);
260 static int columnMV(WindowInfo *window, DataValue *argList,
int nArgs,
261 DataValue *result,
char **errMsg);
262 static int fileNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
263 DataValue *result,
char **errMsg);
264 static int filePathMV(WindowInfo *window, DataValue *argList,
int nArgs,
265 DataValue *result,
char **errMsg);
266 static int lengthMV(WindowInfo *window, DataValue *argList,
int nArgs,
267 DataValue *result,
char **errMsg);
268 static int selectionStartMV(WindowInfo *window, DataValue *argList,
int nArgs,
269 DataValue *result,
char **errMsg);
270 static int selectionEndMV(WindowInfo *window, DataValue *argList,
int nArgs,
271 DataValue *result,
char **errMsg);
272 static int selectionLeftMV(WindowInfo *window, DataValue *argList,
int nArgs,
273 DataValue *result,
char **errMsg);
274 static int selectionRightMV(WindowInfo *window, DataValue *argList,
int nArgs,
275 DataValue *result,
char **errMsg);
276 static int statisticsLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
277 DataValue *result,
char **errMsg);
278 static int incSearchLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
279 DataValue *result,
char **errMsg);
280 static int showLineNumbersMV(WindowInfo *window, DataValue *argList,
int nArgs,
281 DataValue *result,
char **errMsg);
282 static int autoIndentMV(WindowInfo *window, DataValue *argList,
int nArgs,
283 DataValue *result,
char **errMsg);
284 static int wrapTextMV(WindowInfo *window, DataValue *argList,
int nArgs,
285 DataValue *result,
char **errMsg);
286 static int highlightSyntaxMV(WindowInfo *window, DataValue *argList,
int nArgs,
287 DataValue *result,
char **errMsg);
288 static int makeBackupCopyMV(WindowInfo *window, DataValue *argList,
int nArgs,
289 DataValue *result,
char **errMsg);
290 static int incBackupMV(WindowInfo *window, DataValue *argList,
int nArgs,
291 DataValue *result,
char **errMsg);
292 static int showMatchingMV(WindowInfo *window, DataValue *argList,
int nArgs,
293 DataValue *result,
char **errMsg);
294 static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList,
int nArgs,
295 DataValue *result,
char **errMsg);
296 static int overTypeModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
297 DataValue *result,
char **errMsg);
298 static int readOnlyMV(WindowInfo *window, DataValue *argList,
int nArgs,
299 DataValue *result,
char **errMsg);
300 static int lockedMV(WindowInfo *window, DataValue *argList,
int nArgs,
301 DataValue *result,
char **errMsg);
302 static int fileFormatMV(WindowInfo *window, DataValue *argList,
int nArgs,
303 DataValue *result,
char **errMsg);
304 static int fontNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
305 DataValue *result,
char **errMsg);
306 static int fontNameItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
307 DataValue *result,
char **errMsg);
308 static int fontNameBoldMV(WindowInfo *window, DataValue *argList,
int nArgs,
309 DataValue *result,
char **errMsg);
310 static int fontNameBoldItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
311 DataValue *result,
char **errMsg);
312 static int subscriptSepMV(WindowInfo *window, DataValue *argList,
int nArgs,
313 DataValue *result,
char **errMsg);
314 static int minFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
315 DataValue *result,
char **errMsg);
316 static int maxFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
317 DataValue *result,
char **errMsg);
318 static int wrapMarginMV(WindowInfo *window, DataValue *argList,
int nArgs,
319 DataValue *result,
char **errMsg);
320 static int topLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
321 DataValue *result,
char **errMsg);
322 static int numDisplayLinesMV(WindowInfo *window, DataValue *argList,
int nArgs,
323 DataValue *result,
char **errMsg);
324 static int displayWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
325 DataValue *result,
char **errMsg);
326 static int activePaneMV(WindowInfo *window, DataValue *argList,
int nArgs,
327 DataValue *result,
char **errMsg);
328 static int nPanesMV(WindowInfo *window, DataValue *argList,
int nArgs,
329 DataValue *result,
char **errMsg);
330 static int emptyArrayMV(WindowInfo *window, DataValue *argList,
int nArgs,
331 DataValue *result,
char **errMsg);
332 static int serverNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
333 DataValue *result,
char **errMsg);
334 static int tabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
335 DataValue *result,
char **errMsg);
336 static int emTabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
337 DataValue *result,
char **errMsg);
338 static int useTabsMV(WindowInfo *window, DataValue *argList,
int nArgs,
339 DataValue *result,
char **errMsg);
340 static int modifiedMV(WindowInfo *window, DataValue *argList,
int nArgs,
341 DataValue *result,
char **errMsg);
342 static int languageModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
343 DataValue *result,
char **errMsg);
344 static int calltipIDMV(WindowInfo *window, DataValue *argList,
int nArgs,
345 DataValue *result,
char **errMsg);
346 static int readSearchArgs(DataValue *argList,
int nArgs,
int*searchDirection,
347 int *searchType,
int *wrap,
char **errMsg);
348 static int wrongNArgsErr(
char **errMsg);
349 static int tooFewArgsErr(
char **errMsg);
350 static int readIntArg(DataValue dv,
int *result,
char **errMsg);
351 static int readStringArg(DataValue dv,
char **result,
char *stringStorage,
352 char **errMsg);
353
354
355
356
357 static int rangesetListMV(WindowInfo *window, DataValue *argList,
358 int nArgs, DataValue *result,
char **errMsg);
359 static int versionMV(WindowInfo* window, DataValue* argList,
int nArgs,
360 DataValue* result,
char** errMsg);
361 static int rangesetCreateMS(WindowInfo *window, DataValue *argList,
int nArgs,
362 DataValue *result,
char **errMsg);
363 static int rangesetDestroyMS(WindowInfo *window, DataValue *argList,
int nArgs,
364 DataValue *result,
char **errMsg);
365 static int rangesetGetByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
366 DataValue *result,
char **errMsg);
367 static int rangesetAddMS(WindowInfo *window, DataValue *argList,
int nArgs,
368 DataValue *result,
char **errMsg);
369 static int rangesetSubtractMS(WindowInfo *window, DataValue *argList,
int nArgs,
370 DataValue *result,
char **errMsg);
371 static int rangesetInvertMS(WindowInfo *window, DataValue *argList,
int nArgs,
372 DataValue *result,
char **errMsg);
373 static int rangesetInfoMS(WindowInfo *window, DataValue *argList,
int nArgs,
374 DataValue *result,
char **errMsg);
375 static int rangesetRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
376 DataValue *result,
char **errMsg);
377 static int rangesetIncludesPosMS(WindowInfo *window, DataValue *argList,
378 int nArgs, DataValue *result,
char **errMsg);
379 static int rangesetSetColorMS(WindowInfo *window, DataValue *argList,
380 int nArgs, DataValue *result,
char **errMsg);
381 static int rangesetSetNameMS(WindowInfo *window, DataValue *argList,
382 int nArgs, DataValue *result,
char **errMsg);
383 static int rangesetSetModeMS(WindowInfo *window, DataValue *argList,
384 int nArgs, DataValue *result,
char **errMsg);
385
386 static int fillPatternResult(DataValue *result,
char **errMsg, WindowInfo *window,
387 char *patternName, Boolean preallocatedPatternName, Boolean includeName,
388 char *styleName,
int bufferPos);
389 static int getPatternByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
390 DataValue *result,
char **errMsg);
391 static int getPatternAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
392 DataValue *result,
char **errMsg);
393
394 static int fillStyleResult(DataValue *result,
char **errMsg,
395 WindowInfo *window,
char *styleName, Boolean preallocatedStyleName,
396 Boolean includeName,
int patCode,
int bufferPos);
397 static int getStyleByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
398 DataValue *result,
char **errMsg);
399 static int getStyleAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
400 DataValue *result,
char **errMsg);
401 static int filenameDialogMS(WindowInfo* window, DataValue* argList,
int nArgs,
402 DataValue* result,
char** errMsg);
403
404
405 static BuiltInSubr MacroSubrs[] = {lengthMS, getRangeMS, tPrintMS,
406 dialogMS, stringDialogMS, replaceRangeMS, replaceSelectionMS,
407 setCursorPosMS, getCharacterMS, minMS, maxMS, searchMS,
408 searchStringMS, substringMS, replaceSubstringMS, readFileMS,
409 writeFileMS, appendFileMS, beepMS, getSelectionMS, validNumberMS,
410 replaceInStringMS, selectMS, selectRectangleMS, focusWindowMS,
411 shellCmdMS, stringToClipboardMS, clipboardToStringMS, toupperMS,
412 tolowerMS, listDialogMS, getenvMS,
413 stringCompareMS, splitMS, calltipMS, killCalltipMS,
414
415 rangesetCreateMS, rangesetDestroyMS,
416 rangesetAddMS, rangesetSubtractMS, rangesetInvertMS,
417 rangesetInfoMS, rangesetRangeMS, rangesetIncludesPosMS,
418 rangesetSetColorMS, rangesetSetNameMS, rangesetSetModeMS,
419 rangesetGetByNameMS,
420 getPatternByNameMS, getPatternAtPosMS,
421 getStyleByNameMS, getStyleAtPosMS, filenameDialogMS
422 };
423 #define N_MACRO_SUBRS (
sizeof MacroSubrs/
sizeof *MacroSubrs)
424 static const char *MacroSubrNames[
N_MACRO_SUBRS] = {
"length",
"get_range",
"t_print",
425 "dialog",
"string_dialog",
"replace_range",
"replace_selection",
426 "set_cursor_pos",
"get_character",
"min",
"max",
"search",
427 "search_string",
"substring",
"replace_substring",
"read_file",
428 "write_file",
"append_file",
"beep",
"get_selection",
"valid_number",
429 "replace_in_string",
"select",
"select_rectangle",
"focus_window",
430 "shell_command",
"string_to_clipboard",
"clipboard_to_string",
431 "toupper",
"tolower",
"list_dialog",
"getenv",
432 "string_compare",
"split",
"calltip",
"kill_calltip",
433
434 "rangeset_create",
"rangeset_destroy",
435 "rangeset_add",
"rangeset_subtract",
"rangeset_invert",
436 "rangeset_info",
"rangeset_range",
"rangeset_includes",
437 "rangeset_set_color",
"rangeset_set_name",
"rangeset_set_mode",
438 "rangeset_get_by_name",
439 "get_pattern_by_name",
"get_pattern_at_pos",
440 "get_style_by_name",
"get_style_at_pos",
"filename_dialog"
441 };
442 static BuiltInSubr SpecialVars[] = {cursorMV, lineMV, columnMV,
443 fileNameMV, filePathMV, lengthMV, selectionStartMV, selectionEndMV,
444 selectionLeftMV, selectionRightMV, wrapMarginMV, tabDistMV,
445 emTabDistMV, useTabsMV, languageModeMV, modifiedMV,
446 statisticsLineMV, incSearchLineMV, showLineNumbersMV,
447 autoIndentMV, wrapTextMV, highlightSyntaxMV,
448 makeBackupCopyMV, incBackupMV, showMatchingMV, matchSyntaxBasedMV,
449 overTypeModeMV, readOnlyMV, lockedMV, fileFormatMV,
450 fontNameMV, fontNameItalicMV,
451 fontNameBoldMV, fontNameBoldItalicMV, subscriptSepMV,
452 minFontWidthMV, maxFontWidthMV, topLineMV, numDisplayLinesMV,
453 displayWidthMV, activePaneMV, nPanesMV, emptyArrayMV,
454 serverNameMV, calltipIDMV,
455
456 rangesetListMV, versionMV
457 };
458 #define N_SPECIAL_VARS (
sizeof SpecialVars/
sizeof *SpecialVars)
459 static const char *SpecialVarNames[
N_SPECIAL_VARS] = {
"$cursor",
"$line",
"$column",
460 "$file_name",
"$file_path",
"$text_length",
"$selection_start",
461 "$selection_end",
"$selection_left",
"$selection_right",
462 "$wrap_margin",
"$tab_dist",
"$em_tab_dist",
"$use_tabs",
463 "$language_mode",
"$modified",
464 "$statistics_line",
"$incremental_search_line",
"$show_line_numbers",
465 "$auto_indent",
"$wrap_text",
"$highlight_syntax",
466 "$make_backup_copy",
"$incremental_backup",
"$show_matching",
"$match_syntax_based",
467 "$overtype_mode",
"$read_only",
"$locked",
"$file_format",
468 "$font_name",
"$font_name_italic",
469 "$font_name_bold",
"$font_name_bold_italic",
"$sub_sep",
470 "$min_font_width",
"$max_font_width",
"$top_line",
"$n_display_lines",
471 "$display_width",
"$active_pane",
"$n_panes",
"$empty_array",
472 "$server_name",
"$calltip_ID",
473
474 "$rangeset_list",
"$VERSION"
475 };
476
477
478 #define N_RETURN_GLOBALS 5
479 enum retGlobalSyms {
STRING_DIALOG_BUTTON,
SEARCH_END,
READ_STATUS,
480 SHELL_CMD_STATUS,
LIST_DIALOG_BUTTON};
481 static const char *ReturnGlobalNames[
N_RETURN_GLOBALS] = {
"$string_dialog_button",
482 "$search_end",
"$read_status",
"$shell_cmd_status",
483 "$list_dialog_button"};
484 static Symbol *ReturnGlobals[
N_RETURN_GLOBALS];
485
486
487 static char* IgnoredActions[] = {
"focusIn",
"focusOut"};
488
489
490
491 static const char* MouseActions[] = {
"grab_focus",
"extend_adjust",
"extend_start",
492 "extend_end",
"secondary_or_drag_adjust",
"secondary_adjust",
493 "secondary_or_drag_start",
"secondary_start",
"move_destination",
494 "move_to",
"move_to_or_end_drag",
"copy_to",
"copy_to_or_end_drag",
495 "exchange",
"process_bdrag",
"mouse_pan"};
496
497
498
499 static const char* RedundantActions[] = {
"open_dialog",
"save_as_dialog",
500 "revert_to_saved_dialog",
"include_file_dialog",
"load_macro_file_dialog",
501 "load_tags_file_dialog",
"find_dialog",
"replace_dialog",
502 "goto_line_number_dialog",
"mark_dialog",
"goto_mark_dialog",
503 "control_code_dialog",
"filter_selection_dialog",
"execute_command_dialog",
504 "repeat_dialog",
"start_incremental_find"};
505
506
507 static char *LastCommand =
NULL;
508
509
510 static char *ReplayMacro =
NULL;
511
512
513 static textBuffer *MacroRecordBuf =
NULL;
514
515
516 static XtActionHookId MacroRecordActionHook =
0;
517
518
519 static WindowInfo *MacroRecordWindow =
NULL;
520
521
522 static char ReplaceChars[] =
"\\\"ntbrfav";
523 static char EscapeChars[] =
"\\\"\n\t\b\r\f\a\v";
524
525
526
527
528
529 void RegisterMacroSubroutines(
void)
530 {
531 static DataValue subrPtr = {
NO_TAG, {
0}}, noValue = {
NO_TAG, {
0}};
532 unsigned i;
533
534
535
536 for (i=
0; i<
N_MACRO_SUBRS; i++) {
537 subrPtr.val.subr = MacroSubrs[i];
538 InstallSymbol(MacroSubrNames[i],
C_FUNCTION_SYM, subrPtr);
539 }
540 for (i=
0; i<
N_SPECIAL_VARS; i++) {
541 subrPtr.val.subr = SpecialVars[i];
542 InstallSymbol(SpecialVarNames[i],
PROC_VALUE_SYM, subrPtr);
543 }
544
545
546
547 for (i=
0; i<
N_RETURN_GLOBALS; i++)
548 ReturnGlobals[i] = InstallSymbol(ReturnGlobalNames[i],
GLOBAL_SYM,
549 noValue);
550 }
551
552 #define MAX_LEARN_MSG_LEN ((
2 *
MAX_ACCEL_LEN) +
60)
553 void BeginLearn(WindowInfo *window)
554 {
555 WindowInfo *win;
556 XmString s;
557 XmString xmFinish;
558 XmString xmCancel;
559 char *cFinish;
560 char *cCancel;
561 char message[
MAX_LEARN_MSG_LEN];
562
563
564 if (MacroRecordActionHook !=
0)
565 return;
566
567
568 for (win=WindowList; win!=
NULL; win=win->next) {
569 if (!IsTopDocument(win))
570 continue;
571 XtSetSensitive(win->learnItem, False);
572 }
573 SetSensitive(window, window->finishLearnItem, True);
574 XtVaSetValues(window->cancelMacroItem, XmNlabelString,
575 s=XmStringCreateSimple(
"Cancel Learn"),
NULL);
576 XmStringFree(s);
577 SetSensitive(window, window->cancelMacroItem, True);
578
579
580 MacroRecordWindow = window;
581
582
583 MacroRecordBuf = BufCreate();
584
585
586 MacroRecordActionHook =
587 XtAppAddActionHook(XtWidgetToApplicationContext(window->shell),
588 learnActionHook, window);
589
590
591 XtVaGetValues(window->finishLearnItem, XmNacceleratorText, &xmFinish,
NULL);
592 XtVaGetValues(window->cancelMacroItem, XmNacceleratorText, &xmCancel,
NULL);
593
594
595 cFinish = GetXmStringText(xmFinish);
596 cCancel = GetXmStringText(xmCancel);
597
598
599 XmStringFree(xmFinish);
600 XmStringFree(xmCancel);
601
602
603 if (cFinish[
0] ==
'\0') {
604 if (cCancel[
0] ==
'\0') {
605 strncpy(message,
"Learn Mode -- Use menu to finish or cancel",
606 MAX_LEARN_MSG_LEN);
607 message[
MAX_LEARN_MSG_LEN -
1] =
'\0';
608 }
609 else {
610 sprintf(message,
611 "Learn Mode -- Use menu to finish, press %s to cancel",
612 cCancel);
613 }
614 }
615 else {
616 if (cCancel[
0] ==
'\0') {
617 sprintf(message,
618 "Learn Mode -- Press %s to finish, use menu to cancel",
619 cFinish);
620
621 }
622 else {
623 sprintf(message,
624 "Learn Mode -- Press %s to finish, %s to cancel",
625 cFinish,
626 cCancel);
627 }
628 }
629
630
631 NEditFree(cFinish);
632 NEditFree(cCancel);
633
634
635 SetModeMessage(window, message);
636 }
637
638 void AddLastCommandActionHook(XtAppContext context)
639 {
640 XtAppAddActionHook(context, lastActionHook,
NULL);
641 }
642
643 void FinishLearn(
void)
644 {
645 WindowInfo *win;
646
647
648 if (MacroRecordActionHook ==
0)
649 return;
650
651
652 XtRemoveActionHook(MacroRecordActionHook);
653 MacroRecordActionHook =
0;
654
655
656 NEditFree(ReplayMacro);
657
658
659 ReplayMacro = BufGetAll(MacroRecordBuf);
660
661
662 BufFree(MacroRecordBuf);
663
664
665 for (win=WindowList; win!=
NULL; win=win->next) {
666 if (!IsTopDocument(win))
667 continue;
668 XtSetSensitive(win->learnItem, True);
669 }
670 if (IsTopDocument(MacroRecordWindow)) {
671 XtSetSensitive(MacroRecordWindow->finishLearnItem, False);
672 XtSetSensitive(MacroRecordWindow->cancelMacroItem, False);
673 }
674
675
676 for (win=WindowList; win!=
NULL; win=win->next) {
677 if (!IsTopDocument(win))
678 continue;
679 XtSetSensitive(win->replayItem, True);
680 }
681 DimPasteReplayBtns(True);
682
683
684 ClearModeMessage(MacroRecordWindow);
685 }
686
687
688
689
690 void CancelMacroOrLearn(WindowInfo *window)
691 {
692 if (MacroRecordActionHook !=
0)
693 cancelLearn();
694 else if (window->macroCmdData !=
NULL)
695 AbortMacroCommand(window);
696 }
697
698 static void cancelLearn(
void)
699 {
700 WindowInfo *win;
701
702
703 if (MacroRecordActionHook ==
0)
704 return;
705
706
707 XtRemoveActionHook(MacroRecordActionHook);
708 MacroRecordActionHook =
0;
709
710
711 BufFree(MacroRecordBuf);
712
713
714 for (win=WindowList; win!=
NULL; win=win->next) {
715 if (!IsTopDocument(win))
716 continue;
717 XtSetSensitive(win->learnItem, True);
718 }
719 if (IsTopDocument(MacroRecordWindow)) {
720 XtSetSensitive(MacroRecordWindow->finishLearnItem, False);
721 XtSetSensitive(MacroRecordWindow->cancelMacroItem, False);
722 }
723
724
725 ClearModeMessage(MacroRecordWindow);
726 }
727
728
729
730
731 void Replay(WindowInfo *window)
732 {
733 Program *prog;
734 char *errMsg, *stoppedAt;
735
736
737
738 if (ReplayMacro !=
NULL &&
739 ReplayMacro[
0] !=
0 &&
740 window->macroCmdData ==
NULL) {
741
742
743 prog = ParseMacro(ReplayMacro, &errMsg, &stoppedAt);
744 if (prog ==
NULL) {
745 fprintf(stderr,
746 "XNEdit internal error, learn/replay macro syntax error: %s\n",
747 errMsg);
748 return;
749 }
750
751
752 runMacro(window, prog);
753 }
754 }
755
756
757
758
759 void ReadMacroInitFile(WindowInfo *window)
760 {
761 const char* autoloadName = GetRCFileName(
AUTOLOAD_NM);
762 static int initFileLoaded = False;
763
764
765
766 if (autoloadName !=
NULL && !initFileLoaded)
767 {
768 ReadMacroFile(window, autoloadName, False);
769 initFileLoaded = True;
770 }
771 }
772
773
774
775
776
777 int ReadMacroFile(WindowInfo *window,
const char *fileName,
int warnNotExist)
778 {
779 int result;
780 char *fileString;
781
782
783
784
785 fileString = ReadAnyTextFile(fileName, True);
786 if (fileString ==
NULL){
787 if (errno !=
ENOENT || warnNotExist)
788 {
789 DialogF(
DF_ERR, window->shell,
1,
"Read Macro",
790 "Error reading macro file %s: %s",
"OK", fileName,
791 strerror(errno));
792 }
793 return False;
794 }
795
796
797 result = readCheckMacroString(window->shell, fileString, window, fileName,
798 NULL);
799 NEditFree(fileString);
800 return result;
801 }
802
803
804
805
806
807 int ReadMacroString(WindowInfo *window,
char *string,
const char *errIn)
808 {
809 return readCheckMacroString(window->shell, string, window, errIn,
NULL);
810 }
811
812
813
814
815
816
817 int CheckMacroString(Widget dialogParent,
char *string,
const char *errIn,
818 char **errPos)
819 {
820 return readCheckMacroString(dialogParent, string,
NULL, errIn, errPos);
821 }
822
823
824
825
826
827
828
829
830
831 static int readCheckMacroString(Widget dialogParent,
char *string,
832 WindowInfo *runWindow,
const char *errIn,
char **errPos)
833 {
834 char *stoppedAt, *inPtr, *namePtr, *errMsg;
835 char subrName[
MAX_SYM_LEN];
836 Program *prog;
837 Symbol *sym;
838 DataValue subrPtr;
839 Stack* progStack = (Stack*) NEditMalloc(
sizeof(Stack));
840 progStack->top =
NULL;
841 progStack->size =
0;
842
843 inPtr = string;
844 while (*inPtr !=
'\0') {
845
846
847 while (*inPtr==
' ' || *inPtr==
'\t' || *inPtr==
'\n'|| *inPtr==
'#') {
848 if (*inPtr ==
'#')
849 while (*inPtr !=
'\n' && *inPtr !=
'\0') inPtr++;
850 else
851 inPtr++;
852 }
853 if (*inPtr ==
'\0')
854 break;
855
856
857 if (!strncmp(inPtr,
"define",
6) && (inPtr[
6]==
' ' || inPtr[
6]==
'\t')) {
858 inPtr +=
6;
859 inPtr += strspn(inPtr,
" \t\n");
860 namePtr = subrName;
861 while ((namePtr < &subrName[
MAX_SYM_LEN -
1])
862 && (isalnum((
unsigned char)*inPtr) || *inPtr ==
'_')) {
863 *namePtr++ = *inPtr++;
864 }
865 *namePtr =
'\0';
866 if (isalnum((
unsigned char)*inPtr) || *inPtr ==
'_') {
867 return ParseError(dialogParent, string, inPtr, errIn,
868 "subroutine name too long");
869 }
870 inPtr += strspn(inPtr,
" \t\n");
871 if (*inPtr !=
'{') {
872 if (errPos !=
NULL) *errPos = stoppedAt;
873 return ParseError(dialogParent, string, inPtr,
874 errIn,
"expected ''{''");
875 }
876 prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
877 if (prog ==
NULL) {
878 if (errPos !=
NULL) *errPos = stoppedAt;
879 return ParseError(dialogParent, string, stoppedAt,
880 errIn, errMsg);
881 }
882 if (runWindow !=
NULL) {
883 sym = LookupSymbol(subrName);
884 if (sym ==
NULL) {
885 subrPtr.val.prog = prog;
886 subrPtr.tag =
NO_TAG;
887 sym = InstallSymbol(subrName,
MACRO_FUNCTION_SYM, subrPtr);
888 }
else {
889 if (sym->type ==
MACRO_FUNCTION_SYM)
890 FreeProgram(sym->value.val.prog);
891 else
892 sym->type =
MACRO_FUNCTION_SYM;
893 sym->value.val.prog = prog;
894 }
895 }
896 inPtr = stoppedAt;
897
898
899
900
901
902
903 }
else {
904 prog = ParseMacro(inPtr, &errMsg, &stoppedAt);
905 if (prog ==
NULL) {
906 if (errPos !=
NULL) {
907 *errPos = stoppedAt;
908 }
909
910 return ParseError(dialogParent, string, stoppedAt,
911 errIn, errMsg);
912 }
913
914 if (runWindow !=
NULL) {
915 XEvent nextEvent;
916 if (runWindow->macroCmdData ==
NULL) {
917 runMacro(runWindow, prog);
918 while (runWindow->macroCmdData !=
NULL) {
919 XtAppNextEvent(XtWidgetToApplicationContext(
920 runWindow->shell), &nextEvent);
921 ServerDispatchEvent(&nextEvent);
922 }
923 }
else {
924
925
926
927
928
929
930
931
932
933
934 Push(progStack, (
void*) prog);
935 }
936 }
937 inPtr = stoppedAt;
938 }
939 }
940
941
942 while (
NULL != (prog = (Program*) Pop(progStack))) {
943 RunMacroAsSubrCall(prog);
944 }
945
946
947 NEditFree(progStack);
948
949 return True;
950 }
951
952
953
954
955
956
957 static void runMacro(WindowInfo *window, Program *prog)
958 {
959 DataValue result;
960 char *errMsg;
961 int stat;
962 macroCmdInfo *cmdData;
963 XmString s;
964
965
966
967
968 if (window->macroCmdData !=
NULL) {
969 RunMacroAsSubrCall(prog);
970 return;
971 }
972
973
974 BeginWait(window->shell);
975
976
977 XtVaSetValues(window->cancelMacroItem, XmNlabelString,
978 s=XmStringCreateSimple(
"Cancel Macro"),
NULL);
979 XmStringFree(s);
980 SetSensitive(window, window->cancelMacroItem, True);
981
982
983
984 cmdData = (macroCmdInfo *)NEditMalloc(
sizeof(macroCmdInfo));
985 window->macroCmdData = cmdData;
986 cmdData->bannerIsUp = False;
987 cmdData->closeOnCompletion = False;
988 cmdData->program = prog;
989 cmdData->context =
NULL;
990 cmdData->continueWorkProcID =
0;
991 cmdData->dialog =
NULL;
992
993
994 cmdData->bannerTimeoutID = XtAppAddTimeOut(
995 XtWidgetToApplicationContext(window->shell),
BANNER_WAIT_TIME,
996 bannerTimeoutProc, window);
997
998
999 stat = ExecuteMacro(window, prog,
0,
NULL, &result, &cmdData->context,
1000 &errMsg);
1001
1002 if (stat ==
MACRO_ERROR)
1003 {
1004 finishMacroCmdExecution(window);
1005 DialogF(
DF_ERR, window->shell,
1,
"Macro Error",
1006 "Error executing macro: %s",
"OK", errMsg);
1007 return;
1008 }
1009
1010 if (stat ==
MACRO_DONE) {
1011 finishMacroCmdExecution(window);
1012 return;
1013 }
1014 if (stat ==
MACRO_TIME_LIMIT) {
1015 ResumeMacroExecution(window);
1016 return;
1017 }
1018
1019 }
1020
1021
1022
1023
1024
1025
1026
1027
1028 void ResumeMacroExecution(WindowInfo *window)
1029 {
1030 macroCmdInfo *cmdData = (macroCmdInfo *)window->macroCmdData;
1031
1032 if (cmdData !=
NULL)
1033 cmdData->continueWorkProcID = XtAppAddWorkProc(
1034 XtWidgetToApplicationContext(window->shell),
1035 continueWorkProc, window);
1036 }
1037
1038
1039
1040
1041 void AbortMacroCommand(WindowInfo *window)
1042 {
1043 if (window->macroCmdData ==
NULL)
1044 return;
1045
1046 if (window->macroBlocking)
1047 return;
1048
1049
1050
1051
1052
1053 if (window->shellCmdData !=
NULL)
1054 AbortShellCommand(window);
1055
1056
1057 FreeRestartData(((macroCmdInfo *)window->macroCmdData)->context);
1058
1059
1060 finishMacroCmdExecution(window);
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 int MacroWindowCloseActions(WindowInfo *window)
1074 {
1075 macroCmdInfo *mcd, *cmdData = window->macroCmdData;
1076 WindowInfo *w;
1077
1078 if (MacroRecordActionHook !=
0 && MacroRecordWindow == window) {
1079 FinishLearn();
1080 }
1081
1082
1083
1084
1085 if (cmdData ==
NULL) {
1086 for (w=WindowList; w!=
NULL; w=w->next) {
1087 mcd = (macroCmdInfo *)w->macroCmdData;
1088 if (w == MacroRunWindow() && MacroFocusWindow() == window)
1089 SetMacroFocusWindow(MacroRunWindow());
1090 else if (mcd !=
NULL && mcd->context->focusWindow == window)
1091 mcd->context->focusWindow = mcd->context->runWindow;
1092 }
1093 return True;
1094 }
1095
1096
1097
1098
1099
1100 if (window == MacroRunWindow()) {
1101 cmdData->closeOnCompletion = True;
1102 return False;
1103 }
1104
1105
1106 FreeRestartData(cmdData->context);
1107
1108
1109 finishMacroCmdExecution(window);
1110 return True;
1111 }
1112
1113
1114
1115
1116
1117 static void finishMacroCmdExecution(WindowInfo *window)
1118 {
1119 macroCmdInfo *cmdData = window->macroCmdData;
1120 int closeOnCompletion = cmdData->closeOnCompletion;
1121 XmString s;
1122 XClientMessageEvent event;
1123
1124
1125 if (cmdData->bannerTimeoutID !=
0)
1126 XtRemoveTimeOut(cmdData->bannerTimeoutID);
1127 if (cmdData->continueWorkProcID !=
0)
1128 XtRemoveWorkProc(cmdData->continueWorkProcID);
1129
1130
1131 EndWait(window->shell);
1132 XtVaSetValues(window->cancelMacroItem, XmNlabelString,
1133 s=XmStringCreateSimple(
"Cancel Learn"),
NULL);
1134 XmStringFree(s);
1135 SetSensitive(window, window->cancelMacroItem, False);
1136 if (cmdData->bannerIsUp)
1137 ClearModeMessage(window);
1138
1139
1140 if (cmdData->dialog !=
NULL)
1141 XtDestroyWidget(XtParent(cmdData->dialog));
1142
1143
1144 FreeProgram(cmdData->program);
1145 NEditFree(cmdData);
1146 window->macroCmdData =
NULL;
1147
1148
1149
1150
1151 if (closeOnCompletion && !window->filenameSet && !window->fileChanged) {
1152 CloseWindow(window);
1153 window =
NULL;
1154 }
1155
1156
1157 SafeGC();
1158
1159
1160
1161
1162
1163 if (!closeOnCompletion) {
1164 event.format =
8;
1165 event.type = ClientMessage;
1166 XSendEvent(XtDisplay(window->shell), XtWindow(window->shell), False,
1167 NoEventMask, (XEvent *)&event);
1168 }
1169 }
1170
1171
1172
1173
1174
1175
1176
1177
1178 void SafeGC(
void)
1179 {
1180 WindowInfo *win;
1181
1182 for (win=WindowList; win!=
NULL; win=win->next)
1183 if (win->macroCmdData !=
NULL || InSmartIndentMacros(win))
1184 return;
1185 GarbageCollectStrings();
1186 }
1187
1188
1189
1190
1191
1192
1193 void DoMacro(WindowInfo *window,
const char *macro,
const char *errInName)
1194 {
1195 Program *prog;
1196 char *errMsg, *stoppedAt, *tMacro;
1197 int macroLen;
1198
1199
1200
1201 macroLen = strlen(macro);
1202 tMacro = (
char*)NEditMalloc(strlen(macro)+
2);
1203 strncpy(tMacro, macro, macroLen);
1204 tMacro[macroLen] =
'\n';
1205 tMacro[macroLen+
1] =
'\0';
1206
1207
1208 prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
1209 if (prog ==
NULL) {
1210 ParseError(window->shell, tMacro, stoppedAt, errInName, errMsg);
1211 NEditFree(tMacro);
1212 return;
1213 }
1214 NEditFree(tMacro);
1215
1216
1217 runMacro(window, prog);
1218 }
1219
1220
1221
1222
1223
1224
1225 char *GetReplayMacro(
void)
1226 {
1227 return ReplayMacro;
1228 }
1229
1230
1231
1232
1233 void RepeatDialog(WindowInfo *window)
1234 {
1235 Widget form, selBox, radioBox, timesForm;
1236 repeatDialog *rd;
1237 Arg selBoxArgs[
1];
1238 char *lastCmdLabel, *parenChar;
1239 XmString s1;
1240 int cmdNameLen;
1241
1242 if (LastCommand ==
NULL)
1243 {
1244 DialogF(
DF_WARN, window->shell,
1,
"Repeat Macro",
1245 "No previous commands or learn/\nreplay sequences to repeat",
1246 "OK");
1247 return;
1248 }
1249
1250
1251
1252 rd = (repeatDialog *)NEditMalloc(
sizeof(repeatDialog));
1253 rd->lastCommand = NEditStrdup(LastCommand);
1254
1255
1256
1257 parenChar = strchr(LastCommand,
'(');
1258 if (parenChar ==
NULL)
1259 return;
1260 cmdNameLen = parenChar-LastCommand;
1261 lastCmdLabel = (
char*)NEditMalloc(
16 + cmdNameLen);
1262 strcpy(lastCmdLabel,
"Last Command (");
1263 strncpy(&lastCmdLabel[
14], LastCommand, cmdNameLen);
1264 strcpy(&lastCmdLabel[
14 + cmdNameLen],
")");
1265
1266 XtSetArg(selBoxArgs[
0], XmNautoUnmanage, False);
1267 selBox = CreatePromptDialog(window->shell,
"repeat", selBoxArgs,
1);
1268 rd->shell = XtParent(selBox);
1269 XtAddCallback(rd->shell, XmNdestroyCallback, repeatDestroyCB, rd);
1270 XtAddCallback(selBox, XmNokCallback, repeatOKCB, rd);
1271 XtAddCallback(selBox, XmNapplyCallback, repeatApplyCB, rd);
1272 XtAddCallback(selBox, XmNcancelCallback, repeatCancelCB, rd);
1273 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
1274 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
1275 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
1276 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_APPLY_BUTTON));
1277 XtVaSetValues(XtParent(selBox), XmNtitle,
"Repeat Macro",
NULL);
1278 AddMotifCloseCallback(XtParent(selBox), repeatCancelCB, rd);
1279
1280 form = XtVaCreateManagedWidget(
"form", xmFormWidgetClass, selBox,
NULL);
1281
1282 radioBox = XtVaCreateManagedWidget(
"cmdSrc", xmRowColumnWidgetClass, form,
1283 XmNradioBehavior, True,
1284 XmNorientation, XmHORIZONTAL,
1285 XmNpacking, XmPACK_TIGHT,
1286 XmNtopAttachment, XmATTACH_FORM,
1287 XmNleftAttachment, XmATTACH_FORM,
NULL);
1288 rd->lastCmdToggle = XtVaCreateManagedWidget(
"lastCmdToggle",
1289 xmToggleButtonWidgetClass, radioBox, XmNset, True,
1290 XmNlabelString, s1=XmStringCreateSimple(lastCmdLabel),
1291 XmNmnemonic,
'C',
NULL);
1292 XmStringFree(s1);
1293 NEditFree(lastCmdLabel);
1294 XtVaCreateManagedWidget(
"learnReplayToggle",
1295 xmToggleButtonWidgetClass, radioBox, XmNset, False,
1296 XmNlabelString,
1297 s1=XmStringCreateSimple(
"Learn/Replay"),
1298 XmNmnemonic,
'L',
1299 XmNsensitive, ReplayMacro !=
NULL,
NULL);
1300 XmStringFree(s1);
1301
1302 timesForm = XtVaCreateManagedWidget(
"form", xmFormWidgetClass, form,
1303 XmNtopAttachment, XmATTACH_WIDGET,
1304 XmNtopWidget, radioBox,
1305 XmNtopOffset,
10,
1306 XmNleftAttachment, XmATTACH_FORM,
NULL);
1307 radioBox = XtVaCreateManagedWidget(
"method", xmRowColumnWidgetClass,
1308 timesForm,
1309 XmNradioBehavior, True,
1310 XmNorientation, XmHORIZONTAL,
1311 XmNpacking, XmPACK_TIGHT,
1312 XmNtopAttachment, XmATTACH_FORM,
1313 XmNbottomAttachment, XmATTACH_FORM,
1314 XmNleftAttachment, XmATTACH_FORM,
NULL);
1315 rd->inSelToggle = XtVaCreateManagedWidget(
"inSelToggle",
1316 xmToggleButtonWidgetClass, radioBox, XmNset, False,
1317 XmNlabelString, s1=XmStringCreateSimple(
"In Selection"),
1318 XmNmnemonic,
'I',
NULL);
1319 XmStringFree(s1);
1320 rd->toEndToggle = XtVaCreateManagedWidget(
"toEndToggle",
1321 xmToggleButtonWidgetClass, radioBox, XmNset, False,
1322 XmNlabelString, s1=XmStringCreateSimple(
"To End"),
1323 XmNmnemonic,
'T',
NULL);
1324 XmStringFree(s1);
1325 XtVaCreateManagedWidget(
"nTimesToggle",
1326 xmToggleButtonWidgetClass, radioBox, XmNset, True,
1327 XmNlabelString, s1=XmStringCreateSimple(
"N Times"),
1328 XmNmnemonic,
'N',
1329 XmNset, True,
NULL);
1330 XmStringFree(s1);
1331 rd->repeatText = XtVaCreateManagedWidget(
"repeatText", xmTextWidgetClass,
1332 timesForm,
1333 XmNcolumns,
5,
1334 XmNtopAttachment, XmATTACH_FORM,
1335 XmNbottomAttachment, XmATTACH_FORM,
1336 XmNleftAttachment, XmATTACH_WIDGET,
1337 XmNleftWidget, radioBox,
NULL);
1338 RemapDeleteKey(rd->repeatText);
1339
1340
1341 AddDialogMnemonicHandler(form,
FALSE);
1342
1343
1344 #if XmVersion >=
1002
1345 XtVaSetValues(form, XmNinitialFocus, timesForm,
NULL);
1346 XtVaSetValues(timesForm, XmNinitialFocus, rd->repeatText,
NULL);
1347 #endif
1348
1349
1350 rd->forWindow = window;
1351 ManageDialogCenteredOnPointer(selBox);
1352 }
1353
1354 static void repeatOKCB(Widget w, XtPointer clientData, XtPointer callData)
1355 {
1356 repeatDialog *rd = (repeatDialog *)clientData;
1357
1358 if (doRepeatDialogAction(rd, ((XmAnyCallbackStruct *)callData)->event))
1359 XtDestroyWidget(rd->shell);
1360 }
1361
1362
1363
1364
1365
1366 static void repeatApplyCB(Widget w, XtPointer clientData, XtPointer callData)
1367 {
1368 doRepeatDialogAction((repeatDialog *)clientData,
1369 ((XmAnyCallbackStruct *)callData)->event);
1370 }
1371
1372 static int doRepeatDialogAction(repeatDialog *rd, XEvent *event)
1373 {
1374 int nTimes;
1375 char nTimesStr[
TYPE_INT_STR_SIZE(
int)];
1376 char *params[
2];
1377
1378
1379 if (XmToggleButtonGetState(rd->inSelToggle))
1380 {
1381 if (!rd->forWindow->buffer->primary.selected)
1382 {
1383 DialogF(
DF_WARN, rd->shell,
1,
"Repeat Macro",
1384 "No selection in window to repeat within",
"OK");
1385 XmProcessTraversal(rd->inSelToggle, XmTRAVERSE_CURRENT);
1386 return False;
1387 }
1388 params[
0] =
"in_selection";
1389 }
else if (XmToggleButtonGetState(rd->toEndToggle))
1390 {
1391 params[
0] =
"to_end";
1392 }
else
1393 {
1394 if (GetIntTextWarn(rd->repeatText, &nTimes,
"number of times", True)
1395 !=
TEXT_READ_OK)
1396 {
1397 XmProcessTraversal(rd->repeatText, XmTRAVERSE_CURRENT);
1398 return False;
1399 }
1400 sprintf(nTimesStr,
"%d", nTimes);
1401 params[
0] = nTimesStr;
1402 }
1403
1404
1405 if (XmToggleButtonGetState(rd->lastCmdToggle))
1406 params[
1] = NEditStrdup(rd->lastCommand);
1407 else {
1408 if (ReplayMacro ==
NULL)
1409 return False;
1410 params[
1] = NEditStrdup(ReplayMacro);
1411 }
1412
1413
1414 XtCallActionProc(rd->forWindow->lastFocus,
"repeat_macro", event, params,
2);
1415 NEditFree(params[
1]);
1416 return True;
1417 }
1418
1419 static void repeatCancelCB(Widget w, XtPointer clientData, XtPointer callData)
1420 {
1421 repeatDialog *rd = (repeatDialog *)clientData;
1422
1423 XtDestroyWidget(rd->shell);
1424 }
1425
1426 static void repeatDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
1427 {
1428 repeatDialog *rd = (repeatDialog *)clientData;
1429
1430 NEditFree(rd->lastCommand);
1431 NEditFree(rd);
1432 }
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443 void RepeatMacro(WindowInfo *window,
const char *command,
int how)
1444 {
1445 Program *prog;
1446 char *errMsg, *stoppedAt, *loopMacro, *loopedCmd;
1447
1448 if (command ==
NULL)
1449 return;
1450
1451
1452 if (how ==
REPEAT_TO_END)
1453 loopMacro =
"lastCursor=-1\nstartPos=$cursor\n\
1454 while($cursor>=startPos&&$cursor!=lastCursor){\nlastCursor=$cursor\n%s\n}\n";
1455 else if (how ==
REPEAT_IN_SEL)
1456 loopMacro =
"selStart = $selection_start\nif (selStart == -1)\nreturn\n\
1457 selEnd = $selection_end\nset_cursor_pos(selStart)\nselect(0,0)\n\
1458 boundText = get_range(selEnd, selEnd+10)\n\
1459 while($cursor >= selStart && $cursor < selEnd && \\\n\
1460 get_range(selEnd, selEnd+10) == boundText) {\n\
1461 startLength = $text_length\n%s\n\
1462 selEnd += $text_length - startLength\n}\n";
1463 else
1464 loopMacro =
"for(i=0;i<%d;i++){\n%s\n}\n";
1465 loopedCmd = (
char*)NEditMalloc(strlen(command) + strlen(loopMacro) +
25);
1466 if (how ==
REPEAT_TO_END || how ==
REPEAT_IN_SEL)
1467 sprintf(loopedCmd, loopMacro, command);
1468 else
1469 sprintf(loopedCmd, loopMacro, how, command);
1470
1471
1472 prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt);
1473 if (prog ==
NULL) {
1474 fprintf(stderr,
"XNEdit internal error, repeat macro syntax wrong: %s\n",
1475 errMsg);
1476 return;
1477 }
1478 NEditFree(loopedCmd);
1479
1480
1481 runMacro(window, prog);
1482 }
1483
1484
1485
1486
1487
1488 static void learnActionHook(Widget w, XtPointer clientData, String actionName,
1489 XEvent *event, String *params, Cardinal *numParams)
1490 {
1491 WindowInfo *window;
1492 int i;
1493 char *actionString;
1494
1495
1496
1497 for (window=WindowList; window!=
NULL; window=window->next) {
1498 if (window->textArea == w)
1499 break;
1500 for (i=
0; i<window->nPanes; i++) {
1501 if (window->textPanes[i] == w)
1502 break;
1503 }
1504 if (i < window->nPanes)
1505 break;
1506 }
1507 if (window ==
NULL || window != (WindowInfo *)clientData)
1508 return;
1509
1510
1511
1512 if (isMouseAction(actionName)) {
1513 XBell(XtDisplay(w),
0);
1514 return;
1515 }
1516
1517
1518 actionString = actionToString(w, actionName, event, params, *numParams);
1519 if (actionString !=
NULL) {
1520 BufInsert(MacroRecordBuf, MacroRecordBuf->length, actionString);
1521 NEditFree(actionString);
1522 }
1523 }
1524
1525
1526
1527
1528 static void lastActionHook(Widget w, XtPointer clientData, String actionName,
1529 XEvent *event, String *params, Cardinal *numParams)
1530 {
1531 WindowInfo *window;
1532 int i;
1533 char *actionString;
1534
1535
1536 for (window=WindowList; window!=
NULL; window=window->next) {
1537 if (window->textArea == w)
1538 break;
1539 for (i=
0; i<window->nPanes; i++) {
1540 if (window->textPanes[i] == w)
1541 break;
1542 }
1543 if (i < window->nPanes)
1544 break;
1545 }
1546 if (window ==
NULL)
1547 return;
1548
1549
1550
1551 if (!strcmp(actionName,
"repeat_macro"))
1552 return;
1553
1554
1555 actionString = actionToString(w, actionName, event, params, *numParams);
1556 if (actionString !=
NULL) {
1557 NEditFree(LastCommand);
1558 LastCommand = actionString;
1559 }
1560 }
1561
1562
1563
1564
1565
1566 static char *actionToString(Widget w,
char *actionName, XEvent *event,
1567 String *params, Cardinal numParams)
1568 {
1569 char chars[
512], *charList[
1], *outStr, *outPtr;
1570 KeySym keysym;
1571 int i, nChars, nParams, length, nameLength;
1572 #ifndef NO_XMIM
1573 int status;
1574 #endif
1575
1576 if (isIgnoredAction(actionName) || isRedundantAction(actionName) ||
1577 isMouseAction(actionName))
1578 return NULL;
1579
1580
1581 if (!strcmp(actionName,
"self_insert") ||
1582 !strcmp(actionName,
"self-insert")) {
1583 actionName =
"insert_string";
1584
1585 nChars = TextLookupString(w, (XKeyEvent *)event, chars,
511, &keysym, &status);
1586 if (nChars ==
0 || status == XLookupNone ||
1587 status == XLookupKeySym || status == XBufferOverflow)
1588 return NULL;
1589
1590 chars[nChars] =
'\0';
1591 charList[
0] = chars;
1592 params = charList;
1593 nParams =
1;
1594 }
else
1595 nParams = numParams;
1596
1597
1598 nameLength = strlen(actionName);
1599 length = nameLength +
3;
1600 for (i=
0; i<nParams; i++) {
1601 length += escapedStringLength(params[i] ? params[i] :
"") +
4;
1602 }
1603
1604
1605 outPtr = outStr = (
char*)NEditMalloc(length +
1);
1606 strcpy(outPtr, actionName);
1607 outPtr += nameLength;
1608 *outPtr++ =
'(';
1609 for (i=
0; i<nParams; i++) {
1610 *outPtr++ =
'\"';
1611 outPtr += escapeStringChars(params[i] ? params[i] :
"", outPtr);
1612 *outPtr++ =
'\"'; *outPtr++ =
','; *outPtr++ =
' ';
1613 }
1614 if (nParams !=
0)
1615 outPtr -=
2;
1616 *outPtr++ =
')'; *outPtr++ =
'\n'; *outPtr++ =
'\0';
1617 return outStr;
1618 }
1619
1620 static int isMouseAction(
const char *action)
1621 {
1622 int i;
1623
1624 for (i=
0; i<(
int)XtNumber(MouseActions); i++)
1625 if (!strcmp(action, MouseActions[i]))
1626 return True;
1627 return False;
1628 }
1629
1630 static int isRedundantAction(
const char *action)
1631 {
1632 int i;
1633
1634 for (i=
0; i<(
int)XtNumber(RedundantActions); i++)
1635 if (!strcmp(action, RedundantActions[i]))
1636 return True;
1637 return False;
1638 }
1639
1640 static int isIgnoredAction(
const char *action)
1641 {
1642 int i;
1643
1644 for (i=
0; i<(
int)XtNumber(IgnoredActions); i++)
1645 if (!strcmp(action, IgnoredActions[i]))
1646 return True;
1647 return False;
1648 }
1649
1650
1651
1652
1653
1654 #define MAX_TIMEOUT_MSG_LEN (
MAX_ACCEL_LEN +
60)
1655 static void bannerTimeoutProc(XtPointer clientData, XtIntervalId *id)
1656 {
1657 WindowInfo *window = (WindowInfo *)clientData;
1658 macroCmdInfo *cmdData = window->macroCmdData;
1659 XmString xmCancel;
1660 char *cCancel =
"\0";
1661 char message[
MAX_TIMEOUT_MSG_LEN];
1662
1663 cmdData->bannerIsUp = True;
1664
1665
1666 XtVaGetValues(window->cancelMacroItem, XmNacceleratorText, &xmCancel,
NULL);
1667
1668 if (!XmStringEmpty(xmCancel))
1669 {
1670
1671 cCancel = GetXmStringText(xmCancel);
1672
1673
1674 XmStringFree(xmCancel);
1675 }
1676
1677
1678 if (cCancel[
0] ==
'\0') {
1679 strncpy(message,
"Macro Command in Progress",
MAX_TIMEOUT_MSG_LEN);
1680 message[
MAX_TIMEOUT_MSG_LEN -
1] =
'\0';
1681 }
1682 else {
1683 sprintf(message,
1684 "Macro Command in Progress -- Press %s to Cancel",
1685 cCancel);
1686 }
1687
1688
1689 NEditFree(cCancel);
1690
1691 SetModeMessage(window, message);
1692 cmdData->bannerTimeoutID =
0;
1693 }
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706 static Boolean continueWorkProc(XtPointer clientData)
1707 {
1708 WindowInfo *window = (WindowInfo *)clientData;
1709 macroCmdInfo *cmdData = window->macroCmdData;
1710 char *errMsg;
1711 int stat;
1712 DataValue result;
1713
1714 stat = ContinueMacro(cmdData->context, &result, &errMsg);
1715 if (stat ==
MACRO_ERROR)
1716 {
1717 finishMacroCmdExecution(window);
1718 DialogF(
DF_ERR, window->shell,
1,
"Macro Error",
1719 "Error executing macro: %s",
"OK", errMsg);
1720 return True;
1721 }
else if (stat ==
MACRO_DONE)
1722 {
1723 finishMacroCmdExecution(window);
1724 return True;
1725 }
else if (stat ==
MACRO_PREEMPT)
1726 {
1727 cmdData->continueWorkProcID =
0;
1728 return True;
1729 }
1730
1731
1732 if (stat !=
MACRO_TIME_LIMIT)
1733 return True;
1734 return False;
1735 }
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747 static int escapeStringChars(
char *fromString,
char *toString)
1748 {
1749 char *e, *c, *outPtr = toString;
1750
1751
1752 for (c=fromString; *c!=
'\0'; c++) {
1753 for (e=EscapeChars; *e!=
'\0'; e++) {
1754 if (*c == *e) {
1755 *outPtr++ =
'\\';
1756 *outPtr++ = ReplaceChars[e-EscapeChars];
1757 break;
1758 }
1759 }
1760 if (*e ==
'\0')
1761 *outPtr++ = *c;
1762 }
1763 *outPtr =
'\0';
1764 return outPtr - toString;
1765 }
1766
1767
1768
1769
1770
1771 static int escapedStringLength(
char *string)
1772 {
1773 char *c, *e;
1774 int length =
0;
1775
1776
1777 for (c=string; *c!=
'\0'; c++) {
1778 for (e=EscapeChars; *e!=
'\0'; e++) {
1779 if (*c == *e) {
1780 length++;
1781 break;
1782 }
1783 }
1784 length++;
1785 }
1786 return length;
1787 }
1788
1789
1790
1791
1792 static int lengthMS(WindowInfo *window, DataValue *argList,
int nArgs,
1793 DataValue *result,
char **errMsg)
1794 {
1795 char *string, stringStorage[
TYPE_INT_STR_SIZE(
int)];
1796
1797 if (nArgs !=
1)
1798 return wrongNArgsErr(errMsg);
1799 if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
1800 return False;
1801 result->tag =
INT_TAG;
1802 result->val.n = strlen(string);
1803 return True;
1804 }
1805
1806
1807
1808
1809 static int minMS(WindowInfo *window, DataValue *argList,
int nArgs,
1810 DataValue *result,
char **errMsg)
1811 {
1812 int minVal, value, i;
1813
1814 if (nArgs ==
1)
1815 return tooFewArgsErr(errMsg);
1816 if (!readIntArg(argList[
0], &minVal, errMsg))
1817 return False;
1818 for (i=
0; i<nArgs; i++) {
1819 if (!readIntArg(argList[i], &value, errMsg))
1820 return False;
1821 minVal = value < minVal ? value : minVal;
1822 }
1823 result->tag =
INT_TAG;
1824 result->val.n = minVal;
1825 return True;
1826 }
1827 static int maxMS(WindowInfo *window, DataValue *argList,
int nArgs,
1828 DataValue *result,
char **errMsg)
1829 {
1830 int maxVal, value, i;
1831
1832 if (nArgs ==
1)
1833 return tooFewArgsErr(errMsg);
1834 if (!readIntArg(argList[
0], &maxVal, errMsg))
1835 return False;
1836 for (i=
0; i<nArgs; i++) {
1837 if (!readIntArg(argList[i], &value, errMsg))
1838 return False;
1839 maxVal = value > maxVal ? value : maxVal;
1840 }
1841 result->tag =
INT_TAG;
1842 result->val.n = maxVal;
1843 return True;
1844 }
1845
1846 static int focusWindowMS(WindowInfo *window, DataValue *argList,
int nArgs,
1847 DataValue *result,
char **errMsg)
1848 {
1849 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
1850 WindowInfo *w;
1851 char fullname[
2*
MAXPATHLEN];
1852 char normalizedString[
MAXPATHLEN];
1853
1854
1855
1856 if (nArgs !=
1)
1857 return wrongNArgsErr(errMsg);
1858
1859 if (!readStringArg(argList[
0], &string, stringStorage, errMsg)) {
1860 return False;
1861 }
else if (!strcmp(string,
"last")) {
1862 w = WindowList;
1863 }
else if (!strcmp(string,
"next")) {
1864 w = window->next;
1865 }
else if (strlen(string) >=
MAXPATHLEN) {
1866 *errMsg =
"Pathname too long in focus_window()";
1867 return False;
1868 }
else {
1869
1870 for (w=WindowList; w !=
NULL; w = w->next) {
1871 snprintf(fullname,
sizeof(fullname),
"%s%s", w->path, w->filename);
1872 if (!strcmp(string, fullname)) {
1873 break;
1874 }
1875 }
1876
1877 if (w ==
NULL) {
1878 strncpy(normalizedString, string,
MAXPATHLEN);
1879 normalizedString[
MAXPATHLEN-
1] =
'\0';
1880 if (
1 == NormalizePathname(normalizedString)) {
1881
1882 *errMsg =
"Pathname too long in focus_window()";
1883 return False;
1884 }
1885 for (w=WindowList; w !=
NULL; w = w->next) {
1886 snprintf(fullname,
sizeof(fullname),
1887 "%s%s", w->path, w->filename);
1888 if (!strcmp(normalizedString, fullname))
1889 break;
1890 }
1891 }
1892 }
1893
1894
1895 if (w ==
NULL) {
1896 result->tag =
STRING_TAG;
1897 result->val.str.rep =
PERM_ALLOC_STR(
"");
1898 result->val.str.len =
0;
1899 return True;
1900 }
1901
1902
1903 SetMacroFocusWindow(w);
1904
1905
1906 if (w->highlightSyntax && w->highlightData==
NULL)
1907 StartHighlighting(w, False);
1908
1909
1910 result->tag =
STRING_TAG;
1911 size_t result_str_len = strlen(w->path)+strlen(w->filename)+
1;
1912 AllocNString(&result->val.str, result_str_len);
1913 snprintf(result->val.str.rep, result_str_len,
"%s%s", w->path, w->filename);
1914 return True;
1915 }
1916
1917
1918
1919
1920
1921 static int getRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
1922 DataValue *result,
char **errMsg)
1923 {
1924 int from, to;
1925 textBuffer *buf = window->buffer;
1926 char *rangeText;
1927
1928
1929 if (nArgs !=
2)
1930 return wrongNArgsErr(errMsg);
1931 if (!readIntArg(argList[
0], &from, errMsg))
1932 return False;
1933 if (!readIntArg(argList[
1], &to, errMsg))
1934 return False;
1935 if (from <
0) from =
0;
1936 if (from > buf->length) from = buf->length;
1937 if (to <
0) to =
0;
1938 if (to > buf->length) to = buf->length;
1939 if (from > to) {
int temp = from; from = to; to = temp;}
1940
1941
1942
1943 result->tag =
STRING_TAG;
1944 AllocNString(&result->val.str, to - from +
1);
1945 rangeText = BufGetRange(buf, from, to);
1946 BufUnsubstituteNullChars(rangeText, buf);
1947 strcpy(result->val.str.rep, rangeText);
1948
1949
1950 NEditFree(rangeText);
1951 return True;
1952 }
1953
1954
1955
1956
1957
1958 static int getCharacterMS(WindowInfo *window, DataValue *argList,
int nArgs,
1959 DataValue *result,
char **errMsg)
1960 {
1961 int pos;
1962 textBuffer *buf = window->buffer;
1963
1964
1965 if (nArgs !=
1)
1966 return wrongNArgsErr(errMsg);
1967 if (!readIntArg(argList[
0], &pos, errMsg))
1968 return False;
1969 if (pos <
0) pos =
0;
1970 if (pos > buf->length) pos = buf->length;
1971
1972
1973 result->tag =
STRING_TAG;
1974 AllocNString(&result->val.str,
2);
1975 result->val.str.rep[
0] = BufGetCharacter(buf, pos);
1976 BufUnsubstituteNullChars(result->val.str.rep, buf);
1977
1978
1979 return True;
1980 }
1981
1982
1983
1984
1985
1986 static int replaceRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
1987 DataValue *result,
char **errMsg)
1988 {
1989 int from, to;
1990 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
1991 textBuffer *buf = window->buffer;
1992
1993
1994 if (nArgs !=
3)
1995 return wrongNArgsErr(errMsg);
1996 if (!readIntArg(argList[
0], &from, errMsg))
1997 return False;
1998 if (!readIntArg(argList[
1], &to, errMsg))
1999 return False;
2000 if (!readStringArg(argList[
2], &string, stringStorage, errMsg))
2001 return False;
2002 if (from <
0) from =
0;
2003 if (from > buf->length) from = buf->length;
2004 if (to <
0) to =
0;
2005 if (to > buf->length) to = buf->length;
2006 if (from > to) {
int temp = from; from = to; to = temp;}
2007
2008
2009 if (
IS_ANY_LOCKED(window->lockReasons)) {
2010 XBell(XtDisplay(window->shell),
0);
2011 result->tag =
NO_TAG;
2012 return True;
2013 }
2014
2015
2016
2017
2018
2019
2020
2021 if (!BufSubstituteNullChars(string, strlen(string), window->buffer)) {
2022 *errMsg =
"Too much binary data in file";
2023 return False;
2024 }
2025
2026
2027 BufReplace(buf, from, to, string);
2028 result->tag =
NO_TAG;
2029 return True;
2030 }
2031
2032
2033
2034
2035
2036 static int replaceSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
2037 DataValue *result,
char **errMsg)
2038 {
2039 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
2040
2041
2042 if (nArgs !=
1)
2043 return wrongNArgsErr(errMsg);
2044 if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
2045 return False;
2046
2047
2048 if (
IS_ANY_LOCKED(window->lockReasons)) {
2049 XBell(XtDisplay(window->shell),
0);
2050 result->tag =
NO_TAG;
2051 return True;
2052 }
2053
2054
2055
2056
2057
2058
2059
2060 if (!BufSubstituteNullChars(string, strlen(string), window->buffer)) {
2061 *errMsg =
"Too much binary data in file";
2062 return False;
2063 }
2064
2065
2066 BufReplaceSelected(window->buffer, string);
2067 result->tag =
NO_TAG;
2068 return True;
2069 }
2070
2071
2072
2073
2074
2075
2076 static int getSelectionMS(WindowInfo *window, DataValue *argList,
int nArgs,
2077 DataValue *result,
char **errMsg)
2078 {
2079 char *selText;
2080
2081
2082
2083 if (nArgs !=
0 && nArgs !=
1)
2084 return wrongNArgsErr(errMsg);
2085 if (nArgs ==
1) {
2086 if (argList[
0].tag !=
STRING_TAG || strcmp(argList[
0].val.str.rep,
"any")) {
2087 *errMsg =
"Unrecognized argument to %s";
2088 return False;
2089 }
2090 selText = GetAnySelection(window);
2091 if (selText ==
NULL)
2092 selText = NEditStrdup(
"");
2093 }
else {
2094 selText = BufGetSelectionText(window->buffer);
2095 BufUnsubstituteNullChars(selText, window->buffer);
2096 }
2097
2098
2099 result->tag =
STRING_TAG;
2100 AllocNStringCpy(&result->val.str, selText);
2101 NEditFree(selText);
2102 return True;
2103 }
2104
2105
2106
2107
2108
2109 static int validNumberMS(WindowInfo *window, DataValue *argList,
int nArgs,
2110 DataValue *result,
char **errMsg)
2111 {
2112 char *string, stringStorage[
TYPE_INT_STR_SIZE(
int)];
2113
2114 if (nArgs !=
1) {
2115 return wrongNArgsErr(errMsg);
2116 }
2117 if (!readStringArg(argList[
0], &string, stringStorage, errMsg)) {
2118 return False;
2119 }
2120
2121 result->tag =
INT_TAG;
2122 result->val.n = StringToNum(string,
NULL);
2123
2124 return True;
2125 }
2126
2127
2128
2129
2130 static int replaceSubstringMS(WindowInfo *window, DataValue *argList,
int nArgs,
2131 DataValue *result,
char **errMsg)
2132 {
2133 int from, to, length, replaceLen, outLen;
2134 char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *string, *replStr;
2135
2136
2137 if (nArgs !=
4)
2138 return wrongNArgsErr(errMsg);
2139 if (!readStringArg(argList[
0], &string, stringStorage[
1], errMsg))
2140 return False;
2141 if (!readIntArg(argList[
1], &from, errMsg))
2142 return False;
2143 if (!readIntArg(argList[
2], &to, errMsg))
2144 return False;
2145 if (!readStringArg(argList[
3], &replStr, stringStorage[
1], errMsg))
2146 return False;
2147 length = strlen(string);
2148 if (from <
0) from =
0;
2149 if (from > length) from = length;
2150 if (to <
0) to =
0;
2151 if (to > length) to = length;
2152 if (from > to) {
int temp = from; from = to; to = temp;}
2153
2154
2155 replaceLen = strlen(replStr);
2156 outLen = length - (to - from) + replaceLen;
2157 result->tag =
STRING_TAG;
2158 AllocNString(&result->val.str, outLen+
1);
2159 strncpy(result->val.str.rep, string, from);
2160 strncpy(&result->val.str.rep[from], replStr, replaceLen);
2161 strncpy(&result->val.str.rep[from + replaceLen], &string[to], length - to);
2162 return True;
2163 }
2164
2165
2166
2167
2168
2169 static int substringMS(WindowInfo *window, DataValue *argList,
int nArgs,
2170 DataValue *result,
char **errMsg)
2171 {
2172 int from, to, length;
2173 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
2174
2175
2176 if (nArgs !=
2 && nArgs !=
3)
2177 return wrongNArgsErr(errMsg);
2178 if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
2179 return False;
2180 if (!readIntArg(argList[
1], &from, errMsg))
2181 return False;
2182 length = to = strlen(string);
2183 if (nArgs ==
3)
2184 if (!readIntArg(argList[
2], &to, errMsg))
2185 return False;
2186 if (from <
0) from += length;
2187 if (from <
0) from =
0;
2188 if (from > length) from = length;
2189 if (to <
0) to += length;
2190 if (to <
0) to =
0;
2191 if (to > length) to = length;
2192 if (from > to) to = from;
2193
2194
2195 result->tag =
STRING_TAG;
2196 AllocNStringNCpy(&result->val.str, &string[from], to - from);
2197 return True;
2198 }
2199
2200 static int toupperMS(WindowInfo *window, DataValue *argList,
int nArgs,
2201 DataValue *result,
char **errMsg)
2202 {
2203 int length;
2204 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
2205
2206
2207 if (nArgs !=
1)
2208 return wrongNArgsErr(errMsg);
2209 if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
2210 return False;
2211 length = strlen(string);
2212
2213
2214 result->tag =
STRING_TAG;
2215 AllocNString(&result->val.str, length +
1);
2216 UpCaseString(result->val.str.rep, string);
2217 return True;
2218 }
2219
2220 static int tolowerMS(WindowInfo *window, DataValue *argList,
int nArgs,
2221 DataValue *result,
char **errMsg)
2222 {
2223 int length;
2224 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
2225
2226
2227 if (nArgs !=
1)
2228 return wrongNArgsErr(errMsg);
2229 if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
2230 return False;
2231 length = strlen(string);
2232
2233
2234 result->tag =
STRING_TAG;
2235 AllocNString(&result->val.str, length +
1);
2236 DownCaseString(result->val.str.rep, string);
2237 return True;
2238 }
2239
2240 static int stringToClipboardMS(WindowInfo *window, DataValue *argList,
int nArgs,
2241 DataValue *result,
char **errMsg)
2242 {
2243 long itemID =
0;
2244 XmString s;
2245 int stat;
2246 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
2247
2248
2249 if (nArgs !=
1)
2250 return wrongNArgsErr(errMsg);
2251 if (!readStringArg(argList[
0], &string, stringStorage, errMsg))
2252 return False;
2253
2254
2255
2256 result->tag =
NO_TAG;
2257 stat = SpinClipboardStartCopy(TheDisplay, XtWindow(window->textArea),
2258 s=XmStringCreateSimple(
"NEdit"), XtLastTimestampProcessed(TheDisplay),
2259 window->textArea,
NULL, &itemID);
2260 XmStringFree(s);
2261 if (stat != ClipboardSuccess)
2262 return True;
2263 char *format =
"UTF8_STRING";
2264 for(
int i=
0;i<
2;i++) {
2265 (
void)SpinClipboardCopy(TheDisplay, XtWindow(window->textArea), itemID, format,
2266 string, strlen(string),
0,
NULL);
2267 format =
"STRING";
2268 }
2269 SpinClipboardEndCopy(TheDisplay, XtWindow(window->textArea), itemID);
2270 return True;
2271 }
2272
2273 static int clipboardToStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
2274 DataValue *result,
char **errMsg)
2275 {
2276 unsigned long length, retLength;
2277 long id =
0;
2278
2279
2280 if (nArgs !=
0)
2281 return wrongNArgsErr(errMsg);
2282
2283
2284
2285 char *format_name =
"UTF8_STRING";
2286 int res = ClipboardNoData;
2287 for(
int i=
0;i<
2;i++) {
2288 res = SpinClipboardInquireLength(
2289 TheDisplay,
2290 XtWindow(window->shell),
2291 format_name,
2292 &length);
2293 if(res == ClipboardSuccess) {
2294 break;
2295 }
2296 format_name =
"STRING";
2297 }
2298
2299 if (res != ClipboardSuccess) {
2300 result->tag =
STRING_TAG;
2301 result->val.str.rep =
PERM_ALLOC_STR(
"");
2302 result->val.str.len =
0;
2303
2304
2305
2306
2307 SpinClipboardUnlock(TheDisplay, XtWindow(window->shell));
2308 return True;
2309 }
2310
2311
2312 result->tag =
STRING_TAG;
2313 AllocNString(&result->val.str, (
int)length +
1);
2314
2315
2316 if (SpinClipboardRetrieve(TheDisplay, XtWindow(window->shell), format_name,
2317 result->val.str.rep, length, &retLength, &id) != ClipboardSuccess) {
2318 retLength =
0;
2319
2320
2321
2322
2323 SpinClipboardUnlock(TheDisplay, XtWindow(window->shell));
2324 }
2325 result->val.str.rep[retLength] =
'\0';
2326 result->val.str.len = retLength;
2327
2328 return True;
2329 }
2330
2331
2332
2333
2334
2335
2336
2337
2338 static int readFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
2339 DataValue *result,
char **errMsg)
2340 {
2341 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *name;
2342 struct stat statbuf;
2343 FILE *fp;
2344 int readLen;
2345
2346
2347 if (nArgs !=
1)
2348 return wrongNArgsErr(errMsg);
2349 if (!readStringArg(argList[
0], &name, stringStorage, errMsg))
2350 return False;
2351
2352
2353 if ((fp = fopen(name,
"r")) ==
NULL)
2354 goto errorNoClose;
2355 if (fstat(fileno(fp), &statbuf) !=
0)
2356 goto error;
2357 result->tag =
STRING_TAG;
2358 AllocNString(&result->val.str, statbuf.st_size+
1);
2359 readLen = fread(result->val.str.rep,
sizeof(
char), statbuf.st_size+
1, fp);
2360 if (ferror(fp))
2361 goto error;
2362 if(!feof(fp)){
2363
2364 int chunkSize =
1024;
2365 char *buffer;
2366
2367 buffer = (
char*)NEditMalloc(readLen *
sizeof(
char));
2368 memcpy(buffer, result->val.str.rep, readLen *
sizeof(
char));
2369 while (!feof(fp)){
2370 buffer = NEditRealloc(buffer, (readLen+chunkSize)*
sizeof(
char));
2371 readLen += fread(&buffer[readLen],
sizeof(
char), chunkSize, fp);
2372 if (ferror(fp)){
2373 NEditFree(buffer);
2374 goto error;
2375 }
2376 }
2377 AllocNString(&result->val.str, readLen +
1);
2378 memcpy(result->val.str.rep, buffer, readLen *
sizeof(
char));
2379 NEditFree(buffer);
2380 }
2381 fclose(fp);
2382
2383
2384 ReturnGlobals[
READ_STATUS]->value.tag =
INT_TAG;
2385 ReturnGlobals[
READ_STATUS]->value.val.n = True;
2386 return True;
2387
2388 error:
2389 fclose(fp);
2390
2391 errorNoClose:
2392 ReturnGlobals[
READ_STATUS]->value.tag =
INT_TAG;
2393 ReturnGlobals[
READ_STATUS]->value.val.n = False;
2394 result->tag =
STRING_TAG;
2395 result->val.str.rep =
PERM_ALLOC_STR(
"");
2396 result->val.str.len =
0;
2397 return True;
2398 }
2399
2400
2401
2402
2403
2404
2405 static int writeFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
2406 DataValue *result,
char **errMsg)
2407 {
2408 return writeOrAppendFile(False, window, argList, nArgs, result, errMsg);
2409 }
2410
2411 static int appendFileMS(WindowInfo *window, DataValue *argList,
int nArgs,
2412 DataValue *result,
char **errMsg)
2413 {
2414 return writeOrAppendFile(True, window, argList, nArgs, result, errMsg);
2415 }
2416
2417 static int writeOrAppendFile(
int append, WindowInfo *window,
2418 DataValue *argList,
int nArgs, DataValue *result,
char **errMsg)
2419 {
2420 char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *name, *string;
2421 FILE *fp;
2422
2423
2424 if (nArgs !=
2)
2425 return wrongNArgsErr(errMsg);
2426 if (!readStringArg(argList[
0], &string, stringStorage[
1], errMsg))
2427 return False;
2428 if (!readStringArg(argList[
1], &name, stringStorage[
0], errMsg))
2429 return False;
2430
2431
2432 if ((fp = fopen(name, append ?
"a" :
"w")) ==
NULL) {
2433 result->tag =
INT_TAG;
2434 result->val.n = False;
2435 return True;
2436 }
2437
2438
2439 fwrite(string,
sizeof(
char), strlen(string), fp);
2440 if (ferror(fp)) {
2441 fclose(fp);
2442 result->tag =
INT_TAG;
2443 result->val.n = False;
2444 return True;
2445 }
2446 fclose(fp);
2447
2448
2449 result->tag =
INT_TAG;
2450 result->val.n = True;
2451 return True;
2452 }
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466 static int searchMS(WindowInfo *window, DataValue *argList,
int nArgs,
2467 DataValue *result,
char **errMsg)
2468 {
2469 DataValue newArgList[
9];
2470
2471
2472
2473 if (nArgs >
8)
2474 return wrongNArgsErr(errMsg);
2475
2476
2477
2478 newArgList[
0].tag =
STRING_TAG;
2479 newArgList[
0].val.str.rep = (
char *)BufAsString(window->buffer);
2480 newArgList[
0].val.str.len = window->buffer->length;
2481
2482
2483 memcpy(&newArgList[
1], argList, nArgs *
sizeof(DataValue));
2484
2485 return searchStringMS(window, newArgList, nArgs+
1, result, errMsg);
2486 }
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499 static int searchStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
2500 DataValue *result,
char **errMsg)
2501 {
2502 int beginPos, wrap, direction, found = False, foundStart, foundEnd, type;
2503 int skipSearch = False, len;
2504 char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *string, *searchStr;
2505
2506
2507 if (nArgs <
3)
2508 return tooFewArgsErr(errMsg);
2509 if (!readStringArg(argList[
0], &string, stringStorage[
0], errMsg))
2510 return False;
2511 if (!readStringArg(argList[
1], &searchStr, stringStorage[
1], errMsg))
2512 return False;
2513 if (!readIntArg(argList[
2], &beginPos, errMsg))
2514 return False;
2515 if (!readSearchArgs(&argList[
3], nArgs-
3, &direction, &type, &wrap, errMsg))
2516 return False;
2517
2518 len = argList[
0].val.str.len;
2519 if (beginPos > len) {
2520 if (direction ==
SEARCH_FORWARD) {
2521 if (wrap) {
2522 beginPos =
0;
2523 }
else {
2524 found = False;
2525 skipSearch = True;
2526 }
2527 }
else {
2528 beginPos = len;
2529 }
2530 }
else if (beginPos <
0) {
2531 if (direction ==
SEARCH_BACKWARD) {
2532 if (wrap) {
2533 beginPos = len;
2534 }
else {
2535 found = False;
2536 skipSearch = True;
2537 }
2538 }
else {
2539 beginPos =
0;
2540 }
2541 }
2542
2543 if (!skipSearch)
2544 found = SearchString(string, searchStr, direction, type, wrap, beginPos,
2545 &foundStart, &foundEnd,
NULL,
NULL, GetWindowDelimiters(window));
2546
2547
2548 ReturnGlobals[
SEARCH_END]->value.tag =
INT_TAG;
2549 ReturnGlobals[
SEARCH_END]->value.val.n = found ? foundEnd :
0;
2550 result->tag =
INT_TAG;
2551 result->val.n = found ? foundStart : -
1;
2552 return True;
2553 }
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566 static int replaceInStringMS(WindowInfo *window, DataValue *argList,
int nArgs,
2567 DataValue *result,
char **errMsg)
2568 {
2569 char stringStorage[
3][
TYPE_INT_STR_SIZE(
int)], *string, *searchStr, *replaceStr;
2570 char *argStr, *replacedStr;
2571 int searchType =
SEARCH_LITERAL, copyStart, copyEnd;
2572 int replacedLen, replaceEnd, force=False, i;
2573
2574
2575 if (nArgs <
3 || nArgs >
5)
2576 return wrongNArgsErr(errMsg);
2577 if (!readStringArg(argList[
0], &string, stringStorage[
0], errMsg))
2578 return False;
2579 if (!readStringArg(argList[
1], &searchStr, stringStorage[
1], errMsg))
2580 return False;
2581 if (!readStringArg(argList[
2], &replaceStr, stringStorage[
2], errMsg))
2582 return False;
2583 for (i =
3; i < nArgs; i++) {
2584
2585 if (!readStringArg(argList[i], &argStr, stringStorage[
2], errMsg))
2586 return False;
2587 if (!StringToSearchType(argStr, &searchType)) {
2588
2589 if (!strcmp(argStr,
"copy")) {
2590 force = True;
2591 }
else {
2592 *errMsg =
"unrecognized argument to %s";
2593 return False;
2594 }
2595 }
2596 }
2597
2598
2599 replacedStr = ReplaceAllInString(string, searchStr, replaceStr, searchType,
2600 ©Start, ©End, &replacedLen, GetWindowDelimiters(window));
2601
2602
2603 result->tag =
STRING_TAG;
2604 if (replacedStr ==
NULL) {
2605 if (force) {
2606
2607 if (argList[
0].tag ==
STRING_TAG) {
2608 result->val.str.rep = argList[
0].val.str.rep;
2609 result->val.str.len = argList[
0].val.str.len;
2610 }
2611 else {
2612 AllocNStringCpy(&result->val.str, string);
2613 }
2614 }
2615 else {
2616 result->val.str.rep =
PERM_ALLOC_STR(
"");
2617 result->val.str.len =
0;
2618 }
2619 }
2620 else {
2621 size_t remainder = strlen(&string[copyEnd]);
2622 replaceEnd = copyStart + replacedLen;
2623 AllocNString(&result->val.str, replaceEnd + remainder +
1);
2624 strncpy(result->val.str.rep, string, copyStart);
2625 strcpy(&result->val.str.rep[copyStart], replacedStr);
2626 strcpy(&result->val.str.rep[replaceEnd], &string[copyEnd]);
2627 NEditFree(replacedStr);
2628 }
2629 return True;
2630 }
2631
2632 static int readSearchArgs(DataValue *argList,
int nArgs,
int *searchDirection,
2633 int *searchType,
int *wrap,
char **errMsg)
2634 {
2635 int i;
2636 char *argStr, stringStorage[
TYPE_INT_STR_SIZE(
int)];
2637
2638 *wrap = False;
2639 *searchDirection =
SEARCH_FORWARD;
2640 *searchType =
SEARCH_LITERAL;
2641 for (i=
0; i<nArgs; i++) {
2642 if (!readStringArg(argList[i], &argStr, stringStorage, errMsg))
2643 return False;
2644 else if (!strcmp(argStr,
"wrap"))
2645 *wrap = True;
2646 else if (!strcmp(argStr,
"nowrap"))
2647 *wrap = False;
2648 else if (!strcmp(argStr,
"backward"))
2649 *searchDirection =
SEARCH_BACKWARD;
2650 else if (!strcmp(argStr,
"forward"))
2651 *searchDirection =
SEARCH_FORWARD;
2652 else if (!StringToSearchType(argStr, searchType)) {
2653 *errMsg =
"Unrecognized argument to %s";
2654 return False;
2655 }
2656 }
2657 return True;
2658 }
2659
2660 static int setCursorPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
2661 DataValue *result,
char **errMsg)
2662 {
2663 int pos;
2664
2665
2666 if (nArgs !=
1)
2667 return wrongNArgsErr(errMsg);
2668 if (!readIntArg(argList[
0], &pos, errMsg))
2669 return False;
2670
2671
2672 TextSetCursorPos(window->lastFocus, pos);
2673 result->tag =
NO_TAG;
2674 return True;
2675 }
2676
2677 static int selectMS(WindowInfo *window, DataValue *argList,
int nArgs,
2678 DataValue *result,
char **errMsg)
2679 {
2680 int start, end, startTmp;
2681
2682
2683 if (nArgs !=
2)
2684 return wrongNArgsErr(errMsg);
2685 if (!readIntArg(argList[
0], &start, errMsg))
2686 return False;
2687 if (!readIntArg(argList[
1], &end, errMsg))
2688 return False;
2689
2690
2691 if (start > end) {
2692 startTmp = start;
2693 start = end;
2694 end = startTmp;
2695 }
2696 if (start <
0) start =
0;
2697 if (start > window->buffer->length) start = window->buffer->length;
2698 if (end <
0) end =
0;
2699 if (end > window->buffer->length) end = window->buffer->length;
2700
2701
2702 BufSelect(window->buffer, start, end);
2703 result->tag =
NO_TAG;
2704 return True;
2705 }
2706
2707 static int selectRectangleMS(WindowInfo *window, DataValue *argList,
int nArgs,
2708 DataValue *result,
char **errMsg)
2709 {
2710 int start, end, left, right;
2711
2712
2713 if (nArgs !=
4)
2714 return wrongNArgsErr(errMsg);
2715 if (!readIntArg(argList[
0], &start, errMsg))
2716 return False;
2717 if (!readIntArg(argList[
1], &end, errMsg))
2718 return False;
2719 if (!readIntArg(argList[
2], &left, errMsg))
2720 return False;
2721 if (!readIntArg(argList[
3], &right, errMsg))
2722 return False;
2723
2724
2725 BufRectSelect(window->buffer, start, end, left, right);
2726 result->tag =
NO_TAG;
2727 return True;
2728 }
2729
2730
2731
2732
2733 static int beepMS(WindowInfo *window, DataValue *argList,
int nArgs,
2734 DataValue *result,
char **errMsg)
2735 {
2736 if (nArgs !=
0)
2737 return wrongNArgsErr(errMsg);
2738 XBell(XtDisplay(window->shell),
0);
2739 result->tag =
NO_TAG;
2740 return True;
2741 }
2742
2743 static int tPrintMS(WindowInfo *window, DataValue *argList,
int nArgs,
2744 DataValue *result,
char **errMsg)
2745 {
2746 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *string;
2747 int i;
2748
2749 if (nArgs ==
0)
2750 return tooFewArgsErr(errMsg);
2751 for (i=
0; i<nArgs; i++) {
2752 if (!readStringArg(argList[i], &string, stringStorage, errMsg))
2753 return False;
2754 printf(
"%s%s", string, i==nArgs-
1 ?
"" :
" ");
2755 }
2756 fflush( stdout );
2757 result->tag =
NO_TAG;
2758 return True;
2759 }
2760
2761
2762
2763
2764 static int getenvMS(WindowInfo *window, DataValue *argList,
int nArgs,
2765 DataValue *result,
char **errMsg)
2766 {
2767 char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
2768 char *name;
2769 char *value;
2770
2771
2772 if (nArgs !=
1)
2773 return wrongNArgsErr(errMsg);
2774 if (!readStringArg(argList[
0], &name, stringStorage[
0], errMsg)) {
2775 *errMsg =
"argument to %s must be a string";
2776 return False;
2777 }
2778 value = getenv(name);
2779 if (value ==
NULL)
2780 value =
"";
2781
2782
2783 result->tag =
STRING_TAG;
2784 AllocNStringCpy(&result->val.str, value);
2785 return True;
2786 }
2787
2788 static int shellCmdMS(WindowInfo *window, DataValue *argList,
int nArgs,
2789 DataValue *result,
char **errMsg)
2790 {
2791 char stringStorage[
2][
TYPE_INT_STR_SIZE(
int)], *cmdString, *inputString;
2792
2793 if (nArgs !=
2)
2794 return wrongNArgsErr(errMsg);
2795 if (!readStringArg(argList[
0], &cmdString, stringStorage[
0], errMsg))
2796 return False;
2797 if (!readStringArg(argList[
1], &inputString, stringStorage[
1], errMsg))
2798 return False;
2799
2800
2801
2802 if (MacroRunWindow()->macroCmdData ==
NULL) {
2803 *errMsg =
"%s can''t be called from non-suspendable context";
2804 return False;
2805 }
2806
2807 ShellCmdToMacroString(window, cmdString, inputString);
2808 result->tag =
INT_TAG;
2809 result->val.n =
0;
2810 return True;
2811 }
2812
2813
2814
2815
2816
2817
2818
2819
2820 void ReturnShellCommandOutput(WindowInfo *window,
const char *outText,
int status)
2821 {
2822 DataValue retVal;
2823 macroCmdInfo *cmdData = window->macroCmdData;
2824
2825 if (cmdData ==
NULL)
2826 return;
2827 retVal.tag =
STRING_TAG;
2828 AllocNStringCpy(&retVal.val.str, outText);
2829 ModifyReturnedValue(cmdData->context, retVal);
2830 ReturnGlobals[
SHELL_CMD_STATUS]->value.tag =
INT_TAG;
2831 ReturnGlobals[
SHELL_CMD_STATUS]->value.val.n = status;
2832 }
2833
2834 static int dialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
2835 DataValue *result,
char **errMsg)
2836 {
2837 macroCmdInfo *cmdData;
2838 char stringStorage[
TYPE_INT_STR_SIZE(
int)];
2839 char btnStorage[
TYPE_INT_STR_SIZE(
int)];
2840 char *btnLabel;
2841 char *message;
2842 Arg al[
20];
2843 int ac;
2844 Widget dialog, btn;
2845 int i, nBtns;
2846 XmString s1, s2;
2847
2848
2849
2850 window = MacroRunWindow();
2851 cmdData = window->macroCmdData;
2852
2853
2854
2855 if (!cmdData) {
2856 *errMsg =
"%s can''t be called from non-suspendable context";
2857 return False;
2858 }
2859
2860
2861
2862 if (nArgs ==
0) {
2863 *errMsg =
"%s subroutine called with no arguments";
2864 return False;
2865 }
2866 if (!readStringArg(argList[
0], &message, stringStorage, errMsg)) {
2867 return False;
2868 }
2869
2870
2871 for (i=
1; i<nArgs; i++) {
2872 if (!readStringArg(argList[i], &btnLabel, btnStorage, errMsg)) {
2873 return False;
2874 }
2875 }
2876
2877
2878 if (nArgs ==
1) {
2879 btnLabel =
"OK";
2880 nBtns =
1;
2881 }
2882 else {
2883 nBtns = nArgs -
1;
2884 argList++;
2885 readStringArg(argList[
0], &btnLabel, btnStorage, errMsg);
2886 }
2887
2888
2889 ac =
0;
2890 XtSetArg(al[ac], XmNtitle,
" "); ac++;
2891 XtSetArg(al[ac], XmNmessageString, s1=
MKSTRING(message)); ac++;
2892 XtSetArg(al[ac], XmNokLabelString, s2=XmStringCreateSimple(btnLabel)); ac++;
2893 dialog = CreateMessageDialog(window->shell,
"macroDialog", al, ac);
2894 if (
1 == nArgs)
2895 {
2896
2897 XtVaSetValues(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
2898 XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
2899 NULL);
2900 }
2901
2902 XmStringFree(s1);
2903 XmStringFree(s2);
2904 AddMotifCloseCallback(XtParent(dialog), dialogCloseCB, window);
2905 XtAddCallback(dialog, XmNokCallback, dialogBtnCB, window);
2906 XtVaSetValues(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
2907 XmNuserData, (XtPointer)
1,
NULL);
2908 cmdData->dialog = dialog;
2909
2910
2911 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
2912 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
2913
2914
2915
2916 XtAddCallback(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON),
2917 XmNactivateCallback, dialogCloseCB, window);
2918
2919
2920 for (i=
1; i<nBtns; i++) {
2921 readStringArg(argList[i], &btnLabel, btnStorage, errMsg);
2922 btn = XtVaCreateManagedWidget(
"mdBtn", xmPushButtonWidgetClass, dialog,
2923 XmNlabelString, s1=XmStringCreateSimple(btnLabel),
2924 XmNuserData, (XtPointer)(
intptr_t)(i+
1),
NULL);
2925 XtAddCallback(btn, XmNactivateCallback, dialogBtnCB, window);
2926 XmStringFree(s1);
2927 }
2928
2929 #ifdef LESSTIF_VERSION
2930
2931
2932
2933 XtAddEventHandler(dialog, KeyPressMask, False, dialogEscCB,
2934 (XtPointer)window);
2935 XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
2936 True, GrabModeAsync, GrabModeAsync);
2937 #endif
2938
2939
2940 ManageDialogCenteredOnPointer(dialog);
2941
2942
2943 PreemptMacro();
2944
2945
2946 result->tag =
INT_TAG;
2947 result->val.n =
0;
2948 return True;
2949 }
2950
2951 static void dialogBtnCB(Widget w, XtPointer clientData, XtPointer callData)
2952 {
2953 WindowInfo *window = (WindowInfo *)clientData;
2954 macroCmdInfo *cmdData = window->macroCmdData;
2955 XtPointer userData;
2956 DataValue retVal;
2957
2958
2959
2960
2961 if (cmdData ==
NULL)
2962 return;
2963 if (XtClass(w) == xmPushButtonWidgetClass) {
2964 XtVaGetValues(w, XmNuserData, &userData,
NULL);
2965 retVal.val.n = (
int)(
intptr_t)userData;
2966 }
else
2967 retVal.val.n =
1;
2968 retVal.tag =
INT_TAG;
2969 ModifyReturnedValue(cmdData->context, retVal);
2970
2971
2972 XtDestroyWidget(XtParent(cmdData->dialog));
2973 cmdData->dialog =
NULL;
2974
2975
2976 ResumeMacroExecution(window);
2977 }
2978
2979 static void dialogCloseCB(Widget w, XtPointer clientData, XtPointer callData)
2980 {
2981 WindowInfo *window = (WindowInfo *)clientData;
2982 macroCmdInfo *cmdData = window->macroCmdData;
2983 DataValue retVal;
2984
2985
2986 retVal.val.n =
0;
2987 retVal.tag =
INT_TAG;
2988 ModifyReturnedValue(cmdData->context, retVal);
2989
2990
2991 XtDestroyWidget(XtParent(cmdData->dialog));
2992 cmdData->dialog =
NULL;
2993
2994
2995 ResumeMacroExecution(window);
2996 }
2997
2998 #ifdef LESSTIF_VERSION
2999 static void dialogEscCB(Widget w, XtPointer clientData, XEvent *event,
3000 Boolean *cont)
3001 {
3002 if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
3003 return;
3004 if (clientData !=
NULL) {
3005 dialogCloseCB(w, (WindowInfo *)clientData,
NULL);
3006 }
3007 *cont = False;
3008 }
3009 #endif
3010
3011 static int stringDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
3012 DataValue *result,
char **errMsg)
3013 {
3014 macroCmdInfo *cmdData;
3015 char stringStorage[
TYPE_INT_STR_SIZE(
int)];
3016 char btnStorage[
TYPE_INT_STR_SIZE(
int)];
3017 char *btnLabel;
3018 char *message;
3019 Widget dialog, btn;
3020 int i, nBtns;
3021 XmString s1, s2;
3022 Arg al[
20];
3023 int ac;
3024
3025
3026
3027 window = MacroRunWindow();
3028 cmdData = window->macroCmdData;
3029
3030
3031
3032 if (!cmdData) {
3033 *errMsg =
"%s can''t be called from non-suspendable context";
3034 return False;
3035 }
3036
3037
3038
3039 if (nArgs ==
0) {
3040 *errMsg =
"%s subroutine called with no arguments";
3041 return False;
3042 }
3043 if (!readStringArg(argList[
0], &message, stringStorage, errMsg)) {
3044 return False;
3045 }
3046
3047 for (i=
1; i<nArgs; i++) {
3048 if (!readStringArg(argList[i], &btnLabel, stringStorage, errMsg)) {
3049 return False;
3050 }
3051 }
3052 if (nArgs ==
1) {
3053 btnLabel =
"OK";
3054 nBtns =
1;
3055 }
3056 else {
3057 nBtns = nArgs -
1;
3058 argList++;
3059 readStringArg(argList[
0], &btnLabel, btnStorage, errMsg);
3060 }
3061
3062
3063 ac =
0;
3064 XtSetArg(al[ac], XmNtitle,
" "); ac++;
3065 XtSetArg(al[ac], XmNselectionLabelString, s1=
MKSTRING(message)); ac++;
3066 XtSetArg(al[ac], XmNokLabelString, s2=XmStringCreateSimple(btnLabel)); ac++;
3067 dialog = CreatePromptDialog(window->shell,
"macroStringDialog", al, ac);
3068 if (
1 == nArgs)
3069 {
3070
3071 XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
3072 XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
3073 NULL);
3074 }
3075
3076 XmStringFree(s1);
3077 XmStringFree(s2);
3078 AddMotifCloseCallback(XtParent(dialog), stringDialogCloseCB, window);
3079 XtAddCallback(dialog, XmNokCallback, stringDialogBtnCB, window);
3080 XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
3081 XmNuserData, (XtPointer)
1,
NULL);
3082 cmdData->dialog = dialog;
3083
3084
3085 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
3086 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
3087
3088
3089
3090 XtAddCallback(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON),
3091 XmNactivateCallback, stringDialogCloseCB, window);
3092
3093
3094
3095
3096 XtVaCreateWidget(
"x", xmSeparatorWidgetClass, dialog,
NULL);
3097 for (i=
1; i<nBtns; i++) {
3098 readStringArg(argList[i], &btnLabel, btnStorage, errMsg);
3099 btn = XtVaCreateManagedWidget(
"mdBtn", xmPushButtonWidgetClass, dialog,
3100 XmNlabelString, s1=XmStringCreateSimple(btnLabel),
3101 XmNuserData, (XtPointer)(
intptr_t)(i+
1),
NULL);
3102 XtAddCallback(btn, XmNactivateCallback, stringDialogBtnCB, window);
3103 XmStringFree(s1);
3104 }
3105
3106 #ifdef LESSTIF_VERSION
3107
3108
3109
3110 XtAddEventHandler(dialog, KeyPressMask, False, stringDialogEscCB,
3111 (XtPointer)window);
3112 XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
3113 True, GrabModeAsync, GrabModeAsync);
3114 #endif
3115
3116
3117 ManageDialogCenteredOnPointer(dialog);
3118
3119
3120 PreemptMacro();
3121
3122
3123 result->tag =
INT_TAG;
3124 result->val.n =
0;
3125 return True;
3126 }
3127
3128 static void stringDialogBtnCB(Widget w, XtPointer clientData,
3129 XtPointer callData)
3130 {
3131 WindowInfo *window = (WindowInfo *)clientData;
3132 macroCmdInfo *cmdData = window->macroCmdData;
3133 XtPointer userData;
3134 DataValue retVal;
3135 char *text;
3136 int btnNum;
3137
3138
3139 if (cmdData ==
NULL)
3140 return;
3141
3142
3143 text = XmTextGetString(XmSelectionBoxGetChild(cmdData->dialog,
3144 XmDIALOG_TEXT));
3145 retVal.tag =
STRING_TAG;
3146 AllocNStringCpy(&retVal.val.str, text);
3147 NEditFree(text);
3148 ModifyReturnedValue(cmdData->context, retVal);
3149
3150
3151
3152
3153 if (XtClass(w) == xmPushButtonWidgetClass) {
3154 XtVaGetValues(w, XmNuserData, &userData,
NULL);
3155 btnNum = (
int)(
intptr_t)userData;
3156 }
else
3157 btnNum =
1;
3158
3159
3160 ReturnGlobals[
STRING_DIALOG_BUTTON]->value.tag =
INT_TAG;
3161 ReturnGlobals[
STRING_DIALOG_BUTTON]->value.val.n = btnNum;
3162
3163
3164 XtDestroyWidget(XtParent(cmdData->dialog));
3165 cmdData->dialog =
NULL;
3166
3167
3168 ResumeMacroExecution(window);
3169 }
3170
3171 static void stringDialogCloseCB(Widget w, XtPointer clientData,
3172 XtPointer callData)
3173 {
3174 WindowInfo *window = (WindowInfo *)clientData;
3175 macroCmdInfo *cmdData = window->macroCmdData;
3176 DataValue retVal;
3177
3178
3179 if (cmdData ==
NULL)
3180 return;
3181
3182
3183 retVal.tag =
STRING_TAG;
3184 retVal.val.str.rep =
PERM_ALLOC_STR(
"");
3185 retVal.val.str.len =
0;
3186 ModifyReturnedValue(cmdData->context, retVal);
3187
3188
3189 ReturnGlobals[
STRING_DIALOG_BUTTON]->value.tag =
INT_TAG;
3190 ReturnGlobals[
STRING_DIALOG_BUTTON]->value.val.n =
0;
3191
3192
3193 XtDestroyWidget(XtParent(cmdData->dialog));
3194 cmdData->dialog =
NULL;
3195
3196
3197 ResumeMacroExecution(window);
3198 }
3199
3200 #ifdef LESSTIF_VERSION
3201 static void stringDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
3202 Boolean *cont)
3203 {
3204 if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
3205 return;
3206 if (clientData !=
NULL) {
3207 stringDialogCloseCB(w, (WindowInfo *)clientData,
NULL);
3208 }
3209 *cont = False;
3210 }
3211 #endif
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237 static int calltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
3238 DataValue *result,
char **errMsg)
3239 {
3240 char stringStorage[
TYPE_INT_STR_SIZE(
int)], *tipText, *txtArg;
3241 Boolean anchored = False, lookup = True;
3242 int mode = -
1, i;
3243 int anchorPos, hAlign =
TIP_LEFT, vAlign =
TIP_BELOW,
3244 alignMode =
TIP_SLOPPY;
3245
3246
3247 if (nArgs <
1) {
3248 *errMsg =
"%s subroutine called with too few arguments";
3249 return False;
3250 }
3251 if (nArgs >
6) {
3252 *errMsg =
"%s subroutine called with too many arguments";
3253 return False;
3254 }
3255
3256
3257 if (!readStringArg(argList[
0], &tipText, stringStorage, errMsg))
3258 return False;
3259
3260
3261 if (nArgs >
1) {
3262 if (!readIntArg(argList[
1], &anchorPos, errMsg))
3263 return False;
3264 }
else {
3265 anchorPos = -
1;
3266 }
3267 if (anchorPos >=
0) anchored = True;
3268
3269
3270 for (i =
2; i < nArgs; ++i) {
3271 if (!readStringArg(argList[i], &txtArg, stringStorage, errMsg)){
3272 return False;
3273 }
3274 switch( txtArg[
0] ) {
3275 case 'c':
3276 if (strcmp(txtArg,
"center"))
3277 goto bad_arg;
3278 hAlign =
TIP_CENTER;
3279 break;
3280 case 'r':
3281 if (strcmp(txtArg,
"right"))
3282 goto bad_arg;
3283 hAlign =
TIP_RIGHT;
3284 break;
3285 case 'a':
3286 if (strcmp(txtArg,
"above"))
3287 goto bad_arg;
3288 vAlign =
TIP_ABOVE;
3289 break;
3290 case 's':
3291 if (strcmp(txtArg,
"strict"))
3292 goto bad_arg;
3293 alignMode =
TIP_STRICT;
3294 break;
3295 case 't':
3296 if (!strcmp(txtArg,
"tipText"))
3297 mode = -
1;
3298 else if (!strcmp(txtArg,
"tipKey"))
3299 mode =
TIP;
3300 else if (!strcmp(txtArg,
"tagKey"))
3301 mode =
TIP_FROM_TAG;
3302 else
3303 goto bad_arg;
3304 break;
3305 default:
3306 goto bad_arg;
3307 }
3308 }
3309
3310 result->tag =
INT_TAG;
3311 if (mode <
0) lookup = False;
3312
3313 result->val.n = ShowTipString( window, tipText, anchored, anchorPos, lookup,
3314 mode, hAlign, vAlign, alignMode );
3315
3316 return True;
3317
3318 bad_arg:
3319
3320
3321
3322
3323 *errMsg =
"unrecognized argument to %s";
3324 return False;
3325 }
3326
3327
3328
3329
3330 static int killCalltipMS(WindowInfo *window, DataValue *argList,
int nArgs,
3331 DataValue *result,
char **errMsg)
3332 {
3333 int calltipID =
0;
3334
3335 if (nArgs >
1) {
3336 *errMsg =
"%s subroutine called with too many arguments";
3337 return False;
3338 }
3339 if (nArgs >
0) {
3340 if (!readIntArg(argList[
0], &calltipID, errMsg))
3341 return False;
3342 }
3343
3344 KillCalltip( window, calltipID );
3345
3346 result->tag =
NO_TAG;
3347 return True;
3348 }
3349
3350
3351
3352
3353 static int calltipIDMV(WindowInfo *window, DataValue *argList,
3354 int nArgs, DataValue *result,
char **errMsg)
3355 {
3356 result->tag =
INT_TAG;
3357 result->val.n = GetCalltipID(window,
0);
3358 return True;
3359 }
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382 static int filenameDialogMS(WindowInfo* window, DataValue* argList,
int nArgs,
3383 DataValue* result,
char** errMsg)
3384 {
3385 char stringStorage[
5][
TYPE_INT_STR_SIZE(
int)];
3386 char* title =
"Choose Filename";
3387 char* mode =
"exist";
3388 char* defaultPath =
"";
3389 char* filter =
"";
3390 char* defaultName =
"";
3391 char* orgDefaultPath;
3392 char* orgFilter;
3393 int gfnResult;
3394
3395
3396
3397 window = MacroRunWindow();
3398
3399
3400
3401 if (
NULL == window->macroCmdData) {
3402 M_FAILURE(
"%s can''t be called from non-suspendable context");
3403 }
3404
3405
3406 if (nArgs >
0 && !readStringArg(argList[
0], &title, stringStorage[
0],
3407 errMsg)) {
3408 return False;
3409 }
3410
3411 if (nArgs >
1 && !readStringArg(argList[
1], &mode, stringStorage[
1],
3412 errMsg)) {
3413 return False;
3414 }
3415 if (
0 != strcmp(mode,
"exist") &&
0 != strcmp(mode,
"new")) {
3416 M_FAILURE(
"Invalid value for mode in %s");
3417 }
3418
3419 if (nArgs >
2 && !readStringArg(argList[
2], &defaultPath, stringStorage[
2],
3420 errMsg)) {
3421 return False;
3422 }
3423
3424 if (nArgs >
3 && !readStringArg(argList[
3], &filter, stringStorage[
3],
3425 errMsg)) {
3426 return False;
3427 }
3428
3429 if (nArgs >
4 && !readStringArg(argList[
4], &defaultName, stringStorage[
4],
3430 errMsg)) {
3431 return False;
3432 }
3433
3434 if (nArgs >
5) {
3435 M_FAILURE(
"%s called with too many arguments. Expects at most 5 arguments.");
3436 }
3437
3438
3439 orgDefaultPath = GetFileDialogDefaultDirectory();
3440 if (
'\0' != defaultPath[
0]) {
3441 SetFileDialogDefaultDirectory(defaultPath);
3442 }
else {
3443 SetFileDialogDefaultDirectory(window->path);
3444 }
3445
3446
3447 orgFilter = FileDialogGetFilter();
3448 if (
'\0' != filter[
0]) {
3449 FileDialogSetFilter(filter);
3450 }
3451
3452
3453
3454 window->macroBlocking = True;
3455 FileSelection getfile = {
NULL,
NULL };
3456 if (
0 == strcmp(mode,
"exist")) {
3457 gfnResult = GetExistingFilename(window->shell, title, &getfile);
3458 }
else {
3459 gfnResult = GetNewFilename(window->shell, title, &getfile, defaultName);
3460 }
3461 window->macroBlocking = False;
3462
3463
3464 SetFileDialogDefaultDirectory(orgDefaultPath);
3465 FileDialogSetFilter(orgFilter);
3466 NEditFree(orgDefaultPath);
3467 NEditFree(orgFilter);
3468
3469 result->tag =
STRING_TAG;
3470 if (
GFN_OK == gfnResult) {
3471
3472 if (!AllocNStringNCpy(&result->val.str, getfile.path,
MAXPATHLEN)) {
3473 M_FAILURE(
"failed to allocate return value: %s");
3474 }
3475 NEditFree(getfile.path);
3476 }
else {
3477
3478 result->val.str.rep =
PERM_ALLOC_STR(
"");
3479 result->val.str.len =
0;
3480 }
3481
3482 return True;
3483 }
3484
3485
3486 static int listDialogMS(WindowInfo *window, DataValue *argList,
int nArgs,
3487 DataValue *result,
char **errMsg)
3488 {
3489 macroCmdInfo *cmdData;
3490 char stringStorage[
TYPE_INT_STR_SIZE(
int)];
3491 char textStorage[
TYPE_INT_STR_SIZE(
int)];
3492 char btnStorage[
TYPE_INT_STR_SIZE(
int)];
3493 char *btnLabel;
3494 char *message, *text;
3495 Widget dialog, btn;
3496 int i, nBtns;
3497 XmString s1, s2;
3498 long nlines =
0;
3499 char *p, *old_p, **text_lines, *tmp;
3500 int tmp_len;
3501 int n, is_last;
3502 XmString *test_strings;
3503 int tabDist;
3504 Arg al[
20];
3505 int ac;
3506
3507
3508
3509
3510 window = MacroRunWindow();
3511 cmdData = window->macroCmdData;
3512
3513
3514
3515 if (!cmdData) {
3516 *errMsg =
"%s can''t be called from non-suspendable context";
3517 return False;
3518 }
3519
3520
3521
3522 if (nArgs <
2) {
3523 *errMsg =
"%s subroutine called with no message, string or arguments";
3524 return False;
3525 }
3526
3527 if (!readStringArg(argList[
0], &message, stringStorage, errMsg))
3528 return False;
3529
3530 if (!readStringArg(argList[
1], &text, textStorage, errMsg))
3531 return False;
3532
3533 if (!text || text[
0] ==
'\0') {
3534 *errMsg =
"%s subroutine called with empty list data";
3535 return False;
3536 }
3537
3538
3539 for (i=
2; i<nArgs; i++)
3540 if (!readStringArg(argList[i], &btnLabel, btnStorage, errMsg))
3541 return False;
3542
3543
3544 if (nArgs ==
2) {
3545 btnLabel =
"OK";
3546 nBtns =
1;
3547 }
3548 else {
3549 nBtns = nArgs -
2;
3550 argList +=
2;
3551 readStringArg(argList[
0], &btnLabel, btnStorage, errMsg);
3552 }
3553
3554
3555 nlines =
1;
3556 for (p = text; *p; p++)
3557 if (*p ==
'\n')
3558 nlines++;
3559
3560
3561
3562
3563 test_strings = (XmString *) NEditMalloc(
sizeof(XmString) * nlines);
3564 text_lines = (
char **)NEditMalloc(
sizeof(
char *) * (nlines +
1));
3565 for (n =
0; n < nlines; n++) {
3566 test_strings[n] = (XmString)
0;
3567 text_lines[n] = (
char *)
0;
3568 }
3569 text_lines[n] = (
char *)
0;
3570
3571
3572 tabDist = window->buffer->tabDist;
3573
3574
3575 n =
0;
3576 is_last =
0;
3577 p = old_p = text;
3578 tmp_len =
0;
3579 tmp = (
char*)NEditMalloc(
1);
3580 do {
3581 is_last = (*p ==
'\0');
3582 if (*p ==
'\n' || is_last) {
3583 *p =
'\0';
3584 if (strlen(old_p) >
0) {
3585 char *s, *t;
3586 int l;
3587
3588
3589 text_lines[n] = (
char *)NEditMalloc(strlen(old_p) +
1);
3590 strcpy(text_lines[n], old_p);
3591
3592
3593 for (s = old_p, l =
0; *s; s++)
3594 l += (*s ==
'\t') ? tabDist - (l % tabDist) :
1;
3595
3596
3597 if (l > tmp_len)
3598 tmp = (
char*)NEditRealloc(tmp, (tmp_len = l) +
1);
3599 for (s = old_p, t = tmp, l =
0; *s; s++) {
3600 if (*s ==
'\t') {
3601 for (i = tabDist - (l % tabDist); i--; l++)
3602 *t++ =
' ';
3603 }
3604 else {
3605 *t++ = *s;
3606 l++;
3607 }
3608 }
3609 *t =
'\0';
3610
3611 test_strings[n] =
MKSTRING(tmp);
3612 n++;
3613 }
3614 old_p = p +
1;
3615 if (!is_last)
3616 *p =
'\n';
3617 }
3618 p++;
3619 }
while (!is_last);
3620
3621 NEditFree(tmp);
3622 nlines = n;
3623 if (nlines ==
0) {
3624 test_strings[
0] =
MKSTRING(
"");
3625 nlines =
1;
3626 }
3627
3628
3629 ac =
0;
3630 XtSetArg(al[ac], XmNtitle,
" "); ac++;
3631 XtSetArg(al[ac], XmNlistLabelString, s1=
MKSTRING(message)); ac++;
3632 XtSetArg(al[ac], XmNlistItems, test_strings); ac++;
3633 XtSetArg(al[ac], XmNlistItemCount, nlines); ac++;
3634 XtSetArg(al[ac], XmNlistVisibleItemCount, (nlines >
10) ?
10 : nlines); ac++;
3635 XtSetArg(al[ac], XmNokLabelString, s2=XmStringCreateSimple(btnLabel)); ac++;
3636 dialog = CreateSelectionDialog(window->shell,
"macroListDialog", al, ac);
3637 if (
2 == nArgs)
3638 {
3639
3640 XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
3641 XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
3642 NULL);
3643 }
3644
3645 AddMotifCloseCallback(XtParent(dialog), listDialogCloseCB, window);
3646 XtAddCallback(dialog, XmNokCallback, listDialogBtnCB, window);
3647 XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
3648 XmNuserData, (XtPointer)
1,
NULL);
3649 XmStringFree(s1);
3650 XmStringFree(s2);
3651 cmdData->dialog = dialog;
3652
3653
3654 while (n--)
3655 XmStringFree(test_strings[n]);
3656 NEditFree(test_strings);
3657
3658
3659 XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_LIST),
3660 XmNselectionPolicy, XmSINGLE_SELECT,
3661 XmNuserData, (XtPointer)text_lines,
NULL);
3662
3663
3664 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_APPLY_BUTTON));
3665 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
3666 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
3667 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT));
3668 XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_SELECTION_LABEL));
3669
3670
3671
3672 XtAddCallback(XmSelectionBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON),
3673 XmNactivateCallback, listDialogCloseCB, window);
3674
3675
3676
3677
3678 XtVaCreateWidget(
"x", xmSeparatorWidgetClass, dialog,
NULL);
3679 for (i=
1; i<nBtns; i++) {
3680 readStringArg(argList[i], &btnLabel, btnStorage, errMsg);
3681 btn = XtVaCreateManagedWidget(
"mdBtn", xmPushButtonWidgetClass, dialog,
3682 XmNlabelString, s1=XmStringCreateSimple(btnLabel),
3683 XmNuserData, (XtPointer)(
intptr_t)(i+
1),
NULL);
3684 XtAddCallback(btn, XmNactivateCallback, listDialogBtnCB, window);
3685 XmStringFree(s1);
3686 }
3687
3688 #ifdef LESSTIF_VERSION
3689
3690
3691 XtAddEventHandler(dialog, KeyPressMask, False, listDialogEscCB,
3692 (XtPointer)window);
3693 XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
3694 True, GrabModeAsync, GrabModeAsync);
3695 #endif
3696
3697
3698 ManageDialogCenteredOnPointer(dialog);
3699
3700
3701 PreemptMacro();
3702
3703
3704 result->tag =
INT_TAG;
3705 result->val.n =
0;
3706 return True;
3707 }
3708
3709 static void listDialogBtnCB(Widget w, XtPointer clientData,
3710 XtPointer callData)
3711 {
3712 WindowInfo *window = (WindowInfo *)clientData;
3713 macroCmdInfo *cmdData = window->macroCmdData;
3714 XtPointer userData;
3715 DataValue retVal;
3716 char *text;
3717 char **text_lines;
3718 int btnNum;
3719 int n_sel, *seltable, sel_index =
0;
3720 Widget theList;
3721 size_t length;
3722
3723
3724 if (cmdData ==
NULL)
3725 return;
3726
3727 theList = XmSelectionBoxGetChild(cmdData->dialog, XmDIALOG_LIST);
3728
3729 XtVaGetValues(theList, XmNuserData, &text_lines,
NULL);
3730 if (!XmListGetSelectedPos(theList, &seltable, &n_sel)) {
3731 n_sel =
0;
3732 }
3733 else {
3734 sel_index = seltable[
0] -
1;
3735 NEditFree(seltable);
3736 }
3737
3738 if (!n_sel) {
3739 text = NEditStrdup(
"");
3740 length =
0;
3741 }
3742 else {
3743 length = strlen((
char *)text_lines[sel_index]);
3744 text = NEditStrdup(text_lines[sel_index]);
3745 }
3746
3747
3748 for (sel_index =
0; text_lines[sel_index]; sel_index++)
3749 NEditFree(text_lines[sel_index]);
3750 NEditFree(text_lines);
3751
3752 retVal.tag =
STRING_TAG;
3753 retVal.val.str.rep = text;
3754 retVal.val.str.len = length;
3755 ModifyReturnedValue(cmdData->context, retVal);
3756
3757
3758
3759
3760 if (XtClass(w) == xmPushButtonWidgetClass) {
3761 XtVaGetValues(w, XmNuserData, &userData,
NULL);
3762 btnNum = (
int)(
intptr_t)userData;
3763 }
else
3764 btnNum =
1;
3765
3766
3767 ReturnGlobals[
LIST_DIALOG_BUTTON]->value.tag =
INT_TAG;
3768 ReturnGlobals[
LIST_DIALOG_BUTTON]->value.val.n = btnNum;
3769
3770
3771 XtDestroyWidget(XtParent(cmdData->dialog));
3772 cmdData->dialog =
NULL;
3773
3774
3775 ResumeMacroExecution(window);
3776 }
3777
3778 static void listDialogCloseCB(Widget w, XtPointer clientData,
3779 XtPointer callData)
3780 {
3781 WindowInfo *window = (WindowInfo *)clientData;
3782 macroCmdInfo *cmdData = window->macroCmdData;
3783 DataValue retVal;
3784 char **text_lines;
3785 int sel_index;
3786 Widget theList;
3787
3788
3789 if (cmdData ==
NULL)
3790 return;
3791
3792
3793 theList = XmSelectionBoxGetChild(cmdData->dialog, XmDIALOG_LIST);
3794 XtVaGetValues(theList, XmNuserData, &text_lines,
NULL);
3795 for (sel_index =
0; text_lines[sel_index]; sel_index++)
3796 NEditFree(text_lines[sel_index]);
3797 NEditFree(text_lines);
3798
3799
3800 retVal.tag =
STRING_TAG;
3801 retVal.val.str.rep = NEditStrdup(
"");
3802 retVal.val.str.len =
0;
3803 ModifyReturnedValue(cmdData->context, retVal);
3804
3805
3806 ReturnGlobals[
LIST_DIALOG_BUTTON]->value.tag =
INT_TAG;
3807 ReturnGlobals[
LIST_DIALOG_BUTTON]->value.val.n =
0;
3808
3809
3810 XtDestroyWidget(XtParent(cmdData->dialog));
3811 cmdData->dialog =
NULL;
3812
3813
3814 ResumeMacroExecution(window);
3815 }
3816
3817
3818 #ifdef LESSTIF_VERSION
3819 static void listDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
3820 Boolean *cont)
3821 {
3822 if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
3823 return;
3824 if (clientData !=
NULL) {
3825 listDialogCloseCB(w, (WindowInfo *)clientData,
NULL);
3826 }
3827 *cont = False;
3828 }
3829 #endif
3830
3831
3832 static int stringCompareMS(WindowInfo *window, DataValue *argList,
int nArgs,
3833 DataValue *result,
char **errMsg)
3834 {
3835 char stringStorage[
3][
TYPE_INT_STR_SIZE(
int)];
3836 char *leftStr, *rightStr, *argStr;
3837 int considerCase = True;
3838 int i;
3839 int compareResult;
3840
3841 if (nArgs <
2) {
3842 return(wrongNArgsErr(errMsg));
3843 }
3844 if (!readStringArg(argList[
0], &leftStr, stringStorage[
0], errMsg))
3845 return False;
3846 if (!readStringArg(argList[
1], &rightStr, stringStorage[
1], errMsg))
3847 return False;
3848 for (i =
2; i < nArgs; ++i) {
3849 if (!readStringArg(argList[i], &argStr, stringStorage[
2], errMsg))
3850 return False;
3851 else if (!strcmp(argStr,
"case"))
3852 considerCase = True;
3853 else if (!strcmp(argStr,
"nocase"))
3854 considerCase = False;
3855 else {
3856 *errMsg =
"Unrecognized argument to %s";
3857 return False;
3858 }
3859 }
3860 if (considerCase) {
3861 compareResult = strcmp(leftStr, rightStr);
3862 compareResult = (compareResult >
0) ?
1 : ((compareResult <
0) ? -
1 :
0);
3863 }
3864 else {
3865 compareResult = strcasecmp(leftStr, rightStr);
3866 }
3867 result->tag =
INT_TAG;
3868 result->val.n = compareResult;
3869 return True;
3870 }
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883 static int splitMS(WindowInfo *window, DataValue *argList,
int nArgs,
3884 DataValue *result,
char **errMsg)
3885 {
3886 char stringStorage[
3][
TYPE_INT_STR_SIZE(
int)];
3887 char *sourceStr, *splitStr, *typeSplitStr;
3888 int searchType, beginPos, foundStart, foundEnd, strLength, lastEnd;
3889 int found, elementEnd, indexNum;
3890 char indexStr[
TYPE_INT_STR_SIZE(
int)], *allocIndexStr;
3891 DataValue element;
3892 int elementLen;
3893
3894 if (nArgs <
2) {
3895 return(wrongNArgsErr(errMsg));
3896 }
3897 if (!readStringArg(argList[
0], &sourceStr, stringStorage[
0], errMsg)) {
3898 *errMsg =
"first argument must be a string: %s";
3899 return(False);
3900 }
3901 if (!readStringArg(argList[
1], &splitStr, stringStorage[
1], errMsg)) {
3902 splitStr =
NULL;
3903 }
3904 else {
3905 if (splitStr[
0] ==
0) {
3906 splitStr =
NULL;
3907 }
3908 }
3909 if (splitStr ==
NULL) {
3910 *errMsg =
"second argument must be a non-empty string: %s";
3911 return(False);
3912 }
3913 if (nArgs >
2 && readStringArg(argList[
2], &typeSplitStr, stringStorage[
2], errMsg)) {
3914 if (!StringToSearchType(typeSplitStr, &searchType)) {
3915 *errMsg =
"unrecognized argument to %s";
3916 return(False);
3917 }
3918 }
3919 else {
3920 searchType =
SEARCH_LITERAL;
3921 }
3922
3923 result->tag =
ARRAY_TAG;
3924 result->val.arrayPtr = ArrayNew();
3925
3926 beginPos =
0;
3927 lastEnd =
0;
3928 indexNum =
0;
3929 strLength = strlen(sourceStr);
3930 found =
1;
3931 while (found && beginPos < strLength) {
3932 sprintf(indexStr,
"%d", indexNum);
3933 allocIndexStr = AllocString(strlen(indexStr) +
1);
3934 if (!allocIndexStr) {
3935 *errMsg =
"array element failed to allocate key: %s";
3936 return(False);
3937 }
3938 strcpy(allocIndexStr, indexStr);
3939 found = SearchString(sourceStr, splitStr,
SEARCH_FORWARD, searchType,
3940 False, beginPos, &foundStart, &foundEnd,
3941 NULL,
NULL, GetWindowDelimiters(window));
3942 elementEnd = found ? foundStart : strLength;
3943 elementLen = elementEnd - lastEnd;
3944 element.tag =
STRING_TAG;
3945 if (!AllocNStringNCpy(&element.val.str, &sourceStr[lastEnd], elementLen)) {
3946 *errMsg =
"failed to allocate element value: %s";
3947 return(False);
3948 }
3949
3950 if (!ArrayInsert(result, allocIndexStr, &element)) {
3951 M_ARRAY_INSERT_FAILURE();
3952 }
3953
3954 if (found) {
3955 if (foundStart == foundEnd) {
3956 beginPos = foundEnd +
1;
3957 }
else {
3958 beginPos = foundEnd;
3959 }
3960 }
else {
3961 beginPos = strLength;
3962 }
3963 lastEnd = foundEnd;
3964 ++indexNum;
3965 }
3966 if (found) {
3967 sprintf(indexStr,
"%d", indexNum);
3968 allocIndexStr = AllocString(strlen(indexStr) +
1);
3969 if (!allocIndexStr) {
3970 *errMsg =
"array element failed to allocate key: %s";
3971 return(False);
3972 }
3973 strcpy(allocIndexStr, indexStr);
3974 element.tag =
STRING_TAG;
3975 if (lastEnd == strLength) {
3976
3977 element.val.str.rep =
PERM_ALLOC_STR(
"");
3978 element.val.str.len =
0;
3979
3980 if (!ArrayInsert(result, allocIndexStr, &element)) {
3981 M_ARRAY_INSERT_FAILURE();
3982 }
3983 }
else {
3984
3985
3986 elementLen = strLength - lastEnd;
3987 if (!AllocNStringNCpy(&element.val.str, &sourceStr[lastEnd], elementLen)) {
3988 *errMsg =
"failed to allocate element value: %s";
3989 return(False);
3990 }
3991
3992 if (!ArrayInsert(result, allocIndexStr, &element)) {
3993 M_ARRAY_INSERT_FAILURE();
3994 }
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004 found = SearchString(sourceStr, splitStr,
SEARCH_FORWARD,
4005 searchType, False, strLength, &foundStart, &foundEnd,
4006 NULL,
NULL, GetWindowDelimiters(window));
4007 if (found) {
4008 ++indexNum;
4009 sprintf(indexStr,
"%d", indexNum);
4010 allocIndexStr = AllocString(strlen(indexStr) +
1);
4011 if (!allocIndexStr) {
4012 *errMsg =
"array element failed to allocate key: %s";
4013 return(False);
4014 }
4015 strcpy(allocIndexStr, indexStr);
4016 element.tag =
STRING_TAG;
4017 element.val.str.rep =
PERM_ALLOC_STR(
"");
4018 element.val.str.len =
0;
4019
4020 if (!ArrayInsert(result, allocIndexStr, &element)) {
4021 M_ARRAY_INSERT_FAILURE();
4022 }
4023 }
4024 }
4025 }
4026 return(True);
4027 }
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063 static int cursorMV(WindowInfo *window, DataValue *argList,
int nArgs,
4064 DataValue *result,
char **errMsg)
4065 {
4066 result->tag =
INT_TAG;
4067 result->val.n = TextGetCursorPos(window->lastFocus);
4068 return True;
4069 }
4070
4071 static int lineMV(WindowInfo *window, DataValue *argList,
int nArgs,
4072 DataValue *result,
char **errMsg)
4073 {
4074 int line, cursorPos, colNum;
4075
4076 result->tag =
INT_TAG;
4077 cursorPos = TextGetCursorPos(window->lastFocus);
4078 if (!TextPosToLineAndCol(window->lastFocus, cursorPos, &line, &colNum))
4079 line = BufCountLines(window->buffer,
0, cursorPos) +
1;
4080 result->val.n = line;
4081 return True;
4082 }
4083
4084 static int columnMV(WindowInfo *window, DataValue *argList,
int nArgs,
4085 DataValue *result,
char **errMsg)
4086 {
4087 textBuffer *buf = window->buffer;
4088 int cursorPos;
4089
4090 result->tag =
INT_TAG;
4091 cursorPos = TextGetCursorPos(window->lastFocus);
4092 result->val.n = BufCountDispChars(buf, BufStartOfLine(buf, cursorPos),
4093 cursorPos);
4094 return True;
4095 }
4096
4097 static int fileNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
4098 DataValue *result,
char **errMsg)
4099 {
4100 result->tag =
STRING_TAG;
4101 AllocNStringCpy(&result->val.str, window->filename);
4102 return True;
4103 }
4104
4105 static int filePathMV(WindowInfo *window, DataValue *argList,
int nArgs,
4106 DataValue *result,
char **errMsg)
4107 {
4108 result->tag =
STRING_TAG;
4109 AllocNStringCpy(&result->val.str, window->path);
4110 return True;
4111 }
4112
4113 static int lengthMV(WindowInfo *window, DataValue *argList,
int nArgs,
4114 DataValue *result,
char **errMsg)
4115 {
4116 result->tag =
INT_TAG;
4117 result->val.n = window->buffer->length;
4118 return True;
4119 }
4120
4121 static int selectionStartMV(WindowInfo *window, DataValue *argList,
int nArgs,
4122 DataValue *result,
char **errMsg)
4123 {
4124 result->tag =
INT_TAG;
4125 result->val.n = window->buffer->primary.selected ?
4126 window->buffer->primary.start : -
1;
4127 return True;
4128 }
4129
4130 static int selectionEndMV(WindowInfo *window, DataValue *argList,
int nArgs,
4131 DataValue *result,
char **errMsg)
4132 {
4133 result->tag =
INT_TAG;
4134 result->val.n = window->buffer->primary.selected ?
4135 window->buffer->primary.end : -
1;
4136 return True;
4137 }
4138
4139 static int selectionLeftMV(WindowInfo *window, DataValue *argList,
int nArgs,
4140 DataValue *result,
char **errMsg)
4141 {
4142 selection *sel = &window->buffer->primary;
4143
4144 result->tag =
INT_TAG;
4145 result->val.n = sel->selected && sel->rectangular ? sel->rectStart : -
1;
4146 return True;
4147 }
4148
4149 static int selectionRightMV(WindowInfo *window, DataValue *argList,
int nArgs,
4150 DataValue *result,
char **errMsg)
4151 {
4152 selection *sel = &window->buffer->primary;
4153
4154 result->tag =
INT_TAG;
4155 result->val.n = sel->selected && sel->rectangular ? sel->rectEnd : -
1;
4156 return True;
4157 }
4158
4159 static int wrapMarginMV(WindowInfo *window, DataValue *argList,
int nArgs,
4160 DataValue *result,
char **errMsg)
4161 {
4162 int margin, nCols;
4163
4164 XtVaGetValues(window->textArea, textNcolumns, &nCols,
4165 textNwrapMargin, &margin,
NULL);
4166 result->tag =
INT_TAG;
4167 result->val.n = margin ==
0 ? nCols : margin;
4168 return True;
4169 }
4170
4171 static int statisticsLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
4172 DataValue *result,
char **errMsg)
4173 {
4174 result->tag =
INT_TAG;
4175 result->val.n = window->showStats ?
1 :
0;
4176 return True;
4177 }
4178
4179 static int incSearchLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
4180 DataValue *result,
char **errMsg)
4181 {
4182 result->tag =
INT_TAG;
4183 result->val.n = window->showISearchLine ?
1 :
0;
4184 return True;
4185 }
4186
4187 static int showLineNumbersMV(WindowInfo *window, DataValue *argList,
int nArgs,
4188 DataValue *result,
char **errMsg)
4189 {
4190 result->tag =
INT_TAG;
4191 result->val.n = window->showLineNumbers ?
1 :
0;
4192 return True;
4193 }
4194
4195 static int autoIndentMV(WindowInfo *window, DataValue *argList,
int nArgs,
4196 DataValue *result,
char **errMsg)
4197 {
4198 char *res =
NULL;
4199
4200 switch (window->indentStyle) {
4201 case NO_AUTO_INDENT:
4202 res =
PERM_ALLOC_STR(
"off");
4203 break;
4204 case AUTO_INDENT:
4205 res =
PERM_ALLOC_STR(
"on");
4206 break;
4207 case SMART_INDENT:
4208 res =
PERM_ALLOC_STR(
"smart");
4209 break;
4210 default:
4211 *errMsg =
"Invalid indent style value encountered in %s";
4212 return False;
4213 break;
4214 }
4215 result->tag =
STRING_TAG;
4216 result->val.str.rep = res;
4217 result->val.str.len = strlen(res);
4218 return True;
4219 }
4220
4221 static int wrapTextMV(WindowInfo *window, DataValue *argList,
int nArgs,
4222 DataValue *result,
char **errMsg)
4223 {
4224 char *res =
NULL;
4225
4226 switch (window->wrapMode) {
4227 case NO_WRAP:
4228 res =
PERM_ALLOC_STR(
"none");
4229 break;
4230 case NEWLINE_WRAP:
4231 res =
PERM_ALLOC_STR(
"auto");
4232 break;
4233 case CONTINUOUS_WRAP:
4234 res =
PERM_ALLOC_STR(
"continuous");
4235 break;
4236 default:
4237 *errMsg =
"Invalid wrap style value encountered in %s";
4238 return False;
4239 break;
4240 }
4241 result->tag =
STRING_TAG;
4242 result->val.str.rep = res;
4243 result->val.str.len = strlen(res);
4244 return True;
4245 }
4246
4247 static int highlightSyntaxMV(WindowInfo *window, DataValue *argList,
int nArgs,
4248 DataValue *result,
char **errMsg)
4249 {
4250 result->tag =
INT_TAG;
4251 result->val.n = window->highlightSyntax ?
1 :
0;
4252 return True;
4253 }
4254
4255 static int makeBackupCopyMV(WindowInfo *window, DataValue *argList,
int nArgs,
4256 DataValue *result,
char **errMsg)
4257 {
4258 result->tag =
INT_TAG;
4259 result->val.n = window->saveOldVersion ?
1 :
0;
4260 return True;
4261 }
4262
4263 static int incBackupMV(WindowInfo *window, DataValue *argList,
int nArgs,
4264 DataValue *result,
char **errMsg)
4265 {
4266 result->tag =
INT_TAG;
4267 result->val.n = window->autoSave ?
1 :
0;
4268 return True;
4269 }
4270
4271 static int showMatchingMV(WindowInfo *window, DataValue *argList,
int nArgs,
4272 DataValue *result,
char **errMsg)
4273 {
4274 char *res =
NULL;
4275
4276 switch (window->showMatchingStyle) {
4277 case NO_FLASH:
4278 res =
PERM_ALLOC_STR(
NO_FLASH_STRING);
4279 break;
4280 case FLASH_DELIMIT:
4281 res =
PERM_ALLOC_STR(
FLASH_DELIMIT_STRING);
4282 break;
4283 case FLASH_RANGE:
4284 res =
PERM_ALLOC_STR(
FLASH_RANGE_STRING);
4285 break;
4286 default:
4287 *errMsg =
"Invalid match flashing style value encountered in %s";
4288 return False;
4289 break;
4290 }
4291 result->tag =
STRING_TAG;
4292 result->val.str.rep = res;
4293 result->val.str.len = strlen(res);
4294 return True;
4295 }
4296
4297 static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList,
int nArgs,
4298 DataValue *result,
char **errMsg)
4299 {
4300 result->tag =
INT_TAG;
4301 result->val.n = window->matchSyntaxBased ?
1 :
0;
4302 return True;
4303 }
4304
4305
4306
4307 static int overTypeModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
4308 DataValue *result,
char **errMsg)
4309 {
4310 result->tag =
INT_TAG;
4311 result->val.n = window->overstrike ?
1 :
0;
4312 return True;
4313 }
4314
4315 static int readOnlyMV(WindowInfo *window, DataValue *argList,
int nArgs,
4316 DataValue *result,
char **errMsg)
4317 {
4318 result->tag =
INT_TAG;
4319 result->val.n = (
IS_ANY_LOCKED(window->lockReasons)) ?
1 :
0;
4320 return True;
4321 }
4322
4323 static int lockedMV(WindowInfo *window, DataValue *argList,
int nArgs,
4324 DataValue *result,
char **errMsg)
4325 {
4326 result->tag =
INT_TAG;
4327 result->val.n = (
IS_USER_LOCKED(window->lockReasons)) ?
1 :
0;
4328 return True;
4329 }
4330
4331 static int fileFormatMV(WindowInfo *window, DataValue *argList,
int nArgs,
4332 DataValue *result,
char **errMsg)
4333 {
4334 char *res =
NULL;
4335
4336 switch (window->fileFormat) {
4337 case UNIX_FILE_FORMAT:
4338 res =
PERM_ALLOC_STR(
"unix");
4339 break;
4340 case DOS_FILE_FORMAT:
4341 res =
PERM_ALLOC_STR(
"dos");
4342 break;
4343 case MAC_FILE_FORMAT:
4344 res =
PERM_ALLOC_STR(
"macintosh");
4345 break;
4346 default:
4347 *errMsg =
"Invalid linefeed style value encountered in %s";
4348 return False;
4349 }
4350 result->tag =
STRING_TAG;
4351 result->val.str.rep = res;
4352 result->val.str.len = strlen(res);
4353 return True;
4354 }
4355
4356 static int fontNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
4357 DataValue *result,
char **errMsg)
4358 {
4359 result->tag =
STRING_TAG;
4360 AllocNStringCpy(&result->val.str, window->fontName);
4361 return True;
4362 }
4363
4364 static int fontNameItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
4365 DataValue *result,
char **errMsg)
4366 {
4367 result->tag =
STRING_TAG;
4368 AllocNStringCpy(&result->val.str, window->italicFontName);
4369 return True;
4370 }
4371
4372 static int fontNameBoldMV(WindowInfo *window, DataValue *argList,
int nArgs,
4373 DataValue *result,
char **errMsg)
4374 {
4375 result->tag =
STRING_TAG;
4376 AllocNStringCpy(&result->val.str, window->boldFontName);
4377 return True;
4378 }
4379
4380 static int fontNameBoldItalicMV(WindowInfo *window, DataValue *argList,
int nArgs,
4381 DataValue *result,
char **errMsg)
4382 {
4383 result->tag =
STRING_TAG;
4384 AllocNStringCpy(&result->val.str, window->boldItalicFontName);
4385 return True;
4386 }
4387
4388 static int subscriptSepMV(WindowInfo *window, DataValue *argList,
int nArgs,
4389 DataValue *result,
char **errMsg)
4390 {
4391 result->tag =
STRING_TAG;
4392 result->val.str.rep =
PERM_ALLOC_STR(
ARRAY_DIM_SEP);
4393 result->val.str.len = strlen(result->val.str.rep);
4394 return True;
4395 }
4396
4397 static int minFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
4398 DataValue *result,
char **errMsg)
4399 {
4400 result->tag =
INT_TAG;
4401 result->val.n = TextGetMinFontWidth(window->textArea, window->highlightSyntax);
4402 return True;
4403 }
4404
4405 static int maxFontWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
4406 DataValue *result,
char **errMsg)
4407 {
4408 result->tag =
INT_TAG;
4409 result->val.n = TextGetMaxFontWidth(window->textArea, window->highlightSyntax);
4410 return True;
4411 }
4412
4413 static int topLineMV(WindowInfo *window, DataValue *argList,
int nArgs,
4414 DataValue *result,
char **errMsg)
4415 {
4416 result->tag =
INT_TAG;
4417 result->val.n = TextFirstVisibleLine(window->lastFocus);
4418 return True;
4419 }
4420
4421 static int numDisplayLinesMV(WindowInfo *window, DataValue *argList,
int nArgs,
4422 DataValue *result,
char **errMsg)
4423 {
4424 result->tag =
INT_TAG;
4425 result->val.n = TextNumVisibleLines(window->lastFocus);
4426 return True;
4427 }
4428
4429 static int displayWidthMV(WindowInfo *window, DataValue *argList,
int nArgs,
4430 DataValue *result,
char **errMsg)
4431 {
4432 result->tag =
INT_TAG;
4433 result->val.n = TextVisibleWidth(window->lastFocus);
4434 return True;
4435 }
4436
4437 static int activePaneMV(WindowInfo *window, DataValue *argList,
int nArgs,
4438 DataValue *result,
char **errMsg)
4439 {
4440 result->tag =
INT_TAG;
4441 result->val.n = WidgetToPaneIndex(window, window->lastFocus) +
1;
4442 return True;
4443 }
4444
4445 static int nPanesMV(WindowInfo *window, DataValue *argList,
int nArgs,
4446 DataValue *result,
char **errMsg)
4447 {
4448 result->tag =
INT_TAG;
4449 result->val.n = window->nPanes +
1;
4450 return True;
4451 }
4452
4453 static int emptyArrayMV(WindowInfo *window, DataValue *argList,
int nArgs,
4454 DataValue *result,
char **errMsg)
4455 {
4456 result->tag =
ARRAY_TAG;
4457 result->val.arrayPtr =
NULL;
4458 return True;
4459 }
4460
4461 static int serverNameMV(WindowInfo *window, DataValue *argList,
int nArgs,
4462 DataValue *result,
char **errMsg)
4463 {
4464 result->tag =
STRING_TAG;
4465 AllocNStringCpy(&result->val.str, GetPrefServerName());
4466 return True;
4467 }
4468
4469 static int tabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
4470 DataValue *result,
char **errMsg)
4471 {
4472 result->tag =
INT_TAG;
4473 result->val.n = window->buffer->tabDist;
4474 return True;
4475 }
4476
4477 static int emTabDistMV(WindowInfo *window, DataValue *argList,
int nArgs,
4478 DataValue *result,
char **errMsg)
4479 {
4480 int dist;
4481
4482 XtVaGetValues(window->textArea, textNemulateTabs, &dist,
NULL);
4483 result->tag =
INT_TAG;
4484 result->val.n = dist;
4485 return True;
4486 }
4487
4488 static int useTabsMV(WindowInfo *window, DataValue *argList,
int nArgs,
4489 DataValue *result,
char **errMsg)
4490 {
4491 result->tag =
INT_TAG;
4492 result->val.n = window->buffer->useTabs;
4493 return True;
4494 }
4495
4496 static int modifiedMV(WindowInfo *window, DataValue *argList,
int nArgs,
4497 DataValue *result,
char **errMsg)
4498 {
4499 result->tag =
INT_TAG;
4500 result->val.n = window->fileChanged;
4501 return True;
4502 }
4503
4504 static int languageModeMV(WindowInfo *window, DataValue *argList,
int nArgs,
4505 DataValue *result,
char **errMsg)
4506 {
4507 char *lmName = LanguageModeName(window->languageMode);
4508
4509 if (lmName ==
NULL)
4510 lmName =
"Plain";
4511 result->tag =
STRING_TAG;
4512 AllocNStringCpy(&result->val.str, lmName);
4513 return True;
4514 }
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534 static int rangesetListMV(WindowInfo *window, DataValue *argList,
int nArgs,
4535 DataValue *result,
char **errMsg)
4536 {
4537 RangesetTable *rangesetTable = window->buffer->rangesetTable;
4538 unsigned char *rangesetList;
4539 char *allocIndexStr;
4540 char indexStr[
TYPE_INT_STR_SIZE(
int)] ;
4541 int nRangesets, i;
4542 DataValue element;
4543
4544 result->tag =
ARRAY_TAG;
4545 result->val.arrayPtr = ArrayNew();
4546
4547 if (rangesetTable ==
NULL) {
4548 return True;
4549 }
4550
4551 rangesetList = RangesetGetList(rangesetTable);
4552 nRangesets = strlen((
char*)rangesetList);
4553 for(i =
0; i < nRangesets; i++) {
4554 element.tag =
INT_TAG;
4555 element.val.n = rangesetList[i];
4556
4557 sprintf(indexStr,
"%d", nRangesets - i -
1);
4558 allocIndexStr = AllocString(strlen(indexStr) +
1);
4559 if (allocIndexStr ==
NULL)
4560 M_FAILURE(
"Failed to allocate array key in %s");
4561 strcpy(allocIndexStr, indexStr);
4562
4563 if (!ArrayInsert(result, allocIndexStr, &element))
4564 M_FAILURE(
"Failed to insert array element in %s");
4565 }
4566
4567 return True;
4568 }
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580 static int versionMV(WindowInfo* window, DataValue* argList,
int nArgs,
4581 DataValue* result,
char** errMsg)
4582 {
4583 static unsigned version =
NEDIT_VERSION *
1000 +
NEDIT_REVISION;
4584
4585 result->tag =
INT_TAG;
4586 result->val.n = version;
4587 return True;
4588 }
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598 static int rangesetCreateMS(WindowInfo *window, DataValue *argList,
int nArgs,
4599 DataValue *result,
char **errMsg)
4600 {
4601 int label;
4602 int i, nRangesetsRequired;
4603 DataValue element;
4604 char indexStr[
TYPE_INT_STR_SIZE(
int)], *allocIndexStr;
4605
4606 RangesetTable *rangesetTable = window->buffer->rangesetTable;
4607
4608 if (nArgs >
1)
4609 return wrongNArgsErr(errMsg);
4610
4611 if (rangesetTable ==
NULL) {
4612 window->buffer->rangesetTable = rangesetTable =
4613 RangesetTableAlloc(window->buffer);
4614 }
4615
4616 if (nArgs ==
0) {
4617 label = RangesetCreate(rangesetTable);
4618
4619 result->tag =
INT_TAG;
4620 result->val.n = label;
4621 return True;
4622 }
4623 else {
4624 if (!readIntArg(argList[
0], &nRangesetsRequired, errMsg))
4625 return False;
4626
4627 result->tag =
ARRAY_TAG;
4628 result->val.arrayPtr = ArrayNew();
4629
4630 if (nRangesetsRequired > nRangesetsAvailable(rangesetTable))
4631 return True;
4632
4633 for (i =
0; i < nRangesetsRequired; i++) {
4634 element.tag =
INT_TAG;
4635 element.val.n = RangesetCreate(rangesetTable);
4636
4637 sprintf(indexStr,
"%d", i);
4638 allocIndexStr = AllocString(strlen(indexStr) +
1);
4639 if (!allocIndexStr) {
4640 *errMsg =
"Array element failed to allocate key: %s";
4641 return(False);
4642 }
4643 strcpy(allocIndexStr, indexStr);
4644 ArrayInsert(result, allocIndexStr, &element);
4645 }
4646
4647 return True;
4648 }
4649 }
4650
4651
4652
4653
4654 static int rangesetDestroyMS(WindowInfo *window, DataValue *argList,
int nArgs,
4655 DataValue *result,
char **errMsg)
4656 {
4657 RangesetTable *rangesetTable = window->buffer->rangesetTable;
4658 DataValue *array;
4659 DataValue element;
4660 char keyString[
TYPE_INT_STR_SIZE(
int)];
4661 int deleteLabels[
N_RANGESETS];
4662 int i, arraySize;
4663 int label =
0;
4664
4665 if (nArgs !=
1) {
4666 return wrongNArgsErr(errMsg);
4667 }
4668
4669 if (argList[
0].tag ==
ARRAY_TAG) {
4670 array = &argList[
0];
4671 arraySize = ArraySize(array);
4672
4673 if (arraySize >
N_RANGESETS) {
4674 M_FAILURE(
"Too many elements in array in %s");
4675 }
4676
4677 for (i =
0; i < arraySize; i++) {
4678 sprintf(keyString,
"%d", i);
4679
4680 if (!ArrayGet(array, keyString, &element)) {
4681 M_FAILURE(
"Invalid key in array in %s");
4682 }
4683
4684 if (!readIntArg(element, &label, errMsg)
4685 || !RangesetLabelOK(label)) {
4686 M_FAILURE(
"Invalid rangeset label in array in %s");
4687 }
4688
4689 deleteLabels[i] = label;
4690 }
4691
4692 for (i =
0; i < arraySize; i++) {
4693 RangesetForget(rangesetTable, deleteLabels[i]);
4694 }
4695 }
else {
4696 if (!readIntArg(argList[
0], &label, errMsg)
4697 || !RangesetLabelOK(label)) {
4698 M_FAILURE(
"Invalid rangeset label in %s");
4699 }
4700
4701 if(rangesetTable !=
NULL) {
4702 RangesetForget(rangesetTable, label);
4703 }
4704 }
4705
4706
4707 result->tag =
NO_TAG;
4708 return True;
4709 }
4710
4711
4712
4713
4714
4715
4716
4717 static int rangesetGetByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
4718 DataValue *result,
char **errMsg)
4719 {
4720 char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
4721 Rangeset *rangeset;
4722 int label;
4723 char *name, *rangeset_name;
4724 RangesetTable *rangesetTable = window->buffer->rangesetTable;
4725 unsigned char *rangesetList;
4726 char *allocIndexStr;
4727 char indexStr[
TYPE_INT_STR_SIZE(
int)] ;
4728 int nRangesets, i, insertIndex =
0;
4729 DataValue element;
4730
4731 if (nArgs !=
1) {
4732 return wrongNArgsErr(errMsg);
4733 }
4734
4735 if (!readStringArg(argList[
0], &name, stringStorage[
0], errMsg)) {
4736 M_FAILURE(
"First parameter is not a name string in %s");
4737 }
4738
4739 result->tag =
ARRAY_TAG;
4740 result->val.arrayPtr = ArrayNew();
4741
4742 if (rangesetTable ==
NULL) {
4743 return True;
4744 }
4745
4746 rangesetList = RangesetGetList(rangesetTable);
4747 nRangesets = strlen((
char *)rangesetList);
4748 for (i =
0; i < nRangesets; ++i) {
4749 label = rangesetList[i];
4750 rangeset = RangesetFetch(rangesetTable, label);
4751 if (rangeset) {
4752 rangeset_name = RangesetGetName(rangeset);
4753 if (strcmp(name, rangeset_name ? rangeset_name :
"") ==
0) {
4754 element.tag =
INT_TAG;
4755 element.val.n = label;
4756
4757 sprintf(indexStr,
"%d", insertIndex);
4758 allocIndexStr = AllocString(strlen(indexStr) +
1);
4759 if (allocIndexStr ==
NULL)
4760 M_FAILURE(
"Failed to allocate array key in %s");
4761
4762 strcpy(allocIndexStr, indexStr);
4763
4764 if (!ArrayInsert(result, allocIndexStr, &element))
4765 M_FAILURE(
"Failed to insert array element in %s");
4766
4767 ++insertIndex;
4768 }
4769 }
4770 }
4771
4772 return True;
4773 }
4774
4775
4776
4777
4778
4779
4780
4781
4782 static int rangesetAddMS(WindowInfo *window, DataValue *argList,
int nArgs,
4783 DataValue *result,
char **errMsg)
4784 {
4785 textBuffer *buffer = window->buffer;
4786 RangesetTable *rangesetTable = buffer->rangesetTable;
4787 Rangeset *targetRangeset, *sourceRangeset;
4788 int start, end, isRect, rectStart, rectEnd, maxpos, index;
4789 int label =
0;
4790
4791 if (nArgs <
1 || nArgs >
3)
4792 return wrongNArgsErr(errMsg);
4793
4794 if (!readIntArg(argList[
0], &label, errMsg)
4795 || !RangesetLabelOK(label)) {
4796 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
4797 }
4798
4799 if (rangesetTable ==
NULL) {
4800 M_FAILURE(
"Rangeset does not exist in %s");
4801 }
4802
4803 targetRangeset = RangesetFetch(rangesetTable, label);
4804
4805 if (targetRangeset ==
NULL) {
4806 M_FAILURE(
"Rangeset does not exist in %s");
4807 }
4808
4809 start = end = -
1;
4810
4811 if (nArgs ==
1) {
4812
4813 if (!BufGetSelectionPos(buffer, &start, &end,
4814 &isRect, &rectStart, &rectEnd) || isRect) {
4815 M_FAILURE(
"Selection missing or rectangular in call to %s");
4816 }
4817 if (!RangesetAddBetween(targetRangeset, start, end)) {
4818 M_FAILURE(
"Failure to add selection in %s");
4819 }
4820 }
4821
4822 if (nArgs ==
2) {
4823
4824 if (!readIntArg(argList[
1], &label, errMsg)
4825 || !RangesetLabelOK(label)) {
4826 M_FAILURE(
"Second parameter is an invalid rangeset label in %s");
4827 }
4828
4829 sourceRangeset = RangesetFetch(rangesetTable, label);
4830 if (sourceRangeset ==
NULL) {
4831 M_FAILURE(
"Second rangeset does not exist in %s");
4832 }
4833
4834 RangesetAdd(targetRangeset, sourceRangeset);
4835 }
4836
4837 if (nArgs ==
3) {
4838
4839 if (!readIntArg(argList[
1], &start, errMsg)) {
4840 return False;
4841 }
4842 if (!readIntArg(argList[
2], &end, errMsg)) {
4843 return False;
4844 }
4845
4846
4847 maxpos = buffer->length;
4848 if (start <
0) start =
0;
4849 if (start > maxpos) start = maxpos;
4850 if (end <
0) end =
0;
4851 if (end > maxpos) end = maxpos;
4852 if (start > end) {
int temp = start; start = end; end = temp;}
4853
4854 if ((start != end) && !RangesetAddBetween(targetRangeset, start, end)) {
4855 M_FAILURE(
"Failed to add range in %s");
4856 }
4857 }
4858
4859
4860 if (nArgs !=
2 && start >=
0) {
4861 start = (start + end) /
2;
4862 index =
1 + RangesetFindRangeOfPos(targetRangeset, start, False);
4863 }
4864 else {
4865 index =
0;
4866 }
4867
4868
4869 result->tag =
INT_TAG;
4870 result->val.n = index;
4871 return True;
4872 }
4873
4874
4875
4876
4877
4878
4879
4880
4881 static int rangesetSubtractMS(WindowInfo *window, DataValue *argList,
int nArgs,
4882 DataValue *result,
char **errMsg)
4883 {
4884 textBuffer *buffer = window->buffer;
4885 RangesetTable *rangesetTable = buffer->rangesetTable;
4886 Rangeset *targetRangeset, *sourceRangeset;
4887 int start, end, isRect, rectStart, rectEnd, maxpos;
4888 int label =
0;
4889
4890 if (nArgs <
1 || nArgs >
3) {
4891 return wrongNArgsErr(errMsg);
4892 }
4893
4894 if (!readIntArg(argList[
0], &label, errMsg)
4895 || !RangesetLabelOK(label)) {
4896 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
4897 }
4898
4899 if (rangesetTable ==
NULL) {
4900 M_FAILURE(
"Rangeset does not exist in %s");
4901 }
4902
4903 targetRangeset = RangesetFetch(rangesetTable, label);
4904 if (targetRangeset ==
NULL) {
4905 M_FAILURE(
"Rangeset does not exist in %s");
4906 }
4907
4908 if (nArgs ==
1) {
4909
4910 if (!BufGetSelectionPos(buffer, &start, &end, &isRect, &rectStart, &rectEnd)
4911 || isRect) {
4912 M_FAILURE(
"Selection missing or rectangular in call to %s");
4913 }
4914 RangesetRemoveBetween(targetRangeset, start, end);
4915 }
4916
4917 if (nArgs ==
2) {
4918
4919 if (!readIntArg(argList[
1], &label, errMsg)
4920 || !RangesetLabelOK(label)) {
4921 M_FAILURE(
"Second parameter is an invalid rangeset label in %s");
4922 }
4923
4924 sourceRangeset = RangesetFetch(rangesetTable, label);
4925 if (sourceRangeset ==
NULL) {
4926 M_FAILURE(
"Second rangeset does not exist in %s");
4927 }
4928 RangesetRemove(targetRangeset, sourceRangeset);
4929 }
4930
4931 if (nArgs ==
3) {
4932
4933 if (!readIntArg(argList[
1], &start, errMsg))
4934 return False;
4935 if (!readIntArg(argList[
2], &end, errMsg))
4936 return False;
4937
4938
4939 maxpos = buffer->length;
4940 if (start <
0) start =
0;
4941 if (start > maxpos) start = maxpos;
4942 if (end <
0) end =
0;
4943 if (end > maxpos) end = maxpos;
4944 if (start > end) {
int temp = start; start = end; end = temp;}
4945
4946 RangesetRemoveBetween(targetRangeset, start, end);
4947 }
4948
4949
4950 result->tag =
NO_TAG;
4951 return True;
4952 }
4953
4954
4955
4956
4957
4958
4959
4960 static int rangesetInvertMS(WindowInfo *window, DataValue *argList,
int nArgs,
4961 DataValue *result,
char **errMsg)
4962 {
4963
4964 RangesetTable *rangesetTable = window->buffer->rangesetTable;
4965 Rangeset *rangeset;
4966 int label =
0;
4967
4968 if (nArgs !=
1)
4969 return wrongNArgsErr(errMsg);
4970
4971 if (!readIntArg(argList[
0], &label, errMsg)
4972 || !RangesetLabelOK(label)) {
4973 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
4974 }
4975
4976 if (rangesetTable ==
NULL) {
4977 M_FAILURE(
"Rangeset does not exist in %s");
4978 }
4979
4980 rangeset = RangesetFetch(rangesetTable, label);
4981 if (rangeset ==
NULL) {
4982 M_FAILURE(
"Rangeset does not exist in %s");
4983 }
4984
4985 if (RangesetInverse(rangeset) <
0) {
4986 M_FAILURE(
"Problem inverting rangeset in %s");
4987 }
4988
4989
4990 result->tag =
NO_TAG;
4991 return True;
4992 }
4993
4994
4995
4996
4997
4998
4999
5000 static int rangesetInfoMS(WindowInfo *window, DataValue *argList,
int nArgs,
5001 DataValue *result,
char **errMsg)
5002 {
5003 RangesetTable *rangesetTable = window->buffer->rangesetTable;
5004 Rangeset *rangeset =
NULL;
5005 int count, defined;
5006 char *color, *name, *mode;
5007 DataValue element;
5008 int label =
0;
5009
5010 if (nArgs !=
1)
5011 return wrongNArgsErr(errMsg);
5012
5013 if (!readIntArg(argList[
0], &label, errMsg)
5014 || !RangesetLabelOK(label)) {
5015 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
5016 }
5017
5018 if (rangesetTable !=
NULL) {
5019 rangeset = RangesetFetch(rangesetTable, label);
5020 }
5021
5022 RangesetGetInfo(rangeset, &defined, &label, &count, &color, &name, &mode);
5023
5024
5025 result->tag =
ARRAY_TAG;
5026 result->val.arrayPtr = ArrayNew();
5027
5028 element.tag =
INT_TAG;
5029 element.val.n = defined;
5030 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"defined"), &element))
5031 M_FAILURE(
"Failed to insert array element \"defined\" in %s");
5032
5033 element.tag =
INT_TAG;
5034 element.val.n = count;
5035 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"count"), &element))
5036 M_FAILURE(
"Failed to insert array element \"count\" in %s");
5037
5038 element.tag =
STRING_TAG;
5039 if (!AllocNStringCpy(&element.val.str, color))
5040 M_FAILURE(
"Failed to allocate array value \"color\" in %s");
5041 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"color"), &element))
5042 M_FAILURE(
"Failed to insert array element \"color\" in %s");
5043
5044 element.tag =
STRING_TAG;
5045 if (!AllocNStringCpy(&element.val.str, name))
5046 M_FAILURE(
"Failed to allocate array value \"name\" in %s");
5047 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"name"), &element)) {
5048 M_FAILURE(
"Failed to insert array element \"name\" in %s");
5049 }
5050
5051 element.tag =
STRING_TAG;
5052 if (!AllocNStringCpy(&element.val.str, mode))
5053 M_FAILURE(
"Failed to allocate array value \"mode\" in %s");
5054 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"mode"), &element))
5055 M_FAILURE(
"Failed to insert array element \"mode\" in %s");
5056
5057 return True;
5058 }
5059
5060
5061
5062
5063
5064
5065
5066 static int rangesetRangeMS(WindowInfo *window, DataValue *argList,
int nArgs,
5067 DataValue *result,
char **errMsg)
5068 {
5069 textBuffer *buffer = window->buffer;
5070 RangesetTable *rangesetTable = buffer->rangesetTable;
5071 Rangeset *rangeset;
5072 int start, end, dummy, rangeIndex, ok;
5073 DataValue element;
5074 int label =
0;
5075
5076 if (nArgs <
1 || nArgs >
2) {
5077 return wrongNArgsErr(errMsg);
5078 }
5079
5080 if (!readIntArg(argList[
0], &label, errMsg)
5081 || !RangesetLabelOK(label)) {
5082 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
5083 }
5084
5085 if (rangesetTable ==
NULL) {
5086 M_FAILURE(
"Rangeset does not exist in %s");
5087 }
5088
5089 ok = False;
5090 rangeset = RangesetFetch(rangesetTable, label);
5091 if (rangeset !=
NULL) {
5092 if (nArgs ==
1) {
5093 rangeIndex = RangesetGetNRanges(rangeset) -
1;
5094 ok = RangesetFindRangeNo(rangeset,
0, &start, &dummy);
5095 ok &= RangesetFindRangeNo(rangeset, rangeIndex, &dummy, &end);
5096 rangeIndex = -
1;
5097 }
5098 else if (nArgs ==
2) {
5099 if (!readIntArg(argList[
1], &rangeIndex, errMsg)) {
5100 return False;
5101 }
5102 ok = RangesetFindRangeNo(rangeset, rangeIndex-
1, &start, &end);
5103 }
5104 }
5105
5106
5107 result->tag =
ARRAY_TAG;
5108 result->val.arrayPtr = ArrayNew();
5109
5110 if (!ok)
5111 return True;
5112
5113 element.tag =
INT_TAG;
5114 element.val.n = start;
5115 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"start"), &element))
5116 M_FAILURE(
"Failed to insert array element \"start\" in %s");
5117
5118 element.tag =
INT_TAG;
5119 element.val.n = end;
5120 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"end"), &element))
5121 M_FAILURE(
"Failed to insert array element \"end\" in %s");
5122
5123 return True;
5124 }
5125
5126
5127
5128
5129
5130
5131
5132 static int rangesetIncludesPosMS(WindowInfo *window, DataValue *argList,
5133 int nArgs, DataValue *result,
char **errMsg)
5134 {
5135 textBuffer *buffer = window->buffer;
5136 RangesetTable *rangesetTable = buffer->rangesetTable;
5137 Rangeset *rangeset;
5138 int pos, rangeIndex, maxpos;
5139 int label =
0;
5140
5141 if (nArgs <
1 || nArgs >
2) {
5142 return wrongNArgsErr(errMsg);
5143 }
5144
5145 if (!readIntArg(argList[
0], &label, errMsg)
5146 || !RangesetLabelOK(label)) {
5147 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
5148 }
5149
5150 if (rangesetTable ==
NULL) {
5151 M_FAILURE(
"Rangeset does not exist in %s");
5152 }
5153
5154 rangeset = RangesetFetch(rangesetTable, label);
5155 if (rangeset ==
NULL) {
5156 M_FAILURE(
"Rangeset does not exist in %s");
5157 }
5158
5159 if (nArgs ==
1) {
5160 pos = TextGetCursorPos(window->lastFocus);
5161 }
5162 else if (nArgs ==
2) {
5163 if (!readIntArg(argList[
1], &pos, errMsg))
5164 return False;
5165 }
5166
5167 maxpos = buffer->length;
5168 if (pos <
0 || pos > maxpos) {
5169 rangeIndex =
0;
5170 }
5171 else {
5172 rangeIndex = RangesetFindRangeOfPos(rangeset, pos, False) +
1;
5173 }
5174
5175
5176 result->tag =
INT_TAG;
5177 result->val.n = rangeIndex;
5178 return True;
5179 }
5180
5181
5182
5183
5184
5185
5186 static int rangesetSetColorMS(WindowInfo *window, DataValue *argList,
5187 int nArgs, DataValue *result,
char **errMsg)
5188 {
5189 char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
5190 textBuffer *buffer = window->buffer;
5191 RangesetTable *rangesetTable = buffer->rangesetTable;
5192 Rangeset *rangeset;
5193 char *color_name;
5194 int label =
0;
5195
5196 if (nArgs !=
2) {
5197 return wrongNArgsErr(errMsg);
5198 }
5199
5200 if (!readIntArg(argList[
0], &label, errMsg)
5201 || !RangesetLabelOK(label)) {
5202 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
5203 }
5204
5205 if (rangesetTable ==
NULL) {
5206 M_FAILURE(
"Rangeset does not exist in %s");
5207 }
5208
5209 rangeset = RangesetFetch(rangesetTable, label);
5210 if (rangeset ==
NULL) {
5211 M_FAILURE(
"Rangeset does not exist in %s");
5212 }
5213
5214 color_name =
"";
5215 if (rangeset !=
NULL) {
5216 if (!readStringArg(argList[
1], &color_name, stringStorage[
0], errMsg)) {
5217 M_FAILURE(
"Second parameter is not a color name string in %s");
5218 }
5219 }
5220
5221 RangesetAssignColorName(rangeset, color_name);
5222
5223
5224 result->tag =
NO_TAG;
5225 return True;
5226 }
5227
5228
5229
5230
5231
5232 static int rangesetSetNameMS(WindowInfo *window, DataValue *argList,
5233 int nArgs, DataValue *result,
char **errMsg)
5234 {
5235 char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
5236 textBuffer *buffer = window->buffer;
5237 RangesetTable *rangesetTable = buffer->rangesetTable;
5238 Rangeset *rangeset;
5239 char *name;
5240 int label =
0;
5241
5242 if (nArgs !=
2) {
5243 return wrongNArgsErr(errMsg);
5244 }
5245
5246 if (!readIntArg(argList[
0], &label, errMsg)
5247 || !RangesetLabelOK(label)) {
5248 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
5249 }
5250
5251 if (rangesetTable ==
NULL) {
5252 M_FAILURE(
"Rangeset does not exist in %s");
5253 }
5254
5255 rangeset = RangesetFetch(rangesetTable, label);
5256 if (rangeset ==
NULL) {
5257 M_FAILURE(
"Rangeset does not exist in %s");
5258 }
5259
5260 name =
"";
5261 if (rangeset !=
NULL) {
5262 if (!readStringArg(argList[
1], &name, stringStorage[
0], errMsg)) {
5263 M_FAILURE(
"Second parameter is not a valid name string in %s");
5264 }
5265 }
5266
5267 RangesetAssignName(rangeset, name);
5268
5269
5270 result->tag =
NO_TAG;
5271 return True;
5272 }
5273
5274
5275
5276
5277
5278 static int rangesetSetModeMS(WindowInfo *window, DataValue *argList,
5279 int nArgs, DataValue *result,
char **errMsg)
5280 {
5281 char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
5282 textBuffer *buffer = window->buffer;
5283 RangesetTable *rangesetTable = buffer->rangesetTable;
5284 Rangeset *rangeset;
5285 char *update_fn_name;
5286 int ok;
5287 int label =
0;
5288
5289 if (nArgs <
1 || nArgs >
2) {
5290 return wrongNArgsErr(errMsg);
5291 }
5292
5293 if (!readIntArg(argList[
0], &label, errMsg)
5294 || !RangesetLabelOK(label)) {
5295 M_FAILURE(
"First parameter is an invalid rangeset label in %s");
5296 }
5297
5298 if (rangesetTable ==
NULL) {
5299 M_FAILURE(
"Rangeset does not exist in %s");
5300 }
5301
5302 rangeset = RangesetFetch(rangesetTable, label);
5303 if (rangeset ==
NULL) {
5304 M_FAILURE(
"Rangeset does not exist in %s");
5305 }
5306
5307 update_fn_name =
"";
5308 if (rangeset !=
NULL) {
5309 if (nArgs ==
2) {
5310 if (!readStringArg(argList[
1], &update_fn_name, stringStorage[
0], errMsg)) {
5311 M_FAILURE(
"Second parameter is not a string in %s");
5312 }
5313 }
5314 }
5315
5316 ok = RangesetChangeModifyResponse(rangeset, update_fn_name);
5317
5318 if (!ok) {
5319 M_FAILURE(
"Second parameter is not a valid mode in %s");
5320 }
5321
5322
5323 result->tag =
NO_TAG;
5324 return True;
5325 }
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351 static int fillStyleResult(DataValue *result,
char **errMsg,
5352 WindowInfo *window,
char *styleName, Boolean preallocatedStyleName,
5353 Boolean includeName,
int patCode,
int bufferPos)
5354 {
5355 DataValue
DV;
5356 char colorValue[
20];
5357 int r, g, b;
5358
5359
5360 result->tag =
ARRAY_TAG;
5361 result->val.arrayPtr = ArrayNew();
5362
5363
5364 DV.tag =
STRING_TAG;
5365
5366 if (includeName) {
5367
5368 if (preallocatedStyleName) {
5369 DV.val.str.rep = styleName;
5370 DV.val.str.len = strlen(styleName);
5371 }
5372 else {
5373 AllocNStringCpy(&
DV.val.str, styleName);
5374 }
5375 M_STR_ALLOC_ASSERT(
DV);
5376 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"style"), &
DV)) {
5377 M_ARRAY_INSERT_FAILURE();
5378 }
5379 }
5380
5381
5382 AllocNStringCpy(&
DV.val.str, ColorOfNamedStyle(window->colorProfile, styleName));
5383 M_STR_ALLOC_ASSERT(
DV);
5384 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"color"), &
DV)) {
5385 M_ARRAY_INSERT_FAILURE();
5386 }
5387
5388
5389
5390
5391 if (patCode) {
5392 HighlightColorValueOfCode(window, patCode, &r, &g, &b);
5393 sprintf(colorValue,
"#%02x%02x%02x", r/
256, g/
256, b/
256);
5394 AllocNStringCpy(&
DV.val.str, colorValue);
5395 M_STR_ALLOC_ASSERT(
DV);
5396 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"rgb"), &
DV)) {
5397 M_ARRAY_INSERT_FAILURE();
5398 }
5399 }
5400
5401
5402 AllocNStringCpy(&
DV.val.str, BgColorOfNamedStyle(window->colorProfile, styleName));
5403 M_STR_ALLOC_ASSERT(
DV);
5404 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"background"), &
DV)) {
5405 M_ARRAY_INSERT_FAILURE();
5406 }
5407
5408
5409
5410
5411 if (patCode) {
5412 GetHighlightBGColorOfCode(window, patCode, &r, &g, &b);
5413 sprintf(colorValue,
"#%02x%02x%02x", r/
256, g/
256, b/
256);
5414 AllocNStringCpy(&
DV.val.str, colorValue);
5415 M_STR_ALLOC_ASSERT(
DV);
5416 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"back_rgb"), &
DV)) {
5417 M_ARRAY_INSERT_FAILURE();
5418 }
5419 }
5420
5421
5422 DV.tag =
INT_TAG;
5423
5424
5425 DV.val.n = FontOfNamedStyleIsBold(window->colorProfile, styleName);
5426 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"bold"), &
DV)) {
5427 M_ARRAY_INSERT_FAILURE();
5428 }
5429
5430
5431 DV.val.n = FontOfNamedStyleIsItalic(window->colorProfile, styleName);
5432 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"italic"), &
DV)) {
5433 M_ARRAY_INSERT_FAILURE();
5434 }
5435
5436 if (bufferPos >=
0) {
5437
5438 const char *styleNameNotUsed =
NULL;
5439 DV.val.n = StyleLengthOfCodeFromPos(window, bufferPos, &styleNameNotUsed);
5440 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"extent"), &
DV)) {
5441 M_ARRAY_INSERT_FAILURE();
5442 }
5443 }
5444 return True;
5445 }
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455 static int getStyleByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
5456 DataValue *result,
char **errMsg)
5457 {
5458 char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
5459 char *styleName;
5460
5461
5462 if (nArgs !=
1) {
5463 return wrongNArgsErr(errMsg);
5464 }
5465
5466
5467 result->tag =
ARRAY_TAG;
5468 result->val.arrayPtr =
NULL;
5469
5470 if (!readStringArg(argList[
0], &styleName, stringStorage[
0], errMsg)) {
5471 M_FAILURE(
"First parameter is not a string in %s");
5472 }
5473
5474 if (!NamedStyleExists(window->colorProfile, styleName)) {
5475
5476 return True;
5477 }
5478
5479 return fillStyleResult(result, errMsg, window,
5480 styleName, (argList[
0].tag ==
STRING_TAG), False,
0, -
1);
5481 }
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495 static int getStyleAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
5496 DataValue *result,
char **errMsg)
5497 {
5498 int patCode;
5499 int bufferPos;
5500 textBuffer *buf = window->buffer;
5501
5502
5503 if (nArgs !=
1) {
5504 return wrongNArgsErr(errMsg);
5505 }
5506
5507
5508 result->tag =
ARRAY_TAG;
5509 result->val.arrayPtr =
NULL;
5510
5511 if (!readIntArg(argList[
0], &bufferPos, errMsg)) {
5512 return False;
5513 }
5514
5515
5516 if ((bufferPos <
0) || (bufferPos >= buf->length)) {
5517
5518
5519 return True;
5520 }
5521
5522
5523 patCode = HighlightCodeOfPos(window, bufferPos);
5524 if (patCode ==
0) {
5525
5526 return True;
5527 }
5528
5529 return fillStyleResult(result, errMsg, window,
5530 HighlightStyleOfCode(window, patCode), False, True, patCode, bufferPos);
5531 }
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543 static int fillPatternResult(DataValue *result,
char **errMsg,
5544 WindowInfo *window,
char *patternName, Boolean preallocatedPatternName,
5545 Boolean includeName,
char* styleName,
int bufferPos)
5546 {
5547 DataValue
DV;
5548
5549
5550 result->tag =
ARRAY_TAG;
5551 result->val.arrayPtr = ArrayNew();
5552
5553
5554 DV.tag =
STRING_TAG;
5555
5556 if (includeName) {
5557
5558 if (preallocatedPatternName) {
5559 DV.val.str.rep = patternName;
5560 DV.val.str.len = strlen(patternName);
5561 }
5562 else {
5563 AllocNStringCpy(&
DV.val.str, patternName);
5564 }
5565 M_STR_ALLOC_ASSERT(
DV);
5566 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"pattern"), &
DV)) {
5567 M_ARRAY_INSERT_FAILURE();
5568 }
5569 }
5570
5571
5572 AllocNStringCpy(&
DV.val.str, styleName);
5573 M_STR_ALLOC_ASSERT(
DV);
5574 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"style"), &
DV)) {
5575 M_ARRAY_INSERT_FAILURE();
5576 }
5577
5578
5579 DV.tag =
INT_TAG;
5580
5581 if (bufferPos >=
0) {
5582
5583 int checkCode =
0;
5584 DV.val.n = HighlightLengthOfCodeFromPos(window, bufferPos, &checkCode);
5585 if (!ArrayInsert(result,
PERM_ALLOC_STR(
"extent"), &
DV)) {
5586 M_ARRAY_INSERT_FAILURE();
5587 }
5588 }
5589
5590 return True;
5591 }
5592
5593
5594
5595
5596
5597
5598
5599
5600 static int getPatternByNameMS(WindowInfo *window, DataValue *argList,
int nArgs,
5601 DataValue *result,
char **errMsg)
5602 {
5603 char stringStorage[
1][
TYPE_INT_STR_SIZE(
int)];
5604 char *patternName =
NULL;
5605 highlightPattern *pattern;
5606
5607
5608 result->tag =
ARRAY_TAG;
5609 result->val.arrayPtr =
NULL;
5610
5611
5612 if (nArgs !=
1) {
5613 return wrongNArgsErr(errMsg);
5614 }
5615
5616 if (!readStringArg(argList[
0], &patternName, stringStorage[
0], errMsg)) {
5617 M_FAILURE(
"First parameter is not a string in %s");
5618 }
5619
5620 pattern = FindPatternOfWindow(window, patternName);
5621 if (pattern ==
NULL) {
5622
5623 return True;
5624 }
5625
5626 return fillPatternResult(result, errMsg, window, patternName,
5627 (argList[
0].tag ==
STRING_TAG), False, pattern->style, -
1);
5628 }
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638 static int getPatternAtPosMS(WindowInfo *window, DataValue *argList,
int nArgs,
5639 DataValue *result,
char **errMsg)
5640 {
5641 int bufferPos = -
1;
5642 textBuffer *buffer = window->buffer;
5643 int patCode =
0;
5644
5645
5646 result->tag =
ARRAY_TAG;
5647 result->val.arrayPtr =
NULL;
5648
5649
5650 if (nArgs !=
1) {
5651 return wrongNArgsErr(errMsg);
5652 }
5653
5654
5655
5656 if (!readIntArg(argList[
0], &bufferPos, errMsg)) {
5657 return False;
5658 }
5659
5660
5661
5662
5663 if ((bufferPos <
0) || (bufferPos >= buffer->length)) {
5664
5665
5666 return True;
5667 }
5668
5669
5670 patCode = HighlightCodeOfPos(window, bufferPos);
5671 if (patCode ==
0) {
5672
5673 return True;
5674 }
5675
5676 return fillPatternResult(result, errMsg, window,
5677 HighlightNameOfCode(window, patCode), False, True,
5678 HighlightStyleOfCode(window, patCode), bufferPos);
5679 }
5680
5681 static int wrongNArgsErr(
char **errMsg)
5682 {
5683 *errMsg =
"Wrong number of arguments to function %s";
5684 return False;
5685 }
5686
5687 static int tooFewArgsErr(
char **errMsg)
5688 {
5689 *errMsg =
"Too few arguments to function %s";
5690 return False;
5691 }
5692
5693
5694
5695
5696
5697
5698 static int readIntArg(DataValue dv,
int *result,
char **errMsg)
5699 {
5700 char *c;
5701
5702 if (dv.tag ==
INT_TAG) {
5703 *result = dv.val.n;
5704 return True;
5705 }
else if (dv.tag ==
STRING_TAG) {
5706 for (c=dv.val.str.rep; *c !=
'\0'; c++) {
5707 if (!(isdigit((
unsigned char)*c) || *c ==
' ' || *c ==
'\t')) {
5708 goto typeError;
5709 }
5710 }
5711 sscanf(dv.val.str.rep,
"%d", result);
5712 return True;
5713 }
5714
5715 typeError:
5716 *errMsg =
"%s called with non-integer argument";
5717 return False;
5718 }
5719
5720
5721
5722
5723
5724
5725
5726
5727 static int readStringArg(DataValue dv,
char **result,
char *stringStorage,
5728 char **errMsg)
5729 {
5730 if (dv.tag ==
STRING_TAG) {
5731 *result = dv.val.str.rep;
5732 return True;
5733 }
else if (dv.tag ==
INT_TAG) {
5734 sprintf(stringStorage,
"%d", dv.val.n);
5735 *result = stringStorage;
5736 return True;
5737 }
5738 *errMsg =
"%s called with unknown object";
5739 return False;
5740 }
5741