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

Defined functions

endPS defined in line 254; used 4 times
endsent defined in line 217; used 1 times
isa defined in line 531; used 3 times
lbrack defined in line 492; used 1 times
lfind defined in line 38; used 4 times
lmatchp defined in line 319; used 3 times
lnext defined in line 456; used 20 times
lskipa1 defined in line 434; used 3 times
lskipatom defined in line 428; used 2 times
lskipbal defined in line 410; used 3 times
lsmatch defined in line 347; used 1 times
ltosol1 defined in line 391; used 2 times
ltosolid defined in line 385; used 2 times

Defined variables

llimit defined in line 22; used 13 times
wasend defined in line 29; used 1 times
  • in line 52
Last modified: 1980-09-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1288
Valid CSS Valid XHTML 1.0 Strict