- Change help version to 5.4DEV
[nedit.git] / source / nedit.c
blob35b940e636eda6046a82ae7a7581dc10408c08cc
1 static const char CVSID[] = "$Id: nedit.c,v 1.37 2002/11/13 21:57:44 tringali 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 *******************************************************************************/
33 #ifdef HAVE_CONFIG_H
34 #include "../config.h"
35 #endif
37 #include "nedit.h"
38 /* #include "textBuf.h" */
39 #include "file.h"
40 #include "preferences.h"
41 #include "regularExp.h"
42 #include "selection.h"
43 #include "tags.h"
44 #include "menu.h"
45 #include "macro.h"
46 #include "server.h"
47 #include "interpret.h"
48 #include "parse.h"
49 #include "help.h"
50 #include "../util/misc.h"
51 #include "../util/printUtils.h"
52 #include "../util/fileUtils.h"
53 #include "../util/getfiles.h"
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
59 #ifndef NO_XMIM
60 #include <X11/Xlocale.h>
61 #else
62 #include <locale.h>
63 #endif
64 #include <X11/Intrinsic.h>
65 #include <Xm/Xm.h>
66 #if XmVersion >= 1002
67 #include <Xm/RepType.h>
68 #endif
69 #ifdef VMS
70 #include <rmsdef.h>
71 #include "../util/VMSparam.h"
72 #include "../util/VMSUtils.h"
73 #else
74 #ifndef __MVS__
75 #include <sys/param.h>
76 #endif
77 #endif /*VMS*/
79 #ifdef HAVE_DEBUG_H
80 #include "../debug.h"
81 #endif
84 static void nextArg(int argc, char **argv, int *argIndex);
85 static int checkDoMacroArg(const char *macro);
86 static void maskArgvKeywords(int argc, char **argv, const char **maskArgs);
87 static void unmaskArgvKeywords(int argc, char **argv, const char **maskArgs);
88 static void patchResourcesForVisual(void);
90 WindowInfo *WindowList = NULL;
91 Display *TheDisplay = NULL;
92 char *ArgV0 = NULL;
93 Boolean IsServer = False;
95 /* iso8859 appears to be necessary for newer versions of XFree86 that
96 default to Unicode encoding, which doesn't quite work with Motif.
97 Otherwise Motif puts up garbage (square blocks).
99 (This of course, is a stupid default because there are far more iso8859
100 apps than Unicode apps. But the X folks insist it's a client bug. Hah.)
102 RedHat 7.3 won't default to '-1' for an encoding, if left with a *,
103 and so reverts to "fixed". Yech. */
105 #define NEDIT_DEFAULT_FONT "-*-helvetica-medium-r-normal-*-*-120-*-*-*-iso8859-1"
106 #define NEDIT_FIXED_FONT "-*-courier-medium-r-normal-*-*-120-*-*-*-iso8859-1"
108 static char *fallbackResources[] = {
109 /* Try to avoid Motif's horrificly ugly default colors and fonts,
110 if the user's environment provides no usable defaults. We try
111 to choose a Windows-y default color setting here. Editable text
112 fields are forced to a fixed-pitch font for usability. */
113 "*FontList: " NEDIT_DEFAULT_FONT,
114 "*XmText.FontList: " NEDIT_FIXED_FONT,
115 "*XmTextField.FontList: " NEDIT_FIXED_FONT,
116 "*XmList.FontList: " NEDIT_FIXED_FONT,
117 "*XmFileSelectionBox*XmList.FontList: " NEDIT_FIXED_FONT,
118 "*background: #b3b3b3",
119 "*foreground: black",
120 "*XmText*foreground: black",
121 "*XmText*background: #e5e5e5",
122 "*XmList*foreground: black",
123 "*XmList*background: #e5e5e5",
124 "*XmTextField*foreground: black",
125 "*XmTextField*background: #e5e5e5",
126 "*XmText.translations: #override\\n"
127 "Ctrl~Alt~Meta<KeyPress>v: paste-clipboard()\\n"
128 "Ctrl~Alt~Meta<KeyPress>c: copy-clipboard()\\n"
129 "Ctrl~Alt~Meta<KeyPress>x: cut-clipboard()\\n"
130 "Ctrl~Alt~Meta<KeyPress>u: delete-to-start-of-line()\\n",
131 "*XmTextField.translations: #override\\n"
132 "Ctrl~Alt~Meta<KeyPress>v: paste-clipboard()\\n"
133 "Ctrl~Alt~Meta<KeyPress>c: copy-clipboard()\\n"
134 "Ctrl~Alt~Meta<KeyPress>x: cut-clipboard()\\n"
135 "Ctrl~Alt~Meta<KeyPress>u: delete-to-start-of-line()\\n",
137 /* NEdit-specific widgets. Theses things should probably be manually
138 jammed into the database, rather than fallbacks. We really want
139 the accelerators to be there even if someone creates an app-defaults
140 file against our wishes. */
142 "*text.lineNumForeground: #777777",
143 "*text.background: #e5e5e5",
144 "*text.foreground: black",
145 "*text.highlightBackground: red",
146 "*text.highlightForeground: black",
147 "*menuBar.marginHeight: 0",
148 "*menuBar.shadowThickness: 1",
149 "*pane.sashHeight: 11",
150 "*pane.sashWidth: 11",
151 "*text.selectionArrayCount: 3",
152 "*helpText.background: #cccccc",
153 "*helpText.foreground: black",
154 "*helpText.selectBackground: #b3b3b3",
155 "*statsLine.background: #b3b3b3",
156 "*statsLine.FontList: " NEDIT_DEFAULT_FONT,
157 "*helpText.font: " NEDIT_FIXED_FONT,
158 "*calltip.background: LemonChiffon1",
159 "*calltip.foreground: black",
160 "*iSearchForm*highlightThickness: 1",
161 "*fileMenu.tearOffModel: XmTEAR_OFF_ENABLED",
162 "*editMenu.tearOffModel: XmTEAR_OFF_ENABLED",
163 "*searchMenu.tearOffModel: XmTEAR_OFF_ENABLED",
164 "*preferencesMenu.tearOffModel: XmTEAR_OFF_ENABLED",
165 "*windowsMenu.tearOffModel: XmTEAR_OFF_ENABLED",
166 "*shellMenu.tearOffModel: XmTEAR_OFF_ENABLED",
167 "*macroMenu.tearOffModel: XmTEAR_OFF_ENABLED",
168 "*helpMenu.tearOffModel: XmTEAR_OFF_ENABLED",
169 "*fileMenu.mnemonic: F",
170 "*fileMenu.new.accelerator: Ctrl<Key>n",
171 "*fileMenu.new.acceleratorText: Ctrl+N",
172 "*fileMenu.open.accelerator: Ctrl<Key>o",
173 "*fileMenu.open.acceleratorText: Ctrl+O",
174 "*fileMenu.openSelected.accelerator: Ctrl<Key>y",
175 "*fileMenu.openSelected.acceleratorText: Ctrl+Y",
176 "*fileMenu.close.accelerator: Ctrl<Key>w",
177 "*fileMenu.close.acceleratorText: Ctrl+W",
178 "*fileMenu.save.accelerator: Ctrl<Key>s",
179 "*fileMenu.save.acceleratorText: Ctrl+S",
180 "*fileMenu.includeFile.accelerator: Alt<Key>i",
181 "*fileMenu.includeFile.acceleratorText: Alt+I",
182 "*fileMenu.print.accelerator: Ctrl<Key>p",
183 "*fileMenu.print.acceleratorText: Ctrl+P",
184 "*fileMenu.exit.accelerator: Ctrl<Key>q",
185 "*fileMenu.exit.acceleratorText: Ctrl+Q",
186 "*editMenu.mnemonic: E",
187 "*editMenu.undo.accelerator: Ctrl<Key>z",
188 "*editMenu.undo.acceleratorText: Ctrl+Z",
189 "*editMenu.redo.accelerator: Shift Ctrl<Key>z",
190 "*editMenu.redo.acceleratorText: Shift+Ctrl+Z",
191 "*editMenu.cut.accelerator: Ctrl<Key>x",
192 "*editMenu.cut.acceleratorText: Ctrl+X",
193 "*editMenu.copy.accelerator: Ctrl<Key>c",
194 "*editMenu.copy.acceleratorText: Ctrl+C",
195 "*editMenu.paste.accelerator: Ctrl<Key>v",
196 "*editMenu.paste.acceleratorText: Ctrl+V",
197 "*editMenu.pasteColumn.accelerator: Shift Ctrl<Key>v",
198 "*editMenu.pasteColumn.acceleratorText: Ctrl+Shift+V",
199 "*editMenu.delete.acceleratorText: Del",
200 "*editMenu.selectAll.accelerator: Ctrl<Key>a",
201 "*editMenu.selectAll.acceleratorText: Ctrl+A",
202 "*editMenu.shiftLeft.accelerator: Ctrl<Key>9",
203 "*editMenu.shiftLeft.acceleratorText: [Shift]Ctrl+9",
204 "*editMenu.shiftLeftShift.accelerator: Shift Ctrl<Key>9",
205 "*editMenu.shiftRight.accelerator: Ctrl<Key>0",
206 "*editMenu.shiftRight.acceleratorText: [Shift]Ctrl+0",
207 "*editMenu.shiftRightShift.accelerator: Shift Ctrl<Key>0",
208 "*editMenu.upperCase.accelerator: Ctrl<Key>6",
209 "*editMenu.upperCase.acceleratorText: Ctrl+6",
210 "*editMenu.lowerCase.accelerator: Shift Ctrl<Key>6",
211 "*editMenu.lowerCase.acceleratorText: Shift+Ctrl+6",
212 "*editMenu.fillParagraph.accelerator: Ctrl<Key>j",
213 "*editMenu.fillParagraph.acceleratorText: Ctrl+J",
214 "*editMenu.insertFormFeed.accelerator: Alt Ctrl<Key>l",
215 "*editMenu.insertFormFeed.acceleratorText: Alt+Ctrl+L",
216 "*editMenu.insertCtrlCode.accelerator: Alt Ctrl<Key>i",
217 "*editMenu.insertCtrlCode.acceleratorText: Alt+Ctrl+I",
218 "*searchMenu.mnemonic: S",
219 "*searchMenu.find.accelerator: Ctrl<Key>f",
220 "*searchMenu.find.acceleratorText: [Shift]Ctrl+F",
221 "*searchMenu.findShift.accelerator: Shift Ctrl<Key>f",
222 "*searchMenu.findAgain.accelerator: Ctrl<Key>g",
223 "*searchMenu.findAgain.acceleratorText: [Shift]Ctrl+G",
224 "*searchMenu.findAgainShift.accelerator: Shift Ctrl<Key>g",
225 "*searchMenu.findSelection.accelerator: Ctrl<Key>h",
226 "*searchMenu.findSelection.acceleratorText: [Shift]Ctrl+H",
227 "*searchMenu.findSelectionShift.accelerator: Shift Ctrl<Key>h",
228 "*searchMenu.findIncremental.accelerator: Ctrl<Key>i",
229 "*searchMenu.findIncrementalShift.accelerator: Shift Ctrl<Key>i",
230 "*searchMenu.findIncremental.acceleratorText: [Shift]Ctrl+I",
231 "*searchMenu.replace.accelerator: Ctrl<Key>r",
232 "*searchMenu.replace.acceleratorText: [Shift]Ctrl+R",
233 "*searchMenu.replaceShift.accelerator: Shift Ctrl<Key>r",
234 "*searchMenu.findReplace.accelerator: Ctrl<Key>r",
235 "*searchMenu.findReplace.acceleratorText: [Shift]Ctrl+R",
236 "*searchMenu.findReplaceShift.accelerator: Shift Ctrl<Key>r",
237 "*searchMenu.replaceFindAgain.accelerator: Ctrl<Key>t",
238 "*searchMenu.replaceFindAgain.acceleratorText: [Shift]Ctrl+T",
239 "*searchMenu.replaceFindAgainShift.accelerator: Shift Ctrl<Key>t",
240 "*searchMenu.replaceAgain.accelerator: Alt<Key>t",
241 "*searchMenu.replaceAgain.acceleratorText: [Shift]Alt+T",
242 "*searchMenu.replaceAgainShift.accelerator: Shift Alt<Key>t",
243 "*searchMenu.gotoLineNumber.accelerator: Ctrl<Key>l",
244 "*searchMenu.gotoLineNumber.acceleratorText: Ctrl+L",
245 "*searchMenu.gotoSelected.accelerator: Ctrl<Key>e",
246 "*searchMenu.gotoSelected.acceleratorText: Ctrl+E",
247 "*searchMenu.mark.accelerator: Alt<Key>m",
248 "*searchMenu.mark.acceleratorText: Alt+M a-z",
249 "*searchMenu.gotoMark.accelerator: Alt<Key>g",
250 "*searchMenu.gotoMark.acceleratorText: [Shift]Alt+G a-z",
251 "*searchMenu.gotoMarkShift.accelerator: Shift Alt<Key>g",
252 "*searchMenu.gotoMatching.accelerator: Ctrl<Key>m",
253 "*searchMenu.gotoMatching.acceleratorText: [Shift]Ctrl+M",
254 "*searchMenu.gotoMatchingShift.accelerator: Shift Ctrl<Key>m",
255 "*searchMenu.findDefinition.accelerator: Ctrl<Key>d",
256 "*searchMenu.findDefinition.acceleratorText: Ctrl+D",
257 "*searchMenu.showCalltip.accelerator: Ctrl<Key>apostrophe",
258 "*searchMenu.showCalltip.acceleratorText: Ctrl+'",
259 "*preferencesMenu.mnemonic: P",
260 "*preferencesMenu.statisticsLine.accelerator: Alt<Key>a",
261 "*preferencesMenu.statisticsLine.acceleratorText: Alt+A",
262 "*preferencesMenu.overtype.acceleratorText: Insert",
263 "*shellMenu.mnemonic: l",
264 "*shellMenu.filterSelection.accelerator: Alt<Key>r",
265 "*shellMenu.filterSelection.acceleratorText: Alt+R",
266 "*shellMenu.executeCommand.accelerator: Alt<Key>x",
267 "*shellMenu.executeCommand.acceleratorText: Alt+X",
268 "*shellMenu.executeCommandLine.accelerator: <Key>KP_Enter",
269 "*shellMenu.executeCommandLine.acceleratorText: KP Enter",
270 "*shellMenu.cancelShellCommand.accelerator: Ctrl<Key>period",
271 "*shellMenu.cancelShellCommand.acceleratorText: Ctrl+.",
272 "*macroMenu.mnemonic: c",
273 "*macroMenu.learnKeystrokes.accelerator: Alt<Key>k",
274 "*macroMenu.learnKeystrokes.acceleratorText: Alt+K",
275 "*macroMenu.finishLearn.accelerator: Alt<Key>k",
276 "*macroMenu.finishLearn.acceleratorText: Alt+K",
277 "*macroMenu.cancelLearn.accelerator: Ctrl<Key>period",
278 "*macroMenu.cancelLearn.acceleratorText: Ctrl+.",
279 "*macroMenu.replayKeystrokes.accelerator: Ctrl<Key>k",
280 "*macroMenu.replayKeystrokes.acceleratorText: Ctrl+K",
281 "*macroMenu.repeat.accelerator: Ctrl<Key>comma",
282 "*macroMenu.repeat.acceleratorText: Ctrl+,",
283 "*windowsMenu.mnemonic: W",
284 "*windowsMenu.splitWindow.accelerator: Ctrl<Key>2",
285 "*windowsMenu.splitWindow.acceleratorText: Ctrl+2",
286 "*windowsMenu.closePane.accelerator: Ctrl<Key>1",
287 "*windowsMenu.closePane.acceleratorText: Ctrl+1",
288 "*helpMenu.mnemonic: H",
289 "nedit.helpForm.sw.helpText*translations: #override\
290 <Key>Tab:help-focus-buttons()\\n\
291 <Key>Return:help-button-action(\"dismiss\")\\n\
292 <KeyPress>osfCancel:help-button-action(\"dismiss\")\\n\
293 ~Meta~Ctrl~Shift<Btn1Down>:\
294 grab-focus() help-hyperlink()\\n\
295 ~Meta~Ctrl~Shift<Btn1Up>:\
296 help-hyperlink(\"current\", \"process-cancel\", \"extend-end\")\\n\
297 ~Meta~Ctrl~Shift<Btn2Down>:\
298 process-bdrag() help-hyperlink()\\n\
299 ~Meta~Ctrl~Shift<Btn2Up>:\
300 help-hyperlink(\"new\", \"process-cancel\", \"copy-to\")",
301 NULL
304 static const char cmdLineHelp[] =
305 #ifndef VMS
306 "Usage: nedit [-read] [-create] [-line n | +n] [-server] [-do command]\n\
307 [-tags file] [-tabs n] [-wrap] [-nowrap] [-autowrap]\n\
308 [-autoindent] [-noautoindent] [-autosave] [-noautosave]\n\
309 [-lm languagemode] [-rows n] [-columns n] [-font font]\n\
310 [-geometry geometry] [-iconic] [-noiconic] [-svrname name]\n\
311 [-display [host]:server[.screen] [-xrm resourcestring]\n\
312 [-import file] [-background color] [-foreground color]\n\
313 [-V|-version] [--]\n\
314 [file...]\n";
315 #else
317 #endif /*VMS*/
319 int main(int argc, char **argv)
321 int i, lineNum, nRead, fileSpecified = FALSE, editFlags = CREATE;
322 int gotoLine = False, macroFileRead = False, opts = True;
323 int iconic = False;
324 char *toDoCommand = NULL, *geometry = NULL, *langMode = NULL;
325 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
326 XtAppContext context;
327 XrmDatabase prefDB;
328 static const char *protectedKeywords[] = {"-iconic", "-icon", "-geometry",
329 "-g", "-rv", "-reverse", "-bd", "-bordercolor", "-borderwidth",
330 "-bw", "-title", NULL};
332 /* Save the command which was used to invoke nedit for restart command */
333 ArgV0 = argv[0];
335 /* Set locale for C library, X, and Motif input functions.
336 Reverts to "C" if requested locale not available. */
337 XtSetLanguageProc(NULL, NULL, NULL);
339 /* Initialize X toolkit (does not open display yet) */
340 XtToolkitInitialize();
341 context = XtCreateApplicationContext();
343 /* Set up a warning handler to trap obnoxious Xt grab warnings */
344 SuppressPassiveGrabWarnings();
346 /* Set up default resources if no app-defaults file is found */
347 XtAppSetFallbackResources(context, fallbackResources);
349 #if XmVersion >= 1002
350 /* Allow users to change tear off menus with X resources */
351 XmRepTypeInstallTearOffModelConverter();
352 #endif
354 #ifdef VMS
355 /* Convert the command line to Unix style (This is not an ideal solution) */
356 ConvertVMSCommandLine(&argc, &argv);
357 #endif /*VMS*/
358 #ifdef __EMX__
359 /* expand wildcards if necessary */
360 _wildcard(&argc, &argv);
361 #endif
363 /* Read the preferences file and command line into a database */
364 prefDB = CreateNEditPrefDB(&argc, argv);
366 /* Open the display and read X database and remaining command line args.
367 XtOpenDisplay must be allowed to process some of the resource arguments
368 with its inaccessible internal option table, but others, like -geometry
369 and -iconic are per-window and it should not be allowed to consume them,
370 so we temporarily masked them out. */
371 maskArgvKeywords(argc, argv, protectedKeywords);
372 TheDisplay = XtOpenDisplay (context, NULL, APP_NAME, APP_CLASS,
373 NULL, 0, &argc, argv);
374 unmaskArgvKeywords(argc, argv, protectedKeywords);
375 if (!TheDisplay) {
376 XtWarning ("NEdit: Can't open display\n");
377 exit(EXIT_FAILURE);
380 patchResourcesForVisual();
382 /* Initialize global symbols and subroutines used in the macro language */
383 InitMacroGlobals();
384 RegisterMacroSubroutines();
386 /* Store preferences from the command line and .nedit file,
387 and set the appropriate preferences */
388 RestoreNEditPrefs(prefDB, XtDatabase(TheDisplay));
389 LoadPrintPreferences(XtDatabase(TheDisplay), APP_NAME, APP_CLASS, True);
390 SetDeleteRemap(GetPrefMapDelete());
391 SetPointerCenteredDialogs(GetPrefRepositionDialogs());
392 SetGetEFTextFieldRemoval(!GetPrefStdOpenDialog());
394 /* Set up action procedures for menu item commands */
395 InstallMenuActions(context);
397 /* Add Actions for following hyperlinks in the help window */
398 InstallHelpLinkActions(context);
400 /* Install word delimiters for regular expression matching */
401 SetREDefaultWordDelimiters(GetPrefDelimiters());
403 /* Read the nedit dynamic database of files for the Open Previous
404 command (and eventually other information as well) */
405 ReadNEditDB();
407 /* Process -import command line argument before others which might
408 open windows (loading preferences doesn't update menu settings,
409 which would then be out of sync with the real preference settings) */
410 for (i=1; i<argc; i++) {
411 if(!strcmp(argv[i], "--")) {
412 break; /* treat all remaining arguments as filenames */
413 } else if (!strcmp(argv[i], "-import")) {
414 nextArg(argc, argv, &i);
415 ImportPrefFile(argv[i], False);
416 } else if (!strcmp(argv[i], "-importold")) {
417 nextArg(argc, argv, &i);
418 ImportPrefFile(argv[i], True);
422 /* Load the default tags file. Don't complain if it doesn't load, the tag
423 file resource is intended to be set and forgotten. Running nedit in a
424 directory without a tags should not cause it to spew out errors. */
425 if (*GetPrefTagFile() != '\0')
426 AddTagsFile(GetPrefTagFile(), TAG);
428 /* Process any command line arguments (-tags, -do, -read, -create,
429 +<line_number>, -line, -server, and files to edit) not already
430 processed by RestoreNEditPrefs. */
431 fileSpecified = FALSE;
432 for (i=1; i<argc; i++) {
433 if (opts && !strcmp(argv[i], "--")) {
434 opts = False; /* treat all remaining arguments as filenames */
435 continue;
436 } else if (opts && !strcmp(argv[i], "-tags")) {
437 nextArg(argc, argv, &i);
438 if (!AddTagsFile(argv[i], TAG))
439 fprintf(stderr, "NEdit: Unable to load tags file\n");
440 } else if (opts && !strcmp(argv[i], "-do")) {
441 nextArg(argc, argv, &i);
442 if (checkDoMacroArg(argv[i]))
443 toDoCommand = argv[i];
444 } else if (opts && !strcmp(argv[i], "-read")) {
445 editFlags |= PREF_READ_ONLY;
446 } else if (opts && !strcmp(argv[i], "-create")) {
447 editFlags |= SUPPRESS_CREATE_WARN;
448 } else if (opts && !strcmp(argv[i], "-line")) {
449 nextArg(argc, argv, &i);
450 nRead = sscanf(argv[i], "%d", &lineNum);
451 if (nRead != 1)
452 fprintf(stderr, "NEdit: argument to line should be a number\n");
453 else
454 gotoLine = True;
455 } else if (opts && (*argv[i] == '+')) {
456 nRead = sscanf((argv[i]+1), "%d", &lineNum);
457 if (nRead != 1)
458 fprintf(stderr, "NEdit: argument to + should be a number\n");
459 else
460 gotoLine = True;
461 } else if (opts && !strcmp(argv[i], "-server")) {
462 IsServer = True;
463 } else if (opts && (!strcmp(argv[i], "-iconic") ||
464 !strcmp(argv[i], "-icon"))) {
465 iconic = True;
466 } else if (opts && !strcmp(argv[i], "-noiconic")) {
467 iconic = False;
468 } else if (opts && (!strcmp(argv[i], "-geometry") ||
469 !strcmp(argv[i], "-g"))) {
470 nextArg(argc, argv, &i);
471 geometry = argv[i];
472 } else if (opts && !strcmp(argv[i], "-lm")) {
473 nextArg(argc, argv, &i);
474 langMode = argv[i];
475 } else if (opts && !strcmp(argv[i], "-import")) {
476 nextArg(argc, argv, &i); /* already processed, skip */
477 } else if (opts && (!strcmp(argv[i], "-V") ||
478 !strcmp(argv[i], "-version"))) {
479 PrintVersion();
480 exit(EXIT_SUCCESS);
481 } else if (opts && (*argv[i] == '-')) {
482 #ifdef VMS
483 *argv[i] = '/';
484 #endif /*VMS*/
485 fprintf(stderr, "NEdit: Unrecognized option %s\n%s", argv[i],
486 cmdLineHelp);
487 exit(EXIT_FAILURE);
488 } else {
489 #ifdef VMS
490 int numFiles, j;
491 char **nameList = NULL;
492 /* Use VMS's LIB$FILESCAN for filename in argv[i] to process */
493 /* wildcards and to obtain a full VMS file specification */
494 numFiles = VMSFileScan(argv[i], &nameList, NULL, INCLUDE_FNF);
495 /* for each expanded file name do: */
496 for (j = 0; j < numFiles; ++j) {
497 ParseFilename(nameList[j], filename, pathname);
498 EditExistingFile(WindowList, filename, pathname, editFlags,
499 geometry, iconic, langMode);
500 if (!macroFileRead) {
501 ReadMacroInitFile(WindowList);
502 macroFileRead = True;
504 if (toDoCommand != NULL)
505 DoMacro(WindowList, toDoCommand, "-do macro");
506 if (gotoLine)
507 SelectNumberedLine(WindowList, lineNum);
508 fileSpecified = TRUE;
509 free(nameList[j]);
511 if (nameList != NULL)
512 free(nameList);
513 #else
514 if (ParseFilename(argv[i], filename, pathname) == 0 ) {
515 EditExistingFile(WindowList, filename, pathname, editFlags,
516 geometry, iconic, langMode);
517 fileSpecified = TRUE;
518 } else {
519 fprintf(stderr, "NEdit: file name too long: %s", argv[i]);
521 if (!macroFileRead) {
522 ReadMacroInitFile(WindowList);
523 macroFileRead = True;
525 if (toDoCommand != NULL)
526 DoMacro(WindowList, toDoCommand, "-do macro");
527 if (gotoLine)
528 SelectNumberedLine(WindowList, lineNum);
529 #endif /*VMS*/
530 toDoCommand = NULL;
533 #ifdef VMS
534 VMSFileScanDone();
535 #endif /*VMS*/
537 /* If no file to edit was specified, open a window to edit "Untitled" */
538 if (!fileSpecified) {
539 EditNewFile(geometry, iconic, langMode, NULL);
540 ReadMacroInitFile(WindowList);
541 if (toDoCommand != NULL)
542 DoMacro(WindowList, toDoCommand, "-do macro");
545 /* Begin remembering last command invoked for "Repeat" menu item */
546 AddLastCommandActionHook(context);
548 /* Set up communication port and write ~/.nedit_server_process file */
549 if (IsServer)
550 InitServerCommunication();
552 /* Process events. */
553 if (IsServer)
554 ServerMainLoop(context);
555 else
556 XtAppMainLoop(context);
558 /* Not reached but this keeps some picky compilers happy */
559 return EXIT_SUCCESS;
562 static void nextArg(int argc, char **argv, int *argIndex)
564 if (*argIndex + 1 >= argc) {
565 #ifdef VMS
566 *argv[*argIndex] = '/';
567 #endif /*VMS*/
568 fprintf(stderr, "NEdit: %s requires an argument\n%s", argv[*argIndex],
569 cmdLineHelp);
570 exit(EXIT_FAILURE);
572 (*argIndex)++;
576 ** Return True if -do macro is valid, otherwise write an error on stderr
578 static int checkDoMacroArg(const char *macro)
580 Program *prog;
581 char *errMsg, *stoppedAt, *tMacro;
582 int macroLen;
584 /* Add a terminating newline (which command line users are likely to omit
585 since they are typically invoking a single routine) */
586 macroLen = strlen(macro);
587 tMacro = XtMalloc(strlen(macro)+2);
588 strncpy(tMacro, macro, macroLen);
589 tMacro[macroLen] = '\n';
590 tMacro[macroLen+1] = '\0';
592 /* Do a test parse */
593 prog = ParseMacro(tMacro, &errMsg, &stoppedAt);
594 if (prog == NULL) {
595 ParseError(NULL, tMacro, stoppedAt, "argument to -do", errMsg);
596 return False;
598 FreeProgram(prog);
599 return True;
603 ** maskArgvKeywords and unmaskArgvKeywords mangle selected keywords by
604 ** replacing the '-' with a space, for the purpose of hiding them from
605 ** XtOpenDisplay's option processing. Why this silly scheme? XtOpenDisplay
606 ** really needs to see command line arguments, particularly -display, but
607 ** there's no way to change the option processing table it uses, to keep
608 ** it from consuming arguments which are meant to apply per-window, like
609 ** -geometry and -iconic.
611 static void maskArgvKeywords(int argc, char **argv, const char **maskArgs)
613 int i, k;
615 for (i=1; i<argc; i++)
616 for (k=0; maskArgs[k]!=NULL; k++)
617 if (!strcmp(argv[i], maskArgs[k]))
618 argv[i][0] = ' ';
622 static void unmaskArgvKeywords(int argc, char **argv, const char **maskArgs)
624 int i, k;
626 for (i=1; i<argc; i++)
627 for (k=0; maskArgs[k]!=NULL; k++)
628 if (argv[i][0]==' ' && !strcmp(&argv[i][1], &maskArgs[k][1]))
629 argv[i][0] = '-';
633 ** If we're not using the default visual, then some default resources in
634 ** the database (colors) are not valid, because they are indexes into the
635 ** default colormap. If we used them blindly, then we'd get "random"
636 ** unreadable colors. So we inspect the resource list, and use the
637 ** fallback "grey" color instead if this is the case.
639 static void patchResourcesForVisual(void)
641 Cardinal i;
642 Visual *visual;
643 int depth;
644 Colormap map;
645 Boolean usingDefaultVisual;
646 XrmDatabase db;
648 if (!TheDisplay)
649 return;
651 db = XtDatabase(TheDisplay);
653 usingDefaultVisual = FindBestVisual(TheDisplay,
654 APP_NAME,
655 APP_CLASS,
656 &visual,
657 &depth,
658 &map);
660 if (!usingDefaultVisual)
662 for (i = 1; i < XtNumber(fallbackResources); ++i)
664 Cardinal resIndex = i - 1;
666 if (strstr(fallbackResources[resIndex], "*background:") ||
667 strstr(fallbackResources[resIndex], "*foreground:"))
669 /* Qualify by application name to prevent them from being
670 converted against the wrong colormap. */
671 char buf[1024] = "*" APP_NAME;
672 strcat(buf, fallbackResources[resIndex]);
673 XrmPutLineResource(&db, buf);