482504: Bad CapsLock grab on certain keyboard configurations
[nedit.git] / source / nedit.c
blob6e86b655364fbe6635c9463537c21d772bf2bc1e
1 static const char CVSID[] = "$Id: nedit.c,v 1.21 2001/10/31 16:36:40 edg Exp $";
2 /*******************************************************************************
3 * *
4 * nedit.c -- Nirvana Editor main program *
5 * *
6 * Copyright (C) 1999 Mark Edel *
7 * *
8 * This is free software; you can redistribute it and/or modify it under the *
9 * terms of the GNU General Public License as published by the Free Software *
10 * Foundation; either version 2 of the License, or (at your option) any later *
11 * version. *
12 * *
13 * This software is distributed in the hope that it will be useful, but WITHOUT *
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License along with *
19 * software; if not, write to the Free Software Foundation, Inc., 59 Temple *
20 * Place, Suite 330, Boston, MA 02111-1307 USA *
21 * *
22 * Nirvana Text Editor *
23 * May 10, 1991 *
24 * *
25 * Written by Mark Edel *
26 * *
27 * Modifications: *
28 * *
29 * 8/18/93 - Mark Edel & Joy Kyriakopulos - Ported to VMS *
30 * *
31 *******************************************************************************/
32 #include <stdio.h>
33 #include <stdlib.h>
34 #ifndef NO_XMIM
35 #include <X11/Xlocale.h>
36 #else
37 #include <locale.h>
38 #endif
39 #include <X11/Intrinsic.h>
40 #include <Xm/Xm.h>
41 #if XmVersion >= 1002
42 #include <Xm/RepType.h>
43 #endif
44 #ifdef VMS
45 #include <rmsdef.h>
46 #include "../util/VMSparam.h"
47 #include "../util/VMSUtils.h"
48 #else
49 #ifndef __MVS__
50 #include <sys/param.h>
51 #endif
52 #endif /*VMS*/
53 #include "textBuf.h"
54 #include "nedit.h"
55 #include "file.h"
56 #include "preferences.h"
57 #include "regularExp.h"
58 #include "selection.h"
59 #include "tags.h"
60 #include "menu.h"
61 #include "macro.h"
62 #include "server.h"
63 #include "rbTree.h"
64 #include "interpret.h"
65 #include "parse.h"
66 #include "help.h"
67 #include "../util/misc.h"
68 #include "../util/printUtils.h"
69 #include "../util/fileUtils.h"
70 #include "../util/getfiles.h"
73 static void nextArg(int argc, char **argv, int *argIndex);
74 static int checkDoMacroArg(const char *macro);
75 static void maskArgvKeywords(int argc, char **argv, const char **maskArgs);
76 static void unmaskArgvKeywords(int argc, char **argv, const char **maskArgs);
78 WindowInfo *WindowList = NULL;
79 Display *TheDisplay = NULL;
80 char *ArgV0 = NULL;
81 Boolean IsServer = False;
83 #define NEDIT_DEFAULT_FONT "-*-helvetica-medium-r-normal-*-*-120-*-*-*-*-*"
84 #define NEDIT_FIXED_FONT "-*-courier-medium-r-normal-*-*-120-*-*-*-*-*"
86 static char *fallbackResources[] = {
87 "*menuBar.marginHeight: 0",
88 "*menuBar.shadowThickness: 1",
89 "*pane.sashHeight: 11",
90 "*pane.sashWidth: 11",
91 "*text.selectionArrayCount: 3",
92 "nedit*fontList: " NEDIT_DEFAULT_FONT,
93 "nedit*XmList.fontList: " NEDIT_FIXED_FONT,
94 /* This should not be necessary, but some default in LessTif is
95 overriding the resource above, and specifying the app-name fixes it */
96 "nedit*XmText.fontList: " NEDIT_FIXED_FONT,
97 /* Same with this, both Solaris Motif and LessTif seem to have some
98 very specific defaults for file selection box fonts */
99 "nedit*XmFileSelectionBox*XmList.fontList: " NEDIT_FIXED_FONT,
100 "nedit*XmTextField.fontList: " NEDIT_FIXED_FONT,
101 "nedit*background: #b3b3b3",
102 "nedit*foreground: black",
103 "nedit*text.lineNumForeground: #777777",
104 "nedit*text.background: #e5e5e5",
105 "nedit*text.foreground: black",
106 "nedit*text.highlightBackground: red",
107 "nedit*text.highlightForeground: black",
108 "nedit*XmText*foreground: black",
109 "nedit*XmText*background: #cccccc",
110 "nedit*helpText.background: #cccccc",
111 "nedit*helpText.foreground: black",
112 "nedit*helpText.selectBackground: #b3b3b3",
113 "nedit*statsLine.background: #b3b3b3",
114 "nedit*helpText.font: " NEDIT_FIXED_FONT,
115 "*XmText.translations: #override \
116 Ctrl~Alt~Meta<KeyPress>v: paste-clipboard()\\n\
117 Ctrl~Alt~Meta<KeyPress>c: copy-clipboard()\\n\
118 Ctrl~Alt~Meta<KeyPress>x: cut-clipboard()\\n\
119 Ctrl~Alt~Meta<KeyPress>u: delete-to-start-of-line()\\n",
120 "*XmTextField.translations: #override \
121 Ctrl~Alt~Meta<KeyPress>v: paste-clipboard()\\n\
122 Ctrl~Alt~Meta<KeyPress>c: copy-clipboard()\\n\
123 Ctrl~Alt~Meta<KeyPress>x: cut-clipboard()\\n\
124 Ctrl~Alt~Meta<KeyPress>u: delete-to-start-of-line()\\n",
125 "nedit*XmList*foreground: black",
126 "nedit*XmList*background: #cccccc",
127 "nedit*XmTextField*background: #cccccc",
128 "nedit*XmTextField*foreground: black",
129 "*iSearchForm*highlightThickness: 1",
130 "*fileMenu.tearOffModel: XmTEAR_OFF_ENABLED",
131 "*editMenu.tearOffModel: XmTEAR_OFF_ENABLED",
132 "*searchMenu.tearOffModel: XmTEAR_OFF_ENABLED",
133 "*preferencesMenu.tearOffModel: XmTEAR_OFF_ENABLED",
134 "*windowsMenu.tearOffModel: XmTEAR_OFF_ENABLED",
135 "*shellMenu.tearOffModel: XmTEAR_OFF_ENABLED",
136 "*macroMenu.tearOffModel: XmTEAR_OFF_ENABLED",
137 "*helpMenu.tearOffModel: XmTEAR_OFF_ENABLED",
138 "*fileMenu.mnemonic: F",
139 "*fileMenu.new.accelerator: Ctrl<Key>n",
140 "*fileMenu.new.acceleratorText: Ctrl+N",
141 "*fileMenu.open.accelerator: Ctrl<Key>o",
142 "*fileMenu.open.acceleratorText: Ctrl+O",
143 "*fileMenu.openSelected.accelerator: Ctrl<Key>y",
144 "*fileMenu.openSelected.acceleratorText: Ctrl+Y",
145 "*fileMenu.close.accelerator: Ctrl<Key>w",
146 "*fileMenu.close.acceleratorText: Ctrl+W",
147 "*fileMenu.save.accelerator: Ctrl<Key>s",
148 "*fileMenu.save.acceleratorText: Ctrl+S",
149 "*fileMenu.includeFile.accelerator: Alt<Key>i",
150 "*fileMenu.includeFile.acceleratorText: Alt+I",
151 "*fileMenu.print.accelerator: Ctrl<Key>p",
152 "*fileMenu.print.acceleratorText: Ctrl+P",
153 "*fileMenu.exit.accelerator: Ctrl<Key>q",
154 "*fileMenu.exit.acceleratorText: Ctrl+Q",
155 "*editMenu.mnemonic: E",
156 "*editMenu.undo.accelerator: Ctrl<Key>z",
157 "*editMenu.undo.acceleratorText: Ctrl+Z",
158 "*editMenu.redo.accelerator: Shift Ctrl<Key>z",
159 "*editMenu.redo.acceleratorText: Shift+Ctrl+Z",
160 "*editMenu.cut.accelerator: Ctrl<Key>x",
161 "*editMenu.cut.acceleratorText: Ctrl+X",
162 "*editMenu.copy.accelerator: Ctrl<Key>c",
163 "*editMenu.copy.acceleratorText: Ctrl+C",
164 "*editMenu.paste.accelerator: Ctrl<Key>v",
165 "*editMenu.paste.acceleratorText: Ctrl+V",
166 "*editMenu.pasteColumn.accelerator: Shift Ctrl<Key>v",
167 "*editMenu.pasteColumn.acceleratorText: Ctrl+Shift+V",
168 "*editMenu.delete.acceleratorText: Del",
169 "*editMenu.selectAll.accelerator: Ctrl<Key>a",
170 "*editMenu.selectAll.acceleratorText: Ctrl+A",
171 "*editMenu.shiftLeft.accelerator: Ctrl<Key>9",
172 "*editMenu.shiftLeft.acceleratorText: [Shift]Ctrl+9",
173 "*editMenu.shiftLeftShift.accelerator: Shift Ctrl<Key>9",
174 "*editMenu.shiftRight.accelerator: Ctrl<Key>0",
175 "*editMenu.shiftRight.acceleratorText: [Shift]Ctrl+0",
176 "*editMenu.shiftRightShift.accelerator: Shift Ctrl<Key>0",
177 "*editMenu.upperCase.accelerator: Ctrl<Key>6",
178 "*editMenu.upperCase.acceleratorText: Ctrl+6",
179 "*editMenu.lowerCase.accelerator: Shift Ctrl<Key>6",
180 "*editMenu.lowerCase.acceleratorText: Shift+Ctrl+6",
181 "*editMenu.fillParagraph.accelerator: Ctrl<Key>j",
182 "*editMenu.fillParagraph.acceleratorText: Ctrl+J",
183 "*editMenu.insertFormFeed.accelerator: Alt Ctrl<Key>l",
184 "*editMenu.insertFormFeed.acceleratorText: Alt+Ctrl+L",
185 "*editMenu.insertCtrlCode.accelerator: Alt Ctrl<Key>i",
186 "*editMenu.insertCtrlCode.acceleratorText: Alt+Ctrl+I",
187 "*searchMenu.mnemonic: S",
188 "*searchMenu.find.accelerator: Ctrl<Key>f",
189 "*searchMenu.find.acceleratorText: [Shift]Ctrl+F",
190 "*searchMenu.findShift.accelerator: Shift Ctrl<Key>f",
191 "*searchMenu.findAgain.accelerator: Ctrl<Key>g",
192 "*searchMenu.findAgain.acceleratorText: [Shift]Ctrl+G",
193 "*searchMenu.findAgainShift.accelerator: Shift Ctrl<Key>g",
194 "*searchMenu.findSelection.accelerator: Ctrl<Key>h",
195 "*searchMenu.findSelection.acceleratorText: [Shift]Ctrl+H",
196 "*searchMenu.findSelectionShift.accelerator: Shift Ctrl<Key>h",
197 "*searchMenu.findIncremental.accelerator: Ctrl<Key>i",
198 "*searchMenu.findIncrementalShift.accelerator: Shift Ctrl<Key>i",
199 "*searchMenu.findIncremental.acceleratorText: [Shift]Ctrl+I",
200 "*searchMenu.replace.accelerator: Ctrl<Key>r",
201 "*searchMenu.replace.acceleratorText: [Shift]Ctrl+R",
202 "*searchMenu.replaceShift.accelerator: Shift Ctrl<Key>r",
203 "*searchMenu.findReplace.accelerator: Ctrl<Key>r",
204 "*searchMenu.findReplace.acceleratorText: [Shift]Ctrl+R",
205 "*searchMenu.findReplaceShift.accelerator: Shift Ctrl<Key>r",
206 "*searchMenu.replaceFindAgain.accelerator: Ctrl<Key>t",
207 "*searchMenu.replaceFindAgain.acceleratorText: [Shift]Ctrl+T",
208 "*searchMenu.replaceFindAgainShift.accelerator: Shift Ctrl<Key>t",
209 "*searchMenu.replaceAgain.accelerator: Alt<Key>t",
210 "*searchMenu.replaceAgain.acceleratorText: [Shift]Alt+T",
211 "*searchMenu.replaceAgainShift.accelerator: Shift Alt<Key>t",
212 "*searchMenu.gotoLineNumber.accelerator: Ctrl<Key>l",
213 "*searchMenu.gotoLineNumber.acceleratorText: Ctrl+L",
214 "*searchMenu.gotoSelected.accelerator: Ctrl<Key>e",
215 "*searchMenu.gotoSelected.acceleratorText: Ctrl+E",
216 "*searchMenu.mark.accelerator: Alt<Key>m",
217 "*searchMenu.mark.acceleratorText: Alt+M a-z",
218 "*searchMenu.gotoMark.accelerator: Alt<Key>g",
219 "*searchMenu.gotoMark.acceleratorText: [Shift]Alt+G a-z",
220 "*searchMenu.gotoMarkShift.accelerator: Shift Alt<Key>g",
221 "*searchMenu.gotoMatching.accelerator: Ctrl<Key>m",
222 "*searchMenu.gotoMatching.acceleratorText: [Shift]Ctrl+M",
223 "*searchMenu.gotoMatchingShift.accelerator: Shift Ctrl<Key>m",
224 "*searchMenu.findDefinition.accelerator: Ctrl<Key>d",
225 "*searchMenu.findDefinition.acceleratorText: Ctrl+D",
226 "*preferencesMenu.mnemonic: P",
227 "*preferencesMenu.statisticsLine.accelerator: Alt<Key>a",
228 "*preferencesMenu.statisticsLine.acceleratorText: Alt+A",
229 "*preferencesMenu.overtype.acceleratorText: Insert",
230 "*shellMenu.mnemonic: l",
231 "*shellMenu.filterSelection.accelerator: Alt<Key>r",
232 "*shellMenu.filterSelection.acceleratorText: Alt+R",
233 "*shellMenu.executeCommand.accelerator: Alt<Key>x",
234 "*shellMenu.executeCommand.acceleratorText: Alt+X",
235 "*shellMenu.executeCommandLine.accelerator: <Key>KP_Enter",
236 "*shellMenu.executeCommandLine.acceleratorText: KP Enter",
237 "*shellMenu.cancelShellCommand.accelerator: Ctrl<Key>period",
238 "*shellMenu.cancelShellCommand.acceleratorText: Ctrl+.",
239 "*macroMenu.mnemonic: c",
240 "*macroMenu.learnKeystrokes.accelerator: Alt<Key>k",
241 "*macroMenu.learnKeystrokes.acceleratorText: Alt+K",
242 "*macroMenu.finishLearn.accelerator: Alt<Key>k",
243 "*macroMenu.finishLearn.acceleratorText: Alt+K",
244 "*macroMenu.cancelLearn.accelerator: Ctrl<Key>period",
245 "*macroMenu.cancelLearn.acceleratorText: Ctrl+.",
246 "*macroMenu.replayKeystrokes.accelerator: Ctrl<Key>k",
247 "*macroMenu.replayKeystrokes.acceleratorText: Ctrl+K",
248 "*macroMenu.repeat.accelerator: Ctrl<Key>comma",
249 "*macroMenu.repeat.acceleratorText: Ctrl+,",
250 "*windowsMenu.mnemonic: W",
251 "*windowsMenu.splitWindow.accelerator: Ctrl<Key>2",
252 "*windowsMenu.splitWindow.acceleratorText: Ctrl+2",
253 "*windowsMenu.closePane.accelerator: Ctrl<Key>1",
254 "*windowsMenu.closePane.acceleratorText: Ctrl+1",
255 "*helpMenu.mnemonic: H",
259 static const char cmdLineHelp[] =
260 #ifndef VMS
261 "Usage: nedit [-read] [-create] [-line n | +n] [-server] [-do command]\n\
262 [-tags file] [-tabs n] [-wrap] [-nowrap] [-autowrap]\n\
263 [-autoindent] [-noautoindent] [-autosave] [-noautosave]\n\
264 [-lm languagemode] [-rows n] [-columns n] [-font font]\n\
265 [-geometry geometry] [-iconic] [-noiconic] [-svrname name]\n\
266 [-display [host]:server[.screen] [-xrm resourcestring]\n\
267 [-import file] [-background color] [-foreground color]\n\
268 [file...]\n";
269 #else
271 #endif /*VMS*/
273 int main(int argc, char **argv)
275 int i, lineNum, nRead, fileSpecified = FALSE, editFlags = CREATE;
276 int gotoLine = False, macroFileRead = False;
277 int iconic = False;
278 char *toDoCommand = NULL, *geometry = NULL, *langMode = NULL;
279 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
280 XtAppContext context;
281 XrmDatabase prefDB;
282 static const char *protectedKeywords[] = {"-iconic", "-icon", "-geometry",
283 "-g", "-rv", "-reverse", "-bd", "-bordercolor", "-borderwidth",
284 "-bw", "-title", NULL};
286 /* Save the command which was used to invoke nedit for restart command */
287 ArgV0 = argv[0];
289 /* Set locale for C library, X, and Motif input functions.
290 Reverts to "C" if requested locale not available. */
291 XtSetLanguageProc(NULL, NULL, NULL);
293 /* Initialize X toolkit (does not open display yet) */
294 XtToolkitInitialize();
295 context = XtCreateApplicationContext();
297 /* Set up a warning handler to trap obnoxious Xt grab warnings */
298 SuppressPassiveGrabWarnings();
300 /* Set up default resources if no app-defaults file is found */
301 XtAppSetFallbackResources(context, fallbackResources);
303 #if XmVersion >= 1002
304 /* Allow users to change tear off menus with X resources */
305 XmRepTypeInstallTearOffModelConverter();
306 #endif
308 #ifdef VMS
309 /* Convert the command line to Unix style (This is not an ideal solution) */
310 ConvertVMSCommandLine(&argc, &argv);
311 #endif /*VMS*/
312 #ifdef __EMX__
313 /* expand wildcards if necessary */
314 _wildcard(&argc, &argv);
315 #endif
317 /* Read the preferences file and command line into a database */
318 prefDB = CreateNEditPrefDB(&argc, argv);
320 /* Open the display and read X database and remaining command line args.
321 XtOpenDisplay must be allowed to process some of the resource arguments
322 with its inaccessible internal option table, but others, like -geometry
323 and -iconic are per-window and it should not be allowed to consume them,
324 so we temporarily masked them out. */
325 maskArgvKeywords(argc, argv, protectedKeywords);
326 TheDisplay = XtOpenDisplay (context, NULL, APP_NAME, APP_CLASS,
327 NULL, 0, &argc, argv);
328 unmaskArgvKeywords(argc, argv, protectedKeywords);
329 if (!TheDisplay) {
330 XtWarning ("NEdit: Can't open display\n");
331 exit(EXIT_FAILURE);
334 /* Initialize global symbols and subroutines used in the macro language */
335 InitMacroGlobals();
336 RegisterMacroSubroutines();
338 /* Store preferences from the command line and .nedit file,
339 and set the appropriate preferences */
340 RestoreNEditPrefs(prefDB, XtDatabase(TheDisplay));
341 LoadPrintPreferences(XtDatabase(TheDisplay), APP_NAME, APP_CLASS, True);
342 SetDeleteRemap(GetPrefMapDelete());
343 SetPointerCenteredDialogs(GetPrefRepositionDialogs());
344 SetGetEFTextFieldRemoval(!GetPrefStdOpenDialog());
346 /* Set up action procedures for menu item commands */
347 InstallMenuActions(context);
349 /* Install word delimiters for regular expression matching */
350 SetREDefaultWordDelimiters(GetPrefDelimiters());
352 /* Read the nedit dynamic database of files for the Open Previous
353 command (and eventually other information as well) */
354 ReadNEditDB();
356 /* Process -import command line argument before others which might
357 open windows (loading preferences doesn't update menu settings,
358 which would then be out of sync with the real preference settings) */
359 for (i=1; i<argc; i++) {
360 if (!strcmp(argv[i], "-import")) {
361 nextArg(argc, argv, &i);
362 ImportPrefFile(argv[i], False);
363 }else if (!strcmp(argv[i], "-importold")) {
364 nextArg(argc, argv, &i);
365 ImportPrefFile(argv[i], True);
369 /* Load the default tags file. Don't complain if it doesn't load, the tag
370 file resource is intended to be set and forgotten. Running nedit in a
371 directory without a tags should not cause it to spew out errors. */
372 if (*GetPrefTagFile() != '\0')
373 AddTagsFile(GetPrefTagFile());
375 /* Process any command line arguments (-tags, -do, -read, -create,
376 +<line_number>, -line, -server, and files to edit) not already
377 processed by RestoreNEditPrefs. */
378 fileSpecified = FALSE;
379 for (i=1; i<argc; i++) {
380 if (!strcmp(argv[i], "-tags")) {
381 nextArg(argc, argv, &i);
382 if (!AddTagsFile(argv[i]))
383 fprintf(stderr, "NEdit: Unable to load tags file\n");
384 } else if (!strcmp(argv[i], "-do")) {
385 nextArg(argc, argv, &i);
386 if (checkDoMacroArg(argv[i]))
387 toDoCommand = argv[i];
388 } else if (!strcmp(argv[i], "-read")) {
389 editFlags |= PREF_READ_ONLY;
390 } else if (!strcmp(argv[i], "-create")) {
391 editFlags |= SUPPRESS_CREATE_WARN;
392 } else if (!strcmp(argv[i], "-line")) {
393 nextArg(argc, argv, &i);
394 nRead = sscanf(argv[i], "%d", &lineNum);
395 if (nRead != 1)
396 fprintf(stderr, "NEdit: argument to line should be a number\n");
397 else
398 gotoLine = True;
399 } else if (*argv[i] == '+') {
400 nRead = sscanf((argv[i]+1), "%d", &lineNum);
401 if (nRead != 1)
402 fprintf(stderr, "NEdit: argument to + should be a number\n");
403 else
404 gotoLine = True;
405 } else if (!strcmp(argv[i], "-server")) {
406 IsServer = True;
407 } else if (!strcmp(argv[i], "-iconic") || !strcmp(argv[i], "-icon")) {
408 iconic = True;
409 } else if (!strcmp(argv[i], "-noiconic")) {
410 iconic = False;
411 } else if (!strcmp(argv[i], "-geometry") || !strcmp(argv[i], "-g")) {
412 nextArg(argc, argv, &i);
413 geometry = argv[i];
414 } else if (!strcmp(argv[i], "-lm")) {
415 nextArg(argc, argv, &i);
416 langMode = argv[i];
417 } else if (!strcmp(argv[i], "-import")) {
418 nextArg(argc, argv, &i); /* already processed, skip */
419 } else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "-version")) {
420 PrintVersion();
421 exit(EXIT_SUCCESS);
422 } else if (*argv[i] == '-') {
423 #ifdef VMS
424 *argv[i] = '/';
425 #endif /*VMS*/
426 fprintf(stderr, "NEdit: Unrecognized option %s\n%s", argv[i],
427 cmdLineHelp);
428 exit(EXIT_FAILURE);
429 } else {
430 #ifdef VMS
431 int numFiles, j;
432 char **nameList = NULL;
433 /* Use VMS's LIB$FILESCAN for filename in argv[i] to process */
434 /* wildcards and to obtain a full VMS file specification */
435 numFiles = VMSFileScan(argv[i], &nameList, NULL, INCLUDE_FNF);
436 /* for each expanded file name do: */
437 for (j = 0; j < numFiles; ++j) {
438 ParseFilename(nameList[j], filename, pathname);
439 EditExistingFile(WindowList, filename, pathname, editFlags,
440 geometry, iconic, langMode);
441 if (!macroFileRead) {
442 ReadMacroInitFile(WindowList);
443 macroFileRead = True;
445 if (toDoCommand != NULL)
446 DoMacro(WindowList, toDoCommand, "-do macro");
447 if (gotoLine)
448 SelectNumberedLine(WindowList, lineNum);
449 fileSpecified = TRUE;
450 free(nameList[j]);
452 if (nameList != NULL)
453 free(nameList);
454 #else
455 ParseFilename(argv[i], filename, pathname);
456 EditExistingFile(WindowList, filename, pathname, editFlags,
457 geometry, iconic, langMode);
458 fileSpecified = TRUE;
459 if (!macroFileRead) {
460 ReadMacroInitFile(WindowList);
461 macroFileRead = True;
463 if (toDoCommand != NULL)
464 DoMacro(WindowList, toDoCommand, "-do macro");
465 if (gotoLine)
466 SelectNumberedLine(WindowList, lineNum);
467 #endif /*VMS*/
468 toDoCommand = NULL;
471 #ifdef VMS
472 VMSFileScanDone();
473 #endif /*VMS*/
475 /* If no file to edit was specified, open a window to edit "Untitled" */
476 if (!fileSpecified) {
477 EditNewFile(geometry, iconic, langMode, NULL);
478 ReadMacroInitFile(WindowList);
479 if (toDoCommand != NULL)
480 DoMacro(WindowList, toDoCommand, "-do macro");
483 /* Begin remembering last command invoked for "Repeat" menu item */
484 AddLastCommandActionHook(context);
486 /* Set up communication port and write ~/.nedit_server_process file */
487 if (IsServer)
488 InitServerCommunication();
490 /* Process events. */
491 if (IsServer)
492 ServerMainLoop(context);
493 else
494 XtAppMainLoop(context);
496 /* Not reached but this keeps some picky compilers happy */
497 return EXIT_SUCCESS;
500 static void nextArg(int argc, char **argv, int *argIndex)
502 if (*argIndex + 1 >= argc) {
503 #ifdef VMS
504 *argv[*argIndex] = '/';
505 #endif /*VMS*/
506 fprintf(stderr, "NEdit: %s requires an argument\n%s", argv[*argIndex],
507 cmdLineHelp);
508 exit(EXIT_FAILURE);
510 (*argIndex)++;
514 ** Return True if -do macro is valid, otherwise write an error on stderr
516 static int checkDoMacroArg(const char *macro)
518 Program *prog;
519 char *errMsg, *stoppedAt, *tMacro;
520 int macroLen;
522 /* Add a terminating newline (which command line users are likely to omit
523 since they are typically invoking a single routine) */
524 macroLen = strlen(macro);
525 tMacro = XtMalloc(strlen(macro)+2);
526 strncpy(tMacro, macro, macroLen);
527 tMacro[macroLen] = '\n';
528 tMacro[macroLen+1] = '\0';
530 /* Do a test parse */
531 prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
532 if (prog == NULL) {
533 ParseError(NULL, tMacro, stoppedAt, "argument to -do", errMsg);
534 return False;
536 FreeProgram(prog);
537 return True;
541 ** maskArgvKeywords and unmaskArgvKeywords mangle selected keywords by
542 ** replacing the '-' with a space, for the purpose of hiding them from
543 ** XtOpenDisplay's option processing. Why this silly scheme? XtOpenDisplay
544 ** really needs to see command line arguments, particularly -display, but
545 ** there's no way to change the option processing table it uses, to keep
546 ** it from consuming arguments which are meant to apply per-window, like
547 ** -geometry and -iconic.
549 static void maskArgvKeywords(int argc, char **argv, const char **maskArgs)
551 int i, k;
553 for (i=1; i<argc; i++)
554 for (k=0; maskArgs[k]!=NULL; k++)
555 if (!strcmp(argv[i], maskArgs[k]))
556 argv[i][0] = ' ';
560 static void unmaskArgvKeywords(int argc, char **argv, const char **maskArgs)
562 int i, k;
564 for (i=1; i<argc; i++)
565 for (k=0; maskArgs[k]!=NULL; k++)
566 if (argv[i][0]==' ' && !strcmp(&argv[i][1], &maskArgs[k][1]))
567 argv[i][0] = '-';