changeset 9542:00ee8d8c2e0c v7.4.2051

commit https://github.com/vim/vim/commit/502ae4ba63561c98ac69af26cd9883bfd18d225f Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jul 16 19:50:13 2016 +0200 patch 7.4.2051 Problem: No proper testing of trunc_string(). Solution: Add a unittest for message.c.
author Christian Brabandt <cb@256bit.org>
date Sat, 16 Jul 2016 20:00:05 +0200
parents ece716527680
children 69b7bcb20b05
files src/Makefile src/main.c src/message.c src/message_test.c src/proto/main.pro src/structs.h src/version.c
diffstat 7 files changed, 420 insertions(+), 303 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile
+++ b/src/Makefile
@@ -1558,9 +1558,11 @@ JSON_TEST_SRC = json_test.c
 JSON_TEST_TARGET = json_test$(EXEEXT)
 MEMFILE_TEST_SRC = memfile_test.c
 MEMFILE_TEST_TARGET = memfile_test$(EXEEXT)
-
-UNITTEST_SRC = $(JSON_TEST_SRC) $(MEMFILE_TEST_SRC)
-UNITTEST_TARGETS = $(JSON_TEST_TARGET) $(MEMFILE_TEST_TARGET)
+MESSAGE_TEST_SRC = message_test.c
+MESSAGE_TEST_TARGET = message_test$(EXEEXT)
+
+UNITTEST_SRC = $(JSON_TEST_SRC) $(MEMFILE_TEST_SRC) $(MESSAGE_TEST_SRC)
+UNITTEST_TARGETS = $(JSON_TEST_TARGET) $(MEMFILE_TEST_TARGET) $(MESSAGE_TEST_TARGET)
 
 # All sources, also the ones that are not configured
 ALL_SRC = $(BASIC_SRC) $(ALL_GUI_SRC) $(UNITTEST_SRC) $(EXTRA_SRC)
@@ -1604,7 +1606,6 @@ OBJ_COMMON = \
 	objects/mark.o \
 	objects/memline.o \
 	objects/menu.o \
-	objects/message.o \
 	objects/misc1.o \
 	objects/misc2.o \
 	objects/move.o \
@@ -1642,19 +1643,28 @@ OBJ_COMMON = \
 	$(CHANNEL_OBJ) \
 	$(WSDEBUG_OBJ)
 
+# The files included by tests are not in OBJ_COMMON.
 OBJ = $(OBJ_COMMON) \
 	objects/json.o \
 	objects/main.o \
-	objects/memfile.o
+	objects/memfile.o \
+	objects/message.o
 
 JSON_TEST_OBJ = $(OBJ_COMMON) \
-	objects/json_test.o \
-	objects/memfile.o
+	objects/memfile.o \
+	objects/message.o \
+	objects/json_test.o
 
 MEMFILE_TEST_OBJ = $(OBJ_COMMON) \
 	objects/json.o \
+	objects/message.o \
 	objects/memfile_test.o
 
+MESSAGE_TEST_OBJ = $(OBJ_COMMON) \
+	objects/json.o \
+	objects/memfile.o \
+	objects/message_test.o
+
 PRO_AUTO = \
 	arabic.pro \
 	blowfish.pro \
@@ -1970,6 +1980,9 @@ run_json_test: $(JSON_TEST_TARGET)
 run_memfile_test: $(MEMFILE_TEST_TARGET)
 	./$(MEMFILE_TEST_TARGET)
 
+run_message_test: $(MESSAGE_TEST_TARGET)
+	./$(MESSAGE_TEST_TARGET)
+
 # Run individual OLD style test, assuming that Vim was already compiled.
 test1 \
 	test_autocmd_option \
@@ -2123,6 +2136,13 @@ testclean:
 		MAKE="$(MAKE)" LINK_AS_NEEDED=$(LINK_AS_NEEDED) \
 		sh $(srcdir)/link.sh
 
+$(MESSAGE_TEST_TARGET): auto/config.mk objects $(MESSAGE_TEST_OBJ)
+	$(CCC) version.c -o objects/version.o
+	@LINK="$(PURIFY) $(SHRPENV) $(CClink) $(ALL_LIB_DIRS) $(LDFLAGS) \
+		-o $(MESSAGE_TEST_TARGET) $(MESSAGE_TEST_OBJ) $(ALL_LIBS)" \
+		MAKE="$(MAKE)" LINK_AS_NEEDED=$(LINK_AS_NEEDED) \
+		sh $(srcdir)/link.sh
+
 # install targets
 
 install: $(GUI_INSTALL)
@@ -2941,6 +2961,9 @@ objects/menu.o: menu.c
 objects/message.o: message.c
 	$(CCC) -o $@ message.c
 
+objects/message_test.o: message_test.c
+	$(CCC) -o $@ message_test.c
+
 objects/misc1.o: misc1.c
 	$(CCC) -o $@ misc1.c
 
@@ -3426,6 +3449,10 @@ objects/memfile_test.o: memfile_test.c m
  os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h \
  structs.h regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h \
  ex_cmds.h proto.h globals.h farsi.h arabic.h memfile.c
+objects/message_test.o: message_test.c main.c vim.h auto/config.h feature.h \
+ os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h \
+ structs.h regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h \
+ ex_cmds.h proto.h globals.h farsi.h arabic.h message.c
 objects/hangulin.o: hangulin.c vim.h auto/config.h feature.h os_unix.h \
  auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
  regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h proto.h \
--- a/src/main.c
+++ b/src/main.c
@@ -23,70 +23,6 @@
 # include "iscygpty.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? */
-    int		not_a_term;		/* no warning for missing term? */
-    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)
-# define EXPAND_FILENAMES
-    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 */
@@ -98,15 +34,15 @@ typedef struct
 static int file_owned(char *fname);
 #endif
 static void mainerr(int, char_u *);
+# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+static void init_locale(void);
+# endif
+static void early_arg_scan(mparm_T *parmp);
 #ifndef NO_VIM_MAIN
 static void main_msg(char *s);
 static void usage(void);
 static int get_number_arg(char_u *p, int *idx, int def);
-# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
-static void init_locale(void);
-# endif
 static void parse_command_name(mparm_T *parmp);
-static void early_arg_scan(mparm_T *parmp);
 static void command_line_scan(mparm_T *parmp);
 static void check_tty(mparm_T *parmp);
 static void read_stdin(void);
@@ -231,120 +167,7 @@ main
 #endif
     starttime = time(NULL);
 
