BSD 4_3 development
[unix-history] / usr / contrib / jove / buf.c
/*************************************************************************
* This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
* provided to you without charge for use only on a licensed Unix *
* system. You may copy JOVE provided that this notice is included with *
* the copy. You may not sell copies of this program or versions *
* modified for use on microcomputer systems, unless the copies are *
* included with a Unix system distribution and the source is provided. *
*************************************************************************/
/* Contains commands that deal with creating, selecting, killing and
listing buffers, and buffer modes, and find-file, etc. */
#include "jove.h"
#include <sys/stat.h>
char *Mainbuf = "Main",
*NoName = "Sans un nom!";
Buffer *world = 0, /* First in the list */
*curbuf = 0,
*lastbuf = 0; /* 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. */
TogMinor(bit)
{
if (exp_p) {
if (exp == 0)
curbuf->b_minor &= ~bit;
else
curbuf->b_minor |= bit;
} else
curbuf->b_minor ^= bit;
UpdModLine++;
}
/* Creates a new buffer, links it at the end of the buffer chain, and
returns it. */
static Buffer *
buf_alloc()
{
register Buffer *b,
*lastbp;
lastbp = 0;
for (b = world; b != 0; lastbp = b, b = b->b_next)
;
b = (Buffer *) emalloc(sizeof (Buffer));
if (lastbp)
lastbp->b_next = b;
else
world = b;
b->b_first = 0;
b->b_next = 0;
return b;
}
/* Makes a buffer and initializes it. Obsolete. Used to take two
arguments, a buffer name and a file name. */
static Buffer *
mak_buf()
{
register Buffer *newb;
register int i;
newb = buf_alloc();
newb->b_fname = 0;
newb->b_name = NoName;
set_ino(newb);
newb->b_marks = 0;
newb->b_themark = 0; /* Index into markring */
/* No marks yet */
for (i = 0; i < NMARKS; i++)
newb->b_markring[i] = 0;
newb->b_modified = 0;
newb->b_type = B_FILE; /* File until proven SCRATCH */
newb->b_ntbf = 0;
newb->b_minor = 0;
newb->b_major = TEXT;
newb->b_first = 0;
initlist(newb);
return newb;
}
ReNamBuf()
{
register char *new = 0,
*prompt = ProcFmt,
*second = "%s already exists; new name? ";
for (;;) {
new = ask((char *) 0, prompt, new);
if (!buf_exists(new))
break;
prompt = second;
}
setbname(curbuf, new);
}
FindFile()
{
register char *name;
char fnamebuf[FILESIZE];
name = ask_file(curbuf->b_fname, fnamebuf);
SetABuf(curbuf);
SetBuf(do_find(curwind, name, 0));
}
static
mkbuflist(bnamp)
register char **bnamp;
{
register Buffer *b;
for (b = world; b != 0; b = b->b_next)
if (b->b_name != 0)
*bnamp++ = b->b_name;
*bnamp = 0;
}
char *
ask_buf(def)
Buffer *def;
{
char *bnames[100];
register char *bname;
register int offset;
char prompt[100];
if (def != 0 && def->b_name != 0)
sprintf(prompt, ": %f (default %s) ", def->b_name);
else
sprintf(prompt, ProcFmt);
mkbuflist(bnames);
offset = complete(bnames, prompt, RET_STATE);
if (offset == EOF)
complain((char *) 0);
if (offset == ORIGINAL)
bname = Minibuf;
else if (offset == NULLSTRING) {
if (def)
bname = def->b_name;
else
complain((char *) 0);
} else if (offset < 0)
complain((char *) 0);
else
bname = bnames[offset];
return bname;
}
BufSelect()
{
register char *bname;
bname = ask_buf(lastbuf);
SetABuf(curbuf);
SetBuf(do_select(curwind, bname));
}
static
defb_wind(b)
register Buffer *b;
{
register Window *w = fwind;
char *alt;
if (lastbuf == b || lastbuf == 0) {
lastbuf = 0;
alt = (b->b_next != 0) ? b->b_next->b_name : Mainbuf;
} else
alt = lastbuf->b_name;
do {
if (w->w_bufp == b) {
if (one_windp())
(void) do_select(w, alt);
else {
register Window *save = w->w_next;
del_wind(w);
w = save->w_prev;
}
}
w = w->w_next;
} while (w != fwind);
}
Buffer *
getNMbuf()
{
register Buffer *delbuf;
register char *bname;
bname = ask_buf(curbuf);
if ((delbuf = buf_exists(bname)) == 0)
complain("[No such buffer]");
if (delbuf->b_modified)
confirm("%s modified, are you sure? ", bname);
return delbuf;
}
BufErase()
{
register Buffer *delbuf;
if (delbuf = getNMbuf()) {
initlist(delbuf);
delbuf->b_modified = 0;
}
}
static
kill_buf(delbuf)
register Buffer *delbuf;
{
register Buffer *b,
*lastb = 0;
extern Buffer *perr_buf;
#ifdef IPROCS
pbuftiedp(delbuf); /* Make sure buffer is not tied to a process */
#endif
for (b = world; b != 0; lastb = b, b = b->b_next)
if (b == delbuf)
break;
if (lastb)
lastb->b_next = delbuf->b_next;
else
world = delbuf->b_next;
#define okay_free(ptr) if (ptr) free(ptr)
lfreelist(delbuf->b_first);
okay_free(delbuf->b_name);
okay_free(delbuf->b_fname);
free((char *) delbuf);
if (delbuf == lastbuf)
SetABuf(curbuf);
if (perr_buf == delbuf) {
ErrFree();
perr_buf = 0;
}
defb_wind(delbuf);
if (curbuf == delbuf)
SetBuf(curwind->w_bufp);
}
/* offer to kill some buffers */
KillSome()
{
register Buffer *b,
*next;
Buffer *oldb;
register char *y_or_n;
for (b = world; b != 0; b = next) {
next = b->b_next;
y_or_n = ask("No", "Kill %s? ", b->b_name);
if (Upper(*y_or_n) != 'Y')
continue;
if (IsModified(b)) {
y_or_n = ask("No", "%s modified; should I save it? ", b->b_name);
if (Upper(*y_or_n) == 'Y') {
oldb = curbuf;
SetBuf(b);
SaveFile();
SetBuf(oldb);
}
}
kill_buf(b);
}
}
BufKill()
{
Buffer *b;
if ((b = getNMbuf()) == 0)
return;
kill_buf(b);
}
static char *
line_cnt(b, buf)
register Buffer *b;
char *buf;
{
register int nlines = 0;
register Line *lp;
for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++)
;
sprintf(buf, "%d", nlines);
return buf;
}
static char *TypeNames[] = {
0,
"Scratch",
"File",
"Process",
"I-process"
};
BufList()
{
register char *format = "%-2s %-5s %-11s %-1s %-*s %-s";
register Buffer *b;
int bcount = 1, /* To give each buffer a number */
buf_width = 11;
char nbuf[10];
extern int ModCount;
for (b = world; b != 0; b = b->b_next)
buf_width = max(buf_width, 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(format, "NO", "Lines", "Type", NullStr, buf_width, "Name", "File");
Typeout(format, "--", "-----", "----", NullStr, buf_width, "----", "----");
for (b = world; b != 0; b = b->b_next) {
Typeout(format, itoa(bcount++),
line_cnt(b, 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();
}
bufname(b)
register Buffer *b;
{
char tmp[100],
*cp;
int try = 1;
if (b->b_fname == 0)
complain("[No file name]");
cp = basename(b->b_fname);
strcpy(tmp, cp);
while (buf_exists(tmp)) {
sprintf(tmp, "%s.%d", cp, try);
try++;
}
setbname(b, tmp);
}
initlist(b)
register Buffer *b;
{
lfreelist(b->b_first);
b->b_first = b->b_dot = b->b_last = 0;
(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
0. */
Buffer *
buf_exists(name)
register char *name;
{
register Buffer *bp;
register int n;
if (name == 0)
return 0;
for (bp = world; bp != 0; bp = bp->b_next)
if (strcmp(bp->b_name, name) == 0)
return bp;
/* Doesn't match any names. Try for a buffer number... */
if ((n = chr_to_int(name, 10, 1)) > 0) {
for (bp = world; n > 1; bp = bp->b_next) {
if (bp == 0)
break;
--n;
}
return bp;
}
return 0;
}
/* 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 = 0;
char fnamebuf[FILESIZE];
if (name) {
PathParse(name, fnamebuf);
if (stat(fnamebuf, s) == -1)
s->st_ino = 0;
for (b = world; b != 0; b = b->b_next) {
if ((b->b_ino != 0 && b->b_ino == s->st_ino) ||
(strcmp(b->b_fname, fnamebuf) == 0))
break;
}
}
return b;
}
char *
ralloc(obj, size)
register char *obj;
{
register char *new;
if (obj)
new = realloc(obj, (unsigned) size);
if (new == 0 || !obj)
new = emalloc(size);
return new;
}
setbname(b, name)
register Buffer *b;
register char *name;
{
UpdModLine++; /* Kludge ... but speeds things up considerably */
if (name) {
if (b->b_name == NoName)
b->b_name = 0;
b->b_name = ralloc(b->b_name, strlen(name) + 1);
strcpy(b->b_name, name);
} else
b->b_name = 0;
}
setfname(b, name)
register Buffer *b;
register char *name;
{
char wholename[FILESIZE],
oldname[FILESIZE],
*oldptr = oldname;
Buffer *save = curbuf;
SetBuf(b);
UpdModLine++; /* Kludge ... but speeds things up considerably */
if (b->b_fname == 0)
oldptr = 0;
else
strcpy(oldname, b->b_fname);
if (name) {
PathParse(name, wholename);
curbuf->b_fname = ralloc(curbuf->b_fname, strlen(wholename) + 1);
strcpy(curbuf->b_fname, wholename);
} else
b->b_fname = 0;
DoAutoExec(curbuf->b_fname, oldptr);
curbuf->b_mtime = curbuf->b_ino = 0; /* until they're known. */
SetBuf(save);
}
set_ino(b)
register Buffer *b;
{
struct stat stbuf;
if (b->b_fname == 0 || stat(b->b_fname, &stbuf) == -1) {
b->b_ino = 0;
b->b_mtime = 0;
} else {
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;
{
register Buffer *b;
b = file_exists(fname);
if (b == 0) {
b = mak_buf();
setfname(b, fname);
bufname(b);
set_ino(b);
b->b_ntbf = 1;
if (force) {
Buffer *oldb = curbuf;
SetBuf(b); /* this'll read the file */
SetBuf(oldb);
}
}
if (w)
tiewind(w, b);
return b;
}
/* Set alternate buffer */
SetABuf(b)
Buffer *b;
{
if (b != 0)
lastbuf = b;
}
SetBuf(newbuf)
register Buffer *newbuf;
{
register Buffer *oldb = curbuf;
if (newbuf == curbuf || newbuf == 0)
return;
lsave();
curbuf = newbuf;
getDOT();
/* Do the read now ... */
if (curbuf->b_ntbf)
read_file(curbuf->b_fname, 0);
#ifdef IPROCS
if (oldb != 0 && oldb->b_type != curbuf->b_type) {
if (curbuf->b_type == B_IPROCESS)
PushPBs(); /* Push process bindings */
else if (oldb->b_type == B_IPROCESS)
PopPBs();
}
assign_p(); /* Set cur_proc */
#endif
}
Buffer *
do_select(w, name)
register Window *w;
register char *name;
{
register Buffer *new;
if ((new = buf_exists(name)) == 0) {
new = mak_buf();
setfname(new, (char *) 0);
setbname(new, name);
}
if (w)
tiewind(w, new);
return new;
}