source: trunk/third/nvi/vi/v_match.c @ 14302

Revision 14302, 3.6 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14301, which included commits to RCS files with non-trunk default branches.
Line 
1/*-
2 * Copyright (c) 1992, 1993, 1994
3 *      The Regents of the University of California.  All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 *      Keith Bostic.  All rights reserved.
6 *
7 * See the LICENSE file for redistribution information.
8 */
9
10#include "config.h"
11
12#ifndef lint
13static const char sccsid[] = "@(#)v_match.c     10.8 (Berkeley) 3/6/96";
14#endif /* not lint */
15
16#include <sys/types.h>
17#include <sys/queue.h>
18#include <sys/time.h>
19
20#include <bitstring.h>
21#include <limits.h>
22#include <stdio.h>
23#include <string.h>
24
25#include "../common/common.h"
26#include "vi.h"
27
28/*
29 * v_match -- %
30 *      Search to matching character.
31 *
32 * PUBLIC: int v_match __P((SCR *, VICMD *));
33 */
34int
35v_match(sp, vp)
36        SCR *sp;
37        VICMD *vp;
38{
39        VCS cs;
40        MARK *mp;
41        size_t cno, len, off;
42        int cnt, isempty, matchc, startc, (*gc)__P((SCR *, VCS *));
43        char *p;
44
45        /*
46         * !!!
47         * Historic practice; ignore the count.
48         *
49         * !!!
50         * Historical practice was to search for the initial character in the
51         * forward direction only.
52         */
53        if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
54                if (isempty)
55                        goto nomatch;
56                return (1);
57        }
58        for (off = vp->m_start.cno;; ++off) {
59                if (off >= len) {
60nomatch:                msgq(sp, M_BERR, "184|No match character on this line");
61                        return (1);
62                }
63                switch (startc = p[off]) {
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                case '{':
81                        matchc = '}';
82                        gc = cs_next;
83                        break;
84                case '}':
85                        matchc = '{';
86                        gc = cs_prev;
87                        break;
88                case '<':
89                        matchc = '>';
90                        gc = cs_next;
91                        break;
92                case '>':
93                        matchc = '<';
94                        gc = cs_prev;
95                        break;
96                default:
97                        continue;
98                }
99                break;
100        }
101
102        cs.cs_lno = vp->m_start.lno;
103        cs.cs_cno = off;
104        if (cs_init(sp, &cs))
105                return (1);
106        for (cnt = 1;;) {
107                if (gc(sp, &cs))
108                        return (1);
109                if (cs.cs_flags != 0) {
110                        if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF)
111                                break;
112                        continue;
113                }
114                if (cs.cs_ch == startc)
115                        ++cnt;
116                else if (cs.cs_ch == matchc && --cnt == 0)
117                        break;
118        }
119        if (cnt) {
120                msgq(sp, M_BERR, "185|Matching character not found");
121                return (1);
122        }
123
124        vp->m_stop.lno = cs.cs_lno;
125        vp->m_stop.cno = cs.cs_cno;
126
127        /*
128         * If moving right, non-motion commands move to the end of the range.
129         * Delete and yank stay at the start.
130         *
131         * If moving left, all commands move to the end of the range.
132         *
133         * !!!
134         * Don't correct for leftward movement -- historic vi deleted the
135         * starting cursor position when deleting to a match.
136         */
137        if (vp->m_start.lno < vp->m_stop.lno ||
138            vp->m_start.lno == vp->m_stop.lno &&
139            vp->m_start.cno < vp->m_stop.cno)
140                vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
141        else
142                vp->m_final = vp->m_stop;
143
144        /*
145         * !!!
146         * If the motion is across lines, and the earliest cursor position
147         * is at or before any non-blank characters in the line, i.e. the
148         * movement is cutting all of the line's text, and the later cursor
149         * position has nothing other than whitespace characters between it
150         * and the end of its line, the buffer is in line mode.
151         */
152        if (!ISMOTION(vp) || vp->m_start.lno == vp->m_stop.lno)
153                return (0);
154        mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_start : &vp->m_stop;
155        if (mp->cno != 0) {
156                cno = 0;
157                if (nonblank(sp, mp->lno, &cno))
158                        return (1);
159                if (cno < mp->cno)
160                        return (0);
161        }
162        mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_stop : &vp->m_start;
163        if (db_get(sp, mp->lno, DBG_FATAL, &p, &len))
164                return (1);
165        for (p += mp->cno + 1, len -= mp->cno; --len; ++p)
166                if (!isblank(*p))
167                        return (0);
168        F_SET(vp, VM_LMODE);
169        return (0);
170}
Note: See TracBrowser for help on using the repository browser.