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: }

Defined functions

endPS defined in line 255; used 4 times
endsent defined in line 218; used 1 times
isa defined in line 534; used 3 times
lbrack defined in line 495; used 1 times
lfind defined in line 39; used 4 times
lmatchp defined in line 320; used 3 times
lnext defined in line 459; used 20 times
lskipa1 defined in line 437; used 3 times
lskipatom defined in line 431; used 2 times
lskipbal defined in line 411; used 3 times
lsmatch defined in line 348; used 1 times
ltosol1 defined in line 392; used 2 times
ltosolid defined in line 386; used 2 times

Defined variables

llimit defined in line 23; used 13 times
sccsid defined in line 2; never used
wasend defined in line 30; used 1 times
  • in line 53
Last modified: 1981-07-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1558
Valid CSS Valid XHTML 1.0 Strict