📄 nc.c
字号:
static const char CVSID[] = "$Id: nc.c,v 1.34.2.5 2003/11/20 18:37:13 edg Exp $";/******************************************************************************** ** nc.c -- Nirvana Editor client program for nedit server processes ** ** 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. ** ** 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 ** November, 1995 ** ** Written by Mark Edel ** ********************************************************************************/#ifdef HAVE_CONFIG_H#include "../config.h"#endif#include "server_common.h"#include "../util/fileUtils.h"#include "../util/utils.h"#include "../util/prefFile.h"#include "../util/system.h"#include <stdio.h>#include <stdlib.h>#include <limits.h>#include <string.h>#ifdef VMS#include <lib$routines.h>#include descrip#include ssdef#include syidef#include "../util/VMSparam.h"#include "../util/VMSutils.h"#else#ifndef __MVS__#include <sys/param.h>#endif#include <sys/types.h>#include <sys/utsname.h>#include <unistd.h>#include <pwd.h>#include "../util/clearcase.h"#endif /* VMS */#ifdef __EMX__#include <process.h>#endif#include <X11/Intrinsic.h>#include <X11/Xatom.h>#ifdef HAVE_DEBUG_H#include "../debug.h"#endif#define APP_NAME "nc"#define APP_CLASS "NEditClient"#define PROPERTY_CHANGE_TIMEOUT (Preferences.timeOut * 1000) /* milliseconds */#define SERVER_START_TIMEOUT (Preferences.timeOut * 3000) /* milliseconds */#define REQUEST_TIMEOUT (Preferences.timeOut * 1000) /* milliseconds */#define FILE_OPEN_TIMEOUT (Preferences.timeOut * 3000) /* milliseconds */typedef struct{ char* shell; char* serverRequest;} CommandLine;static void timeOutProc(Boolean *timeOutReturn, XtIntervalId *id);static int startServer(const char *message, const char *commandLine);static CommandLine processCommandLine(int argc, char** argv);static void parseCommandLine(int argc, char **arg, CommandLine *cmdLine);static void nextArg(int argc, char **argv, int *argIndex);static void copyCommandLineArg(CommandLine *cmdLine, const char *arg);static void printNcVersion(void);static Boolean findExistingServer(XtAppContext context, Window rootWindow, Atom serverExistsAtom);static void startNewServer(XtAppContext context, Window rootWindow, char* commandLine, Atom serverExistsAtom);static void waitUntilRequestProcessed(XtAppContext context, Window rootWindow, char* commandString, Atom serverRequestAtom);static void waitUntilFilesOpenedOrClosed(XtAppContext context, Window rootWindow);Display *TheDisplay;static Atom currentWaitForAtom;static Atom noAtom = (Atom)(-1);static const char cmdLineHelp[] =#ifdef VMS"";#else"Usage: nc [-read] [-create]\n"" [-line n | +n] [-do command] [-lm languagemode]\n"" [-svrname name] [-svrcmd command]\n"" [-ask] [-noask] [-timeout seconds]\n"" [-geometry geometry | -g geometry] [-icon | -iconic]\n"" [-wait]\n"" [-V | -version]\n"" [-xrm resourcestring] [-display [host]:server[.screen]]\n"" [--] [file...]";#endif /*VMS*//* Structure to hold X Resource values */static struct { int autoStart; char serverCmd[2*MAXPATHLEN]; /* holds executable name + flags */ char serverName[MAXPATHLEN]; int waitForClose; int timeOut;} Preferences;/* Application resources */static PrefDescripRec PrefDescrip[] = { {"autoStart", "AutoStart", PREF_BOOLEAN, "True", &Preferences.autoStart, NULL, True}, {"serverCommand", "ServerCommand", PREF_STRING, "nedit -server", Preferences.serverCmd, (void *)sizeof(Preferences.serverCmd), False}, {"serverName", "serverName", PREF_STRING, "", Preferences.serverName, (void *)sizeof(Preferences.serverName), False}, {"waitForClose", "WaitForClose", PREF_BOOLEAN, "False", &Preferences.waitForClose, NULL, False}, {"timeOut", "TimeOut", PREF_INT, "10", &Preferences.timeOut, NULL, False}};/* Resource related command line options */static XrmOptionDescRec OpTable[] = { {"-ask", ".autoStart", XrmoptionNoArg, (caddr_t)"False"}, {"-noask", ".autoStart", XrmoptionNoArg, (caddr_t)"True"}, {"-svrname", ".serverName", XrmoptionSepArg, (caddr_t)NULL}, {"-svrcmd", ".serverCommand", XrmoptionSepArg, (caddr_t)NULL}, {"-wait", ".waitForClose", XrmoptionNoArg, (caddr_t)"True"}, {"-timeout", ".timeOut", XrmoptionSepArg, (caddr_t)NULL}};/* Struct to hold info about files being opened and edited. */typedef struct _FileListEntry { Atom waitForFileOpenAtom; Atom waitForFileClosedAtom; char* path; struct _FileListEntry *next;} FileListEntry;typedef struct { int waitForOpenCount; int waitForCloseCount; FileListEntry* fileList;} FileListHead;static FileListHead fileListHead;static void setPropertyValue(Atom atom) { XChangeProperty(TheDisplay, RootWindow(TheDisplay, DefaultScreen(TheDisplay)), atom, XA_STRING, 8, PropModeReplace, (unsigned char *)"True", 4);}/* Add another entry to the file entry list, if it doesn't exist yet. */static void addToFileList(const char *path){ FileListEntry *item; /* see if the file already exists in the list */ for (item = fileListHead.fileList; item; item = item->next) { if (!strcmp(item->path, path)) break; } /* Add the atom to the head of the file list if it wasn't found. */ if (item == 0) { item = malloc(sizeof(item[0])); item->waitForFileOpenAtom = None; item->waitForFileClosedAtom = None; item->path = (char*)malloc(strlen(path)+1); strcpy(item->path, path); item->next = fileListHead.fileList; fileListHead.fileList = item; }}/* Creates the properties for the various paths */static void createWaitProperties(){ FileListEntry *item; for (item = fileListHead.fileList; item; item = item->next) { fileListHead.waitForOpenCount++; item->waitForFileOpenAtom = CreateServerFileOpenAtom(Preferences.serverName, item->path); setPropertyValue(item->waitForFileOpenAtom); if (Preferences.waitForClose == True) { fileListHead.waitForCloseCount++; item->waitForFileClosedAtom = CreateServerFileClosedAtom(Preferences.serverName, item->path, False); setPropertyValue(item->waitForFileClosedAtom); } }}int main(int argc, char **argv){ XtAppContext context; Window rootWindow; CommandLine commandLine; Atom serverExistsAtom, serverRequestAtom; XrmDatabase prefDB; Boolean serverExists; /* Initialize toolkit and get an application context */ XtToolkitInitialize(); context = XtCreateApplicationContext(); #ifdef VMS /* Convert the command line to Unix style */ ConvertVMSCommandLine(&argc, &argv);#endif /*VMS*/#ifdef __EMX__ /* expand wildcards if necessary */ _wildcard(&argc, &argv);#endif /* Read the preferences command line into a database (note that we don't support the .nc file anymore) */ prefDB = CreatePreferencesDatabase(NULL, APP_CLASS, OpTable, XtNumber(OpTable), (unsigned *)&argc, argv); /* Process the command line before calling XtOpenDisplay, because the latter consumes certain command line arguments that we still need (-icon, -geometry ...) */ commandLine = processCommandLine(argc, argv); /* Open the display and find the root window */ TheDisplay = XtOpenDisplay (context, NULL, APP_NAME, APP_CLASS, NULL, 0, &argc, argv); if (!TheDisplay) { XtWarning ("nc: Can't open display\n"); exit(EXIT_FAILURE); } rootWindow = RootWindow(TheDisplay, DefaultScreen(TheDisplay)); /* Read the application resources into the Preferences data structure */ RestorePreferences(prefDB, XtDatabase(TheDisplay), APP_NAME, APP_CLASS, PrefDescrip, XtNumber(PrefDescrip)); /* Make sure that the time out unit is at least 1 second and not too large either (overflow!). */ if (Preferences.timeOut < 1) { Preferences.timeOut = 1; } else if (Preferences.timeOut > 1000) { Preferences.timeOut = 1000; } #ifndef VMS /* For Clearcase users who have not set a server name, use the clearcase view name. Clearcase views make files with the same absolute path names but different contents (and therefore can't be edited in the same nedit session). This should have no bad side-effects for non-clearcase users */ if (Preferences.serverName[0] == '\0') { const char* viewTag = GetClearCaseViewTag(); if (viewTag != NULL && strlen(viewTag) < MAXPATHLEN) { strcpy(Preferences.serverName, viewTag); } }#endif /* VMS */ /* Create the wait properties for the various files. */ createWaitProperties(); /* Monitor the properties on the root window */ XSelectInput(TheDisplay, rootWindow, PropertyChangeMask); /* Create the server property atoms on the current DISPLAY. */ CreateServerPropertyAtoms(Preferences.serverName, &serverExistsAtom, &serverRequestAtom); serverExists = findExistingServer(context, rootWindow, serverExistsAtom); if (serverExists == False) { startNewServer(context, rootWindow, commandLine.shell, serverExistsAtom); } waitUntilRequestProcessed(context, rootWindow, commandLine.serverRequest, serverRequestAtom); waitUntilFilesOpenedOrClosed(context, rootWindow); XtCloseDisplay(TheDisplay); XtFree(commandLine.shell); XtFree(commandLine.serverRequest); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -