jimomura@lsuc.UUCP (Jim Omura) (05/04/86)
==========
os.9/public.domain #72, from jimomura, 8051 chars, Fri Mar 21 21:21:28 1986
----------
TITLE: 'microEMACS' part 3 'uebuffer1.c'
/*
* Buffer management.
* Some of the functions are internal,
* and some are actually attached to user
* keys. Like everyone else, they set hints
* for the display system.
*/
#include <stdio.h>
#include "ueed.h"
#ifndef OS9
/*
* Attach a buffer to a window. The
* values of dot and mark come from the buffer
* if the use count is 0. Otherwise, they come
* from some other window.
*/
usebuffer(f, n)
{
register BUFFER *bp;
register WINDOW *wp;
register int s;
char bufn[NBUFN];
if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
return (s);
if ((bp=bfind(bufn, TRUE, 0)) == NULL)
return (FALSE);
if (--curbp->b_nwnd == 0) { /* Last use. */
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
curbp->b_markp = curwp->w_markp;
curbp->b_marko = curwp->w_marko;
}
curbp = bp; /* Switch. */
curwp->w_bufp = bp;
curwp->w_linep = bp->b_linep; /* For macros, ignored. */
curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */
if (bp->b_nwnd++ == 0) { /* First use. */
curwp->w_dotp = bp->b_dotp;
curwp->w_doto = bp->b_doto;
curwp->w_markp = bp->b_markp;
curwp->w_marko = bp->b_marko;
return (TRUE);
}
wp = wheadp; /* Look for old. */
while (wp != NULL) {
if (wp!=curwp && wp->w_bufp==bp) {
curwp->w_dotp = wp->w_dotp;
curwp->w_doto = wp->w_doto;
curwp->w_markp = wp->w_markp;
curwp->w_marko = wp->w_marko;
break;
}
wp = wp->w_wndp;
}
return (TRUE);
}
/*
* Dispose of a buffer, by name.
* Ask for the name. Look it up (don't get too
* upset if it isn't there at all!). Get quite upset
* if the buffer is being displayed. Clear the buffer (ask
* if the buffer has been changed). Then free the header
* line and the buffer header. Bound to "C-X K".
*/
killbuffer(f, n)
{
register BUFFER *bp;
register BUFFER *bp1;
register BUFFER *bp2;
register int s;
char bufn[NBUFN];
if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
return (s);
if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */
return (TRUE);
if (bp->b_nwnd != 0) { /* Error if on screen. */
mlwrite("Buffer is being displayed");
return (FALSE);
}
if ((s=bclear(bp)) != TRUE) /* Blow text away. */
return (s);
free((char *) bp->b_linep); /* Release header line. */
bp1 = NULL; /* Find the header. */
bp2 = bheadp;
while (bp2 != bp) {
bp1 = bp2;
bp2 = bp2->b_bufp;
}
bp2 = bp2->b_bufp; /* Next one in chain. */
if (bp1 == NULL) /* Unlink it. */
bheadp = bp2;
else
bp1->b_bufp = bp2;
free((char *) bp); /* Release buffer block */
return (TRUE);
}
/*
* List all of the active
* buffers. First update the special
* buffer that holds the list. Next make
* sure at least 1 window is displaying the
* buffer list, splitting the screen if this
* is what it takes. Lastly, repaint all of
* the windows that are displaying the
* list. Bound to "C-X C-B".
*/
listbuffers(f, n)
{
register WINDOW *wp;
register BUFFER *bp;
register int s;
if ((s=makelist()) != TRUE)
return (s);
if (blistp->b_nwnd == 0) { /* Not on screen yet. */
if ((wp=wpopup()) == NULL)
return (FALSE);
bp = wp->w_bufp;
if (--bp->b_nwnd == 0) {
bp->b_dotp = wp->w_dotp;
bp->b_doto = wp->w_doto;
bp->b_markp = wp->w_markp;
bp->b_marko = wp->w_marko;
}
wp->w_bufp = blistp;
++blistp->b_nwnd;
}
wp = wheadp;
while (wp != NULL) {
if (wp->w_bufp == blistp) {
wp->w_linep = lforw(blistp->b_linep);
wp->w_dotp = lforw(blistp->b_linep);
wp->w_doto = 0;
wp->w_markp = NULL;
wp->w_marko = 0;
wp->w_flag |= WFMODE|WFHARD;
}
wp = wp->w_wndp;
}
return (TRUE);
}
/*
* This routine rebuilds the
* text in the special secret buffer
* that holds the buffer list. It is called
* by the list buffers command. Return TRUE
* if everything works. Return FALSE if there
* is an error (if there is no memory).
*/
makelist()
{
register char *cp1;
register char *cp2;
register int c;
register BUFFER *bp;
register LINE *lp;
register int nbytes;
register int s;
register int type;
char b[6+1];
char line[128];
blistp->b_flag &= ~BFCHG; /* Don't complain! */
if ((s=bclear(blistp)) != TRUE) /* Blow old text away */
return (s);
strcpy(blistp->b_fname, "");
if (addline("C Size Buffer File") == FALSE
|| addline("- ---- ------ ----") == FALSE)
return (FALSE);
bp = bheadp; /* For all buffers */
while (bp != NULL) {
if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones. */
bp = bp->b_bufp;
continue;
}
cp1 = &line[0]; /* Start at left edge */
if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */
*cp1++ = '*';
else
*cp1++ = ' ';
*cp1++ = ' '; /* Gap. */
nbytes = 0; /* Count bytes in buf. */
lp = lforw(bp->b_linep);
while (lp != bp->b_linep) {
nbytes += llength(lp)+1;
lp = lforw(lp);
}
itoa(b, 6, nbytes); /* 6 digit buffer size. */
cp2 = &b[0];
while ((c = *cp2++) != 0)
*cp1++ = c;
*cp1++ = ' '; /* Gap. */
cp2 = &bp->b_bname[0]; /* Buffer name */
while ((c = *cp2++) != 0)
*cp1++ = c;
cp2 = &bp->b_fname[0]; /* File name */
if (*cp2 != 0) {
while (cp1 < &line[1+1+6+1+NBUFN+1])
*cp1++ = ' ';
while ((c = *cp2++) != 0) {
if (cp1 < &line[128-1])
*cp1++ = c;
}
}
*cp1 = 0; /* Add to the buffer. */
if (addline(line) == FALSE)
return (FALSE);
bp = bp->b_bufp;
}
return (TRUE); /* All done */
}
#endif
==========
os.9/public.domain #73, from jimomura, 4861 chars, Fri Mar 21 21:29:33 1986
----------
TITLE: 'microEMACS' part 4 'uebuffer2.c'
/*
* Buffer management.
* Some of the functions are internal,
* and some are actually attached to user
* keys. Like everyone else, they set hints
* for the display system.
*/
#include <stdio.h>
#include "ueed.h"
#ifndef OS9
itoa(buf, width, num)
register char buf[];
register int width;
register int num;
{
buf[width] = 0; /* End of string. */
while (num >= 10) { /* Conditional digits. */
buf[--width] = (num%10) + '0';
num /= 10;
}
buf[--width] = num + '0'; /* Always 1 digit. */
while (width != 0) /* Pad with blanks. */
buf[--width] = ' ';
}
/*
* The argument "text" points to
* a string. Append this line to the
* buffer list buffer. Handcraft the EOL
* on the end. Return TRUE if it worked and
* FALSE if you ran out of room.
*/
addline(text)
char *text;
{
register LINE *lp;
register int i;
register int ntext;
ntext = strlen(text);
if ((lp=lalloc(ntext)) == NULL)
return (FALSE);
for (i=0; i<ntext; ++i)
lputc(lp, i, text[i]);
blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */
lp->l_bp = blistp->b_linep->l_bp;
blistp->b_linep->l_bp = lp;
lp->l_fp = blistp->b_linep;
if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */
blistp->b_dotp = lp; /* move it to new line */
return (TRUE);
}
#endif
/*
* Look through the list of
* buffers. Return TRUE if there
* are any changed buffers. Buffers
* that hold magic internal stuff are
* not considered; who cares if the
* list of buffer names is hacked.
* Return FALSE if no buffers
* have been changed.
*/
anycb()
{
register BUFFER *bp;
bp = bheadp;
while (bp != NULL) {
if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
return (TRUE);
bp = bp->b_bufp;
}
return (FALSE);
}
/*
* Find a buffer, by name. Return a pointer
* to the BUFFER structure associated with it. If
* the named buffer is found, but is a TEMP buffer (like
* the buffer list) conplain. If the buffer is not found
* and the "cflag" is TRUE, create it. The "bflag" is
* the settings for the flags in in buffer.
*/
BUFFER *bfind(bname, cflag, bflag)
register char *bname;
{
register BUFFER *bp;
register LINE *lp;
bp = bheadp;
while (bp != NULL) {
if (strcmp(bname, bp->b_bname) == 0) {
if ((bp->b_flag&BFTEMP) != 0) {
mlwrite("Cannot select builtin buffer");
return (NULL);
}
return (bp);
}
bp = bp->b_bufp;
}
if (cflag != FALSE) {
if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
return (NULL);
if ((lp=lalloc(0)) == NULL) {
free((char *) bp);
return (NULL);
}
bp->b_bufp = bheadp;
bheadp = bp;
bp->b_dotp = lp;
bp->b_doto =
bp->b_markp =
bp->b_marko =
bp->b_nwnd = 0;
bp->b_linep = lp;
bp->b_flag = bflag;
strcpy(bp->b_fname, "");
strcpy(bp->b_bname, bname);
lp->l_fp = lp;
lp->l_bp = lp;
}
return (bp);
}
/*
* This routine blows away all of the text
* in a buffer. If the buffer is marked as changed
* then we ask if it is ok to blow it away; this is
* to save the user the grief of losing text. The
* window chain is nearly always wrong if this gets
* called; the caller must arrange for the updates
* that are required. Return TRUE if everything
* looks good.
*/
bclear(bp)
register BUFFER *bp;
{
register LINE *lp;
register int s;
if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */
&& (bp->b_flag&BFCHG) != 0 /* Something changed */
&& (s=mlyesno("Discard changes")) != TRUE)
return (s);
bp->b_flag &= ~BFCHG; /* Not changed */
while ((lp=lforw(bp->b_linep)) != bp->b_linep)
lfree(lp);
bp->b_dotp = bp->b_linep; /* Fix "." */
bp->b_doto =
bp->b_markp = /* Invalidate "mark" */
bp->b_marko = 0;
return (TRUE);
}
==========
os.9/public.domain #74, from jimomura, 1953 chars, Fri Mar 21 21:33:48 1986
----------
TITLE: 'microEMACS' part 5 'uecoco.c'
/*
* The routines in this file provide support for the COCO /TERM terminal
* under OS9. The serial I/O services are provided by routines in
* "termio.c".
* Adapted 1/5/86 by:
* Bob Santy
* 5 Johnson Ave
* Medford, MA 02155
* (617) 488-7160
*/
#include <stdio.h>
#include "ueed.h"
/* Color Computer /TERM specifications */
#define NROW 16 /* Screen size. */
#define NCOL 32 /* Edit if you want to. */
#define BEL 0x07 /* BEL character. */
#define ESC 0x1B /* ESC character. */
#define CURSOR 0x02 /* Commands manual p126 */
#define CEOL 0x04 /* 1.01 Supplement */
#define CEOS 0x0B /* 1.01 Supplement */
extern int ttopen(); /* Forward references. */
extern int ttgetc();
extern int ttputc();
extern int ttflush();
extern int ttclose();
extern int cocomove();
extern int cocoeeol();
extern int cocoeeop();
extern int cocobeep();
extern int cocoopen();
/*
* Standard terminal interface dispatch table. Most of the fields point into
* "termio" code.
*/
TERM term = {
NROW-1,
NCOL,
cocoopen,
ttclose,
ttgetc,
ttputc,
ttflush,
cocomove,
cocoeeol,
cocoeeop,
cocobeep
};
/*
* Cursor move command.
*/
cocomove(row, col)
{
ttputc(CURSOR);
cocoparm(col);
cocoparm(row);
}
/*
* Clear to end of line.
*/
cocoeeol()
{
ttputc(CEOL);
}
/*
* Clear to end of screen.
*/
cocoeeop()
{
ttputc(CEOS);
}
/*
* Sound the horn (will work in
* OS9 Rev 2.00
*/
cocobeep()
{
ttputc(BEL);
ttflush();
}
/*
* Cursor position needs 32 added to
* X and Y coordinates.
*/
cocoparm(n)
register int n;
{
ttputc(n + 32);
}
/*
* Open terminal. No special codes.
*/
cocoopen()
{
ttopen();
}
==========
os.9/public.domain #75, from jimomura, 1223 chars, Fri Mar 21 21:36:22 1986
----------
TITLE: 'microEMACS' part 6 'uedisplay.h'
/* #define WFDEBUG 0 /* Window flag debug. */
typedef struct VIDEO {
short v_flag; /* Flags */
char v_text[1]; /* Screen data. */
} VIDEO;
#define VFCHG 0x0001 /* Changed. */
#ifdef DISPLAY1
int sgarbf = TRUE; /* TRUE if screen is garbage */
int mpresf = FALSE; /* TRUE if message in last line */
int vtrow = 0; /* Row location of SW cursor */
int vtcol = 0; /* Column location of SW cursor */
int ttrow = HUGE; /* Row location of HW cursor */
int ttcol = HUGE; /* Column location of HW cursor */
#else
extern int sgarbf; /* TRUE if screen is garbage */
extern int mpresf; /* TRUE if message in last line */
extern int vtrow; /* Row location of SW cursor */
extern int vtcol; /* Column location of SW cursor */
extern int ttrow; /* Row location of HW cursor */
extern int ttcol; /* Column location of HW cursor */
#endif
==========
os.9/public.domain #76, from jimomura, 11146 chars, Fri Mar 21 21:57:12 1986
----------
TITLE: 'microEMACS' part 7 'uedisplay1.c'
/*
* The functions in this file handle redisplay. There are two halves, the
* ones that update the virtual display screen, and the ones that make the
* physical display screen the same as the virtual display screen. These
* functions use hints that are left in the windows by the commands.
*
* REVISION HISTORY:
*
* ? Steve Wilhite, 1-Dec-85
* - massive cleanup on code.
*/
#include <stdio.h>
#include "ueed.h"
#define DISPLAY1 1
#include "uedisplay.h"
VIDEO **vscreen; /* Virtual screen. */
VIDEO **pscreen; /* Physical screen. */
/*
* Initialize the data structures used by the display code. The edge vectors
* used to access the screens are set up. The operating system's terminal I/O
* channel is set up. All the other things get initialized at compile time.
* The original window has "WFCHG" set, so that it will get completely
* redrawn on the first call to "update".
*/
vtinit()
{
register int i;
register VIDEO *vp;
(*term.t_open)();
vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
if (vscreen == NULL)
exit(1);
pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
if (pscreen == NULL)
exit(1);
for (i = 0; i < term.t_nrow; ++i)
{
vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
if (vp == NULL)
exit(1);
vscreen[i] = vp;
vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
if (vp == NULL)
exit(1);
pscreen[i] = vp;
}
}
/*
* Clean up the virtual terminal system, in anticipation for a return to the
* operating system. Move down to the last line and clear it out (the next
* system prompt will be written in the line). Shut down the channel to the
* terminal.
*/
vttidy()
{
movecursor(term.t_nrow, 0);
(*term.t_eeol)();
(*term.t_close)();
}
/*
* Set the virtual cursor to the specified row and column on the virtual
* screen. There is no checking for nonsense values; this might be a good
* idea during the early stages.
*/
vtmove(row, col)
{
vtrow = row;
vtcol = col;
}
/*
* Write a character to the virtual screen. The virtual row and column are
* updated. If the line is too long put a "$" in the last column. This routine
* only puts printing characters into the virtual terminal buffers. Only
* column overflow is checked.
*/
vtputc(c)
int c;
{
register VIDEO *vp;
vp = vscreen[vtrow];
if (vtcol >= term.t_ncol)
vp->v_text[term.t_ncol - 1] = '$';
else if (c == '\t')
{
do
{
vtputc(' ');
}
while ((vtcol&0x07) != 0);
}
else if (c < 0x20 || c == 0x7F)
{
vtputc('^');
vtputc(c ^ 0x40);
}
else
vp->v_text[vtcol++] = c;
}
/*
* Erase from the end of the software cursor to the end of the line on which
* the software cursor is located.
*/
vteeol()
{
register VIDEO *vp;
vp = vscreen[vtrow];
while (vtcol < term.t_ncol)
vp->v_text[vtcol++] = ' ';
}
/*
* Make sure that the display is right. This is a three part process. First,
* scan through all of the windows looking for dirty ones. Check the framing,
* and refresh the screen. Second, make sure that "currow" and "curcol" are
* correct for the current window. Third, make the virtual and physical
* screens the same.
*/
update()
{
register LINE *lp;
register WINDOW *wp;
register VIDEO *vp1;
register VIDEO *vp2;
register int i;
register int j;
register int c;
wp = wheadp;
while (wp != NULL)
{
/* Look at any window with update flags set on. */
if (wp->w_flag != 0)
{
/* If not force reframe, check the framing. */
if ((wp->w_flag & WFFORCE) == 0)
{
lp = wp->w_linep;
for (i = 0; i < wp->w_ntrows; ++i)
{
if (lp == wp->w_dotp)
goto out;
if (lp == wp->w_bufp->b_linep)
break;
lp = lforw(lp);
}
}
/* Not acceptable, better compute a new value for the line at the
* top of the window. Then set the "WFHARD" flag to force full
* redraw.
*/
i = wp->w_force;
if (i > 0)
{
--i;
if (i >= wp->w_ntrows)
i = wp->w_ntrows-1;
}
else if (i < 0)
{
i += wp->w_ntrows;
if (i < 0)
i = 0;
}
else
i = wp->w_ntrows/2;
lp = wp->w_dotp;
while (i != 0 && lback(lp) != wp->w_bufp->b_linep)
{
--i;
lp = lback(lp);
}
wp->w_linep = lp;
wp->w_flag |= WFHARD; /* Force full. */
out:
/* Try to use reduced update. Mode line update has its own special
* flag. The fast update is used if the only thing to do is within
* the line editing.
*/
lp = wp->w_linep;
i = wp->w_toprow;
if ((wp->w_flag & ~WFMODE) == WFEDIT)
{
while (lp != wp->w_dotp)
{
++i;
lp = lforw(lp);
}
vscreen[i]->v_flag |= VFCHG;
vtmove(i, 0);
for (j = 0; j < llength(lp); ++j)
vtputc(lgetc(lp, j));
vteeol();
}
else if ((wp->w_flag & (WFEDIT | WFHARD)) != 0)
{
while (i < wp->w_toprow+wp->w_ntrows)
{
vscreen[i]->v_flag |= VFCHG;
vtmove(i, 0);
if (lp != wp->w_bufp->b_linep)
{
for (j = 0; j < llength(lp); ++j)
vtputc(lgetc(lp, j));
lp = lforw(lp);
}
vteeol();
++i;
}
}
#ifndef WFDEBUG
if ((wp->w_flag&WFMODE) != 0)
modeline(wp);
wp->w_flag =
wp->w_force = 0;
#endif
}
#ifdef WFDEBUG
modeline(wp);
wp->w_flag =
wp->w_force = 0;
#endif
wp = wp->w_wndp;
}
/* Always recompute the row and column number of the hardware cursor. This
* is the only update for simple moves.
*/
lp = curwp->w_linep;
currow = curwp->w_toprow;
while (lp != curwp->w_dotp)
{
++currow;
lp = lforw(lp);
}
curcol =
i = 0;
while (i < curwp->w_doto)
{
c = lgetc(lp, i++);
if (c == '\t')
curcol |= 0x07;
else if (c < 0x20 || c == 0x7F)
++curcol;
++curcol;
}
if (curcol >= term.t_ncol) /* Long line. */
curcol = term.t_ncol-1;
/* Special hacking if the screen is garbage. Clear the hardware screen,
* and update your copy to agree with it. Set all the virtual screen
* change bits, to force a full update.
*/
if (sgarbf != FALSE)
{
for (i = 0; i < term.t_nrow; ++i)
{
vscreen[i]->v_flag |= VFCHG;
vp1 = pscreen[i];
for (j = 0; j < term.t_ncol; ++j)
vp1->v_text[j] = ' ';
}
movecursor(0, 0); /* Erase the screen. */
(*term.t_eeop)();
sgarbf = FALSE; /* Erase-page clears */
mpresf = FALSE; /* the message area. */
}
/* Make sure that the physical and virtual displays agree. Unlike before,
* the "updateline" code is only called with a line that has been updated
* for sure.
*/
for (i = 0; i < term.t_nrow; ++i)
{
vp1 = vscreen[i];
if ((vp1->v_flag&VFCHG) != 0)
{
vp1->v_flag &= ~VFCHG;
vp2 = pscreen[i];
updateline(i, &vp1->v_text[0], &vp2->v_text[0]);
}
}
/* Finally, update the hardware cursor and flush out buffers. */
movecursor(currow, curcol);
(*term.t_flush)();
}
/*
* Update a single line. This does not know how to use insert or delete
* character sequences; we are using VT52 functionality. Update the physical
* row and column variables. It does try an exploit erase to end of line. The
* RAINBOW version of this routine uses fast video.
*/
updateline(row, vline, pline)
char vline[];
char pline[];
{
#ifdef RAINBOW
register char *cp1;
register char *cp2;
register int nch;
cp1 = &vline[0]; /* Use fast video. */
cp2 = &pline[0];
putline(row+1, 1, cp1);
nch = term.t_ncol;
do
{
*cp2 = *cp1;
++cp2;
++cp1;
}
while (--nch);
#else
register char *cp1;
register char *cp2;
register char *cp3;
register char *cp4;
register char *cp5;
register int nbflag;
cp1 = &vline[0]; /* Compute left match. */
cp2 = &pline[0];
while (cp1!=&vline[term.t_ncol] && cp1[0]==cp2[0])
{
++cp1;
++cp2;
}
/* This can still happen, even though we only call this routine on changed
* lines. A hard update is always done when a line splits, a massive
* change is done, or a buffer is displayed twice. This optimizes out most
* of the excess updating. A lot of computes are used, but these tend to
* be hard operations that do a lot of update, so I don't really care.
*/
if (cp1 == &vline[term.t_ncol]) /* All equal. */
return;
nbflag = FALSE;
cp3 = &vline[term.t_ncol]; /* Compute right match. */
cp4 = &pline[term.t_ncol];
while (cp3[-1] == cp4[-1])
{
--cp3;
--cp4;
if (cp3[0] != ' ') /* Note if any nonblank */
nbflag = TRUE; /* in right match. */
}
cp5 = cp3;
if (nbflag == FALSE) /* Erase to EOL ? */
{
while (cp5!=cp1 && cp5[-1]==' ')
--cp5;
if (cp3-cp5 <= 3) /* Use only if erase is */
cp5 = cp3; /* fewer characters. */
}
movecursor(row, cp1-&vline[0]); /* Go to start of line. */
while (cp1 != cp5) /* Ordinary. */
{
(*term.t_putchar)(*cp1);
++ttcol;
*cp2++ = *cp1++;
}
if (cp5 != cp3) /* Erase. */
{
(*term.t_eeol)();
while (cp1 != cp3)
*cp2++ = *cp1++;
}
#endif
}
==========
os.9/public.domain #77, from jimomura, 7492 chars, Fri Mar 21 22:10:12 1986
----------
TITLE: 'microEMACS' part 8 'uedisplay2.c'
/*
* The functions in this file handle redisplay. There are two halves, the
* ones that update the virtual display screen, and the ones that make the
* physical display screen the same as the virtual display screen. These
* functions use hints that are left in the windows by the commands.
*
* REVISION HISTORY:
*
* ? Steve Wilhite, 1-Dec-85
* - massive cleanup on code.
*/
#include <stdio.h>
#include "ueed.h"
#include "uedisplay.h"
extern VIDEO **vscreen; /* Virtual screen. */
/*
* Redisplay the mode line for the window pointed to by the "wp". This is the
* only routine that has any idea of how the modeline is formatted. You can
* change the modeline format by hacking at this routine. Called by "update"
* any time there is a dirty window.
*/
modeline(wp)
WINDOW *wp;
{
register char *cp;
register int c;
register int n;
register BUFFER *bp;
n = wp->w_toprow+wp->w_ntrows; /* Location. */
vscreen[n]->v_flag |= VFCHG; /* Redraw next time. */
vtmove(n, 0); /* Seek to right line. */
vtputc('-');
bp = wp->w_bufp;
if ((bp->b_flag&BFCHG) != 0) /* "*" if changed. */
vtputc('*');
else
vtputc('-');
n = 2;
cp = " MicroEMACS -"; /* Buffer name. */
while ((c = *cp++) != 0)
{
vtputc(c);
++n;
}
#ifndef OS9
cp = &bp->b_bname[0];
while ((c = *cp++) != 0)
{
vtputc(c);
++n;
}
vtputc(' ');
++n;
#endif
if (bp->b_fname[0] != 0) /* File name. */
{
cp = " File: ";
while ((c = *cp++) != 0)
{
vtputc(c);
++n;
}
cp = &bp->b_fname[0];
while ((c = *cp++) != 0)
{
vtputc(c);
++n;
}
vtputc(' ');
++n;
}
#ifdef WFDEBUG
vtputc('-');
vtputc((wp->w_flag&WFMODE)!=0 ? 'M' : '-');
vtputc((wp->w_flag&WFHARD)!=0 ? 'H' : '-');
vtputc((wp->w_flag&WFEDIT)!=0 ? 'E' : '-');
vtputc((wp->w_flag&WFMOVE)!=0 ? 'V' : '-');
vtputc((wp->w_flag&WFFORCE)!=0 ? 'F' : '-');
n += 6;
#endif
while (n < term.t_ncol) /* Pad to full width. */
{
vtputc('-');
++n;
}
}
/*
* Send a command to the terminal to move the hardware cursor to row "row"
* and column "col". The row and column arguments are origin 0. Optimize out
* random calls. Update "ttrow" and "ttcol".
*/
movecursor(row, col)
{
if (row!=ttrow || col!=ttcol)
{
ttrow = row;
ttcol = col;
(*term.t_move)(row, col);
}
}
/*
* Erase the message line. This is a special routine because the message line
* is not considered to be part of the virtual screen. It always works
* immediately; the terminal buffer is flushed via a call to the flusher.
*/
mlerase()
{
movecursor(term.t_nrow, 0);
(*term.t_eeol)();
(*term.t_flush)();
mpresf = FALSE;
}
/*
* Ask a yes or no question in the message line. Return either TRUE, FALSE, or
* ABORT. The ABORT status is returned if the user bumps out of the question
* with a ^G. Used any time a confirmation is required.
*/
mlyesno(prompt)
char *prompt;
{
register int s;
char buf[64];
for (;;)
{
strcpy(buf, prompt);
strcat(buf, " [y/n]? ");
s = mlreply(buf, buf, sizeof(buf));
if (s == ABORT)
return (ABORT);
if (s != FALSE)
{
if (buf[0]=='y' || buf[0]=='Y')
return (TRUE);
if (buf[0]=='n' || buf[0]=='N')
return (FALSE);
}
}
}
/*
* Write a prompt into the message line, then read back a response. Keep
* track of the physical position of the cursor. If we are in a keyboard
* macro throw the prompt away, and return the remembered response. This
* lets macros run at full speed. The reply is always terminated by a carriage
* return. Handle erase, kill, and abort keys.
*/
mlreply(prompt, buf, nbuf)
char *prompt;
char *buf;
{
register int cpos;
register int i;
register int c;
cpos = 0;
if (kbdmop != NULL)
{
while ((c = *kbdmop++) != '\0')
buf[cpos++] = c;
buf[cpos] = 0;
if (buf[0] == 0)
return (FALSE);
return (TRUE);
}
mlwrite(prompt);
for (;;)
{
c = (*term.t_getchar)();
switch (c)
{
case 0x0D: /* Return, end of line */
buf[cpos++] = 0;
if (kbdmip != NULL)
{
if (kbdmip+cpos > &kbdm[NKBDM-3])
{
ctrlg(FALSE, 0);
(*term.t_flush)();
return (ABORT);
}
for (i=0; i<cpos; ++i)
*kbdmip++ = buf[i];
}
(*term.t_putchar)('\r');
ttcol = 0;
(*term.t_flush)();
if (buf[0] == 0)
return (FALSE);
return (TRUE);
case 0x07: /* Bell, abort */
(*term.t_putchar)('^');
(*term.t_putchar)('G');
ttcol += 2;
ctrlg(FALSE, 0);
(*term.t_flush)();
return (ABORT);
case 0x7F: /* Rubout, erase */
case 0x08: /* Backspace, erase */
if (cpos != 0)
{
(*term.t_putchar)('\b');
(*term.t_putchar)(' ');
(*term.t_putchar)('\b');
--ttcol;
if (buf[--cpos] < 0x20)
{
(*term.t_putchar)('\b');
(*term.t_putchar)(' ');
(*term.t_putchar)('\b');
--ttcol;
}
(*term.t_flush)();
}
break;
case 0x15: /* C-U, kill */
while (cpos != 0)
{
(*term.t_putchar)('\b');
(*term.t_putchar)(' ');
(*term.t_putchar)('\b');
--ttcol;
if (buf[--cpos] < 0x20)
{
(*term.t_putchar)('\b');
(*term.t_putchar)(' ');
(*term.t_putchar)('\b');
--ttcol;
}
}
(*term.t_flush)();
break;
default:
if (cpos < nbuf-1)
{
buf[cpos++] = c;
if (c < ' ')
{
(*term.t_putchar)('^');
++ttcol;
c ^= 0x40;
}
(*term.t_putchar)(c);
++ttcol;
(*term.t_flush)();
}
}
}
}
==========
os.9/public.domain #78, from jimomura, 3718 chars, Fri Mar 21 22:17:22 1986
----------
TITLE: 'microEMACS' part 9 'uedisplay3.c'
/*
* The functions in this file handle redisplay. There are two halves, the
* ones that update the virtual display screen, and the ones that make the
* physical display screen the same as the virtual display screen. These
* functions use hints that are left in the windows by the commands.
*
* REVISION HISTORY:
*
* ? Steve Wilhite, 1-Dec-85
* - massive cleanup on code.
*/
#include <stdio.h>
#include "ueed.h"
#include "uedisplay.h"
/*
* Write a message into the message line. Keep track of the physical cursor
* position. A small class of printf like format items is handled.
* This routine is probably one of the lease portable.
* Assumes all arguments (with the possible exception of the first) are passed
* in the order expected on a downward growing stack without addtional
* padding; this assumption is made by the "++" in the
* argument scan loop. It works for the two or less argument case
* on OSK despite the fact the first two arguments are passed in registers.
* Set the "message line" flag TRUE.
*/
mlwrite(fmt, arg)
char *fmt;
{
register int c;
register char *ap;
movecursor(term.t_nrow, 0);
ap = (char *) &arg;
while ((c = *fmt++) != 0) {
if (c != '%') {
(*term.t_putchar)(c);
++ttcol;
}
else
{
c = *fmt++;
switch (c) {
case 'd':
mlputi(*(int *)ap, 10);
ap += sizeof(int);
break;
case 'o':
mlputi(*(int *)ap, 8);
ap += sizeof(int);
break;
case 'x':
mlputi(*(int *)ap, 16);
ap += sizeof(int);
break;
case 'D': /* this is %ld on many printf impleminations */
mlputli(*(long *)ap, 10);
ap += sizeof(long);
break;
case 's':
mlputs(*(char **)ap);
ap += sizeof(char *);
break;
default:
(*term.t_putchar)(c);
++ttcol;
}
}
}
(*term.t_eeol)();
(*term.t_flush)();
mpresf = TRUE;
}
/*
* Write out a string. Update the physical cursor position. This assumes that
* the characters in the string all have width "1"; if this is not the case
* things will get screwed up a little.
*/
mlputs(s)
char *s;
{
register int c;
while ((c = *s++) != 0)
{
(*term.t_putchar)(c);
++ttcol;
}
}
/*
* Write out an integer, in the specified radix. Update the physical cursor
* position. This will not handle any negative numbers; maybe it should.
*/
mlputi(i, r)
{
register int q;
static char hexdigits[] = "0123456789ABCDEF";
if (i < 0)
{
i = -i;
(*term.t_putchar)('-');
}
q = i/r;
if (q != 0)
mlputi(q, r);
(*term.t_putchar)(hexdigits[i%r]);
++ttcol;
}
/*
* do the same except as a long integer.
*/
mlputli(l, r)
long l;
{
register long q;
if (l < 0)
{
l = -l;
(*term.t_putchar)('-');
}
q = l/r;
if (q != 0)
mlputli(q, r);
(*term.t_putchar)((int)(l%r)+'0');
++ttcol;
}
#ifdef RAINBOW
putline(row, col, buf)
int row, col;
char buf[];
{
int n;
n = strlen(buf);
if (col + n - 1 > term.t_ncol)
n = term.t_ncol - col + 1;
Put_Data(row, col, n, buf);
}
#endif
==========
os.9/public.domain #79, from jimomura, 10892 chars, Fri Mar 21 22:32:08 1986
----------
TITLE: 'microEMACS' part 10 'ueed.h'
/*
* This file is the general header file for all parts of the MicroEMACS
* display editor. It contains definitions used by everyone, and it contains
* the stuff you have to edit to create a version of the editor for a specific
* operating system and terminal.
*/
/* #define AMIGA 1 /* AmigaDOS, Lattice */
/* #define ST520 0 /* ST520, TOS */
/* #define MWC86 0
/* #define V7 0 /* V7 UN*X or Coherent */
/* #define VMS 0 /* VAX/VMS */
/* #define CPM 0 /* CP/M-86 */
/* #define OS9 1 /* os9/6809 level 1 (coco) */
/* #define OSK 1 /* os9/68000 predefined */
/* #define MSDOS 0 /* MS-DOS predefined */
/* #define ANSI 1 /* ANSI terminal (Vt100) */
#define VT52 1 /* VT52 terminal (Zenith). */
/* #define VT100 0 /* Handle VT100 style keypad. */
/* #define LK201 0 /* Handle LK201 style keypad. */
/* #define RAINBOW 0 /* Use Rainbow fast video. */
/* #define TERMCAP 0 /* Use TERMCAP */
#define CVMVAS 1 /* C-V, M-V arg. in screens. */
#define NFILEN 80 /* # of bytes, file name */
#define NBUFN 16 /* # of bytes, buffer name */
#define NLINE 256 /* # of bytes, line */
#define NKBDM 256 /* # of strokes, keyboard macro */
#define NPAT 80 /* # of bytes, pattern */
#define HUGE 1000 /* Huge number */
#define AGRAVE 0x60 /* M- prefix, Grave (LK201) */
#define METACH 0x1B /* M- prefix, Control-[, ESC */
#define CTMECH 0x1C /* C-M- prefix, Control-\ */
#define EXITCH 0x1D /* Exit level, Control-] */
#define CTRLCH 0x1E /* C- prefix, Control-^ */
#define HELPCH 0x1F /* Help key, Control-_ */
#define CTRL 0x0100 /* Control flag, or'ed in */
#define META 0x0200 /* Meta flag, or'ed in */
#define CTLX 0x0400 /* ^X flag, or'ed in */
#define FALSE 0 /* False, no, bad, etc. */
#define TRUE 1 /* True, yes, good, etc. */
#define ABORT 2 /* Death, ^G, abort, etc. */
#define FIOSUC 0 /* File I/O, success. */
#define FIOFNF 1 /* File I/O, file not found. */
#define FIOEOF 2 /* File I/O, end of file. */
#define FIOERR 3 /* File I/O, error. */
#define CFCPCN 0x0001 /* Last command was C-P, C-N */
#define CFKILL 0x0002 /* Last command was a kill */
/*
* There is a window structure allocated for every active display window. The
* windows are kept in a big list, in top to bottom screen order, with the
* listhead at "wheadp". Each window contains its own values of dot and mark.
* The flag field contains some bits that are set by commands to guide
* redisplay; although this is a bit of a compromise in terms of decoupling,
* the full blown redisplay is just too expensive to run for every input
* character.
*/
typedef struct WINDOW {
struct WINDOW *w_wndp; /* Next window */
struct BUFFER *w_bufp; /* Buffer displayed in window */
struct LINE *w_linep; /* Top line in the window */
struct LINE *w_dotp; /* Line containing "." */
short w_doto; /* Byte offset for "." */
struct LINE *w_markp; /* Line containing "mark" */
short w_marko; /* Byte offset for "mark" */
char w_toprow; /* Origin 0 top row of window */
char w_ntrows; /* # of rows of text in window */
char w_force; /* If NZ, forcing row. */
char w_flag; /* Flags. */
} WINDOW;
#define WFFORCE 0x01 /* Window needs forced reframe */
#define WFMOVE 0x02 /* Movement from line to line */
#define WFEDIT 0x04 /* Editing within a line */
#define WFHARD 0x08 /* Better to a full display */
#define WFMODE 0x10 /* Update mode line. */
/*
* Text is kept in buffers. A buffer header, described below, exists for every
* buffer in the system. The buffers are kept in a big list, so that commands
* that search for a buffer by name can find the buffer header. There is a
* safe store for the dot and mark in the header, but this is only valid if
* the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
* the buffer is kept in a circularly linked list of lines, with a pointer to
* the header line in "b_linep".
*/
typedef struct BUFFER {
struct BUFFER *b_bufp; /* Link to next BUFFER */
struct LINE *b_dotp; /* Link to "." LINE structure */
short b_doto; /* Offset of "." in above LINE */
struct LINE *b_markp; /* The same as the above two, */
short b_marko; /* but for the "mark" */
struct LINE *b_linep; /* Link to the header LINE */
char b_nwnd; /* Count of windows on buffer */
char b_flag; /* Flags */
char b_fname[NFILEN]; /* File name */
char b_bname[NBUFN]; /* Buffer name */
} BUFFER;
#define BFTEMP 0x01 /* Internal temporary buffer */
#define BFCHG 0x02 /* Changed since last write */
/*
* The starting position of a region, and the size of the region in
* characters, is kept in a region structure. Used by the region commands.
*/
typedef struct {
struct LINE *r_linep; /* Origin LINE address. */
short r_offset; /* Origin LINE offset. */
short r_size; /* Length in characters. */
} REGION;
/*
* All text is kept in circularly linked lists of "LINE" structures. These
* begin at the header line (which is the blank line beyond the end of the
* buffer). This line is pointed to by the "BUFFER". Each line contains a the
* number of bytes in the line (the "used" size), the size of the text array,
* and the text. The end of line is not stored as a byte; it's implied. Future
* additions will include update hints, and a list of marks into the line.
*/
typedef struct LINE {
struct LINE *l_fp; /* Link to the next line */
struct LINE *l_bp; /* Link to the previous line */
short l_size; /* Allocated size */
short l_used; /* Used size */
char l_text[1]; /* A bunch of characters. */
} LINE;
#define lforw(lp) ((lp)->l_fp)
#define lback(lp) ((lp)->l_bp)
#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)
#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
#define llength(lp) ((lp)->l_used)
/*
* The editor communicates with the display using a high level interface. A
* "TERM" structure holds useful variables, and indirect pointers to routines
* that do useful operations. The low level get and put routines are here too.
* This lets a terminal, in addition to having non standard commands, have
* funny get and put character code too. The calls might get changed to
* "termp->t_field" style in the future, to make it possible to run more than
* one terminal type.
*/
typedef struct {
short t_nrow; /* Number of rows. */
short t_ncol; /* Number of columns. */
int (*t_open)(); /* Open terminal at the start. */
int (*t_close)(); /* Close terminal at end. */
int (*t_getchar)(); /* Get character from keyboard. */
int (*t_putchar)(); /* Put character to display. */
int (*t_flush)(); /* Flush output buffers. */
int (*t_move)(); /* Move the cursor, origin 0. */
int (*t_eeol)(); /* Erase to end of line. */
int (*t_eeop)(); /* Erase to end of page. */
int (*t_beep)(); /* Beep. */
} TERM;
extern int fillcol; /* Fill column */
extern int currow; /* Cursor row */
extern int curcol; /* Cursor column */
extern int thisflag; /* Flags, this command */
extern int lastflag; /* Flags, last command */
extern int curgoal; /* Goal for C-P, C-N */
extern int mpresf; /* Stuff in message line */
extern int sgarbf; /* State of screen unknown */
extern WINDOW *curwp; /* Current window */
extern BUFFER *curbp; /* Current buffer */
extern WINDOW *wheadp; /* Head of list of windows */
extern BUFFER *bheadp; /* Head of list of buffers */
extern BUFFER *blistp; /* Buffer for C-X C-B */
extern short kbdm[]; /* Holds kayboard macro data */
extern short *kbdmip; /* Input pointer for above */
extern short *kbdmop; /* Output pointer for above */
extern char pat[]; /* Search pattern */
extern TERM term; /*(Terminal information. */
extern BUFFER *bfind(); /* Lookup a buffer by name */
extern WINDOW *wpopup(); /* Pop up window creation */
extern LINE *lalloc(); /* Allocate a line */
==========
os.9/public.domain #80, from jimomura, 9175 chars, Sat Mar 22 18:46:49 1986
----------
TITLE: 'microEMACS' part 11 'uefile1.c'
/*
* The routines in this file
* handle the reading and writing of
* disk files. All of details about the
* reading and writing of the disk are
* in "fileio.c".
*/
#include <stdio.h>
#include "ueed.h"
/*
* Read a file into the current
* buffer. This is really easy; all you do it
* find the name of the file, and call the standard
* "read a file into the current buffer" code.
* Bound to "C-X C-R".
*/
fileread(f, n)
{
register int s;
char fname[NFILEN];
if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
return (s);
return (readin(fname));
}
#ifndef OS9
/*
* Select a file for editing.
* Look around to see if you can find the
* fine in another buffer; if you can find it
* just switch to the buffer. If you cannot find
* the file, create a new buffer, read in the
* text, and switch to the new buffer.
* Bound to C-X C-V.
*/
filevisit(f, n)
{
register BUFFER *bp;
register WINDOW *wp;
register LINE *lp;
register int i;
register int s;
char bname[NBUFN];
char fname[NFILEN];
if ((s=mlreply("Visit file: ", fname, NFILEN)) != TRUE)
return (s);
for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
if ((bp->b_flag&BFTEMP)==0 && strcmp(bp->b_fname, fname)==0) {
if (--curbp->b_nwnd == 0) {
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
curbp->b_markp = curwp->w_markp;
curbp->b_marko = curwp->w_marko;
}
curbp = bp;
curwp->w_bufp = bp;
if (bp->b_nwnd++ == 0) {
curwp->w_dotp = bp->b_dotp;
curwp->w_doto = bp->b_doto;
curwp->w_markp = bp->b_markp;
curwp->w_marko = bp->b_marko;
} else {
wp = wheadp;
while (wp != NULL) {
if (wp!=curwp && wp->w_bufp==bp) {
curwp->w_dotp = wp->w_dotp;
curwp->w_doto = wp->w_doto;
curwp->w_markp = wp->w_markp;
curwp->w_marko = wp->w_marko;
break;
}
wp = wp->w_wndp;
}
}
lp = curwp->w_dotp;
i = curwp->w_ntrows/2;
while (i-- && lback(lp)!=curbp->b_linep)
lp = lback(lp);
curwp->w_linep = lp;
curwp->w_flag |= WFMODE|WFHARD;
mlwrite("[Old buffer]");
return (TRUE);
}
}
makename(bname, fname); /* New buffer name. */
while ((bp=bfind(bname, FALSE, 0)) != NULL) {
s = mlreply("Buffer name: ", bname, NBUFN);
if (s == ABORT) /* ^G to just quit */
return (s);
if (s == FALSE) { /* CR to clobber it */
makename(bname, fname);
break;
}
}
if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
mlwrite("Cannot create buffer");
return (FALSE);
}
if (--curbp->b_nwnd == 0) { /* Undisplay. */
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
curbp->b_markp = curwp->w_markp;
curbp->b_marko = curwp->w_marko;
}
curbp = bp; /* Switch to it. */
curwp->w_bufp = bp;
curbp->b_nwnd++;
return (readin(fname)); /* Read it in. */
}
#endif
/*
* Read file "fname" into the current
* buffer, blowing away any text found there. Called
* by both the read and visit commands. Return the final
* status of the read. Also called by the mainline,
* to read in a file specified on the command line as
* an argument.
*/
readin(fname)
char fname[];
{
register LINE *lp1;
register LINE *lp2;
register int i;
register WINDOW *wp;
register BUFFER *bp;
register int s;
register int nbytes;
register int nline;
char line[NLINE];
bp = curbp; /* Cheap. */
if ((s=bclear(bp)) != TRUE) /* Might be old. */
return (s);
bp->b_flag &= ~(BFTEMP|BFCHG);
strcpy(bp->b_fname, fname);
if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
goto out;
if (s == FIOFNF) { /* File not found. */
mlwrite("[New file]");
goto out;
}
mlwrite("[Reading file]");
nline = 0;
while ((s=ffgetline(line, NLINE)) == FIOSUC) {
nbytes = strlen(line);
if ((lp1=lalloc(nbytes)) == NULL) {
s = FIOERR; /* Keep message on the */
break; /* display. */
}
lp2 = lback(curbp->b_linep);
lp2->l_fp = lp1;
lp1->l_fp = curbp->b_linep;
lp1->l_bp = lp2;
curbp->b_linep->l_bp = lp1;
for (i=0; i<nbytes; ++i)
lputc(lp1, i, line[i]);
++nline;
}
ffclose(); /* Ignore errors. */
if (s == FIOEOF) { /* Don't zap message! */
if (nline == 1)
mlwrite("[Read 1 line]");
else
mlwrite("[Read %d lines]", nline);
}
out:
for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
if (wp->w_bufp == curbp) {
wp->w_linep = lforw(curbp->b_linep);
wp->w_dotp = lforw(curbp->b_linep);
wp->w_doto =
wp->w_markp =
wp->w_marko = 0;
wp->w_flag |= WFMODE|WFHARD;
}
}
if (s == FIOERR) /* False if error. */
return (FALSE);
return (TRUE);
}
/*
* Take a file name, and from it
* fabricate a buffer name. This routine knows
* about the syntax of file names on the target system.
* I suppose that this information could be put in
* a better place than a line of code.
*/
makename(bname, fname)
char bname[];
char fname[];
{
register char *cp1;
register char *cp2;
cp1 = &fname[0];
while (*cp1 != 0)
++cp1;
#ifdef AMIGA
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
--cp1;
#endif
#ifdef VMS
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
--cp1;
#endif
#ifdef CPM
while (cp1!=&fname[0] && cp1[-1]!=':')
--cp1;
#endif
#ifdef MSDOS
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\')
--cp1;
#endif
#ifdef V7
while (cp1!=&fname[0] && cp1[-1]!='/')
--cp1;
#endif
#ifdef OSK
while (cp1!=&fname[0] && cp1[-1]!='/')
--cp1;
#endif
cp2 = &bname[0];
while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
*cp2++ = *cp1++;
*cp2 = 0;
}
/*
* Ask for a file name, and write the
* contents of the current buffer to that file.
* Update the remembered file name and clear the
* buffer changed flag. This handling of file names
* is different from the earlier versions, and
* is more compatable with Gosling EMACS than
* with ITS EMACS. Bound to "C-X C-W".
*/
filewrite(f, n)
{
register WINDOW *wp;
register int s;
char fname[NFILEN];
if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
return (s);
if ((s=writeout(fname)) == TRUE) {
strcpy(curbp->b_fname, fname);
curbp->b_flag &= ~BFCHG;
wp = wheadp; /* Update mode lines. */
while (wp != NULL) {
if (wp->w_bufp == curbp)
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
}
return (s);
}
--
James Omura, Barrister & Solicitor, Toronto
ihnp4!utzoo!lsuc!jimomura
Byte Information eXchange: jimomura
(416) 652-3880