|
|
1.1 ! root 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, "()") ? "()" : "{}"; ! 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: strcLIN(sp); ! 374: wdot = 0; ! 375: wcursor = 0; ! 376: cursor = scurs; ! 377: } ! 378: ! 379: ltosolid() ! 380: { ! 381: ! 382: return (ltosol1("()")); ! 383: } ! 384: ! 385: ltosol1(parens) ! 386: register char *parens; ! 387: { ! 388: register char *cp; ! 389: ! 390: if (*parens && !*wcursor && !lnext()) ! 391: return (0); ! 392: while (isspace(*wcursor) || (*wcursor == 0 && *parens)) ! 393: if (!lnext()) ! 394: return (0); ! 395: if (any(*wcursor, parens) || dir > 0) ! 396: return (1); ! 397: for (cp = wcursor; cp > linebuf; cp--) ! 398: if (isspace(cp[-1]) || any(cp[-1], parens)) ! 399: break; ! 400: wcursor = cp; ! 401: return (1); ! 402: } ! 403: ! 404: lskipbal(parens) ! 405: register char *parens; ! 406: { ! 407: register int level = dir; ! 408: register int c; ! 409: ! 410: do { ! 411: if (!lnext()) ! 412: return (0); ! 413: c = *wcursor; ! 414: if (c == parens[1]) ! 415: level--; ! 416: else if (c == parens[0]) ! 417: level++; ! 418: } while (level); ! 419: return (1); ! 420: } ! 421: ! 422: lskipatom() ! 423: { ! 424: ! 425: return (lskipa1("()")); ! 426: } ! 427: ! 428: lskipa1(parens) ! 429: register char *parens; ! 430: { ! 431: register int c; ! 432: ! 433: for (;;) { ! 434: if (dir < 0 && wcursor == linebuf) { ! 435: if (!lnext()) ! 436: return (0); ! 437: break; ! 438: } ! 439: c = *wcursor; ! 440: if (c && (isspace(c) || any(c, parens))) ! 441: break; ! 442: if (!lnext()) ! 443: return (0); ! 444: if (dir > 0 && wcursor == linebuf) ! 445: break; ! 446: } ! 447: return (ltosol1(parens)); ! 448: } ! 449: ! 450: lnext() ! 451: { ! 452: ! 453: if (dir > 0) { ! 454: if (*wcursor) ! 455: wcursor++; ! 456: if (*wcursor) ! 457: return (1); ! 458: if (wdot >= llimit) { ! 459: if (wcursor > linebuf) ! 460: wcursor--; ! 461: return (0); ! 462: } ! 463: wdot++; ! 464: getline(*wdot); ! 465: wcursor = linebuf; ! 466: return (1); ! 467: } else { ! 468: --wcursor; ! 469: if (wcursor >= linebuf) ! 470: return (1); ! 471: #ifdef LISPCODE ! 472: if (lf == lindent && linebuf[0] == '(') ! 473: llimit = wdot; ! 474: #endif ! 475: if (wdot <= llimit) { ! 476: wcursor = linebuf; ! 477: return (0); ! 478: } ! 479: wdot--; ! 480: getline(*wdot); ! 481: wcursor = linebuf[0] == 0 ? linebuf : strend(linebuf) - 1; ! 482: return (1); ! 483: } ! 484: } ! 485: ! 486: lbrack(c, f) ! 487: register int c; ! 488: int (*f)(); ! 489: { ! 490: register line *addr; ! 491: ! 492: addr = dot; ! 493: for (;;) { ! 494: addr += dir; ! 495: if (addr < one || addr > dol) { ! 496: addr -= dir; ! 497: break; ! 498: } ! 499: getline(*addr); ! 500: if (linebuf[0] == '{' || ! 501: #ifdef LISPCODE ! 502: value(LISP) && linebuf[0] == '(' || ! 503: #endif ! 504: isa(svalue(SECTIONS))) { ! 505: if (c == ']' && f != vmove) { ! 506: addr--; ! 507: getline(*addr); ! 508: } ! 509: break; ! 510: } ! 511: if (c == ']' && f != vmove && linebuf[0] == '}') ! 512: break; ! 513: } ! 514: if (addr == dot) ! 515: return (0); ! 516: if (f != vmove) ! 517: wcursor = c == ']' ? strend(linebuf) : linebuf; ! 518: else ! 519: wcursor = 0; ! 520: wdot = addr; ! 521: vmoving = 0; ! 522: return (1); ! 523: } ! 524: ! 525: isa(cp) ! 526: register char *cp; ! 527: { ! 528: ! 529: if (linebuf[0] != '.') ! 530: return (0); ! 531: for (; cp[0] && cp[1]; cp += 2) ! 532: if (linebuf[1] == cp[0]) { ! 533: if (linebuf[2] == cp[1]) ! 534: return (1); ! 535: if (linebuf[2] == 0 && cp[1] == ' ') ! 536: return (1); ! 537: } ! 538: return (0); ! 539: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.