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