minix/commands/elle/eebuff.c
2009-11-09 10:26:00 +00:00

1073 lines
26 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
* This software is quasi-public; it may be used freely with
* like software, but may NOT be sold or made part of licensed
* products without permission of the author.
*/
/* EEBUFF Buffer and Window functions.
* Each buffer is an independent SB-string described by a
* buffer structure. All buffer structures are allocated dynamically
* and chained together starting from buf_head.
*/
#include "elle.h"
#if FX_FILLMODE
extern int fill_mode;
#endif
#if FX_SKMAC
extern int kdef_mode;
#endif
struct buffer *make_buf(), *find_buf(), *sel_mbuf(), *sel_nbuf();
struct window *make_win();
/* EFUN: "Select Buffer" */
/* Select old buffer or create a new one. Defaults to previously
* used buffer.
*/
f_selbuffer()
{ register char *ans;
register struct buffer *b;
if((b = last_buf) == cur_buf) /* If default same as current, */
if(!(b = sel_mbuf(b))) /* try to pick a more useful one. */
b = sel_nbuf(cur_buf);
ans = ask("Select buffer (%s): ",b->b_name);
if (ans == 0) /* he aborted */
return;
if (*ans != '\0') /* Null string => use last buff */
{ b = find_buf (ans); /* Else find/create one */
if (b == 0)
b = make_buf (ans);
}
sel_buf(b);
chkfree(ans);
}
#if FX_SELXBUFFER
/* EFUN: "Select Existing Buffer" (not EMACS) - from IMAGEN config */
static int findstr();
f_selxbuffer()
{ register char *ans;
register struct buffer *b;
b = last_buf; /* This is default */
ans = ask("Select existing buffer (%s): ", b->b_name);
if (ans == 0) /* Aborted */
return;
if (*ans != 0)
{ for (b = buf_head; b != 0; b = b->b_next)
if (findstr(ans, b->b_name))
break;
if (b == 0)
ding("That isn't a substring of any buffer name!");
}
chkfree(ans);
if (b != 0)
{ saytoo(" => ");
sayntoo(b->b_name);
sel_buf(b);
}
}
static int
findstr(str, instr) /* Find "str" in string "instr" */
register char *str, *instr;
{ register char *sp, *isp;
while (*instr)
{ sp = str;
isp = instr;
while (*sp)
if (*sp++ != *isp++)
goto next;
return(1);
next: ++instr;
}
return(0);
}
#endif /*FX_SELXBUFFER*/
/* EFUN: "Kill Buffer" */
/* Kill specified buffer - defaults to current buffer.
* This code assumes a killed buffer will never be on a window list unless it
* is pointed to by cur_buf or oth_win->w_buf!!!!
*/
f_kbuffer()
{ register struct buffer *b, *ob;
register char *ans;
if((ans = ask("Kill buffer: ")) == 0)
return;
if(*ans == 0) b = cur_buf;
else if(*ans == SP) b = 0;
else b = find_buf(ans);
chkfree(ans);
if(!b)
{ ding("No such buffer");
return;
}
#if IMAGEN
if (b->b_flags & B_PERMANENT)
{ ding("Permanent buffer--cannot kill!");
return;
}
if (b->b_flags & B_MODIFIED)
{ if ((ans == ask("Buffer is modified; are you sure? ")) == 0)
return;
if(upcase(*ans) != 'Y')
{ chkfree(ans);
return;
}
chkfree(ans);
}
#endif /*IMAGEN*/
if(b == cur_buf || (oth_win && (oth_win->w_buf == b)))
{ ob = last_buf;
do
{
/* If default same as doomed buffer, try to pick
* a more useful alternative. */
if((b == ob) && !(ob = sel_mbuf(b)))
ob = sel_nbuf(b);
ans = ask("Killing in-use buffer; select which other buffer (%s): ",
ob->b_name);
if(ans == 0) return;
if(*ans)
{ if(*ans == SP) ob = 0;
else ob = find_buf(ans);
}
chkfree(ans);
if(!ob)
{ ding("No such buffer");
return;
}
} while (b == ob);
/* B is buffer to kill, OB is buffer to replace it with */
if(oth_win && (oth_win->w_buf == b))
{ f_othwind(); /* Select other one */
chg_buf(ob); /* Change to new buffer */
f_othwind();
}
if(cur_buf == b)
chg_buf(ob);
}
kill_buf(b); /* Die!!!! */
if(last_buf == b)
last_buf = cur_buf;
}
/* EFUN: "List Buffers" */
/* Display a list of all user buffers. Internal buffers, whose names
* start with a space, are not shown.
*/
f_listbufs()
{
register struct buffer *b;
register char *cp;
register int i;
struct buffer *tbuf, *savbuf;
char temp[20];
/* First must set up special buffer... */
savbuf = cur_buf;
chg_buf(tbuf = make_buf(" **SHOW**"));
e_sputz("Buffers in this ELLE:\n\n");
for(b = buf_head; b; b = b->b_next)
{ cp = b->b_name;
if(*cp == SP) continue; /* Ignore internal buffs */
e_sputz((b->b_flags&B_MODIFIED) ? "* " : " ");
e_sputz(cp); /* Insert buffer name */
dottoa(temp,ex_blen(b)); /* Get buff-length string */
if((i = ((FNAMELEN > 14) ? 30 : 20)
- strlen(cp) - strlen(temp)) > 0)
e_insn(SP, i);
e_sputz(" (");
e_sputz(temp);
e_sputz(") ");
if(cp = b->b_fn)
e_sputz(cp);
#if IMAGEN
if (b->b_flags & B_CMODE)
e_sputz(" (C)");
else if (b->b_flags & B_TEXTMODE)
e_sputz(" (Text)");
else
e_sputz(" (Fundamental)");
#endif /*IMAGEN*/
e_putc(LF);
}
mk_showin(tbuf); /* Show this buffer in temp window */
chg_buf(savbuf); /* Return to real current buffer */
kill_buf(tbuf);
}
/* EFUN: "Buffer Not Modified" */
/* Mark the current buffer as not modified.
*/
f_bufnotmod()
{
cur_buf -> b_flags &= ~B_MODIFIED;
redp(RD_MODE);
}
#if FX_EOLMODE
/* EFUN: "EOL CRLF Mode" (not EMACS) */
/* Toggle the EOL mode of the current buffer.
** LF EOL Mode means LF alone is an EOL.
** CRLF EOL Mode means CRLF together is an EOL.
*/
f_eolmode()
{
cur_buf->b_flags ^= B_EOLCRLF; /* Flip this bit */
say((cur_buf->b_flags & B_EOLCRLF)
? "EOL Mode is CRLF" /* If now on */
: "EOL Mode is LF"); /* If now off */
redp(RD_WINRES); /* Redo window for this buf */
}
#endif /*FX_EOLMODE*/
#if FX_GOBEG
/* EFUN: "Goto Beginning" */
f_gobeg()
{ e_gobob();
ed_setcur();
}
#endif /*FX_GOBEG*/
#if FX_GOEND
/* EFUN: "Goto End" */
f_goend()
{ e_goeob();
ed_setcur();
}
#endif /*FX_GOEND*/
#if FX_WHATPAGE
/* EFUN: "What Page" */
/* Extra info added as per earlier ICONOGRAPHICS "What Buffer Position"
** Reports on current position as follows:
** Dot=<n>, Page <n> Line <n> (line <n> of <m>)
*/
f_whatpage()
{
register chroff cnt;
register int c;
register int page, line;
int lineatp;
char tempstr[12], *dottoa ();
saynow("Dot=");
dottoa(tempstr, cur_dot);
sayntoo(tempstr);
e_gobob();
page = line = lineatp = 1;
for (cnt = cur_dot; --cnt >= 0;)
if ((c = e_getc()) == LF)
++line;
else if (c == FF)
{ ++page;
lineatp = line;
}
saytoo(", Page ");
dottoa(tempstr, (chroff)page);
saytoo(tempstr);
saytoo(" Line ");
dottoa(tempstr, (chroff)(1 + line - lineatp));
saytoo(tempstr);
saytoo(" Col ");
dottoa(tempstr, (chroff)indtion(cur_dot));
saytoo(tempstr);
saytoo(" [line ");
dottoa(tempstr, (chroff)line);
saytoo(tempstr);
sayntoo(" of "); /* Force out while scan rest */
for(e_gocur(); e_gonl() ; ++line) ; /* Count lines until EOF */
c = e_rgetc(); /* Remember what last char is */
dottoa(tempstr, (chroff)line);
saytoo(tempstr);
if (c != LF) /* Check last char */
saytoo(" (no EOL at EOF!)");
sayntoo("]");
e_gocur(); /* Back to original position */
}
#endif /*FX_WHATPAGE*/
init_buf () /* init buffer stuff */
{
buf_head = 0;
lines_buf = cur_buf = make_buf(" **LINES**"); /* For sep_win */
e_insn('-',scr_wid-2); /* Fill with dashes */
last_buf = cur_buf = make_buf ("Main"); /* Make Main buffer */
init_win(); /* Now can init windows */
}
struct buffer *
make_buf(bname) /* create buffer "bname" if it doesn't exist */
char *bname;
{ register struct buffer *b;
register char *name;
b = find_buf(name = bname);
if (b) /* if it exists already */
return(b);
b = (struct buffer *) memalloc(sizeof (struct buffer));
b -> b_next = buf_head; /* link it in */
buf_head = b;
b->b_name = strdup(name); /* Allocate copy of name string */
b->b_dot = 0; /* Set dot to beg */
sb_open(b,(SBSTR *)0); /* Open buffer with null initial sbstring */
b->b_fn = 0;
b->b_flags = 0;
b->b_mode = cur_mode; /* Inherit current mode */
return(b);
}
struct buffer *
find_buf(name) /* returns pointer to buffer of that name or 0 */
char *name;
{ register struct buffer *b = buf_head;
while (b && strcmp(b->b_name, name))
b = b -> b_next;
return(b);
}
sel_buf(b) /* select buffer, saving last */
struct buffer *b;
{
if(b != cur_buf) last_buf = cur_buf;
chg_buf(b);
}
chg_buf (newbuf) /* change current buffer to newbuf */
struct buffer *newbuf;
{ register struct buffer *obuf, *nbuf;
if ((nbuf = newbuf) == (obuf = cur_buf))
return; /* Do nothing if same buffers */
obuf->b_dot = cur_dot;
cur_buf = nbuf;
cur_mode = nbuf->b_mode;
e_gosetcur(nbuf->b_dot); /* Set cur_dot and go there */
cur_win->w_buf = nbuf;
cur_win->w_dot = cur_dot;
#if IMAGEN
cur_win->w_redp = RD_WINRES|RD_REDO;
#else
cur_win->w_redp = RD_WINRES; /* Reset flags - do complete update */
#endif /*-IMAGEN*/
unlk_buf(obuf); /* Unlock previous buffer if can */
mark_p = 0; /* this is lazy */
redp(RD_MODE|RD_WINRES);
}
/* See if specified buffer belongs to any active window, and
* if not then get it into an idle, unlocked state; this helps the
* edit package compact and swap stuff out while it's not being used.
* Assumes proper state of dot has been stored into b_dot.
*/
unlk_buf(bufp)
struct buffer *bufp;
{ register struct buffer *b;
register struct window *w;
b = bufp;
for(w = win_head; w; w = w->w_next)
if(b == w->w_buf)
return; /* Buffer is actively being shown */
sb_rewind((SBBUF *)b); /* Return to idle state */
}
/* SEL_NBUF(buf) - Select next user buffer. Ignores internal buffers.
* Arg of 0 starts at beg of buffer list. Always returns
* a buffer pointer - returns argument (which may be 0)
* if found no other user buffers.
*
* SEL_MBUF(buf) - Select next modified buffer.
* Returns buffer ptr to "next" modified buffer, if any.
* Arg of 0 starts at beg of buffer list and scans all of them.
* Returns 0 if no other modified buffers exist (unlike SEL_NBUF!)
* Ignores internal buffers, whose names start with a space.
*/
/* struct buffer *buf_mptr; */
#if 0
struct buffer *
sel_mbuf(buf)
struct buffer *buf;
{ register struct buffer *b;
register int sweep;
sweep = 0; /* Make 2 sweeps only */
if(b = buf) b = b->b_next;
do {
if(b == 0) /* Initialize if needed */
b = buf_head;
for(; b; b = b->b_next)
if((b->b_flags & B_MODIFIED) && (*b->b_name != SP))
return((b == buf) ? 0 : b);
} while(sweep++ != 0);
return(0);
}
#endif /*COMMENT*/
struct buffer *
sel_mbuf(buf)
register struct buffer *buf;
{ register struct buffer *b, *b2;
b = b2 = sel_nbuf(buf);
do { if(b == buf) break;
if(b->b_flags & B_MODIFIED)
return(b);
} while((b = sel_nbuf(b)) != b2);
return(0);
}
struct buffer *
sel_nbuf(buf)
register struct buffer *buf;
{ register struct buffer *b;
b = buf;
do {
if(!b || !(b = b->b_next))
b = buf_head;
if(*b->b_name != SP)
break;
} while (b != buf);
return(b);
}
kill_buf(buf)
struct buffer *buf;
{ register struct buffer *b, *b1, *bt;
b = buf;
b1 = 0;
for(bt = buf_head; bt && bt != b; bt = bt -> b_next)
b1 = bt;
if(bt == 0)
{ ring_bell();
errbarf("No such buffer"); /* Internal error */
return;
}
if (b1 == 0)
buf_head = b->b_next;
else
b1->b_next = b->b_next;
sbs_del(sb_close((SBBUF *)b)); /* Close buffer & delete sbstring */
sb_fdcls(-1); /* Make sweep for unused FD's */
if(b->b_fn)
chkfree(b->b_fn); /* Flush filename if one */
chkfree(b->b_name); /* Flush name */
chkfree((char *)b); /* Flush buffer */
}
/* ZAP_BUFFER - Delete all of the buffer, but if it's been modified,
* ask first. Returns 0 if user aborts.
*/
zap_buffer()
{
#if IMAGEN
extern struct buffer *exec_buf; /* in e_make.c */
if(cur_buf != exec_buf && cur_buf -> b_flags & B_MODIFIED)
#else
if(cur_buf -> b_flags & B_MODIFIED)
#endif /*-IMAGEN*/
if(ask_kbuf(cur_buf) <= 0)
return(0); /* Aborted */
ed_reset(); /* This takes care of redisplay too */
mark_p = 0;
#if IMAGEN
cur_buf->b_flags &= ~B_BACKEDUP; /* Clear backed-up flag */
#endif
return(1);
}
/* ASK_KBUF - Ask user "are you sure?" before killing a buffer.
* Returns +1 if user says "yes" - OK to kill.
* 0 if user aborts (^G)
* -1 if user says "no".
*/
ask_kbuf(buf)
struct buffer *buf;
{ register struct buffer *b;
register char *s;
register int ans;
b = buf;
s = ask("Buffer %s contains changes - forget them? ", b->b_name);
if(s == 0) return(0);
ans = (upcase(*s) == 'Y') ? 1 : -1;
chkfree(s);
return(ans);
}
/* Window stuff */
/* Like EMACS, ELLE only provides at most two user windows.
* The current user window is pointed to by user_win;
* the "other" one is oth_win. If oth_win == 0, there is only one user
* window.
*/
#if FX_2MODEWINDS
int sepmode_p = 0; /* Set true if separator window is a 2nd mode win */
#endif
/* EFUN: "Two Windows" */
/* Divide the current window in half, put the current buffer in the
* other window, and go to the new window.
*/
f_2winds()
{ register int h, t;
register struct window *w;
if (oth_win)
{
#if !(IMAGEN)
ding("Already 2 windows");
#endif /*-IMAGEN*/
return;
}
w = cur_win;
d_fixcur(); /* Stabilize current window */
h = (w->w_ht) / 2;
t = w->w_pos + h; /* Pos of dividing window */
sep_win = make_win(t, 1, lines_buf);
/* assume using dashes to separate */
oth_win = make_win(t + 1, w->w_ht - (h + 1), cur_buf);
/* Other window has balance */
#if FX_SOWIND
oth_win->w_flags |= cur_win->w_flags&W_STANDOUT;
sep_win->w_flags |= mode_win->w_flags&W_STANDOUT;
#endif
#if FX_2MODEWINDS
chk2modws(); /* Update 2-mode-wind status */
#endif
w->w_ht = h; /* Decrease current window to half */
/* Minimize redisplay by moving each window's dot into
* a currently displayed area */
if(cur_dot < (oth_win->w_topldot = scr[t+1]->sl_boff))
oth_win->w_dot = oth_win->w_topldot; /* Adj bottom win */
else /* Adjust top window */
{ oth_win->w_dot = cur_dot; /* Bottom keeps dot */
cur_dot = scr[t-1]->sl_boff; /* but top needs new one. */
}
f_othwind(); /* switch to other window */
redp(RD_WINDS); /* Update all windows */
}
/* EFUN: "One Window" */
/* Revert to using only one window; use the current buffer (unlike
* EMACS which always selects the top window's buffer)
* Ensures that current window's vars are correctly set for
* new dimensions (w_pos, w_ht, plus w_topldot to minimize redisplay),
* then kills unneeded windows.
*/
f_1wind()
{ register struct window *w;
if (oth_win == 0)
{
#if (!IMAGEN)
ding("Only 1 window");
#endif /*-IMAGEN*/
return;
}
w = cur_win;
if(w->w_pos) /* If not top window */
{ d_fixcur(); /* Ensure screen-line data correct */
e_go(w->w_topldot); /* Beginning from top of window, */
d_fgoloff(-w->w_pos); /* Move back enough lines */
w->w_topldot = e_dot(); /* To set new start of window */
e_gocur(); /* Then move back to orig place */
w->w_pos = 0;
}
w->w_ht += oth_win -> w_ht + 1;
kill_win (oth_win);
kill_win (sep_win);
oth_win = sep_win = 0;
#if FX_2MODEWINDS
chk2modws(); /* Update notion of whether have 2 mode winds */
#endif
redp(RD_FIXWIN|RD_WINDS|RD_MODE); /* New topldot for this window,
* and check all remaining windows */
}
/* EFUN: "Other Window" */
/* Move to the "other" user window.
*/
f_othwind ()
{ if (oth_win == 0)
{
#if !(IMAGEN)
ding("Only 1 window");
#endif /*-IMAGEN*/
return;
}
chg_win(oth_win);
oth_win = user_win;
user_win = cur_win;
redp(RD_MODE);
}
/* EFUN: "Grow Window" */
/* Grow the current window - while in two window mode,
* increase the size of the current window by the arg
* and decrease the other accordingly
*/
f_growind()
{ register struct window *cw, *ow;
register int e;
if ((ow = oth_win) == 0)
{
#if !(IMAGEN)
ding("Only 1 window");
#endif /*-IMAGEN*/
return;
}
e = exp;
if((cw = cur_win)->w_pos != 0) /* If current window is on bottom */
{ cw = ow; /* Then fake code to think it's top */
ow = cur_win;
e = -e;
}
if( cw->w_ht + e < 1
|| ow->w_ht + e < 1)
{ ding("Too much");
return;
}
cw -> w_ht += e;
ow -> w_pos += e;
ow -> w_ht -= e;
sep_win -> w_pos += e;
redp(RD_WINDS | RD_MODE); /* Update all windows */
}
#if FX_SHRINKWIND
/* EFUN: "Shrink Window" (not EMACS) - from IMAGEN config */
f_shrinkwind()
{
if (! oth_win)
return;
f_othwind();
f_growind();
f_othwind();
}
#endif /*FX_SHRINKWIND*/
#if FX_DELWIND
/* EFUN: "Delete Window" (not EMACS) - from IMAGEN config */
f_delwind()
{
if(!oth_win)
return;
f_othwind();
f_1wind();
}
#endif /*FX_DELWIND*/
#if FX_SOWIND
/* EFUN: "Standout Window" (not EMACS) */
/* Toggles the display standout mode for the current window.
** With argument of 4, toggles the standout mode for the non-buffer
** parts of the screen, such as the ELLE mode line.
** (This corresponds to FS INVMOD$ in EMACS)
** With argument of 0, turns standout mode off for all windows.
*/
/* It suffices to set the window flag bit and force a RD_WINRES for that
* window; the redisplay code will do the rest.
*/
static void tgso_wind();
f_sowind()
{
register struct window *w;
switch(exp)
{ default: /* Toggle current window */
tgso_wind(cur_win);
break;
case 4: /* Toggle mode & separator windows */
tgso_wind(mode_win);
tgso_wind(sep_win); /* This may not exist */
break;
case 0: /* Turn off standout for all winds */
for(w = win_head; w; w = w->w_next)
if(w->w_flags&W_STANDOUT)
tgso_wind(w);
}
#if FX_2MODEWINDS
chk2modws(); /* Update notion of whether have 2 mode winds */
#endif
}
static void
tgso_wind(w) /* Toggle standout mode for given window */
register struct window *w;
{
if (w == 0) return; /* For case of no sep_win */
if (w->w_flags & W_STANDOUT)
w->w_flags &= ~W_STANDOUT;
else w->w_flags |= W_STANDOUT;
w->w_redp |= RD_WINRES; /* Re-do this particular window */
redp(RD_CHKALL); /* Check all windows for changes */
}
#endif /*FX_SOWIND*/
#if FX_2MODEWINDS
/* EFUN: "Two Mode Windows" (not EMACS) */
/* With arg, sets ev_2modws to that value (0, 1, or 2).
** No arg, toggles current setting between 0 and 2.
*/
f_2modewinds()
{
ev_2modws = exp_p ? exp : (ev_2modws ? 0 : 2);
chk2modws();
}
/* CHK2MODWS - Called after anything changes which might affect
** whether 2 mode windows are in effect or not. Fixes up
** sep_win to either be or not be a mode window.
*/
chk2modws()
{ register struct window *w;
static struct buffer *sep_buf = 0;
if(!(w = sep_win))
{ sepmode_p = 0; /* Don't have 2 windows at all */
return;
}
sepmode_p = (ev_2modws == 1)
? (mode_win->w_flags&W_STANDOUT)
: ev_2modws;
if(sepmode_p) /* Turn 2-mode-winds on? */
{
if(!sep_buf)
sep_buf = make_buf(" **SEPMODE**");
w->w_buf = sep_buf;
w->w_flags |= W_MODE;
}
else /* Turn 2-mode-winds off */
{ w->w_buf = lines_buf;
w->w_flags &= ~W_MODE;
redp(RD_CHKALL); /* No longer a mode win, so must */
/* check all to ensure it's updated */
}
w->w_redp |= RD_WINRES;
redp(RD_MODE);
}
#endif /*FX_2MODEWINDS*/
init_win ()
{
win_head = 0;
oth_win = 0;
user_win = make_win(0, scr_ht - (ECHOLINES+1), cur_buf); /* Main */
mode_win = make_win(scr_ht - (ECHOLINES+1), 1, make_buf(" **MODE**"));
ask_win = make_win(scr_ht - ECHOLINES, 1, make_buf(" **ASK**"));
#if FX_SOWIND
if(ev_modwso)
mode_win->w_flags |= W_STANDOUT;
#endif
cur_win = user_win;
}
chg_win(newwin) /* change current window to newwin */
struct window *newwin;
{
cur_win->w_dot = cur_dot; /* Save window's current dot */
cur_win->w_redp |= rd_type&RDS_WINFLGS; /* and its redisplay flags */
cur_win = newwin; /* OK, switch to new current window */
cur_buf = newwin->w_buf; /* Set new buffer from win */
e_gosetcur(newwin->w_dot); /* Set new cur_dot from win too */
/* Note done this way to canonicalize the location
** (may be past new EOB) and ensure SB buffer
** internals agree with cur_dot.
*/
rd_type &= ~RDS_WINFLGS; /* Remove old per-window flags */
redp(RD_WINRES|RD_MODE); /* Maybe caller shd handle? */
/* Note WINRES must be set in case we are pointing
* to a buffer that was modified while we were in
* the other window!
*/
}
struct window *
make_win (pos, ht, buf)
int pos, ht;
struct buffer *buf;
{ register struct window *w;
register struct buffer *b;
b = buf;
w = (struct window *) memalloc(sizeof (struct window));
w->w_flags = 0;
w->w_pos = pos;
w->w_ht = ht;
w->w_buf = b;
w->w_dot = b->b_dot; /* Set dot from buffer value */
w->w_topldot = 0; /* Set top of window to beg of buffer */
w->w_pct = 200; /* Assume "ALL" */
w->w_bmod = 0;
w->w_emod = 0;
w->w_oldz = 0;
w->w_redp = RD_WINRES; /* Window will need complete update */
w->w_next = win_head; /* Done, now link it in */
win_head = w;
return (w);
}
kill_win (win)
struct window *win;
{ register struct window *w, *w1, *kw;
kw = win;
w1 = 0;
for (w = win_head; w && w != kw; w = w -> w_next)
w1 = w;
if (w == 0)
{ ring_bell();
errbarf("No such window"); /* Internal error */
return;
}
if (w1 == 0)
win_head = w -> w_next;
else
w1 -> w_next = w -> w_next;
kw->w_buf->b_dot = (kw == cur_win) ? cur_dot : kw->w_dot;
chkfree (kw);
#if IMAGEN /* Not needed? */
redp (RD_WINRES|RD_WINDS|RD_REDO);
#endif /*IMAGEN*/
}
/*
* "Show-window" routines, used to set up, step through, and close a
* temporary "show" window.
* MK_SHOWIN(bufp)
* UP_SHOWIN()
* KL_SHOWIN()
*/
/* MK_SHOWIN(bufp) - Temporarily display a buffer
*/
mk_showin(b)
struct buffer *b;
{ register struct window *w;
register int i;
int moreflg, intflg; /* Interrupt flag */
struct window *savwin;
/* First must set up special window... */
savwin = cur_win;
chg_win(w = make_win(0, scr_ht-(ECHOLINES+3), b));
redo:
d_fixcur(); /* Fix up screen image of current window */
/* Find how many lines actually used, and reduce size to that */
i = w->w_ht;
while(--i >= 0)
{
if(scr[i]->sl_boff != w->w_oldz) break;
}
if(++i <= 0)
goto skipit; /* Punt the whole thing */
if(!(moreflg = (i >= w->w_ht)))
w->w_ht = i; /* Reduce size of window */
intflg = upd_wind(w); /* Update the window! */
if(!intflg) /* Unless input waiting, add prompt. */
{
yellat( moreflg ?
"--MORE-- (type Space for more, or type any command to flush)" :
"------------------------------------------------ (Hit space to continue)--",
w->w_ht);
}
tbufls(); /* Ensure all output forced out */
i = cmd_read(); /* then wait for user to input a char */
if(i == SP)
{ if(moreflg)
{ yellat("", w->w_ht);
d_screen(1);
w->w_redp |= RD_WINRES;
goto redo;
}
}
#if !(IMAGEN) /* IMAGEN - always ignore what was typed */
else unrchf = i;
#endif /*-IMAGEN*/
skipit: chg_win(savwin);
kill_win(w);
redp(RD_WINDS); /* Update all remaining windows */
}
/* Mode Line generation */
struct window *
make_mode(bw)
register struct window *bw; /* Base window we are reporting status of */
{
register struct buffer *b; /* Buffer of this window */
struct window *mw, *savew; /* Save current window */
struct buffer *saveb; /* and current buffer (in case different) */
char temp[20];
saveb = cur_buf; /* Save values prior to context switch */
savew = cur_win;
b = bw->w_buf; /* Get buffer for that window */
#if FX_2MODEWINDS
if((mw = sep_win) && (mw->w_flags&W_MODE) &&
(bw->w_pos == 0)) /* Base window is top window? */
{ /* Use sep_win as mode wind */
}
else
#endif
mw = mode_win; /* Default is normal mode window */
chg_win(mw); /* Go to mode line window */
e_gobob(); /* go to beginning */
e_reset(); /* Flush buffer */
#if IMAGEN
e_sputz(" ");
e_sputz(b->b_name);
if (b -> b_flags & B_MODIFIED)
e_sputz("*");
e_sputz(" (");
if (b->b_flags & B_QUERYREP)
e_sputz("[Query Replace] ");
if (b->b_flags & B_CMODE)
e_sputz("C");
else if (b->b_flags & B_TEXTMODE)
e_sputz("Text");
else
e_sputz("Fundamental");
e_sputz(") ");
if (b->b_fn)
e_sputz(b->b_fn);
e_sputz(" ");
#else
e_sputz(ev_verstr); /* Editor name/version */
e_sputz(" (");
e_sputz(cur_mode->mjm_name); /* insert major mode name */
#if FX_FILLMODE
if(fill_mode) e_sputz(" Fill");
#endif /*FX_FILLMODE*/
#if FX_SKMAC
if(kdef_mode) e_sputz(" MacroDef");
#endif /*FX_SKMAC*/
e_sputz(") ");
e_sputz(b->b_name); /* buffer name */
e_sputz(": ");
if (b->b_fn)
e_sputz(b->b_fn); /* file name */
if (b->b_flags & B_MODIFIED)
e_sputz(" *");
else e_sputz(" ");
#endif /*-IMAGEN*/
if(bw->w_pct < 200) /* Not ALL? */
{ e_sputz(" --");
switch(bw->w_pct)
{ case -1:
e_sputz("TOP");
break;
case 150:
e_sputz("BOT");
break;
default:
dottoa(&temp[0],(chroff)bw->w_pct);
e_sputz(&temp[0]);
e_putc('%');
}
e_sputz("--");
}
#if FX_SOWIND
if(mw->w_flags&W_STANDOUT)
e_insn(SP, (int)(scr_wd0 - e_blen())); /* Stuff out with spaces */
#endif
redp(RD_WINRES);
chg_win(savew); /* Restore context */
chg_buf(saveb);
return(mw); /* Return mode window */
}
buf_mod()
{ register struct buffer *b;
b = cur_buf;
if((b->b_flags & B_MODIFIED) == 0)
{ b->b_flags |= B_MODIFIED;
redp(RD_MODE);
}
}
/* BUF_TMOD - called when text modified in buffer, to set all
* the appropriate indicators so that redisplay works right.
* Changed text is everything from CUR_DOT to the given offset
* from same. If stuff was deleted, offset should be 0.
* BUF_TMAT - similar but argument is location of other end of range,
* when caller knows that and wants life easy.
*/
buf_tmat(dot)
chroff dot;
{ buf_tmod(dot - cur_dot); /* Convert to offset */
}
buf_tmod(offset)
chroff offset;
{ register struct window *w;
chroff a, b, tmp;
w = cur_win;
a = cur_dot;
b = a + offset;
if(a > b) /* Get into right order */
{ tmp = a;
a = b;
b = tmp;
}
b = e_blen() - b; /* Make upper bound relative to EOB */
if(w->w_bmod < 0) /* Have range vars been set yet? */
{ w->w_bmod = a; /* Nope, so can just set 'em now. */
w->w_emod = b;
}
else
{ if(a < w->w_bmod)
w->w_bmod = a;
if(b < w->w_emod)
w->w_emod = b;
}
buf_mod(); /* Maybe later just insert here? */
redp(RD_TMOD);
}