📄 buf.c
字号:
/*************************************************************************** * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * * is provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ***************************************************************************//* Contains commands that deal with creating, selecting, killing and listing buffers, and buffer modes, and find-file, etc. */#include "jove.h"#include "ctype.h"#include "disp.h"#ifdef IPROCS# include "fp.h"# include "iproc.h"#endif#ifdef MAC# include "mac.h"#else# include <sys/stat.h>#endifprivate void setbname proto((Buffer *, char *));private char *Mainbuf = "Main", *NoName = "Sans un nom!";Buffer *world = NULL, /* First in the list */ *curbuf = NULL, /* pointer into world for current buffer */ *lastbuf = NULL; /* Last buffer we were in so we have a default buffer during a select buffer. *//* Toggle BIT in the current buffer's minor mode flags. If argument is supplied, a positive one always turns on the mode and zero argument always turns it off. */voidTogMinor(bit)int bit;{ if (is_an_arg()) { if (arg_value() == 0) curbuf->b_minor &= ~bit; else curbuf->b_minor |= bit; } else curbuf->b_minor ^= bit; UpdModLine = YES;}/* Creates a new buffer, links it at the end of the buffer chain, and returns it. */private Buffer *free_bufs = NULL;private Buffer *buf_alloc(){ register Buffer *b, *lastbp; lastbp = NULL; for (b = world; b != NULL; b = b->b_next) lastbp = b; if (free_bufs != NULL) { b = free_bufs; free_bufs = b->b_next; } else { b = (Buffer *) emalloc(sizeof (Buffer)); } if (lastbp) lastbp->b_next = b; else world = b; b->b_first = NULL; b->b_next = NULL;#ifdef MAC b->Type = BUFFER; /* kludge, but simplifies menu handlers */ b->Name = NULL;#endif return b;}/* Makes a buffer and initializes it. Obsolete. Used to take two arguments, a buffer name and a file name. */private Buffer *mak_buf(){ register Buffer *newb; register int i; newb = buf_alloc(); newb->b_fname = NULL; newb->b_name = NoName; set_ino(newb); newb->b_marks = NULL; newb->b_themark = 0; /* Index into markring */ /* No marks yet */ for (i = 0; i < NMARKS; i++) newb->b_markring[i] = NULL; newb->b_modified = NO; newb->b_type = B_FILE; /* File until proven SCRATCH */ newb->b_ntbf = NO; newb->b_minor = 0; newb->b_major = TEXT; newb->b_first = NULL; newb->b_map = NULL;#ifdef IPROCS newb->b_process = NULL;#endif initlist(newb);#ifdef MAC Bufchange = YES;#endif return newb;}voidReNamBuf(){ register char *new = NULL, *prompt = ProcFmt, *second = "%s already exists; new name? "; for (;;) { new = ask((char *)NULL, prompt, new); if (!buf_exists(new)) break; prompt = second; } setbname(curbuf, new);}voidFindFile(){ register char *name; char fnamebuf[FILESIZE]; name = ask_file((char *)NULL, curbuf->b_fname, fnamebuf); SetABuf(curbuf); SetBuf(do_find(curwind, name, NO));}private voidmkbuflist(bnamp, ebnamp)register char **bnamp;char **ebnamp;{ register Buffer *b; for (b = world; b != NULL; b = b->b_next) { if (b->b_name != NULL) { *bnamp++ = b->b_name; if (bnamp >= ebnamp) complain("too many buffers to list"); } } *bnamp = NULL;}char *ask_buf(def)Buffer *def;{ char *bnames[100]; register char *bname; register int offset; char prompt[100]; if (def != NULL && def->b_name != NULL) { swritef(prompt, sizeof(prompt), ": %f (default %s) ", def->b_name); } else { swritef(prompt, sizeof(prompt), ProcFmt); } mkbuflist(bnames, &bnames[sizeof(bnames) / sizeof(*bnames)]); offset = complete(bnames, prompt, RET_STATE); if (offset == EOF) complain((char *)NULL); if (offset == ORIGINAL || offset == AMBIGUOUS) { bname = Minibuf; } else if (offset == NULLSTRING) { if (def == NULL) complain((char *)NULL); bname = def->b_name; } else { if (offset < 0) complain((char *)NULL); bname = bnames[offset]; } return bname;}voidBufSelect(){ register char *bname; bname = ask_buf(lastbuf); SetABuf(curbuf); SetBuf(do_select(curwind, bname));}#ifdef MSDOSprivate voidBufNSelect(n)int n;{ register Buffer *b; for (b = world; b != NULL; b = b->b_next) { if (b->b_name != NULL) { if (n == 0) { SetABuf(curbuf); SetBuf(do_select(curwind, b->b_name)); return; } n -= 1; } } complain("[No such buffer]");}void Buf0Select() { BufNSelect(0); }void Buf1Select() { BufNSelect(1); }void Buf2Select() { BufNSelect(2); }void Buf3Select() { BufNSelect(3); }void Buf4Select() { BufNSelect(4); }void Buf5Select() { BufNSelect(5); }void Buf6Select() { BufNSelect(6); }void Buf7Select() { BufNSelect(7); }void Buf8Select() { BufNSelect(8); }void Buf9Select() { BufNSelect(9); }#endif /* MSDOS */private voiddefb_wind(b)register Buffer *b;{ register Window *w = fwind; char *alt; if (lastbuf == b || lastbuf == NULL) { lastbuf = NULL; alt = (b->b_next != NULL) ? b->b_next->b_name : Mainbuf; } else alt = lastbuf->b_name; do { if (w->w_bufp == b) { if (one_windp() || alt != Mainbuf) (void) do_select(w, alt); else { Window *save = w->w_next; del_wind(w); w = save->w_prev; } } w = w->w_next; } while (w != fwind || w->w_bufp == b);}private Buffer *getNMbuf(){ register Buffer *delbuf; register char *bname; bname = ask_buf(curbuf); if ((delbuf = buf_exists(bname)) == NULL) complain("[No such buffer]"); if (delbuf->b_modified) confirm("%s modified, are you sure? ", bname); return delbuf;}voidBufErase(){ register Buffer *delbuf; if ((delbuf = getNMbuf()) != NULL) { initlist(delbuf); delbuf->b_modified = NO; }}/* Free a buffer structure. * The actual struct is preserved to reduce the damage * from dangling references to it. They seem to be pervasive. * We try to reset enough that a dangling reference will be useless. */private voidkill_buf(delbuf)register Buffer *delbuf;{ register Buffer *b, *lastb = NULL;#ifdef IPROCS pbuftiedp(delbuf); /* check for lingering processes */#endif /* clean up windows associated with this buffer */ if (delbuf == curbuf) curbuf = NULL; if (delbuf == lastbuf) lastbuf = curbuf; /* even if NULL */ defb_wind(delbuf); if (curbuf == NULL) SetBuf(curwind->w_bufp); /* unlink the buffer */ for (b = world; b != NULL; lastb = b, b = b->b_next) if (b == delbuf) break; if (lastb) lastb->b_next = delbuf->b_next; else world = delbuf->b_next;#ifndef MAC if (perr_buf == delbuf) { ErrFree(); perr_buf = NULL; }#endif lfreelist(delbuf->b_first); delbuf->b_first = delbuf->b_dot = delbuf->b_last = NULL; if (delbuf->b_name) { free((UnivPtr) delbuf->b_name); delbuf->b_name = NULL; } if (delbuf->b_fname) { free((UnivPtr) delbuf->b_fname); delbuf->b_fname = NULL; } flush_marks(delbuf); delbuf->b_marks = NULL; delbuf->b_next = free_bufs; free_bufs = delbuf;#ifdef MAC Bufchange = YES; delbuf->Name = NULL;#endif}/* offer to kill some buffers */voidKillSome(){ register Buffer *b, *next; Buffer *oldb; register char *y_or_n; for (b = world; b != NULL; b = next) { next = b->b_next; if (yes_or_no_p("Kill %s? ", b->b_name) == NO) continue; if (IsModified(b)) { y_or_n = ask("No", "%s modified; should I save it? ", b->b_name); if (CharUpcase(*y_or_n) == 'Y') { oldb = curbuf; SetBuf(b); SaveFile(); SetBuf(oldb); } } kill_buf(b); }}voidBufKill(){ Buffer *b; if ((b = getNMbuf()) == NULL) return; kill_buf(b);}private char *line_cnt(b, buf, size)register Buffer *b;char *buf;size_t size;{ register int nlines = 0; register Line *lp; for (lp = b->b_first; lp != NULL; lp = lp->l_next, nlines++) ; swritef(buf, size, "%d", nlines); return buf;}private const char *const TypeNames[] = { NULL, "Scratch", "File", "Process",};voidBufList(){ register char *fmt = "%-2s %-5s %-11s %-1s %-*s %-s"; register Buffer *b; int bcount = 1, /* To give each buffer a number */ buf_width = 11; char nbuf[10]; for (b = world; b != NULL; b = b->b_next) buf_width = max(buf_width, (int)strlen(b->b_name)); TOstart("Buffer list", TRUE); /* true means auto-newline */ Typeout("(* means buffer needs saving)"); Typeout("(+ means file hasn't been read yet)"); Typeout(NullStr); Typeout(fmt, "NO", "Lines", "Type", NullStr, buf_width, "Name", "File"); Typeout(fmt, "--", "-----", "----", NullStr, buf_width, "----", "----"); for (b = world; b != NULL; b = b->b_next) { Typeout(fmt, itoa(bcount++), line_cnt(b, nbuf, sizeof(nbuf)), TypeNames[b->b_type], IsModified(b) ? "*" : b->b_ntbf ? "+" : NullStr, buf_width, /* For the * (variable length field) */ b->b_name, filename(b)); if (TOabort) break; } TOstop();}private voidbufname(b)register Buffer *b;{ char tmp[100], *cp; int try = 1; if (b->b_fname == NULL) complain("[No file name]"); cp = basename(b->b_fname); strcpy(tmp, cp); while (buf_exists(tmp)) { swritef(tmp, sizeof(tmp), "%s.%d", cp, try); try += 1; } setbname(b, tmp);}voidinitlist(b)register Buffer *b;{ lfreelist(b->b_first); b->b_first = b->b_dot = b->b_last = NULL; (void) listput(b, b->b_first); SavLine(b->b_dot, NullStr); b->b_char = 0; AllMarkSet(b, b->b_dot, 0); if (b == curbuf) getDOT();}/* Returns pointer to buffer with name NAME, or if NAME is a string of digits returns the buffer whose number equals those digits. Otherwise, returns NULL. */Buffer *buf_exists(name)register char *name;{ register Buffer *bp; int n; if (name == NULL) return NULL; for (bp = world; bp != NULL; bp = bp->b_next) if (strcmp(bp->b_name, name) == 0) return bp; /* Doesn't match any names. Try for a buffer number... */ if (chr_to_int(name, 10, YES, &n) != INT_BAD) { for (bp = world; n > 1; bp = bp->b_next) { if (bp == NULL) break; n -= 1; } return bp; } return NULL;}/* Returns buffer pointer with a file name NAME, if one exists. Stat's the file and compares inodes, in case NAME is a link, as well as the actual characters that make up the file name. */Buffer *file_exists(name)register char *name;{ struct stat stbuf; register struct stat *s = &stbuf; register Buffer *b = NULL; char fnamebuf[FILESIZE];#ifdef MSDOS strlwr(name);#endif /* MSDOS */ if (name) { PathParse(name, fnamebuf); if (stat(fnamebuf, s) == -1) s->st_ino = 0; for (b = world; b != NULL; b = b->b_next) { if (#ifndef MSDOS (b->b_ino != 0 && b->b_ino == s->st_ino && b->b_dev != 0 && b->b_dev == s->st_dev) ||#endif /* MSDOS */ (b->b_fname != NULL && strcmp(b->b_fname, fnamebuf) == 0)) break; } } return b;}private voidsetbname(b, name)register Buffer *b;register char *name;{ UpdModLine = YES; /* Kludge ... but speeds things up considerably */ if (name != NULL) { if (b->b_name == NoName) b->b_name = NULL; b->b_name = freealloc((UnivPtr) b->b_name, strlen(name) + 1); strcpy(b->b_name, name); } else { b->b_name = NULL; }#ifdef MAC Bufchange = YES;#endif}voidsetfname(b, name)register Buffer *b;register char *name;{ char wholename[FILESIZE], oldname[FILESIZE], *oldptr = oldname; Buffer *save = curbuf; SetBuf(b); UpdModLine = YES; /* Kludge ... but speeds things up considerably */ if (b->b_fname == NULL) oldptr = NULL; else strcpy(oldname, b->b_fname); if (name) {#ifdef MSDOS strlwr(name);#endif /* MSDOS */ PathParse(name, wholename); curbuf->b_fname = freealloc((UnivPtr) curbuf->b_fname, strlen(wholename) + 1); strcpy(curbuf->b_fname, wholename); } else b->b_fname = NULL; DoAutoExec(curbuf->b_fname, oldptr); curbuf->b_mtime = curbuf->b_dev = curbuf->b_ino = 0; /* until they're known. */ SetBuf(save);#ifdef MAC Bufchange = YES;#endif}voidset_ino(b)register Buffer *b;{ struct stat stbuf; if (b->b_fname == NULL || stat(pr_name(b->b_fname, NO), &stbuf) == -1) { b->b_dev = 0; b->b_ino = 0; b->b_mtime = 0; } else { b->b_dev = stbuf.st_dev; b->b_ino = stbuf.st_ino; b->b_mtime = stbuf.st_mtime; }}/* Find the file `fname' into buf and put in in window `w' */Buffer *do_find(w, fname, force)register Window *w;register char *fname;bool force;{ register Buffer *b; b = file_exists(fname); if (b == NULL) { b = mak_buf(); setfname(b, fname); bufname(b); set_ino(b); b->b_ntbf = YES; } if (force) { Buffer *oldb = curbuf; SetBuf(b); /* this'll read the file */ SetBuf(oldb); } if (w) tiewind(w, b); return b;}/* set alternate buffer */voidSetABuf(b)Buffer *b;{ if (b != NULL) lastbuf = b;}/* check to see if BP is a valid buffer pointer */private boolvalid_bp(bp)register Buffer *bp;{ register Buffer *b; for (b = world; b != NULL; b = b->b_next) if (b == bp) return YES; return NO;}voidSetBuf(newbuf)register Buffer *newbuf;{ if (newbuf == curbuf || newbuf == NULL) return; if (!valid_bp(newbuf)) complain("Internal error: (0x%x) is not a valid buffer pointer!", newbuf); lsave(); curbuf = newbuf; curline = newbuf->b_dot; curchar = newbuf->b_char; getDOT(); /* do the read now ... */ if (curbuf->b_ntbf) read_file(curbuf->b_fname, NO);#ifdef MAC Modechange = YES;#endif}Buffer *do_select(w, name)register Window *w;register char *name;{ register Buffer *new; if ((new = buf_exists(name)) == NULL) { new = mak_buf(); setfname(new, (char *)NULL); setbname(new, name); } if (w) tiewind(w, new); return new;}voidbuf_init(){ SetBuf(do_select(curwind, Mainbuf));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -