$NetBSD: patch-ap,v 1.2 2013/01/23 17:26:07 wiz Exp $ --- vi/v_match.c.orig 2007-11-19 03:41:42.000000000 +1100 +++ vi/v_match.c @@ -39,6 +39,19 @@ v_match(SCR *sp, VICMD *vp) size_t cno, len, off; int cnt, isempty, matchc, startc, (*gc)__P((SCR *, VCS *)); CHAR_T *p; + char *cp; + char *match_chars; + + static int match_lno, match_col, match_dir; + + /* + * Historically vi would match (), {} and [] however + * an update included <>. This is ok for editing HTML + * but a pain in the butt for C source. + * Making it an option lets the user decide what is 'right'. + * Also fixed to do something sensible with "". + */ + match_chars = O_STR(sp, O_MATCHCHARS); /* * !!! @@ -58,44 +71,27 @@ v_match(SCR *sp, VICMD *vp) nomatch: msgq(sp, M_BERR, "184|No match character on this line"); return (1); } - switch (startc = p[off]) { - case '(': - matchc = ')'; - gc = cs_next; - break; - case ')': - matchc = '('; - gc = cs_prev; - break; - case '[': - matchc = ']'; - gc = cs_next; - break; - case ']': - matchc = '['; - gc = cs_prev; - break; - case '{': - matchc = '}'; - gc = cs_next; - break; - case '}': - matchc = '{'; - gc = cs_prev; + startc = p[off]; + cp = strchr(match_chars, startc); + if (cp != NULL) break; - case '<': - matchc = '>'; - gc = cs_next; - break; - case '>': - matchc = '<'; - gc = cs_prev; - break; - default: - continue; - } - break; } + cnt = cp - match_chars; + matchc = match_chars[cnt ^ 1]; + + /* Alternate back-forward search if startc and matchc the same */ + if (startc == matchc) { + /* are we continuing from where last match finished? */ + if (match_lno == vp->m_start.lno && match_col ==vp->m_start.cno) + /* yes - continue in sequence */ + match_dir++; + else + /* no - go forward, back, back, forward */ + match_dir = 1; + if (match_dir & 2) + cnt++; + } + gc = cnt & 1 ? cs_prev : cs_next; cs.cs_lno = vp->m_start.lno; cs.cs_cno = off; @@ -109,10 +105,10 @@ nomatch: msgq(sp, M_BERR, "184|No match break; continue; } + if (cs.cs_ch == matchc && --cnt == 0) + break; if (cs.cs_ch == startc) ++cnt; - else if (cs.cs_ch == matchc && --cnt == 0) - break; } if (cnt) { msgq(sp, M_BERR, "185|Matching character not found"); @@ -139,6 +135,9 @@ nomatch: msgq(sp, M_BERR, "184|No match else vp->m_final = vp->m_stop; + match_lno = vp->m_final.lno; + match_col = vp->m_final.cno; + /* * !!! * If the motion is across lines, and the earliest cursor position