1: /* Copyright (c) 1981 Regents of the University of California */
2: static char *sccsid = "@(#)ex_vops3.c 7.1 7/8/81";
3: #include "ex.h"
4: #include "ex_tty.h"
5: #include "ex_vis.h"
6:
7: /*
8: * Routines to handle structure.
9: * Operations supported are:
10: * ( ) { } [ ]
11: *
12: * These cover: LISP TEXT
13: * ( ) s-exprs sentences
14: * { } list at same paragraphs
15: * [ ] defuns sections
16: *
17: * { and } for C used to attempt to do something with matching {}'s, but
18: * I couldn't find definitions which worked intuitively very well, so I
19: * scrapped this.
20: *
21: * The code here is very hard to understand.
22: */
23: line *llimit;
24: int (*lf)();
25:
26: #ifdef LISPCODE
27: int lindent();
28: #endif
29:
30: bool wasend;
31:
32: /*
33: * Find over structure, repeated count times.
34: * Don't go past line limit. F is the operation to
35: * be performed eventually. If pastatom then the user said {}
36: * rather than (), implying past atoms in a list (or a paragraph
37: * rather than a sentence.
38: */
39: lfind(pastatom, cnt, f, limit)
40: bool pastatom;
41: int cnt, (*f)();
42: line *limit;
43: {
44: register int c;
45: register int rc = 0;
46: char save[LBSIZE];
47:
48: /*
49: * Initialize, saving the current line buffer state
50: * and computing the limit; a 0 argument means
51: * directional end of file.
52: */
53: wasend = 0;
54: lf = f;
55: strcpy(save, linebuf);
56: if (limit == 0)
57: limit = dir < 0 ? one : dol;
58: llimit = limit;
59: wdot = dot;
60: wcursor = cursor;
61:
62: if (pastatom >= 2) {
63: while (cnt > 0 && word(f, cnt))
64: cnt--;
65: if (pastatom == 3)
66: eend(f);
67: if (dot == wdot) {
68: wdot = 0;
69: if (cursor == wcursor)
70: rc = -1;
71: }
72: }
73: #ifdef LISPCODE
74: else if (!value(LISP)) {
75: #else
76: else {
77: #endif
78: char *icurs;
79: line *idot;
80:
81: if (linebuf[0] == 0) {
82: do
83: if (!lnext())
84: goto ret;
85: while (linebuf[0] == 0);
86: if (dir > 0) {
87: wdot--;
88: linebuf[0] = 0;
89: wcursor = linebuf;
90: /*
91: * If looking for sentence, next line
92: * starts one.
93: */
94: if (!pastatom) {
95: icurs = wcursor;
96: idot = wdot;
97: goto begin;
98: }
99: }
100: }
101: icurs = wcursor;
102: idot = wdot;
103:
104: /*
105: * Advance so as to not find same thing again.
106: */
107: if (dir > 0) {
108: if (!lnext()) {
109: rc = -1;
110: goto ret;
111: }
112: } else
113: ignore(lskipa1(""));
114:
115: /*
116: * Count times find end of sentence/paragraph.
117: */
118: begin:
119: for (;;) {
120: while (!endsent(pastatom))
121: if (!lnext())
122: goto ret;
123: if (!pastatom || wcursor == linebuf && endPS())
124: if (--cnt <= 0)
125: break;
126: if (linebuf[0] == 0) {
127: do
128: if (!lnext())
129: goto ret;
130: while (linebuf[0] == 0);
131: } else
132: if (!lnext())
133: goto ret;
134: }
135:
136: /*
137: * If going backwards, and didn't hit the end of the buffer,
138: * then reverse direction.
139: */
140: if (dir < 0 && (wdot != llimit || wcursor != linebuf)) {
141: dir = 1;
142: llimit = dot;
143: /*
144: * Empty line needs special treatement.
145: * If moved to it from other than begining of next line,
146: * then a sentence starts on next line.
147: */
148: if (linebuf[0] == 0 && !pastatom &&
149: (wdot != dot - 1 || cursor != linebuf)) {
150: lnext();
151: goto ret;
152: }
153: }
154:
155: /*
156: * If we are not at a section/paragraph division,
157: * advance to next.
158: */
159: if (wcursor == icurs && wdot == idot || wcursor != linebuf || !endPS())
160: ignore(lskipa1(""));
161: }
162: #ifdef LISPCODE
163: else {
164: c = *wcursor;
165: /*
166: * Startup by skipping if at a ( going left or a ) going
167: * right to keep from getting stuck immediately.
168: */
169: if (dir < 0 && c == '(' || dir > 0 && c == ')') {
170: if (!lnext()) {
171: rc = -1;
172: goto ret;
173: }
174: }
175: /*
176: * Now chew up repitition count. Each time around
177: * if at the beginning of an s-exp (going forwards)
178: * or the end of an s-exp (going backwards)
179: * skip the s-exp. If not at beg/end resp, then stop
180: * if we hit a higher level paren, else skip an atom,
181: * counting it unless pastatom.
182: */
183: while (cnt > 0) {
184: c = *wcursor;
185: if (dir < 0 && c == ')' || dir > 0 && c == '(') {
186: if (!lskipbal("()"))
187: goto ret;
188: /*
189: * Unless this is the last time going
190: * backwards, skip past the matching paren
191: * so we don't think it is a higher level paren.
192: */
193: if (dir < 0 && cnt == 1)
194: goto ret;
195: if (!lnext() || !ltosolid())
196: goto ret;
197: --cnt;
198: } else if (dir < 0 && c == '(' || dir > 0 && c == ')')
199: /* Found a higher level paren */
200: goto ret;
201: else {
202: if (!lskipatom())
203: goto ret;
204: if (!pastatom)
205: --cnt;
206: }
207: }
208: }
209: #endif
210: ret:
211: strcLIN(save);
212: return (rc);
213: }
214:
215: /*
216: * Is this the end of a sentence?
217: */
218: endsent(pastatom)
219: bool pastatom;
220: {
221: register char *cp = wcursor;
222: register int c, d;
223:
224: /*
225: * If this is the beginning of a line, then
226: * check for the end of a paragraph or section.
227: */
228: if (cp == linebuf)
229: return (endPS());
230:
231: /*
232: * Sentences end with . ! ? not at the beginning
233: * of the line, and must be either at the end of the line,
234: * or followed by 2 spaces. Any number of intervening ) ] ' "
235: * characters are allowed.
236: */
237: if (!any(c = *cp, ".!?"))
238: goto tryps;
239: do
240: if ((d = *++cp) == 0)
241: return (1);
242: while (any(d, ")]'"));
243: if (*cp == 0 || *cp++ == ' ' && *cp == ' ')
244: return (1);
245: tryps:
246: if (cp[1] == 0)
247: return (endPS());
248: return (0);
249: }
250:
251: /*
252: * End of paragraphs/sections are respective
253: * macros as well as blank lines and form feeds.
254: */
255: endPS()
256: {
257:
258: return (linebuf[0] == 0 ||
259: isa(svalue(PARAGRAPHS)) || isa(svalue(SECTIONS)));
260:
261: }
262:
263: #ifdef LISPCODE
264: lindent(addr)
265: line *addr;
266: {
267: register int i;
268: char *swcurs = wcursor;
269: line *swdot = wdot;
270:
271: again:
272: if (addr > one) {
273: register char *cp;
274: register int cnt = 0;
275:
276: addr--;
277: getline(*addr);
278: for (cp = linebuf; *cp; cp++)
279: if (*cp == '(')
280: cnt++;
281: else if (*cp == ')')
282: cnt--;
283: cp = vpastwh(linebuf);
284: if (*cp == 0)
285: goto again;
286: if (cnt == 0)
287: return (whitecnt(linebuf));
288: addr++;
289: }
290: wcursor = linebuf;
291: linebuf[0] = 0;
292: wdot = addr;
293: dir = -1;
294: llimit = one;
295: lf = lindent;
296: if (!lskipbal("()"))
297: i = 0;
298: else if (wcursor == linebuf)
299: i = 2;
300: else {
301: register char *wp = wcursor;
302:
303: dir = 1;
304: llimit = wdot;
305: if (!lnext() || !ltosolid() || !lskipatom()) {
306: wcursor = wp;
307: i = 1;
308: } else
309: i = 0;
310: i += column(wcursor) - 1;
311: if (!inopen)
312: i--;
313: }
314: wdot = swdot;
315: wcursor = swcurs;
316: return (i);
317: }
318: #endif
319:
320: lmatchp(addr)
321: line *addr;
322: {
323: register int i;
324: register char *parens, *cp;
325:
326: for (cp = cursor; !any(*cp, "({[)}]");)
327: if (*cp++ == 0)
328: return (0);
329: lf = 0;
330: parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}";
331: if (*cp == parens[1]) {
332: dir = -1;
333: llimit = one;
334: } else {
335: dir = 1;
336: llimit = dol;
337: }
338: if (addr)
339: llimit = addr;
340: if (splitw)
341: llimit = dot;
342: wcursor = cp;
343: wdot = dot;
344: i = lskipbal(parens);
345: return (i);
346: }
347:
348: lsmatch(cp)
349: char *cp;
350: {
351: char save[LBSIZE];
352: register char *sp = save;
353: register char *scurs = cursor;
354:
355: wcursor = cp;
356: strcpy(sp, linebuf);
357: *wcursor = 0;
358: strcpy(cursor, genbuf);
359: cursor = strend(linebuf) - 1;
360: if (lmatchp(dot - vcline)) {
361: register int i = insmode;
362: register int c = outcol;
363: register int l = outline;
364:
365: if (!MI)
366: endim();
367: vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1);
368: flush();
369: sleep(1);
370: vgoto(l, c);
371: if (i)
372: goim();
373: }
374: else {
375: strcLIN(sp);
376: strcpy(scurs, genbuf);
377: if (!lmatchp((line *) 0))
378: beep();
379: }
380: strcLIN(sp);
381: wdot = 0;
382: wcursor = 0;
383: cursor = scurs;
384: }
385:
386: ltosolid()
387: {
388:
389: return (ltosol1("()"));
390: }
391:
392: ltosol1(parens)
393: register char *parens;
394: {
395: register char *cp;
396:
397: if (*parens && !*wcursor && !lnext())
398: return (0);
399: while (isspace(*wcursor) || (*wcursor == 0 && *parens))
400: if (!lnext())
401: return (0);
402: if (any(*wcursor, parens) || dir > 0)
403: return (1);
404: for (cp = wcursor; cp > linebuf; cp--)
405: if (isspace(cp[-1]) || any(cp[-1], parens))
406: break;
407: wcursor = cp;
408: return (1);
409: }
410:
411: lskipbal(parens)
412: register char *parens;
413: {
414: register int level = dir;
415: register int c;
416:
417: do {
418: if (!lnext()) {
419: wdot = NOLINE;
420: return (0);
421: }
422: c = *wcursor;
423: if (c == parens[1])
424: level--;
425: else if (c == parens[0])
426: level++;
427: } while (level);
428: return (1);
429: }
430:
431: lskipatom()
432: {
433:
434: return (lskipa1("()"));
435: }
436:
437: lskipa1(parens)
438: register char *parens;
439: {
440: register int c;
441:
442: for (;;) {
443: if (dir < 0 && wcursor == linebuf) {
444: if (!lnext())
445: return (0);
446: break;
447: }
448: c = *wcursor;
449: if (c && (isspace(c) || any(c, parens)))
450: break;
451: if (!lnext())
452: return (0);
453: if (dir > 0 && wcursor == linebuf)
454: break;
455: }
456: return (ltosol1(parens));
457: }
458:
459: lnext()
460: {
461:
462: if (dir > 0) {
463: if (*wcursor)
464: wcursor++;
465: if (*wcursor)
466: return (1);
467: if (wdot >= llimit) {
468: if (lf == vmove && wcursor > linebuf)
469: wcursor--;
470: return (0);
471: }
472: wdot++;
473: getline(*wdot);
474: wcursor = linebuf;
475: return (1);
476: } else {
477: --wcursor;
478: if (wcursor >= linebuf)
479: return (1);
480: #ifdef LISPCODE
481: if (lf == lindent && linebuf[0] == '(')
482: llimit = wdot;
483: #endif
484: if (wdot <= llimit) {
485: wcursor = linebuf;
486: return (0);
487: }
488: wdot--;
489: getline(*wdot);
490: wcursor = linebuf[0] == 0 ? linebuf : strend(linebuf) - 1;
491: return (1);
492: }
493: }
494:
495: lbrack(c, f)
496: register int c;
497: int (*f)();
498: {
499: register line *addr;
500:
501: addr = dot;
502: for (;;) {
503: addr += dir;
504: if (addr < one || addr > dol) {
505: addr -= dir;
506: break;
507: }
508: getline(*addr);
509: if (linebuf[0] == '{' ||
510: #ifdef LISPCODE
511: value(LISP) && linebuf[0] == '(' ||
512: #endif
513: isa(svalue(SECTIONS))) {
514: if (c == ']' && f != vmove) {
515: addr--;
516: getline(*addr);
517: }
518: break;
519: }
520: if (c == ']' && f != vmove && linebuf[0] == '}')
521: break;
522: }
523: if (addr == dot)
524: return (0);
525: if (f != vmove)
526: wcursor = c == ']' ? strend(linebuf) : linebuf;
527: else
528: wcursor = 0;
529: wdot = addr;
530: vmoving = 0;
531: return (1);
532: }
533:
534: isa(cp)
535: register char *cp;
536: {
537:
538: if (linebuf[0] != '.')
539: return (0);
540: for (; cp[0] && cp[1]; cp += 2)
541: if (linebuf[1] == cp[0]) {
542: if (linebuf[2] == cp[1])
543: return (1);
544: if (linebuf[2] == 0 && cp[1] == ' ')
545: return (1);
546: }
547: return (0);
548: }
Defined functions
isa
defined in line
534; used 3 times
lfind
defined in line
39; used 4 times
lnext
defined in line
459; used 20 times
- in line 83,
108,
121,
128-132(2),
150,
170,
195,
305,
397-400(2),
418,
444,
451
- in /usr/src/ucb/ex/ex3/ex_voper.c line
749,
764-767(2),
789-792(2),
800
Defined variables
llimit
defined in line
23; used 13 times
sccsid
defined in line
2;
never used