📄 main.c
字号:
/* vi:set ts=8 sts=4 sw=4:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
*/
#define EXTERN
#include "vim.h"
#ifdef SPAWNO
# include <spawno.h> /* special MSDOS swapping library */
#endif
static void mainerr __ARGS((int, char_u *));
static void main_msg __ARGS((char *s));
static void usage __ARGS((void));
static int get_number_arg __ARGS((char_u *p, int *idx, int def));
/*
* Type of error message. These must match with errors[] in mainerr().
*/
#define ME_UNKNOWN_OPTION 0
#define ME_TOO_MANY_ARGS 1
#define ME_ARG_MISSING 2
#define ME_GARBAGE 3
#define ME_EXTRA_CMD 4
static void
mainerr(n, str)
int n;
char_u *str;
{
static char *(errors[]) =
{
"Unknown option",
"Too many edit arguments",
"Argument missing after",
"Garbage after option",
"Too many \"+command\" or \"-c command\" arguments",
};
#if defined(UNIX) || defined(__EMX__)
reset_signals(); /* kill us with CTRL-C here, if you like */
#endif
mch_errmsg(longVersion);
mch_errmsg("\n");
mch_errmsg(errors[n]);
if (str != NULL)
{
mch_errmsg(": \"");
mch_errmsg((char *)str);
mch_errmsg("\"");
}
mch_errmsg("\nMore info with: \"vim -h\"\n");
mch_windexit(1);
}
/*
* print a message with three spaces prepended and '\n' appended.
*/
static void
main_msg(s)
char *s;
{
mch_msg(" ");
mch_msg(s);
mch_msg("\n");
}
static void
usage()
{
int i;
static char_u *(use[]) =
{
(char_u *)"[file ..] edit specified file(s)",
(char_u *)"- read from stdin",
(char_u *)"-t tag edit file where tag is defined",
#ifdef QUICKFIX
(char_u *)"-q [errorfile] edit file with first error"
#endif
};
#if defined(UNIX) || defined(__EMX__)
reset_signals(); /* kill us with CTRL-C here, if you like */
#endif
mch_msg(longVersion);
mch_msg("\nusage:");
for (i = 0; ; ++i)
{
mch_msg(" vim [options] ");
mch_msg((char *)use[i]);
if (i == (sizeof(use) / sizeof(char_u *)) - 1)
break;
mch_msg("\n or:");
}
mch_msg("\n\nOptions:\n");
main_msg("--\t\t\tEnd of options");
#ifdef HAVE_OLE
main_msg("-register\t\tRegister this gvim for OLE");
main_msg("-unregister\t\tUnregister gvim for OLE");
#endif
#ifdef USE_GUI
main_msg("-g\t\t\tRun using GUI (like \"gvim\")");
main_msg("-f\t\t\tForeground: Don't fork when starting GUI");
#endif
main_msg("-v\t\t\tVi mode (like \"vi\")");
main_msg("-e\t\t\tEx mode (like \"ex\")");
main_msg("-s\t\t\tSilent (batch) mode (only for \"ex\")");
main_msg("-R\t\t\tReadonly mode (like \"view\")");
main_msg("-Z\t\t\tRestricted mode (like \"rvim\")");
main_msg("-b\t\t\tBinary mode");
#ifdef LISPINDENT
main_msg("-l\t\t\tLisp mode");
#endif
main_msg("-C\t\t\tCompatible with Vi: 'compatible'");
main_msg("-N\t\t\tNot fully Vi compatible: 'nocompatible'");
main_msg("-V[N]\t\tVerbose level");
main_msg("-n\t\t\tNo swap file, use memory only");
main_msg("-r\t\t\tList swap files and exit");
main_msg("-r (with file name)\tRecover crashed session");
main_msg("-L\t\t\tSame as -r");
#ifdef AMIGA
main_msg("-f\t\t\tDon't use newcli to open window");
main_msg("-d <device>\t\tUse <device> for I/O");
#endif
#ifdef RIGHTLEFT
main_msg("-H\t\t\tstart in Hebrew mode");
#endif
#ifdef FKMAP
main_msg("-F\t\t\tstart in Farsi mode");
#endif
main_msg("-T <terminal>\tSet terminal type to <terminal>");
main_msg("-o[N]\t\tOpen N windows (default: one for each file)");
main_msg("+\t\t\tStart at end of file");
main_msg("+<lnum>\t\tStart at line <lnum>");
main_msg("-c <command>\t\tExecute <command> first");
main_msg("-s <scriptin>\tRead commands from script file <scriptin>");
main_msg("-w <scriptout>\tAppend commands to script file <scriptout>");
main_msg("-W <scriptout>\tWrite commands to script file <scriptout>");
main_msg("-u <vimrc>\t\tUse <vimrc> instead of any .vimrc");
#ifdef USE_GUI
main_msg("-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc");
#endif
#ifdef VIMINFO
main_msg("-i <viminfo>\t\tUse <viminfo> instead of .viminfo");
#endif
main_msg("-h\t\t\tprint Help (this message) and exit");
main_msg("--version\t\tprint version information and exit");
#ifdef USE_GUI_X11
# ifdef USE_GUI_MOTIF
mch_msg("\nOptions recognised by gvim (Motif version):\n");
# else
# ifdef USE_GUI_ATHENA
mch_msg("\nOptions recognised by gvim (Athena version):\n");
# endif /* USE_GUI_ATHENA */
# endif /* USE_GUI_MOTIF */
main_msg("-display <display>\tRun vim on <display>");
main_msg("-iconic\t\tStart vim iconified");
# if 0
main_msg("-name <name>\t\tUse resource as if vim was <name>");
mch_msg("\t\t\t (Unimplemented)\n");
# endif
main_msg("-background <color>\tUse <color> for the background (also: -bg)");
main_msg("-foreground <color>\tUse <color> for normal text (also: -fg)");
main_msg("-font <font>\t\tUse <font> for normal text (also: -fn)");
main_msg("-boldfont <font>\tUse <font> for bold text");
main_msg("-italicfont <font>\tUse <font> for italic text");
main_msg("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)");
main_msg("-borderwidth <width>\tUse a border width of <width> (also: -bw)");
main_msg("-scrollbarwidth <width>\tUse a scrollbar width of <width> (also: -sw)");
main_msg("-menuheight <height>\tUse a menu bar height of <height> (also: -mh)");
main_msg("-reverse\t\tUse reverse video (also: -rv)");
main_msg("+reverse\t\tDon't use reverse video (also: +rv)");
main_msg("-xrm <resource>\tSet the specified resource");
#endif /* USE_GUI_X11 */
mch_windexit(1);
}
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
/* Maximum number of commands from + or -c options */
#define MAX_ARG_CMDS 10
#ifndef PROTO /* don't want a prototype for main() */
int
#ifdef VIMDLL
_export
#endif
main(argc, argv)
int argc;
char **argv;
{
char_u *initstr; /* init string from environment */
char_u *term = NULL; /* specified terminal name */
char_u *fname = NULL; /* file name from command line */
char_u *tagname = NULL; /* tag from -t option */
char_u *use_vimrc = NULL; /* vimrc from -u option */
#ifdef QUICKFIX
char_u *use_ef = NULL; /* 'errorfile' from -q option */
#endif
int n_commands = 0; /* no. of commands from + or -c */
char_u *commands[MAX_ARG_CMDS]; /* commands from + or -c option */
int no_swap_file = FALSE; /* "-n" option used */
int c;
int i;
int bin_mode = FALSE; /* -b option used */
int window_count = 1; /* number of windows to use */
int arg_idx = 0; /* index for arg_files[] */
int had_minmin = FALSE; /* found "--" option */
int argv_idx; /* index in argv[n][] */
int want_full_screen = TRUE;
int want_argument; /* option with argument */
#define EDIT_NONE 0 /* no edit type yet */
#define EDIT_FILE 1 /* file name argument[s] given, use arg_files[] */
#define EDIT_STDIN 2 /* read file from stdin */
#define EDIT_TAG 3 /* tag name argument given, use tagname */
#define EDIT_QF 4 /* start in quickfix mode */
int edit_type = EDIT_NONE; /* type of editing to do */
int stdout_isatty; /* is stdout a terminal? */
int input_isatty; /* is active input a terminal? */
OPARG oa; /* operator arguments */
#ifdef RISCOS
/* Turn off all the horrible filename munging in UnixLib. */
__uname_control = __UNAME_NO_PROCESS;
#endif
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
/*
* Default mappings for some often used keys.
* Use the Windows (CUA) keybindings.
*/
static struct initmap
{
char_u *arg;
int mode;
} initmappings[] =
{
# ifdef USE_GUI
{(char_u *)"<C-PageUp> H", NORMAL+VISUAL},
{(char_u *)"<C-PageUp> <C-O>H",INSERT},
{(char_u *)"<C-PageDown> L$", NORMAL+VISUAL},
{(char_u *)"<C-PageDown> <C-O>L<C-O>$", INSERT},
/* paste, copy and cut */
{(char_u *)"<S-Insert> \"*P", NORMAL},
{(char_u *)"<S-Insert> \"-d\"*P", VISUAL},
{(char_u *)"<S-Insert> <C-R>*", INSERT+CMDLINE},
{(char_u *)"<C-Insert> \"*y", VISUAL},
{(char_u *)"<S-Del> \"*d", VISUAL},
{(char_u *)"<C-Del> \"*d", VISUAL},
{(char_u *)"<C-X> \"*d", VISUAL},
/* Missing: CTRL-C (can't be mapped) and CTRL-V (means something) */
# else
{(char_u *)"\316\204 H", NORMAL+VISUAL}, /* CTRL-PageUp is "H" */
{(char_u *)"\316\204 \017H",INSERT}, /* CTRL-PageUp is "^OH"*/
{(char_u *)"\316v L$", NORMAL+VISUAL}, /* CTRL-PageDown is "L$" */
{(char_u *)"\316v \017L\017$", INSERT}, /* CTRL-PageDown ="^OL^O$"*/
{(char_u *)"\316w <C-Home>", NORMAL+VISUAL},
{(char_u *)"\316w <C-Home>", INSERT+CMDLINE},
{(char_u *)"\316u <C-End>", NORMAL+VISUAL},
{(char_u *)"\316u <C-End>", INSERT+CMDLINE},
/* paste, copy and cut */
# ifdef USE_CLIPBOARD
{(char_u *)"\316\324 \"*P", NORMAL}, /* SHIFT-Insert is "*P */
{(char_u *)"\316\324 \"-d\"*P", VISUAL}, /* SHIFT-Insert is "-d"*P */
{(char_u *)"\316\324 \017\"*P", INSERT}, /* SHIFT-Insert is ^O"*P */
{(char_u *)"\316\325 \"*y", VISUAL}, /* CTRL-Insert is "*y */
{(char_u *)"\316\327 \"*d", VISUAL}, /* SHIFT-Del is "*d */
{(char_u *)"\316\330 \"*d", VISUAL}, /* CTRL-Del is "*d */
{(char_u *)"\030 \"-d", VISUAL}, /* CTRL-X is "-d */
# else
{(char_u *)"\316\324 P", NORMAL}, /* SHIFT-Insert is P */
{(char_u *)"\316\324 d\"0P", VISUAL}, /* SHIFT-Insert is d"0P */
{(char_u *)"\316\324 \017P", INSERT}, /* SHIFT-Insert is ^OP */
{(char_u *)"\316\325 y", VISUAL}, /* CTRL-Insert is y */
{(char_u *)"\316\327 d", VISUAL}, /* SHIFT-Del is d */
{(char_u *)"\316\330 d", VISUAL}, /* CTRL-Del is d */
# endif
# endif
};
#endif
#if defined(macintosh)
/*
* Default mappings for some often used keys.
* Use the Standard MacOS binding.
*/
static struct initmap
{
char_u *arg;
int mode;
} initmappings[] =
{
/* paste, copy and cut */
{(char_u *)"<D-v> \"*P", NORMAL},
{(char_u *)"<D-v> \"-d\"*P", VISUAL},
{(char_u *)"<D-v> <C-R>*", INSERT+CMDLINE},
{(char_u *)"<D-c> \"*y", VISUAL},
{(char_u *)"<D-x> \"*d", VISUAL},
{(char_u *)"<Backspace> \"-d", VISUAL},
};
#endif
#ifdef MEM_PROFILE
atexit(vim_mem_profile_dump);
#endif
#ifdef __EMX__
_wildcard(&argc, &argv);
#endif
#ifdef HAVE_LOCALE_H
setlocale(LC_ALL, ""); /* for ctype() and the like */
#endif
#if defined(USE_GUI_WIN32) && defined(HAVE_OLE)
/* Check for special OLE command line parameters */
if (argc == 2 && (argv[1][0] == '-' || argv[1][0] == '/'))
{
/* Register Vim as an OLE Automation server */
if (STRICMP(argv[1] + 1, "register") == 0)
{
RegisterMe();
mch_windexit(0);
}
/* Unregister Vim as an OLE Automation server */
if (STRICMP(argv[1] + 1, "unregister") == 0)
{
UnregisterMe(TRUE);
mch_windexit(0);
}
/* Ignore an -embedding argument. It is only relevant if the
* application wants to treat the case when it is started manually
* differently from the case where it is started via automation (and
* we don't).
*/
if (STRICMP(argv[1] + 1, "embedding") == 0)
argc = 1;
}
{
int bDoRestart = FALSE;
InitOLE(&bDoRestart);
/* automatically exit after registering */
if (bDoRestart)
mch_windexit(0);
}
#endif
#ifdef USE_GUI
gui_prepare(&argc, argv); /* Prepare for possibly starting GUI sometime */
#endif
#ifdef USE_CLIPBOARD
clip_init(FALSE); /* Initialise clipboard stuff */
#endif
/*
* Check if we have an interactive window.
* On the Amiga: If there is no window, we open one with a newcli command
* (needed for :! to * work). mch_check_win() will also handle the -d
* argument.
*/
stdout_isatty = (mch_check_win(argc, argv) != FAIL);
/*
* allocate the first window and buffer. Can't do anything without it
*/
if ((curwin = win_alloc(NULL)) == NULL ||
(curbuf = buflist_new(NULL, NULL, 1L, FALSE)) == NULL)
mch_windexit(0);
curwin->w_buffer = curbuf;
curbuf->b_nwindows = 1; /* there is one window */
win_init(curwin); /* init current window */
init_yank(); /* init yank buffers */
/*
* Allocate space for the generic buffers (needed for set_init_1()).
*/
if ((IObuff = alloc(IOSIZE)) == NULL ||
(NameBuff = alloc(MAXPATHL)) == NULL)
mch_windexit(0);
/*
* Set the default values for the options.
* First find out the home directory, needed to expand "~" in options.
*/
init_homedir(); /* find real value of $HOME */
set_init_1();
/*
* If the executable name starts with "r" we disable shell commands.
* If the next character is "g" we run the GUI version.
* If the next characters are "view" we start in readonly mode.
* If the next characters are "ex" we start in ex mode.
*/
initstr = gettail((char_u *)argv[0]);
if (initstr[0] == 'r')
{
restricted = TRUE;
++initstr;
}
if (initstr[0] == 'g')
{
#ifdef USE_GUI
gui.starting = TRUE;
++initstr;
#else
mch_errmsg((char *)e_nogvim);
mch_windexit(2);
#endif
}
if (STRNCMP(initstr, "view", 4) == 0)
{
readonlymode = TRUE;
curbuf->b_p_ro = TRUE;
p_uc = 10000; /* don't update very often */
}
if (STRNCMP(initstr, "ex", 2) == 0)
{
exmode_active = TRUE;
change_compatible(TRUE); /* set 'compatible' */
}
/*
* On some systems, when we compile with the GUI, we always use it. On Mac
* there is no terminal version, and on Windows we can't figure out how to
* fork one off with :gui.
*/
#ifdef ALWAYS_USE_GUI
gui.starting = TRUE;
#endif
++argv;
--argc;
#ifndef macintosh
/*
* Allocate arg_files[], big enough to hold all potential file name
* arguments.
*/
arg_files = (char_u **)alloc((unsigned)(sizeof(char_u *) * (argc + 1)));
if (arg_files == NULL)
mch_windexit(2);
#else
arg_files = NULL;
#endif
arg_file_count = 0;
/*
* Process the command line arguments.
*/
argv_idx = 1; /* active option letter is argv[0][argv_idx] */
while (argc > 0)
{
/*
* "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
*/
if (argv[0][0] == '+' && !had_minmin)
{
if (n_commands >= MAX_ARG_CMDS)
mainerr(ME_EXTRA_CMD, NULL);
argv_idx = -1; /* skip to next argument */
if (argv[0][1] == NUL)
commands[n_commands++] = (char_u *)"$";
else
commands[n_commands++] = (char_u *)&(argv[0][1]);
}
/*
* Option argument.
*/
else if (argv[0][0] == '-' && !had_minmin)
{
want_argument = FALSE;
c = argv[0][argv_idx++];
switch (c)
{
case NUL: /* "-" read from stdin */
if (edit_type != EDIT_NONE)
mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
edit_type = EDIT_STDIN;
read_cmd_fd = 2; /* read from stderr instead of stdin */
argv_idx = -1; /* skip to next argument */
break;
case '-': /* "--" don't take any more options */
/* "--help" give help message */
/* "--version" give version message */
if (STRCMP(argv[0] + argv_idx, "help") == 0)
usage();
if (STRCMP(argv[0] + argv_idx, "version") == 0)
{
Columns = 80; /* need to init Columns */
do_version((char_u *)"");
mch_windexit(1);
}
if (argv[0][argv_idx])
mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
had_minmin = TRUE;
argv_idx = -1; /* skip to next argument */
break;
case 'b': /* "-b" binary mode */
bin_mode = TRUE; /* postpone to after reading .exrc files */
break;
case 'C': /* "-C" Compatible */
change_compatible(TRUE);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -