summaryrefslogtreecommitdiff
path: root/editors/nvi/patches/patch-ap
blob: 26e1b8ab72ef45e3fa7d7a0d500b5956b3e3814d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
$NetBSD: patch-ap,v 1.1 2009/08/07 16:39:21 lukem 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