3841 lines · 98.2 KB · C
RawDownload
/* 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. * See README.txt for an overview of the Vim source code. */ #if defined(MSDOS) || defined(WIN32) || defined(_WIN64)# include "vimio.h"		/* for close() and dup() */#endif #define EXTERN#include "vim.h" #ifdef SPAWNO# include <spawno.h>		/* special MS-DOS swapping library */#endif #ifdef HAVE_FCNTL_H# include <fcntl.h>#endif #ifdef __CYGWIN__# ifndef WIN32#  include <sys/cygwin.h>	/* for cygwin_conv_to_posix_path() */# endif# include <limits.h>#endif /* Maximum number of commands from + or -c arguments. */#define MAX_ARG_CMDS 10 /* values for "window_layout" */#define WIN_HOR	    1	    /* "-o" horizontally split windows */#define	WIN_VER	    2	    /* "-O" vertically split windows */#define	WIN_TABS    3	    /* "-p" windows on tab pages */ /* Struct for various parameters passed between main() and other functions. */typedef struct{    int		argc;    char	**argv;     int		evim_mode;		/* started as "evim" */    char_u	*use_vimrc;		/* vimrc from -u argument */     int		n_commands;		     /* no. of commands from + or -c */    char_u	*commands[MAX_ARG_CMDS];     /* commands from + or -c arg. */    char_u	cmds_tofree[MAX_ARG_CMDS];   /* commands that need free() */    int		n_pre_commands;		     /* no. of commands from --cmd */    char_u	*pre_commands[MAX_ARG_CMDS]; /* commands from --cmd argument */     int		edit_type;		/* type of editing to do */    char_u	*tagname;		/* tag from -t argument */#ifdef FEAT_QUICKFIX    char_u	*use_ef;		/* 'errorfile' from -q argument */#endif     int		want_full_screen;    int		stdout_isatty;		/* is stdout a terminal? */    char_u	*term;			/* specified terminal name */#ifdef FEAT_CRYPT    int		ask_for_key;		/* -x argument */#endif    int		no_swap_file;		/* "-n" argument used */#ifdef FEAT_EVAL    int		use_debug_break_level;#endif#ifdef FEAT_WINDOWS    int		window_count;		/* number of windows to use */    int		window_layout;		/* 0, WIN_HOR, WIN_VER or WIN_TABS */#endif #ifdef FEAT_CLIENTSERVER    int		serverArg;		/* TRUE when argument for a server */    char_u	*serverName_arg;	/* cmdline arg for server name */    char_u	*serverStr;		/* remote server command */    char_u	*serverStrEnc;		/* encoding of serverStr */    char_u	*servername;		/* allocated name for our server */#endif#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)    int		literal;		/* don't expand file names */#endif#ifdef MSWIN    int		full_path;		/* file name argument was full path */#endif#ifdef FEAT_DIFF    int		diff_mode;		/* start with 'diff' set */#endif} mparm_T; /* Values for edit_type. */#define EDIT_NONE   0	    /* no edit type yet */#define EDIT_FILE   1	    /* file name argument[s] given, use argument list */#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 */ #if defined(UNIX) || defined(VMS)static int file_owned __ARGS((char *fname));#endifstatic 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));#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)static void init_locale __ARGS((void));#endifstatic void parse_command_name __ARGS((mparm_T *parmp));static void early_arg_scan __ARGS((mparm_T *parmp));static void command_line_scan __ARGS((mparm_T *parmp));static void check_tty __ARGS((mparm_T *parmp));static void read_stdin __ARGS((void));static void create_windows __ARGS((mparm_T *parmp));#ifdef FEAT_WINDOWSstatic void edit_buffers __ARGS((mparm_T *parmp));#endifstatic void exe_pre_commands __ARGS((mparm_T *parmp));static void exe_commands __ARGS((mparm_T *parmp));static void source_startup_scripts __ARGS((mparm_T *parmp));static void main_start_gui __ARGS((void));#if defined(HAS_SWAP_EXISTS_ACTION)static void check_swap_exists_action __ARGS((void));#endif#ifdef FEAT_CLIENTSERVERstatic void exec_on_server __ARGS((mparm_T *parmp));static void prepare_server __ARGS((mparm_T *parmp));static void cmdsrv_main __ARGS((int *argc, char **argv, char_u *serverName_arg, char_u **serverStr));static char_u *serverMakeName __ARGS((char_u *arg, char *cmd));#endif  #ifdef STARTUPTIMEstatic FILE *time_fd = NULL;#endif /* * Different types of error messages. */static char *(main_errors[]) ={    N_("Unknown option argument"),#define ME_UNKNOWN_OPTION	0    N_("Too many edit arguments"),#define ME_TOO_MANY_ARGS	1    N_("Argument missing after"),#define ME_ARG_MISSING		2    N_("Garbage after option argument"),#define ME_GARBAGE		3    N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"),#define ME_EXTRA_CMD		4    N_("Invalid argument for"),#define ME_INVALID_ARG		5}; #ifndef PROTO	    /* don't want a prototype for main() */    int# ifdef VIMDLL_export# endif# ifdef FEAT_GUI_MSWIN#  ifdef __BORLANDC___cdecl#  endifVimMain# elsemain# endif(argc, argv)    int		argc;    char	**argv;{    char_u	*fname = NULL;		/* file name from command line */    mparm_T	params;			/* various parameters passed between					 * main() and other functions. */     /*     * Do any system-specific initialisations.  These can NOT use IObuff or     * NameBuff.  Thus emsg2() cannot be called!     */    mch_early_init();     /* Many variables are in "params" so that we can pass them to invoked     * functions without a lot of arguments.  "argc" and "argv" are also     * copied, so that they can be changed. */    vim_memset(&params, 0, sizeof(params));    params.argc = argc;    params.argv = argv;    params.want_full_screen = TRUE;#ifdef FEAT_EVAL    params.use_debug_break_level = -1;#endif#ifdef FEAT_WINDOWS    params.window_count = -1;#endif #ifdef FEAT_TCL    vim_tcl_init(params.argv[0]);#endif #ifdef MEM_PROFILE    atexit(vim_mem_profile_dump);#endif #ifdef STARTUPTIME    time_fd = mch_fopen(STARTUPTIME, "a");    TIME_MSG("--- VIM STARTING ---");#endif    starttime = time(NULL); #ifdef __EMX__    _wildcard(&params.argc, &params.argv);#endif #ifdef FEAT_MBYTE    (void)mb_init();	/* init mb_bytelen_tab[] to ones */#endif#ifdef FEAT_EVAL    eval_init();	/* init global variables */#endif #ifdef __QNXNTO__    qnx_init();		/* PhAttach() for clipboard, (and gui) */#endif #ifdef MAC_OS_CLASSIC    /* Prepare for possibly starting GUI sometime */    /* Macintosh needs this before any memory is allocated. */    gui_prepare(&params.argc, params.argv);    TIME_MSG("GUI prepared");#endif     /* Init the table of Normal mode commands. */    init_normal_cmds(); #if defined(HAVE_DATE_TIME) && defined(VMS) && defined(VAXC)    make_version();	/* Construct the long version string. */#endif     /*     * Allocate space for the generic buffers (needed for set_init_1() and     * EMSG2()).     */    if ((IObuff = alloc(IOSIZE)) == NULL	    || (NameBuff = alloc(MAXPATHL)) == NULL)	mch_exit(0);    TIME_MSG("Allocated generic buffers"); #ifdef NBDEBUG    /* Wait a moment for debugging NetBeans.  Must be after allocating     * NameBuff. */    nbdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL");    nbdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20);    TIME_MSG("NetBeans debug wait");#endif #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)    /*     * Setup to use the current locale (for ctype() and many other things).     * NOTE: Translated messages with encodings other than latin1 will not     * work until set_init_1() has been called!     */    init_locale();    TIME_MSG("locale set");#endif #ifdef FEAT_GUI    gui.dofork = TRUE;		    /* default is to use fork() */#endif     /*     * Do a first scan of the arguments in "argv[]":     *   -display or --display     *   --server...     *   --socketid     */    early_arg_scan(&params); #ifdef FEAT_SUN_WORKSHOP    findYourself(params.argv[0]);#endif#if defined(FEAT_GUI) && !defined(MAC_OS_CLASSIC)    /* Prepare for possibly starting GUI sometime */    gui_prepare(&params.argc, params.argv);    TIME_MSG("GUI prepared");#endif #ifdef FEAT_CLIPBOARD    clip_init(FALSE);		/* Initialise clipboard stuff */    TIME_MSG("clipboard setup");#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 or     * -dev argument.     */    params.stdout_isatty = (mch_check_win(params.argc, params.argv) != FAIL);    TIME_MSG("window checked");     /*     * Allocate the first window and buffer.     * Can't do anything without it, exit when it fails.     */    if (win_alloc_first() == FAIL)	mch_exit(0);     init_yank();		/* init yank buffers */     alist_init(&global_alist);	/* Init the argument list to empty. */     /*     * Set the default values for the options.     * NOTE: Non-latin1 translated messages are working only after this,     * because this is where "has_mbyte" will be set, which is used by     * msg_outtrans_len_attr().     * First find out the home directory, needed to expand "~" in options.     */    init_homedir();		/* find real value of $HOME */    set_init_1();    TIME_MSG("inits 1"); #ifdef FEAT_EVAL    set_lang_var();		/* set v:lang and v:ctype */#endif #ifdef FEAT_CLIENTSERVER    /*     * Do the client-server stuff, unless "--servername ''" was used.     * This may exit Vim if the command was sent to the server.     */    exec_on_server(&params);#endif     /*     * Figure out the way to work from the command name argv[0].     * "vimdiff" starts diff mode, "rvim" sets "restricted", etc.     */    parse_command_name(&params);     /*     * Process the command line arguments.  File names are put in the global     * argument list "global_alist".     */    command_line_scan(&params);    TIME_MSG("parsing arguments");     /*     * 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 fork one off with     * :gui.     */#ifdef ALWAYS_USE_GUI    gui.starting = TRUE;#else# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)    /*     * Check if the GUI can be started.  Reset gui.starting if not.     * Don't know about other systems, stay on the safe side and don't check.     */    if (gui.starting && gui_init_check() == FAIL)    {	gui.starting = FALSE; 	/* When running "evim" or "gvim -y" we need the menus, exit if we	 * don't have them. */	if (params.evim_mode)	    mch_exit(1);    }# endif#endif     if (GARGCOUNT > 0)    {#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)	/*	 * Expand wildcards in file names.	 */	if (!params.literal)	{	    /* Temporarily add '(' and ')' to 'isfname'.  These are valid	     * filename characters but are excluded from 'isfname' to make	     * "gf" work on a file name in parenthesis (e.g.: see vim.h). */	    do_cmdline_cmd((char_u *)":set isf+=(,)");	    alist_expand(NULL, 0);	    do_cmdline_cmd((char_u *)":set isf&");	}#endif	fname = alist_name(&GARGLIST[0]);    } #if defined(WIN32) && defined(FEAT_MBYTE)    {	extern void set_alist_count(void); 	/* Remember the number of entries in the argument list.  If it changes	 * we don't react on setting 'encoding'. */	set_alist_count();    }#endif #ifdef MSWIN    if (GARGCOUNT == 1 && params.full_path)    {	/*	 * If there is one filename, fully qualified, we have very probably	 * been invoked from explorer, so change to the file's directory.	 * Hint: to avoid this when typing a command use a forward slash.	 * If the cd fails, it doesn't matter.	 */	(void)vim_chdirfile(fname);    }#endif    TIME_MSG("expanding arguments"); #ifdef FEAT_DIFF    if (params.diff_mode && params.window_count == -1)	params.window_count = 0;	/* open up to 3 windows */#endif     /* Don't redraw until much later. */    ++RedrawingDisabled;     /*     * When listing swap file names, don't do cursor positioning et. al.     */    if (recoverymode && fname == NULL)	params.want_full_screen = FALSE;     /*     * When certain to start the GUI, don't check capabilities of terminal.     * For GTK we can't be sure, but when started from the desktop it doesn't     * make sense to try using a terminal.     */#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)    if (gui.starting# ifdef FEAT_GUI_GTK	    && !isatty(2)# endif	    )	params.want_full_screen = FALSE;#endif #if defined(FEAT_GUI_MAC) && defined(MACOS_X_UNIX)    /* When the GUI is started from Finder, need to display messages in a     * message box.  isatty(2) returns TRUE anyway, thus we need to check the     * name to know we're not started from a terminal. */    if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0))    {	params.want_full_screen = FALSE; 	/* Avoid always using "/" as the current directory.  Note that when	 * started from Finder the arglist will be filled later in	 * HandleODocAE() and "fname" will be NULL. */	if (getcwd((char *)NameBuff, MAXPATHL) != NULL						&& STRCMP(NameBuff, "/") == 0)	{	    if (fname != NULL)		(void)vim_chdirfile(fname);	    else	    {		expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);		vim_chdir(NameBuff);	    }	}    }#endif     /*     * mch_init() sets up the terminal (window) for use.  This must be     * done after resetting full_screen, otherwise it may move the cursor     * (MSDOS).     * Note that we may use mch_exit() before mch_init()!     */    mch_init();    TIME_MSG("shell init"); #ifdef USE_XSMP    /*     * For want of anywhere else to do it, try to connect to xsmp here.     * Fitting it in after gui_mch_init, but before gui_init (via termcapinit).     * Hijacking -X 'no X connection' to also disable XSMP connection as that     * has a similar delay upon failure.     * Only try if SESSION_MANAGER is set to something non-null.     */    if (!x_no_connect)    {	char *p = getenv("SESSION_MANAGER"); 	if (p != NULL && *p != NUL)	{	    xsmp_init();	    TIME_MSG("xsmp init");	}    }#endif 

Lines 1–500 of 3841.