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