@@ -1,6 +1,14 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
August 10, 2015 : emg 1.8
|
||||
-------------------------
|
||||
Remove most buffer functions.
|
||||
Remove all window functions.
|
||||
Remove window.c, the one remaining function goes to display.c
|
||||
Rework the modeline to look like Mg.
|
||||
Add a version function, bound to "M-e".
|
||||
|
||||
July 10, 2014 : emg 1.7
|
||||
-----------------------
|
||||
Searching now correctly updates line number display.
|
||||
|
||||
@@ -14,9 +14,9 @@ CFLAGS += -ffunction-sections -fdata-sections
|
||||
CFLAGS += -mips16
|
||||
|
||||
# Set the screen size.
|
||||
# Will default to FORCE_COLS=80 and FORCE_ROWS=24
|
||||
# Will default to COLS=80 and ROWS=24
|
||||
# if not set here.
|
||||
#CFLAGS += -DFORCE_COLS=80 -DFORCE_ROWS=24
|
||||
#CFLAGS += -DCOLS=80 -DROWS=24
|
||||
|
||||
# with CFLAGS+= -ffunction-sections -fdata-sections
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
@@ -27,7 +27,7 @@ MAN = emg.0
|
||||
MANSRC = emg.1
|
||||
|
||||
OBJS = basic.o buffer.o display.o file.o fileio.o line.o main.o \
|
||||
random.o region.o search.o tcap.o ttyio.o window.o word.o
|
||||
random.o region.o search.o tcap.o ttyio.o word.o
|
||||
|
||||
all: emg ${MAN}
|
||||
|
||||
|
||||
@@ -254,24 +254,24 @@ int backline(int f, int n)
|
||||
}
|
||||
|
||||
/*
|
||||
* PgDn. Scroll down (FORCE_ROWS - 1).
|
||||
* Just forwline(f, (FORCE_ROWS -1))
|
||||
* PgDn. Scroll down (ROWS - 1).
|
||||
* Just forwline(f, (ROWS -1))
|
||||
* Bound to C-V
|
||||
*/
|
||||
int pagedown(int f, int n)
|
||||
{
|
||||
forwline(f, (FORCE_ROWS - 1));
|
||||
forwline(f, (ROWS - 1));
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* PgUp. Scroll up (FORCE_ROWS - 1).
|
||||
* Just backline(f, (FORCE_ROWS -1))
|
||||
* PgUp. Scroll up (ROWS - 1).
|
||||
* Just backline(f, (ROWS -1))
|
||||
* Bound to M-V
|
||||
*/
|
||||
int pageup(int f, int n)
|
||||
{
|
||||
backline(f, (FORCE_ROWS - 1));
|
||||
backline(f, (ROWS - 1));
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,18 +17,9 @@ extern void mlwrite();
|
||||
extern void mlerase();
|
||||
extern int mlyesno(char *prompt);
|
||||
extern void lfree(LINE *lp);
|
||||
extern WINDOW *wpopup();
|
||||
extern LINE *lalloc();
|
||||
|
||||
int swbuffer(BUFFER *bp);
|
||||
int usebuffer(int f, int n);
|
||||
int nextbuffer(int f, int n);
|
||||
int killbuffer(int f, int n);
|
||||
int zotbuf(BUFFER *bp);
|
||||
int namebuffer(int f, int n);
|
||||
int listbuffers(int f, int n);
|
||||
int makelist();
|
||||
void itoa(char buf[], int width, int num);
|
||||
int addline(char *text);
|
||||
int anycb();
|
||||
BUFFER* bfind(char *bname, int cflag, int bflag);
|
||||
@@ -84,270 +75,6 @@ int swbuffer(BUFFER *bp)
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int usebuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp;
|
||||
char bufn[NBUFN];
|
||||
int s;
|
||||
|
||||
if ((s = mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
|
||||
return (s);
|
||||
if ((bp = bfind(bufn, TRUE, 0)) == NULL)
|
||||
return (FALSE);
|
||||
return (swbuffer(bp));
|
||||
}
|
||||
|
||||
/* switch to the next buffer in the buffer list
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int nextbuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp;
|
||||
|
||||
bp = curbp->b_bufp;
|
||||
/* cycle through the buffers to find an eligable one */
|
||||
while ((bp == NULL) || (bp->b_flag & BFTEMP))
|
||||
{
|
||||
if (bp == NULL)
|
||||
bp = bheadp;
|
||||
else
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (swbuffer(bp));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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".
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int killbuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp;
|
||||
char bufn[NBUFN];
|
||||
int s;
|
||||
|
||||
if ((s = mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
|
||||
return (s);
|
||||
if ((bp = bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown */
|
||||
return (TRUE);
|
||||
return (zotbuf(bp));
|
||||
}
|
||||
|
||||
/* kill the buffer pointed to by bp */
|
||||
int zotbuf(BUFFER *bp)
|
||||
{
|
||||
BUFFER *bp1, *bp2;
|
||||
int s;
|
||||
|
||||
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 (bp->b_linep); /* Release header line */
|
||||
bp1 = 0; /* 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(bp); /* Release buffer block */
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* Rename the current buffer */
|
||||
/* ARGSUSED0 */
|
||||
int namebuffer(int f, int n)
|
||||
{
|
||||
BUFFER *bp; /* pointer to scan through all buffers */
|
||||
char bufn[NBUFN]; /* buffer to hold buffer name */
|
||||
|
||||
/* prompt for and get the new buffer name */
|
||||
ask:
|
||||
if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
|
||||
return (FALSE);
|
||||
|
||||
/* and check for duplicates */
|
||||
bp = bheadp;
|
||||
while (bp != 0)
|
||||
{
|
||||
if (bp != curbp)
|
||||
{
|
||||
/* if the names the same */
|
||||
if (strcmp(bufn, bp->b_bname) == 0)
|
||||
goto ask; /* try again */
|
||||
}
|
||||
bp = bp->b_bufp; /* onward */
|
||||
}
|
||||
|
||||
strncpy(curbp->b_bname, bufn, NBUFN); /* copy buffer name to structure */
|
||||
curwp->w_flag |= WFMODE; /* make mode line replot */
|
||||
mlerase();
|
||||
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".
|
||||
*/
|
||||
/* ARGSUSED0 */
|
||||
int listbuffers(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
BUFFER *bp;
|
||||
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 != 0)
|
||||
{
|
||||
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 = 0;
|
||||
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).
|
||||
*/
|
||||
int makelist()
|
||||
{
|
||||
BUFFER *bp;
|
||||
LINE *lp;
|
||||
char *cp1, *cp2;
|
||||
char b[7], line[128];
|
||||
int nbytes, s, c;
|
||||
|
||||
blistp->b_flag &= ~BFCHG; /* Don't complain! */
|
||||
if ((s = bclear(blistp)) != TRUE) /* Blow old text away */
|
||||
return (s);
|
||||
strncpy (blistp->b_fname, "", 1);
|
||||
if (addline("AC Size Buffer File") == FALSE ||
|
||||
addline("-- ------- ------ ----") == FALSE)
|
||||
return (FALSE);
|
||||
bp = bheadp;
|
||||
|
||||
/* build line to report global mode settings */
|
||||
cp1 = &line[0];
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' ';
|
||||
|
||||
/* output the list of buffers */
|
||||
while (bp != 0)
|
||||
{
|
||||
if ((bp->b_flag & BFTEMP) != 0)
|
||||
{ /* Skip magic ones */
|
||||
bp = bp->b_bufp;
|
||||
continue;
|
||||
}
|
||||
cp1 = &line[0]; /* Start at left edge */
|
||||
|
||||
/* output status of ACTIVE flag (has the file been read in? */
|
||||
if (bp->b_active == TRUE) /* "@" if activated */
|
||||
*cp1++ = '@';
|
||||
else
|
||||
*cp1++ = ' ';
|
||||
|
||||
/* output status of changed flag */
|
||||
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++ = (char)c;
|
||||
*cp1++ = ' '; /* Gap */
|
||||
cp2 = &bp->b_bname[0]; /* Buffer name */
|
||||
while ((c = *cp2++) != 0)
|
||||
*cp1++ = (char)c;
|
||||
cp2 = &bp->b_fname[0]; /* File name */
|
||||
if (*cp2 != 0)
|
||||
{
|
||||
while (cp1 < &line[2 + 1 + 5 + 1 + 6 + 1 + NBUFN]) /* XXX ??? */
|
||||
*cp1++ = ' ';
|
||||
while ((c = *cp2++) != 0)
|
||||
{
|
||||
if (cp1 < &line[128 - 1])
|
||||
*cp1++ = (char)c;
|
||||
}
|
||||
}
|
||||
*cp1 = 0; /* Add to the buffer */
|
||||
if (addline(line) == FALSE)
|
||||
return (FALSE);
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (TRUE); /* All done */
|
||||
}
|
||||
|
||||
void itoa(char buf[], int width, int num)
|
||||
{
|
||||
buf[width] = 0; /* End of string */
|
||||
while (num >= 10)
|
||||
{ /* Conditional digits */
|
||||
buf[--width] = (char)((num % 10) + '0');
|
||||
num /= 10;
|
||||
}
|
||||
buf[--width] = (char)(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
|
||||
|
||||
@@ -19,6 +19,7 @@ extern int getccol();
|
||||
|
||||
void movecursor(int row, int col);
|
||||
void mlerase();
|
||||
int refresh();
|
||||
void vtinit();
|
||||
void vttidy();
|
||||
void vtmove(int row, int col);
|
||||
@@ -58,6 +59,25 @@ int lbound = 0; /* leftmost column of line being displayed */
|
||||
VIDEO **vscreen; /* Virtual screen */
|
||||
VIDEO **pscreen; /* Physical screen */
|
||||
|
||||
/*
|
||||
* Refresh the screen. With no argument, it does the refresh and centers
|
||||
* the cursor on the screen. With an argument it does a reposition instead.
|
||||
* Bound to "C-L:
|
||||
*/
|
||||
int
|
||||
refresh(int f, int n)
|
||||
{
|
||||
if (n >= 0)
|
||||
n++; /* adjust to screen row */
|
||||
if (f == FALSE) {
|
||||
sgarbf = TRUE;
|
||||
n = 0; /* Center dot */
|
||||
}
|
||||
curwp->w_force = n;
|
||||
curwp->w_flag |= WFFORCE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -620,72 +640,41 @@ void updateline(int row, char vline[], char pline[], short *flags)
|
||||
void modeline(WINDOW *wp)
|
||||
{
|
||||
BUFFER *bp;
|
||||
int lchar; /* character to draw line in buffer with */
|
||||
int n; /* cursor position count */
|
||||
int len; /* line/column display check */
|
||||
char sl[25]; /* line/column display (probably overkill) */
|
||||
char sl[17]; /* line/column display (probably overkill) */
|
||||
|
||||
n = wp->w_toprow + wp->w_ntrows; /* Location */
|
||||
vscreen[n]->v_flag |= VFCHG; /* Redraw next time */
|
||||
vtmove(n, 0); /* Seek to right line */
|
||||
if (wp == curwp) /* mark the current buffer */
|
||||
lchar = '=';
|
||||
else
|
||||
if (revexist)
|
||||
lchar = ' ';
|
||||
else
|
||||
lchar = '-';
|
||||
|
||||
vtputc(lchar);
|
||||
bp = wp->w_bufp;
|
||||
|
||||
if ((bp->b_flag & BFCHG) != 0) /* "*" if changed */
|
||||
vtputc('-');
|
||||
vtputc('-');
|
||||
if ((bp->b_flag & BFCHG) != 0) { /* "**" if changed */
|
||||
vtputc('*');
|
||||
vtputc('*');
|
||||
} else {
|
||||
vtputc('-');
|
||||
vtputc('-');
|
||||
}
|
||||
vtputc('-');
|
||||
n = 5;
|
||||
n += vtputs("emg: ");
|
||||
if (bp->b_fname[0] == '\0')
|
||||
n += vtputs("*scratch*");
|
||||
else
|
||||
vtputc(lchar);
|
||||
n += vtputs(&(bp->b_fname[0]));
|
||||
while (n++ < 42) /* Pad out with blanks. */
|
||||
vtputc(' ');
|
||||
n += vtputs("(fundamental)");
|
||||
|
||||
n = 2;
|
||||
/* This is the version string. Do not forget to
|
||||
* increment when releasing a new version. */
|
||||
n += vtputs(" emg 1.7 ");
|
||||
|
||||
vtputc(lchar);
|
||||
vtputc(lchar);
|
||||
vtputc(' ');
|
||||
n += 3;
|
||||
|
||||
n += vtputs(&(bp->b_bname[0]));
|
||||
|
||||
vtputc(' ');
|
||||
vtputc(lchar);
|
||||
vtputc(lchar);
|
||||
n += 3;
|
||||
|
||||
if (bp->b_fname[0] != 0) /* File name */
|
||||
{
|
||||
vtputc(' ');
|
||||
++n;
|
||||
n += vtputs("File: ");
|
||||
|
||||
n += vtputs(&(bp->b_fname[0]));
|
||||
|
||||
vtputc(' ');
|
||||
vtputc(lchar);
|
||||
vtputc(lchar);
|
||||
n += 3;
|
||||
}
|
||||
|
||||
len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ",
|
||||
((100*(wp->w_dotline)) / bp->b_lines),
|
||||
(wp->w_dotline + 1), getccol(FALSE));
|
||||
len = snprintf(sl, sizeof(sl), "--L%d--C%d",
|
||||
(wp->w_dotline + 1), getccol(FALSE));
|
||||
if (len < sizeof(sl) && len != -1)
|
||||
n += vtputs(sl);
|
||||
|
||||
while (n < term.t_ncol) /* Pad to full width */
|
||||
{
|
||||
vtputc(lchar);
|
||||
++n;
|
||||
}
|
||||
while (n++ <= term.t_ncol) /* Pad to full width */
|
||||
vtputc('-');
|
||||
}
|
||||
|
||||
/* update all the mode lines */
|
||||
|
||||
@@ -30,36 +30,27 @@ KEYTAB keytab[] = {
|
||||
{CTRL | 'Y', yank},
|
||||
{CTLX | '(', ctlxlp},
|
||||
{CTLX | ')', ctlxrp},
|
||||
{CTLX | '1', onlywind},
|
||||
{CTLX | '2', splitwind},
|
||||
{CTLX | 'B', usebuffer},
|
||||
{CTLX | 'E', ctlxe},
|
||||
{CTLX | 'F', setfillcol},
|
||||
{CTLX | 'K', killbuffer},
|
||||
{CTLX | 'N', filename},
|
||||
{CTLX | 'O', nextwind},
|
||||
{CTLX | 'S', filesave}, /* non-standard */
|
||||
{CTLX | 'Q', quote}, /* non-standard */
|
||||
{CTLX | 'X', nextbuffer},
|
||||
{CTLX | '^', enlargewind},
|
||||
{CTLX | CTRL | 'B', listbuffers},
|
||||
{CTLX | CTRL | 'C', quit},
|
||||
{CTLX | CTRL | 'F', filefind},
|
||||
{CTLX | CTRL | 'F', fileread},
|
||||
{CTLX | CTRL | 'I', insfile},
|
||||
{CTLX | CTRL | 'R', fileread},
|
||||
{CTLX | CTRL | 'S', filesave},
|
||||
{CTLX | CTRL | 'W', filewrite},
|
||||
{META | '.', setmark},
|
||||
{META | '<', gotobob},
|
||||
{META | '>', gotoeob},
|
||||
{META | 'B', backword},
|
||||
{META | 'E', showversion}, /* non-standard */
|
||||
{META | 'F', forwword},
|
||||
{META | 'G', setline}, /* non-standard */
|
||||
{META | 'S', forwsearch}, /* non-standard */
|
||||
{META | 'V', pageup},
|
||||
{META | 'W', copyregion},
|
||||
{META | 'Z', quickexit},
|
||||
{META | CTRL | 'N', namebuffer},
|
||||
{0x7F, backdel},
|
||||
{META | '[', extendedcmd},
|
||||
{META | 'O', extendedcmd},
|
||||
|
||||
@@ -12,7 +12,6 @@ extern int ctlxlp(); /* Begin macro */
|
||||
extern int ctlxrp(); /* End macro */
|
||||
extern int ctlxe(); /* Execute macro */
|
||||
extern int fileread(); /* Get a file, read only */
|
||||
extern int filefind(); /* Get a file, read write */
|
||||
extern int filewrite(); /* Write a file */
|
||||
extern int filesave(); /* Save current file */
|
||||
extern int filename(); /* Adjust file name */
|
||||
@@ -31,15 +30,6 @@ extern int setfillcol(); /* Set fill column */
|
||||
extern int setmark(); /* Set mark */
|
||||
extern int forwsearch(); /* Search forward */
|
||||
extern int backsearch(); /* Search backwards */
|
||||
extern int nextwind(); /* Move to the next window */
|
||||
extern int prevwind(); /* Move to the previous window */
|
||||
extern int onlywind(); /* Make current window only one */
|
||||
extern int splitwind(); /* Split current window */
|
||||
extern int enlargewind(); /* Enlarge display window */
|
||||
extern int shrinkwind(); /* Shrink window */
|
||||
extern int listbuffers(); /* Display list of buffers */
|
||||
extern int usebuffer(); /* Switch a window to a buffer */
|
||||
extern int killbuffer(); /* Make a buffer go away */
|
||||
extern int refresh(); /* Refresh the screen */
|
||||
extern int twiddle(); /* Twiddle characters */
|
||||
extern int tab(); /* Insert tab */
|
||||
@@ -56,10 +46,9 @@ extern int killregion(); /* Kill region */
|
||||
extern int copyregion(); /* Copy region to kill buffer */
|
||||
extern int quickexit(); /* low keystroke style exit */
|
||||
extern int setline(); /* go to a numbered line */
|
||||
extern int namebuffer(); /* rename the current buffer */
|
||||
extern int deskey(); /* describe a key's binding */
|
||||
extern int insfile(); /* insert a file */
|
||||
extern int nextbuffer(); /* switch to the next buffer */
|
||||
extern int forwhunt(); /* hunt forward for next match */
|
||||
extern int backhunt(); /* hunt backwards for next match */
|
||||
extern int extendedcmd(); /* parse ANSI/VT100 extended keys */
|
||||
extern int extendedcmd(); /* parse ANSI/VT100 extended keys */
|
||||
extern int showversion(); /* show emacs version */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" Basic emg man page.
|
||||
.\" As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain.
|
||||
.\"
|
||||
.Dd June 17, 2014
|
||||
.Dd August 9, 2014
|
||||
.Os
|
||||
.Dt EMG 1
|
||||
.Sh NAME
|
||||
@@ -11,7 +11,7 @@
|
||||
.Nd very small Emacs-like text editor
|
||||
.Sh SYNOPSIS
|
||||
.Nm emg
|
||||
.Op Ar
|
||||
.Op Ar file
|
||||
.Sh DESCRIPTION
|
||||
.Nm ,
|
||||
or Ersatz Mg, is an Emacs-like text editor designed for RetroBSD
|
||||
@@ -21,15 +21,12 @@ was originally created to fit into an operating environment of 96K of RAM,
|
||||
and one in which Mg did not fit and Ersatz Emacs did not build.
|
||||
By combining parts of each a working editor was created.
|
||||
.Pp
|
||||
When invoked without file arguments,
|
||||
When invoked without a file argument,
|
||||
.Nm
|
||||
creates a
|
||||
.Qq main
|
||||
.Em *scratch*
|
||||
buffer.
|
||||
This buffer must be renamed
|
||||
.Ic ( C-x n )
|
||||
in order to be saved
|
||||
.Ic ( C-x C-s ) .
|
||||
This buffer can be edited and saved like a named buffer.
|
||||
.Pp
|
||||
As both Ersatz Emacs and Mg are Public Domain,
|
||||
.Nm
|
||||
@@ -53,9 +50,6 @@ Ersatz Emacs and Mg were combined by
|
||||
to create
|
||||
.Nm .
|
||||
.Sh BUGS
|
||||
None known.
|
||||
However, patches are appreciated if any are found.
|
||||
.Sh TODO
|
||||
It would be nice to have automatic window resizing.
|
||||
It would also be nice if
|
||||
.Nm
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
emg keybindings (July 7, 2014)
|
||||
emg keybindings (August 9, 2014)
|
||||
Based on Ersatz Emacs (2000/09/14)
|
||||
|
||||
M- means to use the <ESC> key prior to using another key
|
||||
@@ -53,25 +53,10 @@ Generally, the procedure for copying or moving text is:
|
||||
2) Delete it (with ^W) or copy it (with M-W) into the kill buffer.
|
||||
3) Move the cursor to the desired location and yank it back (with ^Y).
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
MULTIPLE BUFFERS
|
||||
|
||||
A buffer contains a COPY of a document being edited, and must be saved for
|
||||
changes to be kept. Many buffers may be activated at once.
|
||||
|
||||
^X B Switch to another buffer.
|
||||
^X ^B Show buffer directory in a window (^X 1 to remove).
|
||||
^X K Delete a non-displayed buffer.
|
||||
^X X Switch to next buffer in buffer list.
|
||||
^X N Change the filename associated with the buffer.
|
||||
M-^N Change the name of the buffer.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
READING FROM DISK
|
||||
|
||||
^X^F Find file; read into a new buffer created from filename.
|
||||
(This is the usual way to edit a new file.)
|
||||
^X^R Read file into current buffer, erasing its previous contents.
|
||||
^X^F Read file into current buffer, erasing its previous contents.
|
||||
No new buffer will be created.
|
||||
^X^I Insert file into current buffer at cursor's location.
|
||||
|
||||
@@ -83,16 +68,6 @@ M-^N Change the name of the buffer.
|
||||
^X^W Write current buffer to disk. Type in a new filename at the prompt to
|
||||
write to; it will also become the current buffer's filename.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
MULTIPLE WINDOWS
|
||||
|
||||
Many windows may be visible at once on the screen. Windows may show different
|
||||
parts of the same buffer, or each may display a different one.
|
||||
|
||||
^X 2 Split the current window in two ^X 1 Show only current window
|
||||
^X O Move cursor to next window ^X ^ Enlarge current window
|
||||
M-^V Scroll other window down M-^Z Scroll other window up
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
EXITING
|
||||
|
||||
@@ -118,9 +93,6 @@ M-^V Scroll other window down M-^Z Scroll other window up
|
||||
are from the bottom of the screen.
|
||||
^U<number>^X F
|
||||
Set the right margin to column <number> for paragraph formatting.
|
||||
^U<number>^X^
|
||||
Enlarge a split window by <number> rows. A negative number shrinks the
|
||||
window.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
SPECIAL KEYS
|
||||
|
||||
@@ -34,14 +34,14 @@
|
||||
/*
|
||||
* screen constants
|
||||
* override with
|
||||
* CFLAGS += -DFORCE_COLS=XXX -DFORCE_ROWS=XXX
|
||||
* CFLAGS += -DCOLS=XXX -DROWS=XXX
|
||||
*/
|
||||
#ifndef FORCE_COLS
|
||||
#define FORCE_COLS 80
|
||||
#ifndef COLS
|
||||
#define COLS 80
|
||||
#endif
|
||||
|
||||
#ifndef FORCE_ROWS
|
||||
#define FORCE_ROWS 24
|
||||
#ifndef ROWS
|
||||
#define ROWS 24
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -23,7 +23,6 @@ extern LINE *lalloc();
|
||||
|
||||
int fileread(int f, int n);
|
||||
int insfile(int f, int n);
|
||||
int filefind(int f, int n);
|
||||
int getfile(char fname[]);
|
||||
int readin(char fname[]);
|
||||
void makename(char bname[], char fname[]);
|
||||
@@ -63,22 +62,6 @@ int insfile(int f, int n)
|
||||
return (ifile(fname));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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-F.
|
||||
*/
|
||||
int filefind(int f, int n)
|
||||
{
|
||||
char fname[NFILEN]; /* file user wishes to find */
|
||||
int s; /* status return */
|
||||
|
||||
if ((s = mlreply("Find file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
return (getfile(fname));
|
||||
}
|
||||
|
||||
int getfile(char fname[])
|
||||
{
|
||||
BUFFER *bp;
|
||||
@@ -285,10 +268,7 @@ int filesave(int f, int n)
|
||||
if ((curbp->b_flag & BFCHG) == 0) /* Return, no changes */
|
||||
return (TRUE);
|
||||
if (curbp->b_fname[0] == 0)
|
||||
{ /* Must have a name */
|
||||
mlwrite("No file name");
|
||||
return (FALSE);
|
||||
}
|
||||
filename(f, n); /* Must have a name */
|
||||
if ((s = writeout(curbp->b_fname)) == TRUE)
|
||||
{
|
||||
curbp->b_flag &= ~BFCHG;
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
#define maindef /* make global definitions not external */
|
||||
|
||||
#include <string.h> /* strncpy(3) */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc(3) */
|
||||
#include <string.h> /* strncpy(3) */
|
||||
#include "estruct.h" /* global structures and defines */
|
||||
#include "efunc.h" /* function declarations and name table */
|
||||
#include "edef.h" /* global definitions */
|
||||
@@ -40,13 +41,13 @@ int ctlxe(int f, int n);
|
||||
int ctrlg(int f, int n);
|
||||
int extendedcmd(int f, int n);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
BUFFER *bp;
|
||||
char bname[NBUFN]; /* buffer name of file to read */
|
||||
int c, f, n, mflag;
|
||||
int ffile; /* first file flag */
|
||||
int carg; /* current arg to scan */
|
||||
int basec; /* c stripped of meta character */
|
||||
|
||||
/* initialize the editor and process the startup file */
|
||||
@@ -58,19 +59,21 @@ int main(int argc, char *argv[])
|
||||
update(); /* let the user know we are here */
|
||||
|
||||
/* scan through the command line and get the files to edit */
|
||||
for (carg = 1; carg < argc; ++carg)
|
||||
{
|
||||
if (argc > 2) {
|
||||
(void) fprintf(stderr, "Can only edit one file at a time\n");
|
||||
exit(1);
|
||||
} else if (argc == 2) {
|
||||
/* set up a buffer for this file */
|
||||
makename(bname, argv[carg]);
|
||||
makename(bname, argv[1]);
|
||||
|
||||
/* if this is the first file, read it in */
|
||||
if (ffile)
|
||||
{
|
||||
bp = curbp;
|
||||
makename(bname, argv[carg]);
|
||||
makename(bname, argv[1]);
|
||||
strncpy(bp->b_bname, bname, NBUFN);
|
||||
strncpy(bp->b_fname, argv[carg], NFILEN);
|
||||
if (readin(argv[carg]) == ABORT)
|
||||
strncpy(bp->b_fname, argv[1], NFILEN);
|
||||
if (readin(argv[1]) == ABORT)
|
||||
{
|
||||
strncpy(bp->b_bname, "main", 5);
|
||||
strncpy(bp->b_fname, "", 1);
|
||||
@@ -83,7 +86,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
/* set this to inactive */
|
||||
bp = bfind(bname, TRUE, 0);
|
||||
strncpy(bp->b_fname, argv[carg], NFILEN);
|
||||
strncpy(bp->b_fname, argv[1], NFILEN);
|
||||
bp->b_active = FALSE;
|
||||
}
|
||||
}
|
||||
@@ -467,3 +470,16 @@ int extendedcmd(int f, int n)
|
||||
}
|
||||
return cmd(f, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the version. All this does
|
||||
* is copy the version string into the echo line.
|
||||
* Taken from OpenBSD Mg.
|
||||
* THIS IS WHERE YOU INCREMENT VERSION NUMBER BEFORE RELEASE!
|
||||
*/
|
||||
int
|
||||
showversion(int f, int n)
|
||||
{
|
||||
mlwrite("emg 1.8");
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ extern int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar);
|
||||
extern void update();
|
||||
extern int forwchar(int f, int n);
|
||||
extern int ldelete(int n, int kflag);
|
||||
extern int lnewline();
|
||||
extern int linsert(int n, int c);
|
||||
|
||||
int forwsearch(int f, int n);
|
||||
|
||||
@@ -47,16 +47,16 @@ TERM term = {
|
||||
|
||||
void getwinsize()
|
||||
{
|
||||
int cols = FORCE_COLS;
|
||||
int rows = FORCE_ROWS;
|
||||
int cols = COLS;
|
||||
int rows = ROWS;
|
||||
|
||||
/* Too small and we're out */
|
||||
if ((cols < 10) || (rows < 3))
|
||||
panic("Too few columns or rows");
|
||||
|
||||
if (FORCE_COLS > MAXCOL)
|
||||
if (COLS > MAXCOL)
|
||||
cols = MAXCOL;
|
||||
if (FORCE_ROWS > MAXROW)
|
||||
if (ROWS > MAXROW)
|
||||
rows = MAXROW;
|
||||
|
||||
term.t_ncol = cols;
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/*
|
||||
* Window management. Some of the functions are internal, and some are
|
||||
* attached to keys that the user actually types
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* free(3), malloc(3) */
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
extern void upmode();
|
||||
extern void mlwrite();
|
||||
|
||||
int refresh(int f, int n);
|
||||
int nextwind(int f, int n);
|
||||
int prevwind(int f, int n);
|
||||
int onlywind(int f, int n);
|
||||
int splitwind(int f, int n);
|
||||
int enlargewind(int f, int n);
|
||||
int shrinkwind(int f, int n);
|
||||
WINDOW* wpopup();
|
||||
|
||||
/*
|
||||
* Refresh the screen. With no argument, it does the refresh and centers
|
||||
* the cursor on the screen. With an argument it does a reposition instead.
|
||||
* Bound to "C-L"
|
||||
*/
|
||||
int refresh(int f, int n)
|
||||
{
|
||||
if (n >= 0)
|
||||
n++; /* adjust to screen row */
|
||||
if (f == FALSE)
|
||||
{
|
||||
sgarbf = TRUE;
|
||||
n = 0; /* Center dot */
|
||||
}
|
||||
curwp->w_force = n;
|
||||
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. Bound to "C-X C-N"
|
||||
*/
|
||||
int nextwind(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
|
||||
if ((wp = curwp->w_wndp) == NULL)
|
||||
wp = wheadp;
|
||||
|
||||
curwp = wp;
|
||||
curbp = wp->w_bufp;
|
||||
upmode();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command makes the previous window (previous => up the screen) the
|
||||
* current window. There arn't any errors, although the command does not do a
|
||||
* lot if there is 1 window
|
||||
*/
|
||||
int prevwind(int f, int n)
|
||||
{
|
||||
WINDOW *wp1, *wp2;
|
||||
|
||||
wp1 = wheadp;
|
||||
wp2 = curwp;
|
||||
|
||||
if (wp1 == wp2)
|
||||
wp2 = NULL;
|
||||
|
||||
while (wp1->w_wndp != wp2)
|
||||
wp1 = wp1->w_wndp;
|
||||
|
||||
curwp = wp1;
|
||||
curbp = wp1->w_bufp;
|
||||
upmode();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command makes the current window the only window on the screen. Bound
|
||||
* to "C-X 1". 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
|
||||
*/
|
||||
int onlywind(int f, int n)
|
||||
{
|
||||
WINDOW *wp;
|
||||
LINE *lp;
|
||||
int i;
|
||||
|
||||
while (wheadp != curwp)
|
||||
{
|
||||
wp = wheadp;
|
||||
wheadp = wp->w_wndp;
|
||||
if (--wp->w_bufp->b_nwnd == 0)
|
||||
{
|
||||
wp->w_bufp->b_dotp = wp->w_dotp;
|
||||
wp->w_bufp->b_doto = wp->w_doto;
|
||||
wp->w_bufp->b_markp = wp->w_markp;
|
||||
wp->w_bufp->b_marko = wp->w_marko;
|
||||
}
|
||||
free((char *) wp);
|
||||
}
|
||||
while (curwp->w_wndp != NULL)
|
||||
{
|
||||
wp = curwp->w_wndp;
|
||||
curwp->w_wndp = wp->w_wndp;
|
||||
if (--wp->w_bufp->b_nwnd == 0)
|
||||
{
|
||||
wp->w_bufp->b_dotp = wp->w_dotp;
|
||||
wp->w_bufp->b_doto = wp->w_doto;
|
||||
wp->w_bufp->b_markp = wp->w_markp;
|
||||
wp->w_bufp->b_marko = wp->w_marko;
|
||||
}
|
||||
free((char *) wp);
|
||||
}
|
||||
lp = curwp->w_linep;
|
||||
i = curwp->w_toprow;
|
||||
while (i != 0 && lback (lp) != curbp->b_linep)
|
||||
{
|
||||
--i;
|
||||
lp = lback(lp);
|
||||
}
|
||||
curwp->w_toprow = 0;
|
||||
curwp->w_ntrows = term.t_nrow - 1;
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the current window. A window smaller than 3 lines cannot be split.
|
||||
* The only other error that is possible is a "malloc" failure allocating the
|
||||
* structure for the new window. Bound to "C-X 2"
|
||||
*/
|
||||
int splitwind(int f, int n)
|
||||
{
|
||||
LINE *lp;
|
||||
WINDOW *wp, *wp1, *wp2;
|
||||
int ntru, ntrl, ntrd;
|
||||
|
||||
if (curwp->w_ntrows < 3)
|
||||
{
|
||||
mlwrite("Cannot split a %d line window", curwp->w_ntrows);
|
||||
return (FALSE);
|
||||
}
|
||||
if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL)
|
||||
{
|
||||
mlwrite("Cannot allocate WINDOW block");
|
||||
return (FALSE);
|
||||
}
|
||||
++curbp->b_nwnd; /* Displayed twice */
|
||||
wp->w_bufp = curbp;
|
||||
wp->w_dotp = curwp->w_dotp;
|
||||
wp->w_doto = curwp->w_doto;
|
||||
wp->w_markp = curwp->w_markp;
|
||||
wp->w_marko = curwp->w_marko;
|
||||
wp->w_flag = 0;
|
||||
wp->w_force = 0;
|
||||
ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */
|
||||
ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */
|
||||
lp = curwp->w_linep;
|
||||
ntrd = 0;
|
||||
while (lp != curwp->w_dotp)
|
||||
{
|
||||
++ntrd;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
lp = curwp->w_linep;
|
||||
if (ntrd <= ntru)
|
||||
{ /* Old is upper window */
|
||||
if (ntrd == ntru) /* Hit mode line */
|
||||
lp = lforw(lp);
|
||||
curwp->w_ntrows = ntru;
|
||||
wp->w_wndp = curwp->w_wndp;
|
||||
curwp->w_wndp = wp;
|
||||
wp->w_toprow = curwp->w_toprow + ntru + 1;
|
||||
wp->w_ntrows = ntrl;
|
||||
}
|
||||
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;
|
||||
while (ntru--)
|
||||
lp = lforw (lp);
|
||||
}
|
||||
curwp->w_linep = lp; /* Adjust the top lines */
|
||||
wp->w_linep = lp; /* if necessary */
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
wp->w_flag |= WFMODE | WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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. Bound to "C-X Z"
|
||||
*/
|
||||
int enlargewind(int f, int n)
|
||||
{
|
||||
WINDOW *adjwp;
|
||||
LINE *lp;
|
||||
int i;
|
||||
|
||||
if (n < 0)
|
||||
return (shrinkwind(f, -n));
|
||||
if (wheadp->w_wndp == NULL)
|
||||
{
|
||||
mlwrite("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)
|
||||
{
|
||||
mlwrite("Impossible change");
|
||||
return (FALSE);
|
||||
}
|
||||
if (curwp->w_wndp == adjwp)
|
||||
{ /* Shrink below */
|
||||
lp = adjwp->w_linep;
|
||||
for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i)
|
||||
lp = lforw(lp);
|
||||
adjwp->w_linep = lp;
|
||||
adjwp->w_toprow += n;
|
||||
}
|
||||
else
|
||||
{ /* Shrink above */
|
||||
lp = curwp->w_linep;
|
||||
for (i = 0; i < n && lback(lp) != curbp->b_linep; ++i)
|
||||
lp = lback(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_toprow -= n;
|
||||
}
|
||||
curwp->w_ntrows += n;
|
||||
adjwp->w_ntrows -= n;
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
adjwp->w_flag |= WFMODE | WFHARD;
|
||||
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)
|
||||
{
|
||||
WINDOW *adjwp;
|
||||
LINE *lp;
|
||||
int i;
|
||||
|
||||
if (n < 0)
|
||||
return (enlargewind(f, -n));
|
||||
if (wheadp->w_wndp == NULL)
|
||||
{
|
||||
mlwrite("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)
|
||||
{
|
||||
mlwrite("Impossible change");
|
||||
return (FALSE);
|
||||
}
|
||||
if (curwp->w_wndp == adjwp)
|
||||
{ /* Grow below */
|
||||
lp = adjwp->w_linep;
|
||||
for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; ++i)
|
||||
lp = lback(lp);
|
||||
adjwp->w_linep = lp;
|
||||
adjwp->w_toprow -= n;
|
||||
}
|
||||
else
|
||||
{ /* Grow above */
|
||||
lp = curwp->w_linep;
|
||||
for (i = 0; i < n && lp != curbp->b_linep; ++i)
|
||||
lp = lforw(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_toprow += n;
|
||||
}
|
||||
curwp->w_ntrows -= n;
|
||||
adjwp->w_ntrows += n;
|
||||
curwp->w_flag |= WFMODE | WFHARD;
|
||||
adjwp->w_flag |= WFMODE | WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
WINDOW *wp;
|
||||
|
||||
if (wheadp->w_wndp == NULL /* Only 1 window */
|
||||
&& splitwind(FALSE, 0) == FALSE) /* and it won't split */
|
||||
return (NULL);
|
||||
wp = wheadp; /* Find window to use */
|
||||
while (wp != NULL && wp == curwp)
|
||||
wp = wp->w_wndp;
|
||||
return (wp);
|
||||
}
|
||||
Reference in New Issue
Block a user