static const char CVSID[] = "$Id: nedit.c,v 1.83 2004/09/02 08:49:56 edg Exp $"; /******************************************************************************* * * * nedit.c -- Nirvana Editor main program * * * * Copyright (C) 1999 Mark Edel * * * * This is free software; you can redistribute it and/or modify it under the * * terms of the GNU General Public License as published by the Free Software * * Foundation; either version 2 of the License, or (at your option) any later * * version. In addition, you may distribute version of this program linked to * * Motif or Open Motif. See README for details. * * * * This software is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * * for more details. * * * * You should have received a copy of the GNU General Public License along with * * software; if not, write to the Free Software Foundation, Inc., 59 Temple * * Place, Suite 330, Boston, MA 02111-1307 USA * * * * Nirvana Text Editor * * May 10, 1991 * * * * Written by Mark Edel * * * * Modifications: * * * * 8/18/93 - Mark Edel & Joy Kyriakopulos - Ported to VMS * * * *******************************************************************************/ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "nedit.h" /* #include "textBuf.h" */ #include "file.h" #include "preferences.h" #include "regularExp.h" #include "selection.h" #include "tags.h" #include "menu.h" #include "macro.h" #include "server.h" #include "interpret.h" #include "parse.h" #include "help.h" #include "../util/misc.h" #include "../util/printUtils.h" #include "../util/fileUtils.h" #include "../util/getfiles.h" #include #include #include #include #include #ifndef NO_XMIM #include #else #include #endif #include #include #include #if XmVersion >= 1002 #include #endif #ifdef VMS #include #include "../util/VMSparam.h" #include "../util/VMSUtils.h" #else #ifndef __MVS__ #include #endif #endif /*VMS*/ #ifdef HAVE_DEBUG_H #include "../debug.h" #endif static void nextArg(int argc, char **argv, int *argIndex); static int checkDoMacroArg(const char *macro); static String neditLanguageProc(Display *dpy, String xnl, XtPointer closure); static void maskArgvKeywords(int argc, char **argv, const char **maskArgs); static void unmaskArgvKeywords(int argc, char **argv, const char **maskArgs); static void patchResourcesForVisual(void); static void patchResourcesForKDEbug(void); static void patchLocaleForMotif(void); static unsigned char* sanitizeVirtualKeyBindings(); static int sortAlphabetical(const void* k1, const void* k2); static int virtKeyBindingsAreInvalid(const unsigned char* bindings); static void restoreInsaneVirtualKeyBindings(unsigned char* bindings); #ifdef LESSTIF_VERSION static void bogusWarningFilter(String); #endif WindowInfo *WindowList = NULL; Display *TheDisplay = NULL; char *ArgV0 = NULL; Boolean IsServer = False; Widget TheAppShell; /* Reasons for choice of default font qualifications: iso8859 appears to be necessary for newer versions of XFree86 that default to Unicode encoding, which doesn't quite work with Motif. Otherwise Motif puts up garbage (square blocks). (This of course, is a stupid default because there are far more iso8859 apps than Unicode apps. But the X folks insist it's a client bug. Hah.) RedHat 7.3 won't default to '-1' for an encoding, if left with a *, and so reverts to "fixed". Yech. */ #define NEDIT_DEFAULT_FONT "-*-helvetica-medium-r-normal-*-*-120-*-*-*-iso8859-1," \ "-*-helvetica-bold-r-normal-*-*-120-*-*-*-iso8859-1=BOLD," \ "-*-helvetica-medium-o-normal-*-*-120-*-*-*-iso8859-1=ITALIC" #define NEDIT_FIXED_FONT "-*-courier-medium-r-normal-*-*-120-*-*-*-iso8859-1," \ "-*-courier-bold-r-normal-*-*-120-*-*-*-iso8859-1=BOLD," \ "-*-courier-medium-o-normal-*-*-120-*-*-*-iso8859-1=ITALIC" #define NEDIT_DEFAULT_BG "#b3b3b3" static char *fallbackResources[] = { /* Try to avoid Motif's horrificly ugly default colors and fonts, if the user's environment provides no usable defaults. We try to choose a Windows-y default color setting here. Editable text fields are forced to a fixed-pitch font for usability. By using the VendorShell fontList resources, Motif automatically groups the fonts into the right classes. It's then easier for the user or environment to override this sensibly: nedit -xrm '*textFontList: myfont' */ #if (defined(LESSTIF_VERSION) && defined(__CYGWIN__)) "*FontList: " NEDIT_DEFAULT_FONT, "*XmText.FontList: " NEDIT_FIXED_FONT, "*XmTextField.FontList: " NEDIT_FIXED_FONT, "*XmList.FontList: " NEDIT_FIXED_FONT, "*XmFileSelectionBox*XmList.FontList: " NEDIT_FIXED_FONT, #else "*buttonFontList: " NEDIT_DEFAULT_FONT, "*labelFontList: " NEDIT_DEFAULT_FONT, "*textFontList: " NEDIT_FIXED_FONT, #endif "*background: " NEDIT_DEFAULT_BG, "*foreground: " NEDIT_DEFAULT_FG, "*XmText.foreground: " NEDIT_DEFAULT_FG, "*XmText.background: " NEDIT_DEFAULT_TEXT_BG, "*XmList.foreground: " NEDIT_DEFAULT_FG, "*XmList.background: " NEDIT_DEFAULT_TEXT_BG, "*XmTextField.foreground: " NEDIT_DEFAULT_FG, "*XmTextField.background: " NEDIT_DEFAULT_TEXT_BG, "*XmText.translations: #override\\n" "Ctrl~Alt~Metav: paste-clipboard()\\n" "Ctrl~Alt~Metac: copy-clipboard()\\n" "Ctrl~Alt~Metax: cut-clipboard()\\n" "Ctrl~Alt~Metau: delete-to-start-of-line()\\n", "*XmTextField.translations: #override\\n" "Ctrl~Alt~Metav: paste-clipboard()\\n" "Ctrl~Alt~Metac: copy-clipboard()\\n" "Ctrl~Alt~Metax: cut-clipboard()\\n" "Ctrl~Alt~Metau: delete-to-start-of-line()\\n", "*XmLFolder.highlightThickness: 0", "*XmLFolder.shadowThickness: 1", "*XmLFolder.maxTabWidth: 150", "*XmLFolder.traversalOn: False", "*XmLFolder.inactiveForeground: #666" , "*tab.alignment: XmALIGNMENT_BEGINNING", "*tab.marginWidth: 0", "*tab.marginHeight: 1", /* Prevent the file selection box from acting stupid. */ "*XmFileSelectionBox.resizePolicy: XmRESIZE_NONE", "*XmFileSelectionBox.textAccelerators:", /* NEdit-specific widgets. Theses things should probably be manually jammed into the database, rather than fallbacks. We really want the accelerators to be there even if someone creates an app-defaults file against our wishes. */ "*text.lineNumForeground: " NEDIT_DEFAULT_LINENO_FG, "*text.background: " NEDIT_DEFAULT_TEXT_BG, "*text.foreground: " NEDIT_DEFAULT_FG, "*text.highlightForeground: " NEDIT_DEFAULT_HI_FG, "*text.highlightBackground: " NEDIT_DEFAULT_HI_BG, "*textFrame.shadowThickness: 1", "*menuBar.marginHeight: 0", "*menuBar.shadowThickness: 1", "*pane.sashHeight: 11", "*pane.sashWidth: 11", "*pane.marginWidth: 0", "*pane.marginHeight: 0", "*scrolledW*spacing: 0", "*text.selectionArrayCount: 3", "*helpText.background: " NEDIT_DEFAULT_HELP_BG, "*helpText.foreground: " NEDIT_DEFAULT_HELP_FG, "*helpText.selectBackground: " NEDIT_DEFAULT_BG, "*statsLine.background: " NEDIT_DEFAULT_BG, "*statsLine.FontList: " NEDIT_DEFAULT_FONT, "*calltip.background: LemonChiffon1", "*calltip.foreground: black", "*iSearchForm*highlightThickness: 1", "*fileMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*editMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*searchMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*preferencesMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*windowsMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*shellMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*macroMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*helpMenu.tearOffModel: XmTEAR_OFF_ENABLED", "*fileMenu.mnemonic: F", "*fileMenu.new.accelerator: Ctrln", "*fileMenu.new.acceleratorText: Ctrl+N", "*fileMenu.newOpposite.accelerator: Shift Ctrln", "*fileMenu.newOpposite.acceleratorText: Shift+Ctrl+N", "*fileMenu.open.accelerator: Ctrlo", "*fileMenu.open.acceleratorText: Ctrl+O", "*fileMenu.openSelected.accelerator: Ctrly", "*fileMenu.openSelected.acceleratorText: Ctrl+Y", "*fileMenu.close.accelerator: Ctrlw", "*fileMenu.close.acceleratorText: Ctrl+W", "*fileMenu.save.accelerator: Ctrls", "*fileMenu.save.acceleratorText: Ctrl+S", "*fileMenu.includeFile.accelerator: Alti", "*fileMenu.includeFile.acceleratorText: Alt+I", "*fileMenu.print.accelerator: Ctrlp", "*fileMenu.print.acceleratorText: Ctrl+P", "*fileMenu.exit.accelerator: Ctrlq", "*fileMenu.exit.acceleratorText: Ctrl+Q", "*editMenu.mnemonic: E", "*editMenu.undo.accelerator: Ctrlz", "*editMenu.undo.acceleratorText: Ctrl+Z", "*editMenu.redo.accelerator: Shift Ctrlz", "*editMenu.redo.acceleratorText: Shift+Ctrl+Z", "*editMenu.cut.accelerator: Ctrlx", "*editMenu.cut.acceleratorText: Ctrl+X", "*editMenu.copy.accelerator: Ctrlc", "*editMenu.copy.acceleratorText: Ctrl+C", "*editMenu.paste.accelerator: Ctrlv", "*editMenu.paste.acceleratorText: Ctrl+V", "*editMenu.pasteColumn.accelerator: Shift Ctrlv", "*editMenu.pasteColumn.acceleratorText: Ctrl+Shift+V", "*editMenu.delete.acceleratorText: Del", "*editMenu.selectAll.accelerator: Ctrla", "*editMenu.selectAll.acceleratorText: Ctrl+A", "*editMenu.shiftLeft.accelerator: Ctrl9", "*editMenu.shiftLeft.acceleratorText: [Shift]Ctrl+9", "*editMenu.shiftLeftShift.accelerator: Shift Ctrl9", "*editMenu.shiftRight.accelerator: Ctrl0", "*editMenu.shiftRight.acceleratorText: [Shift]Ctrl+0", "*editMenu.shiftRightShift.accelerator: Shift Ctrl0", "*editMenu.upperCase.accelerator: Ctrl6", "*editMenu.upperCase.acceleratorText: Ctrl+6", "*editMenu.lowerCase.accelerator: Shift Ctrl6", "*editMenu.lowerCase.acceleratorText: Shift+Ctrl+6", "*editMenu.fillParagraph.accelerator: Ctrlj", "*editMenu.fillParagraph.acceleratorText: Ctrl+J", "*editMenu.insertFormFeed.accelerator: Alt Ctrll", "*editMenu.insertFormFeed.acceleratorText: Alt+Ctrl+L", "*editMenu.insertCtrlCode.accelerator: Alt Ctrli", "*editMenu.insertCtrlCode.acceleratorText: Alt+Ctrl+I", "*searchMenu.mnemonic: S", "*searchMenu.find.accelerator: Ctrlf", "*searchMenu.find.acceleratorText: [Shift]Ctrl+F", "*searchMenu.findShift.accelerator: Shift Ctrlf", "*searchMenu.findAgain.accelerator: Ctrlg", "*searchMenu.findAgain.acceleratorText: [Shift]Ctrl+G", "*searchMenu.findAgainShift.accelerator: Shift Ctrlg", "*searchMenu.findSelection.accelerator: Ctrlh", "*searchMenu.findSelection.acceleratorText: [Shift]Ctrl+H", "*searchMenu.findSelectionShift.accelerator: Shift Ctrlh", "*searchMenu.findIncremental.accelerator: Ctrli", "*searchMenu.findIncrementalShift.accelerator: Shift Ctrli", "*searchMenu.findIncremental.acceleratorText: [Shift]Ctrl+I", "*searchMenu.replace.accelerator: Ctrlr", "*searchMenu.replace.acceleratorText: [Shift]Ctrl+R", "*searchMenu.replaceShift.accelerator: Shift Ctrlr", "*searchMenu.findReplace.accelerator: Ctrlr", "*searchMenu.findReplace.acceleratorText: [Shift]Ctrl+R", "*searchMenu.findReplaceShift.accelerator: Shift Ctrlr", "*searchMenu.replaceFindAgain.accelerator: Ctrlt", "*searchMenu.replaceFindAgain.acceleratorText: [Shift]Ctrl+T", "*searchMenu.replaceFindAgainShift.accelerator: Shift Ctrlt", "*searchMenu.replaceAgain.accelerator: Altt", "*searchMenu.replaceAgain.acceleratorText: [Shift]Alt+T", "*searchMenu.replaceAgainShift.accelerator: Shift Altt", "*searchMenu.gotoLineNumber.accelerator: Ctrll", "*searchMenu.gotoLineNumber.acceleratorText: Ctrl+L", "*searchMenu.gotoSelected.accelerator: Ctrle", "*searchMenu.gotoSelected.acceleratorText: Ctrl+E", "*searchMenu.mark.accelerator: Altm", "*searchMenu.mark.acceleratorText: Alt+M a-z", "*searchMenu.gotoMark.accelerator: Altg", "*searchMenu.gotoMark.acceleratorText: [Shift]Alt+G a-z", "*searchMenu.gotoMarkShift.accelerator: Shift Altg", "*searchMenu.gotoMatching.accelerator: Ctrlm", "*searchMenu.gotoMatching.acceleratorText: [Shift]Ctrl+M", "*searchMenu.gotoMatchingShift.accelerator: Shift Ctrlm", "*searchMenu.findDefinition.accelerator: Ctrld", "*searchMenu.findDefinition.acceleratorText: Ctrl+D", "*searchMenu.showCalltip.accelerator: Ctrlapostrophe", "*searchMenu.showCalltip.acceleratorText: Ctrl+'", "*preferencesMenu.mnemonic: P", "*preferencesMenu.statisticsLine.accelerator: Alta", "*preferencesMenu.statisticsLine.acceleratorText: Alt+A", "*preferencesMenu.overtype.acceleratorText: Insert", "*shellMenu.mnemonic: l", "*shellMenu.filterSelection.accelerator: Altr", "*shellMenu.filterSelection.acceleratorText: Alt+R", "*shellMenu.executeCommand.accelerator: Altx", "*shellMenu.executeCommand.acceleratorText: Alt+X", "*shellMenu.executeCommandLine.accelerator: CtrlKP_Enter", "*shellMenu.executeCommandLine.acceleratorText: Ctrl+KP Enter", "*shellMenu.cancelShellCommand.accelerator: Ctrlperiod", "*shellMenu.cancelShellCommand.acceleratorText: Ctrl+.", "*macroMenu.mnemonic: c", "*macroMenu.learnKeystrokes.accelerator: Altk", "*macroMenu.learnKeystrokes.acceleratorText: Alt+K", "*macroMenu.finishLearn.accelerator: Altk", "*macroMenu.finishLearn.acceleratorText: Alt+K", "*macroMenu.cancelLearn.accelerator: Ctrlperiod", "*macroMenu.cancelLearn.acceleratorText: Ctrl+.", "*macroMenu.replayKeystrokes.accelerator: Ctrlk", "*macroMenu.replayKeystrokes.acceleratorText: Ctrl+K", "*macroMenu.repeat.accelerator: Ctrlcomma", "*macroMenu.repeat.acceleratorText: Ctrl+,", "*windowsMenu.mnemonic: W", "*windowsMenu.splitPane.accelerator: Ctrl2", "*windowsMenu.splitPane.acceleratorText: Ctrl+2", "*windowsMenu.closePane.accelerator: Ctrl1", "*windowsMenu.closePane.acceleratorText: Ctrl+1", "*helpMenu.mnemonic: H", "nedit.help.helpForm.sw.helpText*translations: #override\ Tab:help-focus-buttons()\\n\ Return:help-button-action(\"close\")\\n\ osfCancel:help-button-action(\"close\")\\n\ ~Meta~Ctrl~Shift:\ grab-focus() help-hyperlink()\\n\ ~Meta~Ctrl~Shift:\ help-hyperlink(\"current\", \"process-cancel\", \"extend-end\")\\n\ ~Meta~Ctrl~Shift:\ process-bdrag() help-hyperlink()\\n\ ~Meta~Ctrl~Shift:\ help-hyperlink(\"new\", \"process-cancel\", \"copy-to\")", NULL }; static const char cmdLineHelp[] = #ifndef VMS "Usage: nedit [-read] [-create] [-line n | +n] [-server] [-do command]\n\ [-tags file] [-tabs n] [-wrap] [-nowrap] [-autowrap]\n\ [-autoindent] [-noautoindent] [-autosave] [-noautosave]\n\ [-lm languagemode] [-rows n] [-columns n] [-font font]\n\ [-geometry geometry] [-iconic] [-noiconic] [-svrname name]\n\ [-display [host]:server[.screen] [-xrm resourcestring]\n\ [-import file] [-background color] [-foreground color]\n\ [-tabbed] [-untabbed] [-group] [-V|-version]\n\ [--] [file...]\n"; #else ""; #endif /*VMS*/ int main(int argc, char **argv) { int i, lineNum, nRead, fileSpecified = FALSE, editFlags = CREATE; int gotoLine = False, macroFileRead = False, opts = True; int iconic=False, tabbed = -1, group = 0, isTabbed; char *toDoCommand = NULL, *geometry = NULL, *langMode = NULL; char filename[MAXPATHLEN], pathname[MAXPATHLEN]; XtAppContext context; XrmDatabase prefDB; WindowInfo *window = NULL, *lastFile = NULL; static const char *protectedKeywords[] = {"-iconic", "-icon", "-geometry", "-g", "-rv", "-reverse", "-bd", "-bordercolor", "-borderwidth", "-bw", "-title", NULL}; unsigned char* invalidBindings = NULL; /* Save the command which was used to invoke nedit for restart command */ ArgV0 = argv[0]; /* Set locale for C library, X, and Motif input functions. Reverts to "C" if requested locale not available. */ XtSetLanguageProc(NULL, neditLanguageProc, NULL); /* Initialize X toolkit (does not open display yet) */ XtToolkitInitialize(); context = XtCreateApplicationContext(); /* Set up a warning handler to trap obnoxious Xt grab warnings */ SuppressPassiveGrabWarnings(); #ifdef LESSTIF_VERSION /* Set up a handler to suppress bogus Lesstif warning messages */ XtAppSetWarningHandler(context, bogusWarningFilter); #endif /* Set up default resources if no app-defaults file is found */ XtAppSetFallbackResources(context, fallbackResources); #if XmVersion >= 1002 /* Allow users to change tear off menus with X resources */ XmRepTypeInstallTearOffModelConverter(); #endif #ifdef VMS /* Convert the command line to Unix style (This is not an ideal solution) */ ConvertVMSCommandLine(&argc, &argv); #endif /*VMS*/ #ifdef __EMX__ /* expand wildcards if necessary */ _wildcard(&argc, &argv); #endif /* Read the preferences file and command line into a database */ prefDB = CreateNEditPrefDB(&argc, argv); /* Open the display and read X database and remaining command line args. XtOpenDisplay must be allowed to process some of the resource arguments with its inaccessible internal option table, but others, like -geometry and -iconic are per-window and it should not be allowed to consume them, so we temporarily masked them out. */ maskArgvKeywords(argc, argv, protectedKeywords); TheDisplay = XtOpenDisplay (context, NULL, APP_NAME, APP_CLASS, NULL, 0, &argc, argv); unmaskArgvKeywords(argc, argv, protectedKeywords); if (!TheDisplay) { /* Respond to -V or -version even if there is no display */ for (i = 1; i < argc && strcmp(argv[i], "--"); i++) { if (0 == strcmp(argv[i], "-V") || 0 == strcmp(argv[i], "-version")) { PrintVersion(); exit(EXIT_SUCCESS); } } XtWarning ("NEdit: Can't open display\n"); exit(EXIT_FAILURE); } /* Must be done before creating widgets */ patchResourcesForVisual(); patchResourcesForKDEbug(); /* Initialize global symbols and subroutines used in the macro language */ InitMacroGlobals(); RegisterMacroSubroutines(); /* Store preferences from the command line and .nedit file, and set the appropriate preferences */ RestoreNEditPrefs(prefDB, XtDatabase(TheDisplay)); /* Intercept syntactically invalid virtual key bindings BEFORE we create any shells. */ invalidBindings = sanitizeVirtualKeyBindings(); /* Create a hidden application shell that is the parent of all the main editor windows. Realize it so it the window can act as group leader. */ TheAppShell = CreateShellWithBestVis(APP_NAME, APP_CLASS, applicationShellWidgetClass, TheDisplay, NULL, 0); /* Restore the original bindings ASAP such that other apps are not affected. */ restoreInsaneVirtualKeyBindings(invalidBindings); XtSetMappedWhenManaged(TheAppShell, False); XtRealizeWidget(TheAppShell); #ifndef NO_SESSION_RESTART AttachSessionMgrHandler(TheAppShell); #endif /* More preference stuff */ LoadPrintPreferences(XtDatabase(TheDisplay), APP_NAME, APP_CLASS, True); SetDeleteRemap(GetPrefMapDelete()); SetPointerCenteredDialogs(GetPrefRepositionDialogs()); SetGetEFTextFieldRemoval(!GetPrefStdOpenDialog()); /* Set up action procedures for menu item commands */ InstallMenuActions(context); /* Add Actions for following hyperlinks in the help window */ InstallHelpLinkActions(context); /* Add actions for mouse wheel support in scrolled windows (except text area) */ InstallMouseWheelActions(context); /* Install word delimiters for regular expression matching */ SetREDefaultWordDelimiters(GetPrefDelimiters()); /* Read the nedit dynamic database of files for the Open Previous command (and eventually other information as well) */ ReadNEditDB(); /* Process -import command line argument before others which might open windows (loading preferences doesn't update menu settings, which would then be out of sync with the real preference settings) */ for (i=1; i, -line, -server, and files to edit) not already processed by RestoreNEditPrefs. */ fileSpecified = FALSE; for (i=1; ishell != lastFile->shell) { CleanUpTabBarExposeQueue(lastFile); RaiseDocument(lastFile); } if (!macroFileRead) { ReadMacroInitFile(WindowList); macroFileRead = True; } if (gotoLine) SelectNumberedLine(window, lineNum); if (toDoCommand != NULL) { DoMacro(window, toDoCommand, "-do macro"); toDoCommand = NULL; if (!IsValidWindow(window)) window = NULL; /* window closed by macro */ if (lastFile && !IsValidWindow(lastFile)) lastFile = NULL; /* window closed by macro */ } } /* register last opened file for later use */ if (window) lastFile = window; } else { fprintf(stderr, "nedit: file name too long: %s\n", nameList[j]); } free(nameList[j]); } if (nameList != NULL) free(nameList); #else if (ParseFilename(argv[i], filename, pathname) == 0 ) { /* determine if file is to be openned in new tab, by factoring the options -group, -tabbed & -untabbed */ if (group == 2) { isTabbed = 0; /* start a new window for new group */ group = 1; /* next file will be within group */ } else if (group == 1) { isTabbed = 1; /* new tab for file in group */ } else { /* not in group */ isTabbed = tabbed==-1? GetPrefOpenInTab() : tabbed; } /* Files are opened in background to improve opening speed by defering certain time consuiming task such as syntax highlighting. At the end of the file-opening loop, the last file opened will be raised to restore those deferred items. The current file may also be raised if there're macros to execute on. */ window = EditExistingFile(WindowList, filename, pathname, editFlags, geometry, iconic, langMode, isTabbed, True); fileSpecified = TRUE; if (window) { CleanUpTabBarExposeQueue(window); /* raise the last tab of previous window */ if (lastFile && window->shell != lastFile->shell) { CleanUpTabBarExposeQueue(lastFile); RaiseDocument(lastFile); } if (!macroFileRead) { ReadMacroInitFile(WindowList); macroFileRead = True; } if (gotoLine) SelectNumberedLine(window, lineNum); if (toDoCommand != NULL) { DoMacro(window, toDoCommand, "-do macro"); toDoCommand = NULL; if (!IsValidWindow(window)) window = NULL; /* window closed by macro */ if (lastFile && !IsValidWindow(lastFile)) lastFile = NULL; /* window closed by macro */ } } /* register last opened file for later use */ if (window) lastFile = window; } else { fprintf(stderr, "nedit: file name too long: %s\n", argv[i]); } #endif /*VMS*/ } } #ifdef VMS VMSFileScanDone(); #endif /*VMS*/ /* Raise the last file opened */ if (lastFile) { CleanUpTabBarExposeQueue(lastFile); RaiseDocument(lastFile); } CheckCloseDim(); /* If no file to edit was specified, open a window to edit "Untitled" */ if (!fileSpecified) { EditNewFile(NULL, geometry, iconic, langMode, NULL); ReadMacroInitFile(WindowList); CheckCloseDim(); if (toDoCommand != NULL) DoMacro(WindowList, toDoCommand, "-do macro"); } /* Begin remembering last command invoked for "Repeat" menu item */ AddLastCommandActionHook(context); /* Set up communication port and write ~/.nedit_server_process file */ if (IsServer) InitServerCommunication(); /* Process events. */ if (IsServer) ServerMainLoop(context); else XtAppMainLoop(context); /* Not reached but this keeps some picky compilers happy */ return EXIT_SUCCESS; } static void nextArg(int argc, char **argv, int *argIndex) { if (*argIndex + 1 >= argc) { #ifdef VMS *argv[*argIndex] = '/'; #endif /*VMS*/ fprintf(stderr, "NEdit: %s requires an argument\n%s", argv[*argIndex], cmdLineHelp); exit(EXIT_FAILURE); } (*argIndex)++; } /* ** Return True if -do macro is valid, otherwise write an error on stderr */ static int checkDoMacroArg(const char *macro) { Program *prog; char *errMsg, *stoppedAt, *tMacro; int macroLen; /* Add a terminating newline (which command line users are likely to omit since they are typically invoking a single routine) */ macroLen = strlen(macro); tMacro = XtMalloc(strlen(macro)+2); strncpy(tMacro, macro, macroLen); tMacro[macroLen] = '\n'; tMacro[macroLen+1] = '\0'; /* Do a test parse */ prog = ParseMacro(tMacro, &errMsg, &stoppedAt); if (prog == NULL) { ParseError(NULL, tMacro, stoppedAt, "argument to -do", errMsg); return False; } FreeProgram(prog); return True; } /* ** maskArgvKeywords and unmaskArgvKeywords mangle selected keywords by ** replacing the '-' with a space, for the purpose of hiding them from ** XtOpenDisplay's option processing. Why this silly scheme? XtOpenDisplay ** really needs to see command line arguments, particularly -display, but ** there's no way to change the option processing table it uses, to keep ** it from consuming arguments which are meant to apply per-window, like ** -geometry and -iconic. */ static void maskArgvKeywords(int argc, char **argv, const char **maskArgs) { int i, k; for (i=1; i