home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
vile-src.zip
/
vile-8.1
/
window.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-19
|
27KB
|
1,130 lines
/*
* Window management. Some of the functions are internal, and some are
* attached to keys that the user actually types.
*
* $Header: /usr/build/vile/vile/RCS/window.c,v 1.85 1998/09/19 22:52:06 kev Exp $
*
*/
#include "estruct.h"
#include "edef.h"
/*
* Unlink the given window-pointer from the list
*/
static void
unlink_window(WINDOW *thewp)
{
register WINDOW *p, *q;
for (p = wheadp, q = 0; p != 0; q = p, p = p->w_wndp)
if (p == thewp) {
if (q != 0)
q->w_wndp = p->w_wndp;
else
wheadp = p->w_wndp;
break;
}
}
/*
* Set the current window (and associated current buffer).
*/
int
set_curwp (WINDOW *wp)
{
if (wp == curwp)
return (TRUE);
curwp = wp;
#if !WINMARK
/* FIXME: this wouldn't be necessary if MK were stored per-buffer */
MK = nullmark;
#endif
make_current(curwp->w_bufp);
upmode();
updatelistbuffers();
return (TRUE);
}
/*
* Adjust a LINEPTR forward by the given number of screen-rows, limited by
* the end of the buffer.
*/
static LINEPTR
adjust_forw(WINDOW *wp, LINEPTR lp, int n)
{
register int i;
LINEPTR dlp;
for (i = n; i > 0 && (lp != win_head(wp)); ) {
if ((i -= line_height(wp, lp)) < 0)
break;
dlp = lforw(lp);
if (dlp == win_head(wp))
break;
lp = dlp;
}
return lp;
}
/*
* Adjust a LINEPTR backward by the given number of screen-rows, limited by
* the end of the buffer.
*/
static LINEPTR
adjust_back(WINDOW *wp, LINEPTR lp, int n)
{
register int i;
LINEPTR dlp;
for (i = n; i > 0 && (lp != win_head(wp)); ) {
if ((i -= line_height(wp, lp)) < 0)
break;
dlp = lback(lp);
if (dlp == win_head(wp))
break;
lp = dlp;
}
return lp;
}
/*
* Reposition dot's line to line "n" of the window. If the argument is
* positive, it is that line. If it is negative it is that line from the
* bottom. If it is 0 the window is centered around dot (this is what
* the standard redisplay code does). Defaults to 0.
*/
int
reposition(int f, int n)
{
if (f) {
int an;
/* clamp the value at the size of the window */
an = absol(n);
if (an > curwp->w_ntrows)
curwp->w_force = curwp->w_ntrows * (n / an);
else
curwp->w_force = n;
curwp->w_flag |= WFFORCE;
}
return update(TRUE);
}
/*
* Refresh the screen. With no argument, it just does the refresh. With an
* argument it recenters "." in the current window.
*/
/* ARGSUSED */
int
vile_refresh(int f, int n GCC_UNUSED)
{
if (f == FALSE) {
sgarbf = TRUE;
} else {
curwp->w_force = 0; /* Center dot. */
curwp->w_flag |= WFFORCE;
}
return (TRUE);
}
/*
* The command make the next window (next => down the screen) the current
* window. There are no real errors, although the command does nothing if
* there is only 1 window on the screen.
*
* with an argument this command finds the <n>th window from the top
*
*/
int
nextwind(int f, int n)
{
register WINDOW *wp;
register int nwindows; /* total number of windows */
if (f) {
/* first count the # of windows */
nwindows = 0;
for_each_visible_window(wp)
nwindows++;
/* if the argument is negative, it is the nth window
from the bottom of the screen */
if (n < 0)
n = nwindows + n + 1;
/* if an argument, give them that window from the top */
if (n > 0 && n <= nwindows) {
wp = wheadp;
while (--n)
wp = wp->w_wndp;
} else {
mlforce("[Window number out of range]");
return(FALSE);
}
} else {
if ((wp = curwp->w_wndp) == NULL)
wp = wheadp;
}
return set_curwp(wp);
}
int
poswind(int f, int n)
{
register int c;
register int row;
int s;
if (!f)
n = 1;
if (clexec || isnamedcmd) {
static char cbuf[20];
if ((s=mlreply("Position window with cursor at: ", cbuf,
20)) != TRUE)
return s;
c = cbuf[0];
} else {
c = keystroke();
if (ABORTED(c))
return ABORT;
}
if (strchr("+hHtT\r", c)) {
row = n;
} else if (strchr(".mM", c)) {
row = 0;
} else if (strchr("-lLbB\r", c)) {
row = -n;
} else {
if (!(clexec || isnamedcmd))
kbd_alarm();
return FALSE;
}
return(reposition(TRUE,row));
}
/*
* This command makes the previous window (previous => up the screen) the
* current window. There aren't any errors, although the command does not do a
* lot if there is 1 window.
*/
int
prevwind(int f, int n)
{
register WINDOW *wp1;
register WINDOW *wp2;
/* if we have an argument, we mean the nth window from the bottom */
if (f)
return(nextwind(f, -n));
wp1 = wheadp;
wp2 = curwp;
if (wp1 == wp2)
wp2 = NULL;
while (wp1->w_wndp != wp2)
wp1 = wp1->w_wndp;
return set_curwp(wp1);
}
/*
* This command moves the current window down by "arg" lines. Recompute the
* top line in the window. The move up and move down code is almost completely
* the same; most of the work has to do with reframing the window, and picking
* a new dot. We share the code by having "move down" just be an interface to
* "move up". Magic.
*/
int
mvdnwind(int f, int n)
{
if (!f)
n = 1;
return (mvupwind(TRUE, -n));
}
/*
* Move the current window up by "arg" lines. Recompute the new top line of
* the window. Look to see if "." is still on the screen. If it is, you win.
* If it isn't, then move "." to center it in the new framing of the window
* (this command does not really move "." (except as above); it moves the
* frame).
*/
int
mvupwind(int f, int n)
{
register LINE *lp;
register int i;
int was_n = n;
lp = curwp->w_line.l;
if (!f)
n = 1;
if (n < 0)
curwp->w_flag |= WFKILLS;
else
curwp->w_flag |= WFINS;
if (n < 0) {
while (n++ && lforw(lp) != buf_head(curbp))
lp = lforw(lp);
} else {
while (n-- && lback(lp) != buf_head(curbp))
lp = lback(lp);
}
curwp->w_line.l = lp;
curwp->w_line.o = 0;
curwp->w_flag |= WFHARD | WFMODE;
/* is it still in the window */
for (i = 0; i < curwp->w_ntrows; lp = lforw(lp)) {
if ((i += line_height(curwp,lp)) > curwp->w_ntrows)
break;
if (lp == DOT.l)
return (TRUE);
if (lforw(lp) == buf_head(curbp))
break;
}
/*
* now lp is either just past the window bottom, or it's the last
* line of the file
*/
/* preserve the current column */
if (curgoal < 0)
curgoal = getccol(FALSE);
if (was_n < 0)
DOT.l = curwp->w_line.l;
else
DOT.l = lback(lp);
DOT.o = getgoal(DOT.l);
return (TRUE);
}
int
mvdnnxtwind(int f, int n)
{
int status;
(void)nextwind(FALSE, 1);
status = mvdnwind(f, n);
(void)prevwind(FALSE, 1);
return status;
}
int
mvupnxtwind(int f, int n)
{
int status;
(void)nextwind(FALSE, 1);
status = mvupwind(f, n);
(void)prevwind(FALSE, 1);
return status;
}
static int
scroll_sideways(int f, int n)
{
int original = w_val(curwp,WVAL_SIDEWAYS);
if (!f) {
int nominal = term.t_ncol / 2;
n = (n > 0) ? nominal : -nominal;
}
make_local_w_val(curwp,WVAL_SIDEWAYS);
w_val(curwp, WVAL_SIDEWAYS) += n;
if (w_val(curwp, WVAL_SIDEWAYS) < 0) {
if (original == 0)
kbd_alarm();
w_val(curwp, WVAL_SIDEWAYS) = 0;
}
if (original != w_val(curwp,WVAL_SIDEWAYS))
curwp->w_flag |= WFHARD|WFMOVE|WFMODE;
return TRUE;
}
int
mvrightwind(int f, int n)
{
return scroll_sideways(f,n);
}
int
mvleftwind(int f, int n)
{
return scroll_sideways(f,-n);
}
/*
* This command makes the current window the only window on the screen.
* Try to set the framing so that "." does not have to move on the
* display. Some care has to be taken to keep the values of dot and mark in
* the buffer structures right if the distruction of a window makes a buffer
* become undisplayed.
*/
/* ARGSUSED */
int
onlywind(int f GCC_UNUSED, int n GCC_UNUSED)
{
register WINDOW *wp;
wp = wheadp;
while (wp != NULL) {
register WINDOW *nwp;
nwp = wp->w_wndp;
if (wp != curwp) {
if (--wp->w_bufp->b_nwnd == 0)
undispbuff(wp->w_bufp,wp);
unlink_window(wp);
free((char *) wp);
}
wp = nwp;
}
wheadp = curwp;
wheadp->w_wndp = NULL;
curwp->w_line.l = adjust_back(curwp, curwp->w_line.l, curwp->w_toprow);
curwp->w_line.o = 0;
curwp->w_ntrows = term.t_nrow-2;
curwp->w_toprow = 0;
curwp->w_flag |= WFMODE|WFHARD|WFSBAR;
curwp->w_split_hist = 0;
return (TRUE);
}
/*
* Delete the current window
*/
/* ARGSUSED */
int
delwind(int f GCC_UNUSED, int n GCC_UNUSED)
{
return delwp(curwp);
}
/*
* We attach to each window structure another field (an unsigned long)
* which I called w_split_history. When we split a window, we shift this
* field left by one bit. The least significant bit for the upper window
* is 0, the bottom window's lsb is set to 1.
*
* We examine the lsb when deleting windows to decide whether to give up
* the space for the deleted window to the upper window or lower window.
* If the lsb is 0, we give it to the lower window. If it is 1 we give it
* to the upper window. If the lsb of the receiving window is different
* from that of the window being deleted, this means that the two match and
* so the history is shifted right by one bit for the receiving window.
* Otherwise we leave the history alone.
* kev, 2/94
*
* Example:
*
* | | | 00 | 00 | 00 | 00
* | | 0 - - - -
* | | | 01 | 01 | 01 | 01
* | 0 --> - --> - --> - --> - --> |
* | | | | 10 | |
* | | 1 | 1 - | 1 |
* | | | | 11 | |
*
* Full Split Split and Kill Kill
* Screen Again Again either 1
* 10 or
* 11
*/
int
delwp(WINDOW *thewp)
{
register WINDOW *wp; /* window to receive deleted space */
int visible = is_visible_window(thewp);
/* if there is only one window, don't delete it */
if (wheadp->w_wndp == NULL) {
mlforce("[Cannot delete the only window]");
return(FALSE);
}
/* find receiving window and give up our space */
if (thewp == wheadp
|| ((thewp->w_split_hist & 1) == 0 && thewp->w_wndp)
|| !visible) {
/* merge with next window down */
wp = thewp->w_wndp;
if (visible) {
wp->w_line.l = adjust_back(wp, wp->w_line.l,
thewp->w_ntrows+1);
wp->w_line.o = 0;
wp->w_ntrows += thewp->w_ntrows+1;
wp->w_toprow = thewp->w_toprow;
if (wp->w_split_hist & 1)
wp->w_split_hist >>= 1;
}
if (thewp == wheadp)
wheadp = wp;
else {
WINDOW *pwp = wheadp;
while(pwp->w_wndp != thewp)
pwp = pwp->w_wndp;
pwp->w_wndp = wp;
}
} else {
/* find window before thewp in linked list */
wp = wheadp;
while(wp->w_wndp != thewp)
wp = wp->w_wndp;
/* add thewp's rows to the next window up */
wp->w_ntrows += thewp->w_ntrows+1;
wp->w_wndp = thewp->w_wndp; /* make their next window ours */
if ((wp->w_split_hist & 1) == 0)
wp->w_split_hist >>= 1;
}
/* get rid of the current window */
if (visible && --thewp->w_bufp->b_nwnd == 0)
undispbuff(thewp->w_bufp,thewp);
if (thewp == curwp) {
curwp = wp;
make_current(curwp->w_bufp);
}
free((char *)thewp);
if (visible) {
upmode();
wp->w_flag |= WFSBAR | WFHARD;
}
return(TRUE);
}
/*
* Copy the window-traits struct, and adjust the embedded VAL struct so that
* modes that are local remain so.
*/
void
copy_traits(W_TRAITS *dst, W_TRAITS *src)
{
*dst = *src;
copy_mvals(NUM_W_VALUES, dst->w_vals.wv, src->w_vals.wv);
}
/*
Split the current window. A window smaller than 3 lines cannot be
split. An argument of 1 forces the cursor into the upper window, an
argument of two forces the cursor to the lower window. The only other
error that is possible is a "malloc" failure allocating the structure
for the new window.
*/
static WINDOW *
splitw(int f, int n)
{
register WINDOW *wp;
register LINE *lp;
register int ntru;
register int ntrl;
register int ntrd;
register WINDOW *wp1;
register WINDOW *wp2;
if (curwp->w_ntrows < MINWLNS) {
mlforce("[Cannot split a %d line window]", curwp->w_ntrows);
return NULL;
}
/* set everything to 0's unless we want nonzero */
if ((wp = typecalloc(WINDOW)) == NULL) {
(void)no_memory("WINDOW");
return NULL;
}
++curwp->w_bufp->b_nwnd; /* Displayed twice. */
wp->w_bufp = curwp->w_bufp;
copy_traits(&(wp->w_traits), &(curwp->w_traits));
ntru = (curwp->w_ntrows-1) / 2; /* Upper size */
ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */
lp = curwp->w_line.l;
ntrd = 0;
while (lp != DOT.l) {
ntrd += line_height(wp,lp);
lp = lforw(lp);
}
/* ntrd is now the row containing dot */
if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
/* Old is upper window. */
/* Adjust the top line if necessary */
if (ntrd == ntru) { /* Hit mode line. */
if (ntrl > 1) {
ntru++;
ntrl--;
} else {
curwp->w_line.l = lforw(curwp->w_line.l);
curwp->w_line.o = 0;
}
}
curwp->w_ntrows = ntru; /* new size */
/* insert new window after curwp in window list */
wp->w_wndp = curwp->w_wndp;
curwp->w_wndp = wp;
/* set new window's position and size */
wp->w_toprow = curwp->w_toprow+ntru+1;
wp->w_ntrows = ntrl;
/* try to keep lower from reframing */
wp->w_line.l = adjust_forw(wp, wp->w_line.l, ntru+1);
wp->w_line.o = 0;
wp->w_dot.l = wp->w_line.l;
wp->w_dot.o = 0;
/* update the split history */
curwp->w_split_hist <<= 1;
wp->w_split_hist = curwp->w_split_hist | 1;
} else {
/* Old is lower window */
wp1 = NULL;
wp2 = wheadp;
while (wp2 != curwp) {
wp1 = wp2;
wp2 = wp2->w_wndp;
}
if (wp1 == NULL)
wheadp = wp;
else
wp1->w_wndp = wp;
wp->w_wndp = curwp;
wp->w_toprow = curwp->w_toprow;
wp->w_ntrows = ntru;
++ntru; /* Mode line. */
curwp->w_toprow += ntru;
curwp->w_ntrows = ntrl;
wp->w_dot.l = wp->w_line.l;
/* move upper window dot to bottom line of upper */
wp->w_dot.l = adjust_forw(wp, wp->w_dot.l, ntru-2);
wp->w_dot.o = 0;
/* adjust lower window topline */
curwp->w_line.l = adjust_forw(curwp, curwp->w_line.l, ntru);
curwp->w_line.o = 0;
/* update the split history */
wp->w_split_hist <<= 1;
curwp->w_split_hist = wp->w_split_hist | 1;
}
curwp->w_flag |= WFMODE|WFHARD|WFSBAR;
wp->w_flag |= WFMODE|WFHARD;
return wp;
}
/* external callable version -- return int instead of (WINDOW *) */
int
splitwind(int f, int n)
{
return (splitw(f,n)) ? TRUE:FALSE;
}
/*
* Enlarge the current window. Find the window that loses space. Make sure it
* is big enough. If so, hack the window descriptions, and ask redisplay to do
* all the hard work. You don't just set "force reframe" because dot would
* move.
*/
int
enlargewind(int f, int n)
{
register WINDOW *adjwp;
if (n < 0)
return (shrinkwind(f, -n));
if (wheadp->w_wndp == NULL) {
mlforce("[Only one window]");
return (FALSE);
}
if ((adjwp=curwp->w_wndp) == NULL) {
adjwp = wheadp;
while (adjwp->w_wndp != curwp)
adjwp = adjwp->w_wndp;
}
if (adjwp->w_ntrows <= n) {
mlforce("[Impossible change]");
return (FALSE);
}
if (curwp->w_wndp == adjwp) { /* Shrink below. */
adjwp->w_line.l = adjust_forw(adjwp, adjwp->w_line.l, n);
adjwp->w_line.o = 0;
adjwp->w_toprow += n;
} else { /* Shrink above. */
curwp->w_line.l = adjust_back(curwp, curwp->w_line.l, n);
curwp->w_line.o = 0;
curwp->w_toprow -= n;
}
curwp->w_ntrows += n;
adjwp->w_ntrows -= n;
curwp->w_flag |= WFMODE|WFHARD|WFINS|WFSBAR;
adjwp->w_flag |= WFMODE|WFHARD|WFKILLS;
return (TRUE);
}
/*
* Shrink the current window. Find the window that gains space. Hack at the
* window descriptions. Ask the redisplay to do all the hard work.
*/
int
shrinkwind(int f, int n)
{
register WINDOW *adjwp;
if (n < 0)
return (enlargewind(f, -n));
if (wheadp->w_wndp == NULL) {
mlforce("[Only one window]");
return (FALSE);
}
if ((adjwp=curwp->w_wndp) == NULL) {
adjwp = wheadp;
while (adjwp->w_wndp != curwp)
adjwp = adjwp->w_wndp;
}
if (curwp->w_ntrows <= n) {
mlforce("[Impossible change]");
return (FALSE);
}
if (curwp->w_wndp == adjwp) { /* Grow below. */
adjwp->w_line.l = adjust_back(adjwp, adjwp->w_line.l, n);
adjwp->w_line.o = 0;
adjwp->w_toprow -= n;
} else { /* Grow above. */
curwp->w_line.l = adjust_forw(curwp, curwp->w_line.l, n);
curwp->w_line.o = 0;
curwp->w_toprow += n;
}
curwp->w_ntrows -= n;
adjwp->w_ntrows += n;
curwp->w_flag |= WFMODE|WFHARD|WFKILLS|WFSBAR;
adjwp->w_flag |= WFMODE|WFHARD|WFINS;
return (TRUE);
}
/* Resize the current window to the requested size */
int
resize(int f, int n)
{
int clines; /* current # of lines in window */
/* must have a non-default argument, else ignore call */
if (f == FALSE)
return(TRUE);
/* find out what to do */
clines = curwp->w_ntrows;
/* already the right size? */
if (clines == n)
return(TRUE);
return(enlargewind(TRUE, n - clines));
}
/*
* Pick a window for a pop-up. Split the screen if there is only one window.
* Pick the uppermost window that isn't the current window. An LRU algorithm
* might be better. Return a pointer, or NULL on error.
*/
WINDOW *
wpopup(void)
{
register WINDOW *wp;
register WINDOW *owp;
register WINDOW *biggest_wp;
owp = curwp;
wp = biggest_wp = wheadp; /* Find window to split */
while (wp->w_wndp != NULL) {
wp = wp->w_wndp;
if(wp->w_ntrows > biggest_wp->w_ntrows)
biggest_wp = wp;
}
if (biggest_wp->w_ntrows >= MINWLNS) {
curwp = biggest_wp;
wp = splitw(FALSE,0); /* yes -- choose the unoccupied half */
curwp = owp;
}
else {
/* biggest_wp was too small */
wp = wheadp; /* Find window to use */
while (wp!=NULL && wp==curwp) /* uppermost non-current window */
wp = wp->w_wndp;
if (wp == NULL)
wp = wheadp;
}
return wp;
}
/*
* Shrink or expand current window to the number of lines in the buffer.
* If the buffer is too large, make the window as large as possible using
* space from window closest in the split history.
*/
void
shrinkwrap(void)
{
L_NUM nlines;
if (wheadp->w_wndp == NULL)
return; /* only one window */
nlines = line_count(curwp->w_bufp);
if (nlines <= 0)
nlines = 1;
if (nlines == curwp->w_ntrows)
return;
if ((curwp->w_split_hist & 1) == 0 || wheadp == curwp) {
int nrows, snrows;
/* give/steal from lower window */
nrows = curwp->w_ntrows + curwp->w_wndp->w_ntrows - 1;
/* don't take more than 3/4 of its rows */
snrows = (nrows*3)/4;
if (nlines > snrows)
nlines = snrows;
resize(TRUE, nlines);
}
else {
/* give/steal from upper window; need to find upper window */
register WINDOW *wp;
WINDOW *savewp = curwp;
int nrows, snrows;
for (wp = wheadp;
wp->w_wndp != curwp && wp->w_wndp != NULL;
wp = wp->w_wndp)
;
curwp = wp;
nrows = curwp->w_ntrows + curwp->w_wndp->w_ntrows - 1;
/* don't take more than 3/4 of its rows */
snrows = (nrows*3)/4;
if (nlines > snrows)
nlines = snrows;
resize(TRUE, nrows - nlines + 1);
curwp = savewp;
}
}
int
scrnextup(int f, int n) /* scroll the next window up (back) a page */
{
int status;
(void)nextwind(FALSE, 1);
status = backhpage(f, n);
(void)prevwind(FALSE, 1);
return status;
}
int
scrnextdw(int f, int n) /* scroll the next window down (forward) a page */
{
int status;
(void)nextwind(FALSE, 1);
status = forwhpage(f, n);
(void)prevwind(FALSE, 1);
return status;
}
#if ! SMALLER
/* ARGSUSED */
int
savewnd(int f GCC_UNUSED, int n GCC_UNUSED) /* save ptr to current window */
{
swindow = curwp;
return(TRUE);
}
/* ARGSUSED */
int
restwnd(int f GCC_UNUSED, int n GCC_UNUSED) /* restore the saved screen */
{
register WINDOW *wp;
/* find the window */
for_each_visible_window(wp) {
if (wp == swindow)
return set_curwp(wp);
}
mlforce("[No such window exists]");
return(FALSE);
}
#endif
int
newlength(int f, int n) /* resize the screen, re-writing the screen */
{
WINDOW *wp; /* current window being examined */
WINDOW *nextwp; /* next window to scan */
WINDOW *lastwp; /* last window scanned */
if (!f) {
mlforce("[No length given]");
return FALSE;
}
/* make sure it's in range */
if (n < MINWLNS || n > term.t_mrow) {
mlforce("[Screen length out of range]");
return(FALSE);
}
if (term.t_nrow == n) {
return(TRUE);
} else if (wheadp != 0 && term.t_nrow < n) {
/* go to the last window */
wp = wheadp;
while (wp->w_wndp != NULL)
wp = wp->w_wndp;
/* and enlarge it as needed */
wp->w_ntrows = n - wp->w_toprow - 2;
wp->w_flag |= WFHARD|WFMODE;
} else {
/* rebuild the window structure */
nextwp = wheadp;
lastwp = NULL;
while (nextwp != NULL) {
wp = nextwp;
nextwp = wp->w_wndp;
/* get rid of it if it is too low */
if (wp->w_toprow >= n - 2) {
if (--wp->w_bufp->b_nwnd == 0) {
undispbuff(wp->w_bufp,wp);
}
/* update curwp and lastwp if needed */
if (wp == curwp) {
curwp = wheadp;
make_current(curwp->w_bufp);
}
if (lastwp != NULL)
lastwp->w_wndp = NULL;
/* free the structure */
free((char *)wp);
wp = NULL;
} else {
/* need to change this window size? */
if (mode_row(wp) >= n - 3) {
wp->w_ntrows = n - wp->w_toprow - 2;
wp->w_flag |= WFHARD|WFMODE;
}
}
lastwp = wp;
}
}
/* screen is garbage */
term.t_nrow = n;
sgarbf = TRUE;
return(TRUE);
}
int
newwidth(int f, int n) /* resize the screen, re-writing the screen */
{
register WINDOW *wp;
if (!f) {
mlforce("[No width given]");
return FALSE;
}
/* make sure it's in range */
if (n < 10 || n > term.t_mcol) {
mlforce("[Screen width out of range]");
return(FALSE);
}
/* otherwise, just re-width it (no big deal) */
term.t_ncol = n;
term.t_margin = n / 10;
term.t_scrsiz = n - (term.t_margin * 2);
/* force all windows to redraw */
for_each_visible_window(wp)
wp->w_flag |= WFHARD | WFMOVE | WFMODE;
sgarbf = TRUE;
return(TRUE);
}
#if OPT_EVAL
int
getwpos(void) /* get screen offset of current line in current window */
{
register int sline; /* screen line from top of window */
register LINE *lp; /* scannile line pointer */
/* search down the line we want */
lp = curwp->w_line.l;
sline = 1;
while (lp != DOT.l) {
sline += line_height(curwp,lp);
lp = lforw(lp);
}
/* and return the value */
return(sline);
}
#endif
/*
* Initialize all of the windows.
*/
void
winit(int screen)
{
register WINDOW *wp;
wp = typecalloc(WINDOW); /* First window */
if (wp==NULL)
ExitProgram(BADEXIT);
wheadp = wp;
curwp = wp;
wp->w_wndp = NULL; /* Initialize window */
wp->w_dot = nullmark;
wp->w_line = nullmark;
#if WINMARK
wp->w_mark = nullmark;
#endif
wp->w_lastdot = nullmark;
wp->w_toprow = 0;
wp->w_values = global_w_values;
wp->w_ntrows = screen
? term.t_nrow-2 /* "-1" for mode line. */
: 1; /* command-line */
wp->w_force = 0;
wp->w_flag = WFMODE|WFHARD; /* Full. */
wp->w_bufp = NULL;
if (screen) {
(void)bsizes(bminip); /* FIXME */
TRACE(("winit delinking bminip, %d lines, %ld bytes\n",
bminip->b_linecount,
bminip->b_bytecount));
(void) delink_bp(bminip);
} else {
/* create the command-buffer */
TRACE(("winit creating bminip & wminip\n"));
wminip = wp;
bminip = wp->w_bufp = bfind("", BFINVS);
b_set_scratch(bminip);
addline(bminip, "", 0);
wminip->w_dot = bminip->b_dot;
make_local_w_val(wminip,WMDNUMBER);
set_w_val(wminip, WMDNUMBER, FALSE);
make_local_w_val(wminip,WMDLIST);
set_w_val(wminip, WMDLIST, TRUE);
#ifdef WMDLINEWRAP
make_local_w_val(wminip,WMDLINEWRAP);
set_w_val(wminip, WMDLINEWRAP, FALSE);
#endif
}
}
/* For memory-leak testing (only!), releases all display storage. */
#if NO_LEAKS
void wp_leaks(void)
{
register WINDOW *wp;
while ((wp = wheadp) != 0) {
wp = wp->w_wndp;
free((char *)wheadp);
wheadp = wp;
}
free((char *)wminip);
}
#endif
#if OPT_SEL_YANK || OPT_PERL
/*
* Allocate a fake window so that we can yank a selection even if the buffer
* containing the selection is not attached to any window.
*
* curwp is set to the new fake window. A pointer to the old curwp is returned
* for a later call to pop_fake_win() which will restore curwp.
*/
WINDOW *
push_fake_win(BUFFER *bp)
{
WINDOW *oldwp = curwp;
WINDOW *wp;
if ((wp = typealloc(WINDOW)) == NULL) {
(void)no_memory("WINDOW");
return NULL;
}
curwp = wp;
curwp->w_bufp = bp;
if ((wp = bp2any_wp(bp)) == NULL)
copy_traits(&(curwp->w_traits), &(bp->b_wtraits));
else
copy_traits(&(curwp->w_traits), &(wp->w_traits));
curwp->w_flag = 0;
curwp->w_force = 0;
curwp->w_toprow = wheadp->w_toprow - 2; /* should be negative */
curwp->w_ntrows = 1;
curwp->w_wndp = wheadp;
wheadp = curwp;
return oldwp;
}
/*
* kill top fake window allocated by alloc_fake_win;
*
* Set curwp to the oldwp parameter.
*
* Return 0 if no fake window popped, else return the buffer pointer
* of the popped window.
*
*/
BUFFER *
pop_fake_win(WINDOW *oldwp)
{
WINDOW *wp;
BUFFER *bp;
curwp = oldwp;
wp = wheadp;
if (wp->w_toprow >= 0)
return NULL; /* not a fake window */
bp = wp->w_bufp;
/* unlink and free the fake window */
wheadp = wp->w_wndp;
free((char *)wp);
return bp;
}
#endif