version 1.0
[nvi.git] / vi / v_match.c
blobf02e4aef9fd2f95a48db68667dc9a27094e25142
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: v_match.c,v 8.7 1993/12/09 17:05:51 bostic Exp $ (Berkeley) $Date: 1993/12/09 17:05:51 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <string.h>
16 #include "vi.h"
17 #include "vcmd.h"
20 * v_match -- %
21 * Search to matching character.
23 int
24 v_match(sp, ep, vp, fm, tm, rp)
25 SCR *sp;
26 EXF *ep;
27 VICMDARG *vp;
28 MARK *fm, *tm, *rp;
30 register int cnt, matchc, startc;
31 VCS cs;
32 recno_t lno;
33 size_t len, off;
34 int (*gc)__P((SCR *, EXF *, VCS *));
35 char *p;
37 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
38 if (file_lline(sp, ep, &lno))
39 return (1);
40 if (lno == 0)
41 goto nomatch;
42 GETLINE_ERR(sp, fm->lno);
43 return (1);
47 * !!!
48 * Historical practice was to search in the forward direction only.
50 for (off = fm->cno;; ++off) {
51 if (off >= len) {
52 nomatch: msgq(sp, M_BERR, "No match character on this line.");
53 return (1);
55 switch (startc = p[off]) {
56 case '(':
57 matchc = ')';
58 gc = cs_next;
59 break;
60 case ')':
61 matchc = '(';
62 gc = cs_prev;
63 break;
64 case '[':
65 matchc = ']';
66 gc = cs_next;
67 break;
68 case ']':
69 matchc = '[';
70 gc = cs_prev;
71 break;
72 case '{':
73 matchc = '}';
74 gc = cs_next;
75 break;
76 case '}':
77 matchc = '{';
78 gc = cs_prev;
79 break;
80 default:
81 continue;
83 break;
86 cs.cs_lno = fm->lno;
87 cs.cs_cno = off;
88 if (cs_init(sp, ep, &cs))
89 return (1);
90 for (cnt = 1;;) {
91 if (gc(sp, ep, &cs))
92 return (1);
93 if (cs.cs_flags != 0) {
94 if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF)
95 break;
96 continue;
98 if (cs.cs_ch == startc)
99 ++cnt;
100 else if (cs.cs_ch == matchc && --cnt == 0)
101 break;
103 if (cnt) {
104 msgq(sp, M_BERR, "Matching character not found.");
105 return (1);
107 rp->lno = cs.cs_lno;
108 rp->cno = cs.cs_cno;
111 * Movement commands go one space further. Increment the return
112 * MARK or from MARK depending on the direction of the search.
114 if (F_ISSET(vp, VC_C | VC_D | VC_Y)) {
115 if (file_gline(sp, ep, rp->lno, &len) == NULL) {
116 GETLINE_ERR(sp, rp->lno);
117 return (1);
119 if (len)
120 if (gc == cs_next)
121 ++rp->cno;
122 else
123 ++fm->cno;
125 return (0);