-#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
-     *   --windowid
-     */
-    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. */
-    global_alist.id = 0;
-
-    /*
-     * 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
+    common_init(&params);
 
 #ifdef FEAT_CLIENTSERVER
     /*
@@ -1056,6 +879,129 @@ vim_main2(int argc UNUSED, char **argv U
 #endif /* PROTO */
 
 /*
+ * Initialisation shared by main() and some tests.
+ */
+    void
+common_init(mparm_T *params)
+{
+
+#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
+     *   --windowid
+     */
+    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. */
+    global_alist.id = 0;
+
+    /*
+     * 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
+}
+
+/*
  * Main loop: Execute Normal mode commands until exiting Vim.
  * Also used to handle commands in the command-line window, until the window
  * is closed.
@@ -1547,25 +1493,6 @@ getout(int exitval)
     mch_exit(exitval);
 }
 
-#ifndef NO_VIM_MAIN
-/*
- * Get a (optional) count for a Vim argument.
- */
-    static int
-get_number_arg(
-    char_u	*p,	    /* pointer to argument */
-    int		*idx,	    /* index in argument, is incremented */
-    int		def)	    /* default value */
-{
-    if (vim_isdigit(p[*idx]))
-    {
-	def = atoi((char *)&(p[*idx]));
-	while (vim_isdigit(p[*idx]))
-	    *idx = *idx + 1;
-    }
-    return def;
-}
-
 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
 /*
  * Setup to use the current locale (for ctype() and many other things).
@@ -1617,6 +1544,119 @@ init_locale(void)
 #endif
 
 /*
+ * Get the name of the display, before gui_prepare() removes it from
+ * argv[].  Used for the xterm-clipboard display.
+ *
+ * Also find the --server... arguments and --socketid and --windowid
+ */
+    static void
+early_arg_scan(mparm_T *parmp UNUSED)
+{
+#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER) \
+	|| !defined(FEAT_NETBEANS_INTG)
+    int		argc = parmp->argc;
+    char	**argv = parmp->argv;
+    int		i;
+
+    for (i = 1; i < argc; i++)
+    {
+	if (STRCMP(argv[i], "--") == 0)
+	    break;
+# ifdef FEAT_XCLIPBOARD
+	else if (STRICMP(argv[i], "-display") == 0
+#  if defined(FEAT_GUI_GTK)
+		|| STRICMP(argv[i], "--display") == 0
+#  endif
+		)
+	{
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    xterm_display = argv[++i];
+	}
+# endif
+# ifdef FEAT_CLIENTSERVER
+	else if (STRICMP(argv[i], "--servername") == 0)
+	{
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    parmp->serverName_arg = (char_u *)argv[++i];
+	}
+	else if (STRICMP(argv[i], "--serverlist") == 0)
+	    parmp->serverArg = TRUE;
+	else if (STRNICMP(argv[i], "--remote", 8) == 0)
+	{
+	    parmp->serverArg = TRUE;
+#  ifdef FEAT_GUI
+	    if (strstr(argv[i], "-wait") != 0)
+		/* don't fork() when starting the GUI to edit files ourself */
+		gui.dofork = FALSE;
+#  endif
+	}
+# endif
+
+# if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32)
+#  ifdef FEAT_GUI_W32
+	else if (STRICMP(argv[i], "--windowid") == 0)
+#  else
+	else if (STRICMP(argv[i], "--socketid") == 0)
+#  endif
+	{
+	    long_u	id;
+	    int		count;
+
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    if (STRNICMP(argv[i+1], "0x", 2) == 0)
+		count = sscanf(&(argv[i + 1][2]), SCANF_HEX_LONG_U, &id);
+	    else
+		count = sscanf(argv[i + 1], SCANF_DECIMAL_LONG_U, &id);
+	    if (count != 1)
+		mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
+	    else
+#  ifdef FEAT_GUI_W32
+		win_socket_id = id;
+#  else
+		gtk_socket_id = id;
+#  endif
+	    i++;
+	}
+# endif
+# ifdef FEAT_GUI_GTK
+	else if (STRICMP(argv[i], "--echo-wid") == 0)
+	    echo_wid_arg = TRUE;
+# endif
+# ifndef FEAT_NETBEANS_INTG
+	else if (strncmp(argv[i], "-nb", (size_t)3) == 0)
+	{
+	    mch_errmsg(_("'-nb' cannot be used: not enabled at compile time\n"));
+	    mch_exit(2);
+	}
+# endif
+
+    }
+#endif
+}
+
+#ifndef NO_VIM_MAIN
+/*
+ * Get a (optional) count for a Vim argument.
+ */
+    static int
+get_number_arg(
+    char_u	*p,	    /* pointer to argument */
+    int		*idx,	    /* index in argument, is incremented */
+    int		def)	    /* default value */
+{
+    if (vim_isdigit(p[*idx]))
+    {
+	def = atoi((char *)&(p[*idx]));
+	while (vim_isdigit(p[*idx]))
+	    *idx = *idx + 1;
+    }
+    return def;
+}
+
+/*
  * Check for: [r][e][g][vi|vim|view][diff][ex[im]]
  * If the executable name starts with "r" we disable shell commands.
  * If the next character is "e" we run in Easy mode.
@@ -1711,100 +1751,6 @@ parse_command_name(mparm_T *parmp)
 }
 
 /*
- * Get the name of the display, before gui_prepare() removes it from
- * argv[].  Used for the xterm-clipboard display.
- *
- * Also find the --server... arguments and --socketid and --windowid
- */
-    static void
-early_arg_scan(mparm_T *parmp UNUSED)
-{
-#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER) \
-	|| !defined(FEAT_NETBEANS_INTG)
-    int		argc = parmp->argc;
-    char	**argv = parmp->argv;
-    int		i;
-
-    for (i = 1; i < argc; i++)
-    {
-	if (STRCMP(argv[i], "--") == 0)
-	    break;
-# ifdef FEAT_XCLIPBOARD
-	else if (STRICMP(argv[i], "-display") == 0
-#  if defined(FEAT_GUI_GTK)
-		|| STRICMP(argv[i], "--display") == 0
-#  endif
-		)
-	{
-	    if (i == argc - 1)
-		mainerr_arg_missing((char_u *)argv[i]);
-	    xterm_display = argv[++i];
-	}
-# endif
-# ifdef FEAT_CLIENTSERVER
-	else if (STRICMP(argv[i], "--servername") == 0)
-	{
-	    if (i == argc - 1)
-		mainerr_arg_missing((char_u *)argv[i]);
-	    parmp->serverName_arg = (char_u *)argv[++i];
-	}
-	else if (STRICMP(argv[i], "--serverlist") == 0)
-	    parmp->serverArg = TRUE;
-	else if (STRNICMP(argv[i], "--remote", 8) == 0)
-	{
-	    parmp->serverArg = TRUE;
-#  ifdef FEAT_GUI
-	    if (strstr(argv[i], "-wait") != 0)
-		/* don't fork() when starting the GUI to edit files ourself */
-		gui.dofork = FALSE;
-#  endif
-	}
-# endif
-
-# if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32)
-#  ifdef FEAT_GUI_W32
-	else if (STRICMP(argv[i], "--windowid") == 0)
-#  else
-	else if (STRICMP(argv[i], "--socketid") == 0)
-#  endif
-	{
-	    long_u	id;
-	    int		count;
-
-	    if (i == argc - 1)
-		mainerr_arg_missing((char_u *)argv[i]);
-	    if (STRNICMP(argv[i+1], "0x", 2) == 0)
-		count = sscanf(&(argv[i + 1][2]), SCANF_HEX_LONG_U, &id);
-	    else
-		count = sscanf(argv[i + 1], SCANF_DECIMAL_LONG_U, &id);
-	    if (count != 1)
-		mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
-	    else
-#  ifdef FEAT_GUI_W32
-		win_socket_id = id;
-#  else
-		gtk_socket_id = id;
-#  endif
-	    i++;
-	}
-# endif
-# ifdef FEAT_GUI_GTK
-	else if (STRICMP(argv[i], "--echo-wid") == 0)
-	    echo_wid_arg = TRUE;
-# endif
-# ifndef FEAT_NETBEANS_INTG
-	else if (strncmp(argv[i], "-nb", (size_t)3) == 0)
-	{
-	    mch_errmsg(_("'-nb' cannot be used: not enabled at compile time\n"));
-	    mch_exit(2);
-	}
-# endif
-
-    }
-#endif
-}
-
-/*
  * Scan the command line arguments.
  */
     static void
--- a/src/message.c
+++ b/src/message.c
@@ -260,7 +260,7 @@ trunc_string(
 	    return;
 	}
 	n = ptr2cells(s + e);
-	if (len + n >= half)
+	if (len + n > half)
 	    break;
 	len += n;
 	buf[e] = s[e];
new file mode 100644
--- /dev/null
+++ b/src/message_test.c
@@ -0,0 +1,77 @@
+/* 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.
+ */
+
+/*
+ * message_test.c: Unittests for message.c
+ */
+
+#undef NDEBUG
+#include <assert.h>
+
+/* Must include main.c because it contains much more than just main() */
+#define NO_VIM_MAIN
+#include "main.c"
+
+/* This file has to be included because some of the tested functions are
+ * static. */
+#include "message.c"
+
+/*
+ * Test trunc_string().
+ */
+    static void
+test_trunc_string(void)
+{
+    char_u  buf[40];
+
+    /* in place */
+    STRCPY(buf, "text");
+    trunc_string(buf, buf, 20, 40);
+    assert(STRCMP(buf, "text") == 0);
+
+    STRCPY(buf, "a short text");
+    trunc_string(buf, buf, 20, 40);
+    assert(STRCMP(buf, "a short text") == 0);
+
+    STRCPY(buf, "a text tha just fits");
+    trunc_string(buf, buf, 20, 40);
+    assert(STRCMP(buf, "a text tha just fits") == 0);
+
+    STRCPY(buf, "a text that nott fits");
+    trunc_string(buf, buf, 20, 40);
+    assert(STRCMP(buf, "a text t...nott fits") == 0);
+
+    /* copy from string to buf */
+    trunc_string((char_u *)"text", buf, 20, 40);
+    assert(STRCMP(buf, "text") == 0);
+
+    trunc_string((char_u *)"a short text", buf, 20, 40);
+    assert(STRCMP(buf, "a short text") == 0);
+
+    trunc_string((char_u *)"a text tha just fits", buf, 20, 40);
+    assert(STRCMP(buf, "a text tha just fits") == 0);
+
+    trunc_string((char_u *)"a text that nott fits", buf, 20, 40);
+    assert(STRCMP(buf, "a text t...nott fits") == 0);
+}
+
+    int
+main(int argc, char **argv)
+{
+    mparm_T params;
+
+    vim_memset(&params, 0, sizeof(params));
+    params.argc = argc;
+    params.argv = argv;
+    common_init(&params);
+    init_chartab();
+
+    test_trunc_string();
+    return 0;
+}
--- a/src/proto/main.pro
+++ b/src/proto/main.pro
@@ -1,4 +1,5 @@
 /* main.c */
+void common_init(mparm_T *params);
 void main_loop(int cmdwin, int noexmode);
 void getout_preserve_modified(int exitval);
 void getout(int exitval);
--- a/src/structs.h
+++ b/src/structs.h
@@ -3053,3 +3053,67 @@ struct timer_S
     partial_T	*tr_partial;
 #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? */
+    int		not_a_term;		/* no warning for missing term? */
+    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)
+# define EXPAND_FILENAMES
+    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;
--- a/src/version.c
+++ b/src/version.c
@@ -759,6 +759,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2051,
+/**/
     2050,
 /**/
     2049,