|
|
1.1 ! root 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: /* Contains commands that deal with creating, selecting, killing and ! 9: listing buffers, and buffer modes, and find-file, etc. */ ! 10: ! 11: #include "jove.h" ! 12: #include "ctype.h" ! 13: #include "disp.h" ! 14: #if defined(IPROCS) ! 15: # include "fp.h" ! 16: # include "iproc.h" ! 17: #endif ! 18: ! 19: #ifdef MAC ! 20: # include "mac.h" ! 21: #else ! 22: # include <sys/stat.h> ! 23: #endif ! 24: ! 25: private Buffer ! 26: *buf_alloc proto((void)), ! 27: *mak_buf proto((void)); ! 28: ! 29: private char *line_cnt proto((Buffer *, char *)); ! 30: ! 31: private void ! 32: defb_wind proto((Buffer *)), ! 33: kill_buf proto((Buffer *)), ! 34: mkbuflist proto((char **)); ! 35: ! 36: private char *Mainbuf = "Main", ! 37: *NoName = "Sans un nom!"; ! 38: ! 39: Buffer *world = 0, /* First in the list */ ! 40: *curbuf = 0, /* pointer into world for current buffer */ ! 41: *lastbuf = 0; /* Last buffer we were in so we have a default ! 42: buffer during a select buffer. */ ! 43: ! 44: /* Toggle BIT in the current buffer's minor mode flags. If argument is ! 45: supplied, a positive one always turns on the mode and zero argument ! 46: always turns it off. */ ! 47: ! 48: void ! 49: TogMinor(bit) ! 50: int bit; ! 51: { ! 52: if (is_an_arg()) { ! 53: if (arg_value() == 0) ! 54: curbuf->b_minor &= ~bit; ! 55: else ! 56: curbuf->b_minor |= bit; ! 57: } else ! 58: curbuf->b_minor ^= bit; ! 59: UpdModLine = YES; ! 60: } ! 61: ! 62: /* Creates a new buffer, links it at the end of the buffer chain, and ! 63: returns it. */ ! 64: ! 65: private Buffer * ! 66: buf_alloc() ! 67: { ! 68: register Buffer *b, ! 69: *lastbp; ! 70: ! 71: lastbp = 0; ! 72: for (b = world; b != 0; lastbp = b, b = b->b_next) ! 73: ; ! 74: ! 75: b = (Buffer *) emalloc(sizeof (Buffer)); ! 76: if (lastbp) ! 77: lastbp->b_next = b; ! 78: else ! 79: world = b; ! 80: b->b_first = 0; ! 81: b->b_next = 0; ! 82: #if defined(MAC) ! 83: b->Type = BUFFER; /* kludge, but simplifies menu handlers */ ! 84: b->Name = 0; ! 85: #endif ! 86: return b; ! 87: } ! 88: ! 89: /* Makes a buffer and initializes it. Obsolete. Used to take two ! 90: arguments, a buffer name and a file name. */ ! 91: ! 92: private Buffer * ! 93: mak_buf() ! 94: { ! 95: register Buffer *newb; ! 96: register int i; ! 97: ! 98: newb = buf_alloc(); ! 99: newb->b_fname = 0; ! 100: newb->b_name = NoName; ! 101: set_ino(newb); ! 102: newb->b_marks = 0; ! 103: newb->b_themark = 0; /* Index into markring */ ! 104: /* No marks yet */ ! 105: for (i = 0; i < NMARKS; i++) ! 106: newb->b_markring[i] = 0; ! 107: newb->b_modified = 0; ! 108: newb->b_type = B_FILE; /* File until proven SCRATCH */ ! 109: newb->b_ntbf = 0; ! 110: newb->b_minor = 0; ! 111: newb->b_major = TEXT; ! 112: newb->b_first = 0; ! 113: newb->b_map = 0; ! 114: #if defined(IPROCS) ! 115: newb->b_process = 0; ! 116: #endif ! 117: initlist(newb); ! 118: #if defined(MAC) ! 119: Bufchange = 1; ! 120: #endif ! 121: return newb; ! 122: } ! 123: ! 124: void ! 125: ReNamBuf() ! 126: { ! 127: register char *new = 0, ! 128: *prompt = ProcFmt, ! 129: *second = "%s already exists; new name? "; ! 130: ! 131: for (;;) { ! 132: new = ask((char *) 0, prompt, new); ! 133: if (!buf_exists(new)) ! 134: break; ! 135: prompt = second; ! 136: } ! 137: setbname(curbuf, new); ! 138: } ! 139: ! 140: void ! 141: FindFile() ! 142: { ! 143: register char *name; ! 144: char fnamebuf[FILESIZE]; ! 145: ! 146: name = ask_file((char *) 0, curbuf->b_fname, fnamebuf); ! 147: SetABuf(curbuf); ! 148: SetBuf(do_find(curwind, name, 0)); ! 149: } ! 150: ! 151: private void ! 152: mkbuflist(bnamp) ! 153: register char **bnamp; ! 154: { ! 155: register Buffer *b; ! 156: ! 157: for (b = world; b != 0; b = b->b_next) ! 158: if (b->b_name != 0) ! 159: *bnamp++ = b->b_name; ! 160: *bnamp = 0; ! 161: } ! 162: ! 163: char * ! 164: ask_buf(def) ! 165: Buffer *def; ! 166: { ! 167: char *bnames[100]; ! 168: register char *bname; ! 169: register int offset; ! 170: char prompt[100]; ! 171: ! 172: if (def != 0 && def->b_name != 0) ! 173: swritef(prompt, ": %f (default %s) ", def->b_name); ! 174: else ! 175: swritef(prompt, ProcFmt); ! 176: mkbuflist(bnames); ! 177: offset = complete(bnames, prompt, RET_STATE); ! 178: if (offset == EOF) ! 179: complain((char *) 0); ! 180: if (offset == ORIGINAL || offset == AMBIGUOUS) ! 181: bname = Minibuf; ! 182: else if (offset == NULLSTRING) { ! 183: if (def) ! 184: bname = def->b_name; ! 185: else ! 186: complain((char *) 0); ! 187: } else if (offset < 0) ! 188: complain((char *) 0); ! 189: else ! 190: bname = bnames[offset]; ! 191: ! 192: return bname; ! 193: } ! 194: ! 195: void ! 196: BufSelect() ! 197: { ! 198: register char *bname; ! 199: ! 200: bname = ask_buf(lastbuf); ! 201: SetABuf(curbuf); ! 202: SetBuf(do_select(curwind, bname)); ! 203: } ! 204: ! 205: #if defined(MSDOS) ! 206: ! 207: private void ! 208: BufNSelect(n) ! 209: { ! 210: char *bnames[100]; ! 211: char *bname; ! 212: int i; ! 213: ! 214: mkbuflist(bnames); ! 215: for (i=0; i<n; i++) ! 216: if (bnames[i] == 0) ! 217: complain("[No such buffer]"); ! 218: bname = bnames[n-1]; ! 219: SetABuf(curbuf); ! 220: SetBuf(do_select(curwind, bname)); ! 221: } ! 222: ! 223: void Buf1Select() { BufNSelect(1); } ! 224: void Buf2Select() { BufNSelect(2); } ! 225: void Buf3Select() { BufNSelect(3); } ! 226: void Buf4Select() { BufNSelect(4); } ! 227: void Buf5Select() { BufNSelect(5); } ! 228: void Buf6Select() { BufNSelect(6); } ! 229: void Buf7Select() { BufNSelect(7); } ! 230: void Buf8Select() { BufNSelect(8); } ! 231: void Buf9Select() { BufNSelect(9); } ! 232: void Buf10Select() { BufNSelect(10); } ! 233: ! 234: #endif /* MSDOS */ ! 235: ! 236: private void ! 237: defb_wind(b) ! 238: register Buffer *b; ! 239: { ! 240: register Window *w = fwind; ! 241: char *alt; ! 242: ! 243: if (lastbuf == b || lastbuf == 0) { ! 244: lastbuf = 0; ! 245: alt = (b->b_next != 0) ? b->b_next->b_name : Mainbuf; ! 246: } else ! 247: alt = lastbuf->b_name; ! 248: ! 249: do { ! 250: if (w->w_bufp == b) { ! 251: if (one_windp() || alt != Mainbuf) ! 252: (void) do_select(w, alt); ! 253: else { ! 254: Window *save = w->w_next; ! 255: ! 256: del_wind(w); ! 257: w = save->w_prev; ! 258: } ! 259: } ! 260: w = w->w_next; ! 261: } while (w != fwind || w->w_bufp == b); ! 262: } ! 263: ! 264: private Buffer * ! 265: getNMbuf() ! 266: { ! 267: register Buffer *delbuf; ! 268: register char *bname; ! 269: ! 270: bname = ask_buf(curbuf); ! 271: if ((delbuf = buf_exists(bname)) == 0) ! 272: complain("[No such buffer]"); ! 273: if (delbuf->b_modified) ! 274: confirm("%s modified, are you sure? ", bname); ! 275: return delbuf; ! 276: } ! 277: ! 278: void ! 279: BufErase() ! 280: { ! 281: register Buffer *delbuf; ! 282: ! 283: if ((delbuf = getNMbuf()) != NIL) { ! 284: initlist(delbuf); ! 285: delbuf->b_modified = 0; ! 286: } ! 287: } ! 288: ! 289: private void ! 290: kill_buf(delbuf) ! 291: register Buffer *delbuf; ! 292: { ! 293: register Buffer *b, ! 294: *lastb = 0; ! 295: ! 296: #if defined(IPROCS) ! 297: pbuftiedp(delbuf); /* check for lingering processes */ ! 298: #endif ! 299: /* clean up windows associated with this buffer */ ! 300: if (delbuf == curbuf) ! 301: curbuf = NULL; ! 302: if (delbuf == lastbuf) ! 303: lastbuf = curbuf; /* even if NULL */ ! 304: defb_wind(delbuf); ! 305: if (curbuf == NULL) ! 306: SetBuf(curwind->w_bufp); ! 307: ! 308: /* unlink the buffer */ ! 309: for (b = world; b != 0; lastb = b, b = b->b_next) ! 310: if (b == delbuf) ! 311: break; ! 312: if (lastb) ! 313: lastb->b_next = delbuf->b_next; ! 314: else ! 315: world = delbuf->b_next; ! 316: ! 317: #if !defined(MAC) ! 318: if (perr_buf == delbuf) { ! 319: ErrFree(); ! 320: perr_buf = 0; ! 321: } ! 322: #endif ! 323: ! 324: lfreelist(delbuf->b_first); ! 325: if (delbuf->b_name) ! 326: free(delbuf->b_name); ! 327: if (delbuf->b_fname) ! 328: free(delbuf->b_fname); ! 329: flush_marks(delbuf); ! 330: free((char *) delbuf); ! 331: ! 332: #if defined(MAC) ! 333: Bufchange = 1; ! 334: #endif ! 335: } ! 336: ! 337: /* offer to kill some buffers */ ! 338: ! 339: void ! 340: KillSome() ! 341: { ! 342: register Buffer *b, ! 343: *next; ! 344: Buffer *oldb; ! 345: register char *y_or_n; ! 346: ! 347: for (b = world; b != 0; b = next) { ! 348: next = b->b_next; ! 349: if (yes_or_no_p("Kill %s? ", b->b_name) == NO) ! 350: continue; ! 351: if (IsModified(b)) { ! 352: y_or_n = ask("No", "%s modified; should I save it? ", b->b_name); ! 353: if (CharUpcase(*y_or_n) == 'Y') { ! 354: oldb = curbuf; ! 355: SetBuf(b); ! 356: SaveFile(); ! 357: SetBuf(oldb); ! 358: } ! 359: } ! 360: kill_buf(b); ! 361: } ! 362: } ! 363: ! 364: void ! 365: BufKill() ! 366: { ! 367: Buffer *b; ! 368: ! 369: if ((b = getNMbuf()) == 0) ! 370: return; ! 371: kill_buf(b); ! 372: } ! 373: ! 374: private char * ! 375: line_cnt(b, buf) ! 376: register Buffer *b; ! 377: char *buf; ! 378: { ! 379: register int nlines = 0; ! 380: register Line *lp; ! 381: ! 382: for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++) ! 383: ; ! 384: swritef(buf, "%d", nlines); ! 385: return buf; ! 386: } ! 387: ! 388: private const char *const TypeNames[] = { ! 389: 0, ! 390: "Scratch", ! 391: "File", ! 392: "Process", ! 393: }; ! 394: ! 395: void ! 396: BufList() ! 397: { ! 398: register char *fmt = "%-2s %-5s %-11s %-1s %-*s %-s"; ! 399: register Buffer *b; ! 400: int bcount = 1, /* To give each buffer a number */ ! 401: buf_width = 11; ! 402: char nbuf[10]; ! 403: ! 404: for (b = world; b != 0; b = b->b_next) ! 405: buf_width = max(buf_width, (int)strlen(b->b_name)); ! 406: ! 407: TOstart("Buffer list", TRUE); /* true means auto-newline */ ! 408: ! 409: Typeout("(* means buffer needs saving)"); ! 410: Typeout("(+ means file hasn't been read yet)"); ! 411: Typeout(NullStr); ! 412: Typeout(fmt, "NO", "Lines", "Type", NullStr, buf_width, "Name", "File"); ! 413: Typeout(fmt, "--", "-----", "----", NullStr, buf_width, "----", "----"); ! 414: for (b = world; b != 0; b = b->b_next) { ! 415: Typeout(fmt, itoa(bcount++), ! 416: line_cnt(b, nbuf), ! 417: TypeNames[b->b_type], ! 418: IsModified(b) ? "*" : ! 419: b->b_ntbf ? "+" : NullStr, ! 420: buf_width, ! 421: /* For the * (variable length field) */ ! 422: b->b_name, ! 423: filename(b)); ! 424: ! 425: if (TOabort) ! 426: break; ! 427: } ! 428: TOstop(); ! 429: } ! 430: ! 431: void ! 432: bufname(b) ! 433: register Buffer *b; ! 434: { ! 435: char tmp[100], ! 436: *cp; ! 437: int try = 1; ! 438: ! 439: if (b->b_fname == 0) ! 440: complain("[No file name]"); ! 441: cp = basename(b->b_fname); ! 442: strcpy(tmp, cp); ! 443: while (buf_exists(tmp)) { ! 444: swritef(tmp, "%s.%d", cp, try); ! 445: try += 1; ! 446: } ! 447: setbname(b, tmp); ! 448: } ! 449: ! 450: void ! 451: initlist(b) ! 452: register Buffer *b; ! 453: { ! 454: lfreelist(b->b_first); ! 455: b->b_first = b->b_dot = b->b_last = 0; ! 456: (void) listput(b, b->b_first); ! 457: ! 458: SavLine(b->b_dot, NullStr); ! 459: b->b_char = 0; ! 460: AllMarkSet(b, b->b_dot, 0); ! 461: if (b == curbuf) ! 462: getDOT(); ! 463: } ! 464: ! 465: /* Returns pointer to buffer with name NAME, or if NAME is a string of digits ! 466: returns the buffer whose number equals those digits. Otherwise, returns ! 467: 0. */ ! 468: ! 469: Buffer * ! 470: buf_exists(name) ! 471: register char *name; ! 472: { ! 473: register Buffer *bp; ! 474: int n; ! 475: ! 476: if (name == 0) ! 477: return 0; ! 478: ! 479: for (bp = world; bp != 0; bp = bp->b_next) ! 480: if (strcmp(bp->b_name, name) == 0) ! 481: return bp; ! 482: ! 483: /* Doesn't match any names. Try for a buffer number... */ ! 484: ! 485: if (chr_to_int(name, 10, YES, &n) != INT_BAD) { ! 486: for (bp = world; n > 1; bp = bp->b_next) { ! 487: if (bp == 0) ! 488: break; ! 489: n -= 1; ! 490: } ! 491: return bp; ! 492: } ! 493: ! 494: return 0; ! 495: } ! 496: ! 497: /* Returns buffer pointer with a file name NAME, if one exists. Stat's the ! 498: file and compares inodes, in case NAME is a link, as well as the actual ! 499: characters that make up the file name. */ ! 500: ! 501: Buffer * ! 502: file_exists(name) ! 503: register char *name; ! 504: { ! 505: struct stat stbuf; ! 506: register struct stat *s = &stbuf; ! 507: register Buffer *b = 0; ! 508: char fnamebuf[FILESIZE]; ! 509: ! 510: #if defined(MSDOS) ! 511: strlwr(name); ! 512: #endif /* MSDOS */ ! 513: if (name) { ! 514: PathParse(name, fnamebuf); ! 515: if (stat(fnamebuf, s) == -1) ! 516: s->st_ino = 0; ! 517: for (b = world; b != 0; b = b->b_next) { ! 518: if ( ! 519: #if !defined(MSDOS) ! 520: (b->b_ino != 0 && b->b_ino == s->st_ino && ! 521: b->b_dev != 0 && b->b_dev == s->st_dev) || ! 522: #endif /* MSDOS */ ! 523: (b->b_fname != 0 && ! 524: strcmp(b->b_fname, fnamebuf) == 0)) ! 525: break; ! 526: } ! 527: } ! 528: return b; ! 529: } ! 530: ! 531: void ! 532: setbname(b, name) ! 533: register Buffer *b; ! 534: register char *name; ! 535: { ! 536: UpdModLine = YES; /* Kludge ... but speeds things up considerably */ ! 537: if (name) { ! 538: if (b->b_name == NoName) ! 539: b->b_name = 0; ! 540: b->b_name = ralloc(b->b_name, strlen(name) + 1); ! 541: strcpy(b->b_name, name); ! 542: } else ! 543: b->b_name = 0; ! 544: #if defined(MAC) ! 545: Bufchange = 1; ! 546: #endif ! 547: } ! 548: ! 549: void ! 550: setfname(b, name) ! 551: register Buffer *b; ! 552: register char *name; ! 553: { ! 554: char wholename[FILESIZE], ! 555: oldname[FILESIZE], ! 556: *oldptr = oldname; ! 557: Buffer *save = curbuf; ! 558: ! 559: SetBuf(b); ! 560: UpdModLine = YES; /* Kludge ... but speeds things up considerably */ ! 561: if (b->b_fname == 0) ! 562: oldptr = 0; ! 563: else ! 564: strcpy(oldname, b->b_fname); ! 565: if (name) { ! 566: #if defined(MSDOS) ! 567: strlwr(name); ! 568: #endif /* MSDOS */ ! 569: PathParse(name, wholename); ! 570: curbuf->b_fname = ralloc(curbuf->b_fname, strlen(wholename) + 1); ! 571: strcpy(curbuf->b_fname, wholename); ! 572: } else ! 573: b->b_fname = 0; ! 574: DoAutoExec(curbuf->b_fname, oldptr); ! 575: curbuf->b_mtime = curbuf->b_dev = curbuf->b_ino = 0; /* until they're known. */ ! 576: SetBuf(save); ! 577: #if defined(MAC) ! 578: Bufchange = 1; ! 579: #endif ! 580: } ! 581: ! 582: void ! 583: set_ino(b) ! 584: register Buffer *b; ! 585: { ! 586: struct stat stbuf; ! 587: ! 588: if (b->b_fname == 0 || stat(pr_name(b->b_fname, NO), &stbuf) == -1) { ! 589: b->b_dev = 0; ! 590: b->b_ino = 0; ! 591: b->b_mtime = 0; ! 592: } else { ! 593: b->b_dev = stbuf.st_dev; ! 594: b->b_ino = stbuf.st_ino; ! 595: b->b_mtime = stbuf.st_mtime; ! 596: } ! 597: } ! 598: ! 599: /* Find the file `fname' into buf and put in in window `w' */ ! 600: ! 601: Buffer * ! 602: do_find(w, fname, force) ! 603: register Window *w; ! 604: register char *fname; ! 605: int force; ! 606: { ! 607: register Buffer *b; ! 608: ! 609: b = file_exists(fname); ! 610: if (b == 0) { ! 611: b = mak_buf(); ! 612: setfname(b, fname); ! 613: bufname(b); ! 614: set_ino(b); ! 615: b->b_ntbf = 1; ! 616: } ! 617: if (force) { ! 618: Buffer *oldb = curbuf; ! 619: ! 620: SetBuf(b); /* this'll read the file */ ! 621: SetBuf(oldb); ! 622: } ! 623: if (w) ! 624: tiewind(w, b); ! 625: return b; ! 626: } ! 627: ! 628: /* set alternate buffer */ ! 629: ! 630: void ! 631: SetABuf(b) ! 632: Buffer *b; ! 633: { ! 634: if (b != 0) ! 635: lastbuf = b; ! 636: } ! 637: ! 638: ! 639: /* check to see if BP is a valid buffer pointer */ ! 640: private int ! 641: valid_bp(bp) ! 642: register Buffer *bp; ! 643: { ! 644: register Buffer *b; ! 645: ! 646: for (b = world; b != 0; b = b->b_next) ! 647: if (b == bp) ! 648: break; ! 649: return b != 0; ! 650: } ! 651: ! 652: void ! 653: SetBuf(newbuf) ! 654: register Buffer *newbuf; ! 655: { ! 656: if (newbuf == curbuf || newbuf == 0) ! 657: return; ! 658: ! 659: if (!valid_bp(newbuf)) ! 660: complain("Internal error: (0x%x) is not a valid buffer pointer!", newbuf); ! 661: lsave(); ! 662: curbuf = newbuf; ! 663: curline = newbuf->b_dot; ! 664: curchar = newbuf->b_char; ! 665: getDOT(); ! 666: /* do the read now ... */ ! 667: if (curbuf->b_ntbf) ! 668: read_file(curbuf->b_fname, 0); ! 669: #if defined(MAC) ! 670: Modechange = 1; ! 671: #endif ! 672: } ! 673: ! 674: Buffer * ! 675: do_select(w, name) ! 676: register Window *w; ! 677: register char *name; ! 678: { ! 679: register Buffer *new; ! 680: ! 681: if ((new = buf_exists(name)) == 0) { ! 682: new = mak_buf(); ! 683: setfname(new, (char *) 0); ! 684: setbname(new, name); ! 685: } ! 686: if (w) ! 687: tiewind(w, new); ! 688: return new; ! 689: } ! 690: ! 691: void ! 692: buf_init() ! 693: { ! 694: SetBuf(do_select(curwind, Mainbuf)); ! 695: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.