|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.