1: /***************************************************************************
   2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
   3:  * is provided to you without charge, and with no warranty.  You may give  *
   4:  * away copies of JOVE, including sources, provided that this notice is    *
   5:  * included in all the files.                                              *
   6:  ***************************************************************************/
   7: 
   8: #include "jove.h"
   9: #include "ctype.h"
  10: #include "table.h"
  11: 
  12: #ifdef MAC
  13: #	undef private
  14: #	define private
  15: #endif
  16: 
  17: #ifdef  LINT_ARGS
  18: private int
  19:     newchunk(void);
  20: private void
  21:     init_specials(void),
  22:     remfreelines(struct chunk *);
  23: #else
  24: private int
  25:     newchunk();
  26: private void
  27:     init_specials(),
  28:     remfreelines();
  29: #endif	/* LINT_ARGS */
  30: 
  31: #ifdef MAC
  32: #	undef private
  33: #	define private static
  34: #endif
  35: 
  36: /* Make a newline after AFTER in buffer BUF, UNLESS after is 0,
  37:    in which case we insert the newline before after. */
  38: 
  39: Line *
  40: listput(buf, after)
  41: register Buffer *buf;
  42: register Line   *after;
  43: {
  44:     register Line   *newline = nbufline();
  45: 
  46:     if (after == 0) {   /* Before the first line */
  47:         newline->l_next = buf->b_first;
  48:         newline->l_prev = 0;
  49:         buf->b_first = newline;
  50:     } else {
  51:         newline->l_prev = after;
  52:         newline->l_next = after->l_next;
  53:         after->l_next = newline;
  54:     }
  55:     if (newline->l_next)
  56:         newline->l_next->l_prev = newline;
  57:     else
  58:         if (buf)
  59:             buf->b_last = newline;
  60:     if (buf && buf->b_dot == 0)
  61:         buf->b_dot = newline;
  62:     return newline;
  63: }
  64: 
  65: /* Divide the current line and move the current line to the next one */
  66: 
  67: void
  68: LineInsert(num)
  69: register int    num;
  70: {
  71:     char    newline[LBSIZE];
  72:     register Line   *newdot,
  73:             *olddot;
  74:     int oldchar;
  75: 
  76:     olddot = curline;
  77:     oldchar = curchar;
  78: 
  79:     newdot = curline;
  80:     while (--num >= 0) {
  81:         newdot = listput(curbuf, newdot);
  82:         SavLine(newdot, NullStr);
  83:     }
  84: 
  85:     modify();
  86:     if (curchar != 0) {
  87:         strcpy(newline, &linebuf[curchar]);
  88:         linebuf[curchar] = '\0';    /* Shorten this line */
  89:         SavLine(curline, linebuf);
  90:         strcpy(linebuf, newline);
  91:     } else {    /* Redisplay optimization */
  92:         newdot->l_dline = curline->l_dline;
  93:         SavLine(curline, NullStr);
  94:     }
  95: 
  96:     makedirty(curline);
  97:     curline = newdot;
  98:     curchar = 0;
  99:     makedirty(curline);
 100:     IFixMarks(olddot, oldchar, curline, curchar);
 101: }
 102: 
 103: /* Makes the indent of the current line == goal.  If the current indent
 104:    is greater than GOAL it deletes.  If more indent is needed, it uses
 105:    tabs and spaces to get to where it's going. */
 106: 
 107: void
 108: n_indent(goal)
 109: register int    goal;
 110: {
 111:     int dotcol,
 112:         incrmt;
 113: 
 114:     ToIndent();
 115:     dotcol = calc_pos(linebuf, curchar);
 116:     if (goal < dotcol) {
 117:         DelWtSpace();
 118:         dotcol = 0;
 119:     }
 120: 
 121:     for (;;) {
 122:         incrmt = (tabstop - (dotcol % tabstop));
 123:         if (dotcol + incrmt > goal)
 124:             break;
 125:         insert_c('\t', 1);
 126:         dotcol += incrmt;
 127:     }
 128:     if (dotcol != goal)
 129:         insert_c(' ', (goal - dotcol));
 130: }
 131: 
 132: #ifdef ABBREV
 133: void
 134: MaybeAbbrevExpand()
 135: {
 136:     if (MinorMode(Abbrev) && !ismword(LastKeyStruck) &&
 137:         !bolp() && ismword(linebuf[curchar - 1]))
 138:         AbbrevExpand();
 139: }
 140: #endif
 141: 
 142: void
 143: SelfInsert()
 144: {
 145: #ifdef ABBREV
 146:     MaybeAbbrevExpand();
 147: #endif
 148:     if (LastKeyStruck != CTL('J') && MinorMode(OverWrite)) {
 149:         register int    num,
 150:                 i;
 151: 
 152:         for (i = 0, num = arg_value(); i < num; i++) {
 153:             int pos = calc_pos(linebuf, curchar);
 154: 
 155:             if (!eolp()) {
 156:                 if (linebuf[curchar] == '\t') {
 157:                     if ((pos + 1) == ((pos + tabstop) - (pos % tabstop)))
 158:                         del_char(FORWARD, 1);
 159:                 } else
 160:                     del_char(FORWARD, 1);
 161:             }
 162:             insert_c(LastKeyStruck, 1);
 163:         }
 164:     } else
 165:         Insert(LastKeyStruck);
 166: 
 167:     if (MinorMode(Fill) && (curchar >= RMargin ||
 168:                    (calc_pos(linebuf, curchar) >= RMargin))) {
 169:         int margin;
 170:         Bufpos save;
 171: 
 172:         if (MinorMode(Indent)) {
 173:             DOTsave(&save);
 174:             ToIndent();
 175:             margin = calc_pos(linebuf, curchar);
 176:             SetDot(&save);
 177:         } else
 178:             margin = LMargin;
 179:         DoJustify(curline, 0, curline,
 180:               curchar + strlen(&linebuf[curchar]), 1, margin);
 181:     }
 182: }
 183: 
 184: void
 185: Insert(c)
 186: {
 187:     if (c == CTL('J'))
 188:         LineInsert(arg_value());
 189:     else
 190:         insert_c(c, arg_value());
 191: }
 192: 
 193: /* insert character C N times at point */
 194: void
 195: insert_c(c, n)
 196: {
 197:     if (n <= 0)
 198:         return;
 199:     modify();
 200:     makedirty(curline);
 201:     ins_c(c, linebuf, curchar, n, LBSIZE);
 202:     IFixMarks(curline, curchar, curline, curchar + n);
 203:     curchar += n;
 204: }
 205: 
 206: /* Tab in to the right place for C mode */
 207: 
 208: void
 209: Tab()
 210: {
 211: #ifdef LISP
 212:     if (MajorMode(LISPMODE) && (bolp() || !eolp())) {
 213:         int dotchar = curchar;
 214:         Mark    *m = 0;
 215: 
 216:         ToIndent();
 217:         if (dotchar > curchar)
 218:             m = MakeMark(curline, dotchar, M_FLOATER);
 219:         (void) lisp_indent();
 220:         if (m) {
 221:             ToMark(m);
 222:             DelMark(m);
 223:         } else
 224:             ToIndent();
 225:         return;
 226:     }
 227: #endif
 228:     if (MajorMode(CMODE) && strlen(linebuf) == 0)
 229:         (void) c_indent(CIndIncrmt);
 230:     else
 231:         SelfInsert();
 232: }
 233: 
 234: void
 235: QuotChar()
 236: {
 237:     int c,
 238:         slow;
 239: 
 240:     c = waitchar(&slow);
 241:     if (slow)
 242:         message(key_strokes);
 243:     if (c != CTL('@'))
 244:         Insert(c);
 245: }
 246: 
 247: /* Insert the paren.  If in C mode and c is a '}' then insert the
 248:    '}' in the "right" place for C indentation; that is indented
 249:    the same amount as the matching '{' is indented. */
 250: 
 251: int PDelay = 5, /* 1/2 a second */
 252:     CIndIncrmt = 8;
 253: 
 254: void
 255: DoParen()
 256: {
 257:     Bufpos  *bp = (Bufpos *) -1;
 258:     int nx,
 259:         c = LastKeyStruck;
 260: 
 261:     if (!isclosep(c)) {
 262:         SelfInsert();
 263:         return;
 264:     }
 265: 
 266:     if (MajorMode(CMODE) && c == '}' && blnkp(linebuf))
 267:         bp = c_indent(0);
 268: #ifdef LISP
 269:     if (MajorMode(LISPMODE) && c == ')' && blnkp(linebuf))
 270:         bp = lisp_indent();
 271: #endif
 272:     SelfInsert();
 273: #ifdef MAC
 274:     if (MinorMode(ShowMatch) && !in_macro()) {
 275: #else
 276:     if (MinorMode(ShowMatch) && !charp() && !in_macro()) {
 277: #endif
 278:         b_char(1);  /* Back onto the ')' */
 279:         if ((int) bp == -1)
 280:             bp = m_paren(c, BACKWARD, NO, YES);
 281:         f_char(1);
 282:         if (bp != 0) {
 283:             nx = in_window(curwind, bp->p_line);
 284:             if (nx != -1) {     /* is visible */
 285:                 Bufpos  b;
 286: 
 287:                 DOTsave(&b);
 288:                 SetDot(bp);
 289:                 SitFor(PDelay);
 290:                 SetDot(&b);
 291:             } else
 292:                 s_mess("%s", lcontents(bp->p_line));
 293:         }
 294:         mp_error(); /* display error message */
 295:     }
 296: }
 297: 
 298: void
 299: LineAI()
 300: {
 301:     DoNewline(TRUE);
 302: }
 303: 
 304: void
 305: Newline()
 306: {
 307:     DoNewline(MinorMode(Indent));
 308: }
 309: 
 310: void
 311: DoNewline(indentp)
 312: {
 313:     Bufpos  save;
 314:     int indent;
 315: 
 316:     /* first we calculate the indent of the current line */
 317:     DOTsave(&save);
 318:     ToIndent();
 319:     indent = calc_pos(linebuf, curchar);
 320:     SetDot(&save);
 321: 
 322: #ifdef ABBREV
 323:     MaybeAbbrevExpand();
 324: #endif
 325: #ifdef LISP
 326:     if (MajorMode(LISPMODE))
 327:         DelWtSpace();
 328:     else
 329: #endif
 330:         if (indentp || blnkp(linebuf))
 331:         DelWtSpace();
 332: 
 333:     /* If there is more than 2 blank lines in a row then don't make
 334: 	   a newline, just move down one. */
 335:     if (arg_value() == 1 && eolp() && TwoBlank())
 336:         SetLine(curline->l_next);
 337:     else
 338:         LineInsert(arg_value());
 339: 
 340:     if (indentp)
 341: #ifdef LISP
 342:         if (MajorMode(LISPMODE))
 343:         (void) lisp_indent();
 344:         else
 345: #endif
 346:         n_indent((LMargin == 0) ? indent : LMargin);
 347: }
 348: 
 349: void
 350: ins_str(str, ok_nl)
 351: register char   *str;
 352: {
 353:     register char   c;
 354:     Bufpos  save;
 355:     int llen;
 356: 
 357:     if (*str == 0)
 358:         return;     /* ain't nothing to insert! */
 359:     DOTsave(&save);
 360:     llen = strlen(linebuf);
 361:     while (c = *str++) {
 362:         if (c == '\n' || (ok_nl && llen >= LBSIZE - 2)) {
 363:             IFixMarks(save.p_line, save.p_char, curline, curchar);
 364:             modify();
 365:             makedirty(curline);
 366:             LineInsert(1);
 367:             DOTsave(&save);
 368:             llen = strlen(linebuf);
 369:         }
 370:         if (c != '\n') {
 371:             ins_c(c, linebuf, curchar++, 1, LBSIZE);
 372:             llen += 1;
 373:         }
 374:     }
 375:     IFixMarks(save.p_line, save.p_char, curline, curchar);
 376:     modify();
 377:     makedirty(curline);
 378: }
 379: 
 380: void
 381: open_lines(n)
 382: {
 383:     Bufpos  dot;
 384: 
 385:     DOTsave(&dot);
 386:     LineInsert(n);  /* Open the lines... */
 387:     SetDot(&dot);
 388: }
 389: 
 390: void
 391: OpenLine()
 392: {
 393:     open_lines(arg_value());
 394: }
 395: 
 396: /* Take the region FLINE/FCHAR to TLINE/TCHAR and insert it at
 397:    ATLINE/ATCHAR in WHATBUF. */
 398: 
 399: Bufpos *
 400: DoYank(fline, fchar, tline, tchar, atline, atchar, whatbuf)
 401: Line    *fline,
 402:     *tline,
 403:     *atline;
 404: Buffer  *whatbuf;
 405: {
 406:     register Line   *newline;
 407:     static Bufpos   bp;
 408:     char    save[LBSIZE],
 409:         buf[LBSIZE];
 410:     Line    *startline = atline;
 411:     int startchar = atchar;
 412: 
 413:     lsave();
 414:     if (whatbuf)
 415:         modify();
 416:     (void) ltobuf(atline, genbuf);
 417:     strcpy(save, &genbuf[atchar]);
 418: 
 419:     (void) ltobuf(fline, buf);
 420:     if (fline == tline)
 421:         buf[tchar] = '\0';
 422: 
 423:     linecopy(genbuf, atchar, &buf[fchar]);
 424:     atline->l_dline = putline(genbuf);
 425:     makedirty(atline);
 426: 
 427:     fline = fline->l_next;
 428:     while (fline != tline->l_next) {
 429:         newline = listput(whatbuf, atline);
 430:         newline->l_dline = fline->l_dline;
 431:         makedirty(newline);
 432:         fline = fline->l_next;
 433:         atline = newline;
 434:         atchar = 0;
 435:     }
 436: 
 437:     getline(atline->l_dline, genbuf);
 438:     atchar += tchar;
 439:     linecopy(genbuf, atchar, save);
 440:     atline->l_dline = putline(genbuf);
 441:     makedirty(atline);
 442:     IFixMarks(startline, startchar, atline, atchar);
 443:     bp.p_line = atline;
 444:     bp.p_char = atchar;
 445:     this_cmd = YANKCMD;
 446:     getDOT();           /* Whatever used to be in linebuf */
 447:     return &bp;
 448: }
 449: 
 450: void
 451: YankPop()
 452: {
 453:     Line    *line,
 454:         *last;
 455:     Mark    *mp = CurMark();
 456:     Bufpos  *dot;
 457:     int dir = -1;   /* Direction to rotate the ring */
 458: 
 459:     if (last_cmd != YANKCMD)
 460:         complain("Yank something first!");
 461: 
 462:     lfreelist(reg_delete(mp->m_line, mp->m_char, curline, curchar));
 463: 
 464:     /* Now must find a recently killed region. */
 465: 
 466:     if (arg_value() < 0)
 467:         dir = 1;
 468: 
 469:     killptr += dir;
 470:     for (;;) {
 471:         if (killptr < 0)
 472:             killptr = NUMKILLS - 1;
 473:         else if (killptr >= NUMKILLS)
 474:             killptr = 0;
 475:         if (killbuf[killptr])
 476:             break;
 477:         killptr += dir;
 478:     }
 479: 
 480:     this_cmd = YANKCMD;
 481: 
 482:     line = killbuf[killptr];
 483:     last = lastline(line);
 484:     dot = DoYank(line, 0, last, length(last), curline, curchar, curbuf);
 485:     MarkSet(CurMark(), curline, curchar);
 486:     SetDot(dot);
 487: }
 488: 
 489: /* This is an attempt to reduce the amount of memory taken up by each line.
 490:    Without this each malloc of a line uses sizeof (line) + sizeof(HEADER)
 491:    where line is 3 words and HEADER is 1 word.
 492:    This is going to allocate memory in chucks of CHUNKSIZE * sizeof (line)
 493:    and divide each chuck into lineS.  A line is free in a chunk when its
 494:    line->l_dline == 0, so freeline sets dline to 0. */
 495: 
 496: #define CHUNKSIZE   300
 497: 
 498: struct chunk {
 499:     int c_nlines;   /* Number of lines in this chunk (so they
 500: 				   don't all have to be CHUNKSIZE long). */
 501:     Line    *c_block;   /* Chunk of memory */
 502:     struct chunk    *c_nextfree;    /* Next chunk of lines */
 503: };
 504: 
 505: private struct chunk    *fchunk = 0;
 506: private Line    *ffline = 0;    /* First free line */
 507: 
 508: void
 509: freeline(line)
 510: register Line   *line;
 511: {
 512:     line->l_dline = 0;
 513:     line->l_next = ffline;
 514:     if (ffline)
 515:         ffline->l_prev = line;
 516:     line->l_prev = 0;
 517:     ffline = line;
 518: }
 519: 
 520: void
 521: lfreelist(first)
 522: register Line   *first;
 523: {
 524:     if (first)
 525:         lfreereg(first, lastline(first));
 526: }
 527: 
 528: /* Append region from line1 to line2 onto the free list of lines */
 529: 
 530: void
 531: lfreereg(line1, line2)
 532: register Line   *line1,
 533:         *line2;
 534: {
 535:     register Line   *next,
 536:             *last = line2->l_next;
 537: 
 538:     while (line1 != last) {
 539:         next = line1->l_next;
 540:         freeline(line1);
 541:         line1 = next;
 542:     }
 543: }
 544: 
 545: private int
 546: newchunk()
 547: {
 548:     register Line   *newline;
 549:     register int    i;
 550:     struct chunk    *f;
 551:     int nlines = CHUNKSIZE;
 552: 
 553:     f = (struct chunk *) emalloc(sizeof (struct chunk));
 554:     if (f == 0)
 555:         return 0;
 556: 
 557:     if ((f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines))) == 0) {
 558:         while (nlines > 0) {
 559:             f->c_block = (Line *) malloc((unsigned) (sizeof (Line) * nlines));
 560:             if (f->c_block != 0)
 561:                 break;
 562:             nlines /= 2;
 563:         }
 564:     }
 565: 
 566:     if (nlines <= 0)
 567:         return 0;
 568: 
 569:     f->c_nlines = nlines;
 570:     for (i = 0, newline = f->c_block; i < nlines; newline++, i++)
 571:         freeline(newline);
 572:     f->c_nextfree = fchunk;
 573:     fchunk = f;
 574:     return 1;
 575: }
 576: 
 577: /* New BUFfer LINE */
 578: 
 579: Line *
 580: nbufline()
 581: {
 582:     register Line   *newline;
 583: 
 584:     if (ffline == 0)    /* No free list */
 585:         if (newchunk() == 0)
 586:             complain("[Out of lines] ");
 587:     newline = ffline;
 588:     ffline = ffline->l_next;
 589:     if (ffline)
 590:         ffline->l_prev = 0;
 591:     return newline;
 592: }
 593: 
 594: /* Remove the free lines, in chunk c, from the free list because they are
 595:    no longer free. */
 596: 
 597: private void
 598: remfreelines(c)
 599: register struct chunk   *c;
 600: {
 601:     register Line   *lp;
 602:     register int    i;
 603: 
 604:     for (lp = c->c_block, i = 0; i < c->c_nlines; i++, lp++) {
 605:         if (lp->l_prev)
 606:             lp->l_prev->l_next = lp->l_next;
 607:         else
 608:             ffline = lp->l_next;
 609:         if (lp->l_next)
 610:             lp->l_next->l_prev = lp->l_prev;
 611:     }
 612: }
 613: 
 614: /* This is used to garbage collect the chunks of lines when malloc fails
 615:    and we are NOT looking for a new buffer line.  This goes through each
 616:    chunk, and if every line in a given chunk is not allocated, the entire
 617:    chunk is `free'd by "free()". */
 618: 
 619: void
 620: GCchunks()
 621: {
 622:     register struct chunk   *cp;
 623:     struct chunk    *prev = 0,
 624:             *next = 0;
 625:     register int    i;
 626:     register Line   *newline;
 627: 
 628:     for (cp = fchunk; cp != 0; cp = next) {
 629:         for (i = 0, newline = cp->c_block; i < cp->c_nlines; newline++, i++)
 630:             if (newline->l_dline != 0)
 631:                 break;
 632: 
 633:         next = cp->c_nextfree;
 634: 
 635:         if (i == cp->c_nlines) {        /* Unlink it!!! */
 636:             if (prev)
 637:                 prev->c_nextfree = cp->c_nextfree;
 638:             else
 639:                 fchunk = cp->c_nextfree;
 640:             remfreelines(cp);
 641:             free((char *) cp->c_block);
 642:             free((char *) cp);
 643:         } else
 644:             prev = cp;
 645:     }
 646: }
 647: 
 648: #ifdef LISP
 649: 
 650: /* Grind S-Expr */
 651: 
 652: void
 653: GSexpr()
 654: {
 655:     Bufpos  dot,
 656:         end;
 657: 
 658:     if (linebuf[curchar] != '(')
 659:         complain((char *) 0);
 660:     DOTsave(&dot);
 661:     FSexpr();
 662:     DOTsave(&end);
 663:     SetDot(&dot);
 664:     for (;;) {
 665:         if (curline == end.p_line)
 666:             break;
 667:         line_move(FORWARD, 1, NO);
 668:         if (!blnkp(linebuf))
 669:             (void) lisp_indent();
 670:     }
 671:     SetDot(&dot);
 672: }
 673: 
 674: /* lisp_indent() indents a new line in Lisp Mode, according to where
 675:    the matching close-paren would go if we typed that (sort of). */
 676: 
 677: private Table   *specials = NIL;
 678: 
 679: private void
 680: init_specials()
 681: {
 682:     static char *words[] = {
 683:         "case",
 684:         "def",
 685:         "dolist",
 686:         "fluid-let",
 687:         "lambda",
 688:         "let",
 689:         "lexpr",
 690:         "macro",
 691:         "named-l",  /* named-let and named-lambda */
 692:         "nlambda",
 693:         "prog",
 694:         "selectq",
 695:         0
 696:     };
 697:     char    **wordp = words;
 698: 
 699:     specials = make_table();
 700:     while (*wordp)
 701:         add_word(*wordp++, specials);
 702: }
 703: 
 704: void
 705: AddSpecial()
 706: {
 707:     char    *word;
 708: 
 709:     word = ask((char *) 0, ProcFmt);
 710:     if (specials == NIL)
 711:         init_specials();
 712:     add_word(copystr(word), specials);
 713: }
 714: 
 715: Bufpos *
 716: lisp_indent()
 717: {
 718:     Bufpos  *bp,
 719:         savedot;
 720:     int goal;
 721: 
 722:     bp = m_paren(')', BACKWARD, NO, YES);
 723: 
 724:     if (bp == 0)
 725:         return 0;
 726: 
 727:     /* We want to end up
 728: 
 729: 	 	(atom atom atom ...
 730: 	 	      ^ here.
 731: 	 */
 732: 
 733:     DOTsave(&savedot);
 734:     SetDot(bp);
 735:     f_char(1);
 736:     if (linebuf[curchar] != '(') {
 737:         register Word   *wp;
 738: 
 739:         if (specials == NIL)
 740:             init_specials();
 741:         for (wp = table_top(specials); wp != NIL; wp = next_word(wp))
 742:             if (casencmp(word_text(wp), &linebuf[curchar], word_length(wp)) == 0)
 743:                 break;
 744:         if (wp == NIL) {    /* not special */
 745:             int c_char = curchar;
 746: 
 747:             WITH_TABLE(curbuf->b_major)
 748:                 f_word(1);
 749:             END_TABLE();
 750:             if (LookingAt("[ \t]*;\\|[ \t]*$", linebuf, curchar))
 751:                 curchar = c_char;
 752:             else while (linebuf[curchar] == ' ')
 753:                 curchar += 1;
 754:         } else
 755:             curchar += 1;
 756:     }
 757:     goal = calc_pos(linebuf, curchar);
 758:     SetDot(&savedot);
 759:     n_indent(goal);
 760: 
 761:     return bp;
 762: }
 763: #endif /* LISP */

