summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/digraph.txt9
-rw-r--r--runtime/doc/options.txt16
-rw-r--r--runtime/doc/term.txt6
-rw-r--r--runtime/filetype.vim4
-rw-r--r--src/edit.c32
-rw-r--r--src/ex_getln.c43
-rw-r--r--src/getchar.c6
-rw-r--r--src/globals.h2
-rw-r--r--src/keymap.h10
-rw-r--r--src/message.c2
-rw-r--r--src/misc2.c50
-rw-r--r--src/normal.c75
-rw-r--r--src/os_mswin.c2
-rw-r--r--src/os_unix.c25
-rw-r--r--src/quickfix.c4
-rw-r--r--src/regexp.c1296
-rw-r--r--src/term.c238
-rw-r--r--src/testdir/test24.inbin975 -> 1156 bytes
-rw-r--r--src/testdir/test24.ok5
-rw-r--r--src/version.h4
-rw-r--r--src/window.c4
21 files changed, 1199 insertions, 634 deletions
diff --git a/runtime/doc/digraph.txt b/runtime/doc/digraph.txt
index ed4527175..201d6a0e5 100644
--- a/runtime/doc/digraph.txt
+++ b/runtime/doc/digraph.txt
@@ -1,4 +1,4 @@
-*digraph.txt* For Vim version 7.0aa. Last change: 2004 Oct 07
+*digraph.txt* For Vim version 7.0aa. Last change: 2005 Mar 06
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -161,8 +161,13 @@ These are the RFC1345 digraphs for the one-byte characters. See the output of
":digraphs" for the others. The characters above 255 are only available when
Vim was compiled with the |+multi_byte| feature.
+EURO
+
Exception: RFC1345 doesn't specify the euro sign. In Vim the digraph =e was
-added for this.
+added for this. Note the difference between latin1, where the digraph Cu is
+used for the currency sign, and latin9 (iso-8859-15), where the digraph =e is
+used for the euro sign, while both of them are the character 164, 0xa4.
+
*digraph-table*
char digraph hex dec official name ~
^@ NU 0x00 0 NULL (NUL)
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index d0b5abf74..2c52c0475 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt* For Vim version 7.0aa. Last change: 2005 Mar 03
+*options.txt* For Vim version 7.0aa. Last change: 2005 Mar 06
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -3972,6 +3972,10 @@ A jump table for the options with a short description can be found at |Q_op|.
Number of pixel lines inserted between characters. Useful if the font
uses the full character cell height, making lines touch each other.
When non-zero there is room for underlining.
+ With some fonts there can be too much room between lines (to have
+ space for ascents and descents). Then it makes sense to set
+ 'linespace' to a negative value. This may cause display problems
+ though!
*'lisp'* *'nolisp'*
'lisp' boolean (default off)
@@ -4709,8 +4713,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'printmbcharset' 'pmbcs' string (default "")
global
{not in Vi}
- {only available when compiled with the |+printer|
- and |+multi_byte| features}
+ {only available when compiled with the |+printer|,
+ |+postscript| and |+multi_byte| features}
The CJK character set to be used for CJK output from |:hardcopy|.
See |pmbcs-option|.
@@ -4718,8 +4722,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'printmbfont' 'pmbfn' string (default "")
global
{not in Vi}
- {only available when compiled with the |+printer|
- and |+multi_byte| features}
+ {only available when compiled with the |+printer|,
+ |+postscript| and |+multi_byte| features}
List of font names to be used for CJK output from |:hardcopy|.
See |pmbfn-option|.
@@ -6344,7 +6348,7 @@ A jump table for the options with a short description can be found at |Q_op|.
xterm2 Works like "xterm", but with the xterm reporting the
mouse position while the mouse is dragged. This works
much faster and more precise. Your xterm must at
- least at patchlevel 88 / XFree 3.3.3 for this to
+ least at patchlevel 88 / XFree 3.3.3 for this to
work. See below for how Vim detects this
automatically.
*netterm-mouse*
diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt
index fba493c70..0ac9697c4 100644
--- a/runtime/doc/term.txt
+++ b/runtime/doc/term.txt
@@ -1,4 +1,4 @@
-*term.txt* For Vim version 7.0aa. Last change: 2005 Mar 04
+*term.txt* For Vim version 7.0aa. Last change: 2005 Mar 05
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -301,6 +301,10 @@ Note: Use the <> form if possible
t_kd <Down> arrow down *t_kd* *'t_kd'*
t_kr <Right> arrow right *t_kr* *'t_kr'*
t_kl <Left> arrow left *t_kl* *'t_kl'*
+ <xUp> alternate arrow up *<xUp>*
+ <xDown> alternate arrow down *<xDown>*
+ <xRight> alternate arrow right *<xRight>*
+ <xLeft> alternate arrow left *<xLeft>*
<S-Up> shift arrow up
<S-Down> shift arrow down
t_%i <S-Right> shift arrow right *t_%i* *'t_%i'*
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index bbbb6d2c1..768fd5ddd 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -1,7 +1,7 @@
" Vim support file to detect file types
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2005 Feb 18
+" Last Change: 2005 Mar 06
" Listen very carefully, I will say this only once
if exists("did_load_filetypes")
@@ -91,7 +91,7 @@ au BufNewFile,BufRead build.xml setf ant
au BufNewFile,BufRead proftpd.conf* setf apachestyle
" Apache config file
-au BufNewFile,BufRead httpd.conf*,srm.conf*,access.conf*,.htaccess,apache.conf* setf apache
+au BufNewFile,BufRead httpd.conf*,srm.conf*,access.conf*,.htaccess,apache.conf*,apache2.conf*,/etc/apache2/*.conf* setf apache
" XA65 MOS6510 cross assembler
au BufNewFile,BufRead *.a65 setf a65
diff --git a/src/edit.c b/src/edit.c
index ae00c2aba..3a3e86596 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -710,9 +710,11 @@ edit(cmdchar, startln, count)
switch (c)
{
case K_LEFT: c = K_RIGHT; break;
+ case K_XLEFT: c = K_XRIGHT; break;
case K_S_LEFT: c = K_S_RIGHT; break;
case K_C_LEFT: c = K_C_RIGHT; break;
case K_RIGHT: c = K_LEFT; break;
+ case K_XRIGHT: c = K_XLEFT; break;
case K_S_RIGHT: c = K_S_LEFT; break;
case K_C_RIGHT: c = K_C_LEFT; break;
}
@@ -1105,7 +1107,11 @@ doESCkey:
break;
case K_LEFT:
- ins_left();
+ case K_XLEFT:
+ if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
+ ins_s_left();
+ else
+ ins_left();
break;
case K_S_LEFT:
@@ -1114,7 +1120,11 @@ doESCkey:
break;
case K_RIGHT:
- ins_right();
+ case K_XRIGHT:
+ if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
+ ins_s_right();
+ else
+ ins_right();
break;
case K_S_RIGHT:
@@ -1123,7 +1133,11 @@ doESCkey:
break;
case K_UP:
- ins_up(FALSE);
+ case K_XUP:
+ if (mod_mask & MOD_MASK_SHIFT)
+ ins_pageup();
+ else
+ ins_up(FALSE);
break;
case K_S_UP:
@@ -1133,7 +1147,11 @@ doESCkey:
break;
case K_DOWN:
- ins_down(FALSE);
+ case K_XDOWN:
+ if (mod_mask & MOD_MASK_SHIFT)
+ ins_pagedown();
+ else
+ ins_down(FALSE);
break;
case K_S_DOWN:
@@ -6193,12 +6211,14 @@ ins_ctrl_g()
{
/* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */
case K_UP:
+ case K_XUP:
case Ctrl_K:
case 'k': ins_up(TRUE);
break;
/* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */
case K_DOWN:
+ case K_XDOWN:
case Ctrl_J:
case 'j': ins_down(TRUE);
break;
@@ -6428,6 +6448,10 @@ ins_start_select(c)
case K_KPAGEUP:
case K_PAGEDOWN:
case K_KPAGEDOWN:
+ case K_XLEFT:
+ case K_XRIGHT:
+ case K_XUP:
+ case K_XDOWN:
# ifdef MACOS
case K_LEFT:
case K_RIGHT:
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 4c9d17d78..4c6175b6f 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -320,9 +320,11 @@ getcmdline(firstc, count, indent)
switch (c)
{
case K_RIGHT: c = K_LEFT; break;
+ case K_XRIGHT: c = K_XLEFT; break;
case K_S_RIGHT: c = K_S_LEFT; break;
case K_C_RIGHT: c = K_C_LEFT; break;
case K_LEFT: c = K_RIGHT; break;
+ case K_XLEFT: c = K_XRIGHT; break;
case K_S_LEFT: c = K_S_RIGHT; break;
case K_C_LEFT: c = K_C_RIGHT; break;
}
@@ -354,10 +356,11 @@ getcmdline(firstc, count, indent)
/* free old command line when finished moving around in the history
* list */
if (lookfor != NULL
- && c != K_S_DOWN && c != K_S_UP && c != K_DOWN && c != K_UP
+ && c != K_S_DOWN && c != K_S_UP
+ && c != K_DOWN && c != K_UP && c != K_XDOWN && c != K_XUP
&& c != K_PAGEDOWN && c != K_PAGEUP
&& c != K_KPAGEDOWN && c != K_KPAGEUP
- && c != K_LEFT && c != K_RIGHT
+ && c != K_LEFT && c != K_RIGHT && c != K_XLEFT && c != K_XRIGHT
&& (xpc.xp_numfiles > 0 || (c != Ctrl_P && c != Ctrl_N)))
{
vim_free(lookfor);
@@ -375,9 +378,9 @@ getcmdline(firstc, count, indent)
/* Special translations for 'wildmenu' */
if (did_wild_list && p_wmnu)
{
- if (c == K_LEFT)
+ if (c == K_LEFT || c == K_XLEFT)
c = Ctrl_P;
- else if (c == K_RIGHT)
+ else if (c == K_RIGHT || c == K_XRIGHT)
c = Ctrl_N;
}
/* Hitting CR after "emenu Name.": complete submenu */
@@ -398,7 +401,8 @@ getcmdline(firstc, count, indent)
(void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE);
did_wild_list = FALSE;
#ifdef FEAT_WILDMENU
- if (!p_wmnu || (c != K_UP && c != K_DOWN))
+ if (!p_wmnu || (c != K_UP && c != K_DOWN
+ && c != K_XUP && c != K_XDOWN))
#endif
xpc.xp_context = EXPAND_NOTHING;
wim_index = 0;
@@ -443,9 +447,10 @@ getcmdline(firstc, count, indent)
if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu)
{
/* Hitting <Down> after "emenu Name.": complete submenu */
- if (ccline.cmdbuff[ccline.cmdpos - 1] == '.' && c == K_DOWN)
+ if (ccline.cmdbuff[ccline.cmdpos - 1] == '.'
+ && (c == K_DOWN || c == K_XDOWN))
c = p_wc;
- else if (c == K_UP)
+ else if (c == K_UP || c == K_XUP)
{
/* Hitting <Up>: Remove one submenu name in front of the
* cursor */
@@ -492,14 +497,15 @@ getcmdline(firstc, count, indent)
upseg[4] = NUL;
if (ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP
- && c == K_DOWN
+ && (c == K_DOWN || c == K_XDOWN)
&& (ccline.cmdbuff[ccline.cmdpos - 2] != '.'
|| ccline.cmdbuff[ccline.cmdpos - 3] != '.'))
{
/* go down a directory */
c = p_wc;
}
- else if (STRNCMP(xpc.xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN)
+ else if (STRNCMP(xpc.xp_pattern, upseg + 1, 3) == 0
+ && (c == K_DOWN || c == K_XDOWN))
{
/* If in a direct ancestor, strip off one ../ to go down */
int found = FALSE;
@@ -527,7 +533,7 @@ getcmdline(firstc, count, indent)
c = p_wc;
}
}
- else if (c == K_UP)
+ else if (c == K_UP || c == K_XUP)
{
/* go up a directory */
int found = FALSE;
@@ -1096,6 +1102,7 @@ getcmdline(firstc, count, indent)
continue; /* don't do incremental search now */
case K_RIGHT:
+ case K_XRIGHT:
case K_S_RIGHT:
case K_C_RIGHT:
do
@@ -1114,7 +1121,8 @@ getcmdline(firstc, count, indent)
#endif
++ccline.cmdpos;
}
- while ((c == K_S_RIGHT || c == K_C_RIGHT)
+ while ((c == K_S_RIGHT || c == K_C_RIGHT
+ || (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)))
&& ccline.cmdbuff[ccline.cmdpos] != ' ');
#ifdef FEAT_MBYTE
if (has_mbyte)
@@ -1123,6 +1131,7 @@ getcmdline(firstc, count, indent)
goto cmdline_not_changed;
case K_LEFT:
+ case K_XLEFT:
case K_S_LEFT:
case K_C_LEFT:
do
@@ -1137,7 +1146,8 @@ getcmdline(firstc, count, indent)
#endif
ccline.cmdspos -= cmdline_charsize(ccline.cmdpos);
}
- while ((c == K_S_LEFT || c == K_C_LEFT)
+ while ((c == K_S_LEFT || c == K_C_LEFT
+ || (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)))
&& ccline.cmdbuff[ccline.cmdpos - 1] != ' ');
#ifdef FEAT_MBYTE
if (has_mbyte)
@@ -1320,7 +1330,9 @@ getcmdline(firstc, count, indent)
#ifdef FEAT_CMDHIST
case K_UP:
+ case K_XUP:
case K_DOWN:
+ case K_XDOWN:
case K_S_UP:
case K_S_DOWN:
case K_PAGEUP:
@@ -1344,8 +1356,8 @@ getcmdline(firstc, count, indent)
for (;;)
{
/* one step backwards */
- if (c == K_UP || c == K_S_UP || c == Ctrl_P ||
- c == K_PAGEUP || c == K_KPAGEUP)
+ if (c == K_UP || c == K_XUP || c == K_S_UP || c == Ctrl_P
+ || c == K_PAGEUP || c == K_KPAGEUP)
{
if (hiscnt == hislen) /* first time */
hiscnt = hisidx[histype];
@@ -1381,7 +1393,8 @@ getcmdline(firstc, count, indent)
hiscnt = i;
break;
}
- if ((c != K_UP && c != K_DOWN) || hiscnt == i
+ if ((c != K_UP && c != K_DOWN && c != K_XUP && c != K_XDOWN)
+ || hiscnt == i
|| STRNCMP(history[histype][hiscnt].hisstr,
lookfor, (size_t)j) == 0)
break;
diff --git a/src/getchar.c b/src/getchar.c
index e93ce0529..c06b60076 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -4530,6 +4530,7 @@ check_map(keys, mode, exact)
}
#endif
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(MACOS)
/*
* Default mappings for some often used keys.
*/
@@ -4609,6 +4610,7 @@ static struct initmap
{(char_u *)"<Backspace> \"-d", VISUAL},
#endif
+#if 0
/* Map extra keys to their normal equivalents. */
{(char_u *)"<xF1> <F1>", NORMAL+VISUAL+OP_PENDING},
{(char_u *)"<xF1> <F1>", INSERT+CMDLINE},
@@ -4630,7 +4632,9 @@ static struct initmap
{(char_u *)"<xEND> <END>", INSERT+CMDLINE},
{(char_u *)"<xHOME> <HOME>", NORMAL+VISUAL+OP_PENDING},
{(char_u *)"<xHOME> <HOME>", INSERT+CMDLINE},
+#endif
};
+#endif
/*
* Set up default mappings.
@@ -4638,10 +4642,12 @@ static struct initmap
void
init_mappings()
{
+#if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(MACOS)
int i;
for (i = 0; i < sizeof(initmappings) / sizeof(struct initmap); ++i)
add_map(initmappings[i].arg, initmappings[i].mode);
+#endif
}
/*
diff --git a/src/globals.h b/src/globals.h
index 445b453fc..8251f1831 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1412,9 +1412,11 @@ EXTERN char_u e_nbreadonly[] INIT(=N_("E744: NetBeans does not allow changes in
#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL) || defined(PROTO)
EXTERN char_u e_intern2[] INIT(=N_("E685: Internal error: %s"));
#endif
+#if 0
#if defined(HAVE_SETJMP_H) || defined(HAVE_TRY_EXCEPT) || defined(__MINGW32__)
EXTERN char_u e_complex[] INIT(=N_("E361: Crash intercepted; regexp too complex?"));
#endif
+#endif
EXTERN char_u e_outofstack[] INIT(=N_("E363: pattern caused out-of-stack error"));
EXTERN char_u e_emptybuf[] INIT(=N_("E749: empty buffer"));
diff --git a/src/keymap.h b/src/keymap.h
index 5babdf4af..e0e46b773 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -207,6 +207,10 @@ enum key_extra
, KE_XF4
, KE_XEND /* extra (vt100) end key for xterm */
, KE_XHOME /* extra (vt100) home key for xterm */
+ , KE_XUP /* extra vt100 cursor keys for xterm */
+ , KE_XDOWN
+ , KE_XLEFT
+ , KE_XRIGHT
, KE_LEFTMOUSE_NM /* non-mappable Left mouse button click */
, KE_LEFTRELEASE_NM /* non-mappable left mouse button release */
@@ -270,6 +274,12 @@ enum key_extra
#define K_XF3 TERMCAP2KEY(KS_EXTRA, KE_XF3)
#define K_XF4 TERMCAP2KEY(KS_EXTRA, KE_XF4)
+/* extra set of cursor keys for vt100 compatible xterm */
+#define K_XUP TERMCAP2KEY(KS_EXTRA, KE_XUP)
+#define K_XDOWN TERMCAP2KEY(KS_EXTRA, KE_XDOWN)
+#define K_XLEFT TERMCAP2KEY(KS_EXTRA, KE_XLEFT)
+#define K_XRIGHT TERMCAP2KEY(KS_EXTRA, KE_XRIGHT)
+
#define K_F1 TERMCAP2KEY('k', '1') /* function keys */
#define K_F2 TERMCAP2KEY('k', '2')
#define K_F3 TERMCAP2KEY('k', '3')
diff --git a/src/message.c b/src/message.c
index f6494847f..9b0045d14 100644
--- a/src/message.c
+++ b/src/message.c
@@ -1953,6 +1953,7 @@ msg_puts_attr_len(str, maxlen, attr)
case BS:
case 'k':
case K_UP:
+ case K_XUP:
if (!more_back_used)
{
msg_moremsg(TRUE);
@@ -1965,6 +1966,7 @@ msg_puts_attr_len(str, maxlen, attr)
case NL:
case 'j':
case K_DOWN:
+ case K_XDOWN:
lines_left = 1;
break;
case ':': /* start new command line */
diff --git a/src/misc2.c b/src/misc2.c
index 9b21168d8..d4d975dda 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1784,6 +1784,10 @@ static struct key_name_entry
{K_DOWN, (char_u *)"Down"},
{K_LEFT, (char_u *)"Left"},
{K_RIGHT, (char_u *)"Right"},
+ {K_XUP, (char_u *)"xUp"},
+ {K_XDOWN, (char_u *)"xDown"},
+ {K_XLEFT, (char_u *)"xLeft"},
+ {K_XRIGHT, (char_u *)"xRight"},
{K_F1, (char_u *)"F1"},
{K_F2, (char_u *)"F2"},
@@ -1957,20 +1961,6 @@ name_to_mod_mask(c)
return 0;
}
-#if 0 /* not used */
-/*
- * Decide whether the given key code (K_*) is a shifted special
- * key (by looking at mod_mask). If it is, then return the appropriate shifted
- * key code, otherwise just return the character as is.
- */
- int
-check_shifted_spec_key(c)
- int c;
-{
- return simplify_key(c, &mod_mask);
-}
-#endif
-
/*
* Check if if there is a special key code for "key" that includes the
* modifiers specified.
@@ -2008,6 +1998,35 @@ simplify_key(key, modifiers)
}
/*
+ * Change <xHome> to <Home>, <xUp> to <Up>, etc.
+ * "kp" must point to an array that holds the two characters that represent a
+ * special key.
+ */
+ int
+handle_x_keys(key)
+ int key;
+{
+ switch (key)
+ {
+ case K_XUP: return K_UP;
+ case K_XDOWN: return K_DOWN;
+ case K_XLEFT: return K_LEFT;
+ case K_XRIGHT: return K_RIGHT;
+ case K_XHOME: return K_HOME;
+ case K_XEND: return K_END;
+ case K_XF1: return K_F1;
+ case K_XF2: return K_F2;
+ case K_XF3: return K_F3;
+ case K_XF4: return K_F4;
+ case K_S_XF1: return K_S_F1;
+ case K_S_XF2: return K_S_F2;
+ case K_S_XF3: return K_S_F3;
+ case K_S_XF4: return K_S_F4;
+ }
+ return key;
+}
+
+/*
* Return a string which contains the name of the given key when the given
* modifiers are down.
*/
@@ -2246,7 +2265,10 @@ find_special_key(srcp, modp, keycode)
if (modifiers != 0 && last_dash[2] == '>')
key = last_dash[1];
else
+ {
key = get_special_key_code(last_dash + 1);
+ key = handle_x_keys(key);
+ }
/*
* get_special_key_code() may return NUL for invalid
diff --git a/src/normal.c b/src/normal.c
index 9bf2e66b7..df914b5f3 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -381,13 +381,17 @@ static const struct nv_cmd
{K_KINS, nv_edit, 0, 0},
{K_BS, nv_ctrlh, 0, 0},
{K_UP, nv_up, NV_SSS|NV_STS, FALSE},
+ {K_XUP, nv_up, NV_SSS|NV_STS, FALSE},
{K_S_UP, nv_page, NV_SS, BACKWARD},
{K_DOWN, nv_down, NV_SSS|NV_STS, FALSE},
+ {K_XDOWN, nv_down, NV_SSS|NV_STS, FALSE},
{K_S_DOWN, nv_page, NV_SS, FORWARD},
{K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0},
+ {K_XLEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0},
{K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0},
{K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1},
{K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0},
+ {K_XRIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0},
{K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, FALSE},
{K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, TRUE},
{K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD},
@@ -832,10 +836,12 @@ getcount:
{
case 'l': ca.cmdchar = 'h'; break;
case K_RIGHT: ca.cmdchar = K_LEFT; break;
+ case K_XRIGHT: ca.cmdchar = K_XLEFT; break;
case K_S_RIGHT: ca.cmdchar = K_S_LEFT; break;
case K_C_RIGHT: ca.cmdchar = K_C_LEFT; break;
case 'h': ca.cmdchar = 'l'; break;
case K_LEFT: ca.cmdchar = K_RIGHT; break;
+ case K_XLEFT: ca.cmdchar = K_XRIGHT; break;
case K_S_LEFT: ca.cmdchar = K_S_RIGHT; break;
case K_C_LEFT: ca.cmdchar = K_C_RIGHT; break;
case '>': ca.cmdchar = '<'; break;
@@ -4316,7 +4322,9 @@ nv_zet(cap)
else if (nchar == 'l'
|| nchar == 'h'
|| nchar == K_LEFT
- || nchar == K_RIGHT)
+ || nchar == K_XLEFT
+ || nchar == K_RIGHT
+ || nchar == K_XRIGHT)
{
cap->count1 = n ? n * cap->count1 : cap->count1;
goto dozet;
@@ -4423,6 +4431,7 @@ dozet:
/* "zh" - scroll screen to the right */
case 'h':
case K_LEFT:
+ case K_XLEFT:
if (!curwin->w_p_wrap)
{
if ((colnr_T)cap->count1 > curwin->w_leftcol)
@@ -4440,6 +4449,7 @@ dozet:
/* "zl" - scroll screen to the left */
case 'l':
case K_RIGHT:
+ case K_XRIGHT:
if (!curwin->w_p_wrap)
{
/* scroll the window left */
@@ -5294,6 +5304,15 @@ nv_right(cap)
# define PAST_LINE 0
#endif
+ if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
+ {
+ /* <C-Right> and <S-Right> move a word or WORD right */
+ if (mod_mask & MOD_MASK_CTRL)
+ cap->arg = TRUE;
+ nv_wordcmd(cap);
+ return;
+ }
+
cap->oap->motion_type = MCHAR;
cap->oap->inclusive = FALSE;
#ifdef FEAT_VISUAL
@@ -5323,7 +5342,7 @@ nv_right(cap)
&& vim_strchr(p_ww, 's') != NULL)
|| (cap->cmdchar == 'l'
&& vim_strchr(p_ww, 'l') != NULL)
- || (cap->cmdchar == K_RIGHT
+ || ((cap->cmdchar == K_RIGHT || cap->cmdchar == K_XRIGHT)
&& vim_strchr(p_ww, '>') != NULL))
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
{
@@ -5399,6 +5418,15 @@ nv_left(cap)
{
long n;
+ if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
+ {
+ /* <C-Left> and <S-Left> move a word or WORD left */
+ if (mod_mask & MOD_MASK_CTRL)
+ cap->arg = 1;
+ nv_bck_word(cap);
+ return;
+ }
+
cap->oap->motion_type = MCHAR;
cap->oap->inclusive = FALSE;
for (n = cap->count1; n > 0; --n)
@@ -5414,7 +5442,7 @@ nv_left(cap)
&& vim_strchr(p_ww, 'b') != NULL)
|| (cap->cmdchar == 'h'
&& vim_strchr(p_ww, 'h') != NULL)
- || (cap->cmdchar == K_LEFT
+ || ((cap->cmdchar == K_LEFT || cap->cmdchar == K_XLEFT)
&& vim_strchr(p_ww, '<') != NULL))
&& curwin->w_cursor.lnum > 1)
{
@@ -5456,11 +5484,20 @@ nv_left(cap)
nv_up(cap)
cmdarg_T *cap;
{
- cap->oap->motion_type = MLINE;
- if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == FAIL)
- clearopbeep(cap->oap);
- else if (cap->arg)
- beginline(BL_WHITE | BL_FIX);
+ if (mod_mask & MOD_MASK_SHIFT)
+ {
+ /* <S-Up> is page up */
+ cap->arg = BACKWARD;
+ nv_page(cap);
+ }
+ else
+ {
+ cap->oap->motion_type = MLINE;
+ if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == FAIL)
+ clearopbeep(cap->oap);
+ else if (cap->arg)
+ beginline(BL_WHITE | BL_FIX);
+ }
}
/*
@@ -5471,6 +5508,13 @@ nv_up(cap)
nv_down(cap)
cmdarg_T *cap;
{
+ if (mod_mask & MOD_MASK_SHIFT)
+ {
+ /* <S-Down> is page down */
+ cap->arg = FORWARD;
+ nv_page(cap);
+ }
+ else
#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
/* In a quickfix window a <CR> jumps to the error under the cursor. */
if (bt_quickfix(curbuf) && cap->cmdchar == CAR)
@@ -5553,8 +5597,9 @@ nv_gotofile(cap)
nv_end(cap)
cmdarg_T *cap;
{
- if (cap->arg) /* CTRL-END = goto last line */
+ if (cap->arg || (mod_mask & MOD_MASK_CTRL)) /* CTRL-END = goto last line */
{
+ cap->arg = TRUE;
nv_goto(cap);
cap->count1 = 1; /* to end of current line */
}
@@ -7205,6 +7250,7 @@ nv_g_cmd(cap)
*/
case 'j':
case K_DOWN:
+ case K_XDOWN:
/* with 'nowrap' it works just like the normal "j" command; also when
* in a closed fold */
if (!curwin->w_p_wrap
@@ -7224,6 +7270,7 @@ nv_g_cmd(cap)
case 'k':
case K_UP:
+ case K_XUP:
/* with 'nowrap' it works just like the normal "k" command; also when
* in a closed fold */
if (!curwin->w_p_wrap
@@ -7761,8 +7808,14 @@ nv_lineop(cap)
nv_home(cap)
cmdarg_T *cap;
{
- cap->count0 = 1;
- nv_pipe(cap);
+ /* CTRL-HOME is like "gg" */
+ if (mod_mask & MOD_MASK_CTRL)
+ nv_goto(cap);
+ else
+ {
+ cap->count0 = 1;
+ nv_pipe(cap);
+ }
}
/*
diff --git a/src/os_mswin.c b/src/os_mswin.c
index 5e96da8af..a5e10be49 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -2564,9 +2564,11 @@ Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
switch (data->dwData)
{
case COPYDATA_ENCODING:
+# ifdef FEAT_MBYTE
/* Remember the encoding that the client uses. */
vim_free(client_enc);
client_enc = enc_canonize((char_u *)data->lpData);
+# endif
return 1;
case COPYDATA_KEYS:
diff --git a/src/os_unix.c b/src/os_unix.c
index c64a39e02..5df0d35f2 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -610,7 +610,13 @@ mch_delay(msec, ignoreinput)
WaitForChar(msec);
}
-#if defined(HAVE_GETRLIMIT) \
+#if 0 /* disabled, no longer needed now that regmatch() is not recursive */
+# if defined(HAVE_GETRLIMIT)
+# define HAVE_STACK_LIMIT
+# endif
+#endif
+
+#if defined(HAVE_STACK_LIMIT) \
|| (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
# define HAVE_CHECK_STACK_GROWTH
/*
@@ -638,7 +644,7 @@ check_stack_growth(p)
}
#endif
-#if defined(HAVE_GETRLIMIT) || defined(PROTO)
+#if defined(HAVE_STACK_LIMIT) || defined(PROTO)
static char *stack_limit = NULL;
#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
@@ -951,7 +957,7 @@ deathtrap SIGDEFARG(sigarg)
set_vim_var_nr(VV_DYING, (long)entered);
#endif
-#ifdef HAVE_GETRLIMIT
+#ifdef HAVE_STACK_LIMIT
/* Since we are now using the signal stack, need to reset the stack
* limit. Otherwise using a regexp will fail. */
get_stack_limit();
@@ -2683,12 +2689,10 @@ mch_early_init()
{
#ifdef HAVE_CHECK_STACK_GROWTH
int i;
-#endif
-#ifdef HAVE_CHECK_STACK_GROWTH
check_stack_growth((char *)&i);
-# ifdef HAVE_GETRLIMIT
+# ifdef HAVE_STACK_LIMIT
get_stack_limit();
# endif
@@ -3092,7 +3096,8 @@ check_mouse_termcode()
)
{
set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
- ? IF_EB("\233M", CSI_STR "M") : IF_EB("\033[M", ESC_STR "[M")));
+ ? IF_EB("\233M", CSI_STR "M")
+ : IF_EB("\033[M", ESC_STR "[M")));
if (*p_mouse != NUL)
{
/* force mouse off and maybe on to send possibly new mouse
@@ -3128,7 +3133,7 @@ check_mouse_termcode()
# endif
# ifdef FEAT_MOUSE_NET
- /* There is no conflict, but one may type ESC } from Insert mode. Don't
+ /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
* define it in the GUI or when using an xterm. */
if (!use_xterm_mouse()
# ifdef FEAT_GUI
@@ -3148,8 +3153,8 @@ check_mouse_termcode()
&& !gui.in_use
# endif
)
- set_mouse_termcode(KS_DEC_MOUSE,
- (char_u *)IF_EB("\033[", ESC_STR "["));
+ set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
+ ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
else
del_mouse_termcode(KS_DEC_MOUSE);
# endif
diff --git a/src/quickfix.c b/src/quickfix.c
index 8d76e2861..d9ce186cf 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -2418,6 +2418,7 @@ ex_vimgrep(eap)
else
{
found_match = FALSE;
+#if 0
#ifdef HAVE_SETJMP_H
/*
* Matching with a regexp may cause a very deep recursive call of
@@ -2437,6 +2438,7 @@ ex_vimgrep(eap)
goto jumpend;
}
#endif
+#endif
/* Try for a match in all lines of the buffer. */
for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
{
@@ -2475,10 +2477,12 @@ ex_vimgrep(eap)
if (got_int)
break;
}
+#if 0
#ifdef HAVE_SETJMP_H
jumpend:
mch_endjmp();
#endif
+#endif
if (using_dummy)
{
diff --git a/src/regexp.c b/src/regexp.c
index 36f5bb456..79d3e2a57 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -2962,8 +2962,6 @@ static int need_clear_zsubexpr = FALSE; /* extmatch subexpressions
* still need to be cleared */
#endif
-static int out_of_stack; /* TRUE when ran out of stack space */
-
/*
* Structure used to save the current input state, when it needs to be
* restored after trying a match. Used by reg_save() and reg_restore().
@@ -3013,7 +3011,7 @@ static void save_se_one __ARGS((save_se_T *savep, char_u **pp));
*(pp) = (savep)->se_u.ptr; }
static int re_num_cmp __ARGS((long_u val, char_u *scan));
-static int regmatch __ARGS((char_u *prog, regsave_T *startp));
+static int regmatch __ARGS((char_u *prog));
static int regrepeat __ARGS((char_u *p, long maxcount));
#ifdef DEBUG
@@ -3186,41 +3184,20 @@ vim_regexec_multi(rmp, win, buf, lnum, col)
return r;
}
-#if 0 /* this does not appear to work... */
-# ifdef __MINGW32__
-# define MINGW_TRY
+#if 0 /* disabled, no longer needed now that regmatch() is not recursive */
+# ifdef HAVE_SETJMP_H
+# define USE_SETJMP
+# endif
+# ifdef HAVE_TRY_EXCEPT
+# define USE_TRY_EXCEPT
# endif
-#endif
-
-#ifdef MINGW_TRY
-/*
- * Special assembly code for MingW to simulate __try / __except.
- * Does not work with the optimizer!
- */
-# include <excpt.h>
-
-static void *ESP_save; /* used as _ESP below */
-static void *EBP_save; /* used as _EBP below */
-
-__attribute__ ((cdecl))
- EXCEPTION_DISPOSITION
- _except_regexec_handler(
- struct _EXCEPTION_RECORD *ExceptionRecord,
- void *EstablisherFrame,
- struct _CONTEXT *ContextRecord,
- void *DispatcherContext)
-{
- __asm__ __volatile__ (
- "jmp regexec_reentry");
- return 0; /* Function does not return */
-}
#endif
/*
* Match a regexp against a string ("line" points to the string) or multiple
* lines ("line" is NULL, use reg_getline()).
*/
-#ifdef HAVE_SETJMP_H
+#ifdef USE_SETJMP
static long
vim_regexec_both(line_arg, col_arg)
char_u *line_arg;
@@ -3235,7 +3212,7 @@ vim_regexec_both(line, col)
regprog_T *prog;
char_u *s;
long retval;
-#ifdef HAVE_SETJMP_H
+#ifdef USE_SETJMP
char_u *line;
colnr_T col;
int did_mch_startjmp = FALSE;
@@ -3243,7 +3220,7 @@ vim_regexec_both(line, col)
reg_tofree = NULL;
-#ifdef HAVE_SETJMP_H
+#ifdef USE_SETJMP
/* Trick to avoid "might be clobbered by `longjmp'" warning from gcc. */
line = line_arg;
col = col_arg;
@@ -3335,23 +3312,12 @@ vim_regexec_both(line, col)
goto theend;
}
-#ifdef MINGW_TRY
- /* Ugly assembly code that is necessary to simulate "__try". */
- __asm__ __volatile__ (
- "movl %esp, _ESP_save" "\n\t"
- "movl %ebp, _EBP_save");
-
- __asm__ __volatile__ (
- "pushl $__except_regexec_handler" "\n\t"
- "pushl %fs:0" "\n\t"
- "mov %esp, %fs:0");
-#endif
-#ifdef HAVE_TRY_EXCEPT
+#ifdef USE_TRY_EXCEPT
__try
{
#endif
-#ifdef HAVE_SETJMP_H
+#ifdef USE_SETJMP
/*
* Matching with a regexp may cause a very deep recursive call of
* regmatch(). Vim will crash when running out of stack space. Catch
@@ -3378,7 +3344,6 @@ vim_regexec_both(line, col)
regline = line;
reglnum = 0;
- out_of_stack = FALSE;
/* Simplest case: Anchored match need be tried only once. */
if (prog->reganch)
@@ -3406,7 +3371,7 @@ vim_regexec_both(line, col)
else
{
/* Messy cases: unanchored match. */
- while (!got_int && !out_of_stack)
+ while (!got_int)
{
if (prog->regstart != NUL)
{
@@ -3449,15 +3414,12 @@ vim_regexec_both(line, col)
}
}
- if (out_of_stack)
- EMSG(_(e_outofstack));
-
-#ifdef HAVE_SETJMP_H
+#ifdef USE_SETJMP
inner_end:
if (did_mch_startjmp)
mch_endjmp();
#endif
-#ifdef HAVE_TRY_EXCEPT
+#ifdef USE_TRY_EXCEPT
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
@@ -3471,22 +3433,6 @@ inner_end:
retval = 0L;
}
#endif
-#ifdef MINGW_TRY
- __asm__ __volatile__ (
- "jmp regexec_pop" "\n"
- "regexec_reentry:" "\n\t"
- "movl _ESP_save, %esp" "\n\t"
- "movl _EBP_save, %ebp");
-
- EMSG(_(e_complex));
- retval = 0L;
-
- __asm__ __volatile__ (
- "regexec_pop:" "\n\t"
- "mov (%esp), %eax" "\n\t"
- "mov %eax, %fs:0" "\n\t"
- "add $8, %esp");
-#endif
theend:
/* Didn't find a match. */
@@ -3559,7 +3505,7 @@ regtry(prog, col)
need_clear_zsubexpr = TRUE;
#endif
- if (regmatch(prog->program + 1, NULL))
+ if (regmatch(prog->program + 1))
{
cleanup_subexpr();
if (REG_MULTI)
@@ -3649,15 +3595,75 @@ reg_prev_class()
static long bl_minval;
static long bl_maxval;
+/* Values for rs_state. */
+typedef enum regstate_E
+{
+ RS_NOPEN = 0 /* NOPEN and NCLOSE */
+ , RS_MOPEN /* MOPEN + [0-9] */
+ , RS_MCLOSE /* MCLOSE + [0-9] */
+#ifdef FEAT_SYN_HL
+ , RS_ZOPEN /* ZOPEN + [0-9] */
+ , RS_ZCLOSE /* ZCLOSE + [0-9] */
+#endif
+ , RS_BRANCH /* BRANCH */
+ , RS_BRCPLX_MORE /* BRACE_COMPLEX and trying one more match */
+ , RS_BRCPLX_LONG /* BRACE_COMPLEX and trying longest match */
+ , RS_BRCPLX_SHORT /* BRACE_COMPLEX and trying shortest match */
+ , RS_NOMATCH /* NOMATCH */
+ , RS_BEHIND1 /* BEHIND / NOBEHIND matching rest */
+ , RS_BEHIND2 /* BEHIND / NOBEHIND matching behind part */
+ , RS_STAR_LONG /* STAR/PLUS/BRACE_SIMPLE longest match */
+ , RS_STAR_SHORT /* STAR/PLUS/BRACE_SIMPLE shortest match */
+} regstate_T;
+
+/*
+ * When there are alternatives a regstate_T is put on the regstack to remember
+ * what we are doing.
+ * Before it may be another type of item, depending on rs_state, to remember
+ * more things.
+ */
+typedef struct regitem_S
+{
+ regstate_T rs_state; /* what we are doing, on of RS_ below */
+ char_u *rs_scan; /* current node in program */
+ long rs_startp; /* start position for BACK (offset) */
+ union
+ {
+ save_se_T sesave;
+ regsave_T regsave;
+ } rs_un; /* room for saving reginput */
+ short rs_no; /* submatch nr */
+} regitem_T;
+
+static regitem_T *regstack_push __ARGS((garray_T *regstack, regstate_T state, char_u *scan, long startp));
+static void regstack_pop __ARGS((garray_T *regstack, char_u **scan, long *startp));
+
+/* used for BEHIND and NOBEHIND matching */
+typedef struct regbehind_S
+{
+ regsave_T save_after;
+ regsave_T save_behind;
+} regbehind_T;
+
+/* used for STAR, PLUS and BRACE_SIMPLE matching */
+typedef struct regstar_S
+{
+ int nextb; /* next byte */
+ int nextb_ic; /* next byte reverse case */
+ long count;
+ long minval;
+ long maxval;
+} regstar_T;
+
/*
* regmatch - main matching routine
*
- * Conceptually the strategy is simple: Check to see whether the current
- * node matches, call self recursively to see whether the rest matches,
- * and then act accordingly. In practice we make some effort to avoid
- * recursion, in particular by going through "ordinary" nodes (that don't
- * need to know whether the rest of the match failed) by a loop instead of
- * by recursion.
+ * Conceptually the strategy is simple: Check to see whether the current node
+ * matches, push an item onto the regstack and loop to see whether the rest
+ * matches, and then act accordingly. In practice we make some effort to
+ * avoid using the regstack, in particular by going through "ordinary" nodes
+ * (that don't need to know whether the rest of the match failed) by a nested
+ * loop.
*
* Returns TRUE when there is a match. Leaves reginput and reglnum just after
* the last matched character.
@@ -3665,24 +3671,36 @@ static long bl_maxval;
* undefined state!
*/
static int
-regmatch(scan, startp)
+regmatch(scan)
char_u *scan; /* Current node. */
- regsave_T *startp; /* start position for BACK */
{
- char_u *next; /* Next node. */
- int op;
- int c;
-
-#ifdef HAVE_GETRLIMIT
- /* Check if we are running out of stack space. Could be caused by
- * recursively calling ourselves. */
- if (out_of_stack || mch_stackcheck((char *)&op) == FAIL)
- {
- out_of_stack = TRUE;
- return FALSE;
- }
-#endif
-
+ char_u *next; /* Next node. */
+ int op;
+ int c;
+ garray_T regstack;
+ regitem_T *rp;
+ int no;
+ int status; /* one of the RA_ values: */
+#define RA_FAIL 1 /* something failed, abort */
+#define RA_CONT 2 /* continue in inner loop */
+#define RA_BREAK 3 /* break inner loop */
+#define RA_MATCH 4 /* successful match */
+#define RA_NOMATCH 5 /* didn't match */
+ long startp = 0; /* start position for BACK, offset to
+ regstack.ga_data */
+#define STARTP2REGS(startp) (regsave_T *)(((char *)regstack.ga_data) + startp)
+#define REGS2STARTP(p) (long)((char *)p - (char *)regstack.ga_data)
+
+ /* Init the regstack empty. Use an item size of 1 byte, since we push
+ * different things onto it. Use a large grow size to avoid reallocating
+ * it too often. */
+ ga_init2(&regstack, 1, 10000);
+
+ /*
+ * Repeat until the stack is empty.
+ */
+ for (;;)
+ {
/* Some patterns my cause a long time to match, even though they are not
* illegal. E.g., "\([a-z]\+\)\+Q". Allow breaking them with CTRL-C. */
fast_breakcheck();
@@ -3694,10 +3712,20 @@ regmatch(scan, startp)
mch_errmsg("(\n");
}
#endif
- while (scan != NULL)
+
+ /*
+ * Repeat for items that can be matched sequential, without using the
+ * regstack.
+ */
+ for (;;)
{
- if (got_int || out_of_stack)
- return FALSE;
+ if (got_int || scan == NULL)
+ {
+ status = RA_FAIL;
+ break;
+ }
+ status = RA_CONT;
+
#ifdef DEBUG
if (regnarrate)
{
@@ -3735,7 +3763,7 @@ regmatch(scan, startp)
else
{
if (WITH_NL(op))
- op -= ADD_NL;
+ op -= ADD_NL;
#ifdef FEAT_MBYTE
if (has_mbyte)
c = (*mb_ptr2char)(reginput);
@@ -3746,12 +3774,12 @@ regmatch(scan, startp)
{
case BOL:
if (reginput != regline)
- return FALSE;
+ status = RA_NOMATCH;
break;
case EOL:
if (c != NUL)
- return FALSE;
+ status = RA_NOMATCH;
break;
case RE_BOF:
@@ -3760,12 +3788,12 @@ regmatch(scan, startp)
* line of the file. */
if (reglnum != 0 || reginput != regline
|| (REG_MULTI && reg_getline((linenr_T)-1) != NULL))
- return FALSE;
+ status = RA_NOMATCH;
break;
case RE_EOF:
if (reglnum != reg_maxline || c != NUL)
- return FALSE;
+ status = RA_NOMATCH;
break;
case CURSOR:
@@ -3774,237 +3802,262 @@ regmatch(scan, startp)
if (reg_win == NULL
|| (reglnum + reg_firstlnum != reg_win->w_cursor.lnum)
|| ((colnr_T)(reginput - regline) != reg_win->w_cursor.col))
- return FALSE;
+ status = RA_NOMATCH;
break;
case RE_LNUM:
if (!REG_MULTI || !re_num_cmp((long_u)(reglnum + reg_firstlnum),
scan))
- return FALSE;
+ status = RA_NOMATCH;
break;
case RE_COL:
if (!re_num_cmp((long_u)(reginput - regline) + 1, scan))
- return FALSE;
+ status = RA_NOMATCH;
break;
case RE_VCOL:
if (!re_num_cmp((long_u)win_linetabsize(
reg_win == NULL ? curwin : reg_win,
regline, (colnr_T)(reginput - regline)) + 1, scan))
- return FALSE;
+ status = RA_NOMATCH;
break;
case BOW: /* \<word; reginput points to w */
if (c == NUL) /* Can't match at end of line */
- return FALSE;
+ status = RA_NOMATCH;
#ifdef FEAT_MBYTE
- if (has_mbyte)
+ else if (has_mbyte)
{
int this_class;
/* Get class of current and previous char (if it exists). */
this_class = mb_get_class(reginput);
if (this_class <= 1)
- return FALSE; /* not on a word at all */
- if (reg_prev_class() == this_class)
- return FALSE; /* previous char is in same word */
+ status = RA_NOMATCH; /* not on a word at all */
+ else if (reg_prev_class() == this_class)
+ status = RA_NOMATCH; /* previous char is in same word */
}
#endif
else
{
if (!vim_iswordc(c)
|| (reginput > regline && vim_iswordc(reginput[-1])))
- return FALSE;
+ status = RA_NOMATCH;
}
break;
case EOW: /* word\>; reginput points after d */
if (reginput == regline) /* Can't match at start of line */
- return FALSE;
+ status = RA_NOMATCH;
#ifdef FEAT_MBYTE
- if (has_mbyte)
+ else if (has_mbyte)
{
int this_class, prev_class;
/* Get class of current and previous char (if it exists). */
this_class = mb_get_class(reginput);
prev_class = reg_prev_class();
- if (this_class == prev_class)
- return FALSE;
- if (prev_class == 0 || prev_class == 1)
- return FALSE;
+ if (this_class == prev_class
+ || prev_class == 0 || prev_class == 1)
+ status = RA_NOMATCH;
}
- else
#endif
+ else
{
- if (!vim_iswordc(reginput[-1]))
- return FALSE;
- if (reginput[0] != NUL && vim_iswordc(c))
- return FALSE;
+ if (!vim_iswordc(reginput[-1])
+ || (reginput[0] != NUL && vim_iswordc(c)))
+ status = RA_NOMATCH;
}
break; /* Matched with EOW */
case ANY:
if (c == NUL)
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case IDENT:
if (!vim_isIDc(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case SIDENT:
if (VIM_ISDIGIT(*reginput) || !vim_isIDc(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case KWORD:
if (!vim_iswordp(reginput))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case SKWORD:
if (VIM_ISDIGIT(*reginput) || !vim_iswordp(reginput))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case FNAME:
if (!vim_isfilec(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case SFNAME:
if (VIM_ISDIGIT(*reginput) || !vim_isfilec(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case PRINT:
if (ptr2cells(reginput) != 1)
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case SPRINT:
if (VIM_ISDIGIT(*reginput) || ptr2cells(reginput) != 1)
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case WHITE:
if (!vim_iswhite(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NWHITE:
if (c == NUL || vim_iswhite(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case DIGIT:
if (!ri_digit(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NDIGIT:
if (c == NUL || ri_digit(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case HEX:
if (!ri_hex(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NHEX:
if (c == NUL || ri_hex(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case OCTAL:
if (!ri_octal(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NOCTAL:
if (c == NUL || ri_octal(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case WORD:
if (!ri_word(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NWORD:
if (c == NUL || ri_word(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case HEAD:
if (!ri_head(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NHEAD:
if (c == NUL || ri_head(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case ALPHA:
if (!ri_alpha(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NALPHA:
if (c == NUL || ri_alpha(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case LOWER:
if (!ri_lower(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NLOWER:
if (c == NUL || ri_lower(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case UPPER:
if (!ri_upper(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case NUPPER:
if (c == NUL || ri_upper(c))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
case EXACTLY:
@@ -4020,8 +4073,8 @@ regmatch(scan, startp)
!enc_utf8 &&
#endif
TOLOWER_LOC(*opnd) != TOLOWER_LOC(*reginput))))
- return FALSE;
- if (*opnd == NUL)
+ status = RA_NOMATCH;
+ else if (*opnd == NUL)
{
/* match empty string always works; happens when "~" is
* empty. */
@@ -4037,20 +4090,21 @@ regmatch(scan, startp)
len = (int)STRLEN(opnd);
/* Need to match first byte again for multi-byte. */
if (cstrncmp(opnd, reginput, &len) != 0)
- return FALSE;
+ status = RA_NOMATCH;
#ifdef FEAT_MBYTE
/* Check for following composing character. */
- if (enc_utf8 && UTF_COMPOSINGLIKE(reginput, reginput + len))
+ else if (enc_utf8
+ && UTF_COMPOSINGLIKE(reginput, reginput + len))
{
/* raaron: This code makes a composing character get
* ignored, which is the correct behavior (sometimes)
* for voweled Hebrew texts. */
if (!ireg_icombine)
- return FALSE;
+ status = RA_NOMATCH;
}
- else
#endif
- reginput += len;
+ else
+ reginput += len;
}
}
break;
@@ -4058,10 +4112,11 @@ regmatch(scan, startp)
case ANYOF:
case ANYBUT:
if (c == NUL)
- return FALSE;
- if ((cstrchr(OPERAND(scan), c) == NULL) == (op == ANYOF))
- return FALSE;
- ADVANCE_REGINPUT();
+ status = RA_NOMATCH;
+ else if ((cstrchr(OPERAND(scan), c) == NULL) == (op == ANYOF))
+ status = RA_NOMATCH;
+ else
+ ADVANCE_REGINPUT();
break;
#ifdef FEAT_MBYTE
@@ -4075,14 +4130,20 @@ regmatch(scan, startp)
/* Safety check (just in case 'encoding' was changed since
* compiling the program). */
if ((len = (*mb_ptr2len_check)(opnd)) < 2)
- return FALSE;
+ {
+ status = RA_NOMATCH;
+ break;
+ }
for (i = 0; i < len; ++i)
if (opnd[i] != reginput[i])
- return FALSE;
+ {
+ status = RA_NOMATCH;
+ break;
+ }
reginput += len;
}
else
- return FALSE;
+ status = RA_NOMATCH;
break;
#endif
@@ -4092,8 +4153,8 @@ regmatch(scan, startp)
case BACK:
/* When we run into BACK without matching something non-empty, we
* fail. */
- if (startp != NULL && reg_save_equal(startp))
- return FALSE;
+ if (startp != 0 && reg_save_equal(STARTP2REGS(startp)))
+ status = RA_NOMATCH;
break;
case BACKP:
@@ -4110,27 +4171,27 @@ regmatch(scan, startp)
case MOPEN + 8:
case MOPEN + 9:
{
- int no;
- save_se_T save;
-
no = op - MOPEN;
cleanup_subexpr();
- save_se(&save, &reg_startpos[no], &reg_startp[no]);
-
- if (regmatch(next, startp))
- return TRUE;
-
- restore_se(&save, &reg_startpos[no], &reg_startp[no]);
- return FALSE;
+ rp = regstack_push(&regstack, RS_MOPEN, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ {
+ rp->rs_no = no;
+ save_se(&rp->rs_un.sesave, &reg_startpos[no],
+ &reg_startp[no]);
+ /* We simply continue and handle the result when done. */
+ }
}
- /* break; Not Reached */
+ break;
case NOPEN: /* \%( */
case NCLOSE: /* \) after \%( */
- if (regmatch(next, startp))
- return TRUE;
- return FALSE;
- /* break; Not Reached */
+ if (regstack_push(&regstack, RS_NOPEN, scan, startp) == NULL)
+ status = RA_FAIL;
+ /* We simply continue and handle the result when done. */
+ break;
#ifdef FEAT_SYN_HL
case ZOPEN + 1:
@@ -4143,20 +4204,20 @@ regmatch(scan, startp)
case ZOPEN + 8:
case ZOPEN + 9:
{
- int no;
- save_se_T save;
-
no = op - ZOPEN;
cleanup_zsubexpr();
- save_se(&save, &reg_startzpos[no], &reg_startzp[no]);
-
- if (regmatch(next, startp))
- return TRUE;
-
- restore_se(&save, &reg_startzpos[no], &reg_startzp[no]);
- return FALSE;
+ rp = regstack_push(&regstack, RS_ZOPEN, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ {
+ rp->rs_no = no;
+ save_se(&rp->rs_un.sesave, &reg_startzpos[no],
+ &reg_startzp[no]);
+ /* We simply continue and handle the result when done. */
+ }
}
- /* break; Not Reached */
+ break;
#endif
case MCLOSE + 0: /* Match end: \ze */
@@ -4170,20 +4231,19 @@ regmatch(scan, startp)
case MCLOSE + 8:
case MCLOSE + 9:
{
- int no;
- save_se_T save;
-
no = op - MCLOSE;
cleanup_subexpr();
- save_se(&save, &reg_endpos[no], &reg_endp[no]);
-
- if (regmatch(next, startp))
- return TRUE;
-
- restore_se(&save, &reg_endpos[no], &reg_endp[no]);
- return FALSE;
+ rp = regstack_push(&regstack, RS_MCLOSE, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ {
+ rp->rs_no = no;
+ save_se(&rp->rs_un.sesave, &reg_endpos[no], &reg_endp[no]);
+ /* We simply continue and handle the result when done. */
+ }
}
- /* break; Not Reached */
+ break;
#ifdef FEAT_SYN_HL
case ZCLOSE + 1: /* \) after \z( */
@@ -4196,20 +4256,20 @@ regmatch(scan, startp)
case ZCLOSE + 8:
case ZCLOSE + 9:
{
- int no;
- save_se_T save;
-
no = op - ZCLOSE;
cleanup_zsubexpr();
- save_se(&save, &reg_endzpos[no], &reg_endzp[no]);
-
- if (regmatch(next, startp))
- return TRUE;
-
- restore_se(&save, &reg_endzpos[no], &reg_endzp[no]);
- return FALSE;
+ rp = regstack_push(&regstack, RS_ZCLOSE, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ {
+ rp->rs_no = no;
+ save_se(&rp->rs_un.sesave, &reg_endzpos[no],
+ &reg_endzp[no]);
+ /* We simply continue and handle the result when done. */
+ }
}
- /* break; Not Reached */
+ break;
#endif
case BACKREF + 1:
@@ -4222,7 +4282,6 @@ regmatch(scan, startp)
case BACKREF + 8:
case BACKREF + 9:
{
- int no;
int len;
linenr_T clnum;
colnr_T ccol;
@@ -4243,7 +4302,7 @@ regmatch(scan, startp)
* line. */
len = (int)(reg_endp[no] - reg_startp[no]);
if (cstrncmp(reg_startp[no], reginput, &len) != 0)
- return FALSE;
+ status = RA_NOMATCH;
}
}
else /* Multi-line regexp */
@@ -4262,7 +4321,7 @@ regmatch(scan, startp)
len = reg_endpos[no].col - reg_startpos[no].col;
if (cstrncmp(regline + reg_startpos[no].col,
reginput, &len) != 0)
- return FALSE;
+ status = RA_NOMATCH;
}
else
{
@@ -4284,7 +4343,10 @@ regmatch(scan, startp)
vim_free(reg_tofree);
reg_tofree = alloc(len);
if (reg_tofree == NULL)
- return FALSE; /* out of memory! */
+ {
+ status = RA_FAIL; /* outof memory!*/
+ break;
+ }
reg_tofreelen = len;
}
STRCPY(reg_tofree, regline);
@@ -4301,18 +4363,27 @@ regmatch(scan, startp)
len = (int)STRLEN(p + ccol);
if (cstrncmp(p + ccol, reginput, &len) != 0)
- return FALSE; /* doesn't match */
+ {
+ status = RA_NOMATCH; /* doesn't match */
+ break;
+ }
if (clnum == reg_endpos[no].lnum)
break; /* match and at end! */
if (reglnum == reg_maxline)
- return FALSE; /* text too short */
+ {
+ status = RA_NOMATCH; /* text too short */
+ break;
+ }
/* Advance to next line. */
reg_nextline();
++clnum;
ccol = 0;
- if (got_int || out_of_stack)
- return FALSE;
+ if (got_int)
+ {
+ status = RA_FAIL;
+ break;
+ }
}
/* found a match! Note that regline may now point
@@ -4337,7 +4408,6 @@ regmatch(scan, startp)
case ZREF + 8:
case ZREF + 9:
{
- int no;
int len;
cleanup_zsubexpr();
@@ -4348,8 +4418,9 @@ regmatch(scan, startp)
len = (int)STRLEN(re_extmatch_in->matches[no]);
if (cstrncmp(re_extmatch_in->matches[no],
reginput, &len) != 0)
- return FALSE;
- reginput += len;
+ status = RA_NOMATCH;
+ else
+ reginput += len;
}
else
{
@@ -4363,32 +4434,23 @@ regmatch(scan, startp)
{
if (OP(next) != BRANCH) /* No choice. */
next = OPERAND(scan); /* Avoid recursion. */
- else if (startp != NULL && OP(OPERAND(scan)) == BACKP
- && reg_save_equal(startp))
+ else if (startp != 0 && OP(OPERAND(scan)) == BACKP
+ && reg_save_equal(STARTP2REGS(startp)))
/* \+ with something empty before it */
- return FALSE;
+ status = RA_NOMATCH;
else
{
- regsave_T save;
-
- do
- {
- reg_save(&save);
- if (regmatch(OPERAND(scan), &save))
- return TRUE;
- reg_restore(&save);
- scan = regnext(scan);
- } while (scan != NULL && OP(scan) == BRANCH);
- return FALSE;
- /* NOTREACHED */
+ rp = regstack_push(&regstack, RS_BRANCH, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ status = RA_BREAK; /* rest is below */
}
}
break;
case BRACE_LIMITS:
{
- int no;
-
if (OP(next) == BRACE_SIMPLE)
{
bl_minval = OPERAND_MIN(scan);
@@ -4405,7 +4467,7 @@ regmatch(scan, startp)
else
{
EMSG(_(e_internal)); /* Shouldn't happen */
- return FALSE;
+ status = RA_FAIL;
}
}
break;
@@ -4421,22 +4483,25 @@ regmatch(scan, startp)
case BRACE_COMPLEX + 8:
case BRACE_COMPLEX + 9:
{
- int no;
- regsave_T save;
-
no = op - BRACE_COMPLEX;
++brace_count[no];
/* If not matched enough times yet, try one more */
if (brace_count[no] <= (brace_min[no] <= brace_max[no]
- ? brace_min[no] : brace_max[no]))
+ ? brace_min[no] : brace_max[no]))
{
- reg_save(&save);
- if (regmatch(OPERAND(scan), &save))
- return TRUE;
- reg_restore(&save);
- --brace_count[no]; /* failed, decrement match count */
- return FALSE;
+ rp = regstack_push(&regstack, RS_BRCPLX_MORE, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ {
+ rp->rs_no = no;
+ reg_save(&rp->rs_un.regsave);
+ startp = REGS2STARTP(&rp->rs_un.regsave);
+ next = OPERAND(scan);
+ /* We continue and handle the result when done. */
+ }
+ break;
}
/* If matched enough times, may try matching some more */
@@ -4445,12 +4510,18 @@ regmatch(scan, startp)
/* Range is the normal way around, use longest match */
if (brace_count[no] <= brace_max[no])
{
- reg_save(&save);
- if (regmatch(OPERAND(scan), &save))
- return TRUE; /* matched some more times */
- reg_restore(&save);
- --brace_count[no]; /* matched just enough times */
- /* { continue with the items after \{} */
+ rp = regstack_push(&regstack, RS_BRCPLX_LONG,
+ scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ {
+ rp->rs_no = no;
+ reg_save(&rp->rs_un.regsave);
+ startp = REGS2STARTP(&rp->rs_un.regsave);
+ next = OPERAND(scan);
+ /* We continue and handle the result when done. */
+ }
}
}
else
@@ -4458,12 +4529,16 @@ regmatch(scan, startp)
/* Range is backwards, use shortest match first */
if (brace_count[no] <= brace_min[no])
{
- reg_save(&save);
- if (regmatch(next, &save))
- return TRUE;
- reg_restore(&save);
- next = OPERAND(scan);
- /* must try to match one more item */
+ rp = regstack_push(&regstack, RS_BRCPLX_SHORT,
+ scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
+ {
+ reg_save(&rp->rs_un.regsave);
+ startp = REGS2STARTP(&rp->rs_un.regsave);
+ /* We continue and handle the result when done. */
+ }
}
}
}
@@ -4473,12 +4548,7 @@ regmatch(scan, startp)
case STAR:
case PLUS:
{
- int nextb; /* next byte */
- int nextb_ic; /* next byte reverse case */
- long count;
- regsave_T save;
- long minval;
- long maxval;
+ regstar_T rst;
/*
* Lookahead to avoid useless match attempts when we know
@@ -4486,31 +4556,31 @@ regmatch(scan, startp)
*/
if (OP(next) == EXACTLY)
{
- nextb = *OPERAND(next);
+ rst.nextb = *OPERAND(next);
if (ireg_ic)
{
- if (isupper(nextb))
- nextb_ic = TOLOWER_LOC(nextb);
+ if (isupper(rst.nextb))
+ rst.nextb_ic = TOLOWER_LOC(rst.nextb);
else
- nextb_ic = TOUPPER_LOC(nextb);
+ rst.nextb_ic = TOUPPER_LOC(rst.nextb);
}
else
- nextb_ic = nextb;
+ rst.nextb_ic = rst.nextb;
}
else
{
- nextb = NUL;
- nextb_ic = NUL;
+ rst.nextb = NUL;
+ rst.nextb_ic = NUL;
}
if (op != BRACE_SIMPLE)
{
- minval = (op == STAR) ? 0 : 1;
- maxval = MAX_LIMIT;
+ rst.minval = (op == STAR) ? 0 : 1;
+ rst.maxval = MAX_LIMIT;
}
else
{
- minval = bl_minval;
- maxval = bl_maxval;
+ rst.minval = bl_minval;
+ rst.maxval = bl_maxval;
}
/*
@@ -4519,228 +4589,516 @@ regmatch(scan, startp)
* minimal number (since the range is backwards, that's also
* maxval!).
*/
- count = regrepeat(OPERAND(scan), maxval);
+ rst.count = regrepeat(OPERAND(scan), rst.maxval);
if (got_int)
- return FALSE;
- if (minval <= maxval)
{
- /* Range is the normal way around, use longest match */
- while (count >= minval)
- {
- /* If it could match, try it. */
- if (nextb == NUL || *reginput == nextb
- || *reginput == nextb_ic)
- {
- reg_save(&save);
- if (regmatch(next, startp))
- return TRUE;
- reg_restore(&save);
- }
- /* Couldn't or didn't match -- back up one char. */
- if (--count < minval)
- break;
- if (reginput == regline)
- {
- /* backup to last char of previous line */
- --reglnum;
- regline = reg_getline(reglnum);
- /* Just in case regrepeat() didn't count right. */
- if (regline == NULL)
- return FALSE;
- reginput = regline + STRLEN(regline);
- fast_breakcheck();
- if (got_int || out_of_stack)
- return FALSE;
- }
- else
- mb_ptr_back(regline, reginput);
- }
+ status = RA_FAIL;
+ break;
}
- else
+ if (rst.minval <= rst.maxval
+ ? rst.count >= rst.minval : rst.count >= rst.maxval)
{
- /* Range is backwards, use shortest match first.
- * Careful: maxval and minval are exchanged! */
- if (count < maxval)
- return FALSE;
- for (;;)
+ /* It could match. Prepare for trying to match what
+ * follows. The code is below. Parameters are stored in
+ * a regstar_T on the regstack. */
+ if (ga_grow(&regstack, sizeof(regstar_T)) == FAIL)
+ status = RA_FAIL;
+ else
{
- /* If it could work, try it. */
- if (nextb == NUL || *reginput == nextb
- || *reginput == nextb_ic)
+ regstack.ga_len += sizeof(regstar_T);
+ rp = regstack_push(&regstack, rst.minval <= rst.maxval
+ ? RS_STAR_LONG : RS_STAR_SHORT, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
{
- reg_save(&save);
- if (regmatch(next, &save))
- return TRUE;
- reg_restore(&save);
+ *(((regstar_T *)rp) - 1) = rst;
+ status = RA_BREAK; /* skip the restore bits */
}
- /* Couldn't or didn't match: try advancing one char. */
- if (count == minval
- || regrepeat(OPERAND(scan), 1L) == 0)
- break;
- ++count;
- if (got_int || out_of_stack)
- return FALSE;
}
}
- return FALSE;
- }
- /* break; Not Reached */
+ else
+ status = RA_NOMATCH;
- case NOMATCH:
- {
- regsave_T save;
-
- /* If the operand matches, we fail. Otherwise backup and
- * continue with the next item. */
- reg_save(&save);
- if (regmatch(OPERAND(scan), startp))
- return FALSE;
- reg_restore(&save);
}
break;
+ case NOMATCH:
case MATCH:
case SUBPAT:
+ rp = regstack_push(&regstack, RS_NOMATCH, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
{
- regsave_T save;
-
- /* If the operand doesn't match, we fail. Otherwise backup
- * and continue with the next item. */
- reg_save(&save);
- if (!regmatch(OPERAND(scan), startp))
- return FALSE;
- if (op == MATCH) /* zero-width */
- reg_restore(&save);
+ rp->rs_no = op;
+ reg_save(&rp->rs_un.regsave);
+ next = OPERAND(scan);
+ /* We continue and handle the result when done. */
}
break;
case BEHIND:
case NOBEHIND:
+ /* Need a bit of room to store extra positions. */
+ if (ga_grow(&regstack, sizeof(regbehind_T)) == FAIL)
+ status = RA_FAIL;
+ else
{
- regsave_T save_after, save_start;
- regsave_T save_behind_pos;
- int needmatch = (op == BEHIND);
-
- /*
- * Look back in the input of the operand matches or not. This
- * must be done at every position in the input and checking if
- * the match ends at the current position.
- * First check if the next item matches, that's probably
- * faster.
- */
- reg_save(&save_start);
- if (regmatch(next, startp))
+ regstack.ga_len += sizeof(regbehind_T);
+ rp = regstack_push(&regstack, RS_BEHIND1, scan, startp);
+ if (rp == NULL)
+ status = RA_FAIL;
+ else
{
- /* save the position after the found match for next */
- reg_save(&save_after);
-
- /* start looking for a match with operand at the current
- * postion. Go back one character until we find the
- * result, hitting the start of the line or the previous
- * line (for multi-line matching).
- * Set behind_pos to where the match should end, BHPOS
- * will match it. */
- save_behind_pos = behind_pos;
- behind_pos = save_start;
- for (;;)
- {
- reg_restore(&save_start);
- if (regmatch(OPERAND(scan), startp)
- && reg_save_equal(&behind_pos))
- {
- behind_pos = save_behind_pos;
- /* found a match that ends where "next" started */
- if (needmatch)
- {
- reg_restore(&save_after);
- return TRUE;
- }
- return FALSE;
- }
- /*
- * No match: Go back one character. May go to
- * previous line once.
- */
- if (REG_MULTI)
- {
- if (save_start.rs_u.pos.col == 0)
- {
- if (save_start.rs_u.pos.lnum
- < behind_pos.rs_u.pos.lnum
- || reg_getline(
- --save_start.rs_u.pos.lnum) == NULL)
- break;
- reg_restore(&save_start);
- save_start.rs_u.pos.col =
- (colnr_T)STRLEN(regline);
- }
- else
- --save_start.rs_u.pos.col;
- }
- else
- {
- if (save_start.rs_u.ptr == regline)
- break;
- --save_start.rs_u.ptr;
- }
- }
-
- /* NOBEHIND succeeds when no match was found */
- behind_pos = save_behind_pos;
- if (!needmatch)
- {
- reg_restore(&save_after);
- return TRUE;
- }
+ rp->rs_no = op;
+ reg_save(&rp->rs_un.regsave);
+ /* First try if what follows matches. If it does then we
+ * check the behind match by looping. */
}
- return FALSE;
}
+ break;
case BHPOS:
if (REG_MULTI)
{
if (behind_pos.rs_u.pos.col != (colnr_T)(reginput - regline)
|| behind_pos.rs_u.pos.lnum != reglnum)
- return FALSE;
+ status = RA_NOMATCH;
}
else if (behind_pos.rs_u.ptr != reginput)
- return FALSE;
+ status = RA_NOMATCH;
break;
case NEWL:
if ((c != NUL || reglnum == reg_maxline)
&& (c != '\n' || !reg_line_lbr))
- return FALSE;
- if (reg_line_lbr)
+ status = RA_NOMATCH;
+ else if (reg_line_lbr)
ADVANCE_REGINPUT();
else
reg_nextline();
break;
case END:
- return TRUE; /* Success! */
+ status = RA_MATCH; /* Success! */
+ break;
default:
EMSG(_(e_re_corr));
#ifdef DEBUG
printf("Illegal op code %d\n", op);
#endif
- return FALSE;
+ status = RA_FAIL;
+ break;
}
}
+ /* If we can't continue sequentially, break the inner loop. */
+ if (status != RA_CONT)
+ break;
+
+ /* Continue in inner loop, advance to next item. */
scan = next;
+
+ } /* end of inner loop */
+
+ /*
+ * If there is something on the regstack execute the code for the state.
+ * If the state is popped then loop.
+ */
+ while (regstack.ga_len > 0 && status != RA_FAIL)
+ {
+ rp = (regitem_T *)((char *)regstack.ga_data + regstack.ga_len) - 1;
+ switch (rp->rs_state)
+ {
+ case RS_NOPEN:
+ /* Result is passed on as-is, simply pop the state. */
+ regstack_pop(&regstack, &scan, &startp);
+ break;
+
+ case RS_MOPEN:
+ /* Pop the state. Restore pointers when there is no match. */
+ if (status == RA_NOMATCH)
+ restore_se(&rp->rs_un.sesave, &reg_startpos[rp->rs_no],
+ &reg_startp[rp->rs_no]);
+ regstack_pop(&regstack, &scan, &startp);
+ break;
+
+#ifdef FEAT_SYN_HL
+ case RS_ZOPEN:
+ /* Pop the state. Restore pointers when there is no match. */
+ if (status == RA_NOMATCH)
+ restore_se(&rp->rs_un.sesave, &reg_startzpos[rp->rs_no],
+ &reg_startzp[rp->rs_no]);
+ regstack_pop(&regstack, &scan, &startp);
+ break;
+#endif
+
+ case RS_MCLOSE:
+ /* Pop the state. Restore pointers when there is no match. */
+ if (status == RA_NOMATCH)
+ restore_se(&rp->rs_un.sesave, &reg_endpos[rp->rs_no],
+ &reg_endp[rp->rs_no]);
+ regstack_pop(&regstack, &scan, &startp);
+ break;
+
+#ifdef FEAT_SYN_HL
+ case RS_ZCLOSE:
+ /* Pop the state. Restore pointers when there is no match. */
+ if (status == RA_NOMATCH)
+ restore_se(&rp->rs_un.sesave, &reg_endzpos[rp->rs_no],
+ &reg_endzp[rp->rs_no]);
+ regstack_pop(&regstack, &scan, &startp);
+ break;
+#endif
+
+ case RS_BRANCH:
+ if (status == RA_MATCH)
+ /* this branch matched, use it */
+ regstack_pop(&regstack, &scan, &startp);
+ else
+ {
+ if (status != RA_BREAK)
+ {
+ /* After a non-matching branch: try next one. */
+ reg_restore(&rp->rs_un.regsave);
+ scan = rp->rs_scan;
+ }
+ if (scan == NULL || OP(scan) != BRANCH)
+ {
+ /* no more branches, didn't find a match */
+ status = RA_NOMATCH;
+ regstack_pop(&regstack, &scan, &startp);
+ }
+ else
+ {
+ /* Prepare to try a branch. */
+ rp->rs_scan = regnext(scan);
+ reg_save(&rp->rs_un.regsave);
+ startp = REGS2STARTP(&rp->rs_un.regsave);
+ scan = OPERAND(scan);
+ }
+ }
+ break;
+
+ case RS_BRCPLX_MORE:
+ /* Pop the state. Restore pointers when there is no match. */
+ if (status == RA_NOMATCH)
+ {
+ reg_restore(&rp->rs_un.regsave);
+ --brace_count[rp->rs_no]; /* decrement match count */
+ }
+ regstack_pop(&regstack, &scan, &startp);
+ break;
+
+ case RS_BRCPLX_LONG:
+ /* Pop the state. Restore pointers when there is no match. */
+ if (status == RA_NOMATCH)
+ {
+ /* There was no match, but we did find enough matches. */
+ reg_restore(&rp->rs_un.regsave);
+ --brace_count[rp->rs_no];
+ /* continue with the items after "\{}" */
+ status = RA_CONT;
+ }
+ regstack_pop(&regstack, &scan, &startp);
+ if (status == RA_CONT)
+ scan = regnext(scan);
+ break;
+
+ case RS_BRCPLX_SHORT:
+ /* Pop the state. Restore pointers when there is no match. */
+ if (status == RA_NOMATCH)
+ /* There was no match, try to match one more item. */
+ reg_restore(&rp->rs_un.regsave);
+ regstack_pop(&regstack, &scan, &startp);
+ if (status == RA_NOMATCH)
+ {
+ scan = OPERAND(scan);
+ status = RA_CONT;
+ }
+ break;
+
+ case RS_NOMATCH:
+ /* Pop the state. If the operand matches for NOMATCH or
+ * doesn't match for MATCH/SUBPAT, we fail. Otherwise backup,
+ * except for SUBPAT, and continue with the next item. */
+ if (status == (rp->rs_no == NOMATCH ? RA_MATCH : RA_NOMATCH))
+ status = RA_NOMATCH;
+ else
+ {
+ status = RA_CONT;
+ if (rp->rs_no != SUBPAT)
+ reg_restore(&rp->rs_un.regsave); /* zero-width */
+ }
+ regstack_pop(&regstack, &scan, &startp);
+ if (status == RA_CONT)
+ scan = regnext(scan);
+ break;
+
+ case RS_BEHIND1:
+ if (status == RA_NOMATCH)
+ {
+ regstack_pop(&regstack, &scan, &startp);
+ regstack.ga_len -= sizeof(regbehind_T);
+ }
+ else
+ {
+ /* The stuff after BEHIND/NOBEHIND matches. Now try if
+ * the behind part does (not) match before the current
+ * position in the input. This must be done at every
+ * position in the input and checking if the match ends at
+ * the current position. */
+
+ /* save the position after the found match for next */
+ reg_save(&(((regbehind_T *)rp) - 1)->save_after);
+
+ /* start looking for a match with operand at the current
+ * postion. Go back one character until we find the
+ * result, hitting the start of the line or the previous
+ * line (for multi-line matching).
+ * Set behind_pos to where the match should end, BHPOS
+ * will match it. Save the current value. */
+ (((regbehind_T *)rp) - 1)->save_behind = behind_pos;
+ behind_pos = rp->rs_un.regsave;
+
+ rp->rs_state = RS_BEHIND2;
+
+ reg_restore(&rp->rs_un.regsave);
+ scan = OPERAND(rp->rs_scan);
+ }
+ break;
+
+ case RS_BEHIND2:
+ /*
+ * Looping for BEHIND / NOBEHIND match.
+ */
+ if (status == RA_MATCH && reg_save_equal(&behind_pos))
+ {
+ /* found a match that ends where "next" started */
+ behind_pos = (((regbehind_T *)rp) - 1)->save_behind;
+ if (rp->rs_no == BEHIND)
+ reg_restore(&(((regbehind_T *)rp) - 1)->save_after);
+ else
+ /* But we didn't want a match. */
+ status = RA_NOMATCH;
+ regstack_pop(&regstack, &scan, &startp);
+ regstack.ga_len -= sizeof(regbehind_T);
+ }
+ else
+ {
+ /* No match: Go back one character. May go to previous
+ * line once. */
+ no = OK;
+ if (REG_MULTI)
+ {
+ if (rp->rs_un.regsave.rs_u.pos.col == 0)
+ {
+ if (rp->rs_un.regsave.rs_u.pos.lnum
+ < behind_pos.rs_u.pos.lnum
+ || reg_getline(
+ --rp->rs_un.regsave.rs_u.pos.lnum)
+ == NULL)
+ no = FAIL;
+ else
+ {
+ reg_restore(&rp->rs_un.regsave);
+ rp->rs_un.regsave.rs_u.pos.col =
+ (colnr_T)STRLEN(regline);
+ }
+ }
+ else
+ --rp->rs_un.regsave.rs_u.pos.col;
+ }
+ else
+ {
+ if (rp->rs_un.regsave.rs_u.ptr == regline)
+ no = FAIL;
+ else
+ --rp->rs_un.regsave.rs_u.ptr;
+ }
+ if (no == OK)
+ {
+ /* Advanced, prepare for finding match again. */
+ reg_restore(&rp->rs_un.regsave);
+ scan = OPERAND(rp->rs_scan);
+ }
+ else
+ {
+ /* Can't advance. For NOBEHIND that's a match. */
+ behind_pos = (((regbehind_T *)rp) - 1)->save_behind;
+ if (rp->rs_no == NOBEHIND)
+ {
+ reg_restore(&(((regbehind_T *)rp) - 1)->save_after);
+ status = RA_MATCH;
+ }
+ else
+ status = RA_NOMATCH;
+ regstack_pop(&regstack, &scan, &startp);
+ regstack.ga_len -= sizeof(regbehind_T);
+ }
+ }
+ break;
+
+ case RS_STAR_LONG:
+ case RS_STAR_SHORT:
+ {
+ regstar_T *rst = ((regstar_T *)rp) - 1;
+
+ if (status == RA_MATCH)
+ {
+ regstack_pop(&regstack, &scan, &startp);
+ regstack.ga_len -= sizeof(regstar_T);
+ break;
+ }
+
+ /* Tried once already, restore input pointers. */
+ if (status != RA_BREAK)
+ reg_restore(&rp->rs_un.regsave);
+
+ /* Repeat until we found a position where it could match. */
+ for (;;)
+ {
+ if (status != RA_BREAK)
+ {
+ /* Tried first position already, advance. */
+ if (rp->rs_state == RS_STAR_LONG)
+ {
+ /* Trying for longest matc, but couldn't or didn't
+ * match -- back up one char. */
+ if (--rst->count < rst->minval)
+ break;
+ if (reginput == regline)
+ {
+ /* backup to last char of previous line */
+ --reglnum;
+ regline = reg_getline(reglnum);
+ /* Just in case regrepeat() didn't count
+ * right. */
+ if (regline == NULL)
+ break;
+ reginput = regline + STRLEN(regline);
+ fast_breakcheck();
+ }
+ else
+ mb_ptr_back(regline, reginput);
+ }
+ else
+ {
+ /* Range is backwards, use shortest match first.
+ * Careful: maxval and minval are exchanged!
+ * Couldn't or didn't match: try advancing one
+ * char. */
+ if (rst->count == rst->minval
+ || regrepeat(OPERAND(rp->rs_scan), 1L) == 0)
+ break;
+ ++rst->count;
+ }
+ if (got_int)
+ break;
+ }
+ else
+ status = RA_NOMATCH;
+
+ /* If it could match, try it. */
+ if (rst->nextb == NUL || *reginput == rst->nextb
+ || *reginput == rst->nextb_ic)
+ {
+ reg_save(&rp->rs_un.regsave);
+ scan = regnext(rp->rs_scan);
+ status = RA_CONT;
+ break;
+ }
+ }
+ if (status != RA_CONT)
+ {
+ /* Failed. */
+ regstack_pop(&regstack, &scan, &startp);
+ regstack.ga_len -= sizeof(regstar_T);
+ status = RA_NOMATCH;
+ }
+ }
+ break;
+ }
+
+ /* If we want to continue the inner loop or didn't pop a state contine
+ * matching loop */
+ if (status == RA_CONT || rp == (regitem_T *)
+ ((char *)regstack.ga_data + regstack.ga_len) - 1)
+ break;
}
+ /* May want to continue with the inner loop. */
+ if (status == RA_CONT)
+ continue;
+
/*
- * We get here only if there's trouble -- normally "case END" is the
- * terminating point.
+ * If the regstack is empty or something failed we are done.
*/
- EMSG(_(e_re_corr));
+ if (regstack.ga_len == 0 || status == RA_FAIL)
+ {
+ ga_clear(&regstack);
+ if (scan == NULL)
+ {
+ /*
+ * We get here only if there's trouble -- normally "case END" is
+ * the terminating point.
+ */
+ EMSG(_(e_re_corr));
#ifdef DEBUG
- printf("Premature EOL\n");
+ printf("Premature EOL\n");
#endif
- return FALSE;
+ }
+ return (status == RA_MATCH);
+ }
+
+ } /* End of loop until the regstack is empty. */
+
+ /* NOTREACHED */
+}
+
+/*
+ * Push an item onto the regstack.
+ * Returns pointer to new item. Returns NULL when out of memory.
+ */
+ static regitem_T *
+regstack_push(regstack, state, scan, startp)
+ garray_T *regstack;
+ regstate_T state;
+ char_u *scan;
+ long startp;
+{
+ regitem_T *rp;
+
+ if (ga_grow(regstack, sizeof(regitem_T)) == FAIL)
+ return NULL;
+
+ rp = (regitem_T *)((char *)regstack->ga_data + regstack->ga_len);
+ rp->rs_state = state;
+ rp->rs_scan = scan;
+ rp->rs_startp = startp;
+
+ regstack->ga_len += sizeof(regitem_T);
+ return rp;
+}
+
+/*
+ * Pop an item from the regstack.
+ */
+ static void
+regstack_pop(regstack, scan, startp)
+ garray_T *regstack;
+ char_u **scan;
+ long *startp;
+{
+ regitem_T *rp;
+
+ rp = (regitem_T *)((char *)regstack->ga_data + regstack->ga_len) - 1;
+ *scan = rp->rs_scan;
+ *startp = rp->rs_startp;
+
+ regstack->ga_len -= sizeof(regitem_T);
}
/*
diff --git a/src/term.c b/src/term.c
index 3097cc324..3c0ecb05b 100644
--- a/src/term.c
+++ b/src/term.c
@@ -994,21 +994,21 @@ struct builtin_term builtin_termcaps[] =
{(int)KS_CWP, IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")},
# endif
{(int)KS_CRV, IF_EB("\033[>c", ESC_STR "[>c")},
- {K_UP, IF_EB("\033OA", ESC_STR "OA")},
- {K_DOWN, IF_EB("\033OB", ESC_STR "OB")},
- {K_RIGHT, IF_EB("\033OC", ESC_STR "OC")},
- {K_LEFT, IF_EB("\033OD", ESC_STR "OD")},
- {K_S_UP, IF_EB("\033O2A", ESC_STR "O2A")},
- {K_S_DOWN, IF_EB("\033O2B", ESC_STR "O2B")},
- {K_S_RIGHT, IF_EB("\033O2C", ESC_STR "O2C")},
- {K_C_RIGHT, IF_EB("\033O5C", ESC_STR "O5C")},
- {K_S_LEFT, IF_EB("\033O2D", ESC_STR "O2D")},
- {K_C_LEFT, IF_EB("\033O5D", ESC_STR "O5D")},
+
+ {K_UP, IF_EB("\033O*A", ESC_STR "O*A")},
+ {K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")},
+ {K_RIGHT, IF_EB("\033O*C", ESC_STR "O*C")},
+ {K_LEFT, IF_EB("\033O*D", ESC_STR "O*D")},
+ /* An extra set of cursor keys for vt100 mode */
+ {K_XUP, IF_EB("\033[1;*A", ESC_STR "[1;*A")},
+ {K_XDOWN, IF_EB("\033[1;*B", ESC_STR "[1;*B")},
+ {K_XRIGHT, IF_EB("\033[1;*C", ESC_STR "[1;*C")},
+ {K_XLEFT, IF_EB("\033[1;*D", ESC_STR "[1;*D")},
/* An extra set of function keys for vt100 mode */
- {K_XF1, IF_EB("\033OP", ESC_STR "OP")},
- {K_XF2, IF_EB("\033OQ", ESC_STR "OQ")},
- {K_XF3, IF_EB("\033OR", ESC_STR "OR")},
- {K_XF4, IF_EB("\033OS", ESC_STR "OS")},
+ {K_XF1, IF_EB("\033O*P", ESC_STR "O*P")},
+ {K_XF2, IF_EB("\033O*Q", ESC_STR "O*Q")},
+ {K_XF3, IF_EB("\033O*R", ESC_STR "O*R")},
+ {K_XF4, IF_EB("\033O*S", ESC_STR "O*S")},
{K_F1, IF_EB("\033[11;*~", ESC_STR "[11;*~")},
{K_F2, IF_EB("\033[12;*~", ESC_STR "[12;*~")},
{K_F3, IF_EB("\033[13;*~", ESC_STR "[13;*~")},
@@ -1021,32 +1021,28 @@ struct builtin_term builtin_termcaps[] =
{K_F10, IF_EB("\033[21;*~", ESC_STR "[21;*~")},
{K_F11, IF_EB("\033[23;*~", ESC_STR "[23;*~")},
{K_F12, IF_EB("\033[24;*~", ESC_STR "[24;*~")},
- {K_S_XF1, IF_EB("\033O2P", ESC_STR "O2P")},
- {K_S_XF2, IF_EB("\033O2Q", ESC_STR "O2Q")},
- {K_S_XF3, IF_EB("\033O2R", ESC_STR "O2R")},
- {K_S_XF4, IF_EB("\033O2S", ESC_STR "O2S")},
{K_S_TAB, IF_EB("\033[Z", ESC_STR "[Z")},
{K_HELP, IF_EB("\033[28;*~", ESC_STR "[28;*~")},
{K_UNDO, IF_EB("\033[26;*~", ESC_STR "[26;*~")},
{K_INS, IF_EB("\033[2;*~", ESC_STR "[2;*~")},
{K_HOME, IF_EB("\033[1;*H", ESC_STR "[1;*H")},
- {K_S_HOME, IF_EB("\033O2H", ESC_STR "O2H")},
- {K_C_HOME, IF_EB("\033O5H", ESC_STR "O5H")},
+ /* {K_S_HOME, IF_EB("\033O2H", ESC_STR "O2H")}, */
+ /* {K_C_HOME, IF_EB("\033O5H", ESC_STR "O5H")}, */
{K_KHOME, IF_EB("\033[7;*~", ESC_STR "[7;*~")},
- {K_XHOME, IF_EB("\033OH", ESC_STR "OH")}, /* alternate Home */
+ {K_XHOME, IF_EB("\033O*H", ESC_STR "O*H")}, /* other Home */
{K_END, IF_EB("\033[1;*F", ESC_STR "[1;*F")},
- {K_S_END, IF_EB("\033O2F", ESC_STR "O2F")},
- {K_C_END, IF_EB("\033O5F", ESC_STR "O5F")},
+ /* {K_S_END, IF_EB("\033O2F", ESC_STR "O2F")}, */
+ /* {K_C_END, IF_EB("\033O5F", ESC_STR "O5F")}, */
{K_KEND, IF_EB("\033[4;*~", ESC_STR "[4;*~")},
- {K_XEND, IF_EB("\033OF", ESC_STR "OF")}, /* alternate End */
+ {K_XEND, IF_EB("\033O*F", ESC_STR "O*F")}, /* other End */
{K_PAGEUP, IF_EB("\033[5;*~", ESC_STR "[5;*~")},
{K_PAGEDOWN, IF_EB("\033[6;*~", ESC_STR "[6;*~")},
- {K_KPLUS, IF_EB("\033Ok", ESC_STR "Ok")}, /* keypad plus */
- {K_KMINUS, IF_EB("\033Om", ESC_STR "Om")}, /* keypad minus */
- {K_KDIVIDE, IF_EB("\033Oo", ESC_STR "Oo")}, /* keypad / */
- {K_KMULTIPLY, IF_EB("\033Oj", ESC_STR "Oj")}, /* keypad * */
- {K_KENTER, IF_EB("\033OM", ESC_STR "OM")}, /* keypad Enter */
- {K_KPOINT, IF_EB("\033On", ESC_STR "On")}, /* keypad . */
+ {K_KPLUS, IF_EB("\033O*k", ESC_STR "O*k")}, /* keypad plus */
+ {K_KMINUS, IF_EB("\033O*m", ESC_STR "O*m")}, /* keypad minus */
+ {K_KDIVIDE, IF_EB("\033O*o", ESC_STR "O*o")}, /* keypad / */
+ {K_KMULTIPLY, IF_EB("\033O*j", ESC_STR "O*j")}, /* keypad * */
+ {K_KENTER, IF_EB("\033O*M", ESC_STR "O*M")}, /* keypad Enter */
+ {K_KPOINT, IF_EB("\033O*n", ESC_STR "O*n")}, /* keypad . */
{K_KDEL, IF_EB("\033[3;*~", ESC_STR "[3;*~")}, /* keypad Del */
{BT_EXTRA_KEYS, ""},
@@ -1286,6 +1282,10 @@ struct builtin_term builtin_termcaps[] =
{K_DOWN, "[KD]"},
{K_LEFT, "[KL]"},
{K_RIGHT, "[KR]"},
+ {K_XUP, "[xKU]"},
+ {K_XDOWN, "[xKD]"},
+ {K_XLEFT, "[xKL]"},
+ {K_XRIGHT, "[xKR]"},
{K_S_UP, "[S-KU]"},
{K_S_DOWN, "[S-KD]"},
{K_S_LEFT, "[S-KL]"},
@@ -1570,10 +1570,6 @@ static char *(key_names[]) =
"#2", "#4", "%i", "*7",
"k1", "k2", "k3", "k4", "k5", "k6",
"k7", "k8", "k9", "k;", "F1", "F2",
- "F3", "F4", "F5", "F6", "F7", "F8",
- "F9", "FA", "FB", "FC", "FD", "FE",
- "FF", "FG", "FH", "FI", "FJ", "FK",
- "FL", "FM", "FN", "FO", "FP", "FQ", "FR",
"%1", "&8", "kb", "kI", "kD", "kh",
"@7", "kP", "kN", "K1", "K3", "K4", "K5", "kB",
NULL
@@ -3497,6 +3493,8 @@ struct termcode
static int tc_max_len = 0; /* number of entries that termcodes[] can hold */
static int tc_len = 0; /* current number of entries in termcodes[] */
+static int termcode_star __ARGS((char_u *code, int len));
+
void
clear_termcodes()
{
@@ -3516,15 +3514,19 @@ clear_termcodes()
need_gather = TRUE; /* need to fill termleader[] */
}
+#define ATC_FROM_TERM 55
+
/*
* Add a new entry to the list of terminal codes.
* The list is kept alphabetical for ":set termcap"
+ * "flags" is TRUE when replacing 7-bit by 8-bit controls is desired.
+ * "flags" can also be ATC_FROM_TERM for got_code_from_term().
*/
void
-add_termcode(name, string, use_8bit)
+add_termcode(name, string, flags)
char_u *name;
char_u *string;
- int use_8bit; /* replace 7-bit control by 8-bit one */
+ int flags;
{
struct termcode *new_tc;
int i, j;
@@ -3542,7 +3544,7 @@ add_termcode(name, string, use_8bit)
return;
/* Change leading <Esc>[ to CSI, change <Esc>O to <M-O>. */
- if (use_8bit && term_7to8bit(string) != 0)
+ if (flags != 0 && flags != ATC_FROM_TERM && term_7to8bit(string) != 0)
{
mch_memmove(s, s + 1, STRLEN(s));
s[0] = term_7to8bit(string);
@@ -3584,26 +3586,28 @@ add_termcode(name, string, use_8bit)
if (termcodes[i].name[1] < name[1])
continue;
/*
- * Exact match: Replace old code.
- * But don't replace ESC[123;*X with another.
+ * Exact match: May replace old code.
*/
if (termcodes[i].name[1] == name[1])
{
- if (termcodes[i].len >= 4
- && STRNCMP(termcodes[i].code + termcodes[i].len - 3,
- ";*", 2) == 0)
+ if (flags == ATC_FROM_TERM && (j = termcode_star(
+ termcodes[i].code, termcodes[i].len)) > 0)
{
- /* if they are equal but for the ";*" don't add it */
- if (len == termcodes[i].len - 2
+ /* Don't replace ESC[123;*X or ESC O*X with another when
+ * invoked from got_code_from_term(). */
+ if (len == termcodes[i].len - j
&& STRNCMP(s, termcodes[i].code, len - 1) == 0
- && s[len - 1] == termcodes[i].code[len + 1])
+ && s[len - 1]
+ == termcodes[i].code[termcodes[i].len - 1])
{
+ /* They are equal but for the ";*": don't add it. */
vim_free(s);
return;
}
}
else
{
+ /* Replace old code. */
vim_free(termcodes[i].code);
--tc_len;
break;
@@ -3622,14 +3626,37 @@ add_termcode(name, string, use_8bit)
termcodes[i].name[1] = name[1];
termcodes[i].code = s;
termcodes[i].len = len;
- /* recognize special code like "ESC[42;*X" that accepts modifiers */
- if (len >= 5 && STRNCMP(s + len - 3, ";*", 2) == 0)
- termcodes[i].modlen = len - 3;
- else
- termcodes[i].modlen = 0;
+
+ /* For xterm we recognize special codes like "ESC[42;*X" and "ESC O*X" that
+ * accept modifiers. */
+ termcodes[i].modlen = 0;
+ j = termcode_star(s, len);
+ if (j > 0)
+ termcodes[i].modlen = len - 1 - j;
++tc_len;
}
+/*
+ * Check termcode "code[len]" for ending in ;*X, <Esc>O*X or <M-O>*X.
+ * The "X" can be any character.
+ * Return 0 if not found, 2 for ;*X and 1 for O*X and <M-O>*X.
+ */
+ static int
+termcode_star(code, len)
+ char_u *code;
+ int len;
+{
+ /* Shortest is <M-O>*X. With ; shortest is <CSI>1;*X */
+ if (len >= 3 && code[len - 2] == '*')
+ {
+ if (len >= 5 && code[len - 3] == ';')
+ return 2;
+ if ((len >= 4 && code[len - 3] == 'O') || code[len - 3] == 'O' + 128)
+ return 1;
+ }
+ return 0;
+}
+
char_u *
find_termcode(name)
char_u *name;
@@ -3762,9 +3789,12 @@ check_termcode(max_offset, buf, buflen)
char_u *tp;
char_u *p;
int slen = 0; /* init for GCC */
+ int modslen;
int len;
int offset;
char_u key_name[2];
+ int modifiers;
+ int key;
int new_slen;
int extra;
char_u string[MAX_KEY_CODE_LEN + 1];
@@ -3776,7 +3806,6 @@ check_termcode(max_offset, buf, buflen)
int num_bytes;
# endif
int mouse_code = 0; /* init for GCC */
- int modifiers;
int is_click, is_drag;
int wheel_code = 0;
int current_button;
@@ -3859,8 +3888,8 @@ check_termcode(max_offset, buf, buflen)
if (*tp == ESC && !p_ek && (State & INSERT))
continue;
- new_slen = 0; /* Length of what will replace the termcode */
key_name[0] = NUL; /* no key name found yet */
+ modifiers = 0; /* no modifiers yet */
#ifdef FEAT_GUI
if (gui.in_use)
@@ -3918,69 +3947,60 @@ check_termcode(max_offset, buf, buflen)
key_name[0] = termcodes[idx].name[0];
key_name[1] = termcodes[idx].name[1];
-
break;
}
/*
* Check for code with modifier, like xterm uses:
- * ESC[123;2X (shift) ESC[123;3X (alt), etc.
+ * <Esc>[123;*X (modslen == slen - 3)
+ * Also <Esc>O*X and <M-O>*X (modslen == slen - 2).
+ * When there is a modifier the * matches a number.
+ * When there is no modifier the ;* or * is omitted.
*/
if (termcodes[idx].modlen > 0)
{
- slen = termcodes[idx].modlen;
- if (cpo_koffset && offset && len < slen)
+ modslen = termcodes[idx].modlen;
+ if (cpo_koffset && offset && len < modslen)
continue;
if (STRNCMP(termcodes[idx].code, tp,
- (size_t)(slen > len ? len : slen)) == 0)
+ (size_t)(modslen > len ? len : modslen)) == 0)
{
int n;
- int mod;
- if (len <= slen) /* got a partial sequence */
+ if (len <= modslen) /* got a partial sequence */
return -1; /* need to get more chars */
- if (tp[slen] == termcodes[idx].code[slen + 2])
- ++slen; /* no modifiers */
- else if (tp[slen] != ';')
+ if (tp[modslen] == termcodes[idx].code[slen - 1])
+ slen = modslen + 1; /* no modifiers */
+ else if (tp[modslen] != ';' && modslen == slen - 3)
continue; /* no match */
else
{
/* Skip over the digits, the final char must
* follow. */
- for (j = slen + 1; j < len && isdigit(tp[j]); ++j)
+ for (j = slen - 2; j < len && isdigit(tp[j]); ++j)
;
++j;
if (len < j) /* got a partial sequence */
return -1; /* need to get more chars */
- if (tp[j - 1] != termcodes[idx].code[slen + 2])
- continue;
+ if (tp[j - 1] != termcodes[idx].code[slen - 1])
+ continue; /* no match */
/* Match! Convert modifier bits. */
- n = atoi((char *)tp + slen + 1) - 1;
- mod = 0x0;
+ n = atoi((char *)tp + slen - 2) - 1;
if (n & 1)
- mod |= MOD_MASK_SHIFT;
+ modifiers |= MOD_MASK_SHIFT;
if (n & 2)
- mod |= MOD_MASK_ALT;
+ modifiers |= MOD_MASK_ALT;
if (n & 4)
- mod |= MOD_MASK_CTRL;
+ modifiers |= MOD_MASK_CTRL;
if (n & 8)
- mod |= MOD_MASK_META;
-
- /* Add the modifier codes to our string */
- if (mod != 0)
- {
- string[new_slen++] = K_SPECIAL;
- string[new_slen++] = (int)KS_MODIFIER;
- string[new_slen++] = mod;
- }
+ modifiers |= MOD_MASK_META;
slen = j;
}
key_name[0] = termcodes[idx].name[0];
key_name[1] = termcodes[idx].name[1];
-
break;
}
}
@@ -4672,7 +4692,6 @@ check_termcode(max_offset, buf, buflen)
* Translate the actual mouse event into a pseudo mouse event.
* First work out what modifiers are to be used.
*/
- modifiers = 0x0;
if (orig_mouse_code & MOUSE_SHIFT)
modifiers |= MOD_MASK_SHIFT;
if (orig_mouse_code & MOUSE_CTRL)
@@ -4686,14 +4705,6 @@ check_termcode(max_offset, buf, buflen)
else if (orig_num_clicks == 4)
modifiers |= MOD_MASK_4CLICK;
- /* Add the modifier codes to our string */
- if (modifiers != 0)
- {
- string[new_slen++] = K_SPECIAL;
- string[new_slen++] = (int)KS_MODIFIER;
- string[new_slen++] = modifiers;
- }
-
/* Work out our pseudo mouse event */
key_name[0] = (int)KS_EXTRA;
if (wheel_code != 0)
@@ -4785,7 +4796,31 @@ check_termcode(max_offset, buf, buflen)
# endif /* !USE_ON_FLY_SCROLL */
#endif /* FEAT_GUI */
+ /*
+ * Change <xHome> to <Home>, <xUp> to <Up>, etc.
+ */
+ key = handle_x_keys(TERMCAP2KEY(key_name[0], key_name[1]));
+
+ /*
+ * Add any modifier codes to our string.
+ */
+ new_slen = 0; /* Length of what will replace the termcode */
+ if (modifiers != 0)
+ {
+ /* Some keys have the modifier included. Need to handle that here
+ * to make mappings work. */
+ key = simplify_key(key, &modifiers);
+ if (modifiers != 0)
+ {
+ string[new_slen++] = K_SPECIAL;
+ string[new_slen++] = (int)KS_MODIFIER;
+ string[new_slen++] = modifiers;
+ }
+ }
+
/* Finally, add the special key code to our string */
+ key_name[0] = KEY2TERMCAP0(key);
+ key_name[1] = KEY2TERMCAP1(key);
if (key_name[0] == KS_KEY)
string[new_slen++] = key_name[1]; /* from ":set <M-b>=xx" */
else
@@ -5124,7 +5159,8 @@ show_termcodes()
int i;
int len;
-#define INC 27 /* try to make three columns */
+#define INC3 27 /* try to make three columns */
+#define INC2 40 /* try to make two columns */
#define GAP 2 /* spaces between columns */
if (tc_len == 0) /* no terminal codes (must be GUI) */
@@ -5139,9 +5175,10 @@ show_termcodes()
/*
* do the loop two times:
* 1. display the short items (non-strings and short strings)
- * 2. display the long items (strings)
+ * 2. display the medium items (medium length strings)
+ * 3. display the long items (remaining strings)
*/
- for (run = 1; run <= 2 && !got_int; ++run)
+ for (run = 1; run <= 3 && !got_int; ++run)
{
/*
* collect the items in items[]
@@ -5151,21 +5188,23 @@ show_termcodes()
{
len = show_one_termcode(termcodes[i].name,
termcodes[i].code, FALSE);
- if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2))
+ if (len <= INC3 - GAP ? run == 1
+ : len <= INC2 - GAP ? run == 2
+ : run == 3)
items[item_count++] = i;
}
/*
* display the items
*/
- if (run == 1)
+ if (run <= 2)
{
- cols = (Columns + GAP) / INC;
+ cols = (Columns + GAP) / (run == 1 ? INC3 : INC2);
if (cols == 0)
cols = 1;
rows = (item_count + cols - 1) / cols;
}
- else /* run == 2 */
+ else /* run == 3 */
rows = item_count;
for (row = 0; row < rows && !got_int; ++row)
{
@@ -5178,7 +5217,10 @@ show_termcodes()
msg_col = col; /* make columns */
show_one_termcode(termcodes[items[i]].name,
termcodes[items[i]].code, TRUE);
- col += INC;
+ if (run == 2)
+ col += INC2;
+ else
+ col += INC3;
}
out_flush();
ui_breakcheck();
@@ -5343,7 +5385,7 @@ got_code_from_term(code, len)
i = find_term_bykeys(str);
if (i >= 0)
del_termcode_idx(i);
- add_termcode(name, str, FALSE);
+ add_termcode(name, str, ATC_FROM_TERM);
}
}
}
diff --git a/src/testdir/test24.in b/src/testdir/test24.in
index d9640e5f2..bdcdb4c69 100644
--- a/src/testdir/test24.in
+++ b/src/testdir/test24.in
Binary files differ
diff --git a/src/testdir/test24.ok b/src/testdir/test24.ok
index 752dad583..ae9dcb4e2 100644
--- a/src/testdir/test24.ok
+++ b/src/testdir/test24.ok
@@ -20,3 +20,8 @@ test text test text [\u-z]
xx xx a
xx aaaaa xx a
xx aaaaa xx a
+xx Aaa xx
+xx Aaaa xx
+xx Aaa xx
+xx foobar xA xx
+xx an A xx
diff --git a/src/version.h b/src/version.h
index b537d7208..29790b8ef 100644
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
#define VIM_VERSION_NODOT "vim70aa"
#define VIM_VERSION_SHORT "7.0aa"
#define VIM_VERSION_MEDIUM "7.0aa ALPHA"
-#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Mar 4)"
-#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Mar 4, compiled "
+#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Mar 7)"
+#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Mar 7, compiled "
diff --git a/src/window.c b/src/window.c
index 7cd2f0224..f33903442 100644
--- a/src/window.c
+++ b/src/window.c
@@ -263,6 +263,7 @@ do_window(nchar, Prenum, xchar)
/* cursor to window below */
case 'j':
case K_DOWN:
+ case K_XDOWN:
case Ctrl_J:
CHECK_CMDWIN
#ifdef FEAT_VERTSPLIT
@@ -278,6 +279,7 @@ do_window(nchar, Prenum, xchar)
/* cursor to window above */
case 'k':
case K_UP:
+ case K_XUP:
case Ctrl_K:
CHECK_CMDWIN
#ifdef FEAT_VERTSPLIT
@@ -294,6 +296,7 @@ do_window(nchar, Prenum, xchar)
/* cursor to left window */
case 'h':
case K_LEFT:
+ case K_XLEFT:
case Ctrl_H:
case K_BS:
CHECK_CMDWIN
@@ -303,6 +306,7 @@ do_window(nchar, Prenum, xchar)
/* cursor to right window */
case 'l':
case K_RIGHT:
+ case K_XRIGHT:
case Ctrl_L:
CHECK_CMDWIN
win_goto_hor(FALSE, Prenum1);