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

Defined functions

endPS defined in line 263; used 4 times
endsent defined in line 226; used 1 times
isa defined in line 542; used 3 times
lbrack defined in line 503; used 1 times
lfind defined in line 47; used 4 times
lmatchp defined in line 328; used 3 times
lnext defined in line 467; used 20 times
lskipa1 defined in line 445; used 3 times
lskipatom defined in line 439; used 2 times
lskipbal defined in line 419; used 3 times
lsmatch defined in line 356; used 1 times
ltosol1 defined in line 400; used 2 times
ltosolid defined in line 394; used 2 times

Defined variables

llimit defined in line 31; used 13 times
sccsid defined in line 8; never used
wasend defined in line 38; used 1 times
  • in line 61
Last modified: 1985-06-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1951
Valid CSS Valid XHTML 1.0 Strict