|
|
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.4 (Berkeley) 3/9/87"; ! 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: ignore(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: /* ARGSUSED */ ! 227: endsent(pastatom) ! 228: bool pastatom; ! 229: { ! 230: register char *cp = wcursor; ! 231: register int d; ! 232: ! 233: /* ! 234: * If this is the beginning of a line, then ! 235: * check for the end of a paragraph or section. ! 236: */ ! 237: if (cp == linebuf) ! 238: return (endPS()); ! 239: ! 240: /* ! 241: * Sentences end with . ! ? not at the beginning ! 242: * of the line, and must be either at the end of the line, ! 243: * or followed by 2 spaces. Any number of intervening ) ] ' " ! 244: * characters are allowed. ! 245: */ ! 246: if (!any(*cp, ".!?")) ! 247: goto tryps; ! 248: do ! 249: if ((d = *++cp) == 0) ! 250: return (1); ! 251: while (any(d, ")]'")); ! 252: if (*cp == 0 || *cp++ == ' ' && *cp == ' ') ! 253: return (1); ! 254: tryps: ! 255: if (cp[1] == 0) ! 256: return (endPS()); ! 257: return (0); ! 258: } ! 259: ! 260: /* ! 261: * End of paragraphs/sections are respective ! 262: * macros as well as blank lines and form feeds. ! 263: */ ! 264: endPS() ! 265: { ! 266: ! 267: return (linebuf[0] == 0 || ! 268: isa(svalue(PARAGRAPHS)) || isa(svalue(SECTIONS))); ! 269: ! 270: } ! 271: ! 272: #ifdef LISPCODE ! 273: lindent(addr) ! 274: line *addr; ! 275: { ! 276: register int i; ! 277: char *swcurs = wcursor; ! 278: line *swdot = wdot; ! 279: ! 280: again: ! 281: if (addr > one) { ! 282: register char *cp; ! 283: register int cnt = 0; ! 284: ! 285: addr--; ! 286: getline(*addr); ! 287: for (cp = linebuf; *cp; cp++) ! 288: if (*cp == '(') ! 289: cnt++; ! 290: else if (*cp == ')') ! 291: cnt--; ! 292: cp = vpastwh(linebuf); ! 293: if (*cp == 0) ! 294: goto again; ! 295: if (cnt == 0) ! 296: return (whitecnt(linebuf)); ! 297: addr++; ! 298: } ! 299: wcursor = linebuf; ! 300: linebuf[0] = 0; ! 301: wdot = addr; ! 302: dir = -1; ! 303: llimit = one; ! 304: lf = lindent; ! 305: if (!lskipbal("()")) ! 306: i = 0; ! 307: else if (wcursor == linebuf) ! 308: i = 2; ! 309: else { ! 310: register char *wp = wcursor; ! 311: ! 312: dir = 1; ! 313: llimit = wdot; ! 314: if (!lnext() || !ltosolid() || !lskipatom()) { ! 315: wcursor = wp; ! 316: i = 1; ! 317: } else ! 318: i = 0; ! 319: i += column(wcursor) - 1; ! 320: if (!inopen) ! 321: i--; ! 322: } ! 323: wdot = swdot; ! 324: wcursor = swcurs; ! 325: return (i); ! 326: } ! 327: #endif ! 328: ! 329: lmatchp(addr) ! 330: line *addr; ! 331: { ! 332: register int i; ! 333: register char *parens, *cp; ! 334: ! 335: for (cp = cursor; !any(*cp, "({[)}]");) ! 336: if (*cp++ == 0) ! 337: return (0); ! 338: lf = 0; ! 339: parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}"; ! 340: if (*cp == parens[1]) { ! 341: dir = -1; ! 342: llimit = one; ! 343: } else { ! 344: dir = 1; ! 345: llimit = dol; ! 346: } ! 347: if (addr) ! 348: llimit = addr; ! 349: if (splitw) ! 350: llimit = dot; ! 351: wcursor = cp; ! 352: wdot = dot; ! 353: i = lskipbal(parens); ! 354: return (i); ! 355: } ! 356: ! 357: lsmatch(cp) ! 358: char *cp; ! 359: { ! 360: char save[LBSIZE]; ! 361: register char *sp = save; ! 362: register char *scurs = cursor; ! 363: ! 364: wcursor = cp; ! 365: strcpy(sp, linebuf); ! 366: *wcursor = 0; ! 367: strcpy(cursor, genbuf); ! 368: cursor = strend(linebuf) - 1; ! 369: if (lmatchp(dot - vcline)) { ! 370: register int i = insmode; ! 371: register int c = outcol; ! 372: register int l = outline; ! 373: ! 374: if (!MI) ! 375: endim(); ! 376: vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1); ! 377: flush(); ! 378: sleep(1); ! 379: vgoto(l, c); ! 380: if (i) ! 381: goim(); ! 382: } ! 383: else { ! 384: strcLIN(sp); ! 385: strcpy(scurs, genbuf); ! 386: if (!lmatchp((line *) 0)) ! 387: beep(); ! 388: } ! 389: strcLIN(sp); ! 390: wdot = 0; ! 391: wcursor = 0; ! 392: cursor = scurs; ! 393: } ! 394: ! 395: ltosolid() ! 396: { ! 397: ! 398: return (ltosol1("()")); ! 399: } ! 400: ! 401: ltosol1(parens) ! 402: register char *parens; ! 403: { ! 404: register char *cp; ! 405: ! 406: if (*parens && !*wcursor && !lnext()) ! 407: return (0); ! 408: while (isspace(*wcursor) || (*wcursor == 0 && *parens)) ! 409: if (!lnext()) ! 410: return (0); ! 411: if (any(*wcursor, parens) || dir > 0) ! 412: return (1); ! 413: for (cp = wcursor; cp > linebuf; cp--) ! 414: if (isspace(cp[-1]) || any(cp[-1], parens)) ! 415: break; ! 416: wcursor = cp; ! 417: return (1); ! 418: } ! 419: ! 420: lskipbal(parens) ! 421: register char *parens; ! 422: { ! 423: register int level = dir; ! 424: register int c; ! 425: ! 426: do { ! 427: if (!lnext()) { ! 428: wdot = NOLINE; ! 429: return (0); ! 430: } ! 431: c = *wcursor; ! 432: if (c == parens[1]) ! 433: level--; ! 434: else if (c == parens[0]) ! 435: level++; ! 436: } while (level); ! 437: return (1); ! 438: } ! 439: ! 440: lskipatom() ! 441: { ! 442: ! 443: return (lskipa1("()")); ! 444: } ! 445: ! 446: lskipa1(parens) ! 447: register char *parens; ! 448: { ! 449: register int c; ! 450: ! 451: for (;;) { ! 452: if (dir < 0 && wcursor == linebuf) { ! 453: if (!lnext()) ! 454: return (0); ! 455: break; ! 456: } ! 457: c = *wcursor; ! 458: if (c && (isspace(c) || any(c, parens))) ! 459: break; ! 460: if (!lnext()) ! 461: return (0); ! 462: if (dir > 0 && wcursor == linebuf) ! 463: break; ! 464: } ! 465: return (ltosol1(parens)); ! 466: } ! 467: ! 468: lnext() ! 469: { ! 470: ! 471: if (dir > 0) { ! 472: if (*wcursor) ! 473: wcursor++; ! 474: if (*wcursor) ! 475: return (1); ! 476: if (wdot >= llimit) { ! 477: if (lf == vmove && wcursor > linebuf) ! 478: wcursor--; ! 479: return (0); ! 480: } ! 481: wdot++; ! 482: getline(*wdot); ! 483: wcursor = linebuf; ! 484: return (1); ! 485: } else { ! 486: --wcursor; ! 487: if (wcursor >= linebuf) ! 488: return (1); ! 489: #ifdef LISPCODE ! 490: if (lf == lindent && linebuf[0] == '(') ! 491: llimit = wdot; ! 492: #endif ! 493: if (wdot <= llimit) { ! 494: wcursor = linebuf; ! 495: return (0); ! 496: } ! 497: wdot--; ! 498: getline(*wdot); ! 499: wcursor = linebuf[0] == 0 ? linebuf : strend(linebuf) - 1; ! 500: return (1); ! 501: } ! 502: } ! 503: ! 504: lbrack(c, f) ! 505: register int c; ! 506: int (*f)(); ! 507: { ! 508: register line *addr; ! 509: ! 510: addr = dot; ! 511: for (;;) { ! 512: addr += dir; ! 513: if (addr < one || addr > dol) { ! 514: addr -= dir; ! 515: break; ! 516: } ! 517: getline(*addr); ! 518: if (linebuf[0] == '{' || ! 519: #ifdef LISPCODE ! 520: value(LISP) && linebuf[0] == '(' || ! 521: #endif ! 522: isa(svalue(SECTIONS))) { ! 523: if (c == ']' && f != vmove) { ! 524: addr--; ! 525: getline(*addr); ! 526: } ! 527: break; ! 528: } ! 529: if (c == ']' && f != vmove && linebuf[0] == '}') ! 530: break; ! 531: } ! 532: if (addr == dot) ! 533: return (0); ! 534: if (f != vmove) ! 535: wcursor = c == ']' ? strend(linebuf) : linebuf; ! 536: else ! 537: wcursor = 0; ! 538: wdot = addr; ! 539: vmoving = 0; ! 540: return (1); ! 541: } ! 542: ! 543: isa(cp) ! 544: register char *cp; ! 545: { ! 546: ! 547: if (linebuf[0] != '.') ! 548: return (0); ! 549: for (; cp[0] && cp[1]; cp += 2) ! 550: if (linebuf[1] == cp[0]) { ! 551: if (linebuf[2] == cp[1]) ! 552: return (1); ! 553: if (linebuf[2] == 0 && cp[1] == ' ') ! 554: return (1); ! 555: } ! 556: return (0); ! 557: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.