diff --git a/.hgtags b/.hgtags index cd3b16359b..a055c8ada1 100644 --- a/.hgtags +++ b/.hgtags @@ -1572,3 +1572,20 @@ b67d3a44262a97e7b3ae212fcffb36926b5f53f4 v7-3-232 441d364773dc53264b5f26042f8fc6f8b77c8044 v7-3-235 c1733ef5b6e87dde521d0d85a1e5e62259854ac1 v7-3-236 e3bb93df6c34da672244bce5695c1426da139614 v7-3-237 +f2c108f44f415c7cfe92862e791a01cc542ac378 v7-3-238 +0bef86c5c985218a9448fa16d935b913e67af8d5 v7-3-239 +bf283e37792b4b557a2b9081e4fdb0e10acb9655 v7-3-240 +0a650db0265381b540df8ca6bd716c4b2d47dfc9 v7-3-241 +3d96ddbeb3b0003de29b736f63b76675909f133c v7-3-242 +512ddd87f1a817749c8362bd043682a7bbd87014 v7-3-243 +be6b6509636242cd7e6fab9a4b8772e97fc9a0db v7-3-244 +52512eddb876f64399e98d12643233a87c9f2823 v7-3-245 +3f1a4ed36d1b520a1ad5aa6cbf50d68bc8b9c7a5 v7-3-246 +7fe2c092913e84e6717782da1f1a220069eebbe7 v7-3-247 +57a7998e0fa8854a7a8c3946df1d4c9b1ee220e5 v7-3-248 +9f71f5a526aff4f1e0eefe1068d9534aee427afa v7-3-249 +f909f4f0f38c71594266b3595d31ce04d4ebe3ec v7-3-250 +fe6ad3fd85322b394824a5c495a78061a747b074 v7-3-251 +0b4289bcf8364854dd5f94c42d0252504103e5b9 v7-3-252 +c21429d7768cd4b834a086dd47881d01bca74e8c v7-3-253 +1eb805225de7750c03af7b0f7ac2f5dd18d032be v7-3-254 diff --git a/src/INSTALLpc.txt b/src/INSTALLpc.txt index 124bdc3b9d..aeabda6de6 100644 --- a/src/INSTALLpc.txt +++ b/src/INSTALLpc.txt @@ -11,9 +11,9 @@ The file "feature.h" can be edited to match your preferences. You can skip this, then you will get the default behavior as is documented, which should be fine for most people. -With the exception of the last two sections (Windows 3.1 and MS-DOS), -this document assumes that you are building Vim for Win32 -(Windows NT/2000/XP/2003/Vista and Windows 95/98/Me) +With the exception of two sections (Windows 3.1 and MS-DOS), this document +assumes that you are building Vim for Win32 or later. +(Windows 95/98/Me/NT/2000/XP/2003/Vista/7) Contents: @@ -27,6 +27,9 @@ Contents: 8. Windows 3.1 9. MS-DOS +10. Installing after building from sources + + The currently preferred method is using the free Visual C++ Toolkit 2008 |msvc-2008-express|, the produced binary runs on most MS-Windows systems. If you need the executable to run on Windows 98 or ME, use the 2003 one @@ -409,3 +412,59 @@ will work properly! Esp. handling multi-byte file names. If you get all kinds of strange error messages when compiling, try adding changing the file format from "unix" to "dos". + + +10. Installing after building from sources +========================================== + +[provided by Michael Soyka] + +After you've built the Vim binaries as described above, you're ready to +install Vim on your system. However, if you've obtained the Vim sources +using Mercurial or by downloading them as a unix tar file, you must first +create a "vim73" directory. If you instead downloaded the sources as +zip files, you can skip this setup as the zip archives already have the +correct directory structure. + + A. Create a Vim "runtime" subdirectory named "vim73" + ----------------------------------------------------- + If you obtained your Vim sources as zip files, you can skip this step. + Otherwise, continue reading. + + Go to the directory that contains the Vim "src" and "runtime" + directories and create a new subdirectory named "vim73". + + Copy the "runtime" files into "vim73": + copy runtime\* vim73 + + B. Copy the new binaries into the "vim73" directory + ---------------------------------------------------- + Regardless of how you installed the Vim sources, you need to copy the + new binaries you created above into "vim73": + + copy src\*.exe vim73 + copy src\GvimExt\gvimext.dll vim73 + copy src\xxd\xxd.exe vim73 + + C. Move the "vim73" directory into the Vim installation subdirectory + --------------------------------------------------------------------- + Move the "vim73" subdirectory into the subdirectory where you want Vim + to be installed. Typically, this subdirectory will be named "vim". + If you already have a "vim73" subdirectory in "vim", delete it first + by running its unstal.exe program. + + D. Install Vim + --------------- + "cd" to your Vim installation subdirectory "vim\vim73" and run the + "install.exe" program. It will ask you a number of questions about + how you would like to have your Vim setup. Among these are: + - You can tell it to write a "_vimrc" file with your preferences in the + parent directory. + - It can also install an "Edit with Vim" entry in the Windows Explorer + popup menu. + - You can have it create batch files, so that you can run Vim from the + console or in a shell. You can select one of the directories in your + PATH or add the directory to PATH using the Windows Control Panel. + - Create entries for Vim on the desktop and in the Start menu. + +Happy Vimming! diff --git a/src/auto/configure b/src/auto/configure index cf99d852d3..75a6385e13 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -5814,7 +5814,7 @@ __: eof eval "`cd ${PYTHON3_CONFDIR} && make -f "${tmp_mkf}" __ | sed '/ directory /d'`" rm -f -- "${tmp_mkf}" - vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}" + vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags}" vi_cv_path_python3_plibs="${vi_cv_path_python3_plibs} ${python3_BASEMODLIBS} ${python3_LIBS} ${python3_SYSLIBS}" vi_cv_path_python3_plibs=`echo $vi_cv_path_python3_plibs | sed s/-ltermcap//` vi_cv_path_python3_plibs=`echo $vi_cv_path_python3_plibs | sed s/-lffi//` diff --git a/src/configure.in b/src/configure.in index 3e463d3358..098ebe07e0 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1100,7 +1100,7 @@ eof dnl -- delete the lines from make about Entering/Leaving directory eval "`cd ${PYTHON3_CONFDIR} && make -f "${tmp_mkf}" __ | sed '/ directory /d'`" rm -f -- "${tmp_mkf}" - vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}" + vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags}" vi_cv_path_python3_plibs="${vi_cv_path_python3_plibs} ${python3_BASEMODLIBS} ${python3_LIBS} ${python3_SYSLIBS}" dnl remove -ltermcap, it can conflict with an earlier -lncurses vi_cv_path_python3_plibs=`echo $vi_cv_path_python3_plibs | sed s/-ltermcap//` diff --git a/src/eval.c b/src/eval.c index 995182d6d8..76456c6c7c 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3430,6 +3430,9 @@ ex_call(eap) { curwin->w_cursor.lnum = lnum; curwin->w_cursor.col = 0; +#ifdef FEAT_VIRTUALEDIT + curwin->w_cursor.coladd = 0; +#endif } arg = startarg; if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg, @@ -11939,7 +11942,7 @@ f_has(argvars, rettv) #ifdef FEAT_SEARCHPATH "file_in_path", #endif -#if defined(UNIX) && !defined(USE_SYSTEM) +#if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264) "filterpipe", #endif #ifdef FEAT_FIND_ID @@ -14338,7 +14341,7 @@ f_readfile(argvars, rettv) tolist = 0; for ( ; filtd < buflen || readlen <= 0; ++filtd) { - if (buf[filtd] == '\n' || readlen <= 0) + if (readlen <= 0 || buf[filtd] == '\n') { /* In binary mode add an empty list item when the last * non-empty line ends in a '\n'. */ diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 43e861ae83..9542113853 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -1107,7 +1107,7 @@ do_filter(line1, line2, eap, cmd, do_in, do_out) if (do_out) shell_flags |= SHELL_DOOUT; -#if !defined(USE_SYSTEM) && defined(UNIX) +#if (!defined(USE_SYSTEM) && defined(UNIX)) || defined(WIN3264) if (!do_in && do_out && !p_stmp) { /* Use a pipe to fetch stdout of the command, do not use a temp file. */ diff --git a/src/ex_getln.c b/src/ex_getln.c index d509739a1c..24ded0cf26 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -3057,7 +3057,7 @@ cmdline_paste(regname, literally, remcr) int len; /* Locate start of last word in the cmd buffer. */ - for (w = ccline.cmdbuff + ccline.cmdlen; w > ccline.cmdbuff; ) + for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff; ) { #ifdef FEAT_MBYTE if (has_mbyte) @@ -3075,7 +3075,7 @@ cmdline_paste(regname, literally, remcr) --w; } } - len = (int)((ccline.cmdbuff + ccline.cmdlen) - w); + len = (int)((ccline.cmdbuff + ccline.cmdpos) - w); if (p_ic ? STRNICMP(w, arg, len) == 0 : STRNCMP(w, arg, len) == 0) p += len; } @@ -5039,7 +5039,7 @@ ExpandRTDir(pat, num_file, file, dirnames) *num_file = 0; *file = NULL; - pat_len = STRLEN(pat); + pat_len = (int)STRLEN(pat); ga_init2(&ga, (int)sizeof(char *), 10); for (i = 0; dirnames[i] != NULL; ++i) diff --git a/src/gui_w32.c b/src/gui_w32.c index 128869ee12..e4d25704f7 100644 --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -1574,6 +1574,10 @@ gui_mch_init(void) #endif #ifdef FEAT_EVAL +# if _MSC_VER < 1400 +/* HandleToLong() only exists in compilers that can do 64 bit builds */ +# define HandleToLong(h) ((long)(h)) +# endif /* set the v:windowid variable */ set_vim_var_nr(VV_WINDOWID, HandleToLong(s_hwnd)); #endif diff --git a/src/if_py_both.h b/src/if_py_both.h index 07eedb5f31..c7870bc10b 100644 --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -534,7 +534,6 @@ WindowSetattr(PyObject *self, char *name, PyObject *val) { long lnum; long col; - long len; if (!PyArg_Parse(val, "(ll)", &lnum, &col)) return -1; @@ -549,18 +548,15 @@ WindowSetattr(PyObject *self, char *name, PyObject *val) if (VimErrorCheck()) return -1; - /* When column is out of range silently correct it. */ - len = (long)STRLEN(ml_get_buf(this->win->w_buffer, lnum, FALSE)); - if (col > len) - col = len; - this->win->w_cursor.lnum = lnum; this->win->w_cursor.col = col; #ifdef FEAT_VIRTUALEDIT this->win->w_cursor.coladd = 0; #endif - update_screen(VALID); + /* When column is out of range silently correct it. */ + check_cursor_col_win(this->win); + update_screen(VALID); return 0; } else if (strcmp(name, "height") == 0) diff --git a/src/if_python3.c b/src/if_python3.c index b16dfc68ab..023a773e21 100644 --- a/src/if_python3.c +++ b/src/if_python3.c @@ -68,9 +68,16 @@ static void init_structs(void); +/* The "surrogateescape" error handler is new in Python 3.1 */ +#if PY_VERSION_HEX >= 0x030100f0 +# define CODEC_ERROR_HANDLER "surrogateescape" +#else +# define CODEC_ERROR_HANDLER NULL +#endif + #define PyInt Py_ssize_t #define PyString_Check(obj) PyUnicode_Check(obj) -#define PyString_AsBytes(obj) PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL); +#define PyString_AsBytes(obj) PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, CODEC_ERROR_HANDLER); #define PyString_FreeBytes(obj) Py_XDECREF(bytes) #define PyString_AsString(obj) PyBytes_AsString(obj) #define PyString_Size(obj) PyBytes_GET_SIZE(bytes) @@ -661,8 +668,9 @@ DoPy3Command(exarg_T *eap, const char *cmd) /* PyRun_SimpleString expects a UTF-8 string. Wrong encoding may cause * SyntaxError (unicode error). */ - cmdstr = PyUnicode_Decode(cmd, strlen(cmd), (char *)ENC_OPT, NULL); - cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", NULL); + cmdstr = PyUnicode_Decode(cmd, strlen(cmd), + (char *)ENC_OPT, CODEC_ERROR_HANDLER); + cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", CODEC_ERROR_HANDLER); Py_XDECREF(cmdstr); PyRun_SimpleString(PyBytes_AsString(cmdbytes)); Py_XDECREF(cmdbytes); @@ -1463,7 +1471,7 @@ LineToString(const char *str) } *p = '\0'; - result = PyUnicode_Decode(tmp, len, (char *)ENC_OPT, NULL); + result = PyUnicode_Decode(tmp, len, (char *)ENC_OPT, CODEC_ERROR_HANDLER); vim_free(tmp); return result; diff --git a/src/mbyte.c b/src/mbyte.c index c10ca442c5..fb1846a09b 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -132,6 +132,7 @@ static int utf_ptr2cells_len __ARGS((char_u *p, int size)); static int dbcs_char2cells __ARGS((int c)); static int dbcs_ptr2cells_len __ARGS((char_u *p, int size)); static int dbcs_ptr2char __ARGS((char_u *p)); +static int utf_safe_read_char_adv __ARGS((char_u **s, size_t *n)); /* * Lookup table to quickly get the length in bytes of a UTF-8 character from @@ -1700,6 +1701,66 @@ utf_ptr2char(p) return p[0]; } +/* + * Convert a UTF-8 byte sequence to a wide character. + * String is assumed to be terminated by NUL or after "n" bytes, whichever + * comes first. + * The function is safe in the sense that it never accesses memory beyond the + * first "n" bytes of "s". + * + * On success, returns decoded codepoint, advances "s" to the beginning of + * next character and decreases "n" accordingly. + * + * If end of string was reached, returns 0 and, if "n" > 0, advances "s" past + * NUL byte. + * + * If byte sequence is illegal or incomplete, returns -1 and does not advance + * "s". + */ + static int +utf_safe_read_char_adv(s, n) + char_u **s; + size_t *n; +{ + int c, k; + + if (*n == 0) /* end of buffer */ + return 0; + + k = utf8len_tab_zero[**s]; + + if (k == 1) + { + /* ASCII character or NUL */ + (*n)--; + return *(*s)++; + } + + if ((size_t)k <= *n) + { + /* We have a multibyte sequence and it isn't truncated by buffer + * limits so utf_ptr2char() is safe to use. Or the first byte is + * illegal (k=0), and it's also safe to use utf_ptr2char(). */ + c = utf_ptr2char(*s); + + /* On failure, utf_ptr2char() returns the first byte, so here we + * check equality with the first byte. The only non-ASCII character + * which equals the first byte of its own UTF-8 representation is + * U+00C3 (UTF-8: 0xC3 0x83), so need to check that special case too. + * It's safe even if n=1, else we would have k=2 > n. */ + if (c != (int)(**s) || (c == 0xC3 && (*s)[1] == 0x83)) + { + /* byte sequence was successfully decoded */ + *s += k; + *n -= k; + return c; + } + } + + /* byte sequence is incomplete or illegal */ + return -1; +} + /* * Get character at **pp and advance *pp to the next character. * Note: composing characters are skipped! @@ -2667,7 +2728,8 @@ static convertStruct foldCase[] = {0x10400,0x10427,1,40} }; -static int utf_convert(int a, convertStruct table[], int tableSize); +static int utf_convert __ARGS((int a, convertStruct table[], int tableSize)); +static int utf_strnicmp __ARGS((char_u *s1, char_u *s2, size_t n1, size_t n2)); /* * Generic conversion function for case operations. @@ -3079,6 +3141,80 @@ utf_isupper(a) return (utf_tolower(a) != a); } + static int +utf_strnicmp(s1, s2, n1, n2) + char_u *s1, *s2; + size_t n1, n2; +{ + int c1, c2, cdiff; + char_u buffer[6]; + + for (;;) + { + c1 = utf_safe_read_char_adv(&s1, &n1); + c2 = utf_safe_read_char_adv(&s2, &n2); + + if (c1 <= 0 || c2 <= 0) + break; + + if (c1 == c2) + continue; + + cdiff = utf_fold(c1) - utf_fold(c2); + if (cdiff != 0) + return cdiff; + } + + /* some string ended or has an incomplete/illegal character sequence */ + + if (c1 == 0 || c2 == 0) + { + /* some string ended. shorter string is smaller */ + if (c1 == 0 && c2 == 0) + return 0; + return c1 == 0 ? -1 : 1; + } + + /* Continue with bytewise comparison to produce some result that + * would make comparison operations involving this function transitive. + * + * If only one string had an error, comparison should be made with + * folded version of the other string. In this case it is enough + * to fold just one character to determine the result of comparison. */ + + if (c1 != -1 && c2 == -1) + { + n1 = utf_char2bytes(utf_fold(c1), buffer); + s1 = buffer; + } + else if (c2 != -1 && c1 == -1) + { + n2 = utf_char2bytes(utf_fold(c2), buffer); + s2 = buffer; + } + + while (n1 > 0 && n2 > 0 && *s1 != NUL && *s2 != NUL) + { + cdiff = (int)(*s1) - (int)(*s2); + if (cdiff != 0) + return cdiff; + + s1++; + s2++; + n1--; + n2--; + } + + if (n1 > 0 && *s1 == NUL) + n1 = 0; + if (n2 > 0 && *s2 == NUL) + n2 = 0; + + if (n1 == 0 && n2 == 0) + return 0; + return n1 == 0 ? -1 : 1; +} + /* * Version of strnicmp() that handles multi-byte characters. * Needed for Big5, Sjift-JIS and UTF-8 encoding. Other DBCS encodings can @@ -3092,49 +3228,21 @@ mb_strnicmp(s1, s2, nn) char_u *s1, *s2; size_t nn; { - int i, j, l; + int i, l; int cdiff; - int incomplete = FALSE; int n = (int)nn; - for (i = 0; i < n; i += l) + if (enc_utf8) { - if (s1[i] == NUL && s2[i] == NUL) /* both strings end */ - return 0; - if (enc_utf8) - { - l = utf_byte2len(s1[i]); - if (l > n - i) - { - l = n - i; /* incomplete character */ - incomplete = TRUE; - } - /* Check directly first, it's faster. */ - for (j = 0; j < l; ++j) - { - if (s1[i + j] != s2[i + j]) - break; - if (s1[i + j] == 0) - /* Both stings have the same bytes but are incomplete or - * have illegal bytes, accept them as equal. */ - l = j; - } - if (j < l) - { - /* If one of the two characters is incomplete return -1. */ - if (incomplete || i + utf_byte2len(s2[i]) > n) - return -1; - /* Don't case-fold illegal bytes or truncated characters. */ - if (utf_ptr2len(s1 + i) < l || utf_ptr2len(s2 + i) < l) - return -1; - cdiff = utf_fold(utf_ptr2char(s1 + i)) - - utf_fold(utf_ptr2char(s2 + i)); - if (cdiff != 0) - return cdiff; - } - } - else + return utf_strnicmp(s1, s2, nn, nn); + } + else + { + for (i = 0; i < n; i += l) { + if (s1[i] == NUL && s2[i] == NUL) /* both strings end */ + return 0; + l = (*mb_ptr2len)(s1 + i); if (l <= 1) { @@ -3563,7 +3671,7 @@ dbcs_screen_tail_off(base, p) void mb_adjust_cursor() { - mb_adjustpos(&curwin->w_cursor); + mb_adjustpos(curbuf, &curwin->w_cursor); } /* @@ -3571,7 +3679,8 @@ mb_adjust_cursor() * If it points to a tail byte it's moved backwards to the head byte. */ void -mb_adjustpos(lp) +mb_adjustpos(buf, lp) + buf_T *buf; pos_T *lp; { char_u *p; @@ -3582,7 +3691,7 @@ mb_adjustpos(lp) #endif ) { - p = ml_get(lp->lnum); + p = ml_get_buf(buf, lp->lnum, FALSE); lp->col -= (*mb_head_off)(p, p + lp->col); #ifdef FEAT_VIRTUALEDIT /* Reset "coladd" when the cursor would be on the right half of a diff --git a/src/misc1.c b/src/misc1.c index 79515a1f10..e55bb3694b 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -7951,8 +7951,7 @@ term_again: * If we're at the end of a block, skip to the start of * that block. */ - curwin->w_cursor.col = 0; - if (*cin_skipcomment(l) == '}' + if (find_last_paren(l, '{', '}') && (trypos = find_start_brace(ind_maxcomment)) != NULL) /* XXX */ { diff --git a/src/misc2.c b/src/misc2.c index af500261ee..54b055b991 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -333,7 +333,7 @@ coladvance2(pos, addspaces, finetune, wcol) #ifdef FEAT_MBYTE /* prevent from moving onto a trail byte */ if (has_mbyte) - mb_adjustpos(pos); + mb_adjustpos(curbuf, pos); #endif if (col < wcol) @@ -543,17 +543,27 @@ check_cursor_lnum() */ void check_cursor_col() +{ + check_cursor_col_win(curwin); +} + +/* + * Make sure win->w_cursor.col is valid. + */ + void +check_cursor_col_win(win) + win_T *win; { colnr_T len; #ifdef FEAT_VIRTUALEDIT - colnr_T oldcol = curwin->w_cursor.col; - colnr_T oldcoladd = curwin->w_cursor.col + curwin->w_cursor.coladd; + colnr_T oldcol = win->w_cursor.col; + colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd; #endif - len = (colnr_T)STRLEN(ml_get_curline()); + len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, FALSE)); if (len == 0) - curwin->w_cursor.col = 0; - else if (curwin->w_cursor.col >= len) + win->w_cursor.col = 0; + else if (win->w_cursor.col >= len) { /* Allow cursor past end-of-line when: * - in Insert mode or restarting Insert mode @@ -567,33 +577,33 @@ check_cursor_col() || (ve_flags & VE_ONEMORE) #endif || virtual_active()) - curwin->w_cursor.col = len; + win->w_cursor.col = len; else { - curwin->w_cursor.col = len - 1; + win->w_cursor.col = len - 1; #ifdef FEAT_MBYTE - /* prevent cursor from moving on the trail byte */ + /* Move the cursor to the head byte. */ if (has_mbyte) - mb_adjust_cursor(); + mb_adjustpos(win->w_buffer, &win->w_cursor); #endif } } - else if (curwin->w_cursor.col < 0) - curwin->w_cursor.col = 0; + else if (win->w_cursor.col < 0) + win->w_cursor.col = 0; #ifdef FEAT_VIRTUALEDIT /* If virtual editing is on, we can leave the cursor on the old position, * only we must set it to virtual. But don't do it when at the end of the * line. */ if (oldcol == MAXCOL) - curwin->w_cursor.coladd = 0; + win->w_cursor.coladd = 0; else if (ve_flags == VE_ALL) { - if (oldcoladd > curwin->w_cursor.col) - curwin->w_cursor.coladd = oldcoladd - curwin->w_cursor.col; + if (oldcoladd > win->w_cursor.col) + win->w_cursor.coladd = oldcoladd - win->w_cursor.col; else /* avoid weird number when there is a miscalculation or overflow */ - curwin->w_cursor.coladd = 0; + win->w_cursor.coladd = 0; } #endif } @@ -2136,6 +2146,25 @@ ga_append(gap, c) } } +#if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264) +/* + * Append the text in "gap" below the cursor line and clear "gap". + */ + void +append_ga_line(gap) + garray_T *gap; +{ + /* Remove trailing CR. */ + if (gap->ga_len > 0 + && !curbuf->b_p_bin + && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) + --gap->ga_len; + ga_append(gap, NUL); + ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); + gap->ga_len = 0; +} +#endif + /************************************************************************ * functions that use lookup tables for various things, generally to do with * special key codes. @@ -3224,7 +3253,7 @@ get_real_state() #if defined(FEAT_MBYTE) || defined(PROTO) /* * Return TRUE if "p" points to just after a path separator. - * Take care of multi-byte characters. + * Takes care of multi-byte characters. * "b" must point to the start of the file name */ int @@ -3232,7 +3261,7 @@ after_pathsep(b, p) char_u *b; char_u *p; { - return vim_ispathsep(p[-1]) + return p > b && vim_ispathsep(p[-1]) && (!has_mbyte || (*mb_head_off)(b, p - 1) == 0); } #endif diff --git a/src/normal.c b/src/normal.c index 89faddc228..25e7ce457d 100644 --- a/src/normal.c +++ b/src/normal.c @@ -1795,17 +1795,25 @@ do_pending_operator(cap, old_col, gui_yank) { oap->inclusive = FALSE; /* Try to include the newline, unless it's an operator - * that works on lines only */ - if (*p_sel != 'o' - && !op_on_lines(oap->op_type) - && oap->end.lnum < curbuf->b_ml.ml_line_count) + * that works on lines only. */ + if (*p_sel != 'o' && !op_on_lines(oap->op_type)) { - ++oap->end.lnum; - oap->end.col = 0; + if (oap->end.lnum < curbuf->b_ml.ml_line_count) + { + ++oap->end.lnum; + oap->end.col = 0; # ifdef FEAT_VIRTUALEDIT - oap->end.coladd = 0; + oap->end.coladd = 0; # endif - ++oap->line_count; + ++oap->line_count; + } + else + { + /* Cannot move below the last line, make the op + * inclusive to tell the operation to include the + * line break. */ + oap->inclusive = TRUE; + } } } } @@ -8808,7 +8816,7 @@ unadjust_for_sel() { --pp->col; #ifdef FEAT_MBYTE - mb_adjustpos(pp); + mb_adjustpos(curbuf, pp); #endif } else if (pp->lnum > 1) diff --git a/src/ops.c b/src/ops.c index 8c235220e5..bdc53de33b 100644 --- a/src/ops.c +++ b/src/ops.c @@ -1650,7 +1650,9 @@ op_delete(oap) && oap->line_count > 1 && oap->op_type == OP_DELETE) { - ptr = ml_get(oap->end.lnum) + oap->end.col + oap->inclusive; + ptr = ml_get(oap->end.lnum) + oap->end.col; + if (*ptr != NUL) + ptr += oap->inclusive; ptr = skipwhite(ptr); if (*ptr == NUL && inindent(0)) oap->motion_type = MLINE; @@ -1920,11 +1922,20 @@ op_delete(oap) curwin->w_cursor.coladd = 0; } #endif - (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE + if (oap->inclusive && oap->end.lnum == curbuf->b_ml.ml_line_count + && n > (int)STRLEN(ml_get(oap->end.lnum))) + { + /* Special case: gH deletes the last line. */ + del_lines(1L, FALSE); + } + else + { + (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE #ifdef FEAT_VISUAL && !oap->is_VIsual #endif ); + } } else /* delete characters between lines */ { @@ -1941,17 +1952,29 @@ op_delete(oap) ++curwin->w_cursor.lnum; del_lines((long)(oap->line_count - 2), FALSE); - /* delete from start of line until op_end */ - curwin->w_cursor.col = 0; - (void)del_bytes((long)(oap->end.col + 1 - !oap->inclusive), - !virtual_op, oap->op_type == OP_DELETE + n = (oap->end.col + 1 - !oap->inclusive); + if (oap->inclusive && oap->end.lnum == curbuf->b_ml.ml_line_count + && n > (int)STRLEN(ml_get(oap->end.lnum))) + { + /* Special case: gH deletes the last line. */ + del_lines(1L, FALSE); + curwin->w_cursor = curpos; /* restore curwin->w_cursor */ + if (curwin->w_cursor.lnum > 1) + --curwin->w_cursor.lnum; + } + else + { + /* delete from start of line until op_end */ + curwin->w_cursor.col = 0; + (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE #ifdef FEAT_VISUAL && !oap->is_VIsual #endif ); - curwin->w_cursor = curpos; /* restore curwin->w_cursor */ - - (void)do_join(2, FALSE, FALSE); + curwin->w_cursor = curpos; /* restore curwin->w_cursor */ + } + if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) + (void)do_join(2, FALSE, FALSE); } } diff --git a/src/os_unix.c b/src/os_unix.c index 81dcce9b6b..25b000cab1 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3666,27 +3666,6 @@ mch_new_shellsize() /* Nothing to do. */ } -#ifndef USE_SYSTEM -static void append_ga_line __ARGS((garray_T *gap)); - -/* - * Append the text in "gap" below the cursor line and clear "gap". - */ - static void -append_ga_line(gap) - garray_T *gap; -{ - /* Remove trailing CR. */ - if (gap->ga_len > 0 - && !curbuf->b_p_bin - && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) - --gap->ga_len; - ga_append(gap, NUL); - ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); - gap->ga_len = 0; -} -#endif - int mch_call_shell(cmd, options) char_u *cmd; diff --git a/src/os_win32.c b/src/os_win32.c index d4ef93988b..88ead6fd63 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -417,6 +417,11 @@ static PSNSECINFO pSetNamedSecurityInfo; static PGNSECINFO pGetNamedSecurityInfo; #endif +typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD); + +static BOOL allowPiping = FALSE; +static PSETHANDLEINFORMATION pSetHandleInformation; + /* * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or * VER_PLATFORM_WIN32_WINDOWS (Win95). @@ -467,6 +472,18 @@ PlatformId(void) } } #endif + /* + * If we are on windows NT, try to load the pipe functions, only + * available from Win2K. + */ + if (g_PlatformId == VER_PLATFORM_WIN32_NT) + { + HANDLE kernel32 = GetModuleHandle("kernel32"); + pSetHandleInformation = (PSETHANDLEINFORMATION)GetProcAddress( + kernel32, "SetHandleInformation"); + + allowPiping = pSetHandleInformation != NULL; + } done = TRUE; } } @@ -1635,7 +1652,7 @@ executable_exists(char *name) } #if ((defined(__MINGW32__) || defined (__CYGWIN32__)) && \ - __MSVCRT_VERSION__ >= 0x800) || (defined(_MSC_VER) && _MSC_VER >= 1400) + __MSVCRT_VERSION__ >= 0x800) || (defined(_MSC_VER) && _MSC_VER >= 1400) /* * Bad parameter handler. * @@ -3210,7 +3227,7 @@ mch_set_winsize_now(void) * 4. Prompt the user to press a key to close the console window */ static int -mch_system(char *cmd, int options) +mch_system_classic(char *cmd, int options) { STARTUPINFO si; PROCESS_INFORMATION pi; @@ -3315,6 +3332,498 @@ mch_system(char *cmd, int options) return ret; } + +/* + * Thread launched by the gui to send the current buffer data to the + * process. This way avoid to hang up vim totally if the children + * process take a long time to process the lines. + */ + static DWORD WINAPI +sub_process_writer(LPVOID param) +{ + HANDLE g_hChildStd_IN_Wr = param; + linenr_T lnum = curbuf->b_op_start.lnum; + DWORD len = 0; + DWORD l; + char_u *lp = ml_get(lnum); + char_u *s; + int written = 0; + + for (;;) + { + l = (DWORD)STRLEN(lp + written); + if (l == 0) + len = 0; + else if (lp[written] == NL) + { + /* NL -> NUL translation */ + WriteFile(g_hChildStd_IN_Wr, "", 1, &len, NULL); + } + else + { + s = vim_strchr(lp + written, NL); + WriteFile(g_hChildStd_IN_Wr, (char *)lp + written, + s == NULL ? l : (DWORD)(s - (lp + written)), + &len, NULL); + } + if (len == (int)l) + { + /* Finished a line, add a NL, unless this line should not have + * one. */ + if (lnum != curbuf->b_op_end.lnum + || !curbuf->b_p_bin + || (lnum != curbuf->b_no_eol_lnum + && (lnum != curbuf->b_ml.ml_line_count + || curbuf->b_p_eol))) + { + WriteFile(g_hChildStd_IN_Wr, "\n", 1, &ignored, NULL); + } + + ++lnum; + if (lnum > curbuf->b_op_end.lnum) + break; + + lp = ml_get(lnum); + written = 0; + } + else if (len > 0) + written += len; + } + + /* finished all the lines, close pipe */ + CloseHandle(g_hChildStd_IN_Wr); + ExitThread(0); +} + + +# define BUFLEN 100 /* length for buffer, stolen from unix version */ + +/* + * This function read from the children's stdout and write the + * data on screen or in the buffer accordingly. + */ + static void +dump_pipe(int options, + HANDLE g_hChildStd_OUT_Rd, + garray_T *ga, + char_u buffer[], + DWORD *buffer_off) +{ + DWORD availableBytes = 0; + DWORD i; + int c; + char_u *p; + int ret; + DWORD len; + DWORD toRead; + int repeatCount; + + /* we query the pipe to see if there is any data to read + * to avoid to perform a blocking read */ + ret = PeekNamedPipe(g_hChildStd_OUT_Rd, /* pipe to query */ + NULL, /* optional buffer */ + 0, /* buffe size */ + NULL, /* number of read bytes */ + &availableBytes, /* available bytes total */ + NULL); /* byteLeft */ + + repeatCount = 0; + /* We got real data in the pipe, read it */ + while (ret != 0 && availableBytes > 0 && availableBytes > 0) + { + repeatCount++; + toRead = +# ifdef FEAT_MBYTE + (DWORD)(BUFLEN - *buffer_off); +# else + (DWORD)BUFLEN; +# endif + toRead = availableBytes < toRead ? availableBytes : toRead; + ReadFile(g_hChildStd_OUT_Rd, buffer +# ifdef FEAT_MBYTE + + *buffer_off, toRead +# else + , toRead +# endif + , &len, NULL); + + /* If we haven't read anything, there is a problem */ + if (len == 0) + break; + + availableBytes -= len; + + if (options & SHELL_READ) + { + /* Do NUL -> NL translation, append NL separated + * lines to the current buffer. */ + for (i = 0; i < len; ++i) + { + if (buffer[i] == NL) + append_ga_line(ga); + else if (buffer[i] == NUL) + ga_append(ga, NL); + else + ga_append(ga, buffer[i]); + } + } +# ifdef FEAT_MBYTE + else if (has_mbyte) + { + int l; + + len += *buffer_off; + buffer[len] = NUL; + + /* Check if the last character in buffer[] is + * incomplete, keep these bytes for the next + * round. */ + for (p = buffer; p < buffer + len; p += l) + { + l = mb_cptr2len(p); + if (l == 0) + l = 1; /* NUL byte? */ + else if (MB_BYTE2LEN(*p) != l) + break; + } + if (p == buffer) /* no complete character */ + { + /* avoid getting stuck at an illegal byte */ + if (len >= 12) + ++p; + else + { + *buffer_off = len; + return; + } + } + c = *p; + *p = NUL; + msg_puts(buffer); + if (p < buffer + len) + { + *p = c; + *buffer_off = (DWORD)((buffer + len) - p); + mch_memmove(buffer, p, *buffer_off); + return; + } + *buffer_off = 0; + } +# endif /* FEAT_MBYTE */ + else + { + buffer[len] = NUL; + msg_puts(buffer); + } + + windgoto(msg_row, msg_col); + cursor_on(); + out_flush(); + } +} + +/* + * Version of system to use for windows NT > 5.0 (Win2K), use pipe + * for communication and doesn't open any new window. + */ + static int +mch_system_piped(char *cmd, int options) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD ret = 0; + + HANDLE g_hChildStd_IN_Rd = NULL; + HANDLE g_hChildStd_IN_Wr = NULL; + HANDLE g_hChildStd_OUT_Rd = NULL; + HANDLE g_hChildStd_OUT_Wr = NULL; + + char_u buffer[BUFLEN + 1]; /* reading buffer + size */ + DWORD len; + + /* buffer used to receive keys */ + char_u ta_buf[BUFLEN + 1]; /* TypeAHead */ + int ta_len = 0; /* valid bytes in ta_buf[] */ + + DWORD i; + int c; + int noread_cnt = 0; + garray_T ga; + int delay = 1; +# ifdef FEAT_MBYTE + DWORD buffer_off = 0; /* valid bytes in buffer[] */ +# endif + + SECURITY_ATTRIBUTES saAttr; + + /* Set the bInheritHandle flag so pipe handles are inherited. */ + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) + /* Ensure the read handle to the pipe for STDOUT is not inherited. */ + || ! pSetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) + /* Create a pipe for the child process's STDIN. */ + || ! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0) + /* Ensure the write handle to the pipe for STDIN is not inherited. */ + || ! pSetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) + { + CloseHandle(g_hChildStd_IN_Rd); + CloseHandle(g_hChildStd_IN_Wr); + CloseHandle(g_hChildStd_OUT_Rd); + CloseHandle(g_hChildStd_OUT_Wr); + MSG_PUTS(_("\nCannot create pipes\n")); + } + + si.cb = sizeof(si); + si.lpReserved = NULL; + si.lpDesktop = NULL; + si.lpTitle = NULL; + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + + /* set-up our file redirection */ + si.hStdError = g_hChildStd_OUT_Wr; + si.hStdOutput = g_hChildStd_OUT_Wr; + si.hStdInput = g_hChildStd_IN_Rd; + si.wShowWindow = SW_HIDE; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + + if (options & SHELL_READ) + ga_init2(&ga, 1, BUFLEN); + + /* Now, run the command */ + CreateProcess(NULL, /* Executable name */ + cmd, /* Command to execute */ + NULL, /* Process security attributes */ + NULL, /* Thread security attributes */ + + // this command can be litigeous, handle inheritence was + // deactivated for pending temp file, but, if we deactivate + // it, the pipes don't work for some reason. + TRUE, /* Inherit handles, first deactivated, + * but needed */ + CREATE_DEFAULT_ERROR_MODE, /* Creation flags */ + NULL, /* Environment */ + NULL, /* Current directory */ + &si, /* Startup information */ + &pi); /* Process information */ + + + /* Close our unused side of the pipes */ + CloseHandle(g_hChildStd_IN_Rd); + CloseHandle(g_hChildStd_OUT_Wr); + + if (options & SHELL_WRITE) + { + HANDLE thread = + CreateThread(NULL, /* security attributes */ + 0, /* default stack size */ + sub_process_writer, /* function to be executed */ + g_hChildStd_IN_Wr, /* parameter */ + 0, /* creation flag, start immediately */ + NULL); /* we don't care about thread id */ + CloseHandle(thread); + g_hChildStd_IN_Wr = NULL; + } + + /* Keep updating the window while waiting for the shell to finish. */ + for (;;) + { + MSG msg; + + if (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + /* write pipe information in the window */ + if ((options & (SHELL_READ|SHELL_WRITE)) +# ifdef FEAT_GUI + || gui.in_use +# endif + ) + { + len = 0; + if (!(options & SHELL_EXPAND) + && ((options & + (SHELL_READ|SHELL_WRITE|SHELL_COOKED)) + != (SHELL_READ|SHELL_WRITE|SHELL_COOKED) +# ifdef FEAT_GUI + || gui.in_use +# endif + ) + && (ta_len > 0 || noread_cnt > 4)) + { + if (ta_len == 0) + { + /* Get extra characters when we don't have any. Reset the + * counter and timer. */ + noread_cnt = 0; +# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) + gettimeofday(&start_tv, NULL); +# endif + len = ui_inchar(ta_buf, BUFLEN, 10L, 0); + } + if (ta_len > 0 || len > 0) + { + /* + * For pipes: Check for CTRL-C: send interrupt signal to + * child. Check for CTRL-D: EOF, close pipe to child. + */ + if (len == 1 && cmd != NULL) + { + if (ta_buf[ta_len] == Ctrl_C) + { + /* Learn what exit code is expected, for + * now put 9 as SIGKILL */ + TerminateProcess(pi.hProcess, 9); + } + if (ta_buf[ta_len] == Ctrl_D) + { + CloseHandle(g_hChildStd_IN_Wr); + g_hChildStd_IN_Wr = NULL; + } + } + + /* replace K_BS by and K_DEL by */ + for (i = ta_len; i < ta_len + len; ++i) + { + if (ta_buf[i] == CSI && len - i > 2) + { + c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]); + if (c == K_DEL || c == K_KDEL || c == K_BS) + { + mch_memmove(ta_buf + i + 1, ta_buf + i + 3, + (size_t)(len - i - 2)); + if (c == K_DEL || c == K_KDEL) + ta_buf[i] = DEL; + else + ta_buf[i] = Ctrl_H; + len -= 2; + } + } + else if (ta_buf[i] == '\r') + ta_buf[i] = '\n'; +# ifdef FEAT_MBYTE + if (has_mbyte) + i += (*mb_ptr2len_len)(ta_buf + i, + ta_len + len - i) - 1; +# endif + } + + /* + * For pipes: echo the typed characters. For a pty this + * does not seem to work. + */ + for (i = ta_len; i < ta_len + len; ++i) + { + if (ta_buf[i] == '\n' || ta_buf[i] == '\b') + msg_putchar(ta_buf[i]); +# ifdef FEAT_MBYTE + else if (has_mbyte) + { + int l = (*mb_ptr2len)(ta_buf + i); + + msg_outtrans_len(ta_buf + i, l); + i += l - 1; + } +# endif + else + msg_outtrans_len(ta_buf + i, 1); + } + windgoto(msg_row, msg_col); + out_flush(); + + ta_len += len; + + /* + * Write the characters to the child, unless EOF has been + * typed for pipes. Write one character at a time, to + * avoid losing too much typeahead. When writing buffer + * lines, drop the typed characters (only check for + * CTRL-C). + */ + if (options & SHELL_WRITE) + ta_len = 0; + else if (g_hChildStd_IN_Wr != NULL) + { + WriteFile(g_hChildStd_IN_Wr, (char*)ta_buf, + 1, &len, NULL); + // if we are typing in, we want to keep things reactive + delay = 1; + if (len > 0) + { + ta_len -= len; + mch_memmove(ta_buf, ta_buf + len, ta_len); + } + } + } + } + } + + if (ta_len) + ui_inchar_undo(ta_buf, ta_len); + + if (WaitForSingleObject(pi.hProcess, delay) != WAIT_TIMEOUT) + { + dump_pipe(options, g_hChildStd_OUT_Rd, + &ga, buffer, &buffer_off); + break; + } + + ++noread_cnt; + dump_pipe(options, g_hChildStd_OUT_Rd, + &ga, buffer, &buffer_off); + + /* We start waiting for a very short time and then increase it, so + * that we respond quickly when the process is quick, and don't + * consume too much overhead when it's slow. */ + if (delay < 50) + delay += 10; + } + + /* Close the pipe */ + CloseHandle(g_hChildStd_OUT_Rd); + if (g_hChildStd_IN_Wr != NULL) + CloseHandle(g_hChildStd_IN_Wr); + + WaitForSingleObject(pi.hProcess, INFINITE); + + /* Get the command exit code */ + GetExitCodeProcess(pi.hProcess, &ret); + + if (options & SHELL_READ) + { + if (ga.ga_len > 0) + { + append_ga_line(&ga); + /* remember that the NL was missing */ + curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; + } + else + curbuf->b_no_eol_lnum = 0; + ga_clear(&ga); + } + + /* Close the handles to the subprocess, so that it goes away */ + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + return ret; +} + + static int +mch_system(char *cmd, int options) +{ + /* if we can pipe and the shelltemp option is off */ + if (allowPiping && !p_stmp) + return mch_system_piped(cmd, options); + else + return mch_system_classic(cmd, options); +} #else # define mch_system(c, o) system(c) @@ -3388,7 +3897,7 @@ mch_call_shell( char_u *newcmd; long_u cmdlen = ( #ifdef FEAT_GUI_W32 - STRLEN(vimrun_path) + + (allowPiping && !p_stmp ? 0 : STRLEN(vimrun_path)) + #endif STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10); @@ -3497,7 +4006,7 @@ mch_call_shell( MB_ICONWARNING); need_vimrun_warning = FALSE; } - if (!s_dont_use_vimrun) + if (!s_dont_use_vimrun && (!allowPiping || p_stmp)) /* Use vimrun to execute the command. It opens a console * window, which can be closed without killing Vim. */ vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s", @@ -3521,7 +4030,8 @@ mch_call_shell( /* Print the return value, unless "vimrun" was used. */ if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent #if defined(FEAT_GUI_W32) - && ((options & SHELL_DOOUT) || s_dont_use_vimrun) + && ((options & SHELL_DOOUT) || s_dont_use_vimrun + || (allowPiping && !p_stmp)) #endif ) { diff --git a/src/proto/mbyte.pro b/src/proto/mbyte.pro index 9519a19371..88496ccf06 100644 --- a/src/proto/mbyte.pro +++ b/src/proto/mbyte.pro @@ -56,7 +56,7 @@ void utf_find_illegal __ARGS((void)); int utf_valid_string __ARGS((char_u *s, char_u *end)); int dbcs_screen_tail_off __ARGS((char_u *base, char_u *p)); void mb_adjust_cursor __ARGS((void)); -void mb_adjustpos __ARGS((pos_T *lp)); +void mb_adjustpos __ARGS((buf_T *buf, pos_T *lp)); char_u *mb_prevptr __ARGS((char_u *line, char_u *p)); int mb_charlen __ARGS((char_u *str)); int mb_charlen_len __ARGS((char_u *str, int len)); diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index 720d263fd6..d8d3cc374b 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -14,6 +14,7 @@ int decl __ARGS((pos_T *lp)); linenr_T get_cursor_rel_lnum __ARGS((win_T *wp, linenr_T lnum)); void check_cursor_lnum __ARGS((void)); void check_cursor_col __ARGS((void)); +void check_cursor_col_win __ARGS((win_T *win)); void check_cursor __ARGS((void)); void adjust_cursor_col __ARGS((void)); int leftcol_changed __ARGS((void)); @@ -57,6 +58,7 @@ int ga_grow __ARGS((garray_T *gap, int n)); char_u *ga_concat_strings __ARGS((garray_T *gap)); void ga_concat __ARGS((garray_T *gap, char_u *s)); void ga_append __ARGS((garray_T *gap, int c)); +void append_ga_line __ARGS((garray_T *gap)); int name_to_mod_mask __ARGS((int c)); int simplify_key __ARGS((int key, int *modifiers)); int handle_x_keys __ARGS((int key)); diff --git a/src/search.c b/src/search.c index 6fc3d77595..b233357d7b 100644 --- a/src/search.c +++ b/src/search.c @@ -1594,7 +1594,7 @@ searchc(cap, t_cmd) /* Force a move of at least one char, so ";" and "," will move the * cursor, even if the cursor is right in front of char we are looking * at. */ - if (vim_strchr(p_cpo, CPO_SCOLON) == NULL && count == 1) + if (vim_strchr(p_cpo, CPO_SCOLON) == NULL && count == 1 && t_cmd) stop = FALSE; } diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak index f3035b18fc..55d13e48f3 100644 --- a/src/testdir/Make_amiga.mak +++ b/src/testdir/Make_amiga.mak @@ -29,7 +29,7 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \ test66.out test67.out test68.out test69.out test70.out \ test71.out test72.out test73.out test74.out test75.out \ test76.out test77.out test78.out test79.out test80.out \ - test81.out + test81.out test82.out .SUFFIXES: .in .out @@ -130,3 +130,4 @@ test78.out: test78.in test79.out: test79.in test80.out: test80.in test81.out: test81.in +test82.out: test82.in diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak index 9ece4b5179..ba77d22682 100644 --- a/src/testdir/Make_dos.mak +++ b/src/testdir/Make_dos.mak @@ -29,7 +29,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \ test42.out test52.out test65.out test66.out test67.out \ test68.out test69.out test71.out test72.out test73.out \ test74.out test75.out test76.out test77.out test78.out \ - test79.out test80.out test81.out + test79.out test80.out test81.out test82.out SCRIPTS32 = test50.out test70.out diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak index 2ff20ad1b2..d844c3926f 100644 --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -49,7 +49,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \ test42.out test52.out test65.out test66.out test67.out \ test68.out test69.out test71.out test72.out test73.out \ test74.out test75.out test76.out test77.out test78.out \ - test79.out test80.out test81.out + test79.out test80.out test81.out test82.out SCRIPTS32 = test50.out test70.out diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak index 4442a41de0..bd11d7f263 100644 --- a/src/testdir/Make_os2.mak +++ b/src/testdir/Make_os2.mak @@ -29,7 +29,7 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \ test66.out test67.out test68.out test69.out test70.out \ test71.out test72.out test73.out test74.out test75.out \ test76.out test77.out test78.out test79.out test80.out \ - test81.out + test81.out test82.out .SUFFIXES: .in .out diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms index d4101ed959..fe062c30ab 100644 --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -4,7 +4,7 @@ # Authors: Zoltan Arpadffy, # Sandor Kopanyi, # -# Last change: 2011 Jun 26 +# Last change: 2011 Jul 15 # # This has been tested on VMS 6.2 to 8.3 on DEC Alpha, VAX and IA64. # Edit the lines in the Configuration section below to select. @@ -75,7 +75,8 @@ SCRIPT = test1.out test2.out test3.out test4.out test5.out \ test61.out test62.out test63.out test64.out test65.out \ test66.out test67.out test68.out test69.out \ test71.out test72.out test74.out test75.out test76.out \ - test77.out test78.out test79.out test80.out test81.out + test77.out test78.out test79.out test80.out test81.out \ + test82.out # Known problems: # Test 30: a problem around mac format - unknown reason diff --git a/src/testdir/Makefile b/src/testdir/Makefile index 2eea86e265..c776c15f95 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -26,7 +26,7 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \ test64.out test65.out test66.out test67.out test68.out \ test69.out test70.out test71.out test72.out test73.out \ test74.out test75.out test76.out test77.out test78.out \ - test79.out test80.out test81.out + test79.out test80.out test81.out test82.out SCRIPTS_GUI = test16.out diff --git a/src/testdir/test3.in b/src/testdir/test3.in index 1cfd8f23ee..aea055fb3a 100644 --- a/src/testdir/test3.in +++ b/src/testdir/test3.in @@ -1450,6 +1450,36 @@ void func3(void) printf("Don't you dare indent this line incorrectly!\n); } +STARTTEST +:set cino& +:set cino+=l1 +2kdd=][ +ENDTEST + +void func(void) +{ + int tab[] = + { + 1, 2, 3, + 4, 5, 6}; + + printf("Indent this line correctly!\n"); + + switch (foo) + { + case bar: + printf("bar"); + break; + case baz: { + printf("baz"); + break; + } + case quux: +printf("But don't break the indentation of this instruction\n"); +break; + } +} + STARTTEST :set cino& 2kdd=][ diff --git a/src/testdir/test3.ok b/src/testdir/test3.ok index 8475aff9fe..a475669310 100644 --- a/src/testdir/test3.ok +++ b/src/testdir/test3.ok @@ -1308,6 +1308,31 @@ void func3(void) } +void func(void) +{ + int tab[] = + { + 1, 2, 3, + 4, 5, 6}; + + printf("Indent this line correctly!\n"); + + switch (foo) + { + case bar: + printf("bar"); + break; + case baz: { + printf("baz"); + break; + } + case quux: + printf("But don't break the indentation of this instruction\n"); + break; + } +} + + void func(void) { cout << "a" diff --git a/src/testdir/test78.in b/src/testdir/test78.in index bcbc972432..1850bd9236 100644 --- a/src/testdir/test78.in +++ b/src/testdir/test78.in @@ -6,7 +6,7 @@ blocks. STARTTEST :so small.vim -:set nocp fileformat=unix undolevels=-1 +:set nocp fileformat=unix undolevels=-1 viminfo+=nviminfo :e! Xtest ggdG :let text = "\tabcdefghijklmnoparstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnoparstuvwxyz0123456789" diff --git a/src/testdir/test81.in b/src/testdir/test81.in index e47653fd9e..82a6892a1d 100644 --- a/src/testdir/test81.in +++ b/src/testdir/test81.in @@ -1,10 +1,12 @@ Test for t movement command and 'cpo-;' setting STARTTEST -:set nocompatible +:set nocompatible viminfo+=nviminfo :set cpo-=; /firstline/ j0tt;D +0fz;D +$Fy;D $Ty;D:set cpo+=; j0tt;;D $Ty;;D:?firstline?+1,$w! test.out @@ -13,6 +15,8 @@ ENDTEST firstline aaa two three four + zzz +yyy bbb yee yoo four ccc two three four ddd yee yoo four diff --git a/src/testdir/test81.ok b/src/testdir/test81.ok index 8f86b521ee..e9f17dc4f8 100644 --- a/src/testdir/test81.ok +++ b/src/testdir/test81.ok @@ -1,4 +1,6 @@ aaa two + z +y bbb y ccc ddd yee y diff --git a/src/ui.c b/src/ui.c index 74e4bec71a..57758ec13e 100644 --- a/src/ui.c +++ b/src/ui.c @@ -58,7 +58,7 @@ ui_write(s, len) #endif } -#if defined(UNIX) || defined(VMS) || defined(PROTO) +#if defined(UNIX) || defined(VMS) || defined(PROTO) || defined(WIN3264) /* * When executing an external program, there may be some typed characters that * are not consumed by it. Give them back to ui_inchar() and they are stored diff --git a/src/version.c b/src/version.c index 7159149882..c91a7f3493 100644 --- a/src/version.c +++ b/src/version.c @@ -724,6 +724,40 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 254, +/**/ + 253, +/**/ + 252, +/**/ + 251, +/**/ + 250, +/**/ + 249, +/**/ + 248, +/**/ + 247, +/**/ + 246, +/**/ + 245, +/**/ + 244, +/**/ + 243, +/**/ + 242, +/**/ + 241, +/**/ + 240, +/**/ + 239, +/**/ + 238, /**/ 237, /**/