home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
text
/
vim
/
src
/
buffer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-27
|
22KB
|
1,019 lines
/* vi:ts=4:sw=4
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Read the file "credits.txt" for a list of people who contributed.
* Read the file "uganda.txt" for copying and usage conditions.
*/
/*
* buffer.c: functions for dealing with the buffer structure
*/
/*
* The buffer list is a double linked list of all buffers.
* Each buffer can be in one of these states:
* never loaded: b_neverloaded == TRUE, only the file name is valid
* not loaded: b_ml.ml_mfp == NULL, no memfile allocated
* hidden: b_nwindows == 0, loaded but not displayed in a window
* normal: loaded and displayed in a window
*
* Instead of storing file names all over the place, each file name is
* stored in the buffer list. It can be referenced by a number.
*
* The current implementation remembers all file names ever used.
*/
#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "param.h"
static void enter_buffer __ARGS((BUF *));
static BUF *buflist_findname __ARGS((char_u *));
static BUF *buflist_findnr __ARGS((int));
static void buflist_setlnum __ARGS((BUF *, linenr_t));
static linenr_t buflist_findlnum __ARGS((BUF *));
/*
* Open current buffer, that is: open the memfile and read the file into memory
* return FAIL for failure, OK otherwise
*/
int
open_buffer()
{
if (readonlymode && curbuf->b_filename != NULL)
curbuf->b_p_ro = TRUE;
if (ml_open() == FAIL)
{
/*
* There MUST be a memfile, otherwise we can't do anything
* If we can't create one for the current buffer, take another buffer
*/
close_buffer(curbuf, FALSE, FALSE);
for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
if (curbuf->b_ml.ml_mfp != NULL)
break;
/*
* if there is no memfile at all, exit
* This is OK, since there are no changes to loose.
*/
if (curbuf == NULL)
{
EMSG("Cannot allocate buffer, exiting...");
getout(2);
}
EMSG("Cannot allocate buffer, using other one...");
enter_buffer(curbuf);
return FAIL;
}
if (curbuf->b_filename != NULL)
{
if (readfile(curbuf->b_filename, curbuf->b_sfilename, (linenr_t)0,
TRUE, (linenr_t)0, MAXLNUM) == FAIL)
return FAIL;
}
else
MSG("Empty Buffer");
UNCHANGED(curbuf);
curbuf->b_neverloaded = FALSE;
return OK;
}
/*
* Close the link to a buffer. If "free_buf" is TRUE free the buffer if it
* becomes unreferenced. The caller should get a new buffer very soon!
* if 'remove' is TRUE, remove the buffer from the buffer list.
*/
void
close_buffer(buf, free_buf, remove)
BUF *buf;
int free_buf;
int remove;
{
if (buf->b_nwindows > 0)
--buf->b_nwindows;
if (buf->b_nwindows > 0 || !free_buf)
{
if (buf == curbuf)
u_sync(); /* sync undo before going to another buffer */
return;
}
buf_freeall(buf); /* free all things allocated for this buffer */
/*
* If there is no file name, remove the buffer from the list
*/
if (buf->b_filename == NULL || remove)
{
free(buf->b_filename);
free(buf->b_sfilename);
if (buf->b_prev == NULL)
firstbuf = buf->b_next;
else
buf->b_prev->b_next = buf->b_next;
if (buf->b_next == NULL)
lastbuf = buf->b_prev;
else
buf->b_next->b_prev = buf->b_prev;
free(buf);
}
else
buf_clear(buf);
}
/*
* buf_clear() - make buffer empty
*/
void
buf_clear(buf)
BUF *buf;
{
buf->b_ml.ml_line_count = 1;
buf->b_changed = FALSE;
#ifndef MSDOS
buf->b_shortname = FALSE;
#endif
buf->b_p_eol = TRUE;
buf->b_ml.ml_mfp = NULL;
buf->b_ml.ml_flags = ML_EMPTY; /* empty buffer */
}
/*
* buf_freeall() - free all things allocated for the buffer
*/
void
buf_freeall(buf)
BUF *buf;
{
u_blockfree(buf); /* free the memory allocated for undo */
ml_close(buf); /* close and delete the memline/memfile */
buf->b_ml.ml_line_count = 0; /* no lines in buffer */
u_clearall(buf); /* reset all undo information */
}
/*
* Implementation of the command for the buffer list
*/
int
do_buffer(action, start, dir, count, forceit)
int action; /* 0 = normal, 1 = split window, 2 = unload, 3 = delete */
int start; /* 0 = current, 1 = first, 2 = last, 3 = modified */
int dir; /* FORWARD or BACKWARD */
int count; /* buffer number or number of buffers */
int forceit; /* TRUE for :bdelete! */
{
BUF *buf;
int retval;
switch (start)
{
case 0: buf = curbuf;
break;
case 1: buf = firstbuf;
break;
case 2: buf = curbuf;
while (buf->b_next != NULL)
buf = buf->b_next;
break;
default: buf = curbuf;
break;
}
if (start == 3) /* find next modified buffer */
{
while (count-- > 0)
{
do
{
buf = buf->b_next;
if (buf == NULL)
buf = firstbuf;
}
while (buf != curbuf && !buf->b_changed);
}
if (!buf->b_changed)
{
EMSG("No modified buffer found");
return FAIL;
}
}
else if (start == 1 && count) /* find specified buffer number */
{
while (buf != NULL && buf->b_fnum != count)
buf = buf->b_next;
}
else
{
while (buf != NULL && count-- > 0)
{
if (dir == FORWARD)
buf = buf->b_next;
else
buf = buf->b_prev;
}
}
if (buf == NULL) /* could not find it */
{
if (start == 1)
EMSG2("Cannot go to buffer %ld", (char_u *)count);
else if (dir == FORWARD)
EMSG("Cannot go beyond last buffer");
else
EMSG("Cannot go before first buffer");
return FAIL;
}
/*
* delete buffer buf from memory and/or the list
*/
if (action == 2 || action == 3)
{
if (buf->b_nwindows > 1 || (buf != curbuf && buf->b_nwindows != 0))
{
EMSG2("Other window editing buffer %ld", (char_u *)buf->b_fnum);
return FAIL;
}
if (!forceit && buf->b_changed)
{
EMSG2("No write since last change for buffer %ld (use ! to override)",
(char_u *)buf->b_fnum);
return FAIL;
}
/*
* if deleting last buffer, make it empty
*/
if (firstbuf->b_next == NULL)
{
buf = curbuf;
retval = doecmd(NULL, NULL, NULL, FALSE, (linenr_t)1);
/* the doecmd() may create a new buffer, then we have to
* delete the old one */
if (action == 3 && buf != curbuf)
close_buffer(buf, TRUE, action == 3);
return retval;
}
/*
* If deleted buffer is not current one, delete it here.
* Otherwise find buffer to go to and delete it below.
*/
{
if (buf != curbuf)
{
close_buffer(buf, TRUE, action == 3);
return OK;
}
if (buf->b_next != NULL)
buf = buf->b_next;
else
buf = buf->b_prev;
}
}
/*
* make buf current buffer
*/
if (action == 1) /* split window first */
{
if (win_split(0L, FALSE) == FAIL)
return FAIL;
}
buflist_altlnum(); /* remember curpos.lnum */
close_buffer(curbuf, action == 2 || action == 3, action == 3);
enter_buffer(buf);
return OK;
}
/*
* enter a new current buffer.
* (old curbuf must have been freed already)
*/
static void
enter_buffer(buf)
BUF *buf;
{
int need_fileinfo = TRUE;
if (buf->b_neverloaded)
{
buf_copy_options(curbuf, buf);
buf->b_neverloaded = FALSE;
}
curwin->w_buffer = buf;
curbuf = buf;
++curbuf->b_nwindows;
if (curbuf->b_ml.ml_mfp == NULL) /* need to load the file */
{
open_buffer();
need_fileinfo = FALSE;
}
buflist_getlnum(); /* restore curpos.lnum */
maketitle();
updateScreen(NOT_VALID);
if (need_fileinfo)
fileinfo(did_cd);
}
/*
* functions for dealing with the buffer list
*/
/*
* Add a file name to the buffer list. Return a pointer to the buffer.
* If the same file name already exists return a pointer to that buffer.
* If it does not exist, or if fname == NULL, a new entry is created.
* If use_curbuf is TRUE, may use current buffer.
* This is the ONLY way to create a new buffer.
*/
BUF *
buflist_new(fname, sfname, lnum, use_curbuf)
char_u *fname;
char_u *sfname;
linenr_t lnum;
int use_curbuf;
{
static int top_file_num = 1; /* highest file number */
BUF *buf;
fname_expand(&fname, &sfname);
/*
* If file name already exists in the list, update the entry
*/
if (fname != NULL && (buf = buflist_findname(fname)) != NULL)
{
if (lnum != 0)
buflist_setlnum(buf, lnum);
if (buf->b_neverloaded && curbuf != NULL && buf != curbuf)
buf_copy_options(curbuf, buf);
return buf;
}
/*
* If the current buffer has no name and no contents, use the current buffer.
* Otherwise: Need to allocate a new buffer structure.
*
* This is the ONLY place where a new buffer structure is allocated!
*/
if (use_curbuf && curbuf != NULL && curbuf->b_filename == NULL &&
curbuf->b_nwindows <= 1 &&
(curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_flags == ML_EMPTY))
buf = curbuf;
else
{
buf = (BUF *)alloc((unsigned)sizeof(BUF));
if (buf == NULL)
return NULL;
memset((char *)buf, 0, sizeof(BUF));
}
if (fname != NULL)
{
buf->b_filename = strsave(fname);
buf->b_sfilename = strsave(sfname);
}
if (buf->b_winlnum == NULL)
buf->b_winlnum = (WINLNUM *)alloc((unsigned)sizeof(WINLNUM));
if ((fname != NULL && (buf->b_filename == NULL || buf->b_sfilename == NULL)) ||
buf->b_winlnum == NULL)
{
free(buf->b_filename);
buf->b_filename = NULL;
free(buf->b_sfilename);
buf->b_sfilename = NULL;
if (buf != curbuf)
{
free(buf->b_winlnum);
free(buf);
}
return NULL;
}
if (buf == curbuf)
{
buf_freeall(buf); /* free all things allocated for this buffer */
buf->b_nwindows = 0;
}
else
{
if (curbuf != NULL) /* don't do this for first buffer */
buf_copy_options(curbuf, buf);
/*
* put new buffer at the end of the buffer list
*/
buf->b_next = NULL;
if (firstbuf == NULL) /* buffer list is empty */
{
buf->b_prev = NULL;
firstbuf = buf;
}
else /* append new buffer at end of the list */
{
lastbuf->b_next = buf;
buf->b_prev = lastbuf;
}
lastbuf = buf;
buf->b_fnum = top_file_num++;
if (top_file_num < 0) /* wrap around (may cause duplicates) */
{
EMSG("Warning: List of file names overflow");
sleep(3); /* make sure it is noticed */
top_file_num = 1;
}
buf->b_winlnum->wl_lnum = lnum;
buf->b_winlnum->wl_next = NULL;
buf->b_winlnum->wl_prev = NULL;
buf->b_winlnum->wl_win = curwin;
}
if (did_cd)
buf->b_xfilename = buf->b_filename;
else
buf->b_xfilename = buf->b_sfilename;
buf->b_u_synced = TRUE;
buf->b_neverloaded = TRUE;
buf_clear(buf);
clrallmarks(buf); /* clear marks */
return buf;
}
/*
* get alternate file n
* set linenr to lnum or altlnum if lnum == 0
* if (setpm) setpcmark
* return FAIL for failure, OK for success
*/
int
buflist_getfile(n, lnum, setpm)
int n;
linenr_t lnum;
int setpm;
{
BUF *buf;
buf = buflist_findnr(n);
if (buf == NULL)
{
emsg(e_noalt);
return FAIL;
}
if (lnum == 0)
lnum = buflist_findlnum(buf); /* altlnum may be changed by getfile() */
RedrawingDisabled = TRUE;
if (getfile(buf->b_filename, buf->b_sfilename, setpm, lnum) <= 0)
{
RedrawingDisabled = FALSE;
return OK;
}
RedrawingDisabled = FALSE;
return FAIL;
}
/*
* go to the last know line number for the current buffer
*/
void
buflist_getlnum()
{
linenr_t lnum;
curwin->w_cursor.lnum = 1;
curwin->w_cursor.col = 0;
lnum = buflist_findlnum(curbuf);
if (lnum != 0 && lnum <= curbuf->b_ml.ml_line_count)
curwin->w_cursor.lnum = lnum;
}
/*
* find file in buffer list by name (it has to be for the current window)
* 'fname' must have a full path.
*/
static BUF *
buflist_findname(fname)
char_u *fname;
{
BUF *buf;
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
if (buf->b_filename != NULL && fnamecmp(fname, buf->b_filename) == 0)
return (buf);
return NULL;
}
/*
* find file in buffer name list by number
*/
static BUF *
buflist_findnr(nr)
int nr;
{
BUF *buf;
if (nr == 0)
nr = curwin->w_alt_fnum;
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
if (buf->b_fnum == nr)
return (buf);
return NULL;
}
/*
* get name of file 'n' in the buffer list
*/
char_u *
buflist_nr2name(n)
int n;
{
BUF *buf;
char_u *fname;
buf = buflist_findnr(n);
if (buf == NULL)
return NULL;
fname = did_cd ? buf->b_filename : buf->b_sfilename;
home_replace(fname, NameBuff, MAXPATHL);
return NameBuff;
}
/*
* set the lnum for the buffer 'buf' and the current window
*/
static void
buflist_setlnum(buf, lnum)
BUF *buf;
linenr_t lnum;
{
WINLNUM *wlp;
for (wlp = buf->b_winlnum; wlp != NULL; wlp = wlp->wl_next)
if (wlp->wl_win == curwin)
break;
if (wlp == NULL) /* make new entry */
{
wlp = (WINLNUM *)alloc((unsigned)sizeof(WINLNUM));
if (wlp == NULL)
return;
wlp->wl_win = curwin;
}
else /* remove entry from list */
{
if (wlp->wl_prev)
wlp->wl_prev->wl_next = wlp->wl_next;
else
buf->b_winlnum = wlp->wl_next;
if (wlp->wl_next)
wlp->wl_next->wl_prev = wlp->wl_prev;
}
wlp->wl_lnum = lnum;
/*
* insert entry in front of the list
*/
wlp->wl_next = buf->b_winlnum;
buf->b_winlnum = wlp;
wlp->wl_prev = NULL;
if (wlp->wl_next)
wlp->wl_next->wl_prev = wlp;
return;
}
/*
* find the lnum for the buffer 'buf' for the current window
*/
static linenr_t
buflist_findlnum(buf)
BUF *buf;
{
WINLNUM *wlp;
for (wlp = buf->b_winlnum; wlp != NULL; wlp = wlp->wl_next)
if (wlp->wl_win == curwin)
break;
if (wlp == NULL) /* if no lnum for curwin, use the first in the list */
wlp = buf->b_winlnum;
if (wlp)
return wlp->wl_lnum;
else
return (linenr_t)1;
}
/*
* list all know file names (for :files and :buffers command)
*/
void
buflist_list()
{
BUF *buf;
int len;
gotocmdline(TRUE, NUL);
for (buf = firstbuf; buf != NULL && !got_int; buf = buf->b_next)
{
if (buf != firstbuf)
msg_outchar('\n');
if (buf->b_xfilename == NULL)
STRCPY(NameBuff, "No File");
else
/* careful: home_replace calls vimgetenv(), which uses IObuff! */
home_replace(buf->b_xfilename, NameBuff, MAXPATHL);
sprintf((char *)IObuff, "%3d %c%c%c \"",
buf->b_fnum,
buf == curbuf ? '%' :
(curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
buf->b_ml.ml_mfp == NULL ? '-' :
(buf->b_nwindows == 0 ? 'h' : ' '),
buf->b_changed ? '+' : ' ');
len = STRLEN(IObuff);
STRNCPY(IObuff + len, NameBuff, (size_t)IOSIZE - 20 - len);
len = STRLEN(IObuff);
IObuff[len++] = '"';
/*
* try to put the "line" strings in column 40
*/
do
{
IObuff[len++] = ' ';
} while (len < 40 && len < IOSIZE - 18);
sprintf((char *)IObuff + len, "line %ld",
buf == curbuf ? curwin->w_cursor.lnum :
(long)buflist_findlnum(buf));
msg_outstr(IObuff);
flushbuf(); /* output one line at a time */
breakcheck();
}
msg_end();
}
/*
* get file name and line number for file 'fnum'
* used by DoOneCmd() for translating '%' and '#'
* return FAIL if not found, OK for success
*/
int
buflist_name_nr(fnum, fname, lnum)
int fnum;
char_u **fname;
linenr_t *lnum;
{
BUF *buf;
buf = buflist_findnr(fnum);
if (buf == NULL || buf->b_filename == NULL)
return FAIL;
if (did_cd)
*fname = buf->b_filename;
else
*fname = buf->b_sfilename;
*lnum = buflist_findlnum(buf);
return OK;
}
/*
* Set the current file name to 's', short file name to 'ss'.
* The file name with the full path is also remembered, for when :cd is used.
* Returns FAIL for failure (file name already in use by other buffer)
* OK otherwise.
*/
int
setfname(fname, sfname, message)
char_u *fname, *sfname;
int message;
{
BUF *buf;
if (fname == NULL || *fname == NUL)
{
curbuf->b_filename = NULL;
curbuf->b_sfilename = NULL;
}
else
{
fname_expand(&fname, &sfname);
/*
* if the file name is already used in another buffer:
* - if the buffer is loaded, fail
* - if the buffer is not loaded, delete it from the list
*/
buf = buflist_findname(fname);
if (buf != NULL && buf != curbuf)
{
if (buf->b_ml.ml_mfp != NULL) /* it's loaded, fail */
{
if (message)
EMSG("Buffer with this name already exists");
return FAIL;
}
close_buffer(buf, TRUE, TRUE); /* delete from the list */
}
fname = strsave(fname);
sfname = strsave(sfname);
if (fname == NULL || sfname == NULL)
{
free(sfname);
free(fname);
return FAIL;
}
free(curbuf->b_filename);
free(curbuf->b_sfilename);
curbuf->b_filename = fname;
curbuf->b_sfilename = sfname;
}
if (did_cd)
curbuf->b_xfilename = curbuf->b_filename;
else
curbuf->b_xfilename = curbuf->b_sfilename;
#ifndef MSDOS
curbuf->b_shortname = FALSE;
#endif
return OK;
}
/*
* set alternate file name for current window
*
* used by dowrite() and doecmd()
*/
void
setaltfname(fname, sfname, lnum)
char_u *fname;
char_u *sfname;
linenr_t lnum;
{
BUF *buf;
buf = buflist_new(fname, sfname, lnum, FALSE);
if (buf != NULL)
curwin->w_alt_fnum = buf->b_fnum;
}
/*
* add a file name to the buflist and return its number
*
* used by qf_init(), main() and doarglist()
*/
int
buflist_add(fname)
char_u *fname;
{
BUF *buf;
buf = buflist_new(fname, NULL, (linenr_t)0, FALSE);
if (buf != NULL)
return buf->b_fnum;
return 0;
}
/*
* set alternate lnum for current window
*/
void
buflist_altlnum()
{
buflist_setlnum(curbuf, curwin->w_cursor.lnum);
}
/*
* return nonzero if 'fname' is not the same file as current file
* fname must have a full path (expanded by FullName)
*/
int
otherfile(fname)
char_u *fname;
{ /* no name is different */
if (fname == NULL || *fname == NUL || curbuf->b_filename == NULL)
return TRUE;
return fnamecmp(fname, curbuf->b_filename);
}
void
fileinfo(fullname)
int fullname;
{
char_u *name;
#if 0 /* this message is quite useless */
if (bufempty())
{
MSG("Buffer Empty");
return;
}
#endif
if (curbuf->b_filename == NULL)
STRCPY(IObuff, "\"No File");
else
{
if (!fullname && curbuf->b_sfilename != NULL)
name = curbuf->b_sfilename;
else
name = curbuf->b_filename;
/* careful: home_replace cals vimgetenv(), which also uses IObuff! */
home_replace(name, IObuff + 1, IOSIZE - 1);
IObuff[0] = '"';
}
sprintf((char *)IObuff + STRLEN(IObuff),
"\"%s%s%s line %ld of %ld --%d%%-- col %d",
curbuf->b_changed ? " [Modified]" : "",
curbuf->b_notedited ? " [Not edited]" : "",
curbuf->b_p_ro ? " [readonly]" : "",
(long)curwin->w_cursor.lnum,
(long)curbuf->b_ml.ml_line_count,
(int)(((long)curwin->w_cursor.lnum * 100L) / (long)curbuf->b_ml.ml_line_count),
(int)curwin->w_cursor.col + 1);
if (arg_count > 1)
sprintf((char *)IObuff + STRLEN(IObuff), " (file %d of %d)", curwin->w_arg_idx + 1, arg_count);
msg(IObuff);
}
/*
* put filename in title bar of window and in icon title
*/
static char_u *lasttitle = NULL;
static char_u *lasticon = NULL;
void
maketitle()
{
char_u *t;
char_u *i;
if (!p_title && !p_icon)
return;
if (curbuf->b_filename == NULL)
{
t = (char_u *)"";
i = (char_u *)"No File";
}
else
{
home_replace(curbuf->b_filename, IObuff, IOSIZE);
if (arg_count > 1)
sprintf((char *)IObuff + STRLEN(IObuff), " (%d of %d)", curwin->w_arg_idx + 1, arg_count);
t = IObuff;
i = gettail(curbuf->b_filename); /* use filename only for icon */
}
free(lasttitle);
if (p_title)
lasttitle = alloc((unsigned)(STRLEN(t) + 7));
else
lasttitle = NULL;
if (lasttitle != NULL)
sprintf((char *)lasttitle, "VIM - %s", (char *)t);
free(lasticon);
if (p_icon)
lasticon = strsave(i);
else
lasticon = NULL;
resettitle();
}
void
resettitle()
{
mch_settitle(lasttitle, lasticon);
}
/*
* If fname is not a full path, make it a full path
*/
char_u *
fix_fname(fname)
char_u *fname;
{
if (fname != NameBuff) /* if not already expanded */
{
if (!isFullName(fname))
{
(void)FullName(fname, NameBuff, MAXPATHL);
fname = NameBuff;
}
#ifdef AMIGA
else
{
STRNCPY(NameBuff, fname, (size_t)MAXPATHL); /* make copy so we can change it */
fname = NameBuff;
fname_case(fname); /* set correct case for filename */
}
#endif
}
return fname;
}
/*
* make fname a full file name, set sfname to fname if not NULL
*/
void
fname_expand(fname, sfname)
char_u **fname;
char_u **sfname;
{
if (*fname == NULL) /* if no file name given, nothing to do */
return;
if (*sfname == NULL) /* if no short file name given, use fname */
*sfname = *fname;
*fname = fix_fname(*fname); /* expand to full path */
}
/*
* do_arg_all: open a window for each argument
*/
void
do_arg_all()
{
int win_count;
int i;
if (arg_count <= 1)
{
EMSG("Argument list contains less than 2 files");
return;
}
/*
* 1. close all but first window
* 2. make the desired number of windows
* 3. start editing the first window (hide the current window contents)
* 4. stuff commands to fill the other windows
*/
close_others(FALSE);
curwin->w_arg_idx = 0;
win_count = make_windows(arg_count);
for (i = 0; i < win_count; ++i)
{
/* edit file i */
(void)doecmd(arg_files[i], NULL, NULL, TRUE, (linenr_t)1);
curwin->w_arg_idx = i;
if (curwin->w_next == NULL) /* just checking */
break;
win_enter(curwin->w_next, FALSE);
}
win_enter(firstwin, FALSE); /* back to first window */
}
/*
* do_arg_all: open a window for each buffer
*
* when 'all' is TRUE, also load inactive buffers
*/
void
do_buffer_all(all)
int all;
{
int win_count;
BUF *buf;
int i;
/*
* count number of desired windows
*/
win_count = 0;
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
if (all || buf->b_ml.ml_mfp != NULL)
++win_count;
if (win_count == 0) /* Cannot happen? */
{
EMSG("No relevant entries in buffer list");
return;
}
/*
* 1. close all but first window
* 2. make the desired number of windows
* 3. stuff commands to fill the windows
*/
close_others(FALSE);
curwin->w_arg_idx = 0;
win_count = make_windows(win_count);
buf = firstbuf;
for (i = 0; i < win_count; ++i)
{
for ( ; buf != NULL; buf = buf->b_next)
if (all || buf->b_ml.ml_mfp != NULL)
break;
if (buf == NULL) /* Cannot happen? */
break;
if (i != 0)
stuffReadbuff((char_u *)"\n\027\027:"); /* CTRL-W CTRL-W */
stuffReadbuff((char_u *)":buf "); /* edit Nth buffer */
stuffnumReadbuff((long)buf->b_fnum);
buf = buf->b_next;
}
stuffReadbuff((char_u *)"\n100\027k"); /* back to first window */
}