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