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