Defined functions

AddSpecial defined in line 704; used 4 times
DoNewline defined in line 310; used 4 times
DoParen defined in line 254; used 4 times
DoYank defined in line 399; used 8 times
GCchunks defined in line 619; used 3 times
GSexpr defined in line 652; used 4 times
Insert defined in line 184; used 4 times
LineAI defined in line 298; used 4 times
MaybeAbbrevExpand defined in line 133; used 4 times
Newline defined in line 304; used 4 times
OpenLine defined in line 390; used 4 times
QuotChar defined in line 234; used 4 times
SelfInsert defined in line 142; used 8 times
Tab defined in line 208; used 4 times
YankPop defined in line 450; used 4 times
freeline defined in line 508; used 4 times
init_specials defined in line 679; used 4 times
lfreelist defined in line 520; used 7 times
lfreereg defined in line 530; used 4 times
lisp_indent defined in line 715; used 6 times
listput defined in line 39; used 6 times
n_indent defined in line 107; used 11 times
nbufline defined in line 579; used 5 times
newchunk defined in line 545; used 3 times
open_lines defined in line 380; used 4 times
remfreelines defined in line 597; used 3 times

Defined variables

PDelay defined in line 251; used 2 times
fchunk defined in line 505; used 4 times
ffline defined in line 506; used 11 times
private defined in line 677; never used
specials defined in line 677; used 6 times

Defined struct's

chunk defined in line 498; used 17 times

Defined macros

CHUNKSIZE defined in line 496; used 1 times
private defined in line 33; used 10 times
Last modified: 1988-03-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4578
Valid CSS Valid XHTML 1.0 Strict