]> granicus.if.org Git - vim/commitdiff
updated for version 7.0056
authorBram Moolenaar <Bram@vim.org>
Sun, 6 Mar 2005 23:38:09 +0000 (23:38 +0000)
committerBram Moolenaar <Bram@vim.org>
Sun, 6 Mar 2005 23:38:09 +0000 (23:38 +0000)
21 files changed:
runtime/doc/digraph.txt
runtime/doc/options.txt
runtime/doc/term.txt
runtime/filetype.vim
src/edit.c
src/ex_getln.c
src/getchar.c
src/globals.h
src/keymap.h
src/message.c
src/misc2.c
src/normal.c
src/os_mswin.c
src/os_unix.c
src/quickfix.c
src/regexp.c
src/term.c
src/testdir/test24.in
src/testdir/test24.ok
src/version.h
src/window.c

index ed4527175b8cced3ff9534a1489e701aaf3d27a0..201d6a0e5a7dba4f45dc1c49ae63b41ce9793908 100644 (file)
@@ -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)
index d0b5abf74568f73959f885d337c4b28950fe23e7..2c52c047525ccd7ac0ee8714e63e12103331b66f 100644 (file)
@@ -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*
index fba493c7071eae32a7312acc1f2590c423c55bd1..0ac9697c43a102d3652728a6658974ac9e9f3849 100644 (file)
@@ -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'*
index bbbb6d2c14bf4b4131007637298a725afd81b247..768fd5dddf3410daf2c79c11bf9a8b06cb5e6ba0 100644 (file)
@@ -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
index ae00c2aba82da6922cac16208cfadd4db61069d7..3a3e865969633c265d96221cb43a7e0b7c8ec0a9 100644 (file)
@@ -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:
index 4c9d17d78f6821376b68202dc261f21df19d8db0..4c6175b6fb8682f7d4b759d17c35dd5a4a1bb3dc 100644 (file)
@@ -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;
index e93ce05290ec4b06a54f73f4a3aa6271ff979cb9..c06b600768639ed948f7f74c372a9bd71b40a5fc 100644 (file)
@@ -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
 }
 
 /*
index 445b453fc524200296b17ef637f524d0a965a5d9..8251f183124ba6a42fa0dfd51966fd505399ccb4 100644 (file)
@@ -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"));
 
index 5babdf4af84f2c1b80374761b2ebada89e3d1cb2..e0e46b77325f26898087933c3616ddcc26cfd7be 100644 (file)
@@ -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')
index f6494847f5379ae77cf682e62de1045cd5a2953a..9b0045d14e4e3a3aff6461c7be0233ade4d02f5a 100644 (file)
@@ -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 */
index 9b21168d848e03d68d4bed7d58eee42057b8a8ae..d4d975dda8ff51548c8d99a6ef566d74afd757b9 100644 (file)
@@ -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.
@@ -2007,6 +1997,35 @@ simplify_key(key, modifiers)
     return key;
 }
 
+/*
+ * 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
index 9bf2e66b7cf7846d8924d3748617b6dafbc6b522..df914b5f39371629935c942f875648d133a015ee 100644 (file)
@@ -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);
+    }
 }
 
 /*
index 5e96da8afe6c0445dec970727357c30a6556002e..a5e10be498ef701d0970472244774c9db19dd9ea 100644 (file)
@@ -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:
index c64a39e0271314eea9f8dd5ed22246b486ae6698..5df0d35f23bec86e444cdb0d9ed1ddfdd29b4804 100644 (file)
@@ -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
index 8d76e28613030a2d65f87916e510e092b02692b9..d9ce186cf86ea1e20a53e59f5dcc5ae5f839ab99 100644 (file)
@@ -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
@@ -2436,6 +2437,7 @@ ex_vimgrep(eap)
                got_int = TRUE;
                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,9 +2477,11 @@ ex_vimgrep(eap)
                if (got_int)
                    break;
            }
+#if 0
 #ifdef HAVE_SETJMP_H
 jumpend:
            mch_endjmp();
+#endif
 #endif
 
            if (using_dummy)
index 36f5bb456636a04b9f0a79d2e066886d38c0620f..79d3e2a573bf76731a1c6c627ece2206bb44fbe6 100644 (file)
@@ -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);
 }
 
 /*
index 3097cc324d9c1c9fcba16c27af645b523288f95b..3c0ecb05bb41452d82be597e505d168342213939 100644 (file)
@@ -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);
            }
        }
     }
index d9640e5f271a25b2fef4e3c13534090aa5cbf5ae..bdcdb4c69256089868476d1ad0948016f6aeb066 100644 (file)
Binary files a/src/testdir/test24.in and b/src/testdir/test24.in differ
index 752dad5834ca593bac7bb72dd13035ac0834d410..ae9dcb4e21e9342ea2102f693ef43dc7f4d6ab59 100644 (file)
@@ -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
index b537d72085623e894e1465d5aea691338d11321b..29790b8ef14030e2dd7bf2607c9d96e4293a4de6 100644 (file)
@@ -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 "
index 7cd2f02242525de028249ada45ef385bda6c15b7..f33903442c7e173313149aaf5794f3ec2a0e350b 100644 (file)
@@ -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);