|
|
1.1 root 1: /*
2: * This routine gets a bracket character from where the dot lies
3: * and searches for the corresponding bracket.
4: */
5: #include <stdio.h>
6: #include "ed.h"
7:
8: static int o_col, o_row, r_col, r_char, r_row = -1;
9:
10: /*
11: * This is called before each comand is executed.
12: */
13: bracketoff()
14: {
15: if (bind.bracket && (r_row >= 0)) {
16: tmove(r_row, r_col);
17: tputc(r_char);
18: r_row = -1;
19: tmove(o_row, o_col);
20: return (TRUE);
21: }
22: return (FALSE);
23: }
24:
25: /*
26: * toggle bracket mode.
27: */
28: bracketsw()
29: {
30: bind.bracket ^= 1;
31: }
32:
33: bracketsearch()
34: {
35: bstart(0); /* do full search */
36: }
37:
38: /*
39: * This is called after each screen update.
40: */
41: bracketmode(row, col)
42: {
43: r_row = -1;
44: if (bind.bracket)
45: bstart(1);
46: movecursor(row, col);
47: tmove(o_row = row, o_col = col);
48: }
49:
50: static
51: bstart(modesw)
52: {
53: register LINE *clp;
54: int cbo;
55:
56: if (((o_col = cbo = curwp->w_doto) == llength(clp = curwp->w_dotp)))
57: if (modesw)
58: --cbo;
59: else
60: return (FALSE);
61:
62: switch (lgetc(clp, cbo)) {
63: case '/':
64: if ((++cbo == llength(clp)) || ('*' != lgetc(clp, cbo--)))
65: break;
66: case '[':
67: case '{':
68: case '(':
69: return (brksearch(1, modesw, clp, cbo));
70: case '*':
71: if ((++cbo == llength(clp)) || ('/' != lgetc(clp, cbo)))
72: break;
73: case ']':
74: case '}':
75: case ')':
76: return (brksearch(-1, modesw, clp, cbo));
77: case '"':
78: case '\'':
79: if (modesw)
80: break;
81: if (mlyesno("Forward search"))
82: return (brksearch(1, modesw, clp, cbo));
83: return (brksearch(-1, modesw, clp, cbo));
84: }
85: if (!modesw)
86: mlwrite("Place dot on \"'(){}[] /* or */");
87: return (FALSE);
88: }
89:
90: /* defines for states of forward and backward searches */
91: #define NORMAL 0 /* normal state */
92: #define SLASH 1 /* slash maybe comment */
93: #define COMMENT 2 /* comment */
94: #define STAR 3 /* star in comment */
95: #define DQUOTE 4 /* in string */
96: #define SQUOTE 5 /* in single quote */
97: #define BSL 6 /* backslash */
98: #define BADEXPR 7 /* bad expression encountered */
99: #define STARTB 8 /* starting search */
100:
101: /*
102: * scan for end of balanced c expression forward or backward.
103: */
104: static
105: brksearch(dir, mode, clp, cbo)
106: int dir; /* 1 forward -1 backward */
107: int mode; /* 1 paren mode, 0 match paren command */
108: LINE *clp; /* line to start search */
109: int cbo; /* char to start search */
110: {
111: register int c, state;
112: LINE *end;
113: int prev, pstate, bcnt, pcnt, ccnt, bscnt, ctrs;
114:
115: bcnt = ccnt = pcnt = bscnt = 0;
116: state = STARTB;
117: if (mode) { /* end is top or bottom of window */
118: if (dir < 0)
119: end = lback(curwp->w_linep);
120: else
121: for (end = curwp->w_linep, c = curwp->w_ntrows;
122: (c-- > 0) && (curbp->b_linep != end);
123: end = lforw(end)) ;
124: } else /* end is buffer end */
125: end = curbp->b_linep;
126:
127: while (clp != end) {
128: if (dir > 0) { /* get next char */
129: if (cbo == llength(clp)) {
130: clp = lforw(clp);
131: cbo = 0;
132: c = '\n';
133: } else
134: c = lgetc(clp, cbo++);
135: } else { /* get prev char. watch \ here. */
136: c = prev;
137: if (cbo < 0) {
138: clp = lback(clp);
139: cbo = llength(clp) - 1;
140: prev = '\n';
141: }
142: else if (('\\' == (prev = lgetc(clp, cbo--))) &&
143: (state != COMMENT) && (state != SLASH)) {
144: bscnt ^= 1; /* count \ */
145: prev = c; /* don't discard char */
146: continue;
147: }
148: if (bscnt) { /* odd \ discard c */
149: bscnt = 0;
150: continue;
151: }
152: }
153:
154: switch (state) { /* do state processing */
155: case SLASH: /* / encountered */
156: if (c == '*') {
157: state = COMMENT;
158: continue;
159: }
160: state = NORMAL;
161: case NORMAL: /* not in anything */
162: break;
163: case STAR: /* * in comment */
164: if (c == '/') {
165: state = NORMAL;
166: goto processed;
167: }
168: state = COMMENT;
169: case COMMENT: /* in comment */
170: if (c == '*')
171: state = STAR;
172: continue;
173: case SQUOTE: /* in ' string */
174: case DQUOTE: /* in " string */
175: switch (c) {
176: case '\n':
177: state = BADEXPR;
178: goto processed;
179: case '\\': /* can't get here if dir < 0 */
180: pstate = state;
181: state = BSL;
182: continue;
183: case '"':
184: if (state != DQUOTE)
185: continue;
186: state = NORMAL;
187: goto processed;
188: case '\'':
189: if (state != SQUOTE)
190: continue;
191: state = NORMAL;
192: goto processed;
193: default:
194: continue;
195: }
196: case BSL: /* can't get here if dir < 0 */
197: state = pstate;
198: continue;
199: case STARTB:
200: state = NORMAL;
201: if (dir < 0)
202: continue;
203: }
204:
205: switch (c) { /* process chars in NORMAL state */
206: case '[':
207: bcnt += dir;
208: break;
209: case '{':
210: ccnt += dir;
211: if (pcnt | bcnt)
212: state = BADEXPR;
213: break;
214: case ';':
215: if (bcnt)
216: state = BADEXPR;
217: break;
218: case '(':
219: pcnt += dir;
220: break;
221: case '"':
222: state = DQUOTE;
223: continue;
224: case '\'':
225: state = SQUOTE;
226: continue;
227: case '\\': /* can't get here if dir < 0 */
228: pstate = state;
229: state = BSL;
230: continue;
231: case '/':
232: state = SLASH;
233: continue;
234: case ']':
235: bcnt -= dir;
236: break;
237: case '}':
238: ccnt -= dir;
239: if (pcnt | bcnt)
240: state = BADEXPR;
241: break;
242: case ')':
243: pcnt -= dir;
244: }
245:
246: /* done if BADEXPR or balanced expr or ) with no ( etc */
247: processed: if (((ctrs = bcnt | ccnt | pcnt) <= 0) || (state == BADEXPR)) {
248: if (dir > 0) {
249: if (--cbo < 0) {
250: clp = lback(clp);
251: cbo = llength(clp);
252: }
253: } else { /* we are on prev so back up 2 */
254: for (bscnt = 0; bscnt < 2; bscnt++) {
255: if (++cbo > llength(clp)) {
256: clp = lforw(clp);
257: cbo = 0;
258: break;
259: }
260: }
261: }
262: if (mode) { /* paren mode */
263: if ((ctrs < 0) || (state == BADEXPR) ||
264: (0 > (r_row = locatecursor(clp))))
265: return (FALSE);
266: tmove(r_row, (r_col = truecol(clp, cbo)));
267: tstand(1);
268: tputc(r_char = c);
269: tstand(0);
270: } else { /* match paren command */
271: curwp->w_dotp = clp;
272: curwp->w_doto = cbo;
273: curwp->w_flag |= WFMOVE;
274: if ((ctrs < 0) || (state == BADEXPR)) {
275: mlwrite("Bad expression");
276: return (FALSE);
277: }
278: }
279: return (TRUE);
280: }
281: }
282: if (!mode)
283: mlwrite("End not found");
284: return (FALSE);
285: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.