mirror of
https://github.com/rfivet/uemacs.git
synced 2025-01-02 22:46:35 -05:00
Initial import of em-4.0.15-lt
This is a slightly updated version of uemacs-PK (PK is Pekka Kutvonen) which was used at Helsinki University a long time ago. My fingers cannot be retrained.
This commit is contained in:
commit
d7148b21fe
264
ansi.c
Normal file
264
ansi.c
Normal file
@ -0,0 +1,264 @@
|
||||
/* ANSI.C
|
||||
*
|
||||
* The routines in this file provide support for ANSI style terminals
|
||||
* over a serial line. The serial I/O services are provided by routines in
|
||||
* "termio.c". It compiles into nothing if not an ANSI device.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#define termdef 1 /* don't define "term" external */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if ANSI
|
||||
|
||||
#define NROW 25 /* Screen size. */
|
||||
#define NCOL 80 /* Edit if you want to. */
|
||||
|
||||
#if PKCODE
|
||||
#define MROW 64
|
||||
#endif
|
||||
#define NPAUSE 100 /* # times thru update to pause */
|
||||
#define MARGIN 8 /* size of minimim margin and */
|
||||
#define SCRSIZ 64 /* scroll size for extended lines */
|
||||
#define BEL 0x07 /* BEL character. */
|
||||
#define ESC 0x1B /* ESC character. */
|
||||
|
||||
extern int ttopen(); /* Forward references. */
|
||||
extern int ttgetc();
|
||||
extern int ttputc();
|
||||
extern int ttflush();
|
||||
extern int ttclose();
|
||||
extern int ansimove();
|
||||
extern int ansieeol();
|
||||
extern int ansieeop();
|
||||
extern int ansibeep();
|
||||
extern int ansiopen();
|
||||
extern int ansirev();
|
||||
extern int ansiclose();
|
||||
extern int ansikopen();
|
||||
extern int ansikclose();
|
||||
extern int ansicres();
|
||||
|
||||
#if COLOR
|
||||
extern int ansifcol();
|
||||
extern int ansibcol();
|
||||
|
||||
int cfcolor = -1; /* current forground color */
|
||||
int cbcolor = -1; /* current background color */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Standard terminal interface dispatch table. Most of the fields point into
|
||||
* "termio" code.
|
||||
*/
|
||||
TERM term = {
|
||||
#if PKCODE
|
||||
MROW-1,
|
||||
#else
|
||||
NROW-1,
|
||||
#endif
|
||||
NROW-1,
|
||||
NCOL,
|
||||
NCOL,
|
||||
MARGIN,
|
||||
SCRSIZ,
|
||||
NPAUSE,
|
||||
ansiopen,
|
||||
ansiclose,
|
||||
ansikopen,
|
||||
ansikclose,
|
||||
ttgetc,
|
||||
ttputc,
|
||||
ttflush,
|
||||
ansimove,
|
||||
ansieeol,
|
||||
ansieeop,
|
||||
ansibeep,
|
||||
ansirev,
|
||||
ansicres
|
||||
#if COLOR
|
||||
, ansifcol,
|
||||
ansibcol
|
||||
#endif
|
||||
#if SCROLLCODE
|
||||
, NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
#if COLOR
|
||||
ansifcol(color) /* set the current output color */
|
||||
|
||||
int color; /* color to set */
|
||||
|
||||
{
|
||||
if (color == cfcolor)
|
||||
return;
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ansiparm(color+30);
|
||||
ttputc('m');
|
||||
cfcolor = color;
|
||||
}
|
||||
|
||||
ansibcol(color) /* set the current background color */
|
||||
|
||||
int color; /* color to set */
|
||||
|
||||
{
|
||||
if (color == cbcolor)
|
||||
return;
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ansiparm(color+40);
|
||||
ttputc('m');
|
||||
cbcolor = color;
|
||||
}
|
||||
#endif
|
||||
|
||||
ansimove(row, col)
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ansiparm(row+1);
|
||||
ttputc(';');
|
||||
ansiparm(col+1);
|
||||
ttputc('H');
|
||||
}
|
||||
|
||||
ansieeol()
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ttputc('K');
|
||||
}
|
||||
|
||||
ansieeop()
|
||||
{
|
||||
#if COLOR
|
||||
ansifcol(gfcolor);
|
||||
ansibcol(gbcolor);
|
||||
#endif
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ttputc('J');
|
||||
}
|
||||
|
||||
ansirev(state) /* change reverse video state */
|
||||
|
||||
int state; /* TRUE = reverse, FALSE = normal */
|
||||
|
||||
{
|
||||
#if COLOR
|
||||
int ftmp, btmp; /* temporaries for colors */
|
||||
#endif
|
||||
|
||||
ttputc(ESC);
|
||||
ttputc('[');
|
||||
ttputc(state ? '7': '0');
|
||||
ttputc('m');
|
||||
#if COLOR
|
||||
if (state == FALSE) {
|
||||
ftmp = cfcolor;
|
||||
btmp = cbcolor;
|
||||
cfcolor = -1;
|
||||
cbcolor = -1;
|
||||
ansifcol(ftmp);
|
||||
ansibcol(btmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ansicres() /* change screen resolution */
|
||||
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
spal(dummy) /* change pallette settings */
|
||||
|
||||
{
|
||||
/* none for now */
|
||||
}
|
||||
|
||||
ansibeep()
|
||||
{
|
||||
ttputc(BEL);
|
||||
ttflush();
|
||||
}
|
||||
|
||||
ansiparm(n)
|
||||
register int n;
|
||||
{
|
||||
register int q,r;
|
||||
|
||||
q = n/10;
|
||||
if (q != 0) {
|
||||
r = q/10;
|
||||
if (r != 0) {
|
||||
ttputc((r%10)+'0');
|
||||
}
|
||||
ttputc((q%10) + '0');
|
||||
}
|
||||
ttputc((n%10) + '0');
|
||||
}
|
||||
|
||||
ansiopen()
|
||||
{
|
||||
#if V7 | USG | BSD
|
||||
register char *cp;
|
||||
char *getenv();
|
||||
|
||||
if ((cp = getenv("TERM")) == NULL) {
|
||||
puts("Shell variable TERM not defined!");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(cp, "vt100") != 0) {
|
||||
puts("Terminal type not 'vt100'!");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
strcpy(sres, "NORMAL");
|
||||
revexist = TRUE;
|
||||
ttopen();
|
||||
}
|
||||
|
||||
ansiclose()
|
||||
|
||||
{
|
||||
#if COLOR
|
||||
ansifcol(7);
|
||||
ansibcol(0);
|
||||
#endif
|
||||
ttclose();
|
||||
}
|
||||
|
||||
ansikopen() /* open the keyboard (a noop here) */
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
ansikclose() /* close the keyboard (a noop here) */
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
#if FNLABEL
|
||||
fnclabel(f, n) /* label a function key */
|
||||
|
||||
int f,n; /* default flag, numeric argument [unused] */
|
||||
|
||||
{
|
||||
/* on machines with no function keys...don't bother */
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
ansihello()
|
||||
{
|
||||
}
|
||||
#endif
|
462
basic.c
Normal file
462
basic.c
Normal file
@ -0,0 +1,462 @@
|
||||
/* BASIC.C
|
||||
*
|
||||
* The routines in this file move the cursor around on the screen. They
|
||||
* compute a new value for the cursor, then adjust ".". The display code
|
||||
* always updates the cursor location, so only moves between lines, or
|
||||
* functions that adjust the top line in the window and invalidate the
|
||||
* framing, are hard.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
/*
|
||||
* Move the cursor to the
|
||||
* beginning of the current line.
|
||||
* Trivial.
|
||||
*/
|
||||
gotobol(f, n)
|
||||
{
|
||||
curwp->w_doto = 0;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor backwards by "n" characters. If "n" is less than zero call
|
||||
* "forwchar" to actually do the move. Otherwise compute the new cursor
|
||||
* location. Error if you try and move out of the buffer. Set the flag if the
|
||||
* line pointer for dot changes.
|
||||
*/
|
||||
backchar(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *lp;
|
||||
|
||||
if (n < 0)
|
||||
return (forwchar(f, -n));
|
||||
while (n--) {
|
||||
if (curwp->w_doto == 0) {
|
||||
if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
|
||||
return (FALSE);
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = llength(lp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
} else
|
||||
curwp->w_doto--;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor to the end of the current line. Trivial. No errors.
|
||||
*/
|
||||
gotoeol(f, n)
|
||||
{
|
||||
curwp->w_doto = llength(curwp->w_dotp);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forwards by "n" characters. If "n" is less than zero call
|
||||
* "backchar" to actually do the move. Otherwise compute the new cursor
|
||||
* location, and move ".". Error if you try and move off the end of the
|
||||
* buffer. Set the flag if the line pointer for dot changes.
|
||||
*/
|
||||
forwchar(f, n)
|
||||
register int n;
|
||||
{
|
||||
if (n < 0)
|
||||
return (backchar(f, -n));
|
||||
while (n--) {
|
||||
if (curwp->w_doto == llength(curwp->w_dotp)) {
|
||||
if (curwp->w_dotp == curbp->b_linep)
|
||||
return (FALSE);
|
||||
curwp->w_dotp = lforw(curwp->w_dotp);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
} else
|
||||
curwp->w_doto++;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
gotoline(f, n) /* move to a particular line.
|
||||
argument (n) must be a positive integer for
|
||||
this to actually do anything */
|
||||
|
||||
{
|
||||
register int status; /* status return */
|
||||
char arg[NSTRING]; /* buffer to hold argument */
|
||||
|
||||
/* get an argument if one doesnt exist */
|
||||
if (f == FALSE) {
|
||||
if ((status = mlreply("Line to GOTO: ", arg, NSTRING)) != TRUE) {
|
||||
mlwrite("(Aborted)");
|
||||
return(status);
|
||||
}
|
||||
n = atoi(arg);
|
||||
}
|
||||
|
||||
if (n < 1) /* if a bogus argument...then leave */
|
||||
return(FALSE);
|
||||
|
||||
/* first, we go to the start of the buffer */
|
||||
curwp->w_dotp = lforw(curbp->b_linep);
|
||||
curwp->w_doto = 0;
|
||||
return(forwline(f, n-1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Goto the beginning of the buffer. Massive adjustment of dot. This is
|
||||
* considered to be hard motion; it really isn't if the original value of dot
|
||||
* is the same as the new value of dot. Normally bound to "M-<".
|
||||
*/
|
||||
gotobob(f, n)
|
||||
{
|
||||
curwp->w_dotp = lforw(curbp->b_linep);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the end of the buffer. Dot is always put at the end of the file
|
||||
* (ZJ). The standard screen code does most of the hard parts of update.
|
||||
* Bound to "M->".
|
||||
*/
|
||||
gotoeob(f, n)
|
||||
{
|
||||
curwp->w_dotp = curbp->b_linep;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFHARD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move forward by full lines. If the number of lines to move is less than
|
||||
* zero, call the backward line function to actually do it. The last command
|
||||
* controls how the goal column is set. Bound to "C-N". No errors are
|
||||
* possible.
|
||||
*/
|
||||
forwline(f, n)
|
||||
{
|
||||
register LINE *dlp;
|
||||
|
||||
if (n < 0)
|
||||
return (backline(f, -n));
|
||||
|
||||
/* if we are on the last line as we start....fail the command */
|
||||
if (curwp->w_dotp == curbp->b_linep)
|
||||
return(FALSE);
|
||||
|
||||
/* if the last command was not note a line move,
|
||||
reset the goal column */
|
||||
if ((lastflag&CFCPCN) == 0)
|
||||
curgoal = getccol(FALSE);
|
||||
|
||||
/* flag this command as a line move */
|
||||
thisflag |= CFCPCN;
|
||||
|
||||
/* and move the point down */
|
||||
dlp = curwp->w_dotp;
|
||||
while (n-- && dlp!=curbp->b_linep)
|
||||
dlp = lforw(dlp);
|
||||
|
||||
/* reseting the current position */
|
||||
curwp->w_dotp = dlp;
|
||||
curwp->w_doto = getgoal(dlp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is like "forwline", but goes backwards. The scheme is exactly
|
||||
* the same. Check for arguments that are less than zero and call your
|
||||
* alternate. Figure out the new line and call "movedot" to perform the
|
||||
* motion. No errors are possible. Bound to "C-P".
|
||||
*/
|
||||
backline(f, n)
|
||||
{
|
||||
register LINE *dlp;
|
||||
|
||||
if (n < 0)
|
||||
return (forwline(f, -n));
|
||||
|
||||
|
||||
/* if we are on the last line as we start....fail the command */
|
||||
if (lback(curwp->w_dotp) == curbp->b_linep)
|
||||
return(FALSE);
|
||||
|
||||
/* if the last command was not note a line move,
|
||||
reset the goal column */
|
||||
if ((lastflag&CFCPCN) == 0)
|
||||
curgoal = getccol(FALSE);
|
||||
|
||||
/* flag this command as a line move */
|
||||
thisflag |= CFCPCN;
|
||||
|
||||
/* and move the point up */
|
||||
dlp = curwp->w_dotp;
|
||||
while (n-- && lback(dlp)!=curbp->b_linep)
|
||||
dlp = lback(dlp);
|
||||
|
||||
/* reseting the current position */
|
||||
curwp->w_dotp = dlp;
|
||||
curwp->w_doto = getgoal(dlp);
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#if WORDPRO
|
||||
gotobop(f, n) /* go back to the beginning of the current paragraph
|
||||
here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
|
||||
combination to delimit the beginning of a paragraph */
|
||||
|
||||
int f, n; /* default Flag & Numeric argument */
|
||||
|
||||
{
|
||||
register int suc; /* success of last backchar */
|
||||
|
||||
if (n < 0) /* the other way...*/
|
||||
return(gotoeop(f, -n));
|
||||
|
||||
while (n-- > 0) { /* for each one asked for */
|
||||
|
||||
/* first scan back until we are in a word */
|
||||
suc = backchar(FALSE, 1);
|
||||
while (!inword() && suc)
|
||||
suc = backchar(FALSE, 1);
|
||||
curwp->w_doto = 0; /* and go to the B-O-Line */
|
||||
|
||||
/* and scan back until we hit a <NL><NL> or <NL><TAB>
|
||||
or a <NL><SPACE> */
|
||||
while (lback(curwp->w_dotp) != curbp->b_linep)
|
||||
if (llength(curwp->w_dotp) != 0 &&
|
||||
#if PKCODE
|
||||
((justflag == TRUE) ||
|
||||
#endif
|
||||
lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
|
||||
lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
|
||||
#if PKCODE
|
||||
)
|
||||
#endif
|
||||
curwp->w_dotp = lback(curwp->w_dotp);
|
||||
else
|
||||
break;
|
||||
|
||||
/* and then forward until we are in a word */
|
||||
suc = forwchar(FALSE, 1);
|
||||
while (suc && !inword())
|
||||
suc = forwchar(FALSE, 1);
|
||||
}
|
||||
curwp->w_flag |= WFMOVE; /* force screen update */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
gotoeop(f, n) /* go forword to the end of the current paragraph
|
||||
here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
|
||||
combination to delimit the beginning of a paragraph */
|
||||
|
||||
int f, n; /* default Flag & Numeric argument */
|
||||
|
||||
{
|
||||
register int suc; /* success of last backchar */
|
||||
|
||||
if (n < 0) /* the other way...*/
|
||||
return(gotobop(f, -n));
|
||||
|
||||
while (n-- > 0) { /* for each one asked for */
|
||||
|
||||
/* first scan forward until we are in a word */
|
||||
suc = forwchar(FALSE, 1);
|
||||
while (!inword() && suc)
|
||||
suc = forwchar(FALSE, 1);
|
||||
curwp->w_doto = 0; /* and go to the B-O-Line */
|
||||
if (suc) /* of next line if not at EOF */
|
||||
curwp->w_dotp = lforw(curwp->w_dotp);
|
||||
|
||||
/* and scan forword until we hit a <NL><NL> or <NL><TAB>
|
||||
or a <NL><SPACE> */
|
||||
while (curwp->w_dotp != curbp->b_linep) {
|
||||
if (llength(curwp->w_dotp) != 0 &&
|
||||
#if PKCODE
|
||||
((justflag == TRUE) ||
|
||||
#endif
|
||||
lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
|
||||
lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
|
||||
#if PKCODE
|
||||
)
|
||||
#endif
|
||||
curwp->w_dotp = lforw(curwp->w_dotp);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* and then backward until we are in a word */
|
||||
suc = backchar(FALSE, 1);
|
||||
while (suc && !inword()) {
|
||||
suc = backchar(FALSE, 1);
|
||||
}
|
||||
curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */
|
||||
}
|
||||
curwp->w_flag |= WFMOVE; /* force screen update */
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This routine, given a pointer to a LINE, and the current cursor goal
|
||||
* column, return the best choice for the offset. The offset is returned.
|
||||
* Used by "C-N" and "C-P".
|
||||
*/
|
||||
getgoal(dlp)
|
||||
register LINE *dlp;
|
||||
{
|
||||
register int c;
|
||||
register int col;
|
||||
register int newcol;
|
||||
register int dbo;
|
||||
|
||||
col = 0;
|
||||
dbo = 0;
|
||||
while (dbo != llength(dlp)) {
|
||||
c = lgetc(dlp, dbo);
|
||||
newcol = col;
|
||||
if (c == '\t')
|
||||
newcol |= tabmask;
|
||||
else if (c<0x20 || c==0x7F)
|
||||
++newcol;
|
||||
++newcol;
|
||||
if (newcol > curgoal)
|
||||
break;
|
||||
col = newcol;
|
||||
++dbo;
|
||||
}
|
||||
return (dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scroll forward by a specified number of lines, or by a full page if no
|
||||
* argument. Bound to "C-V". The "2" in the arithmetic on the window size is
|
||||
* the overlap; this value is the default overlap value in ITS EMACS. Because
|
||||
* this zaps the top line in the display window, we have to do a hard update.
|
||||
*/
|
||||
forwpage(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *lp;
|
||||
|
||||
if (f == FALSE) {
|
||||
#if SCROLLCODE
|
||||
if (term.t_scroll != NULL)
|
||||
if (overlap == 0)
|
||||
n = curwp->w_ntrows / 3 * 2;
|
||||
else
|
||||
n = curwp->w_ntrows - overlap;
|
||||
else
|
||||
#endif
|
||||
n = curwp->w_ntrows - 2; /* Default scroll. */
|
||||
if (n <= 0) /* Forget the overlap */
|
||||
n = 1; /* if tiny window. */
|
||||
} else if (n < 0)
|
||||
return (backpage(f, -n));
|
||||
#if CVMVAS
|
||||
else /* Convert from pages */
|
||||
n *= curwp->w_ntrows; /* to lines. */
|
||||
#endif
|
||||
lp = curwp->w_linep;
|
||||
while (n-- && lp!=curbp->b_linep)
|
||||
lp = lforw(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = 0;
|
||||
#if SCROLLCODE
|
||||
curwp->w_flag |= WFHARD|WFKILLS;
|
||||
#else
|
||||
curwp->w_flag |= WFHARD;
|
||||
#endif
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command is like "forwpage", but it goes backwards. The "2", like
|
||||
* above, is the overlap between the two windows. The value is from the ITS
|
||||
* EMACS manual. Bound to "M-V". We do a hard update for exactly the same
|
||||
* reason.
|
||||
*/
|
||||
backpage(f, n)
|
||||
register int n;
|
||||
{
|
||||
register LINE *lp;
|
||||
|
||||
if (f == FALSE) {
|
||||
#if SCROLLCODE
|
||||
if (term.t_scroll != NULL)
|
||||
if (overlap == 0)
|
||||
n = curwp->w_ntrows / 3 * 2;
|
||||
else
|
||||
n = curwp->w_ntrows - overlap;
|
||||
else
|
||||
#endif
|
||||
n = curwp->w_ntrows - 2; /* Default scroll. */
|
||||
if (n <= 0) /* Don't blow up if the */
|
||||
n = 1; /* window is tiny. */
|
||||
} else if (n < 0)
|
||||
return (forwpage(f, -n));
|
||||
#if CVMVAS
|
||||
else /* Convert from pages */
|
||||
n *= curwp->w_ntrows; /* to lines. */
|
||||
#endif
|
||||
lp = curwp->w_linep;
|
||||
while (n-- && lback(lp)!=curbp->b_linep)
|
||||
lp = lback(lp);
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = 0;
|
||||
#if SCROLLCODE
|
||||
curwp->w_flag |= WFHARD|WFINS;
|
||||
#else
|
||||
curwp->w_flag |= WFHARD;
|
||||
#endif
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the mark in the current window to the value of "." in the window. No
|
||||
* errors are possible. Bound to "M-.".
|
||||
*/
|
||||
setmark(f, n)
|
||||
{
|
||||
curwp->w_markp = curwp->w_dotp;
|
||||
curwp->w_marko = curwp->w_doto;
|
||||
mlwrite("(Mark set)");
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap the values of "." and "mark" in the current window. This is pretty
|
||||
* easy, bacause all of the hard work gets done by the standard routine
|
||||
* that moves the mark about. The only possible error is "no mark". Bound to
|
||||
* "C-X C-X".
|
||||
*/
|
||||
swapmark(f, n)
|
||||
{
|
||||
register LINE *odotp;
|
||||
register int odoto;
|
||||
|
||||
if (curwp->w_markp == NULL) {
|
||||
mlwrite("No mark in this window");
|
||||
return (FALSE);
|
||||
}
|
||||
odotp = curwp->w_dotp;
|
||||
odoto = curwp->w_doto;
|
||||
curwp->w_dotp = curwp->w_markp;
|
||||
curwp->w_doto = curwp->w_marko;
|
||||
curwp->w_markp = odotp;
|
||||
curwp->w_marko = odoto;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
return (TRUE);
|
||||
}
|
708
bind.c
Normal file
708
bind.c
Normal file
@ -0,0 +1,708 @@
|
||||
/* BIND.C
|
||||
*
|
||||
* This file is for functions having to do with key bindings,
|
||||
* descriptions, help commands and startup file.
|
||||
*
|
||||
* written 11-feb-86 by Daniel Lawrence
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
#include "epath.h"
|
||||
|
||||
extern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */
|
||||
|
||||
help(f, n) /* give me some help!!!!
|
||||
bring up a fake buffer and read the help file
|
||||
into it with view mode */
|
||||
{
|
||||
register WINDOW *wp; /* scaning pointer to windows */
|
||||
register BUFFER *bp; /* buffer pointer to help */
|
||||
char *fname; /* ptr to file returned by flook() */
|
||||
|
||||
/* first check if we are already here */
|
||||
bp = bfind("emacs.hlp", FALSE, BFINVS);
|
||||
|
||||
if (bp == NULL) {
|
||||
fname = flook(pathname[1], FALSE);
|
||||
if (fname == NULL) {
|
||||
mlwrite("(Help file is not online)");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* split the current window to make room for the help stuff */
|
||||
if (splitwind(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
|
||||
if (bp == NULL) {
|
||||
/* and read the stuff in */
|
||||
if (getfile(fname, FALSE) == FALSE)
|
||||
return(FALSE);
|
||||
} else
|
||||
swbuffer(bp);
|
||||
|
||||
/* make this window in VIEW mode, update all mode lines */
|
||||
curwp->w_bufp->b_mode |= MDVIEW;
|
||||
curwp->w_bufp->b_flag |= BFINVS;
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
deskey(f, n) /* describe the command for a certain key */
|
||||
|
||||
{
|
||||
register int c; /* key to describe */
|
||||
register char *ptr; /* string pointer to scan output strings */
|
||||
char outseq[NSTRING]; /* output buffer for command sequence */
|
||||
int (*getbind())();
|
||||
|
||||
/* prompt the user to type us a key to describe */
|
||||
mlwrite(": describe-key ");
|
||||
|
||||
/* get the command sequence to describe
|
||||
change it to something we can print as well */
|
||||
cmdstr(c = getckey(FALSE), &outseq[0]);
|
||||
|
||||
/* and dump it out */
|
||||
ostring(outseq);
|
||||
ostring(" ");
|
||||
|
||||
/* find the right ->function */
|
||||
if ((ptr = getfname(getbind(c))) == NULL)
|
||||
ptr = "Not Bound";
|
||||
|
||||
/* output the command sequence */
|
||||
ostring(ptr);
|
||||
}
|
||||
|
||||
/* bindtokey: add a new key to the key binding table */
|
||||
|
||||
bindtokey(f, n)
|
||||
|
||||
int f, n; /* command arguments [IGNORED] */
|
||||
|
||||
{
|
||||
register unsigned int c;/* command key to bind */
|
||||
register int (*kfunc)();/* ptr to the requested function to bind to */
|
||||
register KEYTAB *ktp; /* pointer into the command table */
|
||||
register int found; /* matched command flag */
|
||||
char outseq[80]; /* output buffer for keystroke sequence */
|
||||
int (*getname())();
|
||||
|
||||
/* prompt the user to type in a key to bind */
|
||||
mlwrite(": bind-to-key ");
|
||||
|
||||
/* get the function name to bind it to */
|
||||
kfunc = getname();
|
||||
if (kfunc == NULL) {
|
||||
mlwrite("(No such function)");
|
||||
return(FALSE);
|
||||
}
|
||||
ostring(" ");
|
||||
|
||||
/* get the command sequence to bind */
|
||||
c = getckey((kfunc == meta) || (kfunc == cex) ||
|
||||
(kfunc == unarg) || (kfunc == ctrlg));
|
||||
|
||||
/* change it to something we can print as well */
|
||||
cmdstr(c, &outseq[0]);
|
||||
|
||||
/* and dump it out */
|
||||
ostring(outseq);
|
||||
|
||||
/* if the function is a prefix key */
|
||||
if (kfunc == meta || kfunc == cex ||
|
||||
kfunc == unarg || kfunc == ctrlg) {
|
||||
|
||||
/* search for an existing binding for the prefix key */
|
||||
ktp = &keytab[0];
|
||||
found = FALSE;
|
||||
while (ktp->k_fp != NULL) {
|
||||
if (ktp->k_fp == kfunc)
|
||||
unbindchar(ktp->k_code);
|
||||
++ktp;
|
||||
}
|
||||
|
||||
/* reset the appropriate global prefix variable */
|
||||
if (kfunc == meta)
|
||||
metac = c;
|
||||
if (kfunc == cex)
|
||||
ctlxc = c;
|
||||
if (kfunc == unarg)
|
||||
reptc = c;
|
||||
if (kfunc == ctrlg)
|
||||
abortc = c;
|
||||
}
|
||||
|
||||
/* search the table to see if it exists */
|
||||
ktp = &keytab[0];
|
||||
found = FALSE;
|
||||
while (ktp->k_fp != NULL) {
|
||||
if (ktp->k_code == c) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
++ktp;
|
||||
}
|
||||
|
||||
if (found) { /* it exists, just change it then */
|
||||
ktp->k_fp = kfunc;
|
||||
} else { /* otherwise we need to add it to the end */
|
||||
/* if we run out of binding room, bitch */
|
||||
if (ktp >= &keytab[NBINDS]) {
|
||||
mlwrite("Binding table FULL!");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
ktp->k_code = c; /* add keycode */
|
||||
ktp->k_fp = kfunc; /* and the function pointer */
|
||||
++ktp; /* and make sure the next is null */
|
||||
ktp->k_code = 0;
|
||||
ktp->k_fp = NULL;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* unbindkey: delete a key from the key binding table */
|
||||
|
||||
unbindkey(f, n)
|
||||
|
||||
int f, n; /* command arguments [IGNORED] */
|
||||
|
||||
{
|
||||
register int c; /* command key to unbind */
|
||||
char outseq[80]; /* output buffer for keystroke sequence */
|
||||
|
||||
/* prompt the user to type in a key to unbind */
|
||||
mlwrite(": unbind-key ");
|
||||
|
||||
/* get the command sequence to unbind */
|
||||
c = getckey(FALSE); /* get a command sequence */
|
||||
|
||||
/* change it to something we can print as well */
|
||||
cmdstr(c, &outseq[0]);
|
||||
|
||||
/* and dump it out */
|
||||
ostring(outseq);
|
||||
|
||||
/* if it isn't bound, bitch */
|
||||
if (unbindchar(c) == FALSE) {
|
||||
mlwrite("(Key not bound)");
|
||||
return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
unbindchar(c)
|
||||
|
||||
int c; /* command key to unbind */
|
||||
|
||||
{
|
||||
register KEYTAB *ktp; /* pointer into the command table */
|
||||
register KEYTAB *sktp; /* saved pointer into the command table */
|
||||
register int found; /* matched command flag */
|
||||
|
||||
/* search the table to see if the key exists */
|
||||
ktp = &keytab[0];
|
||||
found = FALSE;
|
||||
while (ktp->k_fp != NULL) {
|
||||
if (ktp->k_code == c) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
++ktp;
|
||||
}
|
||||
|
||||
/* if it isn't bound, bitch */
|
||||
if (!found)
|
||||
return(FALSE);
|
||||
|
||||
/* save the pointer and scan to the end of the table */
|
||||
sktp = ktp;
|
||||
while (ktp->k_fp != NULL)
|
||||
++ktp;
|
||||
--ktp; /* backup to the last legit entry */
|
||||
|
||||
/* copy the last entry to the current one */
|
||||
sktp->k_code = ktp->k_code;
|
||||
sktp->k_fp = ktp->k_fp;
|
||||
|
||||
/* null out the last one */
|
||||
ktp->k_code = 0;
|
||||
ktp->k_fp = NULL;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
desbind(f, n) /* describe bindings
|
||||
bring up a fake buffer and list the key bindings
|
||||
into it with view mode */
|
||||
|
||||
#if APROP
|
||||
{
|
||||
buildlist(TRUE, "");
|
||||
}
|
||||
|
||||
apro(f, n) /* Apropos (List functions that match a substring) */
|
||||
|
||||
{
|
||||
char mstring[NSTRING]; /* string to match cmd names to */
|
||||
int status; /* status return */
|
||||
|
||||
status = mlreply("Apropos string: ", mstring, NSTRING - 1);
|
||||
if (status != TRUE)
|
||||
return(status);
|
||||
|
||||
return(buildlist(FALSE, mstring));
|
||||
}
|
||||
|
||||
buildlist(type, mstring) /* build a binding list (limited or full) */
|
||||
|
||||
int type; /* true = full list, false = partial list */
|
||||
char *mstring; /* match string if a partial list */
|
||||
|
||||
#endif
|
||||
{
|
||||
register WINDOW *wp; /* scanning pointer to windows */
|
||||
register KEYTAB *ktp; /* pointer into the command table */
|
||||
register NBIND *nptr; /* pointer into the name binding table */
|
||||
register BUFFER *bp; /* buffer to put binding list into */
|
||||
char *strp; /* pointer int string to send */
|
||||
int cpos; /* current position to use in outseq */
|
||||
char outseq[80]; /* output buffer for keystroke sequence */
|
||||
|
||||
/* split the current window to make room for the binding list */
|
||||
if (splitwind(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
|
||||
/* and get a buffer for it */
|
||||
bp = bfind("*Binding list*", TRUE, 0);
|
||||
if (bp == NULL || bclear(bp) == FALSE) {
|
||||
mlwrite("Can not display binding list");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* let us know this is in progress */
|
||||
mlwrite("(Building binding list)");
|
||||
|
||||
/* disconect the current buffer */
|
||||
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;
|
||||
}
|
||||
|
||||
/* connect the current window to this buffer */
|
||||
curbp = bp; /* make this buffer current in current window */
|
||||
bp->b_mode = 0; /* no modes active in binding list */
|
||||
bp->b_nwnd++; /* mark us as more in use */
|
||||
wp = curwp;
|
||||
wp->w_bufp = bp;
|
||||
wp->w_linep = bp->b_linep;
|
||||
wp->w_flag = WFHARD|WFFORCE;
|
||||
wp->w_dotp = bp->b_dotp;
|
||||
wp->w_doto = bp->b_doto;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
|
||||
/* build the contents of this window, inserting it line by line */
|
||||
nptr = &names[0];
|
||||
while (nptr->n_func != NULL) {
|
||||
|
||||
/* add in the command name */
|
||||
strcpy(outseq, nptr->n_name);
|
||||
cpos = strlen(outseq);
|
||||
|
||||
#if APROP
|
||||
/* if we are executing an apropos command..... */
|
||||
if (type == FALSE &&
|
||||
/* and current string doesn't include the search string */
|
||||
strinc(outseq, mstring) == FALSE)
|
||||
goto fail;
|
||||
#endif
|
||||
/* search down any keys bound to this */
|
||||
ktp = &keytab[0];
|
||||
while (ktp->k_fp != NULL) {
|
||||
if (ktp->k_fp == nptr->n_func) {
|
||||
/* padd out some spaces */
|
||||
while (cpos < 28)
|
||||
outseq[cpos++] = ' ';
|
||||
|
||||
/* add in the command sequence */
|
||||
cmdstr(ktp->k_code, &outseq[cpos]);
|
||||
strcat(outseq, "\n");
|
||||
|
||||
/* and add it as a line into the buffer */
|
||||
if (linstr(outseq) != TRUE)
|
||||
return(FALSE);
|
||||
|
||||
cpos = 0; /* and clear the line */
|
||||
}
|
||||
++ktp;
|
||||
}
|
||||
|
||||
/* if no key was bound, we need to dump it anyway */
|
||||
if (cpos > 0) {
|
||||
outseq[cpos++] = '\n';
|
||||
outseq[cpos] = 0;
|
||||
if (linstr(outseq) != TRUE)
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
fail: /* and on to the next name */
|
||||
++nptr;
|
||||
}
|
||||
|
||||
curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
|
||||
curbp->b_flag &= ~BFCHG; /* don't flag this as a change */
|
||||
wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
|
||||
wp->w_doto = 0;
|
||||
wp = wheadp; /* and update ALL mode lines */
|
||||
while (wp != NULL) {
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
mlwrite(""); /* clear the mode line */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
#if APROP
|
||||
strinc(source, sub) /* does source include sub? */
|
||||
|
||||
char *source; /* string to search in */
|
||||
char *sub; /* substring to look for */
|
||||
|
||||
{
|
||||
char *sp; /* ptr into source */
|
||||
char *nxtsp; /* next ptr into source */
|
||||
char *tp; /* ptr into substring */
|
||||
|
||||
/* for each character in the source string */
|
||||
sp = source;
|
||||
while (*sp) {
|
||||
tp = sub;
|
||||
nxtsp = sp;
|
||||
|
||||
/* is the substring here? */
|
||||
while (*tp) {
|
||||
if (*nxtsp++ != *tp)
|
||||
break;
|
||||
else
|
||||
tp++;
|
||||
}
|
||||
|
||||
/* yes, return a success */
|
||||
if (*tp == 0)
|
||||
return(TRUE);
|
||||
|
||||
/* no, onward */
|
||||
sp++;
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get a command key sequence from the keyboard */
|
||||
|
||||
unsigned int getckey(mflag)
|
||||
|
||||
int mflag; /* going for a meta sequence? */
|
||||
|
||||
{
|
||||
register unsigned int c; /* character fetched */
|
||||
char tok[NSTRING]; /* command incoming */
|
||||
|
||||
/* check to see if we are executing a command line */
|
||||
if (clexec) {
|
||||
macarg(tok); /* get the next token */
|
||||
return(stock(tok));
|
||||
}
|
||||
|
||||
/* or the normal way */
|
||||
if (mflag)
|
||||
c = get1key();
|
||||
else
|
||||
c = getcmd();
|
||||
return(c);
|
||||
}
|
||||
|
||||
/* execute the startup file */
|
||||
|
||||
startup(sfname)
|
||||
|
||||
char *sfname; /* name of startup file (null if default) */
|
||||
|
||||
{
|
||||
char *fname; /* resulting file name to execute */
|
||||
|
||||
/* look up the startup file */
|
||||
if (*sfname != 0)
|
||||
fname = flook(sfname, TRUE);
|
||||
else
|
||||
fname = flook(pathname[0], TRUE);
|
||||
|
||||
/* if it isn't around, don't sweat it */
|
||||
if (fname == NULL)
|
||||
return(TRUE);
|
||||
|
||||
/* otherwise, execute the sucker */
|
||||
return(dofile(fname));
|
||||
}
|
||||
|
||||
/* Look up the existance of a file along the normal or PATH
|
||||
environment variable. Look first in the HOME directory if
|
||||
asked and possible
|
||||
*/
|
||||
|
||||
char *flook(fname, hflag)
|
||||
|
||||
char *fname; /* base file name to search for */
|
||||
int hflag; /* Look in the HOME environment variable first? */
|
||||
|
||||
{
|
||||
register char *home; /* path to home directory */
|
||||
register char *path; /* environmental PATH variable */
|
||||
register char *sp; /* pointer into path spec */
|
||||
register int i; /* index */
|
||||
static char fspec[NSTRING]; /* full path spec to search */
|
||||
char *getenv();
|
||||
|
||||
#if ENVFUNC
|
||||
|
||||
if (hflag) {
|
||||
home = getenv("HOME");
|
||||
if (home != NULL) {
|
||||
/* build home dir file spec */
|
||||
strcpy(fspec, home);
|
||||
strcat(fspec, "/");
|
||||
strcat(fspec, fname);
|
||||
|
||||
/* and try it out */
|
||||
if (ffropen(fspec) == FIOSUC) {
|
||||
ffclose();
|
||||
return(fspec);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* always try the current directory first */
|
||||
if (ffropen(fname) == FIOSUC) {
|
||||
ffclose();
|
||||
return(fname);
|
||||
}
|
||||
|
||||
#if ENVFUNC
|
||||
/* get the PATH variable */
|
||||
path = getenv("PATH");
|
||||
if (path != NULL)
|
||||
while (*path) {
|
||||
|
||||
/* build next possible file spec */
|
||||
sp = fspec;
|
||||
while (*path && (*path != PATHCHR))
|
||||
*sp++ = *path++;
|
||||
|
||||
/* add a terminating dir separator if we need it */
|
||||
if (sp != fspec)
|
||||
*sp++ = '/';
|
||||
*sp = 0;
|
||||
strcat(fspec, fname);
|
||||
|
||||
/* and try it out */
|
||||
if (ffropen(fspec) == FIOSUC) {
|
||||
ffclose();
|
||||
return(fspec);
|
||||
}
|
||||
|
||||
if (*path == PATHCHR)
|
||||
++path;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* look it up via the old table method */
|
||||
for (i=2; i < NPNAMES; i++) {
|
||||
strcpy(fspec, pathname[i]);
|
||||
strcat(fspec, fname);
|
||||
|
||||
/* and try it out */
|
||||
if (ffropen(fspec) == FIOSUC) {
|
||||
ffclose();
|
||||
return(fspec);
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL); /* no such luck */
|
||||
}
|
||||
|
||||
cmdstr(c, seq) /* change a key command to a string we can print out */
|
||||
|
||||
int c; /* sequence to translate */
|
||||
char *seq; /* destination string for sequence */
|
||||
|
||||
{
|
||||
char *ptr; /* pointer into current position in sequence */
|
||||
|
||||
ptr = seq;
|
||||
|
||||
/* apply meta sequence if needed */
|
||||
if (c & META) {
|
||||
*ptr++ = 'M';
|
||||
*ptr++ = '-';
|
||||
}
|
||||
|
||||
/* apply ^X sequence if needed */
|
||||
if (c & CTLX) {
|
||||
*ptr++ = '^';
|
||||
*ptr++ = 'X';
|
||||
}
|
||||
|
||||
/* apply SPEC sequence if needed */
|
||||
if (c & SPEC) {
|
||||
*ptr++ = 'F';
|
||||
*ptr++ = 'N';
|
||||
}
|
||||
|
||||
/* apply control sequence if needed */
|
||||
if (c & CONTROL) {
|
||||
*ptr++ = '^';
|
||||
}
|
||||
|
||||
/* and output the final sequence */
|
||||
|
||||
*ptr++ = c & 255; /* strip the prefixes */
|
||||
|
||||
*ptr = 0; /* terminate the string */
|
||||
}
|
||||
|
||||
/* This function looks a key binding up in the binding table */
|
||||
|
||||
int (*getbind(c))()
|
||||
|
||||
int c; /* key to find what is bound to it */
|
||||
|
||||
{
|
||||
register KEYTAB *ktp;
|
||||
|
||||
ktp = &keytab[0]; /* Look in key table. */
|
||||
while (ktp->k_fp != NULL) {
|
||||
if (ktp->k_code == c)
|
||||
return(ktp->k_fp);
|
||||
++ktp;
|
||||
}
|
||||
|
||||
/* no such binding */
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* getfname: This function takes a ptr to function and gets the name
|
||||
associated with it
|
||||
*/
|
||||
|
||||
char *getfname(func)
|
||||
|
||||
int (*func)(); /* ptr to the requested function to bind to */
|
||||
|
||||
{
|
||||
register NBIND *nptr; /* pointer into the name binding table */
|
||||
|
||||
/* skim through the table, looking for a match */
|
||||
nptr = &names[0];
|
||||
while (nptr->n_func != NULL) {
|
||||
if (nptr->n_func == func)
|
||||
return(nptr->n_name);
|
||||
++nptr;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int (*fncmatch(fname))() /* match fname to a function in the names table
|
||||
and return any match or NULL if none */
|
||||
|
||||
char *fname; /* name to attempt to match */
|
||||
|
||||
{
|
||||
register NBIND *ffp; /* pointer to entry in name binding table */
|
||||
|
||||
/* scan through the table, returning any match */
|
||||
ffp = &names[0];
|
||||
while (ffp->n_func != NULL) {
|
||||
if (strcmp(fname, ffp->n_name) == 0)
|
||||
return(ffp->n_func);
|
||||
++ffp;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* stock: String key name TO Command Key */
|
||||
|
||||
unsigned int stock(keyname)
|
||||
|
||||
char *keyname; /* name of key to translate to Command key form */
|
||||
|
||||
{
|
||||
register unsigned int c; /* key sequence to return */
|
||||
|
||||
/* parse it up */
|
||||
c = 0;
|
||||
|
||||
/* first, the META prefix */
|
||||
if (*keyname == 'M' && *(keyname+1) == '-') {
|
||||
c = META;
|
||||
keyname += 2;
|
||||
}
|
||||
|
||||
/* next the function prefix */
|
||||
if (*keyname == 'F' && *(keyname+1) == 'N') {
|
||||
c |= SPEC;
|
||||
keyname += 2;
|
||||
}
|
||||
|
||||
/* control-x as well... (but not with FN) */
|
||||
if (*keyname == '^' && *(keyname+1) == 'X'&& !(c & SPEC)) {
|
||||
c |= CTLX;
|
||||
keyname += 2;
|
||||
}
|
||||
|
||||
/* a control char? */
|
||||
if (*keyname == '^' && *(keyname+1) != 0) {
|
||||
c |= CONTROL;
|
||||
++keyname;
|
||||
}
|
||||
if (*keyname < 32) {
|
||||
c |= CONTROL;
|
||||
*keyname += 'A';
|
||||
}
|
||||
|
||||
|
||||
/* make sure we are not lower case (not with function keys)*/
|
||||
if (*keyname >= 'a' && *keyname <= 'z' && !(c & SPEC))
|
||||
*keyname -= 32;
|
||||
|
||||
/* the final sequence... */
|
||||
c |= *keyname;
|
||||
return(c);
|
||||
}
|
||||
|
||||
char *transbind(skey) /* string key name to binding name.... */
|
||||
|
||||
char *skey; /* name of keey to get binding for */
|
||||
|
||||
{
|
||||
char *bindname;
|
||||
unsigned int stock();
|
||||
int (*getbind())();
|
||||
|
||||
bindname = getfname(getbind(stock(skey)));
|
||||
if (bindname == NULL)
|
||||
bindname = "ERROR";
|
||||
|
||||
return(bindname);
|
||||
}
|
544
buffer.c
Normal file
544
buffer.c
Normal file
@ -0,0 +1,544 @@
|
||||
/* BUFFER.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
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
/*
|
||||
* 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 int s;
|
||||
char bufn[NBUFN];
|
||||
|
||||
if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
|
||||
return (s);
|
||||
if ((bp=bfind(bufn, TRUE, 0)) == NULL)
|
||||
return (FALSE);
|
||||
return(swbuffer(bp));
|
||||
}
|
||||
|
||||
nextbuffer(f, n) /* switch to the next buffer in the buffer list */
|
||||
|
||||
int f, n; /* default flag, numeric argument */
|
||||
{
|
||||
register BUFFER *bp; /* eligable buffer to switch to*/
|
||||
register BUFFER *bbp; /* eligable buffer to switch to*/
|
||||
|
||||
/* make sure the arg is legit */
|
||||
if (f == FALSE)
|
||||
n = 1;
|
||||
if (n < 1)
|
||||
return(FALSE);
|
||||
|
||||
bbp = curbp;
|
||||
while (n-- > 0) {
|
||||
/* advance to the next buffer */
|
||||
bp = bbp->b_bufp;
|
||||
|
||||
/* cycle through the buffers to find an eligable one */
|
||||
while (bp == NULL || bp->b_flag & BFINVS) {
|
||||
if (bp == NULL)
|
||||
bp = bheadp;
|
||||
else
|
||||
bp = bp->b_bufp;
|
||||
|
||||
/* don't get caught in an infinite loop! */
|
||||
if (bp == bbp)
|
||||
return(FALSE);
|
||||
|
||||
}
|
||||
|
||||
bbp = bp;
|
||||
}
|
||||
|
||||
return(swbuffer(bp));
|
||||
}
|
||||
|
||||
swbuffer(bp) /* make buffer BP current */
|
||||
|
||||
BUFFER *bp;
|
||||
|
||||
{
|
||||
register WINDOW *wp;
|
||||
|
||||
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. */
|
||||
if (curbp->b_active != TRUE) { /* buffer not active yet*/
|
||||
/* read it in and activate it */
|
||||
readin(curbp->b_fname, TRUE);
|
||||
curbp->b_dotp = lforw(curbp->b_linep);
|
||||
curbp->b_doto = 0;
|
||||
curbp->b_active = TRUE;
|
||||
curbp->b_mode |= gmode; /* P.K. */
|
||||
}
|
||||
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;
|
||||
cknewwindow();
|
||||
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;
|
||||
}
|
||||
cknewwindow();
|
||||
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 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_flag & BFINVS) /* Deal with special buffers */
|
||||
return (TRUE); /* by doing nothing. */
|
||||
return(zotbuf(bp));
|
||||
}
|
||||
|
||||
zotbuf(bp) /* kill the buffer pointed to by bp */
|
||||
|
||||
register BUFFER *bp;
|
||||
|
||||
{
|
||||
register BUFFER *bp1;
|
||||
register BUFFER *bp2;
|
||||
register 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((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);
|
||||
}
|
||||
|
||||
namebuffer(f,n) /* Rename the current buffer */
|
||||
|
||||
int f, n; /* default Flag & Numeric arg */
|
||||
|
||||
{
|
||||
register 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 != NULL) {
|
||||
if (bp != curbp) {
|
||||
/* if the names the same */
|
||||
if (strcmp(bufn, bp->b_bname) == 0)
|
||||
goto ask; /* try again */
|
||||
}
|
||||
bp = bp->b_bufp; /* onward */
|
||||
}
|
||||
|
||||
strcpy(curbp->b_bname, bufn); /* 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".
|
||||
A numeric argument forces it to list invisable buffers as
|
||||
well.
|
||||
*/
|
||||
|
||||
listbuffers(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register BUFFER *bp;
|
||||
register int s;
|
||||
|
||||
if ((s=makelist(f)) != 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). Iflag
|
||||
* indecates weather to list hidden buffers.
|
||||
*/
|
||||
#define MAXLINE MAXCOL
|
||||
makelist(iflag)
|
||||
|
||||
int iflag; /* list hidden buffer flag */
|
||||
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register int c;
|
||||
register BUFFER *bp;
|
||||
register LINE *lp;
|
||||
register int s;
|
||||
register int i;
|
||||
long nbytes; /* # of bytes in current buffer */
|
||||
char b[7+1];
|
||||
char line[MAXLINE];
|
||||
|
||||
blistp->b_flag &= ~BFCHG; /* Don't complain! */
|
||||
if ((s=bclear(blistp)) != TRUE) /* Blow old text away */
|
||||
return (s);
|
||||
strcpy(blistp->b_fname, "");
|
||||
if (addline("ACT MODES Size Buffer File") == FALSE
|
||||
|| addline("--- ----- ---- ------ ----") == FALSE)
|
||||
return (FALSE);
|
||||
bp = bheadp; /* For all buffers */
|
||||
|
||||
/* build line to report global mode settings */
|
||||
cp1 = &line[0];
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' ';
|
||||
*cp1++ = ' ';
|
||||
|
||||
/* output the mode codes */
|
||||
for (i = 0; i < NUMMODES; i++)
|
||||
if (gmode & (1 << i))
|
||||
*cp1++ = modecode[i];
|
||||
else
|
||||
*cp1++ = '.';
|
||||
strcpy(cp1, " Global Modes");
|
||||
if (addline(line) == FALSE)
|
||||
return(FALSE);
|
||||
|
||||
/* output the list of buffers */
|
||||
while (bp != NULL) {
|
||||
/* skip invisable buffers if iflag is false */
|
||||
if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) {
|
||||
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++ = ' ';
|
||||
|
||||
/* report if the file is truncated */
|
||||
if ((bp->b_flag&BFTRUNC) != 0)
|
||||
*cp1++ = '#';
|
||||
else
|
||||
*cp1++ = ' ';
|
||||
|
||||
*cp1++ = ' '; /* space */
|
||||
|
||||
/* output the mode codes */
|
||||
for (i = 0; i < NUMMODES; i++) {
|
||||
if (bp->b_mode & (1 << i))
|
||||
*cp1++ = modecode[i];
|
||||
else
|
||||
*cp1++ = '.';
|
||||
}
|
||||
*cp1++ = ' '; /* Gap. */
|
||||
nbytes = 0L; /* Count bytes in buf. */
|
||||
lp = lforw(bp->b_linep);
|
||||
while (lp != bp->b_linep) {
|
||||
nbytes += (long)llength(lp)+1L;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
ltoa(b, 7, 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[3+1+5+1+6+4+NBUFN])
|
||||
*cp1++ = ' ';
|
||||
while ((c = *cp2++) != 0) {
|
||||
if (cp1 < &line[MAXLINE-1])
|
||||
*cp1++ = c;
|
||||
}
|
||||
}
|
||||
*cp1 = 0; /* Add to the buffer. */
|
||||
if (addline(line) == FALSE)
|
||||
return (FALSE);
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
return (TRUE); /* All done */
|
||||
}
|
||||
|
||||
ltoa(buf, width, num)
|
||||
|
||||
char buf[];
|
||||
int width;
|
||||
long num;
|
||||
|
||||
{
|
||||
buf[width] = 0; /* End of string. */
|
||||
while (num >= 10) { /* Conditional digits. */
|
||||
buf[--width] = (int)(num%10L) + '0';
|
||||
num /= 10L;
|
||||
}
|
||||
buf[--width] = (int)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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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&BFINVS)==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 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 BUFFER *sb; /* buffer to insert after */
|
||||
register LINE *lp;
|
||||
char *malloc();
|
||||
|
||||
bp = bheadp;
|
||||
while (bp != NULL) {
|
||||
if (strcmp(bname, bp->b_bname) == 0)
|
||||
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);
|
||||
}
|
||||
/* find the place in the list to insert this buffer */
|
||||
if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
|
||||
/* insert at the beginning */
|
||||
bp->b_bufp = bheadp;
|
||||
bheadp = bp;
|
||||
} else {
|
||||
sb = bheadp;
|
||||
while (sb->b_bufp != NULL) {
|
||||
if (strcmp(sb->b_bufp->b_bname, bname) > 0)
|
||||
break;
|
||||
sb = sb->b_bufp;
|
||||
}
|
||||
|
||||
/* and insert it */
|
||||
bp->b_bufp = sb->b_bufp;
|
||||
sb->b_bufp = bp;
|
||||
}
|
||||
|
||||
/* and set up the other buffer fields */
|
||||
bp->b_active = TRUE;
|
||||
bp->b_dotp = lp;
|
||||
bp->b_doto = 0;
|
||||
bp->b_markp = NULL;
|
||||
bp->b_marko = 0;
|
||||
bp->b_flag = bflag;
|
||||
bp->b_mode = gmode;
|
||||
bp->b_nwnd = 0;
|
||||
bp->b_linep = lp;
|
||||
strcpy(bp->b_fname, "");
|
||||
strcpy(bp->b_bname, bname);
|
||||
#if CRYPT
|
||||
bp->b_key[0] = 0;
|
||||
#endif
|
||||
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&BFINVS) == 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 = 0;
|
||||
bp->b_markp = NULL; /* Invalidate "mark" */
|
||||
bp->b_marko = 0;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
unmark(f, n) /* unmark the current buffers change flag */
|
||||
|
||||
int f, n; /* unused command arguments */
|
||||
|
||||
{
|
||||
curbp->b_flag &= ~BFCHG;
|
||||
curwp->w_flag |= WFMODE;
|
||||
return(TRUE);
|
||||
}
|
221
crypt.c
Normal file
221
crypt.c
Normal file
@ -0,0 +1,221 @@
|
||||
/* CRYPT.C
|
||||
*
|
||||
* Encryption routines
|
||||
*
|
||||
* written by Dana Hoggatt and Daniel Lawrence
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if CRYPT
|
||||
|
||||
static int mod95();
|
||||
|
||||
setkey(f, n) /* reset encryption key of current buffer */
|
||||
|
||||
int f; /* default flag */
|
||||
int n; /* numeric argument */
|
||||
|
||||
{
|
||||
register int status; /* return status */
|
||||
int odisinp; /* original vlaue of disinp */
|
||||
char key[NPAT]; /* new encryption string */
|
||||
|
||||
/* turn command input echo off */
|
||||
odisinp = disinp;
|
||||
disinp = FALSE;
|
||||
|
||||
/* get the string to use as an encrytion string */
|
||||
status = mlreply("Encryption String: ", key, NPAT - 1);
|
||||
disinp = odisinp;
|
||||
if (status != TRUE)
|
||||
return(status);
|
||||
|
||||
/* and encrypt it */
|
||||
crypt((char *)NULL, 0);
|
||||
crypt(key, strlen(key));
|
||||
|
||||
/* and save it off */
|
||||
strcpy(curbp->b_key, key);
|
||||
mlwrite(" "); /* clear it off the bottom line */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/**********
|
||||
*
|
||||
* crypt - in place encryption/decryption of a buffer
|
||||
*
|
||||
* (C) Copyright 1986, Dana L. Hoggatt
|
||||
* 1216, Beck Lane, Lafayette, IN
|
||||
*
|
||||
* When consulting directly with the author of this routine,
|
||||
* please refer to this routine as the "DLH-POLY-86-B CIPHER".
|
||||
*
|
||||
* This routine was written for Dan Lawrence, for use in V3.8 of
|
||||
* MicroEMACS, a public domain text/program editor.
|
||||
*
|
||||
* I kept the following goals in mind when preparing this function:
|
||||
*
|
||||
* 1. All printable characters were to be encrypted back
|
||||
* into the printable range, control characters and
|
||||
* high-bit characters were to remain unaffected. this
|
||||
* way, encrypted would still be just as cheap to
|
||||
* transmit down a 7-bit data path as they were before.
|
||||
*
|
||||
* 2. The encryption had to be portable. The encrypted
|
||||
* file from one computer should be able to be decrypted
|
||||
* on another computer.
|
||||
*
|
||||
* 3. The encryption had to be inexpensive, both in terms
|
||||
* of speed and space.
|
||||
*
|
||||
* 4. The system needed to be secure against all but the
|
||||
* most determined of attackers.
|
||||
*
|
||||
* For encryption of a block of data, one calls crypt passing
|
||||
* a pointer to the data block and its length. The data block is
|
||||
* encrypted in place, that is, the encrypted output overwrites
|
||||
* the input. Decryption is totally isomorphic, and is performed
|
||||
* in the same manner by the same routine.
|
||||
*
|
||||
* Before using this routine for encrypting data, you are expected
|
||||
* to specify an encryption key. This key is an arbitrary string,
|
||||
* to be supplied by the user. To set the key takes two calls to
|
||||
* crypt(). First, you call
|
||||
*
|
||||
* crypt(NULL, vector)
|
||||
*
|
||||
* This resets all internal control information. Typically (and
|
||||
* specifically in the case on MICRO-emacs) you would use a "vector"
|
||||
* of 0. Other values can be used to customize your editor to be
|
||||
* "incompatable" with the normally distributed version. For
|
||||
* this purpose, the best results will be obtained by avoiding
|
||||
* multiples of 95.
|
||||
*
|
||||
* Then, you "encrypt" your password by calling
|
||||
*
|
||||
* crypt(pass, strlen(pass))
|
||||
*
|
||||
* where "pass" is your password string. Crypt() will destroy
|
||||
* the original copy of the password (it becomes encrypted),
|
||||
* which is good. You do not want someone on a multiuser system
|
||||
* to peruse your memory space and bump into your password.
|
||||
* Still, it is a better idea to erase the password buffer to
|
||||
* defeat memory perusal by a more technical snooper.
|
||||
*
|
||||
* For the interest of cryptologists, at the heart of this
|
||||
* function is a Beaufort Cipher. The cipher alphabet is the
|
||||
* range of printable characters (' ' to '~'), all "control"
|
||||
* and "high-bit" characters are left unaltered.
|
||||
*
|
||||
* The key is a variant autokey, derived from a wieghted sum
|
||||
* of all the previous clear text and cipher text. A counter
|
||||
* is used as salt to obiterate any simple cyclic behavior
|
||||
* from the clear text, and key feedback is used to assure
|
||||
* that the entire message is based on the original key,
|
||||
* preventing attacks on the last part of the message as if
|
||||
* it were a pure autokey system.
|
||||
*
|
||||
* Overall security of encrypted data depends upon three
|
||||
* factors: the fundamental cryptographic system must be
|
||||
* difficult to compromise; exhaustive searching of the key
|
||||
* space must be computationally expensive; keys and plaintext
|
||||
* must remain out of sight. This system satisfies this set
|
||||
* of conditions to within the degree desired for MicroEMACS.
|
||||
*
|
||||
* Though direct methods of attack (against systems such as
|
||||
* this) do exist, they are not well known and will consume
|
||||
* considerable amounts of computing time. An exhaustive
|
||||
* search requires over a billion investigations, on average.
|
||||
*
|
||||
* The choice, entry, storage, manipulation, alteration,
|
||||
* protection and security of the keys themselves are the
|
||||
* responsiblity of the user.
|
||||
*
|
||||
**********/
|
||||
|
||||
crypt(bptr, len)
|
||||
register char *bptr; /* buffer of characters to be encrypted */
|
||||
register unsigned len; /* number of characters in the buffer */
|
||||
{
|
||||
register int cc; /* current character being considered */
|
||||
|
||||
static long key = 0; /* 29 bit encipherment key */
|
||||
static int salt = 0; /* salt to spice up key with */
|
||||
|
||||
if (!bptr) { /* is there anything here to encrypt? */
|
||||
key = len; /* set the new key */
|
||||
salt = len; /* set the new salt */
|
||||
return;
|
||||
}
|
||||
while (len--) { /* for every character in the buffer */
|
||||
|
||||
cc = *bptr; /* get a character out of the buffer */
|
||||
|
||||
/* only encipher printable characters */
|
||||
if ((cc >= ' ') && (cc <= '~')) {
|
||||
|
||||
/** If the upper bit (bit 29) is set, feed it back into the key. This
|
||||
assures us that the starting key affects the entire message. **/
|
||||
|
||||
key &= 0x1FFFFFFFL; /* strip off overflow */
|
||||
if (key & 0x10000000L) {
|
||||
key ^= 0x0040A001L; /* feedback */
|
||||
}
|
||||
|
||||
/** Down-bias the character, perform a Beaufort encipherment, and
|
||||
up-bias the character again. We want key to be positive
|
||||
so that the left shift here will be more portable and the
|
||||
mod95() faster **/
|
||||
|
||||
cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';
|
||||
|
||||
/** the salt will spice up the key a little bit, helping to obscure
|
||||
any patterns in the clear text, particularly when all the
|
||||
characters (or long sequences of them) are the same. We do
|
||||
not want the salt to go negative, or it will affect the key
|
||||
too radically. It is always a good idea to chop off cyclics
|
||||
to prime values. **/
|
||||
|
||||
if (++salt >= 20857) { /* prime modulus */
|
||||
salt = 0;
|
||||
}
|
||||
|
||||
/** our autokey (a special case of the running key) is being
|
||||
generated by a wieghted checksum of clear text, cipher
|
||||
text, and salt. **/
|
||||
|
||||
key = key + key + cc + *bptr + salt;
|
||||
}
|
||||
*bptr++ = cc; /* put character back into buffer */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int mod95(val)
|
||||
|
||||
register int val;
|
||||
|
||||
{
|
||||
/* The mathematical MOD does not match the computer MOD */
|
||||
|
||||
/* Yes, what I do here may look strange, but it gets the
|
||||
job done, and portably at that. */
|
||||
|
||||
while (val >= 9500)
|
||||
val -= 9500;
|
||||
while (val >= 950)
|
||||
val -= 950;
|
||||
while (val >= 95)
|
||||
val -= 95;
|
||||
while (val < 0)
|
||||
val += 95;
|
||||
return (val);
|
||||
}
|
||||
#else
|
||||
nocrypt()
|
||||
{
|
||||
}
|
||||
#endif
|
2
dosmake.bat
Normal file
2
dosmake.bat
Normal file
@ -0,0 +1,2 @@
|
||||
cl -AL -Ot -Gs -c *.c
|
||||
link @emacs.lnk
|
249
ebind.h
Normal file
249
ebind.h
Normal file
@ -0,0 +1,249 @@
|
||||
/* EBIND.H
|
||||
*
|
||||
* Initial default key to function bindings
|
||||
*
|
||||
* Modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
/*
|
||||
* Command table.
|
||||
* This table is *roughly* in ASCII order, left to right across the
|
||||
* characters of the command. This explains the funny location of the
|
||||
* control-X commands.
|
||||
*/
|
||||
KEYTAB keytab[NBINDS] = {
|
||||
{CONTROL|'A', gotobol},
|
||||
{CONTROL|'B', backchar},
|
||||
{CONTROL|'C', insspace},
|
||||
{CONTROL|'D', forwdel},
|
||||
{CONTROL|'E', gotoeol},
|
||||
{CONTROL|'F', forwchar},
|
||||
{CONTROL|'G', ctrlg},
|
||||
{CONTROL|'H', backdel},
|
||||
{CONTROL|'I', tab},
|
||||
{CONTROL|'J', indent},
|
||||
{CONTROL|'K', killtext},
|
||||
{CONTROL|'L', refresh},
|
||||
{CONTROL|'M', newline},
|
||||
{CONTROL|'N', forwline},
|
||||
{CONTROL|'O', openline},
|
||||
{CONTROL|'P', backline},
|
||||
{CONTROL|'Q', quote},
|
||||
{CONTROL|'R', backsearch},
|
||||
{CONTROL|'S', forwsearch},
|
||||
{CONTROL|'T', twiddle},
|
||||
{CONTROL|'U', unarg},
|
||||
{CONTROL|'V', forwpage},
|
||||
{CONTROL|'W', killregion},
|
||||
{CONTROL|'X', cex},
|
||||
{CONTROL|'Y', yank},
|
||||
{CONTROL|'Z', backpage},
|
||||
{CONTROL|']', meta},
|
||||
{CTLX|CONTROL|'B', listbuffers},
|
||||
{CTLX|CONTROL|'C', quit}, /* Hard quit. */
|
||||
#if PKCODE & AEDIT
|
||||
{CTLX|CONTROL|'A', detab},
|
||||
#endif
|
||||
#if PKCODE
|
||||
{CTLX|CONTROL|'D', filesave}, /* alternative */
|
||||
#else
|
||||
#if AEDIT
|
||||
{CTLX|CONTROL|'D', detab},
|
||||
#endif
|
||||
#endif
|
||||
#if AEDIT
|
||||
{CTLX|CONTROL|'E', entab},
|
||||
#endif
|
||||
{CTLX|CONTROL|'F', filefind},
|
||||
{CTLX|CONTROL|'I', insfile},
|
||||
{CTLX|CONTROL|'L', lowerregion},
|
||||
{CTLX|CONTROL|'M', delmode},
|
||||
{CTLX|CONTROL|'N', mvdnwind},
|
||||
{CTLX|CONTROL|'O', deblank},
|
||||
{CTLX|CONTROL|'P', mvupwind},
|
||||
{CTLX|CONTROL|'R', fileread},
|
||||
{CTLX|CONTROL|'S', filesave},
|
||||
#if AEDIT
|
||||
{CTLX|CONTROL|'T', trim},
|
||||
#endif
|
||||
{CTLX|CONTROL|'U', upperregion},
|
||||
{CTLX|CONTROL|'V', viewfile},
|
||||
{CTLX|CONTROL|'W', filewrite},
|
||||
{CTLX|CONTROL|'X', swapmark},
|
||||
{CTLX|CONTROL|'Z', shrinkwind},
|
||||
{CTLX|'?', deskey},
|
||||
{CTLX|'!', spawn},
|
||||
{CTLX|'@', pipecmd},
|
||||
{CTLX|'#', filter},
|
||||
{CTLX|'$', execprg},
|
||||
{CTLX|'=', showcpos},
|
||||
{CTLX|'(', ctlxlp},
|
||||
{CTLX|')', ctlxrp},
|
||||
{CTLX|'^', enlargewind},
|
||||
{CTLX|'0', delwind},
|
||||
{CTLX|'1', onlywind},
|
||||
{CTLX|'2', splitwind},
|
||||
{CTLX|'A', setvar},
|
||||
{CTLX|'B', usebuffer},
|
||||
{CTLX|'C', spawncli},
|
||||
#if BSD | __hpux | SVR4
|
||||
{CTLX|'D', bktoshell},
|
||||
#endif
|
||||
{CTLX|'E', ctlxe},
|
||||
{CTLX|'F', setfillcol},
|
||||
{CTLX|'K', killbuffer},
|
||||
{CTLX|'M', setmode},
|
||||
{CTLX|'N', filename},
|
||||
{CTLX|'O', nextwind},
|
||||
{CTLX|'P', prevwind},
|
||||
#if PKCODE
|
||||
{CTLX|'Q', quote}, /* alternative */
|
||||
#endif
|
||||
#if ISRCH
|
||||
{CTLX|'R', risearch},
|
||||
{CTLX|'S', fisearch},
|
||||
#endif
|
||||
{CTLX|'W', resize},
|
||||
{CTLX|'X', nextbuffer},
|
||||
{CTLX|'Z', enlargewind},
|
||||
#if WORDPRO
|
||||
{META|CONTROL|'C', wordcount},
|
||||
#endif
|
||||
#if PKCODE
|
||||
{META|CONTROL|'D', newsize},
|
||||
#endif
|
||||
#if PROC
|
||||
{META|CONTROL|'E', execproc},
|
||||
#endif
|
||||
#if CFENCE
|
||||
{META|CONTROL|'F', getfence},
|
||||
#endif
|
||||
{META|CONTROL|'H', delbword},
|
||||
{META|CONTROL|'K', unbindkey},
|
||||
{META|CONTROL|'L', reposition},
|
||||
{META|CONTROL|'M', delgmode},
|
||||
{META|CONTROL|'N', namebuffer},
|
||||
{META|CONTROL|'R', qreplace},
|
||||
{META|CONTROL|'S', newsize},
|
||||
{META|CONTROL|'T', newwidth},
|
||||
{META|CONTROL|'V', scrnextdw},
|
||||
#if WORDPRO
|
||||
{META|CONTROL|'W', killpara},
|
||||
#endif
|
||||
{META|CONTROL|'Z', scrnextup},
|
||||
{META|' ', setmark},
|
||||
{META|'?', help},
|
||||
{META|'!', reposition},
|
||||
{META|'.', setmark},
|
||||
{META|'>', gotoeob},
|
||||
{META|'<', gotobob},
|
||||
{META|'~', unmark},
|
||||
#if APROP
|
||||
{META|'A', apro},
|
||||
#endif
|
||||
{META|'B', backword},
|
||||
{META|'C', capword},
|
||||
{META|'D', delfword},
|
||||
#if CRYPT
|
||||
{META|'E', setkey},
|
||||
#endif
|
||||
{META|'F', forwword},
|
||||
{META|'G', gotoline},
|
||||
#if PKCODE
|
||||
#if WORDPRO
|
||||
{META|'J', justpara},
|
||||
#endif
|
||||
#endif
|
||||
{META|'K', bindtokey},
|
||||
{META|'L', lowerword},
|
||||
{META|'M', setgmode},
|
||||
#if WORDPRO
|
||||
{META|'N', gotoeop},
|
||||
{META|'P', gotobop},
|
||||
{META|'Q', fillpara},
|
||||
#endif
|
||||
{META|'R', sreplace},
|
||||
#if PKCODE
|
||||
{META|'S', forwsearch}, /* alternative P.K. */
|
||||
#else
|
||||
#if BSD
|
||||
{META|'S', bktoshell},
|
||||
#endif
|
||||
#endif
|
||||
{META|'U', upperword},
|
||||
{META|'V', backpage},
|
||||
{META|'W', copyregion},
|
||||
{META|'X', namedcmd},
|
||||
{META|'Z', quickexit},
|
||||
{META|0x7F, delbword},
|
||||
|
||||
#if MSDOS
|
||||
{SPEC|CONTROL|'_', forwhunt},
|
||||
{SPEC|CONTROL|'S', backhunt},
|
||||
{SPEC|71, gotobol},
|
||||
{SPEC|72, backline},
|
||||
{SPEC|73, backpage},
|
||||
{SPEC|75, backchar},
|
||||
{SPEC|77, forwchar},
|
||||
{SPEC|79, gotoeol},
|
||||
{SPEC|80, forwline},
|
||||
{SPEC|81, forwpage},
|
||||
{SPEC|82, insspace},
|
||||
{SPEC|83, forwdel},
|
||||
{SPEC|115, backword},
|
||||
{SPEC|116, forwword},
|
||||
#if WORDPRO
|
||||
{SPEC|132, gotobop},
|
||||
{SPEC|118, gotoeop},
|
||||
#endif
|
||||
{SPEC|84, cbuf1},
|
||||
{SPEC|85, cbuf2},
|
||||
{SPEC|86, cbuf3},
|
||||
{SPEC|87, cbuf4},
|
||||
{SPEC|88, cbuf5},
|
||||
{SPEC|89, cbuf6},
|
||||
{SPEC|90, cbuf7},
|
||||
{SPEC|91, cbuf8},
|
||||
{SPEC|92, cbuf9},
|
||||
{SPEC|93, cbuf10},
|
||||
#if PKCODE
|
||||
{SPEC|117, gotoeob},
|
||||
{SPEC|119, gotobob},
|
||||
{SPEC|141, gotobop},
|
||||
{SPEC|145, gotoeop},
|
||||
{SPEC|146, yank},
|
||||
{SPEC|147, killregion},
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if VT220
|
||||
{SPEC|'1', fisearch}, /* VT220 keys */
|
||||
{SPEC|'2', yank},
|
||||
{SPEC|'3', killregion},
|
||||
{SPEC|'4', setmark},
|
||||
{SPEC|'5', backpage},
|
||||
{SPEC|'6', forwpage},
|
||||
{SPEC|'A', backline},
|
||||
{SPEC|'B', forwline},
|
||||
{SPEC|'C', forwchar},
|
||||
{SPEC|'D', backchar},
|
||||
{SPEC|'c', meta},
|
||||
{SPEC|'d', backchar},
|
||||
{SPEC|'e', forwline},
|
||||
{SPEC|'f', gotobob},
|
||||
{SPEC|'h', help},
|
||||
{SPEC|'i', cex},
|
||||
#endif
|
||||
|
||||
{0x7F, backdel},
|
||||
|
||||
/* special internal bindings */
|
||||
SPEC|META|'W', wrapword, /* called on word wrap */
|
||||
SPEC|META|'C', nullproc, /* every command input */
|
||||
SPEC|META|'R', nullproc, /* on file read */
|
||||
SPEC|META|'X', nullproc, /* on window change P.K. */
|
||||
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
323
edef.h
Normal file
323
edef.h
Normal file
@ -0,0 +1,323 @@
|
||||
/* EDEF.H
|
||||
*
|
||||
* Global variable definitions
|
||||
*
|
||||
* written by Dave G. Conroy
|
||||
* modified by Steve Wilhite, George Jones
|
||||
* greatly modified by Daniel Lawrence
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
/* some global fuction declarations */
|
||||
|
||||
char *flook();
|
||||
char *getctext();
|
||||
char *getfname();
|
||||
char *getval();
|
||||
char *gtenv();
|
||||
char *gtfun();
|
||||
char *gtusr();
|
||||
char *itoa();
|
||||
char *ltos();
|
||||
char *malloc();
|
||||
char *mklower();
|
||||
char *mkupper();
|
||||
char *strcat();
|
||||
char *strcpy();
|
||||
char *strncpy();
|
||||
char *token();
|
||||
char *transbind();
|
||||
unsigned int getckey();
|
||||
unsigned int stock();
|
||||
|
||||
#ifdef maindef
|
||||
|
||||
/* for MAIN.C */
|
||||
|
||||
/* initialized global definitions */
|
||||
|
||||
int fillcol = 72; /* Current fill column */
|
||||
short kbdm[NKBDM]; /* Macro */
|
||||
char *execstr = NULL; /* pointer to string to execute */
|
||||
char golabel[NPAT] = ""; /* current line to go to */
|
||||
int execlevel = 0; /* execution IF level */
|
||||
int eolexist = TRUE; /* does clear to EOL exist */
|
||||
int revexist = FALSE; /* does reverse video exist? */
|
||||
int flickcode = FALSE; /* do flicker supression? */
|
||||
char *modename[] = { /* name of modes */
|
||||
"WRAP", "CMODE", "SPELL", "EXACT", "VIEW", "OVER",
|
||||
"MAGIC", "CRYPT", "ASAVE"};
|
||||
char *mode2name[] = { /* name of modes */
|
||||
"Wrap", "Cmode", "Spell", "Exact", "View", "Over",
|
||||
"Magic", "Crypt", "Asave"};
|
||||
char modecode[] = "WCSEVOMYA"; /* letters to represent modes */
|
||||
int gmode = 0; /* global editor mode */
|
||||
int gflags = GFREAD; /* global control flag */
|
||||
#if PKCODE & IBMPC
|
||||
int gfcolor = 8; /* global forgrnd color (white) */
|
||||
#else
|
||||
int gfcolor = 7; /* global forgrnd color (white) */
|
||||
#endif
|
||||
int gbcolor = 0; /* global backgrnd color (black)*/
|
||||
int gasave = 256; /* global ASAVE size */
|
||||
int gacount = 256; /* count until next ASAVE */
|
||||
int sgarbf = TRUE; /* TRUE if screen is garbage */
|
||||
int mpresf = FALSE; /* TRUE if message in last line */
|
||||
int clexec = FALSE; /* command line execution flag */
|
||||
int mstore = FALSE; /* storing text to macro flag */
|
||||
int discmd = TRUE; /* display command flag */
|
||||
int disinp = TRUE; /* display input characters */
|
||||
struct BUFFER *bstore = NULL; /* buffer to store macro text to*/
|
||||
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 */
|
||||
int lbound = 0; /* leftmost column of current line
|
||||
being displayed */
|
||||
int taboff = 0; /* tab offset for display */
|
||||
int metac = CONTROL | '['; /* current meta character */
|
||||
int ctlxc = CONTROL | 'X'; /* current control X prefix char */
|
||||
int reptc = CONTROL | 'U'; /* current universal repeat char */
|
||||
int abortc = CONTROL | 'G'; /* current abort command char */
|
||||
|
||||
int quotec = 0x11; /* quote char during mlreply() */
|
||||
int tabmask = 0x07; /* tabulator mask */
|
||||
char *cname[] = { /* names of colors */
|
||||
"BLACK", "RED", "GREEN", "YELLOW", "BLUE",
|
||||
"MAGENTA", "CYAN", "WHITE"
|
||||
#if PKCODE & IBMPC
|
||||
,"HIGH"
|
||||
#endif
|
||||
};
|
||||
KILL *kbufp = NULL; /* current kill buffer chunk pointer */
|
||||
KILL *kbufh = NULL; /* kill buffer header pointer */
|
||||
int kused = KBLOCK; /* # of bytes used in kill buffer */
|
||||
WINDOW *swindow = NULL; /* saved window pointer */
|
||||
int cryptflag = FALSE; /* currently encrypting? */
|
||||
short *kbdptr; /* current position in keyboard buf */
|
||||
short *kbdend = &kbdm[0]; /* ptr to end of the keyboard */
|
||||
int kbdmode = STOP; /* current keyboard macro mode */
|
||||
int kbdrep = 0; /* number of repetitions */
|
||||
int restflag = FALSE; /* restricted use? */
|
||||
int lastkey = 0; /* last keystoke */
|
||||
int seed = 0; /* random number seed */
|
||||
long envram = 0l; /* # of bytes current in use by malloc */
|
||||
int macbug = FALSE; /* macro debuging flag */
|
||||
char errorm[] = "ERROR"; /* error literal */
|
||||
char truem[] = "TRUE"; /* true literal */
|
||||
char falsem[] = "FALSE"; /* false litereal */
|
||||
int cmdstatus = TRUE; /* last command status */
|
||||
char palstr[49] = ""; /* palette string */
|
||||
int saveflag = 0; /* Flags, saved with the $target var */
|
||||
char *fline = NULL; /* dynamic return line */
|
||||
int flen = 0; /* current length of fline */
|
||||
int rval = 0; /* return value of a subprocess */
|
||||
#if CALLED
|
||||
int eexitflag = FALSE; /* EMACS exit flag */
|
||||
int eexitval = 0; /* and the exit return value */
|
||||
#endif
|
||||
#if PKCODE
|
||||
int nullflag = FALSE; /* accept null characters */
|
||||
int justflag = FALSE; /* justify, don't fill */
|
||||
#endif
|
||||
int overlap = 0; /* line overlap in forw/back page */
|
||||
int scrollcount = 1; /* number of lines to scroll */
|
||||
|
||||
/* uninitialized global definitions */
|
||||
|
||||
int currow; /* Cursor row */
|
||||
int curcol; /* Cursor column */
|
||||
int thisflag; /* Flags, this command */
|
||||
int lastflag; /* Flags, last command */
|
||||
int curgoal; /* Goal for C-P, C-N */
|
||||
WINDOW *curwp; /* Current window */
|
||||
BUFFER *curbp; /* Current buffer */
|
||||
WINDOW *wheadp; /* Head of list of windows */
|
||||
BUFFER *bheadp; /* Head of list of buffers */
|
||||
BUFFER *blistp; /* Buffer for C-X C-B */
|
||||
|
||||
BUFFER *bfind(); /* Lookup a buffer by name */
|
||||
WINDOW *wpopup(); /* Pop up window creation */
|
||||
LINE *lalloc(); /* Allocate a line */
|
||||
char sres[NBUFN]; /* current screen resolution */
|
||||
|
||||
char pat[NPAT]; /* Search pattern */
|
||||
char tap[NPAT]; /* Reversed pattern array. */
|
||||
char rpat[NPAT]; /* replacement pattern */
|
||||
|
||||
/* The variable matchlen holds the length of the matched
|
||||
* string - used by the replace functions.
|
||||
* The variable patmatch holds the string that satisfies
|
||||
* the search command.
|
||||
* The variables matchline and matchoff hold the line and
|
||||
* offset position of the *start* of match.
|
||||
*/
|
||||
unsigned int matchlen = 0;
|
||||
unsigned int mlenold = 0;
|
||||
char *patmatch = NULL;
|
||||
LINE *matchline = NULL;
|
||||
int matchoff = 0;
|
||||
|
||||
#if MAGIC
|
||||
/*
|
||||
* The variables magical and rmagical determine if there
|
||||
* were actual metacharacters in the search and replace strings -
|
||||
* if not, then we don't have to use the slower MAGIC mode
|
||||
* search functions.
|
||||
*/
|
||||
short int magical = FALSE;
|
||||
short int rmagical = FALSE;
|
||||
MC mcpat[NPAT]; /* the magic pattern */
|
||||
MC tapcm[NPAT]; /* the reversed magic pattern */
|
||||
RMC rmcpat[NPAT]; /* the replacement magic array */
|
||||
|
||||
#endif
|
||||
|
||||
/* directive name table:
|
||||
This holds the names of all the directives.... */
|
||||
|
||||
char *dname[] = {
|
||||
"if", "else", "endif",
|
||||
"goto", "return", "endm",
|
||||
"while", "endwhile", "break",
|
||||
"force"
|
||||
};
|
||||
|
||||
#if DEBUGM
|
||||
/* vars needed for macro debugging output */
|
||||
char outline[NSTRING]; /* global string to hold debug line text */
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* for all the other .C files */
|
||||
|
||||
/* initialized global external declarations */
|
||||
|
||||
extern int fillcol; /* Fill column */
|
||||
extern short kbdm[]; /* Holds kayboard macro data */
|
||||
extern char pat[]; /* Search pattern */
|
||||
extern char rpat[]; /* Replacement pattern */
|
||||
extern char *execstr; /* pointer to string to execute */
|
||||
extern char golabel[]; /* current line to go to */
|
||||
extern int execlevel; /* execution IF level */
|
||||
extern int eolexist; /* does clear to EOL exist? */
|
||||
extern int revexist; /* does reverse video exist? */
|
||||
extern int flickcode; /* do flicker supression? */
|
||||
extern char *modename[]; /* text names of modes */
|
||||
extern char *mode2name[]; /* text names of modes */
|
||||
extern char modecode[]; /* letters to represent modes */
|
||||
extern KEYTAB keytab[]; /* key bind to functions table */
|
||||
extern NBIND names[]; /* name to function table */
|
||||
extern int gmode; /* global editor mode */
|
||||
extern int gflags; /* global control flag */
|
||||
extern int gfcolor; /* global forgrnd color (white) */
|
||||
extern int gbcolor; /* global backgrnd color (black)*/
|
||||
extern int gasave; /* global ASAVE size */
|
||||
extern int gacount; /* count until next ASAVE */
|
||||
extern int sgarbf; /* State of screen unknown */
|
||||
extern int mpresf; /* Stuff in message line */
|
||||
extern int clexec; /* command line execution flag */
|
||||
extern int mstore; /* storing text to macro flag */
|
||||
extern int discmd; /* display command flag */
|
||||
extern int disinp; /* display input characters */
|
||||
extern struct BUFFER *bstore; /* buffer to store macro text to*/
|
||||
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 */
|
||||
extern int lbound; /* leftmost column of current line
|
||||
being displayed */
|
||||
extern int taboff; /* tab offset for display */
|
||||
extern int metac; /* current meta character */
|
||||
extern int ctlxc; /* current control X prefix char */
|
||||
extern int reptc; /* current universal repeat char */
|
||||
extern int abortc; /* current abort command char */
|
||||
|
||||
extern int quotec; /* quote char during mlreply() */
|
||||
extern int tabmask;
|
||||
extern char *cname[]; /* names of colors */
|
||||
extern KILL *kbufp; /* current kill buffer chunk pointer */
|
||||
extern KILL *kbufh; /* kill buffer header pointer */
|
||||
extern int kused; /* # of bytes used in KB */
|
||||
extern WINDOW *swindow; /* saved window pointer */
|
||||
extern int cryptflag; /* currently encrypting? */
|
||||
extern short *kbdptr; /* current position in keyboard buf */
|
||||
extern short *kbdend; /* ptr to end of the keyboard */
|
||||
extern int kbdmode; /* current keyboard macro mode */
|
||||
extern int kbdrep; /* number of repetitions */
|
||||
extern int restflag; /* restricted use? */
|
||||
extern int lastkey; /* last keystoke */
|
||||
extern int seed; /* random number seed */
|
||||
extern long envram; /* # of bytes current in use by malloc */
|
||||
extern int macbug; /* macro debuging flag */
|
||||
extern char errorm[]; /* error literal */
|
||||
extern char truem[]; /* true literal */
|
||||
extern char falsem[]; /* false litereal */
|
||||
extern int cmdstatus; /* last command status */
|
||||
extern char palstr[]; /* palette string */
|
||||
extern int saveflag; /* Flags, saved with the $target var */
|
||||
extern char *fline; /* dynamic return line */
|
||||
extern int flen; /* current length of fline */
|
||||
extern int rval; /* return value of a subprocess */
|
||||
#if CALLED
|
||||
extern int eexitflag; /* EMACS exit flag */
|
||||
extern int eexitval; /* and the exit return value */
|
||||
#endif
|
||||
#if PKCODE
|
||||
extern int justflag; /* justify, don't fill */
|
||||
#endif
|
||||
extern int overlap; /* line overlap in forw/back page */
|
||||
extern int scrollcount; /* number of lines to scroll */
|
||||
|
||||
/* uninitialized global external declarations */
|
||||
|
||||
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 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 BUFFER *bfind(); /* Lookup a buffer by name */
|
||||
extern WINDOW *wpopup(); /* Pop up window creation */
|
||||
extern LINE *lalloc(); /* Allocate a line */
|
||||
extern char sres[NBUFN]; /* current screen resolution */
|
||||
extern char pat[]; /* Search pattern */
|
||||
extern char tap[]; /* Reversed pattern array. */
|
||||
extern char rpat[]; /* replacement pattern */
|
||||
|
||||
extern unsigned int matchlen;
|
||||
extern unsigned int mlenold;
|
||||
extern char *patmatch;
|
||||
extern LINE *matchline;
|
||||
extern int matchoff;
|
||||
|
||||
#if MAGIC
|
||||
extern short int magical;
|
||||
extern short int rmagical;
|
||||
extern MC mcpat[NPAT]; /* the magic pattern */
|
||||
extern MC tapcm[NPAT]; /* the reversed magic pattern */
|
||||
extern RMC rmcpat[NPAT]; /* the replacement magic array */
|
||||
#endif
|
||||
|
||||
extern char *dname[]; /* directive name table */
|
||||
|
||||
#if DEBUGM
|
||||
/* vars needed for macro debugging output */
|
||||
extern char outline[]; /* global string to hold debug line text */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* terminal table defined only in TERM.C */
|
||||
|
||||
#ifndef termdef
|
||||
extern TERM term; /* Terminal information. */
|
||||
#endif
|
||||
|
||||
|
431
efunc.h
Normal file
431
efunc.h
Normal file
@ -0,0 +1,431 @@
|
||||
/* EFUNC.H
|
||||
*
|
||||
* Function declarations and names
|
||||
*
|
||||
* This file list all the C code functions used
|
||||
* and the names to use to bind keys to them. To add functions,
|
||||
* declare it here in both the extern function list and the name
|
||||
* binding table.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
/* External function declarations */
|
||||
|
||||
extern int ctrlg(); /* Abort out of things */
|
||||
extern int quit(); /* Quit */
|
||||
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 */
|
||||
extern int getccol(); /* Get current column */
|
||||
extern int gotobol(); /* Move to start of line */
|
||||
extern int forwchar(); /* Move forward by characters */
|
||||
extern int gotoeol(); /* Move to end of line */
|
||||
extern int backchar(); /* Move backward by characters */
|
||||
extern int forwline(); /* Move forward by lines */
|
||||
extern int backline(); /* Move backward by lines */
|
||||
extern int forwpage(); /* Move forward by pages */
|
||||
extern int backpage(); /* Move backward by pages */
|
||||
extern int gotobob(); /* Move to start of buffer */
|
||||
extern int gotoeob(); /* Move to end of buffer */
|
||||
extern int setfillcol(); /* Set fill column. */
|
||||
extern int setmark(); /* Set mark */
|
||||
extern int swapmark(); /* Swap "." and mark */
|
||||
extern int forwsearch(); /* Search forward */
|
||||
extern int backsearch(); /* Search backwards */
|
||||
extern int sreplace(); /* search and replace */
|
||||
extern int qreplace(); /* search and replace w/query */
|
||||
extern int showcpos(); /* Show the cursor position */
|
||||
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 mvdnwind(); /* Move window down */
|
||||
extern int mvupwind(); /* Move window up */
|
||||
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 reposition(); /* Reposition window */
|
||||
extern int refresh(); /* Refresh the screen */
|
||||
extern int twiddle(); /* Twiddle characters */
|
||||
extern int tab(); /* Insert tab */
|
||||
extern int newline(); /* Insert CR-LF */
|
||||
extern int indent(); /* Insert CR-LF, then indent */
|
||||
extern int openline(); /* Open up a blank line */
|
||||
extern int deblank(); /* Delete blank lines */
|
||||
extern int quote(); /* Insert literal */
|
||||
extern int backword(); /* Backup by words */
|
||||
extern int forwword(); /* Advance by words */
|
||||
extern int forwdel(); /* Forward delete */
|
||||
extern int backdel(); /* Backward delete */
|
||||
extern int killtext(); /* Kill forward */
|
||||
extern int yank(); /* Yank back from killbuffer. */
|
||||
extern int upperword(); /* Upper case word. */
|
||||
extern int lowerword(); /* Lower case word. */
|
||||
extern int upperregion(); /* Upper case region. */
|
||||
extern int lowerregion(); /* Lower case region. */
|
||||
extern int capword(); /* Initial capitalize word. */
|
||||
extern int delfword(); /* Delete forward word. */
|
||||
extern int delbword(); /* Delete backward word. */
|
||||
extern int killregion(); /* Kill region. */
|
||||
extern int copyregion(); /* Copy region to kill buffer. */
|
||||
extern int spawncli(); /* Run CLI in a subjob. */
|
||||
extern int spawn(); /* Run a command in a subjob. */
|
||||
#if BSD | __hpux | SVR4
|
||||
extern int bktoshell(); /* suspend emacs to parent shell*/
|
||||
extern int rtfrmshell(); /* return from a suspended state*/
|
||||
#endif
|
||||
extern int quickexit(); /* low keystroke style exit. */
|
||||
extern int setmode(); /* set an editor mode */
|
||||
extern int delmode(); /* delete a mode */
|
||||
extern int gotoline(); /* go to a numbered line */
|
||||
extern int namebuffer(); /* rename the current buffer */
|
||||
#if WORDPRO
|
||||
extern int gotobop(); /* go to beginning/paragraph */
|
||||
extern int gotoeop(); /* go to end/paragraph */
|
||||
extern int fillpara(); /* fill current paragraph */
|
||||
#if PKCODE
|
||||
extern int justpara(); /* justify current paragraph */
|
||||
#endif
|
||||
#endif
|
||||
extern int help(); /* get the help file here */
|
||||
extern int deskey(); /* describe a key's binding */
|
||||
extern int viewfile(); /* find a file in view mode */
|
||||
extern int insfile(); /* insert a file */
|
||||
extern int scrnextup(); /* scroll next window back */
|
||||
extern int scrnextdw(); /* scroll next window down */
|
||||
extern int bindtokey(); /* bind a function to a key */
|
||||
extern int unbindkey(); /* unbind a key's function */
|
||||
extern int namedcmd(); /* execute named command */
|
||||
extern int desbind(); /* describe bindings */
|
||||
extern int execcmd(); /* execute a command line */
|
||||
extern int execbuf(); /* exec commands from a buffer */
|
||||
extern int execfile(); /* exec commands from a file */
|
||||
extern int nextbuffer(); /* switch to the next buffer */
|
||||
#if WORDPRO
|
||||
extern int killpara(); /* kill the current paragraph */
|
||||
#endif
|
||||
extern int setgmode(); /* set a global mode */
|
||||
extern int delgmode(); /* delete a global mode */
|
||||
extern int insspace(); /* insert a space forword */
|
||||
extern int forwhunt(); /* hunt forward for next match */
|
||||
extern int backhunt(); /* hunt backwards for next match*/
|
||||
extern int pipecmd(); /* pipe command into buffer */
|
||||
extern int filter(); /* filter buffer through dos */
|
||||
extern int delwind(); /* delete the current window */
|
||||
extern int cbuf1(); /* execute numbered comd buffer */
|
||||
extern int cbuf2();
|
||||
extern int cbuf3();
|
||||
extern int cbuf4();
|
||||
extern int cbuf5();
|
||||
extern int cbuf6();
|
||||
extern int cbuf7();
|
||||
extern int cbuf8();
|
||||
extern int cbuf9();
|
||||
extern int cbuf10();
|
||||
extern int cbuf11();
|
||||
extern int cbuf12();
|
||||
extern int cbuf13();
|
||||
extern int cbuf14();
|
||||
extern int cbuf15();
|
||||
extern int cbuf16();
|
||||
extern int cbuf17();
|
||||
extern int cbuf18();
|
||||
extern int cbuf19();
|
||||
extern int cbuf20();
|
||||
extern int cbuf21();
|
||||
extern int cbuf22();
|
||||
extern int cbuf23();
|
||||
extern int cbuf24();
|
||||
extern int cbuf25();
|
||||
extern int cbuf26();
|
||||
extern int cbuf27();
|
||||
extern int cbuf28();
|
||||
extern int cbuf29();
|
||||
extern int cbuf30();
|
||||
extern int cbuf31();
|
||||
extern int cbuf32();
|
||||
extern int cbuf33();
|
||||
extern int cbuf34();
|
||||
extern int cbuf35();
|
||||
extern int cbuf36();
|
||||
extern int cbuf37();
|
||||
extern int cbuf38();
|
||||
extern int cbuf39();
|
||||
extern int cbuf40();
|
||||
extern int storemac(); /* store text for macro */
|
||||
extern int resize(); /* resize current window */
|
||||
extern int clrmes(); /* clear the message line */
|
||||
extern int meta(); /* meta prefix dummy function */
|
||||
extern int cex(); /* ^X prefix dummy function */
|
||||
extern int unarg(); /* ^U repeat arg dummy function */
|
||||
extern int istring(); /* insert string in text */
|
||||
extern int unmark(); /* unmark current buffer */
|
||||
#if ISRCH
|
||||
extern int fisearch(); /* forward incremental search */
|
||||
extern int risearch(); /* reverse incremental search */
|
||||
#endif
|
||||
#if WORDPRO
|
||||
extern int wordcount(); /* count words in region */
|
||||
#endif
|
||||
extern int savewnd(); /* save current window */
|
||||
extern int restwnd(); /* restore current window */
|
||||
extern int upscreen(); /* force screen update */
|
||||
extern int writemsg(); /* write text on message line */
|
||||
#if FNLABEL
|
||||
extern int fnclabel(); /* set function key label */
|
||||
#endif
|
||||
#if APROP
|
||||
extern int apro(); /* apropos fuction */
|
||||
#endif
|
||||
#if CRYPT
|
||||
extern int setkey(); /* set encryption key */
|
||||
#endif
|
||||
extern int wrapword(); /* wordwrap function */
|
||||
#if CFENCE
|
||||
extern int getfence(); /* move cursor to a matching fence */
|
||||
#endif
|
||||
extern int newsize(); /* change the current screen size */
|
||||
extern int setvar(); /* set a variables value */
|
||||
extern int newwidth(); /* change the current screen width */
|
||||
#if AEDIT
|
||||
extern int trim(); /* trim whitespace from end of line */
|
||||
extern int detab(); /* detab rest of line */
|
||||
extern int entab(); /* entab rest of line */
|
||||
#endif
|
||||
#if PROC
|
||||
extern int storeproc(); /* store names procedure */
|
||||
extern int execproc(); /* execute procedure */
|
||||
#endif
|
||||
extern int nullproc(); /* does nothing... */
|
||||
extern int ovstring(); /* overwrite a string */
|
||||
extern int execprg(); /* execute a program */
|
||||
|
||||
extern int cknewwindow();
|
||||
|
||||
/* Name to function binding table
|
||||
|
||||
This table gives the names of all the bindable functions
|
||||
end their C function address. These are used for the bind-to-key
|
||||
function.
|
||||
*/
|
||||
|
||||
NBIND names[] = {
|
||||
{"abort-command", ctrlg},
|
||||
{"add-mode", setmode},
|
||||
{"add-global-mode", setgmode},
|
||||
#if APROP
|
||||
{"apropos", apro},
|
||||
#endif
|
||||
{"backward-character", backchar},
|
||||
{"begin-macro", ctlxlp},
|
||||
{"beginning-of-file", gotobob},
|
||||
{"beginning-of-line", gotobol},
|
||||
{"bind-to-key", bindtokey},
|
||||
{"buffer-position", showcpos},
|
||||
{"case-region-lower", lowerregion},
|
||||
{"case-region-upper", upperregion},
|
||||
{"case-word-capitalize", capword},
|
||||
{"case-word-lower", lowerword},
|
||||
{"case-word-upper", upperword},
|
||||
{"change-file-name", filename},
|
||||
{"change-screen-size", newsize},
|
||||
{"change-screen-width", newwidth},
|
||||
{"clear-and-redraw", refresh},
|
||||
{"clear-message-line", clrmes},
|
||||
{"copy-region", copyregion},
|
||||
#if WORDPRO
|
||||
{"count-words", wordcount},
|
||||
#endif
|
||||
{"ctlx-prefix", cex},
|
||||
{"delete-blank-lines", deblank},
|
||||
{"delete-buffer", killbuffer},
|
||||
{"delete-mode", delmode},
|
||||
{"delete-global-mode", delgmode},
|
||||
{"delete-next-character", forwdel},
|
||||
{"delete-next-word", delfword},
|
||||
{"delete-other-windows", onlywind},
|
||||
{"delete-previous-character", backdel},
|
||||
{"delete-previous-word", delbword},
|
||||
{"delete-window", delwind},
|
||||
{"describe-bindings", desbind},
|
||||
{"describe-key", deskey},
|
||||
#if AEDIT
|
||||
{"detab-line", detab},
|
||||
#endif
|
||||
{"end-macro", ctlxrp},
|
||||
{"end-of-file", gotoeob},
|
||||
{"end-of-line", gotoeol},
|
||||
#if AEDIT
|
||||
{"entab-line", entab},
|
||||
#endif
|
||||
{"exchange-point-and-mark", swapmark},
|
||||
{"execute-buffer", execbuf},
|
||||
{"execute-command-line", execcmd},
|
||||
{"execute-file", execfile},
|
||||
{"execute-macro", ctlxe},
|
||||
{"execute-macro-1", cbuf1},
|
||||
{"execute-macro-2", cbuf2},
|
||||
{"execute-macro-3", cbuf3},
|
||||
{"execute-macro-4", cbuf4},
|
||||
{"execute-macro-5", cbuf5},
|
||||
{"execute-macro-6", cbuf6},
|
||||
{"execute-macro-7", cbuf7},
|
||||
{"execute-macro-8", cbuf8},
|
||||
{"execute-macro-9", cbuf9},
|
||||
{"execute-macro-10", cbuf10},
|
||||
{"execute-macro-11", cbuf11},
|
||||
{"execute-macro-12", cbuf12},
|
||||
{"execute-macro-13", cbuf13},
|
||||
{"execute-macro-14", cbuf14},
|
||||
{"execute-macro-15", cbuf15},
|
||||
{"execute-macro-16", cbuf16},
|
||||
{"execute-macro-17", cbuf17},
|
||||
{"execute-macro-18", cbuf18},
|
||||
{"execute-macro-19", cbuf19},
|
||||
{"execute-macro-20", cbuf20},
|
||||
{"execute-macro-21", cbuf21},
|
||||
{"execute-macro-22", cbuf22},
|
||||
{"execute-macro-23", cbuf23},
|
||||
{"execute-macro-24", cbuf24},
|
||||
{"execute-macro-25", cbuf25},
|
||||
{"execute-macro-26", cbuf26},
|
||||
{"execute-macro-27", cbuf27},
|
||||
{"execute-macro-28", cbuf28},
|
||||
{"execute-macro-29", cbuf29},
|
||||
{"execute-macro-30", cbuf30},
|
||||
{"execute-macro-31", cbuf31},
|
||||
{"execute-macro-32", cbuf32},
|
||||
{"execute-macro-33", cbuf33},
|
||||
{"execute-macro-34", cbuf34},
|
||||
{"execute-macro-35", cbuf35},
|
||||
{"execute-macro-36", cbuf36},
|
||||
{"execute-macro-37", cbuf37},
|
||||
{"execute-macro-38", cbuf38},
|
||||
{"execute-macro-39", cbuf39},
|
||||
{"execute-macro-40", cbuf40},
|
||||
{"execute-named-command", namedcmd},
|
||||
#if PROC
|
||||
{"execute-procedure", execproc},
|
||||
#endif
|
||||
{"execute-program", execprg},
|
||||
{"exit-emacs", quit},
|
||||
#if WORDPRO
|
||||
{"fill-paragraph", fillpara},
|
||||
#endif
|
||||
{"filter-buffer", filter},
|
||||
{"find-file", filefind},
|
||||
{"forward-character", forwchar},
|
||||
{"goto-line", gotoline},
|
||||
#if CFENCE
|
||||
{"goto-matching-fence", getfence},
|
||||
#endif
|
||||
{"grow-window", enlargewind},
|
||||
{"handle-tab", tab},
|
||||
{"hunt-forward", forwhunt},
|
||||
{"hunt-backward", backhunt},
|
||||
{"help", help},
|
||||
{"i-shell", spawncli},
|
||||
#if ISRCH
|
||||
{"incremental-search", fisearch},
|
||||
#endif
|
||||
{"insert-file", insfile},
|
||||
{"insert-space", insspace},
|
||||
{"insert-string", istring},
|
||||
#if WORDPRO
|
||||
#if PKCODE
|
||||
{"justify-paragraph", justpara},
|
||||
#endif
|
||||
{"kill-paragraph", killpara},
|
||||
#endif
|
||||
{"kill-region", killregion},
|
||||
{"kill-to-end-of-line", killtext},
|
||||
#if FNLABEL
|
||||
{"label-function-key", fnclabel},
|
||||
#endif
|
||||
{"list-buffers", listbuffers},
|
||||
{"meta-prefix", meta},
|
||||
{"move-window-down", mvdnwind},
|
||||
{"move-window-up", mvupwind},
|
||||
{"name-buffer", namebuffer},
|
||||
{"newline", newline},
|
||||
{"newline-and-indent", indent},
|
||||
{"next-buffer", nextbuffer},
|
||||
{"next-line", forwline},
|
||||
{"next-page", forwpage},
|
||||
#if WORDPRO
|
||||
{"next-paragraph", gotoeop},
|
||||
#endif
|
||||
{"next-window", nextwind},
|
||||
{"next-word", forwword},
|
||||
{"nop", nullproc},
|
||||
{"open-line", openline},
|
||||
{"overwrite-string", ovstring},
|
||||
{"pipe-command", pipecmd},
|
||||
{"previous-line", backline},
|
||||
{"previous-page", backpage},
|
||||
#if WORDPRO
|
||||
{"previous-paragraph", gotobop},
|
||||
#endif
|
||||
{"previous-window", prevwind},
|
||||
{"previous-word", backword},
|
||||
{"query-replace-string", qreplace},
|
||||
{"quick-exit", quickexit},
|
||||
{"quote-character", quote},
|
||||
{"read-file", fileread},
|
||||
{"redraw-display", reposition},
|
||||
{"resize-window", resize},
|
||||
{"restore-window", restwnd},
|
||||
{"replace-string", sreplace},
|
||||
#if ISRCH
|
||||
{"reverse-incremental-search", risearch},
|
||||
#endif
|
||||
#if PROC
|
||||
{"run", execproc},
|
||||
#endif
|
||||
{"save-file", filesave},
|
||||
{"save-window", savewnd},
|
||||
{"scroll-next-up", scrnextup},
|
||||
{"scroll-next-down", scrnextdw},
|
||||
{"search-forward", forwsearch},
|
||||
{"search-reverse", backsearch},
|
||||
{"select-buffer", usebuffer},
|
||||
{"set", setvar},
|
||||
#if CRYPT
|
||||
{"set-encryption-key", setkey},
|
||||
#endif
|
||||
{"set-fill-column", setfillcol},
|
||||
{"set-mark", setmark},
|
||||
{"shell-command", spawn},
|
||||
{"shrink-window", shrinkwind},
|
||||
{"split-current-window", splitwind},
|
||||
{"store-macro", storemac},
|
||||
#if PROC
|
||||
{"store-procedure", storeproc},
|
||||
#endif
|
||||
#if BSD | __hpux | SVR4
|
||||
{"suspend-emacs", bktoshell},
|
||||
#endif
|
||||
{"transpose-characters", twiddle},
|
||||
#if AEDIT
|
||||
{"trim-line", trim},
|
||||
#endif
|
||||
{"unbind-key", unbindkey},
|
||||
{"universal-argument", unarg},
|
||||
{"unmark-buffer", unmark},
|
||||
{"update-screen", upscreen},
|
||||
{"view-file", viewfile},
|
||||
{"wrap-word", wrapword},
|
||||
{"write-file", filewrite},
|
||||
{"write-message", writemsg},
|
||||
{"yank", yank},
|
||||
|
||||
{"", NULL}
|
||||
};
|
172
emacs.hlp
Normal file
172
emacs.hlp
Normal file
@ -0,0 +1,172 @@
|
||||
=> uEmacs/PK 4.0 HELP INDEX
|
||||
.. The very basics
|
||||
.. Cursor movement
|
||||
.. File commands
|
||||
.. Miscellaneous character commands
|
||||
.. Mode commands
|
||||
.. Keys and commands
|
||||
.. Deleting and inserting
|
||||
.. Formatting
|
||||
.. Window commands
|
||||
.. Buffer commands
|
||||
.. Searching and replacing
|
||||
.. Accessing the operating system
|
||||
.. Macro commands
|
||||
.. Miscellaneous
|
||||
.. Functions
|
||||
.. System variables
|
||||
.. File name completion
|
||||
-------------------------------------------------------------------------------
|
||||
=> THE VERY BASICS
|
||||
Notations: ^X means <Ctrl> and X. The <Meta> key is <Esc> on most systems.
|
||||
Exiting: ^G aborts almost any operation. ^X ^C will get you out of uEmacs.
|
||||
|
||||
A BUFFER is a named area containing a FILE being edited. Many buffers may
|
||||
be active at once. Many WINDOWS may be active at once on the screen. All
|
||||
windows may show different parts of the same buffer, or each may display a
|
||||
different one.
|
||||
-------------------------------------------------------------------------------
|
||||
=> CURSOR MOVEMENT
|
||||
Backward character .... ^B Forward character ..... ^F
|
||||
Previous word ......... Meta B Next word ............. Meta F
|
||||
Beginning of line ..... ^A End of line ........... ^E
|
||||
Previous line ......... ^P Next line ............. ^N
|
||||
Previous paragraph .... Meta P Next paragraph ........ Meta N
|
||||
Previous page ......... ^Z Next page ............. ^V
|
||||
Beginning of file ..... Meta < End of file ........... Meta >
|
||||
-------------------------------------------------------------------------------
|
||||
=> FILE COMMANDS
|
||||
Find file ............. ^X ^F Quick exit ............ Meta Z
|
||||
View file ............. ^X ^V Exit emacs ............ ^X ^C
|
||||
Insert file ........... ^X ^I
|
||||
Change file name ...... ^X N Filter buffer ......... ^X #
|
||||
Save file ............. ^X ^D
|
||||
Read file ............. ^X ^R
|
||||
Write file ............ ^X ^W Execute file .......... not bound
|
||||
-------------------------------------------------------------------------------
|
||||
=> MISCELLANEOUS CHARACTER COMMANDS
|
||||
Newline ............... ^M Transpose characters .. ^T
|
||||
Newline and indent .... ^J Trim line ............. ^X ^T
|
||||
Open line ............. ^O
|
||||
Handle tab ............ ^I Quote character ....... ^X Q
|
||||
Insert space .......... ^C
|
||||
Goto line ............. Meta G Abort command ......... ^G
|
||||
Goto matching fence ... Meta ^F
|
||||
-------------------------------------------------------------------------------
|
||||
=> MODE COMMANDS
|
||||
Add mode .............. ^X M Add global mode ....... Meta M
|
||||
Delete mode ........... ^X ^M Delete global mode .... Meta ^M
|
||||
OVER :: Overwrite, don't insert MAGIC :: Match patterns in search
|
||||
WRAP :: Automatic carriage return ^ $ Beginning and end of line
|
||||
VIEW :: View only, don't change . Any character \c Character c
|
||||
CMODE :: C program indenting c* Any number of character c
|
||||
EXACT :: Match case in search [ ] Character class
|
||||
-------------------------------------------------------------------------------
|
||||
=> KEYS AND COMMANDS
|
||||
Bind to key ........... Meta K Help .................. Meta ?
|
||||
Unbind key ............ Meta ^K Apropos ............... Meta A
|
||||
Describe key .......... ^X ? Abort command ......... ^G
|
||||
Describe bindings ..... not bound
|
||||
Meta prefix ........... Esc :: Although meta-prefix can be bound to
|
||||
Cntlx prefix .......... ^X :: some other key, no other command can
|
||||
Execute named command . Meta X :: be bound to Esc.
|
||||
-------------------------------------------------------------------------------
|
||||
=> DELETING AND INSERTING
|
||||
Delete previous character ^H Delete next character . ^D
|
||||
Delete previous word .. Meta ^H Delete next word ...... Meta D
|
||||
Kill to end of line ... ^K Set mark .............. Meta Space
|
||||
Kill region ........... ^W Yank .................. ^Y
|
||||
Kill paragraph ........ Meta ^W Exchange point and mark ^X ^X
|
||||
Delete blank lines .... ^X ^O :: A region is defined as the area between
|
||||
Copy region ........... Meta W :: the mark and the current position.
|
||||
-------------------------------------------------------------------------------
|
||||
=> FORMATTING
|
||||
Case word upper ....... Meta U Case word lower ....... Meta L
|
||||
Case region upper ..... ^X ^U Case region lower ..... ^X ^L
|
||||
Case word capitalize .. Meta C Trim line ............. ^X ^T
|
||||
Detab line ............ ^X ^A
|
||||
Set fill column ....... ^X F Entab line ............ ^X ^E
|
||||
Fill paragraph ........ Meta Q Change screen size .... Meta ^D
|
||||
Justify paragraph ..... Meta J Change screen width ... Meta ^T
|
||||
-------------------------------------------------------------------------------
|
||||
=> WINDOW COMMANDS
|
||||
Split current window .. ^X 2 Next window ........... ^X O
|
||||
Delete other windows .. ^X 1 Previous window ....... ^X P
|
||||
Delete window ......... ^X 0 Scroll next up ........ Meta ^Z
|
||||
Grow window ........... ^X Z Scroll next down ...... Meta ^V
|
||||
Shrink window ......... ^X ^Z Resize window ......... ^X W
|
||||
Move window up ........ ^X ^P Save window ........... not bound
|
||||
Move window down ...... ^X ^N Restore window ........ not bound
|
||||
-------------------------------------------------------------------------------
|
||||
=> BUFFER COMMANDS
|
||||
Next buffer ........... ^X X Buffer position ....... ^X =
|
||||
Select buffer ......... ^X B Unmark buffer ......... Meta ~
|
||||
List buffers .......... ^X ^B
|
||||
Delete buffer ......... ^X K Write message ......... not bound
|
||||
Name buffer ........... Meta ^N Clear message line .... not bound
|
||||
Filter buffer ......... ^X #
|
||||
Pipe command .......... ^X @ Execute buffer ........ not bound
|
||||
-------------------------------------------------------------------------------
|
||||
=> SEARCHING AND REPLACING
|
||||
Search forward ........ Meta S :: End string with Meta.
|
||||
Incremental search .... ^X S :: Search next ^X, stop Meta, cancel ^G.
|
||||
Search reverse ........ ^R
|
||||
Reverse incremental search Hunt forward .......... Alt-S
|
||||
....................... ^X R Hunt backward ......... Alt-R
|
||||
Replace string ........ Meta R
|
||||
Query replace string .. Meta ^R :: Yes/no Y/N, replace rest !, cancel ^G.
|
||||
-------------------------------------------------------------------------------
|
||||
=> ACCESSING THE OPERATING SYSTEM
|
||||
Quick exit ............ Meta Z :: Write out all changed buffers and exit.
|
||||
Exit emacs ............ ^X ^C :: Exit without automatic save.
|
||||
I shell ............... ^X C :: Start a new command processor.
|
||||
Shell command ......... ^X ! :: Execute one operating system command.
|
||||
Pipe command .......... ^X @ :: Pipe command results to a new buffer. *
|
||||
Filter buffer ......... ^X # :: Filter buffer through a program. *
|
||||
Execute program ....... ^X $ :: * Not under VMS.
|
||||
-------------------------------------------------------------------------------
|
||||
=> MACRO COMMANDS
|
||||
Begin macro ........... ^X (
|
||||
End macro ............. ^X )
|
||||
Execute macro ......... ^X E
|
||||
Store macro ........... not bound
|
||||
Execute macro nn ...... not bound
|
||||
Store procedure ....... not bound
|
||||
Execute procedure ..... Meta ^E
|
||||
-------------------------------------------------------------------------------
|
||||
=> MISCELLANEOUS
|
||||
Universal argument .... ^U Set mark .............. Meta Space
|
||||
Clear and redraw ...... ^L Exchange point and mark ^X ^X
|
||||
Redraw display ........ Meta ^L
|
||||
Execute named command . Meta X Insert string ......... not bound
|
||||
Execute command line .. not bound Overwrite string ...... not bound
|
||||
Set encryption key .... Meta E Wrap word ............. not bound
|
||||
Count words ........... Meta ^C Update screen ......... not bound
|
||||
-------------------------------------------------------------------------------
|
||||
=> SYSTEM VARIABLES
|
||||
Set ................... Meta ^A Current buffer name ... $cbufname
|
||||
Tabulator (4, 8)....... $tab Current file name ..... $cfname
|
||||
Screen resolution ..... $sres :: NORMAL, CGA, EGA, VGA
|
||||
Display commands ...... $discmd :: TRUE, FALSE
|
||||
Scrolling enabled ..... $scroll :: TRUE, FALSE, can only be reset
|
||||
Scrolling movement .... $jump :: # lines, default 1, 0 = 1/2 page
|
||||
Page overlap .......... $overlap :: # lines, default 0, 0 = 1/3 page
|
||||
-------------------------------------------------------------------------------
|
||||
=> FUNCTIONS
|
||||
&neg, &abs, &add, &sub, &tim, &div, &mod ... Arithmetic
|
||||
&equ, &les, &gre ........................... Arithmetic comparisons
|
||||
¬, &and, &or ............................ Logical
|
||||
&lef s len, &rig s pos, &mid s pos len ..... Substring
|
||||
&cat, &len, &upp, &low, &asc, &chr ......... Other string operations
|
||||
&seq, &sle, &sgr ........................... String comparisons
|
||||
&sin ....................................... String index
|
||||
-------------------------------------------------------------------------------
|
||||
=> FILE NAME COMPLETION
|
||||
|
||||
File name completion can be used with all file commands (find-file,
|
||||
view-file, ...) but it works only under UNIX and MS-DOS. It is invoked
|
||||
by a <Space> or <Tab>. If there exist more than one possible completions
|
||||
they are displayed one by one. If the file name contains wild card
|
||||
characters, the name is expanded instead of simple completion. Special
|
||||
characters can be entered verbatim by prefixing them with ^V (or ^Q).
|
||||
-------------------------------------------------------------------------------
|
29
emacs.lnk
Normal file
29
emacs.lnk
Normal file
@ -0,0 +1,29 @@
|
||||
ANSI.OBJ+
|
||||
BASIC.OBJ+
|
||||
BIND.OBJ+
|
||||
BUFFER.OBJ+
|
||||
CRYPT.OBJ+
|
||||
DISPLAY.OBJ+
|
||||
EVAL.OBJ+
|
||||
EXEC.OBJ+
|
||||
FILE.OBJ+
|
||||
FILEIO.OBJ+
|
||||
IBMPC.OBJ+
|
||||
INPUT.OBJ+
|
||||
ISEARCH.OBJ+
|
||||
LINE.OBJ+
|
||||
LOCK.OBJ+
|
||||
MAIN.OBJ+
|
||||
RANDOM.OBJ+
|
||||
REGION.OBJ+
|
||||
SEARCH.OBJ+
|
||||
SPAWN.OBJ+
|
||||
TCAP.OBJ+
|
||||
TERMIO.OBJ+
|
||||
VMSVT.OBJ+
|
||||
VT52.OBJ+
|
||||
WINDOW.OBJ+
|
||||
WORD.OBJ/E/STACK:20000
|
||||
EMACS.EXE/NOI/NOE
|
||||
NUL
|
||||
;
|
27
emacs.prj
Normal file
27
emacs.prj
Normal file
@ -0,0 +1,27 @@
|
||||
ANSI (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
BASIC (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
BIND (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
BUFFER (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
CRYPT (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
DISPLAY (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
EVAL (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
EXEC (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
FILE (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
FILEIO (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
IBMPC (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
INPUT (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
ISEARCH (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
LINE (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
LOCK (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
MAIN (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
PKLOCK (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
RANDOM (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
REGION (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
SEARCH (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
SPAWN (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
TCAP (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
TERMIO (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
VMSVT (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
VT52 (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
WINDOW (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
||||
WORD (EBIND.H EDEF.H EFUNC.H EPATH.H ESTRUCT.H EVAR.H)
|
285
emacs.rc
Normal file
285
emacs.rc
Normal file
@ -0,0 +1,285 @@
|
||||
; EMACS.RC / .emascrc
|
||||
;
|
||||
; Startup file for MicroEMACS 3.9 and uEmacs/PK 4.0
|
||||
; This file is executed every time the editor is entered.
|
||||
;
|
||||
; Modified by Petri Kutvonen, last edited September 1991.
|
||||
|
||||
set $discmd "FALSE"
|
||||
|
||||
; First, try to resolve if we are on a PC ... yes, this is a kludge
|
||||
|
||||
!if &seq $sres "NORMAL"
|
||||
set %system "OTHER"
|
||||
!else
|
||||
set %system "PC"
|
||||
!endif
|
||||
|
||||
!if &seq %system "PC"
|
||||
|
||||
; PC specific initialization
|
||||
|
||||
write-message "(Setting up)"
|
||||
|
||||
; Comment out or change this line if you want more than 25 lines,
|
||||
; other possible $sres values include EGA and VGA
|
||||
|
||||
set $sres "CGA"
|
||||
|
||||
; Uncomment next line if your old screen "snows"
|
||||
|
||||
;set $flicker "TRUE"
|
||||
|
||||
; If your screen "snows" you'll not like scrolling
|
||||
|
||||
!if &seq $flicker "TRUE"
|
||||
set $scroll "FALSE"
|
||||
!endif
|
||||
|
||||
; Function keys (unshifted)
|
||||
; f1 f2 f3 f4 f5 f6 f7 f8 f9 f10
|
||||
; FN; FN< FN= FN> FN? FN@ FNA FNB FNC FND
|
||||
|
||||
bind-to-key help FN;
|
||||
bind-to-key exit-emacs FND
|
||||
|
||||
; Function keys (shifted)
|
||||
; F1 F2 F3 F4 F5 F6 F7 F8 F9 F10
|
||||
; FNT FNU FNV FNW FNX FNY FNZ FN[ FN\ FN]
|
||||
|
||||
; Other special keys (unshifted)
|
||||
; Home End Ins Del PgUp PgDn
|
||||
; FNG FNO FNR FNS FNI FNQ
|
||||
|
||||
; Some common Alt-keys
|
||||
; Alt-X Alt-Z Alt-C Alt-F Alt-O
|
||||
; FN- FN, FN. FN! FN^X
|
||||
|
||||
bind-to-key exit-emacs FN-
|
||||
bind-to-key quick-exit FN,
|
||||
bind-to-key i-shell FN.
|
||||
bind-to-key find-file FN!
|
||||
bind-to-key view-file FN/
|
||||
bind-to-key next-window FN^X
|
||||
|
||||
; Set screen colors
|
||||
|
||||
; You can define a DOS environment variable EMACS_BW (any value)
|
||||
; if you don't like colors, e.g. if you have a LCD screen
|
||||
|
||||
!if &seq &env "EMACS_BW" ""
|
||||
add-global-mode "blue"
|
||||
add-global-mode "HIGH"
|
||||
!endif
|
||||
|
||||
!endif
|
||||
|
||||
; Help facility
|
||||
|
||||
40 store-macro
|
||||
set $discmd "FALSE"
|
||||
!if ¬ &seq $cbufname "emacs.hlp"
|
||||
write-message "(Loading Help)"
|
||||
!force help
|
||||
!force 8 resize-window
|
||||
!if &seq %system "PC"
|
||||
!if &seq &env "EMACS_BW" ""
|
||||
add-mode "red"
|
||||
!endif
|
||||
bind-to-key execute-macro-38 FNI
|
||||
bind-to-key execute-macro-37 FNQ
|
||||
!else
|
||||
bind-to-key execute-macro-38 FN5
|
||||
bind-to-key execute-macro-37 FN6
|
||||
!endif
|
||||
beginning-of-line
|
||||
2 forward-character
|
||||
1 redraw-display
|
||||
save-window
|
||||
!if &seq %system "PC"
|
||||
set %hlpupdn "<PgUp> / <PgDn>"
|
||||
set %hlphelp "<F1>"
|
||||
!else
|
||||
set %hlpupdn "<Prev Scrn> / <Next Scrn>"
|
||||
set %hlphelp "<Help>"
|
||||
!endif
|
||||
execute-macro-39
|
||||
!else
|
||||
set %hlpcode &lef $line 2
|
||||
!if &seq %hlpcode ".."
|
||||
set %hlptopic &mid $line 4 99
|
||||
end-of-line
|
||||
!force search-forward %hlptopic
|
||||
beginning-of-line
|
||||
2 forward-character
|
||||
1 redraw-display
|
||||
execute-macro-39
|
||||
!else
|
||||
!if &seq %system "PC"
|
||||
bind-to-key previous-page FNI
|
||||
bind-to-key next-page FNQ
|
||||
!else
|
||||
bind-to-key previous-page FN5
|
||||
bind-to-key next-page FN6
|
||||
!endif
|
||||
!force restore-window
|
||||
!force delete-window
|
||||
clear-message-line
|
||||
!endif
|
||||
!endif
|
||||
set $discmd "TRUE"
|
||||
!endm
|
||||
|
||||
bind-to-key execute-macro-40 M-?
|
||||
!if &seq %system "PC"
|
||||
bind-to-key execute-macro-40 FN;
|
||||
!else
|
||||
bind-to-key execute-macro-40 FNh
|
||||
!endif
|
||||
|
||||
; Help on Help
|
||||
|
||||
39 store-macro
|
||||
!if &seq &rig $line 5 "INDEX"
|
||||
write-message &cat "Select topic from list and press " %hlphelp
|
||||
!else
|
||||
write-message &cat "Use " &cat %hlpupdn &cat " to scan help file -- " &cat %hlphelp " to toggle help window"
|
||||
!endif
|
||||
!endm
|
||||
|
||||
; Previous help page
|
||||
|
||||
38 store-macro
|
||||
!if &seq $cbufname "emacs.hlp"
|
||||
beginning-of-line
|
||||
!force search-reverse "=>"
|
||||
2 forward-character
|
||||
1 redraw-display
|
||||
execute-macro-39
|
||||
!else
|
||||
previous-page
|
||||
!endif
|
||||
!endm
|
||||
|
||||
; Next help page
|
||||
|
||||
37 store-macro
|
||||
!if &seq $cbufname "emacs.hlp"
|
||||
beginning-of-line
|
||||
2 forward-character
|
||||
!force search-forward "=>"
|
||||
1 redraw-display
|
||||
execute-macro-39
|
||||
!else
|
||||
next-page
|
||||
!endif
|
||||
!endm
|
||||
|
||||
; Set up auto CMODE
|
||||
|
||||
36 store-macro
|
||||
!if &seq &mid $cfname 1 7 "/tmp/Re"
|
||||
add-mode "wrap"
|
||||
!return
|
||||
!endif
|
||||
!if &gre &sin $cfname "/.ed" 0
|
||||
add-mode "wrap"
|
||||
!return
|
||||
!endif
|
||||
!if &gre &sin $cfname "/.let" 0
|
||||
add-mode "wrap"
|
||||
!return
|
||||
!endif
|
||||
!if &gre &sin $cfname "/.art" 0
|
||||
add-mode "wrap"
|
||||
!return
|
||||
!endif
|
||||
!if &gre &sin $cfname "/nn." 0
|
||||
add-mode "wrap"
|
||||
!return
|
||||
!endif
|
||||
set %rctmp &sin $cfname "."
|
||||
!if &equ %rctmp 0
|
||||
!return
|
||||
!endif
|
||||
set %rctmp &mid $cfname &add %rctmp 1 5
|
||||
!if &or &seq %rctmp "c" &seq %rctmp "h"
|
||||
add-mode "cmode"
|
||||
!endif
|
||||
!if &or &seq %rctmp "txt" &or &seq %rctmp "doc" &or &seq %rctmp "tmp" &seq %rctmp "tex"
|
||||
add-mode "wrap"
|
||||
!endif
|
||||
|
||||
!endm
|
||||
|
||||
bind-to-key execute-macro-36 M-FNR
|
||||
|
||||
; Setup for ASCII {|}[\] to ISO Latin-1 translation
|
||||
|
||||
21 store-macro
|
||||
insert-string "ä"
|
||||
!endm
|
||||
22 store-macro
|
||||
insert-string "ö"
|
||||
!endm
|
||||
23 store-macro
|
||||
insert-string "å"
|
||||
!endm
|
||||
24 store-macro
|
||||
insert-string "Ä"
|
||||
!endm
|
||||
25 store-macro
|
||||
insert-string "Ö"
|
||||
!endm
|
||||
26 store-macro
|
||||
insert-string "Å"
|
||||
!endm
|
||||
|
||||
27 store-macro
|
||||
bind-to-key execute-macro-21 {
|
||||
bind-to-key execute-macro-22 |
|
||||
bind-to-key execute-macro-23 }
|
||||
bind-to-key execute-macro-24 [
|
||||
bind-to-key execute-macro-25 \
|
||||
bind-to-key execute-macro-26 ]
|
||||
write-message "ISO Latin-1 äöåÄÖÅ"
|
||||
!endm
|
||||
|
||||
28 store-macro
|
||||
unbind-key {
|
||||
unbind-key |
|
||||
unbind-key }
|
||||
unbind-key [
|
||||
unbind-key \
|
||||
unbind-key ]
|
||||
write-message "ASCII {|}[\]"
|
||||
!endm
|
||||
|
||||
bind-to-key execute-macro-27 ^X[
|
||||
bind-to-key execute-macro-28 ^X]
|
||||
|
||||
; Make cut-paste easier in window systems
|
||||
|
||||
bind-to-key newline ^J
|
||||
|
||||
; uEmacs/PK specific initialization
|
||||
|
||||
!if &seq $progname "uEmacs/PK"
|
||||
|
||||
; Don't scroll on a Sun
|
||||
|
||||
!if &or &seq $TERM "sun" &seq $TERM "sun-cmd"
|
||||
set $scroll "FALSE"
|
||||
!endif
|
||||
|
||||
; Execute local initialization files
|
||||
|
||||
!if &seq %system "PC"
|
||||
!force execute-file "EM.RC"
|
||||
!else
|
||||
!force execute-file &cat $HOME "/.emrc"
|
||||
!force execute-file ".emrc"
|
||||
!endif
|
||||
!endif
|
||||
|
||||
set $discmd "TRUE"
|
53
epath.h
Normal file
53
epath.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* EPATH.H
|
||||
*
|
||||
* This file contains certain info needed to locate the
|
||||
* initialization (etc) files on a system dependent basis
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
/* possible names and paths of help files under different OSs */
|
||||
|
||||
char *pathname[] =
|
||||
|
||||
#if MSDOS
|
||||
{
|
||||
"emacs.rc",
|
||||
"emacs.hlp",
|
||||
"\\sys\\public\\",
|
||||
"\\usr\\bin\\",
|
||||
"\\bin\\",
|
||||
"\\",
|
||||
""
|
||||
};
|
||||
#endif
|
||||
|
||||
#if V7 | BSD | USG
|
||||
{
|
||||
".emacsrc",
|
||||
"emacs.hlp",
|
||||
#if PKCODE
|
||||
"/usr/global/lib/",
|
||||
"/usr/local/bin/",
|
||||
"/usr/local/lib/",
|
||||
#endif
|
||||
"/usr/local/",
|
||||
"/usr/lib/",
|
||||
""
|
||||
};
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
{
|
||||
"emacs.rc",
|
||||
"emacs.hlp",
|
||||
"",
|
||||
#if PKCODE
|
||||
"sys$login:",
|
||||
"emacs_dir:",
|
||||
#endif
|
||||
"sys$sysdevice:[vmstools]"
|
||||
};
|
||||
#endif
|
||||
|
||||
#define NPNAMES (sizeof(pathname)/sizeof(char *))
|
731
estruct.h
Normal file
731
estruct.h
Normal file
@ -0,0 +1,731 @@
|
||||
/* ESTRUCT.H
|
||||
*
|
||||
* Structure and preprocessor defines
|
||||
*
|
||||
* written by Dave G. Conroy
|
||||
* modified by Steve Wilhite, George Jones
|
||||
* substantially modified by Daniel Lawrence
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#define MAXCOL 500
|
||||
#define MAXROW 500
|
||||
|
||||
#ifdef MSDOS
|
||||
#undef MSDOS
|
||||
#endif
|
||||
#ifdef EGA
|
||||
#undef EGA
|
||||
#endif
|
||||
#ifdef CTRLZ
|
||||
#undef CTRLZ
|
||||
#endif
|
||||
|
||||
/* Program Identification.....
|
||||
|
||||
PROGNAME should always be MicroEMACS for a distibrution
|
||||
unmodified version. People using MicroEMACS as a shell
|
||||
for other products should change this to reflect their
|
||||
product. Macros can query this via the $progname variable
|
||||
|
||||
this version in called uEmacs/PK
|
||||
*/
|
||||
|
||||
#define PROGNAME "uEmacs/PK"
|
||||
#define VERSION "4.0.15"
|
||||
|
||||
/* Machine/OS definitions */
|
||||
|
||||
#if defined(AUTOCONF) || defined(MSDOS) || defined(BSD) || defined(SYSV) || defined(VMS)
|
||||
|
||||
/* make an intelligent guess about the target system */
|
||||
|
||||
#if defined(__TURBOC__)
|
||||
#define MSDOS 1 /* MS/PC DOS 3.1-4.0 with Turbo C 2.0 */
|
||||
#else
|
||||
#define MSDOS 0
|
||||
#endif
|
||||
|
||||
#if defined(BSD) || defined(sun) || defined(ultrix) || (defined(vax) && defined(unix)) || defined(ultrix) || defined(__osf__)
|
||||
#ifndef BSD
|
||||
#define BSD 1 /* Berkeley UNIX */
|
||||
#endif
|
||||
#else
|
||||
#define BSD 0
|
||||
#endif
|
||||
|
||||
#if defined(SVR4) || defined(__linux__) /* ex. SunOS 5.3 */
|
||||
#define SVR4 1
|
||||
#define SYSV 1
|
||||
#undef BSD
|
||||
#endif
|
||||
|
||||
#if defined(SYSV) || defined(u3b2) || defined(_AIX) || (defined(i386) && defined(unix)) || defined(__hpux)
|
||||
#define USG 1 /* System V UNIX */
|
||||
#else
|
||||
#define USG 0
|
||||
#endif
|
||||
|
||||
#if defined(VMS) || (defined(vax) && ! defined(unix))
|
||||
#define VMS 1 /* VAX/VMS */
|
||||
#else
|
||||
#define VMS 0
|
||||
#endif
|
||||
|
||||
#define V7 0 /* no more */
|
||||
|
||||
#else
|
||||
|
||||
#define MSDOS 1 /* MS-DOS */
|
||||
#define V7 0 /* V7 UNIX or Coherent or BSD4.2*/
|
||||
#define BSD 0 /* UNIX BSD 4.2 and ULTRIX */
|
||||
#define USG 0 /* UNIX system V */
|
||||
#define VMS 0 /* VAX/VMS */
|
||||
|
||||
#endif /*autoconf */
|
||||
|
||||
#ifndef AUTOCONF
|
||||
|
||||
/* Compiler definitions */
|
||||
#define UNIX 0 /* a random UNIX compiler */
|
||||
#define MSC 0 /* MicroSoft C compiler, versions 3 up */
|
||||
#define TURBO 1 /* Turbo C/MSDOS */
|
||||
|
||||
#else
|
||||
|
||||
#define UNIX (V7 | BSD | USG)
|
||||
#define MSC 0
|
||||
#define TURBO MSDOS
|
||||
|
||||
#endif /*autoconf */
|
||||
|
||||
/* Debugging options */
|
||||
|
||||
#define RAMSIZE 0 /* dynamic RAM memory usage tracking */
|
||||
#define RAMSHOW 0 /* auto dynamic RAM reporting */
|
||||
|
||||
#ifndef AUTOCONF
|
||||
|
||||
/* Special keyboard definitions */
|
||||
|
||||
#define VT220 0 /* Use keypad escapes P.K. */
|
||||
#define VT100 0 /* Handle VT100 style keypad. */
|
||||
|
||||
/* Terminal Output definitions */
|
||||
|
||||
#define ANSI 0 /* ANSI escape sequences */
|
||||
#define VMSVT 0 /* various VMS terminal entries */
|
||||
#define VT52 0 /* VT52 terminal (Zenith). */
|
||||
#define TERMCAP 0 /* Use TERMCAP */
|
||||
#define IBMPC 1 /* IBM-PC CGA/MONO/EGA driver */
|
||||
|
||||
#else
|
||||
|
||||
#define VT220 (UNIX | VMS)
|
||||
#define VT100 0
|
||||
|
||||
#define ANSI 0
|
||||
#define VMSVT VMS
|
||||
#define VT52 0
|
||||
#define TERMCAP UNIX
|
||||
#define IBMPC MSDOS
|
||||
|
||||
#endif /*autoconf */
|
||||
|
||||
/* Configuration options */
|
||||
|
||||
#define CVMVAS 1 /* arguments to page forward/back in pages */
|
||||
#define CLRMSG 0 /* space clears the message line with no insert */
|
||||
#define CFENCE 1 /* fench matching in CMODE */
|
||||
#define TYPEAH 1 /* type ahead causes update to be skipped */
|
||||
#define DEBUGM 1 /* $debug triggers macro debugging */
|
||||
#define VISMAC 0 /* update display during keyboard macros */
|
||||
#define CTRLZ 0 /* add a ^Z at end of files under MSDOS only */
|
||||
#define ADDCR 0 /* ajout d'un CR en fin de chaque ligne (ST520) */
|
||||
#define NBRACE 1 /* new style brace matching command */
|
||||
#define REVSTA 1 /* Status line appears in reverse video */
|
||||
|
||||
#ifndef AUTOCONF
|
||||
|
||||
#define COLOR 1 /* color commands and windows */
|
||||
#define FILOCK 0 /* file locking under unix BSD 4.2 */
|
||||
|
||||
#else
|
||||
|
||||
#define COLOR MSDOS
|
||||
#ifdef SVR4
|
||||
#define FILOCK 1
|
||||
#else
|
||||
#define FILOCK BSD
|
||||
#endif
|
||||
|
||||
#endif /* autoconf */
|
||||
|
||||
#define ISRCH 1 /* Incremental searches like ITS EMACS */
|
||||
#define WORDPRO 1 /* Advanced word processing features */
|
||||
#define FNLABEL 0 /* function key label code [HP150] */
|
||||
#define APROP 1 /* Add code for Apropos command */
|
||||
#define CRYPT 1 /* file encryption enabled? */
|
||||
#define MAGIC 1 /* include regular expression matching? */
|
||||
#define AEDIT 1 /* advanced editing options: en/detabbing */
|
||||
#define PROC 1 /* named procedures */
|
||||
#define CLEAN 0 /* de-alloc memory on exit */
|
||||
#define CALLED 0 /* is emacs a called subroutine? or stand alone */
|
||||
|
||||
#define ASCII 1 /* always using ASCII char sequences for now */
|
||||
#define EBCDIC 0 /* later IBM mainfraim versions will use EBCDIC */
|
||||
|
||||
#ifndef AUTOCONF
|
||||
|
||||
#define XONXOFF 0 /* don't disable XON-XOFF flow control P.K. */
|
||||
#define NATIONL 0 /* interprete [,],\,{,},| as characters P.K. */
|
||||
|
||||
#else
|
||||
|
||||
#define XONXOFF (UNIX | VMS)
|
||||
#define NATIONL (UNIX | VMS)
|
||||
|
||||
#endif /* autoconf */
|
||||
|
||||
#define PKCODE 1 /* include my extensions P.K., define always */
|
||||
#define IBMCHR MSDOS /* use IBM PC character set P.K. */
|
||||
#define SCROLLCODE 1 /* scrolling code P.K. */
|
||||
|
||||
/* System dependant library redefinitions, structures and includes */
|
||||
|
||||
#if TURBO
|
||||
#include <dos.h>
|
||||
#include <mem.h>
|
||||
#undef peek
|
||||
#undef poke
|
||||
#define peek(a,b,c,d) movedata(a,b,FP_SEG(c),FP_OFF(c),d)
|
||||
#define poke(a,b,c,d) movedata(FP_SEG(c),FP_OFF(c),a,b,d)
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
#define atoi xatoi
|
||||
#define abs xabs
|
||||
#define getname xgetname
|
||||
#endif
|
||||
|
||||
#if MSDOS & MSC
|
||||
#include <dos.h>
|
||||
#include <memory.h>
|
||||
#define peek(a,b,c,d) movedata(a,b,FP_SEG(c),FP_OFF(c),d)
|
||||
#define poke(a,b,c,d) movedata(FP_SEG(c),FP_OFF(c),a,b,d)
|
||||
#define movmem(a, b, c) memcpy(b, a, c)
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
#define unlink(a) delete(a)
|
||||
#endif
|
||||
|
||||
/* define some ability flags */
|
||||
|
||||
#if IBMPC
|
||||
#define MEMMAP 1
|
||||
#else
|
||||
#define MEMMAP 0
|
||||
#endif
|
||||
|
||||
#if MSDOS | V7 | USG | BSD
|
||||
#define ENVFUNC 1
|
||||
#else
|
||||
#define ENVFUNC 0
|
||||
#endif
|
||||
|
||||
/* Emacs global flag bit definitions (for gflags) */
|
||||
|
||||
#define GFREAD 1
|
||||
|
||||
/* internal constants */
|
||||
|
||||
#define NBINDS 256 /* max # of bound keys */
|
||||
#define NFILEN 80 /* # of bytes, file name */
|
||||
#define NBUFN 16 /* # of bytes, buffer name */
|
||||
#define NLINE 256 /* # of bytes, input line */
|
||||
#define NSTRING 128 /* # of bytes, string buffers */
|
||||
#define NKBDM 256 /* # of strokes, keyboard macro */
|
||||
#define NPAT 128 /* # of bytes, pattern */
|
||||
#define HUGE 1000 /* Huge number */
|
||||
#define NLOCKS 100 /* max # of file locks active */
|
||||
#define NCOLORS 8 /* number of supported colors */
|
||||
#define KBLOCK 250 /* sizeof kill buffer chunks */
|
||||
#define NBLOCK 16 /* line block chunk size */
|
||||
#define NVSIZE 10 /* max #chars in a var name */
|
||||
|
||||
#define CONTROL 0x0100 /* Control flag, or'ed in */
|
||||
#define META 0x0200 /* Meta flag, or'ed in */
|
||||
#define CTLX 0x0400 /* ^X flag, or'ed in */
|
||||
#define SPEC 0x0800 /* special key (function keys) */
|
||||
|
||||
#if PKCODE
|
||||
#define MAXNLINE 100000 /* max lines from one file */
|
||||
#endif
|
||||
|
||||
#ifdef FALSE
|
||||
#undef FALSE
|
||||
#endif
|
||||
#ifdef TRUE
|
||||
#undef TRUE
|
||||
#endif
|
||||
|
||||
#define FALSE 0 /* False, no, bad, etc. */
|
||||
#define TRUE 1 /* True, yes, good, etc. */
|
||||
#define ABORT 2 /* Death, ^G, abort, etc. */
|
||||
#define FAILED 3 /* not-quite fatal false return */
|
||||
|
||||
#define STOP 0 /* keyboard macro not in use */
|
||||
#define PLAY 1 /* playing */
|
||||
#define RECORD 2 /* recording */
|
||||
|
||||
/* Directive definitions */
|
||||
|
||||
#define DIF 0
|
||||
#define DELSE 1
|
||||
#define DENDIF 2
|
||||
#define DGOTO 3
|
||||
#define DRETURN 4
|
||||
#define DENDM 5
|
||||
#define DWHILE 6
|
||||
#define DENDWHILE 7
|
||||
#define DBREAK 8
|
||||
#define DFORCE 9
|
||||
|
||||
#define NUMDIRS 10
|
||||
|
||||
/*
|
||||
* PTBEG, PTEND, FORWARD, and REVERSE are all toggle-able values for
|
||||
* the scan routines.
|
||||
*/
|
||||
#define PTBEG 0 /* Leave the point at the beginning on search */
|
||||
#define PTEND 1 /* Leave the point at the end on search */
|
||||
#define FORWARD 0 /* forward direction */
|
||||
#define REVERSE 1 /* backwards direction */
|
||||
|
||||
#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 FIOMEM 4 /* File I/O, out of memory */
|
||||
#define FIOFUN 5 /* File I/O, eod of file/bad line*/
|
||||
|
||||
#define CFCPCN 0x0001 /* Last command was C-P, C-N */
|
||||
#define CFKILL 0x0002 /* Last command was a kill */
|
||||
|
||||
#define BELL 0x07 /* a bell character */
|
||||
#define TAB 0x09 /* a tab character */
|
||||
|
||||
#if V7 | USG | BSD
|
||||
#define PATHCHR ':'
|
||||
#else
|
||||
#define PATHCHR ';'
|
||||
#endif
|
||||
|
||||
#define INTWIDTH sizeof(int) * 3
|
||||
|
||||
/* Macro argument token types */
|
||||
|
||||
#define TKNUL 0 /* end-of-string */
|
||||
#define TKARG 1 /* interactive argument */
|
||||
#define TKBUF 2 /* buffer argument */
|
||||
#define TKVAR 3 /* user variables */
|
||||
#define TKENV 4 /* environment variables */
|
||||
#define TKFUN 5 /* function.... */
|
||||
#define TKDIR 6 /* directive */
|
||||
#define TKLBL 7 /* line label */
|
||||
#define TKLIT 8 /* numeric literal */
|
||||
#define TKSTR 9 /* quoted string literal */
|
||||
#define TKCMD 10 /* command name */
|
||||
|
||||
/* Internal defined functions */
|
||||
|
||||
#define nextab(a) (a & ~tabmask) + (tabmask+1)
|
||||
#ifdef abs
|
||||
#undef abs
|
||||
#endif
|
||||
|
||||
/* DIFCASE represents the integer difference between upper
|
||||
and lower case letters. It is an xor-able value, which is
|
||||
fortunate, since the relative positions of upper to lower
|
||||
case letters is the opposite of ascii in ebcdic.
|
||||
*/
|
||||
|
||||
#ifdef islower
|
||||
#undef islower
|
||||
#endif
|
||||
|
||||
#if PKCODE
|
||||
#ifdef isupper
|
||||
#undef isupper
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ASCII
|
||||
|
||||
#define DIFCASE 0x20
|
||||
|
||||
#if NATIONL
|
||||
#define LASTUL ']'
|
||||
#define LASTLL '}'
|
||||
#else
|
||||
#define LASTUL 'Z'
|
||||
#define LASTLL 'z'
|
||||
#endif
|
||||
|
||||
#if IBMCHR
|
||||
|
||||
#define isletter(c) (('a' <= c && LASTLL >= c) || ('A' <= c && LASTUL >= c) || (128<=c && c<=167))
|
||||
#define islower(c) (('a' <= c && LASTLL >= c))
|
||||
#define isupper(c) (('A' <= c && LASTUL >= c))
|
||||
|
||||
#else
|
||||
|
||||
#define isletter(c) isxletter((0xFF & (c)))
|
||||
#define islower(c) isxlower((0xFF & (c)))
|
||||
#define isupper(c) isxupper((0xFF & (c)))
|
||||
|
||||
#define isxletter(c) (('a' <= c && LASTLL >= c) || ('A' <= c && LASTUL >= c) || (192<=c && c<=255))
|
||||
#define isxlower(c) (('a' <= c && LASTLL >= c) || (224 <= c && 252 >= c))
|
||||
#define isxupper(c) (('A' <= c && LASTUL >= c) || (192 <= c && 220 >= c))
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if EBCDIC
|
||||
|
||||
#define DIFCASE 0x40
|
||||
#define isletter(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c) || ('A' <= c && 'I' >= c) || ('J' <= c && 'R' >= c) || ('S' <= c && 'Z' >= c))
|
||||
#define islower(c) (('a' <= c && 'i' >= c) || ('j' <= c && 'r' >= c) || ('s' <= c && 'z' >= c))
|
||||
#if PKCODE
|
||||
#define isupper(c) (('A' <= c && 'I' >= c) || ('J' <= c && 'R' >= c) || ('S' <= c && 'Z' >= c))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Dynamic RAM tracking and reporting redefinitions */
|
||||
|
||||
#if RAMSIZE
|
||||
#define malloc allocate
|
||||
#define free release
|
||||
#endif
|
||||
|
||||
/* De-allocate memory always on exit (if the operating system or
|
||||
main program can not
|
||||
*/
|
||||
|
||||
#if CLEAN
|
||||
#define exit(a) cexit(a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
#if COLOR
|
||||
char w_fcolor; /* current forground color */
|
||||
char w_bcolor; /* current background color */
|
||||
#endif
|
||||
} 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. */
|
||||
#define WFCOLR 0x20 /* Needs a color change */
|
||||
|
||||
#if SCROLLCODE
|
||||
#define WFKILLS 0x40 /* something was deleted */
|
||||
#define WFINS 0x80 /* something was inserted */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* 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".
|
||||
* Buffers may be "Inactive" which means the files associated with them
|
||||
* have not been read in yet. These get read in at "use buffer" time.
|
||||
*/
|
||||
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_active; /* window activated flag */
|
||||
char b_nwnd; /* Count of windows on buffer */
|
||||
char b_flag; /* Flags */
|
||||
int b_mode; /* editor mode of this buffer */
|
||||
char b_fname[NFILEN]; /* File name */
|
||||
char b_bname[NBUFN]; /* Buffer name */
|
||||
#if CRYPT
|
||||
char b_key[NPAT]; /* current encrypted key */
|
||||
#endif
|
||||
} BUFFER;
|
||||
|
||||
#define BFINVS 0x01 /* Internal invisable buffer */
|
||||
#define BFCHG 0x02 /* Changed since last write */
|
||||
#define BFTRUNC 0x04 /* buffer was truncated when read */
|
||||
|
||||
/* mode flags */
|
||||
#define NUMMODES 9 /* # of defined modes */
|
||||
|
||||
#define MDWRAP 0x0001 /* word wrap */
|
||||
#define MDCMOD 0x0002 /* C indentation and fence match*/
|
||||
#define MDSPELL 0x0004 /* spell error parcing */
|
||||
#define MDEXACT 0x0008 /* Exact matching for searches */
|
||||
#define MDVIEW 0x0010 /* read-only buffer */
|
||||
#define MDOVER 0x0020 /* overwrite mode */
|
||||
#define MDMAGIC 0x0040 /* regular expresions in search */
|
||||
#define MDCRYPT 0x0080 /* encrytion mode active */
|
||||
#define MDASAVE 0x0100 /* auto-save mode */
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
long 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_mrow; /* max number of rows allowable */
|
||||
short t_nrow; /* current number of rows used */
|
||||
short t_mcol; /* max Number of columns. */
|
||||
short t_ncol; /* current Number of columns. */
|
||||
short t_margin; /* min margin for extended lines*/
|
||||
short t_scrsiz; /* size of scroll region " */
|
||||
int t_pause; /* # times thru update to pause */
|
||||
int (*t_open)(); /* Open terminal at the start. */
|
||||
int (*t_close)(); /* Close terminal at end. */
|
||||
int (*t_kopen)(); /* Open keyboard */
|
||||
int (*t_kclose)(); /* close keyboard */
|
||||
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. */
|
||||
int (*t_rev)(); /* set reverse video state */
|
||||
int (*t_rez)(); /* change screen resolution */
|
||||
#if COLOR
|
||||
int (*t_setfor)(); /* set forground color */
|
||||
int (*t_setback)(); /* set background color */
|
||||
#endif
|
||||
#if SCROLLCODE
|
||||
int (*t_scroll)(); /* scroll a region of the screen */
|
||||
#endif
|
||||
} TERM;
|
||||
|
||||
/* TEMPORARY macros for terminal I/O (to be placed in a machine
|
||||
dependant place later) */
|
||||
|
||||
#define TTopen (*term.t_open)
|
||||
#define TTclose (*term.t_close)
|
||||
#define TTkopen (*term.t_kopen)
|
||||
#define TTkclose (*term.t_kclose)
|
||||
#define TTgetc (*term.t_getchar)
|
||||
#define TTputc (*term.t_putchar)
|
||||
#define TTflush (*term.t_flush)
|
||||
#define TTmove (*term.t_move)
|
||||
#define TTeeol (*term.t_eeol)
|
||||
#define TTeeop (*term.t_eeop)
|
||||
#define TTbeep (*term.t_beep)
|
||||
#define TTrev (*term.t_rev)
|
||||
#define TTrez (*term.t_rez)
|
||||
#if COLOR
|
||||
#define TTforg (*term.t_setfor)
|
||||
#define TTbacg (*term.t_setback)
|
||||
#endif
|
||||
|
||||
/* structure for the table of initial key bindings */
|
||||
|
||||
typedef struct {
|
||||
short k_code; /* Key code */
|
||||
int (*k_fp)(); /* Routine to handle it */
|
||||
} KEYTAB;
|
||||
|
||||
/* structure for the name binding table */
|
||||
|
||||
typedef struct {
|
||||
char *n_name; /* name of function key */
|
||||
int (*n_func)(); /* function name is bound to */
|
||||
} NBIND;
|
||||
|
||||
/* The editor holds deleted text chunks in the KILL buffer. The
|
||||
kill buffer is logically a stream of ascii characters, however
|
||||
due to its unpredicatable size, it gets implemented as a linked
|
||||
list of chunks. (The d_ prefix is for "deleted" text, as k_
|
||||
was taken up by the keycode structure)
|
||||
*/
|
||||
|
||||
typedef struct KILL {
|
||||
struct KILL *d_next; /* link to next chunk, NULL if last */
|
||||
char d_chunk[KBLOCK]; /* deleted text */
|
||||
} KILL;
|
||||
|
||||
/* When emacs' command interpetor needs to get a variable's name,
|
||||
rather than it's value, it is passed back as a VDESC variable
|
||||
description structure. The v_num field is a index into the
|
||||
appropriate variable table.
|
||||
*/
|
||||
|
||||
typedef struct VDESC {
|
||||
int v_type; /* type of variable */
|
||||
int v_num; /* ordinal pointer to variable in list */
|
||||
} VDESC;
|
||||
|
||||
/* The !WHILE directive in the execution language needs to
|
||||
stack references to pending whiles. These are stored linked
|
||||
to each currently open procedure via a linked list of
|
||||
the following structure
|
||||
*/
|
||||
|
||||
typedef struct WHBLOCK {
|
||||
LINE *w_begin; /* ptr to !while statement */
|
||||
LINE *w_end; /* ptr to the !endwhile statement*/
|
||||
int w_type; /* block type */
|
||||
struct WHBLOCK *w_next; /* next while */
|
||||
} WHBLOCK;
|
||||
|
||||
#define BTWHILE 1
|
||||
#define BTBREAK 2
|
||||
|
||||
/*
|
||||
* Incremental search defines.
|
||||
*/
|
||||
#if ISRCH
|
||||
|
||||
#define CMDBUFLEN 256 /* Length of our command buffer */
|
||||
|
||||
#define IS_ABORT 0x07 /* Abort the isearch */
|
||||
#define IS_BACKSP 0x08 /* Delete previous char */
|
||||
#define IS_TAB 0x09 /* Tab character (allowed search char) */
|
||||
#define IS_NEWLINE 0x0D /* New line from keyboard (Carriage return) */
|
||||
#define IS_QUOTE 0x11 /* Quote next character */
|
||||
#define IS_REVERSE 0x12 /* Search backward */
|
||||
#define IS_FORWARD 0x13 /* Search forward */
|
||||
#define IS_VMSQUOTE 0x16 /* VMS quote character */
|
||||
#define IS_VMSFORW 0x18 /* Search forward for VMS */
|
||||
#define IS_QUIT 0x1B /* Exit the search */
|
||||
#define IS_RUBOUT 0x7F /* Delete previous character */
|
||||
|
||||
/* IS_QUIT is no longer used, the variable metac is used instead */
|
||||
|
||||
#endif
|
||||
|
||||
#if MAGIC
|
||||
/*
|
||||
* Defines for the metacharacters in the regular expression
|
||||
* search routines.
|
||||
*/
|
||||
#define MCNIL 0 /* Like the '\0' for strings.*/
|
||||
#define LITCHAR 1 /* Literal character, or string.*/
|
||||
#define ANY 2
|
||||
#define CCL 3
|
||||
#define NCCL 4
|
||||
#define BOL 5
|
||||
#define EOL 6
|
||||
#define DITTO 7
|
||||
#define CLOSURE 256 /* An or-able value.*/
|
||||
#define MASKCL CLOSURE - 1
|
||||
|
||||
#define MC_ANY '.' /* 'Any' character (except newline).*/
|
||||
#define MC_CCL '[' /* Character class.*/
|
||||
#define MC_NCCL '^' /* Negate character class.*/
|
||||
#define MC_RCCL '-' /* Range in character class.*/
|
||||
#define MC_ECCL ']' /* End of character class.*/
|
||||
#define MC_BOL '^' /* Beginning of line.*/
|
||||
#define MC_EOL '$' /* End of line.*/
|
||||
#define MC_CLOSURE '*' /* Closure - does not extend past newline.*/
|
||||
#define MC_DITTO '&' /* Use matched string in replacement.*/
|
||||
#define MC_ESC '\\' /* Escape - suppress meta-meaning.*/
|
||||
|
||||
#define BIT(n) (1 << (n)) /* An integer with one bit set.*/
|
||||
#define CHCASE(c) ((c) ^ DIFCASE) /* Toggle the case of a letter.*/
|
||||
|
||||
/* HICHAR - 1 is the largest character we will deal with.
|
||||
* HIBYTE represents the number of bytes in the bitmap.
|
||||
*/
|
||||
#define HICHAR 256
|
||||
#define HIBYTE HICHAR >> 3
|
||||
|
||||
/* Typedefs that define the bitmap type for searching (BITMAP),
|
||||
* the meta-character structure for MAGIC mode searching (MC),
|
||||
* and the meta-character structure for MAGIC mode replacment (RMC).
|
||||
*/
|
||||
typedef char *BITMAP;
|
||||
|
||||
typedef struct {
|
||||
short int mc_type;
|
||||
union {
|
||||
int lchar;
|
||||
BITMAP cclmap;
|
||||
} u;
|
||||
} MC;
|
||||
|
||||
typedef struct {
|
||||
short int mc_type;
|
||||
char *rstr;
|
||||
} RMC;
|
||||
#endif
|
||||
|
879
eval.c
Normal file
879
eval.c
Normal file
@ -0,0 +1,879 @@
|
||||
/* EVAL.C
|
||||
*
|
||||
* Expression evaluation functions
|
||||
*
|
||||
* written 1986 by Daniel Lawrence
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
#include "evar.h"
|
||||
|
||||
varinit() /* initialize the user variable list */
|
||||
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i < MAXVARS; i++)
|
||||
uv[i].u_name[0] = 0;
|
||||
}
|
||||
|
||||
char *gtfun(fname) /* evaluate a function */
|
||||
|
||||
char *fname; /* name of function to evaluate */
|
||||
|
||||
{
|
||||
register int fnum; /* index to function to eval */
|
||||
register int status; /* return status */
|
||||
register char *tsp; /* temporary string pointer */
|
||||
char arg1[NSTRING]; /* value of first argument */
|
||||
char arg2[NSTRING]; /* value of second argument */
|
||||
char arg3[NSTRING]; /* value of third argument */
|
||||
static char result[2 * NSTRING]; /* string result */
|
||||
char *flook(); /* look file up on path */
|
||||
char *xlat(); /* translate a char string */
|
||||
#if ENVFUNC
|
||||
char *getenv(); /* get environment string */
|
||||
#endif
|
||||
|
||||
/* look the function up in the function table */
|
||||
fname[3] = 0; /* only first 3 chars significant */
|
||||
mklower(fname); /* and let it be upper or lower case */
|
||||
for (fnum = 0; fnum < NFUNCS; fnum++)
|
||||
if (strcmp(fname, funcs[fnum].f_name) == 0)
|
||||
break;
|
||||
|
||||
/* return errorm on a bad reference */
|
||||
if (fnum == NFUNCS)
|
||||
return(errorm);
|
||||
|
||||
/* if needed, retrieve the first argument */
|
||||
if (funcs[fnum].f_type >= MONAMIC) {
|
||||
if ((status = macarg(arg1)) != TRUE)
|
||||
return(errorm);
|
||||
|
||||
/* if needed, retrieve the second argument */
|
||||
if (funcs[fnum].f_type >= DYNAMIC) {
|
||||
if ((status = macarg(arg2)) != TRUE)
|
||||
return(errorm);
|
||||
|
||||
/* if needed, retrieve the third argument */
|
||||
if (funcs[fnum].f_type >= TRINAMIC)
|
||||
if ((status = macarg(arg3)) != TRUE)
|
||||
return(errorm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* and now evaluate it! */
|
||||
switch (fnum) {
|
||||
case UFADD: return(itoa(atoi(arg1) + atoi(arg2)));
|
||||
case UFSUB: return(itoa(atoi(arg1) - atoi(arg2)));
|
||||
case UFTIMES: return(itoa(atoi(arg1) * atoi(arg2)));
|
||||
case UFDIV: return(itoa(atoi(arg1) / atoi(arg2)));
|
||||
case UFMOD: return(itoa(atoi(arg1) % atoi(arg2)));
|
||||
case UFNEG: return(itoa(-atoi(arg1)));
|
||||
case UFCAT: strcpy(result, arg1);
|
||||
return(strcat(result, arg2));
|
||||
case UFLEFT: return(strncpy(result, arg1, atoi(arg2)));
|
||||
case UFRIGHT: return(strcpy(result,
|
||||
&arg1[(strlen(arg1) - atoi(arg2))]));
|
||||
case UFMID: return(strncpy(result, &arg1[atoi(arg2)-1],
|
||||
atoi(arg3)));
|
||||
case UFNOT: return(ltos(stol(arg1) == FALSE));
|
||||
case UFEQUAL: return(ltos(atoi(arg1) == atoi(arg2)));
|
||||
case UFLESS: return(ltos(atoi(arg1) < atoi(arg2)));
|
||||
case UFGREATER: return(ltos(atoi(arg1) > atoi(arg2)));
|
||||
case UFSEQUAL: return(ltos(strcmp(arg1, arg2) == 0));
|
||||
case UFSLESS: return(ltos(strcmp(arg1, arg2) < 0));
|
||||
case UFSGREAT: return(ltos(strcmp(arg1, arg2) > 0));
|
||||
case UFIND: return(strcpy(result, getval(arg1)));
|
||||
case UFAND: return(ltos(stol(arg1) && stol(arg2)));
|
||||
case UFOR: return(ltos(stol(arg1) || stol(arg2)));
|
||||
case UFLENGTH: return(itoa(strlen(arg1)));
|
||||
case UFUPPER: return(mkupper(arg1));
|
||||
case UFLOWER: return(mklower(arg1));
|
||||
case UFTRUTH: return(ltos(atoi(arg1) == 42));
|
||||
case UFASCII: return(itoa((int)arg1[0]));
|
||||
case UFCHR: result[0] = atoi(arg1);
|
||||
result[1] = 0;
|
||||
return(result);
|
||||
case UFGTKEY: result[0] = tgetc();
|
||||
result[1] = 0;
|
||||
return(result);
|
||||
case UFRND: return(itoa((ernd() % abs(atoi(arg1))) + 1));
|
||||
case UFABS: return(itoa(abs(atoi(arg1))));
|
||||
case UFSINDEX: return(itoa(sindex(arg1, arg2)));
|
||||
case UFENV:
|
||||
#if ENVFUNC
|
||||
tsp = getenv(arg1);
|
||||
return(tsp == NULL ? "" : tsp);
|
||||
#else
|
||||
return("");
|
||||
#endif
|
||||
case UFBIND: return(transbind(arg1));
|
||||
case UFEXIST: return(ltos(fexist(arg1)));
|
||||
case UFFIND:
|
||||
tsp = flook(arg1, TRUE);
|
||||
return(tsp == NULL ? "" : tsp);
|
||||
case UFBAND: return(itoa(atoi(arg1) & atoi(arg2)));
|
||||
case UFBOR: return(itoa(atoi(arg1) | atoi(arg2)));
|
||||
case UFBXOR: return(itoa(atoi(arg1) ^ atoi(arg2)));
|
||||
case UFBNOT: return(itoa(~atoi(arg1)));
|
||||
case UFXLATE: return(xlat(arg1, arg2, arg3));
|
||||
}
|
||||
|
||||
exit(-11); /* never should get here */
|
||||
}
|
||||
|
||||
char *gtusr(vname) /* look up a user var's value */
|
||||
|
||||
char *vname; /* name of user variable to fetch */
|
||||
|
||||
{
|
||||
|
||||
register int vnum; /* ordinal number of user var */
|
||||
|
||||
/* scan the list looking for the user var name */
|
||||
for (vnum = 0; vnum < MAXVARS; vnum++) {
|
||||
if (uv[vnum].u_name[0] == 0)
|
||||
return(errorm);
|
||||
if (strcmp(vname, uv[vnum].u_name) == 0)
|
||||
return(uv[vnum].u_value);
|
||||
}
|
||||
|
||||
/* return errorm if we run off the end */
|
||||
return(errorm);
|
||||
}
|
||||
|
||||
char *gtenv(vname)
|
||||
|
||||
char *vname; /* name of environment variable to retrieve */
|
||||
|
||||
{
|
||||
register int vnum; /* ordinal number of var refrenced */
|
||||
char *getkill();
|
||||
|
||||
/* scan the list, looking for the referenced name */
|
||||
for (vnum = 0; vnum < NEVARS; vnum++)
|
||||
if (strcmp(vname, envars[vnum]) == 0)
|
||||
break;
|
||||
|
||||
/* return errorm on a bad reference */
|
||||
if (vnum == NEVARS)
|
||||
#if ENVFUNC
|
||||
{
|
||||
extern char *getenv();
|
||||
char *ename = getenv(vname);
|
||||
|
||||
if (ename != NULL)
|
||||
return(ename);
|
||||
else
|
||||
return(errorm);
|
||||
}
|
||||
#else
|
||||
return(errorm);
|
||||
#endif
|
||||
|
||||
/* otherwise, fetch the appropriate value */
|
||||
switch (vnum) {
|
||||
case EVFILLCOL: return(itoa(fillcol));
|
||||
case EVPAGELEN: return(itoa(term.t_nrow + 1));
|
||||
case EVCURCOL: return(itoa(getccol(FALSE)));
|
||||
case EVCURLINE: return(itoa(getcline()));
|
||||
case EVRAM: return(itoa((int)(envram / 1024l)));
|
||||
case EVFLICKER: return(ltos(flickcode));
|
||||
case EVCURWIDTH:return(itoa(term.t_ncol));
|
||||
case EVCBUFNAME:return(curbp->b_bname);
|
||||
case EVCFNAME: return(curbp->b_fname);
|
||||
case EVSRES: return(sres);
|
||||
case EVDEBUG: return(ltos(macbug));
|
||||
case EVSTATUS: return(ltos(cmdstatus));
|
||||
case EVPALETTE: return(palstr);
|
||||
case EVASAVE: return(itoa(gasave));
|
||||
case EVACOUNT: return(itoa(gacount));
|
||||
case EVLASTKEY: return(itoa(lastkey));
|
||||
case EVCURCHAR:
|
||||
return(curwp->w_dotp->l_used ==
|
||||
curwp->w_doto ? itoa('\n') :
|
||||
itoa(lgetc(curwp->w_dotp, curwp->w_doto)));
|
||||
case EVDISCMD: return(ltos(discmd));
|
||||
case EVVERSION: return(VERSION);
|
||||
case EVPROGNAME:return(PROGNAME);
|
||||
case EVSEED: return(itoa(seed));
|
||||
case EVDISINP: return(ltos(disinp));
|
||||
case EVWLINE: return(itoa(curwp->w_ntrows));
|
||||
case EVCWLINE: return(itoa(getwpos()));
|
||||
case EVTARGET: saveflag = lastflag;
|
||||
return(itoa(curgoal));
|
||||
case EVSEARCH: return(pat);
|
||||
case EVREPLACE: return(rpat);
|
||||
case EVMATCH: return((patmatch == NULL)? "": patmatch);
|
||||
case EVKILL: return(getkill());
|
||||
case EVCMODE: return(itoa(curbp->b_mode));
|
||||
case EVGMODE: return(itoa(gmode));
|
||||
case EVTPAUSE: return(itoa(term.t_pause));
|
||||
case EVPENDING:
|
||||
#if TYPEAH
|
||||
return(ltos(typahead()));
|
||||
#else
|
||||
return(falsem);
|
||||
#endif
|
||||
case EVLWIDTH: return(itoa(llength(curwp->w_dotp)));
|
||||
case EVLINE: return(getctext());
|
||||
case EVGFLAGS: return(itoa(gflags));
|
||||
case EVRVAL: return(itoa(rval));
|
||||
case EVTAB: return(itoa(tabmask+1));
|
||||
case EVOVERLAP: return(itoa(overlap));
|
||||
case EVSCROLLCOUNT:
|
||||
return(itoa(scrollcount));
|
||||
#if SCROLLCODE
|
||||
case EVSCROLL: return(ltos(term.t_scroll != NULL));
|
||||
#else
|
||||
case EVSCROLL: return(ltos(0));
|
||||
#endif
|
||||
}
|
||||
exit(-12); /* again, we should never get here */
|
||||
}
|
||||
|
||||
char *getkill() /* return some of the contents of the kill buffer */
|
||||
|
||||
{
|
||||
register int size; /* max number of chars to return */
|
||||
static char value[NSTRING]; /* temp buffer for value */
|
||||
|
||||
if (kbufh == NULL)
|
||||
/* no kill buffer....just a null string */
|
||||
value[0] = 0;
|
||||
else {
|
||||
/* copy in the contents... */
|
||||
if (kused < NSTRING)
|
||||
size = kused;
|
||||
else
|
||||
size = NSTRING - 1;
|
||||
strncpy(value, kbufh->d_chunk, size);
|
||||
}
|
||||
|
||||
/* and return the constructed value */
|
||||
return(value);
|
||||
}
|
||||
|
||||
int setvar(f, n) /* set a variable */
|
||||
|
||||
int f; /* default flag */
|
||||
int n; /* numeric arg (can overide prompted value) */
|
||||
|
||||
{
|
||||
register int status; /* status return */
|
||||
#if DEBUGM
|
||||
register char *sp; /* temp string pointer */
|
||||
register char *ep; /* ptr to end of outline */
|
||||
#endif
|
||||
VDESC vd; /* variable num/type */
|
||||
char var[NVSIZE+1]; /* name of variable to fetch */
|
||||
char value[NSTRING]; /* value to set variable to */
|
||||
|
||||
/* first get the variable to set.. */
|
||||
if (clexec == FALSE) {
|
||||
status = mlreply("Variable to set: ", &var[0], NVSIZE);
|
||||
if (status != TRUE)
|
||||
return(status);
|
||||
} else { /* macro line argument */
|
||||
/* grab token and skip it */
|
||||
execstr = token(execstr, var, NVSIZE + 1);
|
||||
}
|
||||
|
||||
/* check the legality and find the var */
|
||||
findvar(var, &vd, NVSIZE + 1);
|
||||
|
||||
/* if its not legal....bitch */
|
||||
if (vd.v_type == -1) {
|
||||
mlwrite("%%No such variable as '%s'", var);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* get the value for that variable */
|
||||
if (f == TRUE)
|
||||
strcpy(value, itoa(n));
|
||||
else {
|
||||
status = mlreply("Value: ", &value[0], NSTRING);
|
||||
if (status != TRUE)
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* and set the appropriate value */
|
||||
status = svar(&vd, value);
|
||||
|
||||
#if DEBUGM
|
||||
/* if $debug == TRUE, every assignment will echo a statment to
|
||||
that effect here. */
|
||||
|
||||
if (macbug) {
|
||||
strcpy(outline, "(((");
|
||||
|
||||
/* assignment status */
|
||||
strcat(outline, ltos(status));
|
||||
strcat(outline, ":");
|
||||
|
||||
/* variable name */
|
||||
strcat(outline, var);
|
||||
strcat(outline, ":");
|
||||
|
||||
/* and lastly the value we tried to assign */
|
||||
strcat(outline, value);
|
||||
strcat(outline, ")))");
|
||||
|
||||
/* expand '%' to "%%" so mlwrite wont bitch */
|
||||
sp = outline;
|
||||
while (*sp)
|
||||
if (*sp++ == '%') {
|
||||
/* advance to the end */
|
||||
ep = --sp;
|
||||
while (*ep++)
|
||||
;
|
||||
/* null terminate the string one out */
|
||||
*(ep + 1) = 0;
|
||||
/* copy backwards */
|
||||
while(ep-- > sp)
|
||||
*(ep + 1) = *ep;
|
||||
|
||||
/* and advance sp past the new % */
|
||||
sp += 2;
|
||||
}
|
||||
|
||||
/* write out the debug line */
|
||||
mlforce(outline);
|
||||
update(TRUE);
|
||||
|
||||
/* and get the keystroke to hold the output */
|
||||
if (get1key() == abortc) {
|
||||
mlforce("(Macro aborted)");
|
||||
status = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* and return it */
|
||||
return(status);
|
||||
}
|
||||
|
||||
findvar(var, vd, size) /* find a variables type and name */
|
||||
|
||||
char *var; /* name of var to get */
|
||||
VDESC *vd; /* structure to hold type and ptr */
|
||||
int size; /* size of var array */
|
||||
|
||||
{
|
||||
register int vnum; /* subscript in varable arrays */
|
||||
register int vtype; /* type to return */
|
||||
|
||||
fvar: vtype = -1;
|
||||
switch (var[0]) {
|
||||
|
||||
case '$': /* check for legal enviromnent var */
|
||||
for (vnum = 0; vnum < NEVARS; vnum++)
|
||||
if (strcmp(&var[1], envars[vnum]) == 0) {
|
||||
vtype = TKENV;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%': /* check for existing legal user variable */
|
||||
for (vnum = 0; vnum < MAXVARS; vnum++)
|
||||
if (strcmp(&var[1], uv[vnum].u_name) == 0) {
|
||||
vtype = TKVAR;
|
||||
break;
|
||||
}
|
||||
if (vnum < MAXVARS)
|
||||
break;
|
||||
|
||||
/* create a new one??? */
|
||||
for (vnum = 0; vnum < MAXVARS; vnum++)
|
||||
if (uv[vnum].u_name[0] == 0) {
|
||||
vtype = TKVAR;
|
||||
strcpy(uv[vnum].u_name, &var[1]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '&': /* indirect operator? */
|
||||
var[4] = 0;
|
||||
if (strcmp(&var[1], "ind") == 0) {
|
||||
/* grab token, and eval it */
|
||||
execstr = token(execstr, var, size);
|
||||
strcpy(var, getval(var));
|
||||
goto fvar;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the results */
|
||||
vd->v_num = vnum;
|
||||
vd->v_type = vtype;
|
||||
return;
|
||||
}
|
||||
|
||||
int svar(var, value) /* set a variable */
|
||||
|
||||
VDESC *var; /* variable to set */
|
||||
char *value; /* value to set to */
|
||||
|
||||
{
|
||||
register int vnum; /* ordinal number of var refrenced */
|
||||
register int vtype; /* type of variable to set */
|
||||
register int status; /* status return */
|
||||
register int c; /* translated character */
|
||||
register char * sp; /* scratch string pointer */
|
||||
|
||||
/* simplify the vd structure (we are gonna look at it a lot) */
|
||||
vnum = var->v_num;
|
||||
vtype = var->v_type;
|
||||
|
||||
/* and set the appropriate value */
|
||||
status = TRUE;
|
||||
switch (vtype) {
|
||||
case TKVAR: /* set a user variable */
|
||||
if (uv[vnum].u_value != NULL)
|
||||
free(uv[vnum].u_value);
|
||||
sp = malloc(strlen(value) + 1);
|
||||
if (sp == NULL)
|
||||
return(FALSE);
|
||||
strcpy(sp, value);
|
||||
uv[vnum].u_value = sp;
|
||||
break;
|
||||
|
||||
case TKENV: /* set an environment variable */
|
||||
status = TRUE; /* by default */
|
||||
switch (vnum) {
|
||||
case EVFILLCOL: fillcol = atoi(value);
|
||||
break;
|
||||
case EVPAGELEN: status = newsize(TRUE, atoi(value));
|
||||
break;
|
||||
case EVCURCOL: status = setccol(atoi(value));
|
||||
break;
|
||||
case EVCURLINE: status = gotoline(TRUE, atoi(value));
|
||||
break;
|
||||
case EVRAM: break;
|
||||
case EVFLICKER: flickcode = stol(value);
|
||||
break;
|
||||
case EVCURWIDTH:status = newwidth(TRUE, atoi(value));
|
||||
break;
|
||||
case EVCBUFNAME:strcpy(curbp->b_bname, value);
|
||||
curwp->w_flag |= WFMODE;
|
||||
break;
|
||||
case EVCFNAME: strcpy(curbp->b_fname, value);
|
||||
curwp->w_flag |= WFMODE;
|
||||
break;
|
||||
case EVSRES: status = TTrez(value);
|
||||
break;
|
||||
case EVDEBUG: macbug = stol(value);
|
||||
break;
|
||||
case EVSTATUS: cmdstatus = stol(value);
|
||||
break;
|
||||
case EVPALETTE: strncpy(palstr, value, 48);
|
||||
spal(palstr);
|
||||
break;
|
||||
case EVASAVE: gasave = atoi(value);
|
||||
break;
|
||||
case EVACOUNT: gacount = atoi(value);
|
||||
break;
|
||||
case EVLASTKEY: lastkey = atoi(value);
|
||||
break;
|
||||
case EVCURCHAR: ldelete(1L, FALSE); /* delete 1 char */
|
||||
c = atoi(value);
|
||||
if (c == '\n')
|
||||
lnewline(FALSE, 1);
|
||||
else
|
||||
linsert(1, c);
|
||||
backchar(FALSE, 1);
|
||||
break;
|
||||
case EVDISCMD: discmd = stol(value);
|
||||
break;
|
||||
case EVVERSION: break;
|
||||
case EVPROGNAME:break;
|
||||
case EVSEED: seed = atoi(value);
|
||||
break;
|
||||
case EVDISINP: disinp = stol(value);
|
||||
break;
|
||||
case EVWLINE: status = resize(TRUE, atoi(value));
|
||||
break;
|
||||
case EVCWLINE: status = forwline(TRUE,
|
||||
atoi(value) - getwpos());
|
||||
break;
|
||||
case EVTARGET: curgoal = atoi(value);
|
||||
thisflag = saveflag;
|
||||
break;
|
||||
case EVSEARCH: strcpy(pat, value);
|
||||
rvstrcpy(tap, pat);
|
||||
#if MAGIC
|
||||
mcclear();
|
||||
#endif
|
||||
break;
|
||||
case EVREPLACE: strcpy(rpat, value);
|
||||
break;
|
||||
case EVMATCH: break;
|
||||
case EVKILL: break;
|
||||
case EVCMODE: curbp->b_mode = atoi(value);
|
||||
curwp->w_flag |= WFMODE;
|
||||
break;
|
||||
case EVGMODE: gmode = atoi(value);
|
||||
break;
|
||||
case EVTPAUSE: term.t_pause = atoi(value);
|
||||
break;
|
||||
case EVPENDING: break;
|
||||
case EVLWIDTH: break;
|
||||
case EVLINE: putctext(value);
|
||||
case EVGFLAGS: gflags = atoi(value);
|
||||
break;
|
||||
case EVRVAL: break;
|
||||
case EVTAB: tabmask = atoi(value)-1;
|
||||
if (tabmask != 0x07 && tabmask != 0x03)
|
||||
tabmask = 0x07;
|
||||
curwp->w_flag |= WFHARD;
|
||||
break;
|
||||
case EVOVERLAP: overlap = atoi(value);
|
||||
break;
|
||||
case EVSCROLLCOUNT:
|
||||
scrollcount = atoi(value);
|
||||
break;
|
||||
case EVSCROLL:
|
||||
#if SCROLLCODE
|
||||
if (! stol(value))
|
||||
term.t_scroll = NULL;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* atoi: ascii string to integer......This is too
|
||||
inconsistant to use the system's */
|
||||
|
||||
atoi(st)
|
||||
|
||||
char *st;
|
||||
|
||||
{
|
||||
int result; /* resulting number */
|
||||
int sign; /* sign of resulting number */
|
||||
char c; /* current char being examined */
|
||||
|
||||
result = 0;
|
||||
sign = 1;
|
||||
|
||||
/* skip preceding whitespace */
|
||||
while (*st == ' ' || *st == '\t')
|
||||
++st;
|
||||
|
||||
/* check for sign */
|
||||
if (*st == '-') {
|
||||
sign = -1;
|
||||
++st;
|
||||
}
|
||||
if (*st == '+')
|
||||
++st;
|
||||
|
||||
/* scan digits, build value */
|
||||
while ((c = *st++))
|
||||
if (c >= '0' && c <= '9')
|
||||
result = result * 10 + c - '0';
|
||||
else
|
||||
return(0);
|
||||
|
||||
return(result * sign);
|
||||
}
|
||||
|
||||
/* itoa: integer to ascii string.......... This is too
|
||||
inconsistant to use the system's */
|
||||
|
||||
char *itoa(i)
|
||||
|
||||
int i; /* integer to translate to a string */
|
||||
|
||||
{
|
||||
register int digit; /* current digit being used */
|
||||
register char *sp; /* pointer into result */
|
||||
register int sign; /* sign of resulting number */
|
||||
static char result[INTWIDTH+1]; /* resulting string */
|
||||
|
||||
/* record the sign...*/
|
||||
sign = 1;
|
||||
if (i < 0) {
|
||||
sign = -1;
|
||||
i = -i;
|
||||
}
|
||||
|
||||
/* and build the string (backwards!) */
|
||||
sp = result + INTWIDTH;
|
||||
*sp = 0;
|
||||
do {
|
||||
digit = i % 10;
|
||||
*(--sp) = '0' + digit; /* and install the new digit */
|
||||
i = i / 10;
|
||||
} while (i);
|
||||
|
||||
/* and fix the sign */
|
||||
if (sign == -1) {
|
||||
*(--sp) = '-'; /* and install the minus sign */
|
||||
}
|
||||
|
||||
return(sp);
|
||||
}
|
||||
|
||||
int gettyp(token) /* find the type of a passed token */
|
||||
|
||||
char *token; /* token to analyze */
|
||||
|
||||
{
|
||||
register char c; /* first char in token */
|
||||
|
||||
/* grab the first char (this is all we need) */
|
||||
c = *token;
|
||||
|
||||
/* no blanks!!! */
|
||||
if (c == 0)
|
||||
return(TKNUL);
|
||||
|
||||
/* a numeric literal? */
|
||||
if (c >= '0' && c <= '9')
|
||||
return(TKLIT);
|
||||
|
||||
switch (c) {
|
||||
case '"': return(TKSTR);
|
||||
|
||||
case '!': return(TKDIR);
|
||||
case '@': return(TKARG);
|
||||
case '#': return(TKBUF);
|
||||
case '$': return(TKENV);
|
||||
case '%': return(TKVAR);
|
||||
case '&': return(TKFUN);
|
||||
case '*': return(TKLBL);
|
||||
|
||||
default: return(TKCMD);
|
||||
}
|
||||
}
|
||||
|
||||
char *getval(token) /* find the value of a token */
|
||||
|
||||
char *token; /* token to evaluate */
|
||||
|
||||
{
|
||||
register int status; /* error return */
|
||||
register BUFFER *bp; /* temp buffer pointer */
|
||||
register int blen; /* length of buffer argument */
|
||||
register int distmp; /* temporary discmd flag */
|
||||
static char buf[NSTRING];/* string buffer for some returns */
|
||||
|
||||
switch (gettyp(token)) {
|
||||
case TKNUL: return("");
|
||||
|
||||
case TKARG: /* interactive argument */
|
||||
strcpy(token, getval(&token[1]));
|
||||
distmp = discmd; /* echo it always! */
|
||||
discmd = TRUE;
|
||||
status = getstring(token,
|
||||
buf, NSTRING, ctoec('\n'));
|
||||
discmd = distmp;
|
||||
if (status == ABORT)
|
||||
return(errorm);
|
||||
return(buf);
|
||||
|
||||
case TKBUF: /* buffer contents fetch */
|
||||
|
||||
/* grab the right buffer */
|
||||
strcpy(token, getval(&token[1]));
|
||||
bp = bfind(token, FALSE, 0);
|
||||
if (bp == NULL)
|
||||
return(errorm);
|
||||
|
||||
/* if the buffer is displayed, get the window
|
||||
vars instead of the buffer vars */
|
||||
if (bp->b_nwnd > 0) {
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
}
|
||||
|
||||
/* make sure we are not at the end */
|
||||
if (bp->b_linep == bp->b_dotp)
|
||||
return(errorm);
|
||||
|
||||
/* grab the line as an argument */
|
||||
blen = bp->b_dotp->l_used - bp->b_doto;
|
||||
if (blen > NSTRING)
|
||||
blen = NSTRING;
|
||||
strncpy(buf, bp->b_dotp->l_text + bp->b_doto,
|
||||
blen);
|
||||
buf[blen] = 0;
|
||||
|
||||
/* and step the buffer's line ptr ahead a line */
|
||||
bp->b_dotp = bp->b_dotp->l_fp;
|
||||
bp->b_doto = 0;
|
||||
|
||||
/* if displayed buffer, reset window ptr vars*/
|
||||
if (bp->b_nwnd > 0) {
|
||||
curwp->w_dotp = curbp->b_dotp;
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_flag |= WFMOVE;
|
||||
}
|
||||
|
||||
/* and return the spoils */
|
||||
return(buf);
|
||||
|
||||
case TKVAR: return(gtusr(token+1));
|
||||
case TKENV: return(gtenv(token+1));
|
||||
case TKFUN: return(gtfun(token+1));
|
||||
case TKDIR: return(errorm);
|
||||
case TKLBL: return(errorm);
|
||||
case TKLIT: return(token);
|
||||
case TKSTR: return(token+1);
|
||||
case TKCMD: return(token);
|
||||
}
|
||||
}
|
||||
|
||||
int stol(val) /* convert a string to a numeric logical */
|
||||
|
||||
char *val; /* value to check for stol */
|
||||
|
||||
{
|
||||
/* check for logical values */
|
||||
if (val[0] == 'F')
|
||||
return(FALSE);
|
||||
if (val[0] == 'T')
|
||||
return(TRUE);
|
||||
|
||||
/* check for numeric truth (!= 0) */
|
||||
return((atoi(val) != 0));
|
||||
}
|
||||
|
||||
char *ltos(val) /* numeric logical to string logical */
|
||||
|
||||
int val; /* value to translate */
|
||||
|
||||
{
|
||||
if (val)
|
||||
return(truem);
|
||||
else
|
||||
return(falsem);
|
||||
}
|
||||
|
||||
char *mkupper(str) /* make a string upper case */
|
||||
|
||||
char *str; /* string to upper case */
|
||||
|
||||
{
|
||||
char *sp;
|
||||
|
||||
sp = str;
|
||||
while (*sp) {
|
||||
if ('a' <= *sp && *sp <= 'z')
|
||||
*sp += 'A' - 'a';
|
||||
++sp;
|
||||
}
|
||||
return(str);
|
||||
}
|
||||
|
||||
char *mklower(str) /* make a string lower case */
|
||||
|
||||
char *str; /* string to lower case */
|
||||
|
||||
{
|
||||
char *sp;
|
||||
|
||||
sp = str;
|
||||
while (*sp) {
|
||||
if ('A' <= *sp && *sp <= 'Z')
|
||||
*sp += 'a' - 'A';
|
||||
++sp;
|
||||
}
|
||||
return(str);
|
||||
}
|
||||
|
||||
int abs(x) /* take the absolute value of an integer */
|
||||
|
||||
int x;
|
||||
|
||||
{
|
||||
return(x < 0 ? -x : x);
|
||||
}
|
||||
|
||||
int ernd() /* returns a random integer */
|
||||
|
||||
{
|
||||
seed = abs(seed * 1721 + 10007);
|
||||
return(seed);
|
||||
}
|
||||
|
||||
int sindex(source, pattern) /* find pattern within source */
|
||||
|
||||
char *source; /* source string to search */
|
||||
char *pattern; /* string to look for */
|
||||
|
||||
{
|
||||
char *sp; /* ptr to current position to scan */
|
||||
char *csp; /* ptr to source string during comparison */
|
||||
char *cp; /* ptr to place to check for equality */
|
||||
|
||||
/* scanning through the source string */
|
||||
sp = source;
|
||||
while (*sp) {
|
||||
/* scan through the pattern */
|
||||
cp = pattern;
|
||||
csp = sp;
|
||||
while (*cp) {
|
||||
if (!eq(*cp, *csp))
|
||||
break;
|
||||
++cp;
|
||||
++csp;
|
||||
}
|
||||
|
||||
/* was it a match? */
|
||||
if (*cp == 0)
|
||||
return((int)(sp - source) + 1);
|
||||
++sp;
|
||||
}
|
||||
|
||||
/* no match at all.. */
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Filter a string through a translation table */
|
||||
|
||||
char *xlat(source, lookup, trans)
|
||||
|
||||
char *source; /* string to filter */
|
||||
char *lookup; /* characters to translate */
|
||||
char *trans; /* resulting translated characters */
|
||||
|
||||
{
|
||||
register char *sp; /* pointer into source table */
|
||||
register char *lp; /* pointer into lookup table */
|
||||
register char *rp; /* pointer into result */
|
||||
static char result[NSTRING]; /* temporary result */
|
||||
|
||||
/* scan source string */
|
||||
sp = source;
|
||||
rp = result;
|
||||
while (*sp) {
|
||||
/* scan lookup table for a match */
|
||||
lp = lookup;
|
||||
while (*lp) {
|
||||
if (*sp == *lp) {
|
||||
*rp++ = trans[lp - lookup];
|
||||
goto xnext;
|
||||
}
|
||||
++lp;
|
||||
}
|
||||
|
||||
/* no match, copy in the source char untranslated */
|
||||
*rp++ = *sp;
|
||||
|
||||
xnext: ++sp;
|
||||
}
|
||||
|
||||
/* terminate and return the result */
|
||||
*rp = 0;
|
||||
return(result);
|
||||
}
|
212
evar.h
Normal file
212
evar.h
Normal file
@ -0,0 +1,212 @@
|
||||
/* EVAR.H
|
||||
*
|
||||
* Environment and user variable definitions
|
||||
*
|
||||
* written 1986 by Daniel Lawrence
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
/* structure to hold user variables and their definitions */
|
||||
|
||||
typedef struct UVAR {
|
||||
char u_name[NVSIZE + 1]; /* name of user variable */
|
||||
char *u_value; /* value (string) */
|
||||
} UVAR;
|
||||
|
||||
/* current user variables (This structure will probably change) */
|
||||
|
||||
#define MAXVARS 255
|
||||
|
||||
UVAR uv[MAXVARS + 1]; /* user variables */
|
||||
|
||||
/* list of recognized environment variables */
|
||||
|
||||
char *envars[] = {
|
||||
"fillcol", /* current fill column */
|
||||
"pagelen", /* number of lines used by editor */
|
||||
"curcol", /* current column pos of cursor */
|
||||
"curline", /* current line in file */
|
||||
"ram", /* ram in use by malloc */
|
||||
"flicker", /* flicker supression */
|
||||
"curwidth", /* current screen width */
|
||||
"cbufname", /* current buffer name */
|
||||
"cfname", /* current file name */
|
||||
"sres", /* current screen resolution */
|
||||
"debug", /* macro debugging */
|
||||
"status", /* returns the status of the last command */
|
||||
"palette", /* current palette string */
|
||||
"asave", /* # of chars between auto-saves */
|
||||
"acount", /* # of chars until next auto-save */
|
||||
"lastkey", /* last keyboard char struck */
|
||||
"curchar", /* current character under the cursor */
|
||||
"discmd", /* display commands on command line */
|
||||
"version", /* current version number */
|
||||
"progname", /* returns current prog name - "MicroEMACS" */
|
||||
"seed", /* current random number seed */
|
||||
"disinp", /* display command line input characters */
|
||||
"wline", /* # of lines in current window */
|
||||
"cwline", /* current screen line in window */
|
||||
"target", /* target for line moves */
|
||||
"search", /* search pattern */
|
||||
"replace", /* replacement pattern */
|
||||
"match", /* last matched magic pattern */
|
||||
"kill", /* kill buffer (read only) */
|
||||
"cmode", /* mode of current buffer */
|
||||
"gmode", /* global modes */
|
||||
"tpause", /* length to pause for paren matching */
|
||||
"pending", /* type ahead pending flag */
|
||||
"lwidth", /* width of current line */
|
||||
"line", /* text of current line */
|
||||
"gflags", /* global internal emacs flags */
|
||||
"rval", /* child process return value */
|
||||
"tab", /* tab 4 or 8 */
|
||||
"overlap",
|
||||
"jump",
|
||||
#if SCROLLCODE
|
||||
"scroll", /* scroll enabled */
|
||||
#endif
|
||||
};
|
||||
|
||||
#define NEVARS sizeof(envars) / sizeof(char *)
|
||||
|
||||
/* and its preprocesor definitions */
|
||||
|
||||
#define EVFILLCOL 0
|
||||
#define EVPAGELEN 1
|
||||
#define EVCURCOL 2
|
||||
#define EVCURLINE 3
|
||||
#define EVRAM 4
|
||||
#define EVFLICKER 5
|
||||
#define EVCURWIDTH 6
|
||||
#define EVCBUFNAME 7
|
||||
#define EVCFNAME 8
|
||||
#define EVSRES 9
|
||||
#define EVDEBUG 10
|
||||
#define EVSTATUS 11
|
||||
#define EVPALETTE 12
|
||||
#define EVASAVE 13
|
||||
#define EVACOUNT 14
|
||||
#define EVLASTKEY 15
|
||||
#define EVCURCHAR 16
|
||||
#define EVDISCMD 17
|
||||
#define EVVERSION 18
|
||||
#define EVPROGNAME 19
|
||||
#define EVSEED 20
|
||||
#define EVDISINP 21
|
||||
#define EVWLINE 22
|
||||
#define EVCWLINE 23
|
||||
#define EVTARGET 24
|
||||
#define EVSEARCH 25
|
||||
#define EVREPLACE 26
|
||||
#define EVMATCH 27
|
||||
#define EVKILL 28
|
||||
#define EVCMODE 29
|
||||
#define EVGMODE 30
|
||||
#define EVTPAUSE 31
|
||||
#define EVPENDING 32
|
||||
#define EVLWIDTH 33
|
||||
#define EVLINE 34
|
||||
#define EVGFLAGS 35
|
||||
#define EVRVAL 36
|
||||
#define EVTAB 37
|
||||
#define EVOVERLAP 38
|
||||
#define EVSCROLLCOUNT 39
|
||||
#define EVSCROLL 40
|
||||
|
||||
/* list of recognized user functions */
|
||||
|
||||
typedef struct UFUNC {
|
||||
char *f_name; /* name of function */
|
||||
int f_type; /* 1 = monamic, 2 = dynamic */
|
||||
} UFUNC;
|
||||
|
||||
#define NILNAMIC 0
|
||||
#define MONAMIC 1
|
||||
#define DYNAMIC 2
|
||||
#define TRINAMIC 3
|
||||
|
||||
UFUNC funcs[] = {
|
||||
"add", DYNAMIC, /* add two numbers together */
|
||||
"sub", DYNAMIC, /* subtraction */
|
||||
"tim", DYNAMIC, /* multiplication */
|
||||
"div", DYNAMIC, /* division */
|
||||
"mod", DYNAMIC, /* mod */
|
||||
"neg", MONAMIC, /* negate */
|
||||
"cat", DYNAMIC, /* concatinate string */
|
||||
"lef", DYNAMIC, /* left string(string, len) */
|
||||
"rig", DYNAMIC, /* right string(string, pos) */
|
||||
"mid", TRINAMIC, /* mid string(string, pos, len) */
|
||||
"not", MONAMIC, /* logical not */
|
||||
"equ", DYNAMIC, /* logical equality check */
|
||||
"les", DYNAMIC, /* logical less than */
|
||||
"gre", DYNAMIC, /* logical greater than */
|
||||
"seq", DYNAMIC, /* string logical equality check */
|
||||
"sle", DYNAMIC, /* string logical less than */
|
||||
"sgr", DYNAMIC, /* string logical greater than */
|
||||
"ind", MONAMIC, /* evaluate indirect value */
|
||||
"and", DYNAMIC, /* logical and */
|
||||
"or", DYNAMIC, /* logical or */
|
||||
"len", MONAMIC, /* string length */
|
||||
"upp", MONAMIC, /* uppercase string */
|
||||
"low", MONAMIC, /* lower case string */
|
||||
"tru", MONAMIC, /* Truth of the universe logical test */
|
||||
"asc", MONAMIC, /* char to integer conversion */
|
||||
"chr", MONAMIC, /* integer to char conversion */
|
||||
"gtk", NILNAMIC, /* get 1 charater */
|
||||
"rnd", MONAMIC, /* get a random number */
|
||||
"abs", MONAMIC, /* absolute value of a number */
|
||||
"sin", DYNAMIC, /* find the index of one string in another */
|
||||
"env", MONAMIC, /* retrieve a system environment var */
|
||||
"bin", MONAMIC, /* loopup what function name is bound to a key */
|
||||
"exi", MONAMIC, /* check if a file exists */
|
||||
"fin", MONAMIC, /* look for a file on the path... */
|
||||
"ban", DYNAMIC, /* bitwise and 9-10-87 jwm */
|
||||
"bor", DYNAMIC, /* bitwise or 9-10-87 jwm */
|
||||
"bxo", DYNAMIC, /* bitwise xor 9-10-87 jwm */
|
||||
"bno", MONAMIC, /* bitwise not */
|
||||
"xla", TRINAMIC, /* XLATE character string translation */
|
||||
};
|
||||
|
||||
#define NFUNCS sizeof(funcs) / sizeof(UFUNC)
|
||||
|
||||
/* and its preprocesor definitions */
|
||||
|
||||
#define UFADD 0
|
||||
#define UFSUB 1
|
||||
#define UFTIMES 2
|
||||
#define UFDIV 3
|
||||
#define UFMOD 4
|
||||
#define UFNEG 5
|
||||
#define UFCAT 6
|
||||
#define UFLEFT 7
|
||||
#define UFRIGHT 8
|
||||
#define UFMID 9
|
||||
#define UFNOT 10
|
||||
#define UFEQUAL 11
|
||||
#define UFLESS 12
|
||||
#define UFGREATER 13
|
||||
#define UFSEQUAL 14
|
||||
#define UFSLESS 15
|
||||
#define UFSGREAT 16
|
||||
#define UFIND 17
|
||||
#define UFAND 18
|
||||
#define UFOR 19
|
||||
#define UFLENGTH 20
|
||||
#define UFUPPER 21
|
||||
#define UFLOWER 22
|
||||
#define UFTRUTH 23
|
||||
#define UFASCII 24
|
||||
#define UFCHR 25
|
||||
#define UFGTKEY 26
|
||||
#define UFRND 27
|
||||
#define UFABS 28
|
||||
#define UFSINDEX 29
|
||||
#define UFENV 30
|
||||
#define UFBIND 31
|
||||
#define UFEXIST 32
|
||||
#define UFFIND 33
|
||||
#define UFBAND 34
|
||||
#define UFBOR 35
|
||||
#define UFBXOR 36
|
||||
#define UFBNOT 37
|
||||
#define UFXLATE 38
|
635
file.c
Normal file
635
file.c
Normal file
@ -0,0 +1,635 @@
|
||||
/* FILE.C
|
||||
*
|
||||
* The routines in this file handle the reading, writing
|
||||
* and lookup of disk files. All of details about the
|
||||
* reading and writing of the disk are in "fileio.c".
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.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 (restflag) /* don't allow this command if restricted */
|
||||
return(resterr());
|
||||
if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
|
||||
return(s);
|
||||
return(readin(fname, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a file into the current
|
||||
* buffer. This is really easy; all you do it
|
||||
* find the name of the file, and call the standard
|
||||
* "insert a file into the current buffer" code.
|
||||
* Bound to "C-X C-I".
|
||||
*/
|
||||
insfile(f, n)
|
||||
{
|
||||
register int s;
|
||||
char fname[NFILEN];
|
||||
|
||||
if (restflag) /* don't allow this command if restricted */
|
||||
return(resterr());
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE)
|
||||
return(s);
|
||||
if ((s=ifile(fname)) != TRUE)
|
||||
return(s);
|
||||
return(reposition(TRUE, -1));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
filefind(f, n)
|
||||
{
|
||||
char fname[NFILEN]; /* file user wishes to find */
|
||||
register int s; /* status return */
|
||||
|
||||
if (restflag) /* don't allow this command if restricted */
|
||||
return(resterr());
|
||||
if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
|
||||
return(s);
|
||||
return(getfile(fname, TRUE));
|
||||
}
|
||||
|
||||
viewfile(f, n) /* visit a file in VIEW mode */
|
||||
{
|
||||
char fname[NFILEN]; /* file user wishes to find */
|
||||
register int s; /* status return */
|
||||
register WINDOW *wp; /* scan for windows that need updating */
|
||||
|
||||
if (restflag) /* don't allow this command if restricted */
|
||||
return(resterr());
|
||||
if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
|
||||
return (s);
|
||||
s = getfile(fname, FALSE);
|
||||
if (s) { /* if we succeed, put it in view mode */
|
||||
curwp->w_bufp->b_mode |= MDVIEW;
|
||||
|
||||
/* scan through and update mode lines of all windows */
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
return(s);
|
||||
}
|
||||
|
||||
#if CRYPT
|
||||
resetkey() /* reset the encryption key if needed */
|
||||
|
||||
{
|
||||
register int s; /* return status */
|
||||
|
||||
/* turn off the encryption flag */
|
||||
cryptflag = FALSE;
|
||||
|
||||
/* if we are in crypt mode */
|
||||
if (curbp->b_mode & MDCRYPT) {
|
||||
if (curbp->b_key[0] == 0) {
|
||||
s = setkey(FALSE, 0);
|
||||
if (s != TRUE)
|
||||
return(s);
|
||||
}
|
||||
|
||||
/* let others know... */
|
||||
cryptflag = TRUE;
|
||||
|
||||
/* and set up the key to be used! */
|
||||
/* de-encrypt it */
|
||||
crypt((char *)NULL, 0);
|
||||
crypt(curbp->b_key, strlen(curbp->b_key));
|
||||
|
||||
/* re-encrypt it...seeding it to start */
|
||||
crypt((char *)NULL, 0);
|
||||
crypt(curbp->b_key, strlen(curbp->b_key));
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
getfile(fname, lockfl)
|
||||
|
||||
char fname[]; /* file name to find */
|
||||
int lockfl; /* check the file for locks? */
|
||||
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register LINE *lp;
|
||||
register int i;
|
||||
register int s;
|
||||
char bname[NBUFN]; /* buffer name to put file */
|
||||
|
||||
#if MSDOS
|
||||
mklower(fname); /* msdos isn't case sensitive */
|
||||
#endif
|
||||
for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
|
||||
if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) {
|
||||
swbuffer(bp);
|
||||
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;
|
||||
cknewwindow();
|
||||
mlwrite("(Old buffer)");
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
makename(bname, fname); /* New buffer name. */
|
||||
while ((bp=bfind(bname, FALSE, 0)) != NULL) {
|
||||
/* old buffer name conflict code */
|
||||
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++;
|
||||
s = readin(fname, lockfl); /* Read it in. */
|
||||
cknewwindow();
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
Read file "fname" into the current buffer, blowing away any text
|
||||
found there. Called by both the read and find 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.
|
||||
The command bound to M-FNR is called after the buffer is set up
|
||||
and before it is read.
|
||||
*/
|
||||
|
||||
readin(fname, lockfl)
|
||||
|
||||
char fname[]; /* name of file to read */
|
||||
int lockfl; /* check for file locks? */
|
||||
|
||||
{
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register int i;
|
||||
register WINDOW *wp;
|
||||
register BUFFER *bp;
|
||||
register int s;
|
||||
register int nbytes;
|
||||
register int nline;
|
||||
int lflag; /* any lines longer than allowed? */
|
||||
char mesg[NSTRING];
|
||||
|
||||
#if (FILOCK && BSD) || SVR4
|
||||
if (lockfl && lockchk(fname) == ABORT)
|
||||
#if PKCODE
|
||||
{
|
||||
s = FIOFNF;
|
||||
bp = curbp;
|
||||
strcpy(bp->b_fname, "");
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
return(ABORT);
|
||||
#endif
|
||||
#endif
|
||||
#if CRYPT
|
||||
s = resetkey();
|
||||
if (s != TRUE)
|
||||
return(s);
|
||||
#endif
|
||||
bp = curbp; /* Cheap. */
|
||||
if ((s=bclear(bp)) != TRUE) /* Might be old. */
|
||||
return (s);
|
||||
bp->b_flag &= ~(BFINVS|BFCHG);
|
||||
strcpy(bp->b_fname, fname);
|
||||
|
||||
/* let a user macro get hold of things...if he wants */
|
||||
execute(META|SPEC|'R', FALSE, 1);
|
||||
|
||||
/* turn off ALL keyboard translation in case we get a dos error */
|
||||
TTkclose();
|
||||
|
||||
if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
|
||||
goto out;
|
||||
|
||||
if (s == FIOFNF) { /* File not found. */
|
||||
mlwrite("(New file)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* read the file in */
|
||||
mlwrite("(Reading file)");
|
||||
nline = 0;
|
||||
lflag = FALSE;
|
||||
while ((s=ffgetline()) == FIOSUC) {
|
||||
nbytes = strlen(fline);
|
||||
if ((lp1=lalloc(nbytes)) == NULL) {
|
||||
s = FIOMEM; /* Keep message on the */
|
||||
break; /* display. */
|
||||
}
|
||||
#if PKCODE
|
||||
if (nline > MAXNLINE) {
|
||||
s = FIOMEM;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
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, fline[i]);
|
||||
++nline;
|
||||
}
|
||||
ffclose(); /* Ignore errors. */
|
||||
strcpy(mesg, "(");
|
||||
if (s==FIOERR) {
|
||||
strcat(mesg, "I/O ERROR, ");
|
||||
curbp->b_flag |= BFTRUNC;
|
||||
}
|
||||
if (s == FIOMEM) {
|
||||
strcat(mesg, "OUT OF MEMORY, ");
|
||||
curbp->b_flag |= BFTRUNC;
|
||||
}
|
||||
sprintf(&mesg[strlen(mesg)], "Read %d line", nline);
|
||||
if (nline != 1)
|
||||
strcat(mesg, "s");
|
||||
strcat(mesg, ")");
|
||||
mlwrite(mesg);
|
||||
|
||||
out:
|
||||
TTkopen(); /* open the keyboard again */
|
||||
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 = 0;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
wp->w_flag |= WFMODE|WFHARD;
|
||||
}
|
||||
}
|
||||
if (s == FIOERR || s == FIOFNF) /* False if error. */
|
||||
return(FALSE);
|
||||
#if 0
|
||||
if (s == ABORT)
|
||||
return(ABORT);
|
||||
#endif
|
||||
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;
|
||||
|
||||
#if VMS
|
||||
#if PKCODE
|
||||
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']' && cp1[-1]!='>')
|
||||
#else
|
||||
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
|
||||
#endif
|
||||
--cp1;
|
||||
#endif
|
||||
#if MSDOS
|
||||
while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
|
||||
--cp1;
|
||||
#endif
|
||||
#if V7 | USG | BSD
|
||||
while (cp1!=&fname[0] && cp1[-1]!='/')
|
||||
--cp1;
|
||||
#endif
|
||||
cp2 = &bname[0];
|
||||
while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
|
||||
*cp2++ = *cp1++;
|
||||
*cp2 = 0;
|
||||
}
|
||||
|
||||
unqname(name) /* make sure a buffer name is unique */
|
||||
|
||||
char *name; /* name to check on */
|
||||
|
||||
{
|
||||
register char *sp;
|
||||
|
||||
/* check to see if it is in the buffer list */
|
||||
while (bfind(name, 0, FALSE) != NULL) {
|
||||
|
||||
/* go to the end of the name */
|
||||
sp = name;
|
||||
while (*sp)
|
||||
++sp;
|
||||
if (sp == name || (*(sp-1) <'0' || *(sp-1) > '8')) {
|
||||
*sp++ = '0';
|
||||
*sp = 0;
|
||||
} else
|
||||
*(--sp) += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 (restflag) /* don't allow this command if restricted */
|
||||
return(resterr());
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the contents of the current
|
||||
* buffer in its associatd file. No nothing
|
||||
* if nothing has changed (this may be a bug, not a
|
||||
* feature). Error if there is no remembered file
|
||||
* name for the buffer. Bound to "C-X C-S". May
|
||||
* get called by "C-Z".
|
||||
*/
|
||||
filesave(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register int s;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
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);
|
||||
}
|
||||
|
||||
/* complain about truncated files */
|
||||
if ((curbp->b_flag&BFTRUNC) != 0) {
|
||||
if (mlyesno("Truncated file ... write it out") == FALSE) {
|
||||
mlwrite("(Aborted)");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((s=writeout(curbp->b_fname)) == TRUE) {
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function performs the details of file
|
||||
* writing. Uses the file management routines in the
|
||||
* "fileio.c" package. The number of lines written is
|
||||
* displayed. Sadly, it looks inside a LINE; provide
|
||||
* a macro for this. Most of the grief is error
|
||||
* checking of some sort.
|
||||
*/
|
||||
writeout(fn)
|
||||
char *fn;
|
||||
{
|
||||
register int s;
|
||||
register LINE *lp;
|
||||
register int nline;
|
||||
|
||||
#if CRYPT
|
||||
s = resetkey();
|
||||
if (s != TRUE)
|
||||
return(s);
|
||||
#endif
|
||||
/* turn off ALL keyboard translation in case we get a dos error */
|
||||
TTkclose();
|
||||
|
||||
if ((s=ffwopen(fn)) != FIOSUC) { /* Open writes message. */
|
||||
TTkopen();
|
||||
return (FALSE);
|
||||
}
|
||||
mlwrite("(Writing...)"); /* tell us were writing */
|
||||
lp = lforw(curbp->b_linep); /* First line. */
|
||||
nline = 0; /* Number of lines. */
|
||||
while (lp != curbp->b_linep) {
|
||||
if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
|
||||
break;
|
||||
++nline;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
if (s == FIOSUC) { /* No write error. */
|
||||
s = ffclose();
|
||||
if (s == FIOSUC) { /* No close error. */
|
||||
if (nline == 1)
|
||||
mlwrite("(Wrote 1 line)");
|
||||
else
|
||||
mlwrite("(Wrote %d lines)", nline);
|
||||
}
|
||||
} else /* Ignore close error */
|
||||
ffclose(); /* if a write error. */
|
||||
TTkopen();
|
||||
if (s != FIOSUC) /* Some sort of error. */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The command allows the user
|
||||
* to modify the file name associated with
|
||||
* the current buffer. It is like the "f" command
|
||||
* in UNIX "ed". The operation is simple; just zap
|
||||
* the name in the BUFFER structure, and mark the windows
|
||||
* as needing an update. You can type a blank line at the
|
||||
* prompt if you wish.
|
||||
*/
|
||||
filename(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register int s;
|
||||
char fname[NFILEN];
|
||||
|
||||
if (restflag) /* don't allow this command if restricted */
|
||||
return(resterr());
|
||||
if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
|
||||
return (s);
|
||||
if (s == FALSE)
|
||||
strcpy(curbp->b_fname, "");
|
||||
else
|
||||
strcpy(curbp->b_fname, fname);
|
||||
wp = wheadp; /* Update mode lines. */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
curbp->b_mode &= ~MDVIEW; /* no longer read only mode */
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert file "fname" into the current
|
||||
* buffer, Called by insert file command. Return the final
|
||||
* status of the read.
|
||||
*/
|
||||
ifile(fname)
|
||||
char fname[];
|
||||
{
|
||||
register LINE *lp0;
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register int i;
|
||||
register BUFFER *bp;
|
||||
register int s;
|
||||
register int nbytes;
|
||||
register int nline;
|
||||
int lflag; /* any lines longer than allowed? */
|
||||
char mesg[NSTRING];
|
||||
|
||||
bp = curbp; /* Cheap. */
|
||||
bp->b_flag |= BFCHG; /* we have changed */
|
||||
bp->b_flag &= ~BFINVS; /* and are not temporary*/
|
||||
if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
|
||||
goto out;
|
||||
if (s == FIOFNF) { /* File not found. */
|
||||
mlwrite("(No such file)");
|
||||
return(FALSE);
|
||||
}
|
||||
mlwrite("(Inserting file)");
|
||||
|
||||
#if CRYPT
|
||||
s = resetkey();
|
||||
if (s != TRUE)
|
||||
return(s);
|
||||
#endif
|
||||
/* back up a line and save the mark here */
|
||||
curwp->w_dotp = lback(curwp->w_dotp);
|
||||
curwp->w_doto = 0;
|
||||
curwp->w_markp = curwp->w_dotp;
|
||||
curwp->w_marko = 0;
|
||||
|
||||
nline = 0;
|
||||
lflag = FALSE;
|
||||
while ((s=ffgetline()) == FIOSUC) {
|
||||
nbytes = strlen(fline);
|
||||
if ((lp1=lalloc(nbytes)) == NULL) {
|
||||
s = FIOMEM; /* Keep message on the */
|
||||
break; /* display. */
|
||||
}
|
||||
lp0 = curwp->w_dotp; /* line previous to insert */
|
||||
lp2 = lp0->l_fp; /* line after insert */
|
||||
|
||||
/* re-link new line between lp0 and lp2 */
|
||||
lp2->l_bp = lp1;
|
||||
lp0->l_fp = lp1;
|
||||
lp1->l_bp = lp0;
|
||||
lp1->l_fp = lp2;
|
||||
|
||||
/* and advance and write out the current line */
|
||||
curwp->w_dotp = lp1;
|
||||
for (i=0; i<nbytes; ++i)
|
||||
lputc(lp1, i, fline[i]);
|
||||
++nline;
|
||||
}
|
||||
ffclose(); /* Ignore errors. */
|
||||
curwp->w_markp = lforw(curwp->w_markp);
|
||||
strcpy(mesg, "(");
|
||||
if (s==FIOERR) {
|
||||
strcat(mesg, "I/O ERROR, ");
|
||||
curbp->b_flag |= BFTRUNC;
|
||||
}
|
||||
if (s == FIOMEM) {
|
||||
strcat(mesg, "OUT OF MEMORY, ");
|
||||
curbp->b_flag |= BFTRUNC;
|
||||
}
|
||||
sprintf(&mesg[strlen(mesg)], "Inserted %d line", nline);
|
||||
if (nline > 1)
|
||||
strcat(mesg, "s");
|
||||
strcat(mesg, ")");
|
||||
mlwrite(mesg);
|
||||
|
||||
out:
|
||||
/* advance to the next line and mark the window for changes */
|
||||
curwp->w_dotp = lforw(curwp->w_dotp);
|
||||
curwp->w_flag |= WFHARD | WFMODE;
|
||||
|
||||
/* copy window parameters back to the buffer structure */
|
||||
curbp->b_dotp = curwp->w_dotp;
|
||||
curbp->b_doto = curwp->w_doto;
|
||||
curbp->b_markp = curwp->w_markp;
|
||||
curbp->b_marko = curwp->w_marko;
|
||||
|
||||
if (s == FIOERR) /* False if error. */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
228
fileio.c
Normal file
228
fileio.c
Normal file
@ -0,0 +1,228 @@
|
||||
/* FILEIO.C
|
||||
*
|
||||
* The routines in this file read and write ASCII files from the disk. All of
|
||||
* the knowledge about files are here.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if PKCODE
|
||||
extern int nullflag;
|
||||
#endif
|
||||
|
||||
FILE *ffp; /* File pointer, all functions. */
|
||||
int eofflag; /* end-of-file flag */
|
||||
|
||||
/*
|
||||
* Open a file for reading.
|
||||
*/
|
||||
ffropen(fn)
|
||||
char *fn;
|
||||
{
|
||||
if ((ffp=fopen(fn, "r")) == NULL)
|
||||
return (FIOFNF);
|
||||
eofflag = FALSE;
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a file for writing. Return TRUE if all is well, and FALSE on error
|
||||
* (cannot create).
|
||||
*/
|
||||
ffwopen(fn)
|
||||
char *fn;
|
||||
{
|
||||
#if VMS
|
||||
register int fd;
|
||||
|
||||
if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
|
||||
|| (ffp=fdopen(fd, "w")) == NULL) {
|
||||
#else
|
||||
if ((ffp=fopen(fn, "w")) == NULL) {
|
||||
#endif
|
||||
mlwrite("Cannot open file for writing");
|
||||
return (FIOERR);
|
||||
}
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close a file. Should look at the status in all systems.
|
||||
*/
|
||||
ffclose()
|
||||
{
|
||||
/* free this since we do not need it anymore */
|
||||
if (fline) {
|
||||
free(fline);
|
||||
fline = NULL;
|
||||
}
|
||||
eofflag = FALSE;
|
||||
|
||||
#if MSDOS & CTRLZ
|
||||
fputc(26, ffp); /* add a ^Z at the end of the file */
|
||||
#endif
|
||||
|
||||
#if V7 | USG | BSD | (MSDOS & (MSC | TURBO))
|
||||
if (fclose(ffp) != FALSE) {
|
||||
mlwrite("Error closing file");
|
||||
return(FIOERR);
|
||||
}
|
||||
return(FIOSUC);
|
||||
#else
|
||||
fclose(ffp);
|
||||
return (FIOSUC);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a line to the already opened file. The "buf" points to the buffer,
|
||||
* and the "nbuf" is its length, less the free newline. Return the status.
|
||||
* Check only at the newline.
|
||||
*/
|
||||
ffputline(buf, nbuf)
|
||||
char buf[];
|
||||
{
|
||||
register int i;
|
||||
#if CRYPT
|
||||
char c; /* character to translate */
|
||||
|
||||
if (cryptflag) {
|
||||
for (i = 0; i < nbuf; ++i) {
|
||||
c = buf[i] & 0xff;
|
||||
crypt(&c, 1);
|
||||
fputc(c, ffp);
|
||||
}
|
||||
} else
|
||||
for (i = 0; i < nbuf; ++i)
|
||||
fputc(buf[i]&0xFF, ffp);
|
||||
#else
|
||||
for (i = 0; i < nbuf; ++i)
|
||||
fputc(buf[i]&0xFF, ffp);
|
||||
#endif
|
||||
|
||||
fputc('\n', ffp);
|
||||
|
||||
if (ferror(ffp)) {
|
||||
mlwrite("Write I/O error");
|
||||
return (FIOERR);
|
||||
}
|
||||
|
||||
return (FIOSUC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a line from a file, and store the bytes in the supplied buffer. The
|
||||
* "nbuf" is the length of the buffer. Complain about long lines and lines
|
||||
* at the end of the file that don't have a newline present. Check for I/O
|
||||
* errors too. Return status.
|
||||
*/
|
||||
ffgetline()
|
||||
|
||||
{
|
||||
register int c; /* current character read */
|
||||
register int i; /* current index into fline */
|
||||
register char *tmpline; /* temp storage for expanding line */
|
||||
|
||||
/* if we are at the end...return it */
|
||||
if (eofflag)
|
||||
return(FIOEOF);
|
||||
|
||||
/* dump fline if it ended up too big */
|
||||
if (flen > NSTRING) {
|
||||
free(fline);
|
||||
fline = NULL;
|
||||
}
|
||||
|
||||
/* if we don't have an fline, allocate one */
|
||||
if (fline == NULL)
|
||||
if ((fline = malloc(flen = NSTRING)) == NULL)
|
||||
return(FIOMEM);
|
||||
|
||||
/* read the line in */
|
||||
#if PKCODE
|
||||
if (!nullflag) {
|
||||
if (fgets(fline, NSTRING, ffp) == (char *)NULL) { /* EOF ? */
|
||||
i = 0;
|
||||
c = EOF;
|
||||
}
|
||||
else {
|
||||
i = strlen(fline);
|
||||
c = 0;
|
||||
if (i > 0) {
|
||||
c = fline[i-1];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
i = 0;
|
||||
c = fgetc(ffp);
|
||||
}
|
||||
while (c != EOF && c != '\n') {
|
||||
#else
|
||||
i = 0;
|
||||
while ((c = fgetc(ffp)) != EOF && c != '\n') {
|
||||
#endif
|
||||
#if PKCODE
|
||||
if (c) {
|
||||
#endif
|
||||
fline[i++] = c;
|
||||
/* if it's longer, get more room */
|
||||
if (i >= flen) {
|
||||
if ((tmpline = malloc(flen+NSTRING)) == NULL)
|
||||
return(FIOMEM);
|
||||
strncpy(tmpline, fline, flen);
|
||||
flen += NSTRING;
|
||||
free(fline);
|
||||
fline = tmpline;
|
||||
}
|
||||
#if PKCODE
|
||||
}
|
||||
c = fgetc(ffp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* test for any errors that may have occured */
|
||||
if (c == EOF) {
|
||||
if (ferror(ffp)) {
|
||||
mlwrite("File read error");
|
||||
return(FIOERR);
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
eofflag = TRUE;
|
||||
else
|
||||
return(FIOEOF);
|
||||
}
|
||||
|
||||
/* terminate and decrypt the string */
|
||||
fline[i] = 0;
|
||||
#if CRYPT
|
||||
if (cryptflag)
|
||||
crypt(fline, strlen(fline));
|
||||
#endif
|
||||
return(FIOSUC);
|
||||
}
|
||||
|
||||
int fexist(fname) /* does <fname> exist on disk? */
|
||||
|
||||
char *fname; /* file to check for existance */
|
||||
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
/* try to open the file for reading */
|
||||
fp = fopen(fname, "r");
|
||||
|
||||
/* if it fails, just return false! */
|
||||
if (fp == NULL)
|
||||
return(FALSE);
|
||||
|
||||
/* otherwise, close it and report true */
|
||||
fclose(fp);
|
||||
return(TRUE);
|
||||
}
|
517
ibmpc.c
Normal file
517
ibmpc.c
Normal file
@ -0,0 +1,517 @@
|
||||
/* IBMPC.C
|
||||
*
|
||||
* The routines in this file provide support for the IBM-PC and other
|
||||
* compatible terminals. It goes directly to the graphics RAM to do
|
||||
* screen output. It compiles into nothing if not an IBM-PC driver
|
||||
* Supported monitor cards include CGA, MONO and EGA.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#define termdef 1 /* don't define "term" external */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if IBMPC
|
||||
#if PKCODE
|
||||
#define NROW 50
|
||||
#else
|
||||
#define NROW 43 /* Max Screen size. */
|
||||
#endif
|
||||
#define NCOL 80 /* Edit if you want to. */
|
||||
#define MARGIN 8 /* size of minimim margin and */
|
||||
#define SCRSIZ 64 /* scroll size for extended lines */
|
||||
#define NPAUSE 200 /* # times thru update to pause */
|
||||
#define BEL 0x07 /* BEL character. */
|
||||
#define ESC 0x1B /* ESC character. */
|
||||
#define SPACE 32 /* space character */
|
||||
|
||||
#define SCADC 0xb8000000L /* CGA address of screen RAM */
|
||||
#define SCADM 0xb0000000L /* MONO address of screen RAM */
|
||||
#define SCADE 0xb8000000L /* EGA address of screen RAM */
|
||||
|
||||
#define MONOCRSR 0x0B0D /* monochrome cursor */
|
||||
#define CGACRSR 0x0607 /* CGA cursor */
|
||||
#define EGACRSR 0x0709 /* EGA cursor */
|
||||
|
||||
#define CDCGA 0 /* color graphics card */
|
||||
#define CDMONO 1 /* monochrome text card */
|
||||
#define CDEGA 2 /* EGA color adapter */
|
||||
#if PKCODE
|
||||
#define CDVGA 3
|
||||
#endif
|
||||
#define CDSENSE 9 /* detect the card type */
|
||||
|
||||
#if PKCODE
|
||||
#define NDRIVE 4
|
||||
#else
|
||||
#define NDRIVE 3 /* number of screen drivers */
|
||||
#endif
|
||||
|
||||
int dtype = -1; /* current display type */
|
||||
char drvname[][8] = { /* screen resolution names */
|
||||
"CGA", "MONO", "EGA"
|
||||
#if PKCODE
|
||||
,"VGA"
|
||||
#endif
|
||||
};
|
||||
long scadd; /* address of screen ram */
|
||||
int *scptr[NROW]; /* pointer to screen lines */
|
||||
unsigned int sline[NCOL]; /* screen line image */
|
||||
int egaexist = FALSE; /* is an EGA card available? */
|
||||
extern union REGS rg; /* cpu register for use of DOS calls */
|
||||
|
||||
extern int ttopen(); /* Forward references. */
|
||||
extern int ttgetc();
|
||||
extern int ttputc();
|
||||
extern int ttflush();
|
||||
extern int ttclose();
|
||||
extern int ibmmove();
|
||||
extern int ibmeeol();
|
||||
extern int ibmeeop();
|
||||
extern int ibmbeep();
|
||||
extern int ibmopen();
|
||||
extern int ibmrev();
|
||||
extern int ibmcres();
|
||||
extern int ibmclose();
|
||||
extern int ibmputc();
|
||||
extern int ibmkopen();
|
||||
extern int ibmkclose();
|
||||
|
||||
#if COLOR
|
||||
extern int ibmfcol();
|
||||
extern int ibmbcol();
|
||||
extern int ibmscroll_reg();
|
||||
|
||||
int cfcolor = -1; /* current forground color */
|
||||
int cbcolor = -1; /* current background color */
|
||||
int ctrans[] = /* ansi to ibm color translation table */
|
||||
#if PKCODE
|
||||
{0, 4, 2, 6, 1, 5, 3, 7, 15};
|
||||
#else
|
||||
{0, 4, 2, 6, 1, 5, 3, 7};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Standard terminal interface dispatch table. Most of the fields point into
|
||||
* "termio" code.
|
||||
*/
|
||||
TERM term = {
|
||||
NROW-1,
|
||||
NROW-1,
|
||||
NCOL,
|
||||
NCOL,
|
||||
MARGIN,
|
||||
SCRSIZ,
|
||||
NPAUSE,
|
||||
ibmopen,
|
||||
ibmclose,
|
||||
ibmkopen,
|
||||
ibmkclose,
|
||||
ttgetc,
|
||||
ibmputc,
|
||||
ttflush,
|
||||
ibmmove,
|
||||
ibmeeol,
|
||||
ibmeeop,
|
||||
ibmbeep,
|
||||
ibmrev,
|
||||
ibmcres
|
||||
#if COLOR
|
||||
, ibmfcol,
|
||||
ibmbcol
|
||||
#endif
|
||||
#if SCROLLCODE
|
||||
, ibmscroll_reg
|
||||
#endif
|
||||
};
|
||||
|
||||
#if COLOR
|
||||
ibmfcol(color) /* set the current output color */
|
||||
|
||||
int color; /* color to set */
|
||||
|
||||
{
|
||||
cfcolor = ctrans[color];
|
||||
}
|
||||
|
||||
ibmbcol(color) /* set the current background color */
|
||||
|
||||
int color; /* color to set */
|
||||
|
||||
{
|
||||
cbcolor = ctrans[color];
|
||||
}
|
||||
#endif
|
||||
|
||||
ibmmove(row, col)
|
||||
{
|
||||
rg.h.ah = 2; /* set cursor position function code */
|
||||
rg.h.dl = col;
|
||||
rg.h.dh = row;
|
||||
rg.h.bh = 0; /* set screen page number */
|
||||
int86(0x10, &rg, &rg);
|
||||
}
|
||||
|
||||
ibmeeol() /* erase to the end of the line */
|
||||
|
||||
{
|
||||
unsigned int attr; /* attribute byte mask to place in RAM */
|
||||
unsigned int *lnptr; /* pointer to the destination line */
|
||||
int i;
|
||||
int ccol; /* current column cursor lives */
|
||||
int crow; /* row */
|
||||
|
||||
/* find the current cursor position */
|
||||
rg.h.ah = 3; /* read cursor position function code */
|
||||
rg.h.bh = 0; /* current video page */
|
||||
int86(0x10, &rg, &rg);
|
||||
ccol = rg.h.dl; /* record current column */
|
||||
crow = rg.h.dh; /* and row */
|
||||
|
||||
/* build the attribute byte and setup the screen pointer */
|
||||
#if COLOR
|
||||
if (dtype != CDMONO)
|
||||
attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
|
||||
else
|
||||
attr = 0x0700;
|
||||
#else
|
||||
attr = 0x0700;
|
||||
#endif
|
||||
lnptr = &sline[0];
|
||||
for (i=0; i < term.t_ncol; i++)
|
||||
*lnptr++ = SPACE | attr;
|
||||
|
||||
if (flickcode && (dtype == CDCGA)) {
|
||||
/* wait for vertical retrace to be off */
|
||||
while ((inp(0x3da) & 8))
|
||||
;
|
||||
|
||||
/* and to be back on */
|
||||
while ((inp(0x3da) & 8) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
/* and send the string out */
|
||||
movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2);
|
||||
|
||||
}
|
||||
|
||||
ibmputc(ch) /* put a character at the current position in the
|
||||
current colors */
|
||||
|
||||
int ch;
|
||||
|
||||
{
|
||||
rg.h.ah = 14; /* write char to screen with current attrs */
|
||||
rg.h.al = ch;
|
||||
#if COLOR
|
||||
if (dtype != CDMONO)
|
||||
rg.h.bl = cfcolor;
|
||||
else
|
||||
rg.h.bl = 0x07;
|
||||
#else
|
||||
rg.h.bl = 0x07;
|
||||
#endif
|
||||
int86(0x10, &rg, &rg);
|
||||
}
|
||||
|
||||
ibmeeop()
|
||||
{
|
||||
int attr; /* attribute to fill screen with */
|
||||
|
||||
rg.h.ah = 6; /* scroll page up function code */
|
||||
rg.h.al = 0; /* # lines to scroll (clear it) */
|
||||
rg.x.cx = 0; /* upper left corner of scroll */
|
||||
rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
|
||||
/* lower right corner of scroll */
|
||||
#if COLOR
|
||||
if (dtype != CDMONO)
|
||||
attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
|
||||
else
|
||||
attr = 0;
|
||||
#else
|
||||
attr = 0;
|
||||
#endif
|
||||
rg.h.bh = attr;
|
||||
int86(0x10, &rg, &rg);
|
||||
}
|
||||
|
||||
ibmrev(state) /* change reverse video state */
|
||||
|
||||
int state; /* TRUE = reverse, FALSE = normal */
|
||||
|
||||
{
|
||||
/* This never gets used under the IBM-PC driver */
|
||||
}
|
||||
|
||||
ibmcres(res) /* change screen resolution */
|
||||
|
||||
char *res; /* resolution to change to */
|
||||
|
||||
{
|
||||
int i; /* index */
|
||||
|
||||
for (i = 0; i < NDRIVE; i++)
|
||||
if (strcmp(res, drvname[i]) == 0) {
|
||||
scinit(i);
|
||||
return(TRUE);
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#if SCROLLCODE
|
||||
|
||||
/* move howmany lines starting at from to to */
|
||||
ibmscroll_reg(from, to, howmany)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (to < from)
|
||||
for (i = 0; i < howmany; i++)
|
||||
movmem(scptr[from+i], scptr[to+i], term.t_ncol*2);
|
||||
else
|
||||
if (to > from)
|
||||
for (i = howmany-1; i >= 0; i--)
|
||||
movmem(scptr[from+i], scptr[to+i], term.t_ncol*2);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
spal() /* reset the pallette registers */
|
||||
|
||||
{
|
||||
/* nothin here now..... */
|
||||
}
|
||||
|
||||
ibmbeep()
|
||||
{
|
||||
bdos(6, BEL, 0);
|
||||
}
|
||||
|
||||
ibmopen()
|
||||
{
|
||||
scinit(CDSENSE);
|
||||
revexist = TRUE;
|
||||
ttopen();
|
||||
}
|
||||
|
||||
ibmclose()
|
||||
|
||||
{
|
||||
#if COLOR
|
||||
ibmfcol(7);
|
||||
ibmbcol(0);
|
||||
#endif
|
||||
/* if we had the EGA open... close it */
|
||||
if (dtype == CDEGA)
|
||||
egaclose();
|
||||
#if PKCODE
|
||||
if (dtype == CDVGA)
|
||||
egaclose();
|
||||
#endif
|
||||
|
||||
ttclose();
|
||||
}
|
||||
|
||||
ibmkopen() /* open the keyboard */
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
ibmkclose() /* close the keyboard */
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
scinit(type) /* initialize the screen head pointers */
|
||||
|
||||
int type; /* type of adapter to init for */
|
||||
|
||||
{
|
||||
union {
|
||||
long laddr; /* long form of address */
|
||||
int *paddr; /* pointer form of address */
|
||||
} addr;
|
||||
int i;
|
||||
|
||||
/* if asked...find out what display is connected */
|
||||
if (type == CDSENSE)
|
||||
type = getboard();
|
||||
|
||||
/* if we have nothing to do....don't do it */
|
||||
if (dtype == type)
|
||||
return(TRUE);
|
||||
|
||||
/* if we try to switch to EGA and there is none, don't */
|
||||
if (type == CDEGA && egaexist != TRUE)
|
||||
return(FALSE);
|
||||
|
||||
/* if we had the EGA open... close it */
|
||||
if (dtype == CDEGA)
|
||||
egaclose();
|
||||
#if PKCODE
|
||||
if (dtype == CDVGA)
|
||||
egaclose();
|
||||
#endif
|
||||
|
||||
/* and set up the various parameters as needed */
|
||||
switch (type) {
|
||||
case CDMONO: /* Monochrome adapter */
|
||||
scadd = SCADM;
|
||||
newsize(TRUE, 25);
|
||||
break;
|
||||
|
||||
case CDCGA: /* Color graphics adapter */
|
||||
scadd = SCADC;
|
||||
newsize(TRUE, 25);
|
||||
break;
|
||||
|
||||
case CDEGA: /* Enhanced graphics adapter */
|
||||
scadd = SCADE;
|
||||
egaopen();
|
||||
newsize(TRUE, 43);
|
||||
break;
|
||||
case CDVGA: /* Enhanced graphics adapter */
|
||||
scadd = SCADE;
|
||||
egaopen();
|
||||
newsize(TRUE, 50);
|
||||
break;
|
||||
}
|
||||
|
||||
/* reset the $sres environment variable */
|
||||
strcpy(sres, drvname[type]);
|
||||
dtype = type;
|
||||
|
||||
/* initialize the screen pointer array */
|
||||
for (i = 0; i < NROW; i++) {
|
||||
addr.laddr = scadd + (long)(NCOL * i * 2);
|
||||
scptr[i] = addr.paddr;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* getboard: Determine which type of display board is attached.
|
||||
Current known types include:
|
||||
|
||||
CDMONO Monochrome graphics adapter
|
||||
CDCGA Color Graphics Adapter
|
||||
CDEGA Extended graphics Adapter
|
||||
*/
|
||||
|
||||
/* getboard: Detect the current display adapter
|
||||
if MONO set to MONO
|
||||
CGA set to CGA EGAexist = FALSE
|
||||
EGA set to CGA EGAexist = TRUE
|
||||
*/
|
||||
|
||||
int getboard()
|
||||
|
||||
{
|
||||
int type; /* board type to return */
|
||||
|
||||
type = CDCGA;
|
||||
int86(0x11, &rg, &rg);
|
||||
if ((((rg.x.ax >> 4) & 3) == 3))
|
||||
type = CDMONO;
|
||||
|
||||
/* test if EGA present */
|
||||
rg.x.ax = 0x1200;
|
||||
rg.x.bx = 0xff10;
|
||||
int86(0x10,&rg, &rg); /* If EGA, bh=0-1 and bl=0-3 */
|
||||
egaexist = !(rg.x.bx & 0xfefc); /* Yes, it's EGA */
|
||||
return(type);
|
||||
}
|
||||
|
||||
egaopen() /* init the computer to work with the EGA */
|
||||
|
||||
{
|
||||
/* put the beast into EGA 43 row mode */
|
||||
rg.x.ax = 3;
|
||||
int86(16, &rg, &rg);
|
||||
|
||||
rg.h.ah = 17; /* set char. generator function code */
|
||||
rg.h.al = 18; /* to 8 by 8 double dot ROM */
|
||||
rg.h.bl = 0; /* block 0 */
|
||||
int86(16, &rg, &rg);
|
||||
|
||||
rg.h.ah = 18; /* alternate select function code */
|
||||
rg.h.al = 0; /* clear AL for no good reason */
|
||||
rg.h.bl = 32; /* alt. print screen routine */
|
||||
int86(16, &rg, &rg);
|
||||
|
||||
rg.h.ah = 1; /* set cursor size function code */
|
||||
rg.x.cx = 0x0607; /* turn cursor on code */
|
||||
int86(0x10, &rg, &rg);
|
||||
|
||||
outp(0x3d4, 10); /* video bios bug patch */
|
||||
outp(0x3d5, 6);
|
||||
}
|
||||
|
||||
egaclose()
|
||||
|
||||
{
|
||||
/* put the beast into 80 column mode */
|
||||
rg.x.ax = 3;
|
||||
int86(16, &rg, &rg);
|
||||
}
|
||||
|
||||
scwrite(row, outstr, forg, bacg) /* write a line out*/
|
||||
|
||||
int row; /* row of screen to place outstr on */
|
||||
char *outstr; /* string to write out (must be term.t_ncol long) */
|
||||
int forg; /* forground color of string to write */
|
||||
int bacg; /* background color */
|
||||
|
||||
{
|
||||
unsigned int attr; /* attribute byte mask to place in RAM */
|
||||
unsigned int *lnptr; /* pointer to the destination line */
|
||||
int i;
|
||||
|
||||
/* build the attribute byte and setup the screen pointer */
|
||||
#if COLOR
|
||||
if (dtype != CDMONO)
|
||||
attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
|
||||
else
|
||||
attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
|
||||
#else
|
||||
attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
|
||||
#endif
|
||||
lnptr = &sline[0];
|
||||
for (i=0; i<term.t_ncol; i++)
|
||||
*lnptr++ = (outstr[i] & 255) | attr;
|
||||
|
||||
if (flickcode && (dtype == CDCGA)) {
|
||||
/* wait for vertical retrace to be off */
|
||||
while ((inp(0x3da) & 8))
|
||||
;
|
||||
|
||||
/* and to be back on */
|
||||
while ((inp(0x3da) & 8) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
/* and send the string out */
|
||||
movmem(&sline[0], scptr[row], term.t_ncol*2);
|
||||
}
|
||||
|
||||
#if FNLABEL
|
||||
fnclabel(f, n) /* label a function key */
|
||||
|
||||
int f,n; /* default flag, numeric argument [unused] */
|
||||
|
||||
{
|
||||
/* on machines with no function keys...don't bother */
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
ibmhello()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
713
input.c
Normal file
713
input.c
Normal file
@ -0,0 +1,713 @@
|
||||
/* INPUT.C
|
||||
*
|
||||
* Various input routines
|
||||
*
|
||||
* written by Daniel Lawrence 5/9/86
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if PKCODE
|
||||
#if MSDOS && TURBO
|
||||
#include <dir.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PKCODE && (UNIX || (MSDOS && TURBO))
|
||||
#define COMPLC 1
|
||||
#else
|
||||
#define COMPLC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
{
|
||||
char c; /* input character */
|
||||
char buf[NPAT]; /* prompt to user */
|
||||
|
||||
for (;;) {
|
||||
/* build and prompt the user */
|
||||
strcpy(buf, prompt);
|
||||
strcat(buf, " (y/n)? ");
|
||||
mlwrite(buf);
|
||||
|
||||
/* get the responce */
|
||||
c = tgetc();
|
||||
|
||||
if (c == ectoc(abortc)) /* Bail out! */
|
||||
return(ABORT);
|
||||
|
||||
if (c=='y' || c=='Y')
|
||||
return(TRUE);
|
||||
|
||||
if (c=='n' || c=='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;
|
||||
{
|
||||
return(nextarg(prompt, buf, nbuf, ctoec('\n')));
|
||||
}
|
||||
|
||||
mlreplyt(prompt, buf, nbuf, eolchar)
|
||||
|
||||
char *prompt;
|
||||
char *buf;
|
||||
int eolchar;
|
||||
|
||||
{
|
||||
return(nextarg(prompt, buf, nbuf, eolchar));
|
||||
}
|
||||
|
||||
/* ectoc: expanded character to character
|
||||
colapse the CONTROL and SPEC flags back into an ascii code */
|
||||
|
||||
ectoc(c)
|
||||
|
||||
int c;
|
||||
|
||||
{
|
||||
if (c & CONTROL)
|
||||
c = c & ~(CONTROL | 0x40);
|
||||
if (c & SPEC)
|
||||
c= c & 255;
|
||||
return(c);
|
||||
}
|
||||
|
||||
/* ctoec: character to extended character
|
||||
pull out the CONTROL and SPEC prefixes (if possible) */
|
||||
|
||||
ctoec(c)
|
||||
|
||||
int c;
|
||||
|
||||
{
|
||||
if (c>=0x00 && c<=0x1F)
|
||||
c = CONTROL | (c+'@');
|
||||
return (c);
|
||||
}
|
||||
|
||||
/* get a command name from the command line. Command completion means
|
||||
that pressing a <SPACE> will attempt to complete an unfinished command
|
||||
name if it is unique.
|
||||
*/
|
||||
|
||||
int (*getname())()
|
||||
|
||||
{
|
||||
register int cpos; /* current column on screen output */
|
||||
register int c;
|
||||
register char *sp; /* pointer to string for output */
|
||||
register NBIND *ffp; /* first ptr to entry in name binding table */
|
||||
register NBIND *cffp; /* current ptr to entry in name binding table */
|
||||
register NBIND *lffp; /* last ptr to entry in name binding table */
|
||||
char buf[NSTRING]; /* buffer to hold tentative command name */
|
||||
int (*fncmatch())();
|
||||
|
||||
/* starting at the beginning of the string buffer */
|
||||
cpos = 0;
|
||||
|
||||
/* if we are executing a command line get the next arg and match it */
|
||||
if (clexec) {
|
||||
if (macarg(buf) != TRUE)
|
||||
return(FALSE);
|
||||
return(fncmatch(&buf[0]));
|
||||
}
|
||||
|
||||
/* build a name string from the keyboard */
|
||||
while (TRUE) {
|
||||
c = tgetc();
|
||||
|
||||
/* if we are at the end, just match it */
|
||||
if (c == 0x0d) {
|
||||
buf[cpos] = 0;
|
||||
|
||||
/* and match it off */
|
||||
return(fncmatch(&buf[0]));
|
||||
|
||||
} else if (c == ectoc(abortc)) { /* Bell, abort */
|
||||
ctrlg(FALSE, 0);
|
||||
TTflush();
|
||||
return( (int (*)()) NULL);
|
||||
|
||||
} else if (c == 0x7F || c == 0x08) { /* rubout/erase */
|
||||
if (cpos != 0) {
|
||||
TTputc('\b');
|
||||
TTputc(' ');
|
||||
TTputc('\b');
|
||||
--ttcol;
|
||||
--cpos;
|
||||
TTflush();
|
||||
}
|
||||
|
||||
} else if (c == 0x15) { /* C-U, kill */
|
||||
while (cpos != 0) {
|
||||
TTputc('\b');
|
||||
TTputc(' ');
|
||||
TTputc('\b');
|
||||
--cpos;
|
||||
--ttcol;
|
||||
}
|
||||
|
||||
TTflush();
|
||||
|
||||
} else if (c == ' ' || c == 0x1b || c == 0x09) {
|
||||
/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
|
||||
/* attempt a completion */
|
||||
buf[cpos] = 0; /* terminate it for us */
|
||||
ffp = &names[0]; /* scan for matches */
|
||||
while (ffp->n_func != NULL) {
|
||||
if (strncmp(buf, ffp->n_name, strlen(buf)) == 0) {
|
||||
/* a possible match! More than one? */
|
||||
if ((ffp + 1)->n_func == NULL ||
|
||||
(strncmp(buf, (ffp+1)->n_name, strlen(buf)) != 0)) {
|
||||
/* no...we match, print it */
|
||||
sp = ffp->n_name + cpos;
|
||||
while (*sp)
|
||||
TTputc(*sp++);
|
||||
TTflush();
|
||||
return(ffp->n_func);
|
||||
} else {
|
||||
/* << << << << << << << << << << << << << << << << << */
|
||||
/* try for a partial match against the list */
|
||||
|
||||
/* first scan down until we no longer match the current input */
|
||||
lffp = (ffp + 1);
|
||||
while ((lffp+1)->n_func != NULL) {
|
||||
if (strncmp(buf, (lffp+1)->n_name, strlen(buf)) != 0)
|
||||
break;
|
||||
++lffp;
|
||||
}
|
||||
|
||||
/* and now, attempt to partial complete the string, char at a time */
|
||||
while (TRUE) {
|
||||
/* add the next char in */
|
||||
buf[cpos] = ffp->n_name[cpos];
|
||||
|
||||
/* scan through the candidates */
|
||||
cffp = ffp + 1;
|
||||
while (cffp <= lffp) {
|
||||
if (cffp->n_name[cpos] != buf[cpos])
|
||||
goto onward;
|
||||
++cffp;
|
||||
}
|
||||
|
||||
/* add the character */
|
||||
TTputc(buf[cpos++]);
|
||||
}
|
||||
/* << << << << << << << << << << << << << << << << << */
|
||||
}
|
||||
}
|
||||
++ffp;
|
||||
}
|
||||
|
||||
/* no match.....beep and onward */
|
||||
TTbeep();
|
||||
onward:;
|
||||
TTflush();
|
||||
/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
|
||||
} else {
|
||||
if (cpos < NSTRING-1 && c > ' ') {
|
||||
buf[cpos++] = c;
|
||||
TTputc(c);
|
||||
}
|
||||
|
||||
++ttcol;
|
||||
TTflush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* tgetc: Get a key from the terminal driver, resolve any keyboard
|
||||
macro action */
|
||||
|
||||
int tgetc()
|
||||
|
||||
{
|
||||
int c; /* fetched character */
|
||||
|
||||
/* if we are playing a keyboard macro back, */
|
||||
if (kbdmode == PLAY) {
|
||||
|
||||
/* if there is some left... */
|
||||
if (kbdptr < kbdend)
|
||||
return((int)*kbdptr++);
|
||||
|
||||
/* at the end of last repitition? */
|
||||
if (--kbdrep < 1) {
|
||||
kbdmode = STOP;
|
||||
#if VISMAC == 0
|
||||
/* force a screen update after all is done */
|
||||
update(FALSE);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
/* reset the macro to the begining for the next rep */
|
||||
kbdptr = &kbdm[0];
|
||||
return((int)*kbdptr++);
|
||||
}
|
||||
}
|
||||
|
||||
/* fetch a character from the terminal driver */
|
||||
c = TTgetc();
|
||||
|
||||
/* record it for $lastkey */
|
||||
lastkey = c;
|
||||
|
||||
/* save it if we need to */
|
||||
if (kbdmode == RECORD) {
|
||||
*kbdptr++ = c;
|
||||
kbdend = kbdptr;
|
||||
|
||||
/* don't overrun the buffer */
|
||||
if (kbdptr == &kbdm[NKBDM - 1]) {
|
||||
kbdmode = STOP;
|
||||
TTbeep();
|
||||
}
|
||||
}
|
||||
|
||||
/* and finally give the char back */
|
||||
return(c);
|
||||
}
|
||||
|
||||
/* GET1KEY: Get one keystroke. The only prefixs legal here
|
||||
are the SPEC and CONTROL prefixes.
|
||||
*/
|
||||
|
||||
get1key()
|
||||
|
||||
{
|
||||
int c;
|
||||
|
||||
/* get a keystroke */
|
||||
c = tgetc();
|
||||
|
||||
#if MSDOS
|
||||
if (c == 0) { /* Apply SPEC prefix */
|
||||
c = tgetc();
|
||||
if (c>=0x00 && c<=0x1F) /* control key? */
|
||||
c = CONTROL | (c+'@');
|
||||
return(SPEC | c);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
|
||||
c = CONTROL | (c+'@');
|
||||
return (c);
|
||||
}
|
||||
|
||||
/* GETCMD: Get a command from the keyboard. Process all applicable
|
||||
prefix keys
|
||||
*/
|
||||
getcmd()
|
||||
|
||||
{
|
||||
int c; /* fetched keystroke */
|
||||
#if VT220
|
||||
int d; /* second character P.K. */
|
||||
int cmask = 0;
|
||||
#endif
|
||||
/* get initial character */
|
||||
c = get1key();
|
||||
|
||||
#if VT220
|
||||
proc_metac:
|
||||
#endif
|
||||
/* process META prefix */
|
||||
if (c == (CONTROL | '[')) {
|
||||
c = get1key();
|
||||
#if VT220
|
||||
if (c == '[' || c == 'O') { /* CSI P.K. */
|
||||
c = get1key();
|
||||
if (c >= 'A' && c <= 'D')
|
||||
return(SPEC | c | cmask);
|
||||
if (c >= 'E' && c <= 'z' && c != 'i' && c != 'c')
|
||||
return(SPEC | c | cmask);
|
||||
d = get1key();
|
||||
if (d == '~') /* ESC [ n ~ P.K. */
|
||||
return(SPEC | c | cmask);
|
||||
switch (c) { /* ESC [ n n ~ P.K. */
|
||||
case '1': c = d + 32;
|
||||
break;
|
||||
case '2': c = d + 48;
|
||||
break;
|
||||
case '3': c = d + 64;
|
||||
break;
|
||||
default: c = '?';
|
||||
break;
|
||||
}
|
||||
if (d != '~') /* eat tilde P.K. */
|
||||
get1key();
|
||||
if (c == 'i') { /* DO key P.K. */
|
||||
c = ctlxc;
|
||||
goto proc_ctlxc;
|
||||
}
|
||||
else if (c == 'c') /* ESC key P.K. */
|
||||
c = get1key();
|
||||
else
|
||||
return(SPEC | c | cmask);
|
||||
}
|
||||
#endif
|
||||
#if VT220
|
||||
if (c == (CONTROL | '[')) {
|
||||
cmask = META;
|
||||
goto proc_metac;
|
||||
}
|
||||
#endif
|
||||
if (islower(c)) /* Force to upper */
|
||||
c ^= DIFCASE;
|
||||
if (c>=0x00 && c<=0x1F) /* control key */
|
||||
c = CONTROL | (c+'@');
|
||||
return(META | c );
|
||||
}
|
||||
#if PKCODE
|
||||
else
|
||||
if (c == metac) {
|
||||
c = get1key();
|
||||
#if VT220
|
||||
if (c == (CONTROL | '[')) {
|
||||
cmask = META;
|
||||
goto proc_metac;
|
||||
}
|
||||
#endif
|
||||
if (islower(c)) /* Force to upper */
|
||||
c ^= DIFCASE;
|
||||
if (c>=0x00 && c<=0x1F) /* control key */
|
||||
c = CONTROL | (c+'@');
|
||||
return(META | c );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if VT220
|
||||
proc_ctlxc:
|
||||
#endif
|
||||
/* process CTLX prefix */
|
||||
if (c == ctlxc) {
|
||||
c = get1key();
|
||||
#if VT220
|
||||
if (c == (CONTROL | '[')) {
|
||||
cmask = CTLX;
|
||||
goto proc_metac;
|
||||
}
|
||||
#endif
|
||||
if (c>='a' && c<='z') /* Force to upper */
|
||||
c -= 0x20;
|
||||
if (c>=0x00 && c<=0x1F) /* control key */
|
||||
c = CONTROL | (c+'@');
|
||||
return(CTLX | c);
|
||||
}
|
||||
|
||||
/* otherwise, just return it */
|
||||
return(c);
|
||||
}
|
||||
|
||||
/* A more generalized prompt/reply function allowing the caller
|
||||
to specify the proper terminator. If the terminator is not
|
||||
a return ('\n') it will echo as "<NL>"
|
||||
*/
|
||||
getstring(prompt, buf, nbuf, eolchar)
|
||||
|
||||
char *prompt; char *buf; int eolchar;
|
||||
|
||||
{
|
||||
register int cpos; /* current character position in string */
|
||||
register int c;
|
||||
register int quotef; /* are we quoting the next char? */
|
||||
#if COMPLC
|
||||
int ffile, ocpos, nskip, didtry = 0;
|
||||
#if MSDOS
|
||||
struct ffblk ffblk;
|
||||
char *fcp;
|
||||
#endif
|
||||
#if UNIX
|
||||
static char tmp[] = "/tmp/meXXXXXX";
|
||||
FILE *tmpf = NULL;
|
||||
#endif
|
||||
ffile = (strcmp(prompt, "Find file: ") == 0
|
||||
|| strcmp(prompt, "View file: ") == 0
|
||||
|| strcmp(prompt, "Insert file: ") == 0
|
||||
|| strcmp(prompt, "Write file: ") == 0
|
||||
|| strcmp(prompt, "Read file: ") == 0
|
||||
|| strcmp(prompt, "File to execute: ") == 0);
|
||||
#endif
|
||||
|
||||
cpos = 0;
|
||||
quotef = FALSE;
|
||||
|
||||
/* prompt the user for the input string */
|
||||
mlwrite(prompt);
|
||||
|
||||
for (;;) {
|
||||
#if COMPLC
|
||||
if (! didtry)
|
||||
nskip = -1;
|
||||
didtry = 0;
|
||||
#endif
|
||||
/* get a character from the user */
|
||||
c = get1key();
|
||||
|
||||
/* If it is a <ret>, change it to a <NL> */
|
||||
#if PKCODE
|
||||
if (c == (CONTROL | 0x4d) && !quotef)
|
||||
#else
|
||||
if (c == (CONTROL | 0x4d))
|
||||
#endif
|
||||
c = CONTROL | 0x40 | '\n';
|
||||
|
||||
/* if they hit the line terminate, wrap it up */
|
||||
if (c == eolchar && quotef == FALSE) {
|
||||
buf[cpos++] = 0;
|
||||
|
||||
/* clear the message line */
|
||||
mlwrite("");
|
||||
TTflush();
|
||||
|
||||
/* if we default the buffer, return FALSE */
|
||||
if (buf[0] == 0)
|
||||
return(FALSE);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* change from command form back to character form */
|
||||
c = ectoc(c);
|
||||
|
||||
if (c == ectoc(abortc) && quotef == FALSE) {
|
||||
/* Abort the input? */
|
||||
ctrlg(FALSE, 0);
|
||||
TTflush();
|
||||
return(ABORT);
|
||||
} else if ((c==0x7F || c==0x08) && quotef==FALSE) {
|
||||
/* rubout/erase */
|
||||
if (cpos != 0) {
|
||||
outstring("\b \b");
|
||||
--ttcol;
|
||||
|
||||
if (buf[--cpos] < 0x20) {
|
||||
outstring("\b \b");
|
||||
--ttcol;
|
||||
}
|
||||
if (buf[cpos] == '\n') {
|
||||
outstring("\b\b \b\b");
|
||||
ttcol -= 2;
|
||||
}
|
||||
|
||||
TTflush();
|
||||
}
|
||||
|
||||
} else if (c == 0x15 && quotef == FALSE) {
|
||||
/* C-U, kill */
|
||||
while (cpos != 0) {
|
||||
outstring("\b \b");
|
||||
--ttcol;
|
||||
|
||||
if (buf[--cpos] < 0x20) {
|
||||
outstring("\b \b");
|
||||
--ttcol;
|
||||
}
|
||||
if (buf[cpos] == '\n') {
|
||||
outstring("\b\b \b\b");
|
||||
ttcol -= 2;
|
||||
}
|
||||
}
|
||||
TTflush();
|
||||
|
||||
#if COMPLC
|
||||
} else if ((c == 0x09 || c == ' ') && quotef == FALSE && ffile) {
|
||||
/* TAB, complete file name */
|
||||
char ffbuf[255];
|
||||
#if MSDOS
|
||||
char sffbuf[128];
|
||||
int lsav = -1;
|
||||
#endif
|
||||
int n, iswild = 0;
|
||||
|
||||
didtry = 1;
|
||||
ocpos = cpos;
|
||||
while (cpos != 0) {
|
||||
outstring("\b \b");
|
||||
--ttcol;
|
||||
|
||||
if (buf[--cpos] < 0x20) {
|
||||
outstring("\b \b");
|
||||
--ttcol;
|
||||
}
|
||||
if (buf[cpos] == '\n') {
|
||||
outstring("\b\b \b\b");
|
||||
ttcol -= 2;
|
||||
}
|
||||
if (buf[cpos] == '*' || buf[cpos] == '?')
|
||||
iswild = 1;
|
||||
#if MSDOS
|
||||
if (lsav < 0 && (buf[cpos] == '\\' ||
|
||||
buf[cpos] == '/' ||
|
||||
buf[cpos] == ':' && cpos == 1))
|
||||
lsav = cpos;
|
||||
#endif
|
||||
}
|
||||
TTflush();
|
||||
if (nskip < 0)
|
||||
{
|
||||
buf[ocpos] = 0;
|
||||
#if UNIX
|
||||
if (tmpf != NULL)
|
||||
fclose(tmpf);
|
||||
strcpy(tmp, "/tmp/meXXXXXX");
|
||||
strcpy(ffbuf, "echo ");
|
||||
strcat(ffbuf, buf);
|
||||
if (! iswild)
|
||||
strcat(ffbuf,"*");
|
||||
strcat(ffbuf, " >");
|
||||
mktemp(tmp);
|
||||
strcat(ffbuf, tmp);
|
||||
strcat(ffbuf, " 2>&1");
|
||||
system(ffbuf);
|
||||
tmpf = fopen(tmp, "r");
|
||||
#endif
|
||||
#if MSDOS
|
||||
strcpy(sffbuf, buf);
|
||||
if (! iswild)
|
||||
strcat(sffbuf,"*.*");
|
||||
#endif
|
||||
nskip = 0;
|
||||
}
|
||||
#if UNIX
|
||||
c = ' ';
|
||||
for (n = nskip; n > 0; n--)
|
||||
while ((c = getc(tmpf)) != EOF && c != ' ');
|
||||
#endif
|
||||
#if MSDOS
|
||||
if (nskip == 0)
|
||||
{
|
||||
strcpy(ffbuf, sffbuf);
|
||||
c = findfirst(ffbuf, &ffblk, FA_DIREC) ? '*' : ' ';
|
||||
}
|
||||
else if (nskip > 0)
|
||||
c = findnext(&ffblk) ? 0 : ' ';
|
||||
#endif
|
||||
nskip++;
|
||||
|
||||
if (c != ' ')
|
||||
{
|
||||
TTbeep();
|
||||
nskip = 0;
|
||||
}
|
||||
|
||||
#if UNIX
|
||||
while ((c = getc(tmpf)) != EOF && c != '\n' && c != ' ' && c != '*')
|
||||
#endif
|
||||
#if MSDOS
|
||||
if (c == '*')
|
||||
fcp = sffbuf;
|
||||
else
|
||||
{
|
||||
strncpy(buf, sffbuf, lsav+1);
|
||||
cpos = lsav+1;
|
||||
fcp = ffblk.ff_name;
|
||||
}
|
||||
while (c != 0 && (c = *fcp++) != 0 && c != '*')
|
||||
#endif
|
||||
{
|
||||
if (cpos < nbuf-1)
|
||||
buf[cpos++] = c;
|
||||
}
|
||||
#if UNIX
|
||||
if (c == '*')
|
||||
TTbeep();
|
||||
#endif
|
||||
|
||||
for (n = 0; n < cpos; n++)
|
||||
{
|
||||
c = buf[n];
|
||||
if ((c < ' ') && (c != '\n')) {
|
||||
outstring("^");
|
||||
++ttcol;
|
||||
c ^= 0x40;
|
||||
}
|
||||
|
||||
if (c != '\n') {
|
||||
if (disinp)
|
||||
TTputc(c);
|
||||
} else { /* put out <NL> for <ret> */
|
||||
outstring("<NL>");
|
||||
ttcol += 3;
|
||||
}
|
||||
++ttcol;
|
||||
}
|
||||
TTflush();
|
||||
#if UNIX
|
||||
rewind(tmpf);
|
||||
unlink(tmp);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} else if ((c == quotec || c == 0x16) && quotef == FALSE) {
|
||||
quotef = TRUE;
|
||||
} else {
|
||||
quotef = FALSE;
|
||||
if (cpos < nbuf-1) {
|
||||
buf[cpos++] = c;
|
||||
|
||||
if ((c < ' ') && (c != '\n')) {
|
||||
outstring("^");
|
||||
++ttcol;
|
||||
c ^= 0x40;
|
||||
}
|
||||
|
||||
if (c != '\n') {
|
||||
if (disinp)
|
||||
TTputc(c);
|
||||
} else { /* put out <NL> for <ret> */
|
||||
outstring("<NL>");
|
||||
ttcol += 3;
|
||||
}
|
||||
++ttcol;
|
||||
TTflush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outstring(s) /* output a string of characters */
|
||||
|
||||
char *s; /* string to output */
|
||||
|
||||
{
|
||||
if (disinp)
|
||||
while (*s)
|
||||
TTputc(*s++);
|
||||
}
|
||||
|
||||
ostring(s) /* output a string of output characters */
|
||||
|
||||
char *s; /* string to output */
|
||||
|
||||
{
|
||||
if (discmd)
|
||||
while (*s)
|
||||
TTputc(*s++);
|
||||
}
|
||||
|
521
isearch.c
Normal file
521
isearch.c
Normal file
@ -0,0 +1,521 @@
|
||||
/* ISEARCH.C
|
||||
*
|
||||
* The functions in this file implement commands that perform incremental
|
||||
* searches in the forward and backward directions. This "ISearch" command
|
||||
* is intended to emulate the same command from the original EMACS
|
||||
* implementation (ITS). Contains references to routines internal to
|
||||
* SEARCH.C.
|
||||
*
|
||||
* REVISION HISTORY:
|
||||
*
|
||||
* D. R. Banks 9-May-86
|
||||
* - added ITS EMACSlike ISearch
|
||||
*
|
||||
* John M. Gamble 5-Oct-86
|
||||
* - Made iterative search use search.c's scanner() routine.
|
||||
* This allowed the elimination of bakscan().
|
||||
* - Put isearch constants into estruct.h
|
||||
* - Eliminated the passing of 'status' to scanmore() and
|
||||
* checknext(), since there were no circumstances where
|
||||
* it ever equalled FALSE.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if ISRCH
|
||||
|
||||
extern int scanner(); /* Handy search routine */
|
||||
extern int eq(); /* Compare chars, match case */
|
||||
|
||||
/* A couple of "own" variables for re-eat */
|
||||
|
||||
int (*saved_get_char)(); /* Get character routine */
|
||||
int eaten_char = -1; /* Re-eaten char */
|
||||
|
||||
/* A couple more "own" variables for the command string */
|
||||
|
||||
int cmd_buff[CMDBUFLEN]; /* Save the command args here */
|
||||
int cmd_offset; /* Current offset into command buff */
|
||||
int cmd_reexecute = -1; /* > 0 if re-executing command */
|
||||
|
||||
|
||||
/*
|
||||
* Subroutine to do incremental reverse search. It actually uses the
|
||||
* same code as the normal incremental search, as both can go both ways.
|
||||
*/
|
||||
|
||||
int risearch(f, n)
|
||||
{
|
||||
LINE *curline; /* Current line on entry */
|
||||
int curoff; /* Current offset on entry */
|
||||
|
||||
/* remember the initial . on entry: */
|
||||
|
||||
curline = curwp->w_dotp; /* Save the current line pointer */
|
||||
curoff = curwp->w_doto; /* Save the current offset */
|
||||
|
||||
/* Make sure the search doesn't match where we already are: */
|
||||
|
||||
backchar(TRUE, 1); /* Back up a character */
|
||||
|
||||
if (!(isearch(f, -n))) /* Call ISearch backwards */
|
||||
{ /* If error in search: */
|
||||
curwp->w_dotp = curline; /* Reset the line pointer */
|
||||
curwp->w_doto = curoff; /* and the offset to original value */
|
||||
curwp->w_flag |= WFMOVE; /* Say we've moved */
|
||||
update(FALSE); /* And force an update */
|
||||
mlwrite ("(search failed)"); /* Say we died */
|
||||
#if PKCODE
|
||||
matchlen = strlen(pat);
|
||||
#endif
|
||||
} else mlerase (); /* If happy, just erase the cmd line */
|
||||
#if PKCODE
|
||||
matchlen = strlen(pat);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Again, but for the forward direction */
|
||||
|
||||
int fisearch(f, n)
|
||||
{
|
||||
LINE *curline; /* Current line on entry */
|
||||
int curoff; /* Current offset on entry */
|
||||
|
||||
/* remember the initial . on entry: */
|
||||
|
||||
curline = curwp->w_dotp; /* Save the current line pointer */
|
||||
curoff = curwp->w_doto; /* Save the current offset */
|
||||
|
||||
/* do the search */
|
||||
|
||||
if (!(isearch(f, n))) /* Call ISearch forwards */
|
||||
{ /* If error in search: */
|
||||
curwp->w_dotp = curline; /* Reset the line pointer */
|
||||
curwp->w_doto = curoff; /* and the offset to original value */
|
||||
curwp->w_flag |= WFMOVE; /* Say we've moved */
|
||||
update(FALSE); /* And force an update */
|
||||
mlwrite ("(search failed)"); /* Say we died */
|
||||
#if PKCODE
|
||||
matchlen = strlen(pat);
|
||||
#endif
|
||||
} else mlerase (); /* If happy, just erase the cmd line */
|
||||
#if PKCODE
|
||||
matchlen = strlen(pat);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Subroutine to do an incremental search. In general, this works similarly
|
||||
* to the older micro-emacs search function, except that the search happens
|
||||
* as each character is typed, with the screen and cursor updated with each
|
||||
* new search character.
|
||||
*
|
||||
* While searching forward, each successive character will leave the cursor
|
||||
* at the end of the entire matched string. Typing a Control-S or Control-X
|
||||
* will cause the next occurrence of the string to be searched for (where the
|
||||
* next occurrence does NOT overlap the current occurrence). A Control-R will
|
||||
* change to a backwards search, META will terminate the search and Control-G
|
||||
* will abort the search. Rubout will back up to the previous match of the
|
||||
* string, or if the starting point is reached first, it will delete the
|
||||
* last character from the search string.
|
||||
*
|
||||
* While searching backward, each successive character will leave the cursor
|
||||
* at the beginning of the matched string. Typing a Control-R will search
|
||||
* backward for the next occurrence of the string. Control-S or Control-X
|
||||
* will revert the search to the forward direction. In general, the reverse
|
||||
* incremental search is just like the forward incremental search inverted.
|
||||
*
|
||||
* In all cases, if the search fails, the user will be feeped, and the search
|
||||
* will stall until the pattern string is edited back into something that
|
||||
* exists (or until the search is aborted).
|
||||
*/
|
||||
|
||||
isearch(f, n)
|
||||
{
|
||||
int status; /* Search status */
|
||||
int col; /* prompt column */
|
||||
register int cpos; /* character number in search string */
|
||||
register int c; /* current input character */
|
||||
register int expc; /* function expanded input char */
|
||||
char pat_save[NPAT]; /* Saved copy of the old pattern str */
|
||||
LINE *curline; /* Current line on entry */
|
||||
int curoff; /* Current offset on entry */
|
||||
int init_direction; /* The initial search direction */
|
||||
|
||||
/* Initialize starting conditions */
|
||||
|
||||
cmd_reexecute = -1; /* We're not re-executing (yet?) */
|
||||
cmd_offset = 0; /* Start at the beginning of the buff */
|
||||
cmd_buff[0] = '\0'; /* Init the command buffer */
|
||||
strncpy (pat_save, pat, NPAT); /* Save the old pattern string */
|
||||
curline = curwp->w_dotp; /* Save the current line pointer */
|
||||
curoff = curwp->w_doto; /* Save the current offset */
|
||||
init_direction = n; /* Save the initial search direction */
|
||||
|
||||
/* This is a good place to start a re-execution: */
|
||||
|
||||
start_over:
|
||||
|
||||
/* ask the user for the text of a pattern */
|
||||
col = promptpattern("ISearch: "); /* Prompt, remember the col */
|
||||
|
||||
cpos = 0; /* Start afresh */
|
||||
status = TRUE; /* Assume everything's cool */
|
||||
|
||||
/*
|
||||
Get the first character in the pattern. If we get an initial Control-S
|
||||
or Control-R, re-use the old search string and find the first occurrence
|
||||
*/
|
||||
|
||||
c = ectoc(expc = get_char()); /* Get the first character */
|
||||
if ((c == IS_FORWARD) ||
|
||||
(c == IS_REVERSE) ||
|
||||
(c == IS_VMSFORW)) /* Reuse old search string? */
|
||||
{
|
||||
for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */
|
||||
col = echochar(pat[cpos],col); /* and re-echo the string */
|
||||
if (c == IS_REVERSE) { /* forward search? */
|
||||
n = -1; /* No, search in reverse */
|
||||
backchar (TRUE, 1); /* Be defensive about EOB */
|
||||
} else
|
||||
n = 1; /* Yes, search forward */
|
||||
status = scanmore(pat, n); /* Do the search */
|
||||
c = ectoc(expc = get_char()); /* Get another character */
|
||||
}
|
||||
|
||||
/* Top of the per character loop */
|
||||
|
||||
for (;;) /* ISearch per character loop */
|
||||
{
|
||||
/* Check for special characters first: */
|
||||
/* Most cases here change the search */
|
||||
|
||||
if (expc == metac) /* Want to quit searching? */
|
||||
return (TRUE); /* Quit searching now */
|
||||
|
||||
switch (c) /* dispatch on the input char */
|
||||
{
|
||||
case IS_ABORT: /* If abort search request */
|
||||
return(FALSE); /* Quit searching again */
|
||||
|
||||
case IS_REVERSE: /* If backward search */
|
||||
case IS_FORWARD: /* If forward search */
|
||||
case IS_VMSFORW: /* of either flavor */
|
||||
if (c == IS_REVERSE) /* If reverse search */
|
||||
n = -1; /* Set the reverse direction */
|
||||
else /* Otherwise, */
|
||||
n = 1; /* go forward */
|
||||
status = scanmore(pat, n); /* Start the search again */
|
||||
c = ectoc(expc = get_char()); /* Get the next char */
|
||||
continue; /* Go continue with the search*/
|
||||
|
||||
case IS_NEWLINE: /* Carriage return */
|
||||
c = '\n'; /* Make it a new line */
|
||||
break; /* Make sure we use it */
|
||||
|
||||
case IS_QUOTE: /* Quote character */
|
||||
case IS_VMSQUOTE: /* of either variety */
|
||||
c = ectoc(expc = get_char()); /* Get the next char */
|
||||
|
||||
case IS_TAB: /* Generically allowed */
|
||||
case '\n': /* controlled characters */
|
||||
break; /* Make sure we use it */
|
||||
|
||||
case IS_BACKSP: /* If a backspace: */
|
||||
case IS_RUBOUT: /* or if a Rubout: */
|
||||
if (cmd_offset <= 1) /* Anything to delete? */
|
||||
return (TRUE); /* No, just exit */
|
||||
--cmd_offset; /* Back up over the Rubout */
|
||||
cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char */
|
||||
curwp->w_dotp = curline; /* Reset the line pointer */
|
||||
curwp->w_doto = curoff; /* and the offset */
|
||||
n = init_direction; /* Reset the search direction */
|
||||
strncpy (pat, pat_save, NPAT); /* Restore the old search str */
|
||||
cmd_reexecute = 0; /* Start the whole mess over */
|
||||
goto start_over; /* Let it take care of itself */
|
||||
|
||||
/* Presumably a quasi-normal character comes here */
|
||||
|
||||
default: /* All other chars */
|
||||
if (c < ' ') /* Is it printable? */
|
||||
{ /* Nope. */
|
||||
reeat (c); /* Re-eat the char */
|
||||
return (TRUE); /* And return the last status */
|
||||
}
|
||||
} /* Switch */
|
||||
|
||||
/* I guess we got something to search for, so search for it */
|
||||
|
||||
pat[cpos++] = c; /* put the char in the buffer */
|
||||
if (cpos >= NPAT) /* too many chars in string? */
|
||||
{ /* Yup. Complain about it */
|
||||
mlwrite("? Search string too long");
|
||||
return(TRUE); /* Return an error */
|
||||
}
|
||||
pat[cpos] = 0; /* null terminate the buffer */
|
||||
col = echochar(c,col); /* Echo the character */
|
||||
if (!status) { /* If we lost last time */
|
||||
TTputc(BELL); /* Feep again */
|
||||
TTflush(); /* see that the feep feeps */
|
||||
} else /* Otherwise, we must have won*/
|
||||
if (!(status = checknext(c, pat, n))) /* See if match */
|
||||
status = scanmore(pat, n); /* or find the next match */
|
||||
c = ectoc(expc = get_char()); /* Get the next char */
|
||||
} /* for {;;} */
|
||||
}
|
||||
|
||||
/*
|
||||
* Trivial routine to insure that the next character in the search string is
|
||||
* still true to whatever we're pointing to in the buffer. This routine will
|
||||
* not attempt to move the "point" if the match fails, although it will
|
||||
* implicitly move the "point" if we're forward searching, and find a match,
|
||||
* since that's the way forward isearch works.
|
||||
*
|
||||
* If the compare fails, we return FALSE and assume the caller will call
|
||||
* scanmore or something.
|
||||
*/
|
||||
|
||||
int checknext (chr, patrn, dir) /* Check next character in search string */
|
||||
char chr; /* Next char to look for */
|
||||
char *patrn; /* The entire search string (incl chr) */
|
||||
int dir; /* Search direction */
|
||||
{
|
||||
register LINE *curline; /* current line during scan */
|
||||
register int curoff; /* position within current line */
|
||||
register int buffchar; /* character at current position */
|
||||
int status; /* how well things go */
|
||||
|
||||
|
||||
/* setup the local scan pointer to current "." */
|
||||
|
||||
curline = curwp->w_dotp; /* Get the current line structure */
|
||||
curoff = curwp->w_doto; /* Get the offset within that line */
|
||||
|
||||
if (dir > 0) /* If searching forward */
|
||||
{
|
||||
if (curoff == llength(curline)) /* If at end of line */
|
||||
{
|
||||
curline = lforw(curline); /* Skip to the next line */
|
||||
if (curline == curbp->b_linep)
|
||||
return (FALSE); /* Abort if at end of buffer */
|
||||
curoff = 0; /* Start at the beginning of the line */
|
||||
buffchar = '\n'; /* And say the next char is NL */
|
||||
} else
|
||||
buffchar = lgetc(curline, curoff++); /* Get the next char */
|
||||
if (status = eq(buffchar, chr)) /* Is it what we're looking for? */
|
||||
{
|
||||
curwp->w_dotp = curline; /* Yes, set the buffer's point */
|
||||
curwp->w_doto = curoff; /* to the matched character */
|
||||
curwp->w_flag |= WFMOVE; /* Say that we've moved */
|
||||
}
|
||||
return (status); /* And return the status */
|
||||
} else /* Else, if reverse search: */
|
||||
return (match_pat (patrn)); /* See if we're in the right place */
|
||||
}
|
||||
|
||||
/*
|
||||
* This hack will search for the next occurrence of <pat> in the buffer, either
|
||||
* forward or backward. It is called with the status of the prior search
|
||||
* attempt, so that it knows not to bother if it didn't work last time. If
|
||||
* we can't find any more matches, "point" is left where it was before. If
|
||||
* we do find a match, "point" will be at the end of the matched string for
|
||||
* forward searches and at the beginning of the matched string for reverse
|
||||
* searches.
|
||||
*/
|
||||
|
||||
int scanmore(patrn, dir) /* search forward or back for a pattern */
|
||||
char *patrn; /* string to scan for */
|
||||
int dir; /* direction to search */
|
||||
{
|
||||
int sts; /* search status */
|
||||
|
||||
if (dir < 0) /* reverse search? */
|
||||
{
|
||||
rvstrcpy(tap, patrn); /* Put reversed string in tap */
|
||||
sts = scanner(tap, REVERSE, PTBEG);
|
||||
}
|
||||
else
|
||||
sts = scanner(patrn, FORWARD, PTEND); /* Nope. Go forward */
|
||||
|
||||
if (!sts)
|
||||
{
|
||||
TTputc(BELL); /* Feep if search fails */
|
||||
TTflush(); /* see that the feep feeps */
|
||||
}
|
||||
|
||||
return(sts); /* else, don't even try */
|
||||
}
|
||||
|
||||
/*
|
||||
* The following is a worker subroutine used by the reverse search. It
|
||||
* compares the pattern string with the characters at "." for equality. If
|
||||
* any characters mismatch, it will return FALSE.
|
||||
*
|
||||
* This isn't used for forward searches, because forward searches leave "."
|
||||
* at the end of the search string (instead of in front), so all that needs to
|
||||
* be done is match the last char input.
|
||||
*/
|
||||
|
||||
int match_pat (patrn) /* See if the pattern string matches string at "." */
|
||||
char *patrn; /* String to match to buffer */
|
||||
{
|
||||
register int i; /* Generic loop index/offset */
|
||||
register int buffchar; /* character at current position */
|
||||
register LINE *curline; /* current line during scan */
|
||||
register int curoff; /* position within current line */
|
||||
|
||||
/* setup the local scan pointer to current "." */
|
||||
|
||||
curline = curwp->w_dotp; /* Get the current line structure */
|
||||
curoff = curwp->w_doto; /* Get the offset within that line */
|
||||
|
||||
/* top of per character compare loop: */
|
||||
|
||||
for (i = 0; i < strlen(patrn); i++) /* Loop for all characters in patrn */
|
||||
{
|
||||
if (curoff == llength(curline)) /* If at end of line */
|
||||
{
|
||||
curline = lforw(curline); /* Skip to the next line */
|
||||
curoff = 0; /* Start at the beginning of the line */
|
||||
if (curline == curbp->b_linep)
|
||||
return (FALSE); /* Abort if at end of buffer */
|
||||
buffchar = '\n'; /* And say the next char is NL */
|
||||
} else
|
||||
buffchar = lgetc(curline, curoff++); /* Get the next char */
|
||||
if (!eq(buffchar, patrn[i])) /* Is it what we're looking for? */
|
||||
return (FALSE); /* Nope, just punt it then */
|
||||
}
|
||||
return (TRUE); /* Everything matched? Let's celebrate*/
|
||||
}
|
||||
|
||||
/* Routine to prompt for I-Search string. */
|
||||
|
||||
int promptpattern(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
char tpat[NPAT+20];
|
||||
|
||||
strcpy(tpat, prompt); /* copy prompt to output string */
|
||||
strcat(tpat, " ("); /* build new prompt string */
|
||||
expandp(pat, &tpat[strlen(tpat)], NPAT/2); /* add old pattern */
|
||||
strcat(tpat, ")<Meta>: ");
|
||||
|
||||
/* check to see if we are executing a command line */
|
||||
if (!clexec) {
|
||||
mlwrite(tpat);
|
||||
}
|
||||
return(strlen(tpat));
|
||||
}
|
||||
|
||||
/* routine to echo i-search characters */
|
||||
|
||||
int echochar(c,col)
|
||||
int c; /* character to be echoed */
|
||||
int col; /* column to be echoed in */
|
||||
{
|
||||
movecursor(term.t_nrow,col); /* Position the cursor */
|
||||
if ((c < ' ') || (c == 0x7F)) /* Control character? */
|
||||
{
|
||||
switch (c) /* Yes, dispatch special cases*/
|
||||
{
|
||||
case '\n': /* Newline */
|
||||
TTputc('<');
|
||||
TTputc('N');
|
||||
TTputc('L');
|
||||
TTputc('>');
|
||||
col += 3;
|
||||
break;
|
||||
|
||||
case '\t': /* Tab */
|
||||
TTputc('<');
|
||||
TTputc('T');
|
||||
TTputc('A');
|
||||
TTputc('B');
|
||||
TTputc('>');
|
||||
col += 4;
|
||||
break;
|
||||
|
||||
case 0x7F: /* Rubout: */
|
||||
TTputc('^'); /* Output a funny looking */
|
||||
TTputc('?'); /* indication of Rubout */
|
||||
col++; /* Count the extra char */
|
||||
break;
|
||||
|
||||
default: /* Vanilla control char */
|
||||
TTputc('^'); /* Yes, output prefix */
|
||||
TTputc(c+0x40); /* Make it "^X" */
|
||||
col++; /* Count this char */
|
||||
}
|
||||
} else
|
||||
TTputc(c); /* Otherwise, output raw char */
|
||||
TTflush(); /* Flush the output */
|
||||
return(++col); /* return the new column no */
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine to get the next character from the input stream. If we're reading
|
||||
* from the real terminal, force a screen update before we get the char.
|
||||
* Otherwise, we must be re-executing the command string, so just return the
|
||||
* next character.
|
||||
*/
|
||||
|
||||
int get_char ()
|
||||
{
|
||||
int c; /* A place to get a character */
|
||||
|
||||
/* See if we're re-executing: */
|
||||
|
||||
if (cmd_reexecute >= 0) /* Is there an offset? */
|
||||
if ((c = cmd_buff[cmd_reexecute++]) != 0)
|
||||
return (c); /* Yes, return any character */
|
||||
|
||||
/* We're not re-executing (or aren't any more). Try for a real char */
|
||||
|
||||
cmd_reexecute = -1; /* Say we're in real mode again */
|
||||
update(FALSE); /* Pretty up the screen */
|
||||
if (cmd_offset >= CMDBUFLEN-1) /* If we're getting too big ... */
|
||||
{
|
||||
mlwrite ("? command too long"); /* Complain loudly and bitterly */
|
||||
return (metac); /* And force a quit */
|
||||
}
|
||||
c = get1key(); /* Get the next character */
|
||||
cmd_buff[cmd_offset++] = c; /* Save the char for next time */
|
||||
cmd_buff[cmd_offset] = '\0';/* And terminate the buffer */
|
||||
return (c); /* Return the character */
|
||||
}
|
||||
|
||||
/*
|
||||
* Hacky routine to re-eat a character. This will save the character to be
|
||||
* re-eaten by redirecting the input call to a routine here. Hack, etc.
|
||||
*/
|
||||
|
||||
/* Come here on the next term.t_getchar call: */
|
||||
|
||||
int uneat()
|
||||
{
|
||||
int c;
|
||||
|
||||
term.t_getchar = saved_get_char; /* restore the routine address */
|
||||
c = eaten_char; /* Get the re-eaten char */
|
||||
eaten_char = -1; /* Clear the old char */
|
||||
return(c); /* and return the last char */
|
||||
}
|
||||
|
||||
int reeat(c)
|
||||
int c;
|
||||
{
|
||||
if (eaten_char != -1) /* If we've already been here */
|
||||
return/*(NULL)*/; /* Don't do it again */
|
||||
eaten_char = c; /* Else, save the char for later */
|
||||
saved_get_char = term.t_getchar; /* Save the char get routine */
|
||||
term.t_getchar = uneat; /* Replace it with ours */
|
||||
}
|
||||
#else
|
||||
isearch()
|
||||
{
|
||||
}
|
||||
#endif
|
655
line.c
Normal file
655
line.c
Normal file
@ -0,0 +1,655 @@
|
||||
/* LINE.C
|
||||
*
|
||||
* The functions in this file are a general set of line management utilities.
|
||||
* They are the only routines that touch the text. They also touch the buffer
|
||||
* and window structures, to make sure that the necessary updating gets done.
|
||||
* There are routines in this file that handle the kill buffer too. It isn't
|
||||
* here for any good reason.
|
||||
*
|
||||
* Note that this code only updates the dot and mark values in the window list.
|
||||
* Since all the code acts on the current window, the buffer that we are
|
||||
* editing must be being displayed, which means that "b_nwnd" is non zero,
|
||||
* which means that the dot and mark values in the buffer headers are nonsense.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
KILL *ykbuf; /* ptr to current kill buffer chunk being yanked */
|
||||
int ykboff; /* offset into that chunk */
|
||||
|
||||
/*
|
||||
* This routine allocates a block of memory large enough to hold a LINE
|
||||
* containing "used" characters. The block is always rounded up a bit. Return
|
||||
* a pointer to the new block, or NULL if there isn't any memory left. Print a
|
||||
* message in the message line if no space.
|
||||
*/
|
||||
LINE *lalloc(used)
|
||||
|
||||
register int used;
|
||||
|
||||
{
|
||||
register LINE *lp;
|
||||
register int size;
|
||||
char *malloc();
|
||||
|
||||
size = (used+NBLOCK-1) & ~(NBLOCK-1);
|
||||
if (size == 0) /* Assume that an empty */
|
||||
size = NBLOCK; /* line is for type-in. */
|
||||
if ((lp = (LINE *) malloc(sizeof(LINE)+size)) == NULL) {
|
||||
mlwrite("(OUT OF MEMORY)");
|
||||
return (NULL);
|
||||
}
|
||||
lp->l_size = size;
|
||||
lp->l_used = used;
|
||||
return (lp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete line "lp". Fix all of the links that might point at it (they are
|
||||
* moved to offset 0 of the next line. Unlink the line from whatever buffer it
|
||||
* might be in. Release the memory. The buffers are updated too; the magic
|
||||
* conditions described in the above comments don't hold here.
|
||||
*/
|
||||
lfree(lp)
|
||||
register LINE *lp;
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register WINDOW *wp;
|
||||
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp)
|
||||
wp->w_linep = lp->l_fp;
|
||||
if (wp->w_dotp == lp) {
|
||||
wp->w_dotp = lp->l_fp;
|
||||
wp->w_doto = 0;
|
||||
}
|
||||
if (wp->w_markp == lp) {
|
||||
wp->w_markp = lp->l_fp;
|
||||
wp->w_marko = 0;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
bp = bheadp;
|
||||
while (bp != NULL) {
|
||||
if (bp->b_nwnd == 0) {
|
||||
if (bp->b_dotp == lp) {
|
||||
bp->b_dotp = lp->l_fp;
|
||||
bp->b_doto = 0;
|
||||
}
|
||||
if (bp->b_markp == lp) {
|
||||
bp->b_markp = lp->l_fp;
|
||||
bp->b_marko = 0;
|
||||
}
|
||||
}
|
||||
bp = bp->b_bufp;
|
||||
}
|
||||
lp->l_bp->l_fp = lp->l_fp;
|
||||
lp->l_fp->l_bp = lp->l_bp;
|
||||
free((char *) lp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine gets called when a character is changed in place in the current
|
||||
* buffer. It updates all of the required flags in the buffer and window
|
||||
* system. The flag used is passed as an argument; if the buffer is being
|
||||
* displayed in more than 1 window we change EDIT t HARD. Set MODE if the
|
||||
* mode line needs to be updated (the "*" has to be set).
|
||||
*/
|
||||
lchange(flag)
|
||||
register int flag;
|
||||
{
|
||||
register WINDOW *wp;
|
||||
|
||||
if (curbp->b_nwnd != 1) /* Ensure hard. */
|
||||
flag = WFHARD;
|
||||
if ((curbp->b_flag&BFCHG) == 0) { /* First change, so */
|
||||
flag |= WFMODE; /* update mode lines. */
|
||||
curbp->b_flag |= BFCHG;
|
||||
}
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == curbp)
|
||||
wp->w_flag |= flag;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
}
|
||||
|
||||
insspace(f, n) /* insert spaces forward into text */
|
||||
|
||||
int f, n; /* default flag and numeric argument */
|
||||
|
||||
{
|
||||
linsert(n, ' ');
|
||||
backchar(f, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* linstr -- Insert a string at the current point
|
||||
*/
|
||||
|
||||
linstr(instr)
|
||||
char *instr;
|
||||
{
|
||||
register int status = TRUE;
|
||||
char tmpc;
|
||||
|
||||
if (instr != NULL)
|
||||
while ((tmpc = *instr) && status == TRUE) {
|
||||
status = (tmpc == '\n'? lnewline(): linsert(1, tmpc));
|
||||
|
||||
/* Insertion error? */
|
||||
if (status != TRUE) {
|
||||
mlwrite("%%Out of memory while inserting");
|
||||
break;
|
||||
}
|
||||
instr++;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert "n" copies of the character "c" at the current location of dot. In
|
||||
* the easy case all that happens is the text is stored in the line. In the
|
||||
* hard case, the line has to be reallocated. When the window list is updated,
|
||||
* take special care; I screwed it up once. You always update dot in the
|
||||
* current window. You update mark, and a dot in another window, if it is
|
||||
* greater than the place where you did the insert. Return TRUE if all is
|
||||
* well, and FALSE on errors.
|
||||
*/
|
||||
|
||||
linsert(n, c)
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register LINE *lp3;
|
||||
register int doto;
|
||||
register int i;
|
||||
register WINDOW *wp;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
lchange(WFEDIT);
|
||||
lp1 = curwp->w_dotp; /* Current line */
|
||||
if (lp1 == curbp->b_linep) { /* At the end: special */
|
||||
if (curwp->w_doto != 0) {
|
||||
mlwrite("bug: linsert");
|
||||
return (FALSE);
|
||||
}
|
||||
if ((lp2=lalloc(n)) == NULL) /* Allocate new line */
|
||||
return (FALSE);
|
||||
lp3 = lp1->l_bp; /* Previous line */
|
||||
lp3->l_fp = lp2; /* Link in */
|
||||
lp2->l_fp = lp1;
|
||||
lp1->l_bp = lp2;
|
||||
lp2->l_bp = lp3;
|
||||
for (i=0; i<n; ++i)
|
||||
lp2->l_text[i] = c;
|
||||
curwp->w_dotp = lp2;
|
||||
curwp->w_doto = n;
|
||||
return (TRUE);
|
||||
}
|
||||
doto = curwp->w_doto; /* Save for later. */
|
||||
if (lp1->l_used+n > lp1->l_size) { /* Hard: reallocate */
|
||||
if ((lp2=lalloc(lp1->l_used+n)) == NULL)
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0];
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*cp2++ = *cp1++;
|
||||
cp2 += n;
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_bp->l_fp = lp2;
|
||||
lp2->l_fp = lp1->l_fp;
|
||||
lp1->l_fp->l_bp = lp2;
|
||||
lp2->l_bp = lp1->l_bp;
|
||||
free((char *) lp1);
|
||||
} else { /* Easy: in place */
|
||||
lp2 = lp1; /* Pretend new line */
|
||||
lp2->l_used += n;
|
||||
cp2 = &lp1->l_text[lp1->l_used];
|
||||
cp1 = cp2-n;
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*--cp2 = *--cp1;
|
||||
}
|
||||
for (i=0; i<n; ++i) /* Add the characters */
|
||||
lp2->l_text[doto+i] = c;
|
||||
wp = wheadp; /* Update windows */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp1)
|
||||
wp->w_linep = lp2;
|
||||
if (wp->w_dotp == lp1) {
|
||||
wp->w_dotp = lp2;
|
||||
if (wp==curwp || wp->w_doto>doto)
|
||||
wp->w_doto += n;
|
||||
}
|
||||
if (wp->w_markp == lp1) {
|
||||
wp->w_markp = lp2;
|
||||
if (wp->w_marko > doto)
|
||||
wp->w_marko += n;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Overwrite a character into the current line at the current position
|
||||
*
|
||||
*/
|
||||
|
||||
lowrite(c)
|
||||
|
||||
char c; /* character to overwrite on current position */
|
||||
|
||||
{
|
||||
if (curwp->w_doto < curwp->w_dotp->l_used &&
|
||||
(lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
|
||||
((curwp->w_doto) & tabmask) == tabmask))
|
||||
ldelete(1L, FALSE);
|
||||
return(linsert(1, c));
|
||||
}
|
||||
|
||||
/*
|
||||
* lover -- Overwrite a string at the current point
|
||||
*/
|
||||
|
||||
lover(ostr)
|
||||
|
||||
char *ostr;
|
||||
|
||||
{
|
||||
register int status = TRUE;
|
||||
char tmpc;
|
||||
|
||||
if (ostr != NULL)
|
||||
while ((tmpc = *ostr) && status == TRUE) {
|
||||
status = (tmpc == '\n'? lnewline(): lowrite(tmpc));
|
||||
|
||||
/* Insertion error? */
|
||||
if (status != TRUE) {
|
||||
mlwrite("%%Out of memory while overwriting");
|
||||
break;
|
||||
}
|
||||
ostr++;
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a newline into the buffer at the current location of dot in the
|
||||
* current window. The funny ass-backwards way it does things is not a botch;
|
||||
* it just makes the last line in the file not a special case. Return TRUE if
|
||||
* everything works out and FALSE on error (memory allocation failure). The
|
||||
* update of dot and mark is a bit easier then in the above case, because the
|
||||
* split forces more updating.
|
||||
*/
|
||||
lnewline()
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register int doto;
|
||||
register WINDOW *wp;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
#if SCROLLCODE
|
||||
lchange(WFHARD|WFINS);
|
||||
#else
|
||||
lchange(WFHARD);
|
||||
#endif
|
||||
lp1 = curwp->w_dotp; /* Get the address and */
|
||||
doto = curwp->w_doto; /* offset of "." */
|
||||
if ((lp2=lalloc(doto)) == NULL) /* New first half line */
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0]; /* Shuffle text around */
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp1 != &lp1->l_text[doto])
|
||||
*cp2++ = *cp1++;
|
||||
cp2 = &lp1->l_text[0];
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_used -= doto;
|
||||
lp2->l_bp = lp1->l_bp;
|
||||
lp1->l_bp = lp2;
|
||||
lp2->l_bp->l_fp = lp2;
|
||||
lp2->l_fp = lp1;
|
||||
wp = wheadp; /* Windows */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp1)
|
||||
wp->w_linep = lp2;
|
||||
if (wp->w_dotp == lp1) {
|
||||
if (wp->w_doto < doto)
|
||||
wp->w_dotp = lp2;
|
||||
else
|
||||
wp->w_doto -= doto;
|
||||
}
|
||||
if (wp->w_markp == lp1) {
|
||||
if (wp->w_marko < doto)
|
||||
wp->w_markp = lp2;
|
||||
else
|
||||
wp->w_marko -= doto;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function deletes "n" bytes, starting at dot. It understands how do deal
|
||||
* with end of lines, etc. It returns TRUE if all of the characters were
|
||||
* deleted, and FALSE if they were not (because dot ran into the end of the
|
||||
* buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
|
||||
*/
|
||||
ldelete(n, kflag)
|
||||
|
||||
long n; /* # of chars to delete */
|
||||
int kflag; /* put killed text in kill buffer flag */
|
||||
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *dotp;
|
||||
register int doto;
|
||||
register int chunk;
|
||||
register WINDOW *wp;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
while (n != 0) {
|
||||
dotp = curwp->w_dotp;
|
||||
doto = curwp->w_doto;
|
||||
if (dotp == curbp->b_linep) /* Hit end of buffer. */
|
||||
return (FALSE);
|
||||
chunk = dotp->l_used-doto; /* Size of chunk. */
|
||||
if (chunk > n)
|
||||
chunk = n;
|
||||
if (chunk == 0) { /* End of line, merge. */
|
||||
#if SCROLLCODE
|
||||
lchange(WFHARD|WFKILLS);
|
||||
#else
|
||||
lchange(WFHARD);
|
||||
#endif
|
||||
if (ldelnewline() == FALSE
|
||||
|| (kflag!=FALSE && kinsert('\n')==FALSE))
|
||||
return (FALSE);
|
||||
--n;
|
||||
continue;
|
||||
}
|
||||
lchange(WFEDIT);
|
||||
cp1 = &dotp->l_text[doto]; /* Scrunch text. */
|
||||
cp2 = cp1 + chunk;
|
||||
if (kflag != FALSE) { /* Kill? */
|
||||
while (cp1 != cp2) {
|
||||
if (kinsert(*cp1) == FALSE)
|
||||
return (FALSE);
|
||||
++cp1;
|
||||
}
|
||||
cp1 = &dotp->l_text[doto];
|
||||
}
|
||||
while (cp2 != &dotp->l_text[dotp->l_used])
|
||||
*cp1++ = *cp2++;
|
||||
dotp->l_used -= chunk;
|
||||
wp = wheadp; /* Fix windows */
|
||||
while (wp != NULL) {
|
||||
if (wp->w_dotp==dotp && wp->w_doto>=doto) {
|
||||
wp->w_doto -= chunk;
|
||||
if (wp->w_doto < doto)
|
||||
wp->w_doto = doto;
|
||||
}
|
||||
if (wp->w_markp==dotp && wp->w_marko>=doto) {
|
||||
wp->w_marko -= chunk;
|
||||
if (wp->w_marko < doto)
|
||||
wp->w_marko = doto;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
n -= chunk;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* getctext: grab and return a string with the text of
|
||||
the current line
|
||||
*/
|
||||
|
||||
char *getctext()
|
||||
|
||||
{
|
||||
register LINE *lp; /* line to copy */
|
||||
register int size; /* length of line to return */
|
||||
register char *sp; /* string pointer into line */
|
||||
register char *dp; /* string pointer into returned line */
|
||||
static char rline[NSTRING]; /* line to return */
|
||||
|
||||
/* find the contents of the current line and its length */
|
||||
lp = curwp->w_dotp;
|
||||
sp = lp->l_text;
|
||||
size = lp->l_used;
|
||||
if (size >= NSTRING)
|
||||
size = NSTRING - 1;
|
||||
|
||||
/* copy it across */
|
||||
dp = rline;
|
||||
while (size--)
|
||||
*dp++ = *sp++;
|
||||
*dp = 0;
|
||||
return(rline);
|
||||
}
|
||||
|
||||
/* putctext: replace the current line with the passed in text */
|
||||
|
||||
putctext(iline)
|
||||
|
||||
char *iline; /* contents of new line */
|
||||
|
||||
{
|
||||
register int status;
|
||||
|
||||
/* delete the current line */
|
||||
curwp->w_doto = 0; /* starting at the beginning of the line */
|
||||
if ((status = killtext(TRUE, 1)) != TRUE)
|
||||
return(status);
|
||||
|
||||
/* insert the new line */
|
||||
if ((status = linstr(iline)) != TRUE)
|
||||
return(status);
|
||||
status = lnewline();
|
||||
backline(TRUE, 1);
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a newline. Join the current line with the next line. If the next line
|
||||
* is the magic header line always return TRUE; merging the last line with the
|
||||
* header line can be thought of as always being a successful operation, even
|
||||
* if nothing is done, and this makes the kill buffer work "right". Easy cases
|
||||
* can be done by shuffling data around. Hard cases require that lines be moved
|
||||
* about in memory. Return FALSE on error and TRUE if all looks ok. Called by
|
||||
* "ldelete" only.
|
||||
*/
|
||||
ldelnewline()
|
||||
{
|
||||
register char *cp1;
|
||||
register char *cp2;
|
||||
register LINE *lp1;
|
||||
register LINE *lp2;
|
||||
register LINE *lp3;
|
||||
register WINDOW *wp;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
lp1 = curwp->w_dotp;
|
||||
lp2 = lp1->l_fp;
|
||||
if (lp2 == curbp->b_linep) { /* At the buffer end. */
|
||||
if (lp1->l_used == 0) /* Blank line. */
|
||||
lfree(lp1);
|
||||
return (TRUE);
|
||||
}
|
||||
if (lp2->l_used <= lp1->l_size-lp1->l_used) {
|
||||
cp1 = &lp1->l_text[lp1->l_used];
|
||||
cp2 = &lp2->l_text[0];
|
||||
while (cp2 != &lp2->l_text[lp2->l_used])
|
||||
*cp1++ = *cp2++;
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep == lp2)
|
||||
wp->w_linep = lp1;
|
||||
if (wp->w_dotp == lp2) {
|
||||
wp->w_dotp = lp1;
|
||||
wp->w_doto += lp1->l_used;
|
||||
}
|
||||
if (wp->w_markp == lp2) {
|
||||
wp->w_markp = lp1;
|
||||
wp->w_marko += lp1->l_used;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
lp1->l_used += lp2->l_used;
|
||||
lp1->l_fp = lp2->l_fp;
|
||||
lp2->l_fp->l_bp = lp1;
|
||||
free((char *) lp2);
|
||||
return (TRUE);
|
||||
}
|
||||
if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL)
|
||||
return (FALSE);
|
||||
cp1 = &lp1->l_text[0];
|
||||
cp2 = &lp3->l_text[0];
|
||||
while (cp1 != &lp1->l_text[lp1->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
cp1 = &lp2->l_text[0];
|
||||
while (cp1 != &lp2->l_text[lp2->l_used])
|
||||
*cp2++ = *cp1++;
|
||||
lp1->l_bp->l_fp = lp3;
|
||||
lp3->l_fp = lp2->l_fp;
|
||||
lp2->l_fp->l_bp = lp3;
|
||||
lp3->l_bp = lp1->l_bp;
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_linep==lp1 || wp->w_linep==lp2)
|
||||
wp->w_linep = lp3;
|
||||
if (wp->w_dotp == lp1)
|
||||
wp->w_dotp = lp3;
|
||||
else if (wp->w_dotp == lp2) {
|
||||
wp->w_dotp = lp3;
|
||||
wp->w_doto += lp1->l_used;
|
||||
}
|
||||
if (wp->w_markp == lp1)
|
||||
wp->w_markp = lp3;
|
||||
else if (wp->w_markp == lp2) {
|
||||
wp->w_markp = lp3;
|
||||
wp->w_marko += lp1->l_used;
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
free((char *) lp1);
|
||||
free((char *) lp2);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all of the text saved in the kill buffer. Called by commands when a
|
||||
* new kill context is being created. The kill buffer array is released, just
|
||||
* in case the buffer has grown to immense size. No errors.
|
||||
*/
|
||||
kdelete()
|
||||
{
|
||||
KILL *kp; /* ptr to scan kill buffer chunk list */
|
||||
|
||||
if (kbufh != NULL) {
|
||||
|
||||
/* first, delete all the chunks */
|
||||
kbufp = kbufh;
|
||||
while (kbufp != NULL) {
|
||||
kp = kbufp->d_next;
|
||||
free(kbufp);
|
||||
kbufp = kp;
|
||||
}
|
||||
|
||||
/* and reset all the kill buffer pointers */
|
||||
kbufh = kbufp = NULL;
|
||||
kused = KBLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a character to the kill buffer, allocating new chunks as needed.
|
||||
* Return TRUE if all is well, and FALSE on errors.
|
||||
*/
|
||||
|
||||
kinsert(c)
|
||||
|
||||
int c; /* character to insert in the kill buffer */
|
||||
|
||||
{
|
||||
KILL *nchunk; /* ptr to newly malloced chunk */
|
||||
|
||||
/* check to see if we need a new chunk */
|
||||
if (kused >= KBLOCK) {
|
||||
if ((nchunk = (KILL *)malloc(sizeof(KILL))) == NULL)
|
||||
return(FALSE);
|
||||
if (kbufh == NULL) /* set head ptr if first time */
|
||||
kbufh = nchunk;
|
||||
if (kbufp != NULL) /* point the current to this new one */
|
||||
kbufp->d_next = nchunk;
|
||||
kbufp = nchunk;
|
||||
kbufp->d_next = NULL;
|
||||
kused = 0;
|
||||
}
|
||||
|
||||
/* and now insert the character */
|
||||
kbufp->d_chunk[kused++] = c;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Yank text back from the kill buffer. This is really easy. All of the work
|
||||
* is done by the standard insert routines. All you do is run the loop, and
|
||||
* check for errors. Bound to "C-Y".
|
||||
*/
|
||||
yank(f, n)
|
||||
{
|
||||
register int c;
|
||||
register int i;
|
||||
register char *sp; /* pointer into string to insert */
|
||||
KILL *kp; /* pointer into kill buffer */
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
/* make sure there is something to yank */
|
||||
if (kbufh == NULL)
|
||||
return(TRUE); /* not an error, just nothing */
|
||||
|
||||
/* for each time.... */
|
||||
while (n--) {
|
||||
kp = kbufh;
|
||||
while (kp != NULL) {
|
||||
if (kp->d_next == NULL)
|
||||
i = kused;
|
||||
else
|
||||
i = KBLOCK;
|
||||
sp = kp->d_chunk;
|
||||
while (i--) {
|
||||
if ((c = *sp++) == '\n') {
|
||||
if (lnewline() == FALSE)
|
||||
return (FALSE);
|
||||
} else {
|
||||
if (linsert(1, c) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
kp = kp->d_next;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
166
lock.c
Normal file
166
lock.c
Normal file
@ -0,0 +1,166 @@
|
||||
/* LOCK.C
|
||||
*
|
||||
* File locking command routines
|
||||
*
|
||||
* written by Daniel Lawrence
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if FILOCK
|
||||
#if BSD | SVR4
|
||||
#include <sys/errno.h>
|
||||
|
||||
extern int sys_nerr; /* number of system error messages defined */
|
||||
extern int errno; /* current error */
|
||||
|
||||
char *lname[NLOCKS]; /* names of all locked files */
|
||||
int numlocks; /* # of current locks active */
|
||||
|
||||
/* lockchk: check a file for locking and add it to the list */
|
||||
|
||||
lockchk(fname)
|
||||
|
||||
char *fname; /* file to check for a lock */
|
||||
|
||||
{
|
||||
register int i; /* loop indexes */
|
||||
register int status; /* return status */
|
||||
char *undolock();
|
||||
|
||||
/* check to see if that file is already locked here */
|
||||
if (numlocks > 0)
|
||||
for (i=0; i < numlocks; ++i)
|
||||
if (strcmp(fname, lname[i]) == 0)
|
||||
return(TRUE);
|
||||
|
||||
/* if we have a full locking table, bitch and leave */
|
||||
if (numlocks == NLOCKS) {
|
||||
mlwrite("LOCK ERROR: Lock table full");
|
||||
return(ABORT);
|
||||
}
|
||||
|
||||
/* next, try to lock it */
|
||||
status = lock(fname);
|
||||
if (status == ABORT) /* file is locked, no override */
|
||||
return(ABORT);
|
||||
if (status == FALSE) /* locked, overriden, dont add to table */
|
||||
return(TRUE);
|
||||
|
||||
/* we have now locked it, add it to our table */
|
||||
lname[++numlocks - 1] = (char *)malloc(strlen(fname) + 1);
|
||||
if (lname[numlocks - 1] == NULL) { /* malloc failure */
|
||||
undolock(fname); /* free the lock */
|
||||
mlwrite("Cannot lock, out of memory");
|
||||
--numlocks;
|
||||
return(ABORT);
|
||||
}
|
||||
|
||||
/* everthing is cool, add it to the table */
|
||||
strcpy(lname[numlocks-1], fname);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* lockrel: release all the file locks so others may edit */
|
||||
|
||||
lockrel()
|
||||
|
||||
{
|
||||
register int i; /* loop index */
|
||||
register int status; /* status of locks */
|
||||
register int s; /* status of one unlock */
|
||||
|
||||
status = TRUE;
|
||||
if (numlocks > 0)
|
||||
for (i=0; i < numlocks; ++i) {
|
||||
if ((s = unlock(lname[i])) != TRUE)
|
||||
status = s;
|
||||
free(lname[i]);
|
||||
}
|
||||
numlocks = 0;
|
||||
return(status);
|
||||
}
|
||||
|
||||
/* lock: Check and lock a file from access by others
|
||||
returns TRUE = files was not locked and now is
|
||||
FALSE = file was locked and overridden
|
||||
ABORT = file was locked, abort command
|
||||
*/
|
||||
|
||||
lock(fname)
|
||||
|
||||
char *fname; /* file name to lock */
|
||||
|
||||
{
|
||||
register char *locker; /* lock error message */
|
||||
register int status; /* return status */
|
||||
char msg[NSTRING]; /* message string */
|
||||
char *dolock();
|
||||
|
||||
/* attempt to lock the file */
|
||||
locker = dolock(fname);
|
||||
if (locker == NULL) /* we win */
|
||||
return(TRUE);
|
||||
|
||||
/* file failed...abort */
|
||||
if (strncmp(locker, "LOCK", 4) == 0) {
|
||||
lckerror(locker);
|
||||
return(ABORT);
|
||||
}
|
||||
|
||||
/* someone else has it....override? */
|
||||
strcpy(msg, "File in use by ");
|
||||
strcat(msg, locker);
|
||||
strcat(msg, ", override?");
|
||||
status = mlyesno(msg); /* ask them */
|
||||
if (status == TRUE)
|
||||
return(FALSE);
|
||||
else
|
||||
return(ABORT);
|
||||
}
|
||||
|
||||
/* unlock: Unlock a file
|
||||
this only warns the user if it fails
|
||||
*/
|
||||
|
||||
unlock(fname)
|
||||
|
||||
char *fname; /* file to unlock */
|
||||
|
||||
{
|
||||
register char *locker; /* undolock return string */
|
||||
char *undolock();
|
||||
|
||||
/* unclock and return */
|
||||
locker = undolock(fname);
|
||||
if (locker == NULL)
|
||||
return(TRUE);
|
||||
|
||||
/* report the error and come back */
|
||||
lckerror(locker);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
lckerror(errstr) /* report a lock error */
|
||||
|
||||
char *errstr; /* lock error string to print out */
|
||||
|
||||
{
|
||||
char obuf[NSTRING]; /* output buffer for error message */
|
||||
|
||||
strcpy(obuf, errstr);
|
||||
strcat(obuf, " - ");
|
||||
if (errno < sys_nerr)
|
||||
strcat(obuf, sys_errlist[errno]);
|
||||
else
|
||||
strcat(obuf, "(can not get system error message)");
|
||||
mlwrite(obuf);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
lckhello() /* dummy function */
|
||||
{
|
||||
}
|
||||
#endif
|
895
main.c
Normal file
895
main.c
Normal file
@ -0,0 +1,895 @@
|
||||
/*
|
||||
* uEmacs/PK 4.0
|
||||
*
|
||||
* based on
|
||||
*
|
||||
* MicroEMACS 3.9
|
||||
* written by Dave G. Conroy.
|
||||
* substatially modified by Daniel M. Lawrence
|
||||
* modified by Petri Kutvonen
|
||||
*
|
||||
* MicroEMACS 3.9 (C)opyright 1987 by Daniel M. Lawrence
|
||||
*
|
||||
* Original statement of copying policy:
|
||||
*
|
||||
* MicroEMACS 3.9 can be copied and distributed freely for any
|
||||
* non-commercial purposes. MicroEMACS 3.9 can only be incorporated
|
||||
* into commercial software with the permission of the current author.
|
||||
*
|
||||
* No copyright claimed for modifications made by Petri Kutvonen.
|
||||
*
|
||||
* MAIN.C
|
||||
*
|
||||
* This file contains the main driving routine, and some keyboard
|
||||
* processing code.
|
||||
*
|
||||
* REVISION HISTORY:
|
||||
*
|
||||
* 1.0 Steve Wilhite, 30-Nov-85
|
||||
*
|
||||
* 2.0 George Jones, 12-Dec-85
|
||||
*
|
||||
* 3.0 Daniel Lawrence, 29-Dec-85
|
||||
*
|
||||
* 3.2-3.6 Daniel Lawrence, Feb...Apr-86
|
||||
*
|
||||
* 3.7 Daniel Lawrence, 14-May-86
|
||||
*
|
||||
* 3.8 Daniel Lawrence, 18-Jan-87
|
||||
*
|
||||
* 3.9 Daniel Lawrence, 16-Jul-87
|
||||
*
|
||||
* 3.9e Daniel Lawrence, 16-Nov-87
|
||||
*
|
||||
* After that versions 3.X and Daniel Lawrence went their own ways.
|
||||
* A modified 3.9e/PK was heavily used at the University of Helsinki
|
||||
* for several years on different UNIX, VMS, and MSDOS platforms.
|
||||
*
|
||||
* This modified version is now called eEmacs/PK.
|
||||
*
|
||||
* 4.0 Petri Kutvonen, 1-Sep-91
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* make global definitions not external */
|
||||
#define maindef
|
||||
|
||||
#include "estruct.h" /* global structures and defines */
|
||||
#include "efunc.h" /* function declarations and name table */
|
||||
#include "edef.h" /* global definitions */
|
||||
#include "ebind.h" /* default key bindings */
|
||||
|
||||
/* for MSDOS, increase the default stack space */
|
||||
|
||||
#if MSDOS & TURBO
|
||||
#if PKCODE
|
||||
extern unsigned _stklen = 20000;
|
||||
#else
|
||||
extern unsigned _stklen = 32766;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
#include <ssdef.h>
|
||||
#define GOOD (SS$_NORMAL)
|
||||
#endif
|
||||
|
||||
#ifndef GOOD
|
||||
#define GOOD 0
|
||||
#endif
|
||||
|
||||
#if UNIX
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#if CALLED
|
||||
emacs(argc, argv)
|
||||
#else
|
||||
main(argc, argv)
|
||||
#endif
|
||||
int argc; /* # of arguments */
|
||||
char *argv[]; /* argument strings */
|
||||
|
||||
{
|
||||
register int c; /* command character */
|
||||
register int f; /* default flag */
|
||||
register int n; /* numeric repeat count */
|
||||
register int mflag; /* negative flag on repeat */
|
||||
register BUFFER *bp; /* temp buffer pointer */
|
||||
register int firstfile; /* first file flag */
|
||||
register int carg; /* current arg to scan */
|
||||
register int startflag; /* startup executed flag */
|
||||
BUFFER *firstbp = NULL; /* ptr to first buffer in cmd line */
|
||||
int basec; /* c stripped of meta character */
|
||||
int viewflag; /* are we starting in view mode? */
|
||||
int gotoflag; /* do we need to goto a line at start? */
|
||||
int gline; /* if so, what line? */
|
||||
int searchflag; /* Do we need to search at start? */
|
||||
int saveflag; /* temp store for lastflag */
|
||||
int errflag; /* C error processing? */
|
||||
char bname[NBUFN]; /* buffer name of file to read */
|
||||
#if CRYPT
|
||||
int cryptflag; /* encrypting on the way in? */
|
||||
char ekey[NPAT]; /* startup encryption key */
|
||||
#endif
|
||||
char *strncpy();
|
||||
extern *pathname[]; /* startup file path/name array */
|
||||
int newc;
|
||||
#if PKCODE
|
||||
int (*getbind())();
|
||||
int (*execfunc)(); /* ptr to function to execute */
|
||||
#endif
|
||||
|
||||
#if UNIX
|
||||
static void emergencyexit();
|
||||
#ifdef SIGWINCH
|
||||
extern void sizesignal();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PKCODE & VMS
|
||||
(void) umask(-1); /* use old protection (this is at wrong place) */
|
||||
#endif
|
||||
|
||||
#if PKCODE & BSD
|
||||
sleep(1); /* time for window manager */
|
||||
#endif
|
||||
|
||||
#if UNIX
|
||||
#ifdef SIGWINCH
|
||||
signal(SIGWINCH, sizesignal);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* initialize the editor */
|
||||
vtinit(); /* Display */
|
||||
edinit("main"); /* Buffers, windows */
|
||||
varinit(); /* user variables */
|
||||
|
||||
viewflag = FALSE; /* view mode defaults off in command line */
|
||||
gotoflag = FALSE; /* set to off to begin with */
|
||||
searchflag = FALSE; /* set to off to begin with */
|
||||
firstfile = TRUE; /* no file to edit yet */
|
||||
startflag = FALSE; /* startup file not executed yet */
|
||||
errflag = FALSE; /* not doing C error parsing */
|
||||
#if CRYPT
|
||||
cryptflag = FALSE; /* no encryption by default */
|
||||
#endif
|
||||
#if CALLED
|
||||
eexitflag = FALSE; /* not time to exit yet */
|
||||
#endif
|
||||
|
||||
/* Parse the command line */
|
||||
for (carg = 1; carg < argc; ++carg) {
|
||||
|
||||
/* Process Switches */
|
||||
#if PKCODE
|
||||
if (argv[carg][0] == '+') {
|
||||
gotoflag = TRUE;
|
||||
gline = atoi(&argv[carg][1]);
|
||||
} else
|
||||
#endif
|
||||
if (argv[carg][0] == '-') {
|
||||
switch (argv[carg][1]) {
|
||||
/* Process Startup macroes */
|
||||
case 'a': /* process error file */
|
||||
case 'A':
|
||||
errflag = TRUE;
|
||||
break;
|
||||
case 'e': /* -e for Edit file */
|
||||
case 'E':
|
||||
viewflag = FALSE;
|
||||
break;
|
||||
case 'g': /* -g for initial goto */
|
||||
case 'G':
|
||||
gotoflag = TRUE;
|
||||
gline = atoi(&argv[carg][2]);
|
||||
break;
|
||||
#if CRYPT
|
||||
case 'k': /* -k<key> for code key */
|
||||
case 'K':
|
||||
cryptflag = TRUE;
|
||||
strcpy(ekey, &argv[carg][2]);
|
||||
break;
|
||||
#endif
|
||||
#if PKCODE
|
||||
case 'n': /* -n accept null chars */
|
||||
case 'N':
|
||||
nullflag = TRUE;
|
||||
break;
|
||||
#endif
|
||||
case 'r': /* -r restrictive use */
|
||||
case 'R':
|
||||
restflag = TRUE;
|
||||
break;
|
||||
case 's': /* -s for initial search string */
|
||||
case 'S':
|
||||
searchflag = TRUE;
|
||||
strncpy(pat,&argv[carg][2],NPAT);
|
||||
break;
|
||||
case 'v': /* -v for View File */
|
||||
case 'V':
|
||||
viewflag = TRUE;
|
||||
break;
|
||||
default: /* unknown switch */
|
||||
/* ignore this for now */
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (argv[carg][0]== '@') {
|
||||
|
||||
/* Process Startup macroes */
|
||||
if (startup(&argv[carg][1]) == TRUE)
|
||||
/* don't execute emacs.rc */
|
||||
startflag = TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
/* Process an input file */
|
||||
|
||||
/* set up a buffer for this file */
|
||||
makename(bname, argv[carg]);
|
||||
unqname(bname);
|
||||
|
||||
/* set this to inactive */
|
||||
bp = bfind(bname, TRUE, 0);
|
||||
strcpy(bp->b_fname, argv[carg]);
|
||||
bp->b_active = FALSE;
|
||||
if (firstfile) {
|
||||
firstbp = bp;
|
||||
firstfile = FALSE;
|
||||
}
|
||||
|
||||
/* set the modes appropriatly */
|
||||
if (viewflag)
|
||||
bp->b_mode |= MDVIEW;
|
||||
#if CRYPT
|
||||
if (cryptflag) {
|
||||
bp->b_mode |= MDCRYPT;
|
||||
crypt((char *)NULL, 0);
|
||||
crypt(ekey, strlen(ekey));
|
||||
strncpy(bp->b_key, ekey, NPAT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if UNIX
|
||||
signal(SIGHUP, emergencyexit);
|
||||
signal(SIGTERM, emergencyexit);
|
||||
#endif
|
||||
|
||||
/* if we are C error parsing... run it! */
|
||||
if (errflag) {
|
||||
if (startup("error.cmd") == TRUE)
|
||||
startflag = TRUE;
|
||||
}
|
||||
|
||||
/* if invoked with no other startup files,
|
||||
run the system startup file here */
|
||||
if (startflag == FALSE) {
|
||||
startup("");
|
||||
startflag = TRUE;
|
||||
}
|
||||
discmd = TRUE; /* P.K. */
|
||||
|
||||
/* if there are any files to read, read the first one! */
|
||||
bp = bfind("main", FALSE, 0);
|
||||
if (firstfile == FALSE && (gflags & GFREAD)) {
|
||||
swbuffer(firstbp);
|
||||
zotbuf(bp);
|
||||
} else
|
||||
bp->b_mode |= gmode;
|
||||
|
||||
/* Deal with startup gotos and searches */
|
||||
if (gotoflag && searchflag) {
|
||||
update(FALSE);
|
||||
mlwrite("(Can not search and goto at the same time!)");
|
||||
}
|
||||
else if (gotoflag) {
|
||||
if (gotoline(TRUE,gline) == FALSE) {
|
||||
update(FALSE);
|
||||
mlwrite("(Bogus goto argument)");
|
||||
}
|
||||
} else if (searchflag) {
|
||||
if (forwhunt(FALSE, 0) == FALSE)
|
||||
update(FALSE);
|
||||
}
|
||||
|
||||
/* setup to process commands */
|
||||
lastflag = 0; /* Fake last flags. */
|
||||
|
||||
loop:
|
||||
|
||||
#if CALLED
|
||||
/* if we were called as a subroutine and want to leave, do so */
|
||||
if (eexitflag)
|
||||
return(eexitval);
|
||||
#endif
|
||||
|
||||
/* execute the "command" macro...normally null */
|
||||
saveflag = lastflag; /* preserve lastflag through this */
|
||||
execute(META|SPEC|'C', FALSE, 1);
|
||||
lastflag = saveflag;
|
||||
|
||||
#if TYPEAH && PKCODE
|
||||
if (typahead())
|
||||
{
|
||||
newc = getcmd();
|
||||
update(FALSE);
|
||||
do
|
||||
{
|
||||
if (c == newc && (execfunc = getbind(c)) != NULL
|
||||
&& execfunc != newline
|
||||
&& execfunc != tab)
|
||||
newc = getcmd();
|
||||
else
|
||||
break;
|
||||
} while (typahead());
|
||||
c = newc;
|
||||
}
|
||||
else
|
||||
{
|
||||
update(FALSE);
|
||||
c = getcmd();
|
||||
}
|
||||
#else
|
||||
/* Fix up the screen */
|
||||
update(FALSE);
|
||||
|
||||
/* get the next command from the keyboard */
|
||||
c = getcmd();
|
||||
#endif
|
||||
/* if there is something on the command line, clear it */
|
||||
if (mpresf != FALSE) {
|
||||
mlerase();
|
||||
update(FALSE);
|
||||
#if CLRMSG
|
||||
if (c == ' ') /* ITS EMACS does this */
|
||||
goto loop;
|
||||
#endif
|
||||
}
|
||||
f = FALSE;
|
||||
n = 1;
|
||||
|
||||
/* do META-# processing if needed */
|
||||
|
||||
basec = c & ~META; /* strip meta char off if there */
|
||||
if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
|
||||
f = TRUE; /* there is a # arg */
|
||||
n = 0; /* start with a zero default */
|
||||
mflag = 1; /* current minus flag */
|
||||
c = basec; /* strip the META */
|
||||
while ((c >= '0' && c <= '9') || (c == '-')) {
|
||||
if (c == '-') {
|
||||
/* already hit a minus or digit? */
|
||||
if ((mflag == -1) || (n != 0))
|
||||
break;
|
||||
mflag = -1;
|
||||
} else {
|
||||
n = n * 10 + (c - '0');
|
||||
}
|
||||
if ((n == 0) && (mflag == -1)) /* lonely - */
|
||||
mlwrite("Arg:");
|
||||
else
|
||||
mlwrite("Arg: %d",n * mflag);
|
||||
|
||||
c = getcmd(); /* get the next key */
|
||||
}
|
||||
n = n * mflag; /* figure in the sign */
|
||||
}
|
||||
|
||||
/* do ^U repeat argument processing */
|
||||
|
||||
if (c == reptc) { /* ^U, start argument */
|
||||
f = TRUE;
|
||||
n = 4; /* with argument of 4 */
|
||||
mflag = 0; /* that can be discarded. */
|
||||
mlwrite("Arg: 4");
|
||||
while ((c=getcmd()) >='0' && c<='9' || c==reptc || c=='-'){
|
||||
if (c == reptc)
|
||||
if ((n > 0) == ((n*4) > 0))
|
||||
n = n*4;
|
||||
else
|
||||
n = 1;
|
||||
/*
|
||||
* If dash, and start of argument string, set arg.
|
||||
* to -1. Otherwise, insert it.
|
||||
*/
|
||||
else if (c == '-') {
|
||||
if (mflag)
|
||||
break;
|
||||
n = 0;
|
||||
mflag = -1;
|
||||
}
|
||||
/*
|
||||
* If first digit entered, replace previous argument
|
||||
* with digit and set sign. Otherwise, append to arg.
|
||||
*/
|
||||
else {
|
||||
if (!mflag) {
|
||||
n = 0;
|
||||
mflag = 1;
|
||||
}
|
||||
n = 10*n + c - '0';
|
||||
}
|
||||
mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
|
||||
}
|
||||
/*
|
||||
* Make arguments preceded by a minus sign negative and change
|
||||
* the special argument "^U -" to an effective "^U -1".
|
||||
*/
|
||||
if (mflag == -1) {
|
||||
if (n == 0)
|
||||
n++;
|
||||
n = -n;
|
||||
}
|
||||
}
|
||||
|
||||
/* and execute the command */
|
||||
execute(c, f, n);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize all of the buffers and windows. The buffer name is passed down
|
||||
* as an argument, because the main routine may have been told to read in a
|
||||
* file by default, and we want the buffer name to be right.
|
||||
*/
|
||||
edinit(bname)
|
||||
char bname[];
|
||||
{
|
||||
register BUFFER *bp;
|
||||
register WINDOW *wp;
|
||||
char *malloc();
|
||||
|
||||
bp = bfind(bname, TRUE, 0); /* First buffer */
|
||||
blistp = bfind("*List*", TRUE, BFINVS); /* Buffer list buffer */
|
||||
wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */
|
||||
if (bp==NULL || wp==NULL || blistp==NULL)
|
||||
exit(1);
|
||||
curbp = bp; /* Make this current */
|
||||
wheadp = wp;
|
||||
curwp = wp;
|
||||
wp->w_wndp = NULL; /* Initialize window */
|
||||
wp->w_bufp = bp;
|
||||
bp->b_nwnd = 1; /* Displayed. */
|
||||
wp->w_linep = bp->b_linep;
|
||||
wp->w_dotp = bp->b_linep;
|
||||
wp->w_doto = 0;
|
||||
wp->w_markp = NULL;
|
||||
wp->w_marko = 0;
|
||||
wp->w_toprow = 0;
|
||||
#if COLOR
|
||||
/* initalize colors to global defaults */
|
||||
wp->w_fcolor = gfcolor;
|
||||
wp->w_bcolor = gbcolor;
|
||||
#endif
|
||||
wp->w_ntrows = term.t_nrow-1; /* "-1" for mode line. */
|
||||
wp->w_force = 0;
|
||||
wp->w_flag = WFMODE|WFHARD; /* Full. */
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the general command execution routine. It handles the fake binding
|
||||
* of all the keys to "self-insert". It also clears out the "thisflag" word,
|
||||
* and arranges to move it to the "lastflag", so that the next command can
|
||||
* look at it. Return the status of command.
|
||||
*/
|
||||
execute(c, f, n)
|
||||
{
|
||||
register int status;
|
||||
int (*execfunc)(); /* ptr to function to execute */
|
||||
int (*getbind())();
|
||||
|
||||
/* if the keystroke is a bound function...do it */
|
||||
execfunc = getbind(c);
|
||||
if (execfunc != NULL) {
|
||||
thisflag = 0;
|
||||
status = (*execfunc)(f, n);
|
||||
lastflag = thisflag;
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a space was typed, fill column is defined, the argument is non-
|
||||
* negative, wrap mode is enabled, and we are now past fill column,
|
||||
* and we are not read-only, perform word wrap.
|
||||
*/
|
||||
if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
|
||||
n >= 0 && getccol(FALSE) > fillcol &&
|
||||
(curwp->w_bufp->b_mode & MDVIEW) == FALSE)
|
||||
execute(META|SPEC|'W', FALSE, 1);
|
||||
|
||||
#if PKCODE
|
||||
if ((c>=0x20 && c<=0x7E) /* Self inserting. */
|
||||
#if IBMPC
|
||||
|| (c>=0x80 && c<=0xFE)) {
|
||||
#else
|
||||
#if VMS || BSD || USG /* 8BIT P.K. */
|
||||
|| (c>=0xA0 && c<=0xFE)) {
|
||||
#else
|
||||
) {
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
if ((c>=0x20 && c<=0xFF)) { /* Self inserting. */
|
||||
#endif
|
||||
if (n <= 0) { /* Fenceposts. */
|
||||
lastflag = 0;
|
||||
return (n<0 ? FALSE : TRUE);
|
||||
}
|
||||
thisflag = 0; /* For the future. */
|
||||
|
||||
/* if we are in overwrite mode, not at eol,
|
||||
and next char is not a tab or we are at a tab stop,
|
||||
delete a char forword */
|
||||
if (curwp->w_bufp->b_mode & MDOVER &&
|
||||
curwp->w_doto < curwp->w_dotp->l_used &&
|
||||
(lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
|
||||
(curwp->w_doto) % 8 == 7))
|
||||
ldelete(1L, FALSE);
|
||||
|
||||
/* do the appropriate insertion */
|
||||
if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
|
||||
status = insbrace(n, c);
|
||||
else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
|
||||
status = inspound();
|
||||
else
|
||||
status = linsert(n, c);
|
||||
|
||||
#if CFENCE
|
||||
/* check for CMODE fence matching */
|
||||
if ((c == '}' || c == ')' || c == ']') &&
|
||||
(curbp->b_mode & MDCMOD) != 0)
|
||||
fmatch(c);
|
||||
#endif
|
||||
|
||||
/* check auto-save mode */
|
||||
if (curbp->b_mode & MDASAVE)
|
||||
if (--gacount == 0) {
|
||||
/* and save the file if needed */
|
||||
upscreen(FALSE, 0);
|
||||
filesave(FALSE, 0);
|
||||
gacount = gasave;
|
||||
}
|
||||
|
||||
lastflag = thisflag;
|
||||
return (status);
|
||||
}
|
||||
TTbeep();
|
||||
mlwrite("(Key not bound)"); /* complain */
|
||||
lastflag = 0; /* Fake last flags. */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fancy quit command, as implemented by Norm. If the any buffer has
|
||||
* changed do a write on that buffer and exit emacs, otherwise simply exit.
|
||||
*/
|
||||
quickexit(f, n)
|
||||
{
|
||||
register BUFFER *bp; /* scanning pointer to buffers */
|
||||
register BUFFER *oldcb; /* original current buffer */
|
||||
register int status;
|
||||
|
||||
oldcb = curbp; /* save in case we fail */
|
||||
|
||||
bp = bheadp;
|
||||
while (bp != NULL) {
|
||||
if ((bp->b_flag&BFCHG) != 0 /* Changed. */
|
||||
&& (bp->b_flag&BFTRUNC) == 0 /* Not truncated P.K. */
|
||||
&& (bp->b_flag&BFINVS) == 0) { /* Real. */
|
||||
curbp = bp; /* make that buffer cur */
|
||||
mlwrite("(Saving %s)",bp->b_fname);
|
||||
#if PKCODE
|
||||
#else
|
||||
mlwrite("\n");
|
||||
#endif
|
||||
if ((status = filesave(f, n)) != TRUE) {
|
||||
curbp = oldcb; /* restore curbp */
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
bp = bp->b_bufp; /* on to the next buffer */
|
||||
}
|
||||
quit(f, n); /* conditionally quit */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static void emergencyexit(signr)
|
||||
int signr;
|
||||
{
|
||||
quickexit(FALSE, 0);
|
||||
quit(TRUE, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quit command. If an argument, always quit. Otherwise confirm if a buffer
|
||||
* has been changed and not written out. Normally bound to "C-X C-C".
|
||||
*/
|
||||
quit(f, n)
|
||||
{
|
||||
register int s;
|
||||
|
||||
if (f != FALSE /* Argument forces it. */
|
||||
|| anycb() == FALSE /* All buffers clean. */
|
||||
/* User says it's OK. */
|
||||
|| (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
|
||||
#if (FILOCK && BSD) || SVR4
|
||||
if (lockrel() != TRUE) {
|
||||
TTputc('\n');
|
||||
TTputc('\r');
|
||||
TTclose();
|
||||
TTkclose();
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
vttidy();
|
||||
if (f)
|
||||
exit(n);
|
||||
else
|
||||
exit(GOOD);
|
||||
}
|
||||
mlwrite("");
|
||||
return(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin a keyboard macro.
|
||||
* Error if not at the top level in keyboard processing. Set up variables and
|
||||
* return.
|
||||
*/
|
||||
ctlxlp(f, n)
|
||||
{
|
||||
if (kbdmode != STOP) {
|
||||
mlwrite("%%Macro already active");
|
||||
return(FALSE);
|
||||
}
|
||||
mlwrite("(Start macro)");
|
||||
kbdptr = &kbdm[0];
|
||||
kbdend = kbdptr;
|
||||
kbdmode = RECORD;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* End keyboard macro. Check for the same limit conditions as the above
|
||||
* routine. Set up the variables and return to the caller.
|
||||
*/
|
||||
ctlxrp(f, n)
|
||||
{
|
||||
if (kbdmode == STOP) {
|
||||
mlwrite("%%Macro not active");
|
||||
return(FALSE);
|
||||
}
|
||||
if (kbdmode == RECORD) {
|
||||
mlwrite("(End macro)");
|
||||
kbdmode = STOP;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a macro.
|
||||
* The command argument is the number of times to loop. Quit as soon as a
|
||||
* command gets an error. Return TRUE if all ok, else FALSE.
|
||||
*/
|
||||
ctlxe(f, n)
|
||||
{
|
||||
if (kbdmode != STOP) {
|
||||
mlwrite("%%Macro already active");
|
||||
return(FALSE);
|
||||
}
|
||||
if (n <= 0)
|
||||
return (TRUE);
|
||||
kbdrep = n; /* remember how many times to execute */
|
||||
kbdmode = PLAY; /* start us in play mode */
|
||||
kbdptr = &kbdm[0]; /* at the beginning */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Abort.
|
||||
* Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
|
||||
* Sometimes called as a routine, to do general aborting of stuff.
|
||||
*/
|
||||
ctrlg(f, n)
|
||||
{
|
||||
TTbeep();
|
||||
kbdmode = STOP;
|
||||
mlwrite("(Aborted)");
|
||||
return(ABORT);
|
||||
}
|
||||
|
||||
/* tell the user that this command is illegal while we are in
|
||||
VIEW (read-only) mode */
|
||||
|
||||
rdonly()
|
||||
|
||||
{
|
||||
TTbeep();
|
||||
mlwrite("(Key illegal in VIEW mode)");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
resterr()
|
||||
|
||||
{
|
||||
TTbeep();
|
||||
mlwrite("(That command is RESTRICTED)");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
nullproc() /* user function that does NOTHING */
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
meta() /* dummy function for binding to meta prefix */
|
||||
{
|
||||
}
|
||||
|
||||
cex() /* dummy function for binding to control-x prefix */
|
||||
{
|
||||
}
|
||||
|
||||
unarg() /* dummy function for binding to universal-argument */
|
||||
{
|
||||
}
|
||||
|
||||
/***** Compiler specific Library functions ****/
|
||||
|
||||
#if MSDOS || PKCODE
|
||||
/* strncpy: copy a string...with length restrictions
|
||||
ALWAYS null terminate
|
||||
*/
|
||||
|
||||
char *strncpy(dst, src, maxlen)
|
||||
|
||||
char *dst; /* destination of copied string */
|
||||
char *src; /* source */
|
||||
int maxlen; /* maximum length */
|
||||
|
||||
{
|
||||
char *dptr; /* ptr into dst */
|
||||
|
||||
dptr = dst;
|
||||
/* while (*src && (maxlen-- > 0))
|
||||
*dptr++ = *src++; */
|
||||
while ((maxlen > 0) && *src) {
|
||||
*dptr++ = *src++;
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
*dptr = 0; /* orig */
|
||||
/* if (maxlen > 0)
|
||||
*dptr = 0; */
|
||||
return(dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if RAMSIZE
|
||||
/* These routines will allow me to track memory usage by placing
|
||||
a layer on top of the standard system malloc() and free() calls.
|
||||
with this code defined, the environment variable, $RAM, will
|
||||
report on the number of bytes allocated via malloc.
|
||||
|
||||
with SHOWRAM defined, the number is also posted on the
|
||||
end of the bottom mode line and is updated whenever it is changed.
|
||||
*/
|
||||
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
char *allocate(nbytes) /* allocate nbytes and track */
|
||||
|
||||
unsigned nbytes; /* # of bytes to allocate */
|
||||
|
||||
{
|
||||
char *mp; /* ptr returned from malloc */
|
||||
char *malloc();
|
||||
|
||||
mp = malloc(nbytes);
|
||||
if (mp) {
|
||||
envram += nbytes;
|
||||
#if RAMSHOW
|
||||
dspram();
|
||||
#endif
|
||||
}
|
||||
|
||||
return(mp);
|
||||
}
|
||||
|
||||
release(mp) /* release malloced memory and track */
|
||||
|
||||
char *mp; /* chunk of RAM to release */
|
||||
|
||||
{
|
||||
unsigned *lp; /* ptr to the long containing the block size */
|
||||
|
||||
if (mp) {
|
||||
/* update amount of ram currently malloced */
|
||||
lp = ((unsigned *)mp) - 1;
|
||||
envram -= (long)*lp - 2;
|
||||
free(mp);
|
||||
#if RAMSHOW
|
||||
dspram();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if RAMSHOW
|
||||
dspram() /* display the amount of RAM currently malloced */
|
||||
|
||||
{
|
||||
char mbuf[20];
|
||||
char *sp;
|
||||
|
||||
TTmove(term.t_nrow - 1, 70);
|
||||
#if COLOR
|
||||
TTforg(7);
|
||||
TTbacg(0);
|
||||
#endif
|
||||
sprintf(mbuf, "[%lu]", envram);
|
||||
sp = &mbuf[0];
|
||||
while (*sp)
|
||||
TTputc(*sp++);
|
||||
TTmove(term.t_nrow, 0);
|
||||
movecursor(term.t_nrow, 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* On some primitave operation systems, and when emacs is used as
|
||||
a subprogram to a larger project, emacs needs to de-alloc its
|
||||
own used memory
|
||||
*/
|
||||
|
||||
#if CLEAN
|
||||
cexit(status)
|
||||
|
||||
int status; /* return status of emacs */
|
||||
|
||||
{
|
||||
register BUFFER *bp; /* buffer list pointer */
|
||||
register WINDOW *wp; /* window list pointer */
|
||||
register WINDOW *tp; /* temporary window pointer */
|
||||
|
||||
/* first clean up the windows */
|
||||
wp = wheadp;
|
||||
while (wp) {
|
||||
tp = wp->w_wndp;
|
||||
free(wp);
|
||||
wp = tp;
|
||||
}
|
||||
wheadp = NULL;
|
||||
|
||||
/* then the buffers */
|
||||
bp = bheadp;
|
||||
while (bp) {
|
||||
bp->b_nwnd = 0;
|
||||
bp->b_flag = 0; /* don't say anything about a changed buffer! */
|
||||
zotbuf(bp);
|
||||
bp = bheadp;
|
||||
}
|
||||
|
||||
/* and the kill buffer */
|
||||
kdelete();
|
||||
|
||||
/* and the video buffers */
|
||||
vtfree();
|
||||
|
||||
/* and now.. we leave [pick the return if we are a subprogram] */
|
||||
#if CALLED
|
||||
eexitflag = TRUE; /* flag a program exit */
|
||||
eexitval = status;
|
||||
return(status);
|
||||
#else
|
||||
#undef exit
|
||||
exit(status);
|
||||
#endif
|
||||
}
|
||||
#endif
|
124
makefile
Normal file
124
makefile
Normal file
@ -0,0 +1,124 @@
|
||||
# makefile for emacs, updated Sun Apr 28 17:59:07 EET DST 1996
|
||||
|
||||
SRC=ansi.c basic.c bind.c buffer.c crypt.c display.c eval.c exec.c \
|
||||
file.c fileio.c ibmpc.c input.c isearch.c line.c lock.c main.c \
|
||||
pklock.c posix.c random.c region.c search.c spawn.c tcap.c \
|
||||
termio.c vmsvt.c vt52.c window.c word.c
|
||||
|
||||
OBJ=ansi.o basic.o bind.o buffer.o crypt.o display.o eval.o exec.o \
|
||||
file.o fileio.o ibmpc.o input.o isearch.o line.o lock.o main.o \
|
||||
pklock.o posix.o random.o region.o search.o spawn.o tcap.o \
|
||||
termio.o vmsvt.o vt52.o window.o word.o
|
||||
|
||||
HDR=ebind.h edef.h efunc.h epath.h estruct.h evar.h
|
||||
|
||||
# DO NOT ADD OR MODIFY ANY LINES ABOVE THIS -- make source creates them
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-O4
|
||||
#CC=c89 +O3 # HP
|
||||
#CFLAGS= -D_HPUX_SOURCE -DSYSV
|
||||
#CFLAGS=-O4 -DSVR4 # Sun
|
||||
#CFLAGS=-O -qchars=signed # RS/6000
|
||||
DEFINES=-DAUTOCONF -DPOSIX -DUSG # Linux
|
||||
#DEFINES=-DAUTOCONF
|
||||
#LIBS=-ltermcap # BSD
|
||||
#LIBS=-lcurses # SYSV
|
||||
#LIBS=-ltermlib
|
||||
LIBS=-L/usr/lib/termcap -ltermcap
|
||||
LFLAGS=-hbx
|
||||
BINDIR=/usr/bin
|
||||
LIBDIR=/usr/lib
|
||||
|
||||
em: ${OBJ}
|
||||
${CC} ${DEFINES} -o em ${OBJ} ${LIBS}
|
||||
|
||||
clean:
|
||||
rm -f core lintout makeout tags makefile.bak *.o
|
||||
|
||||
install: em
|
||||
strip em
|
||||
cp em ${BINDIR}
|
||||
cp emacs.hlp ${LIBDIR}
|
||||
cp emacs.rc ${LIBDIR}/.emacsrc
|
||||
chmod 755 ${BINDIR}/em
|
||||
chmod 644 ${LIBDIR}/emacs.hlp ${LIBDIR}/.emacsrc
|
||||
|
||||
lint: ${SRC}
|
||||
@rm -f lintout
|
||||
lint ${LFLAGS} ${SRC} >lintout
|
||||
cat lintout
|
||||
|
||||
errs:
|
||||
@rm -f makeout
|
||||
make em >makeout
|
||||
|
||||
tags: ${SRC}
|
||||
@rm -f tags
|
||||
ctags ${SRC}
|
||||
|
||||
source:
|
||||
@mv makefile makefile.bak
|
||||
@echo "# makefile for emacs, updated `date`" >makefile
|
||||
@echo '' >>makefile
|
||||
@echo SRC=`ls *.c` >>makefile
|
||||
@echo OBJ=`ls *.c | sed s/c$$/o/` >>makefile
|
||||
@echo HDR=`ls *.h` >>makefile
|
||||
@echo '' >>makefile
|
||||
@sed -n -e '/^# DO NOT ADD OR MODIFY/,$$p' <makefile.bak >>makefile
|
||||
|
||||
depend: ${SRC}
|
||||
@for i in ${SRC}; do\
|
||||
cc ${DEFINES} -M $$i | sed -e 's, \./, ,' | grep -v '/usr/include' | \
|
||||
awk '{ if ($$1 != prev) { if (rec != "") print rec; \
|
||||
rec = $$0; prev = $$1; } \
|
||||
else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
|
||||
else rec = rec " " $$2 } } \
|
||||
END { print rec }'; done >makedep
|
||||
@echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
|
||||
@echo '$$r ./makedep' >>eddep
|
||||
@echo 'w' >>eddep
|
||||
@cp makefile makefile.bak
|
||||
@ed - makefile <eddep
|
||||
@rm eddep makedep
|
||||
@echo '' >>makefile
|
||||
@echo '# DEPENDENCIES MUST END AT END OF FILE' >>makefile
|
||||
@echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>makefile
|
||||
@echo '# see make depend above' >>makefile
|
||||
|
||||
.c.o:
|
||||
${CC} ${CFLAGS} ${DEFINES} -c $*.c
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend uses it
|
||||
|
||||
ansi.o: ansi.c estruct.h edef.h
|
||||
basic.o: basic.c estruct.h edef.h
|
||||
bind.o: bind.c estruct.h edef.h epath.h
|
||||
buffer.o: buffer.c estruct.h edef.h
|
||||
crypt.o: crypt.c estruct.h edef.h
|
||||
display.o: display.c estruct.h edef.h
|
||||
eval.o: eval.c estruct.h edef.h evar.h
|
||||
exec.o: exec.c estruct.h edef.h
|
||||
file.o: file.c estruct.h edef.h
|
||||
fileio.o: fileio.c estruct.h edef.h
|
||||
ibmpc.o: ibmpc.c estruct.h edef.h
|
||||
input.o: input.c estruct.h edef.h
|
||||
isearch.o: isearch.c estruct.h edef.h
|
||||
line.o: line.c estruct.h edef.h
|
||||
lock.o: lock.c estruct.h edef.h
|
||||
main.o: main.c estruct.h efunc.h edef.h ebind.h
|
||||
pklock.o: pklock.c estruct.h
|
||||
random.o: random.c estruct.h edef.h
|
||||
region.o: region.c estruct.h edef.h
|
||||
search.o: search.c estruct.h edef.h
|
||||
spawn.o: spawn.c estruct.h edef.h
|
||||
tcap.o: tcap.c estruct.h edef.h
|
||||
termio.o: termio.c estruct.h edef.h
|
||||
vmsvt.o: vmsvt.c estruct.h edef.h
|
||||
vt52.o: vt52.c estruct.h edef.h
|
||||
window.o: window.c estruct.h edef.h
|
||||
word.o: word.c estruct.h edef.h
|
||||
|
||||
# DEPENDENCIES MUST END AT END OF FILE
|
||||
# IF YOU PUT STUFF HERE IT WILL GO AWAY
|
||||
# see make depend above
|
22
makefile.dos
Normal file
22
makefile.dos
Normal file
@ -0,0 +1,22 @@
|
||||
CFLAGS= -AL -ot -Gs
|
||||
|
||||
OFILES= ansi.obj basic.obj bind.obj buffer.obj crypt.obj \
|
||||
display.obj eval.obj exec.obj file.obj fileio.obj \
|
||||
ibmpc.obj input.obj isearch.obj line.obj \
|
||||
lock.obj main.obj random.obj region.obj search.obj spawn.obj \
|
||||
tcap.obj termio.obj vmsvt.obj vt52.obj \
|
||||
window.obj word.obj pklock.obj
|
||||
|
||||
CFILES= ansi.c basic.c bind.c buffer.c crypt.c \
|
||||
display.c eval.c exec.c file.c fileio.c \
|
||||
ibmpc.c input.c isearch.c line.c \
|
||||
lock.c main.c random.c region.c search.c spawn.c \
|
||||
tcap.c termio.c vmsvt.c vt52.c \
|
||||
window.c word.c pklock.c
|
||||
|
||||
HFILES= estruct.h edef.h efunc.h epath.h ebind.h evar.h
|
||||
|
||||
emacs.exe: $(OFILES)
|
||||
link @emacso.lnk
|
||||
|
||||
$(OFILES): $(HFILES)
|
121
makefile.unx
Normal file
121
makefile.unx
Normal file
@ -0,0 +1,121 @@
|
||||
#
|
||||
# makefile for uEmacs/PK 4.0
|
||||
#
|
||||
|
||||
SRC=ansi.c basic.c bind.c buffer.c crypt.c display.c eval.c exec.c file.c \
|
||||
fileio.c ibmpc.c input.c isearch.c line.c lock.c main.c pklock.c \
|
||||
random.c region.c search.c spawn.c tcap.c termio.c vmsvt.c vt52.c \
|
||||
window.c word.c
|
||||
OBJ=ansi.o basic.o bind.o buffer.o crypt.o display.o eval.o exec.o file.o \
|
||||
fileio.o ibmpc.o input.o isearch.o line.o lock.o main.o pklock.o \
|
||||
random.o region.o search.o spawn.o tcap.o termio.o vmsvt.o vt52.o \
|
||||
window.o word.o
|
||||
HDR=ebind.h edef.h efunc.h epath.h estruct.h evar.h
|
||||
|
||||
# DO NOT ADD OR MODIFY ANY LINES ABOVE THIS -- make source creates them
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-O
|
||||
#CC=c89 +O3 # HP
|
||||
#CFLAGS= -D_HPUX_SOURCE -DSYSV
|
||||
#CFLAGS=-O4 # Sun
|
||||
#CFLAGS=-O -qchars=signed # RS/6000
|
||||
DEFINES=-DAUTOCONF
|
||||
LIBS=-ltermcap # BSD
|
||||
#LIBS=-lcurses # SYSV
|
||||
LFLAGS=-hbx
|
||||
BINDIR=/usr/local/bin
|
||||
LIBDIR=/usr/local/lib
|
||||
|
||||
emacs: ${OBJ}
|
||||
${CC} ${DEFINES} -o emacs ${OBJ} ${LIBS}
|
||||
|
||||
clean:
|
||||
rm -f core lintout makeout tags makefile.bak *.o
|
||||
|
||||
install: emacs
|
||||
strip emacs
|
||||
cp emacs ${BINDIR}
|
||||
cp emacs.hlp ${LIBDIR}
|
||||
cp emacs.rc ${LIBDIR}/.emacsrc
|
||||
chmod 755 ${BINDIR}/emacs
|
||||
chmod 644 ${LIBDIR}/emacs.hlp ${LIBDIR}/.emacsrc
|
||||
|
||||
lint: ${SRC}
|
||||
@rm -f lintout
|
||||
lint ${LFLAGS} ${SRC} >lintout
|
||||
cat lintout
|
||||
|
||||
errs:
|
||||
@rm -f makeout
|
||||
make emacs >makeout
|
||||
|
||||
tags: ${SRC}
|
||||
@rm -f tags
|
||||
ctags ${SRC}
|
||||
|
||||
source:
|
||||
@mv makefile makefile.bak
|
||||
@echo "# makefile for emacs, updated `date`" >makefile
|
||||
@echo '' >>makefile
|
||||
@echo SRC=`ls *.c` >>makefile
|
||||
@echo OBJ=`ls *.c | sed s/c$$/o/` >>makefile
|
||||
@echo HDR=`ls *.h` >>makefile
|
||||
@echo '' >>makefile
|
||||
@sed -n -e '/^# DO NOT ADD OR MODIFY/,$$p' <makefile.bak >>makefile
|
||||
|
||||
depend: ${SRC}
|
||||
@for i in ${SRC}; do\
|
||||
cc ${DEFINES} -M $$i | sed -e 's, \./, ,' | grep -v '/usr/include' | \
|
||||
awk '{ if ($$1 != prev) { if (rec != "") print rec; \
|
||||
rec = $$0; prev = $$1; } \
|
||||
else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
|
||||
else rec = rec " " $$2 } } \
|
||||
END { print rec }'; done >makedep
|
||||
@echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
|
||||
@echo '$$r ./makedep' >>eddep
|
||||
@echo 'w' >>eddep
|
||||
@cp makefile makefile.bak
|
||||
@ed - makefile <eddep
|
||||
@rm eddep makedep
|
||||
@echo '' >>makefile
|
||||
@echo '# DEPENDENCIES MUST END AT END OF FILE' >>makefile
|
||||
@echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>makefile
|
||||
@echo '# see make depend above' >>makefile
|
||||
|
||||
.c.o:
|
||||
${CC} ${CFLAGS} ${DEFINES} -c $*.c
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend uses it
|
||||
|
||||
ansi.o: ansi.c estruct.h edef.h
|
||||
basic.o: basic.c estruct.h edef.h
|
||||
bind.o: bind.c estruct.h edef.h epath.h
|
||||
buffer.o: buffer.c estruct.h edef.h
|
||||
crypt.o: crypt.c estruct.h edef.h
|
||||
display.o: display.c estruct.h edef.h
|
||||
eval.o: eval.c estruct.h edef.h evar.h
|
||||
exec.o: exec.c estruct.h edef.h
|
||||
file.o: file.c estruct.h edef.h
|
||||
fileio.o: fileio.c estruct.h edef.h
|
||||
ibmpc.o: ibmpc.c estruct.h edef.h
|
||||
input.o: input.c estruct.h edef.h
|
||||
isearch.o: isearch.c estruct.h edef.h
|
||||
line.o: line.c estruct.h edef.h
|
||||
lock.o: lock.c estruct.h edef.h
|
||||
main.o: main.c estruct.h efunc.h edef.h ebind.h
|
||||
pklock.o: pklock.c estruct.h
|
||||
random.o: random.c estruct.h edef.h
|
||||
region.o: region.c estruct.h edef.h
|
||||
search.o: search.c estruct.h edef.h
|
||||
spawn.o: spawn.c estruct.h edef.h
|
||||
tcap.o: tcap.c estruct.h edef.h
|
||||
termio.o: termio.c estruct.h edef.h
|
||||
vmsvt.o: vmsvt.c estruct.h edef.h
|
||||
vt52.o: vt52.c estruct.h edef.h
|
||||
window.o: window.c estruct.h edef.h
|
||||
word.o: word.c estruct.h edef.h
|
||||
|
||||
# DEPENDENCIES MUST END AT END OF FILE
|
||||
# IF YOU PUT STUFF HERE IT WILL GO AWAY
|
||||
# see make depend above
|
61
makefilepatch
Normal file
61
makefilepatch
Normal file
@ -0,0 +1,61 @@
|
||||
***************
|
||||
*** 1,29 ****
|
||||
- #
|
||||
- # makefile for uEmacs/PK 4.0
|
||||
- #
|
||||
|
||||
- SRC=ansi.c basic.c bind.c buffer.c crypt.c display.c eval.c exec.c file.c \
|
||||
- fileio.c ibmpc.c input.c isearch.c line.c lock.c main.c pklock.c \
|
||||
- random.c region.c search.c spawn.c tcap.c termio.c vmsvt.c vt52.c \
|
||||
- window.c word.c
|
||||
- OBJ=ansi.o basic.o bind.o buffer.o crypt.o display.o eval.o exec.o file.o \
|
||||
- fileio.o ibmpc.o input.o isearch.o line.o lock.o main.o pklock.o \
|
||||
- random.o region.o search.o spawn.o tcap.o termio.o vmsvt.o vt52.o \
|
||||
- window.o word.o
|
||||
HDR=ebind.h edef.h efunc.h epath.h estruct.h evar.h
|
||||
|
||||
# DO NOT ADD OR MODIFY ANY LINES ABOVE THIS -- make source creates them
|
||||
|
||||
- CC=cc
|
||||
- CFLAGS=-O
|
||||
#CC=c89 +O3 # HP
|
||||
#CFLAGS= -D_HPUX_SOURCE -DSYSV
|
||||
- CFLAGS=-O4 -DSVR4 # Sun
|
||||
#CFLAGS=-O -qchars=signed # RS/6000
|
||||
- DEFINES=-DAUTOCONF
|
||||
- #LIBS=-ltermcap # BSD
|
||||
#LIBS=-lcurses # SYSV
|
||||
- LIBS=-ltermlib
|
||||
LFLAGS=-hbx
|
||||
BINDIR=/usr/local/bin
|
||||
LIBDIR=/usr/local/lib
|
||||
--- 1,29 ----
|
||||
+ # makefile for emacs, updated Sun Apr 28 17:59:07 EET DST 1996
|
||||
+
|
||||
+ SRC=ansi.c basic.c bind.c buffer.c crypt.c display.c eval.c exec.c \
|
||||
+ file.c fileio.c ibmpc.c input.c isearch.c line.c lock.c main.c \
|
||||
+ pklock.c posix.c random.c region.c search.c spawn.c tcap.c \
|
||||
+ termio.c vmsvt.c vt52.c window.c word.c
|
||||
+
|
||||
+ OBJ=ansi.o basic.o bind.o buffer.o crypt.o display.o eval.o exec.o \
|
||||
+ file.o fileio.o ibmpc.o input.o isearch.o line.o lock.o main.o \
|
||||
+ pklock.o posix.o random.o region.o search.o spawn.o tcap.o \
|
||||
+ termio.o vmsvt.o vt52.o window.o word.o
|
||||
|
||||
HDR=ebind.h edef.h efunc.h epath.h estruct.h evar.h
|
||||
|
||||
# DO NOT ADD OR MODIFY ANY LINES ABOVE THIS -- make source creates them
|
||||
|
||||
+ CC=gcc
|
||||
+ CFLAGS=-O4
|
||||
#CC=c89 +O3 # HP
|
||||
#CFLAGS= -D_HPUX_SOURCE -DSYSV
|
||||
+ #CFLAGS=-O4 -DSVR4 # Sun
|
||||
#CFLAGS=-O -qchars=signed # RS/6000
|
||||
+ DEFINES=-DAUTOCONF -DPOSIX -DUSG
|
||||
+ LIBS=-ltermcap # BSD
|
||||
#LIBS=-lcurses # SYSV
|
||||
+ #LIBS=-ltermlib
|
||||
LFLAGS=-hbx
|
||||
BINDIR=/usr/local/bin
|
||||
LIBDIR=/usr/local/lib
|
125
pklock.c
Normal file
125
pklock.c
Normal file
@ -0,0 +1,125 @@
|
||||
/* PKLOCK.C
|
||||
*
|
||||
* locking routines as modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include "estruct.h"
|
||||
|
||||
#if (FILOCK && BSD) || SVR4
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef SVR4
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#define MAXLOCK 512
|
||||
#define MAXNAME 128
|
||||
|
||||
#if defined(SVR4) && ! defined(__linux__)
|
||||
#include <sys/systeminfo.h>
|
||||
|
||||
int gethostname(char *name, int namelen)
|
||||
{
|
||||
return(sysinfo(SI_HOSTNAME, name, namelen));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
*
|
||||
* if successful, returns NULL
|
||||
* if file locked, returns username of person locking the file
|
||||
* if other error, returns "LOCK ERROR: explanation"
|
||||
*
|
||||
*********************/
|
||||
char *dolock(fname)
|
||||
char *fname;
|
||||
{
|
||||
int fd, lk, n;
|
||||
static char lname[MAXLOCK], locker[MAXNAME+1];
|
||||
int mask;
|
||||
struct stat sbuf;
|
||||
|
||||
strcat(strcpy(lname, fname), ".lock~");
|
||||
|
||||
/* check that we are not being cheated, qname must point to */
|
||||
/* a regular file - even this code leaves a small window of */
|
||||
/* vulnerability but it is rather hard to exploit it */
|
||||
|
||||
#if defined(S_IFLNK)
|
||||
if (lstat(lname, &sbuf) == 0)
|
||||
#else
|
||||
if (stat(lname, &sbuf) == 0)
|
||||
#endif
|
||||
#if defined(S_ISREG)
|
||||
if (! S_ISREG(sbuf.st_mode))
|
||||
#else
|
||||
if (! (((sbuf.st_mode) & 070000) == 0)) /* SysV R2 */
|
||||
#endif
|
||||
return "LOCK ERROR: not a regular file";
|
||||
|
||||
mask = umask(0);
|
||||
fd = open(lname, O_RDWR | O_CREAT, 0666);
|
||||
umask(mask);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (errno == EACCES)
|
||||
return NULL;
|
||||
#ifdef EROFS
|
||||
if (errno == EROFS)
|
||||
return NULL;
|
||||
#endif
|
||||
return "LOCK ERROR: cannot access lock file";
|
||||
}
|
||||
if ((n = read(fd, locker, MAXNAME)) < 1)
|
||||
{
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
/* strcpy(locker, getlogin()); */
|
||||
cuserid(locker);
|
||||
strcat(locker+strlen(locker), "@");
|
||||
gethostname(locker+strlen(locker), 64);
|
||||
write(fd, locker, strlen(locker));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
locker[n > MAXNAME ? MAXNAME : n] = 0;
|
||||
return locker;
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
*
|
||||
* undolock -- unlock the file fname
|
||||
*
|
||||
* if successful, returns NULL
|
||||
* if other error, returns "LOCK ERROR: explanation"
|
||||
*
|
||||
*********************/
|
||||
|
||||
char *undolock(fname)
|
||||
char *fname;
|
||||
{
|
||||
int fd, lk;
|
||||
static char lname[MAXLOCK];
|
||||
|
||||
strcat(strcpy(lname, fname), ".lock~");
|
||||
if (unlink(lname) != 0)
|
||||
{
|
||||
if (errno == EACCES || errno == ENOENT)
|
||||
return NULL;
|
||||
#ifdef EROFS
|
||||
if (errno == EROFS)
|
||||
return NULL;
|
||||
#endif
|
||||
return "LOCK ERROR: cannot remove lock file";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
159
posix.c
Normal file
159
posix.c
Normal file
@ -0,0 +1,159 @@
|
||||
/* POSIX.C
|
||||
*
|
||||
* The functions in this file negotiate with the operating system for
|
||||
* characters, and write characters in a barely buffered fashion on the display.
|
||||
* All operating systems.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*
|
||||
* based on termio.c, with all the old cruft removed, and
|
||||
* fixed for termios rather than the old termio.. Linus Torvalds
|
||||
*/
|
||||
|
||||
#ifdef POSIX
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
int kbdflgs; /* saved keyboard fd flags */
|
||||
int kbdpoll; /* in O_NDELAY mode */
|
||||
int kbdqp; /* there is a char in kbdq */
|
||||
char kbdq; /* char we've already read */
|
||||
|
||||
struct termios otermios; /* original terminal characteristics */
|
||||
struct termios ntermios; /* charactoristics to use inside */
|
||||
|
||||
#define TBUFSIZ 128
|
||||
char tobuf[TBUFSIZ]; /* terminal output buffer */
|
||||
|
||||
|
||||
/*
|
||||
* This function is called once to set up the terminal device streams.
|
||||
* On VMS, it translates TT until it finds the terminal, then assigns
|
||||
* a channel to it and sets it raw. On CPM it is a no-op.
|
||||
*/
|
||||
ttopen()
|
||||
{
|
||||
tcgetattr(0, &otermios); /* save old settings */
|
||||
|
||||
/*
|
||||
* base new settings on old ones - don't change things
|
||||
* we don't know about
|
||||
*/
|
||||
ntermios = otermios;
|
||||
|
||||
/* raw CR/NL etc input handling, but keep ISTRIP if we're on a 7-bit line */
|
||||
ntermios.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK
|
||||
| INPCK | INLCR | IGNCR | ICRNL);
|
||||
|
||||
/* raw CR/NR etc output handling */
|
||||
ntermios.c_oflag &= ~(OPOST | ONLCR | OLCUC | OCRNL | ONOCR | ONLRET);
|
||||
|
||||
/* No signal handling, no echo etc */
|
||||
ntermios.c_lflag &= ~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK
|
||||
| ECHONL | NOFLSH | TOSTOP | ECHOCTL | ECHOPRT
|
||||
| ECHOKE | FLUSHO | PENDIN | IEXTEN);
|
||||
|
||||
/* one character, no timeout */
|
||||
ntermios.c_cc[VMIN] = 1;
|
||||
ntermios.c_cc[VTIME] = 0;
|
||||
tcsetattr(0, TCSADRAIN, &ntermios); /* and activate them */
|
||||
|
||||
/*
|
||||
* provide a smaller terminal output buffer so that
|
||||
* the type ahead detection works better (more often)
|
||||
*/
|
||||
setbuffer(stdout, &tobuf[0], TBUFSIZ);
|
||||
|
||||
kbdflgs = fcntl( 0, F_GETFL, 0 );
|
||||
kbdpoll = FALSE;
|
||||
|
||||
/* on all screens we are not sure of the initial position
|
||||
of the cursor */
|
||||
ttrow = 999;
|
||||
ttcol = 999;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function gets called just before we go back home to the command
|
||||
* interpreter. On VMS it puts the terminal back in a reasonable state.
|
||||
* Another no-operation on CPM.
|
||||
*/
|
||||
ttclose()
|
||||
{
|
||||
tcsetattr(0, TCSADRAIN, &otermios); /* restore terminal settings */
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a character to the display. On VMS, terminal output is buffered, and
|
||||
* we just put the characters in the big array, after checking for overflow.
|
||||
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
|
||||
* MS-DOS (use the very very raw console output routine).
|
||||
*/
|
||||
ttputc(c)
|
||||
{
|
||||
fputc(c, stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush terminal buffer. Does real work where the terminal output is buffered
|
||||
* up. A no-operation on systems where byte at a time terminal I/O is done.
|
||||
*/
|
||||
ttflush()
|
||||
{
|
||||
/*
|
||||
* Add some terminal output success checking, sometimes an orphaned
|
||||
* process may be left looping on SunOS 4.1.
|
||||
*
|
||||
* How to recover here, or is it best just to exit and lose
|
||||
* everything?
|
||||
*
|
||||
* jph, 8-Oct-1993
|
||||
* Jani Jaakkola suggested using select after EAGAIN but let's just wait a bit
|
||||
*
|
||||
*/
|
||||
int status;
|
||||
|
||||
status = fflush(stdout);
|
||||
while (status < 0 && errno == EAGAIN) {
|
||||
sleep(1);
|
||||
status = fflush(stdout);
|
||||
}
|
||||
if (status < 0)
|
||||
exit(15);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a character from the terminal, performing no editing and doing no echo
|
||||
* at all. More complex in VMS that almost anyplace else, which figures. Very
|
||||
* simple on CPM, because the system can do exactly what you want.
|
||||
*/
|
||||
ttgetc()
|
||||
{
|
||||
return(255 & fgetc(stdin)); /* 8BIT P.K. */
|
||||
}
|
||||
|
||||
/* typahead: Check to see if any characters are already in the
|
||||
keyboard buffer
|
||||
*/
|
||||
|
||||
typahead()
|
||||
{
|
||||
int x; /* holds # of pending chars */
|
||||
|
||||
#ifdef FIONREAD
|
||||
if (ioctl(0,FIONREAD,&x) < 0)
|
||||
x = 0;
|
||||
#else
|
||||
x = 0;
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif /* POSIX */
|
182
readme
Normal file
182
readme
Normal file
@ -0,0 +1,182 @@
|
||||
+---------------+
|
||||
| uEmacs/PK 4.0 |
|
||||
+---------------+
|
||||
|
||||
Full screen editor based on MicroEMACS 3.9e
|
||||
|
||||
MicroEMACS was written by Dave G. Conroy and
|
||||
greatly modified by Daniel M. Lawrence
|
||||
|
||||
Copyright Notices:
|
||||
|
||||
MicroEMACS 3.9 (c) Copyright 1987 Daniel M. Lawrence.
|
||||
Reference Manual Copyright 1987 by Brian Straight and
|
||||
Daniel M. Lawrence. No copyright claimed for modifications
|
||||
made by Petri H. Kutvonen.
|
||||
|
||||
Original statement of copying policy:
|
||||
|
||||
MicroEMACS 3.9 can be copied and distributed freely for any
|
||||
non-commercial purposes. MicroEMACS 3.9 can only be incorporated
|
||||
into commercial software with the permission of the current author
|
||||
[Daniel M. Lawrence].
|
||||
|
||||
|
||||
WHAT IS uEmacs/PK?
|
||||
|
||||
uEmacs/PK 4.0 is an enhanced version of MicroEMACS 3.9e. Enhancements
|
||||
have been incorporated by Petri H. Kutvonen, University of Helsinki,
|
||||
Finland <kutvonen@cs.Helsinki.FI>.
|
||||
|
||||
|
||||
WHY IS IT BASED ON AN OLD VERSION OF MicroEMACS?
|
||||
|
||||
In my opinion 3.9e was the best of all MicroEMACSes. Creeping
|
||||
featurism, growing size, and reduced portability made versions 3.10 and
|
||||
3.11 less attractive. MicroEMACS 3.9e was one of the few editors that
|
||||
were truly portable between different flavours of UNIX, PC/MS-DOS, and
|
||||
VAX/VMS. It was pretty robust - although not flawless. uEmacs/PK 4.0
|
||||
includes numerous bug fixes, adds some new functionality and comfort but
|
||||
does not sacrifice the best things (small size and portability).
|
||||
|
||||
|
||||
WHAT IS NEW - COMPARED TO MicroEMACS 3.9e?
|
||||
|
||||
Enhachements:
|
||||
|
||||
o advisory file locking on BSD-derived systems
|
||||
o new screen update algorithm, borrowed largely form "vile" by
|
||||
Paul G. Fox <pgf@cayman.com>, uEmacs can now be used on slow (1200 bps)
|
||||
connections because it uses terminal scrolling capabilities
|
||||
o new variables $scroll, $jump, and $overlap to control scrolling
|
||||
o uEmacs reacts to windows size change signals (UNIX), also from "vile"
|
||||
o automatic file name completion, works under UNIX and PC/MS-DOS
|
||||
o functions keys on VT200 style keyboards can be used
|
||||
o new command: justify-paragraph (Meta J)
|
||||
o something important for us Europeans: allow the use of 8 bit ISO Latin 1
|
||||
alphabet (UNIX and VMS), on an IBM-PC the accented characters are
|
||||
interpreted as letters too
|
||||
o the characters {|}[\] can be interpreted as letters, these are
|
||||
frequently used as "national replacement characters" especially in
|
||||
the Nordic countries
|
||||
o allow use of XON/XOFF flow control: alternative key sequences for
|
||||
^S and ^Q, don't disable flow control
|
||||
o speed up reading of files (under VMS especially)
|
||||
o new variable $tab, hardware tab stop (4 or 8)
|
||||
o automatic configuration on some common systems
|
||||
o new style mode line, includes percentage indicator
|
||||
o new help file
|
||||
|
||||
Bug fixes - not very interesting:
|
||||
|
||||
o use TI and TE termcap strings, uEmacs works now correctly under
|
||||
Sunview and OpenWindows
|
||||
o use old protection mask on existing files (VMS)
|
||||
o catch data overrun errors (VMS)
|
||||
o allow VMS file names with characters < and >, replacements for [ and ]
|
||||
o allow ANSI screens larger than 24 lines
|
||||
o fix add/delete(-global)-mode
|
||||
o display EOF as char = 0x0, not as garbage
|
||||
o allow upper case letters in answers
|
||||
o fix command interpreter spawning
|
||||
o don't use reverse video on some (TVI925 style) terminals
|
||||
o fix message line writing
|
||||
o fix replace/undo
|
||||
o fix &left and &mid functions
|
||||
o fix documentation
|
||||
o smaller bug fixes are too numerous to mention
|
||||
|
||||
Something is gone:
|
||||
|
||||
o removed (obsolete and untested) support for Amiga, Atari, and Mac
|
||||
|
||||
|
||||
WHERE HAS IT BEEN TESTED?
|
||||
|
||||
uEmacs/PK 4.0 has been tested by myself on the following platforms:
|
||||
|
||||
IBM PC and compatibles, PC/MS-DOS 3.2 and up
|
||||
Sun 3, SunOS 4.1.1
|
||||
SPARC, SunOS 4.1.X and 5.{2|3|4|5} (Solaris 2)
|
||||
VAX 8800 and 6000-420, VMS 5.4
|
||||
DECstation 3100, Ultrix V4.1
|
||||
IBM RS/6000, AIX 3.1.5
|
||||
IBM PS/2, UNIX System V/386 Release 3.2
|
||||
uVAX II, Ultrix V2.0
|
||||
AT&T 3B2/400, UNIX System V Release 2.0
|
||||
Various Toshiba i486 laptops, Linux 0.99pl13 thru 2.0.21
|
||||
|
||||
I have no reason to believe that there would be any problems to port
|
||||
uEmacs/PK 4.0 to any reasonable BSD-, OSF/1-, or SVR4-based UNIX system.
|
||||
|
||||
|
||||
HOW CAN I GET IT?
|
||||
|
||||
uEmacs/PK is available by anonymous FTP from ftp.cs.Helsinki.FI (IP
|
||||
address can change) in the directory pub/Software/Local/uEmacs-PK. You
|
||||
cannot get it by email of uucp. Hopefully it will bee soon available
|
||||
from other file servers too.
|
||||
|
||||
|
||||
WHAT IS IN THE PACKAGE
|
||||
|
||||
o em-4.0.<x>.tar.gz: full source, make and command files to build the
|
||||
editor, reference manual as a MS-Write document,
|
||||
tarred and gzipped, for patchlevel <x>
|
||||
|
||||
o there used to be a packages with binaries for PC/MS-DOS,
|
||||
SPARC/SunOS4, Sun 3, MIPS/Ultrix, 386/ix, IBM RS/6000, VAX/VMS,
|
||||
if you are really desperate you can try contacting me for an old
|
||||
version of these
|
||||
|
||||
|
||||
HOW TO INSTALL uEmacs/PK?
|
||||
|
||||
o PC/MS-DOS: Compile the package with using Turbo C 2.0 or MSC 6.0.
|
||||
(Pretty obsolete both of these.) There are some support files
|
||||
you might find useful in the full distribution.
|
||||
|
||||
o UNIX: Copy makefile.unx to makefile, edit to taste, look at estruct.h,
|
||||
do a 'make', test the editor, 'make install'.
|
||||
|
||||
o VMS: To compile use '@VMSMAKE', install manually, uEmacs/PK uses a
|
||||
logical name EMACS_DIR to locate its initialization files.
|
||||
|
||||
|
||||
CONTACT INFORMATION
|
||||
|
||||
There will probably not be many new versions of uEmacs/PK, maybe just
|
||||
some bug fixes. I have no intention to develope the code any further.
|
||||
However, if you have some comments or good suggestions, you may find
|
||||
the email address below useful.
|
||||
|
||||
Petri H. Kutvonen
|
||||
Department of Computer Science
|
||||
P.O.Box 26 (Teollisuuskatu 23)
|
||||
FIN-00014 UNIVERSTITY OF HELSINKI
|
||||
Finland
|
||||
|
||||
email: kutvonen@cs.Helsinki.FI
|
||||
fax: +358 9 70844441
|
||||
|
||||
|
||||
ACKNOWLEDGEMENTS AND STATUS
|
||||
|
||||
I would like to thank Linus Torvalds and Jyrki Havia for their work on
|
||||
some bugs. uEmacs/PK 4.0.10 included fixes for a number of bugs and it
|
||||
was assumed to be the final release for the UNIX platform. However,
|
||||
there has been a couple of maintenance releases, so the final version is
|
||||
4.0.13. On other platforms there has been no new releases since 4.0.3 in
|
||||
1991.
|
||||
|
||||
April 23, 1995
|
||||
|
||||
And yet another release (thanks Linus)! This is most definitely the
|
||||
really last (not latest) version, 4.0.14. Hmm ... 14 looks nicer than 13.
|
||||
|
||||
May 2, 1996
|
||||
|
||||
Still one more release - or actually a small patch - which closes a
|
||||
potential security hole. Now we are at 4.0.15. This IS the FINAL release!
|
||||
|
||||
September 25, 1996
|
331
readme.39e
Normal file
331
readme.39e
Normal file
@ -0,0 +1,331 @@
|
||||
MicroEMACS 3.9 Release Notes July 22, 1987
|
||||
|
||||
**********************************************************************
|
||||
|
||||
(C)opyright 1987 by Daniel M. Lawrence
|
||||
MicroEMACS 3.9 can be copied and distributed freely for any
|
||||
non-commercial purposes. MicroEMACS 3.9 can only be incorporated
|
||||
into commercial software with the permission of the current author.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
MicroEMACS 3.9 is availible in a couple of different ways.
|
||||
First, it is availible via my bulletin board system.....
|
||||
|
||||
The Programmer's Room
|
||||
FIDO 201/2
|
||||
(317) 742-5533
|
||||
24 hours 300/1200 baud
|
||||
|
||||
Also it should be online on the following BBS's:
|
||||
|
||||
The Starship Trooper Fido 201/1 (317) 423-2281 2400
|
||||
|
||||
[These following two are open from 10pm till 5pm
|
||||
and only while Purdue is in session]
|
||||
The NightStaff Fido 201/4 (317) 495-4270 1200
|
||||
The Access Violation Fido 201/5 (317) 495-4270 9600
|
||||
|
||||
There it is arranged as three MSDOS .ARC files, EMACSDOC.ARC
|
||||
which contains the documentation and command files, EMACSSRC.ARC which
|
||||
contains the sources and the UNIX Makefile, and EMACSEXE.EXE which
|
||||
contains the MSDOS executables. Also all the various executables are
|
||||
available individually.
|
||||
|
||||
EMACSDOC.ARC includes the files:
|
||||
|
||||
README This file
|
||||
|
||||
(These four files should be in your path for the standard setup)
|
||||
EMACS.RC Standard startup file
|
||||
NEWPAGE.CMD Shifted Function key Pager
|
||||
PPAGE.CMD Programming page
|
||||
WPAGE.CMD Word processing page
|
||||
BPAGE.CMD Block and box manipulation page
|
||||
|
||||
ME110.RC HP110 startup file
|
||||
ME150.RC HP150 startup file
|
||||
AMIGA.RC AMIGA ".emacsrc" startup file
|
||||
ST520.RC ATARI ST startup file
|
||||
|
||||
EMACS.HLP Online help file
|
||||
EMACS.MSS MicroSCRIBE format of EMACS.TXT
|
||||
EMACS.TXT EMACS BEGINNER'S/REFERENCE MANUAL
|
||||
|
||||
AZMAP.CMD Translate AZTEC .SYM files to .MAP
|
||||
BDATA.CMD BASIC Data statement builder
|
||||
FINDCOM.CMD Find mismatched C comments
|
||||
FUNC.CMD Allow function keys on systems with non (like UNIX)
|
||||
MENU.CMD Sample Menu system
|
||||
MENU1 datafile for menu system
|
||||
SHELL.CMD Sample interactive MSDOS shell
|
||||
TRAND.CMD Generate random numbers and do statistics on them
|
||||
|
||||
EMACSSRC.ARC includes the files:
|
||||
|
||||
ALINE.H Atari ST graphic header file
|
||||
ANSI.C ANSI screen driver
|
||||
BASIC.C basic cursor movement
|
||||
BIND.C key binding commands
|
||||
BUFFER.C buffer manipulation commands
|
||||
CRYPT.C encryption functions
|
||||
DOLOCK file locking stub routines
|
||||
DG10.C Data General 10 screen driver
|
||||
DISPLAY.C main display driver
|
||||
EBIND.H binding list
|
||||
EDEF.H global variable declarations
|
||||
EFUNC.H function name list
|
||||
EPATH.H default path settings
|
||||
ESTRUCT.H configuration and structure definitions
|
||||
EVAL.C expression evaluator
|
||||
EVAR.H EMACS macro variable declarations
|
||||
EXEC.C macro execution functions
|
||||
FILE.C user file functions
|
||||
FILEIO.C low level file I/O driver
|
||||
HP110.C HP110 screen driver
|
||||
HP150.C HP150(A or C) screen driver
|
||||
IBMPC.C IBM-PC CGA and MONOCHROME driver
|
||||
INPUT.C low level user input driver
|
||||
ISEARCH.C incremental search functions
|
||||
LINE.C text line manipulation functions
|
||||
LOCK.C file locking functions
|
||||
MAIN.C argument parsing and command loop
|
||||
RANDOM.C other random user functions
|
||||
REGION.C region cut & paste functions
|
||||
SEARCH.C search and replace functions
|
||||
SPAWN.C OS interface driver
|
||||
ST520.C ATARI ST1040 screen driver
|
||||
TCAP.C Termcap screen driver
|
||||
TERMIO.C low level I/O driver
|
||||
TIPC.C TI-PC screen driver
|
||||
VMSVT.C VMS screen driver
|
||||
VT52.C VT52 screen driver
|
||||
WINDOW.C window manipulation functions
|
||||
WORD.C word manipulation functions
|
||||
Z309.C Zenith 100 PC series terminal driver
|
||||
|
||||
EMACSEXE.ARC includes the files:
|
||||
|
||||
MEIBM.EXE IBM-PC CGA/MONO/EGA version
|
||||
MEANSI.EXE MSDOS ANSI graphics version
|
||||
ME110.EXE HP110 portable version
|
||||
ME150.EXE HP150 version
|
||||
ME309.EXE Zenith 100 PC series version
|
||||
ME520.PRG Atari 520/1040ST version
|
||||
MEAMIGA. Amiga 1000 version
|
||||
|
||||
Recently, MicroSPELL 1.0 has been released. This program allows
|
||||
you to spell check text files and uses MicroEMACS to scan the file,
|
||||
doing various corrections.
|
||||
|
||||
MicroSCRIBE, a fairly SCRIBE compatible text formatter to go
|
||||
along with these programs will probably be available for beta testing
|
||||
early spring 1988. This program is turning out to be a lot more complex
|
||||
than I thought it would be, and is taking more time to get out.
|
||||
|
||||
I have in my possesion a port of MicroEMACS 3.8i to the
|
||||
Macintosh, and I will be incorporating the needed changes for the current
|
||||
version to support the Macintosh.
|
||||
|
||||
As before, I will continue to support these programs, and
|
||||
encourage everyone to spread them around as much as they can. If you
|
||||
make what you think are changes that are useful to many, send me the
|
||||
updates, and as time permits, I will incorporate the ones I understand,
|
||||
and agree with into the master sources.
|
||||
|
||||
MicroEMACS is available on disk directly from my by sending me
|
||||
$25 per order and a note specifying the disk format and the product that
|
||||
you need. I can fill orders for IBM-PC high/low density 5 1/4 and 3
|
||||
1/5, ATARI ST single and double density, AMIGA disks and HP150 disks.
|
||||
(You do not need to send disks or mailers, I will provide these.) The
|
||||
distribution set includes on disk all docs, executables and sources.
|
||||
Also I will register you and you will receive automatic notices of new
|
||||
versions of all the programs I am releasing.
|
||||
|
||||
Commercial lisences to allow MicroEMACS to be incorporated into
|
||||
other software packages are also available at a reasonable per package
|
||||
price. Also I am available to do customization of MicroEMACS at an
|
||||
hourly rate. Send all requests to the address below:
|
||||
|
||||
USmail: Daniel Lawrence
|
||||
617 New York St
|
||||
Lafayette, IN 47901
|
||||
|
||||
UUCP: pur-ee!j.cc.purdue.edu!nwd
|
||||
ARPA: nwd@j.cc.purdue.edu
|
||||
FIDO: The Programmer's Room 201/2
|
||||
(317) 742-5533
|
||||
ATT: (317) 742-5153
|
||||
|
||||
|
||||
New Features since version 3.8i
|
||||
===============================
|
||||
|
||||
** New standard startup file
|
||||
|
||||
The new emacs.rc file is segmented into more parts and loads much
|
||||
faster than before. Separate "pages" of shifted function keys are
|
||||
available. Users can write their own "pages".
|
||||
|
||||
*** New Variables (there are a lot...)
|
||||
|
||||
$status returns status of last command
|
||||
$palette color palette settings
|
||||
$lastkey returns last keystroke
|
||||
$curchar returns and set the ascii number of the
|
||||
character under the point
|
||||
$progname always returns "MicroEMACS"
|
||||
$version always returns the current version ("3.9")
|
||||
$discmd sets display of messages on the command
|
||||
line (except via the write-message command)
|
||||
$disinp sets echoing of characters during input on the
|
||||
command line
|
||||
$wline returns and sets # lines in current window
|
||||
$cwline returns and set current line within window
|
||||
$target returns/sets target for line moves
|
||||
$search returns/sets default search string
|
||||
$replace returns/sets default replace string
|
||||
$match returns last matched string in magic search
|
||||
$cmode returns/sets encoded mode of current buffer
|
||||
$gmode returns/sets encoded global mode (see appendix E
|
||||
in emacs.mss to decode this)
|
||||
$tpause returns/sets the pause for fence matching
|
||||
(this is in rather arbitrary units which
|
||||
WILL vary from machine to machine)
|
||||
$line return/sets the contents of the current line
|
||||
$gflags global operations flag (see emacs.txt Appendix G)
|
||||
$rval child process return value
|
||||
|
||||
*** New computers supported
|
||||
|
||||
Atari 1040ST all three graphics modes and 50 line mode on a
|
||||
monochrome monitor. The mouse is bound to the
|
||||
cursor keys for now.
|
||||
|
||||
*** New Compilers supported
|
||||
|
||||
Turbo C v1.0 under MSDOS is now a supported compiler.
|
||||
Mark Williams C on the Atari ST is also supported.
|
||||
|
||||
** New directives
|
||||
|
||||
!while <condition> loops while <cond> is true
|
||||
|
||||
!break breaks out of the innermost !while
|
||||
|
||||
!endwhile delimits the end of a !while loop
|
||||
|
||||
All !gotos are legal into and out of a !while loop.
|
||||
|
||||
*** Autosave mode
|
||||
|
||||
This mode saves the file out to disk every time 256 have been
|
||||
inserted. $asave controls the # of characters between saves, $acount
|
||||
controls the # of chars to the next save.
|
||||
|
||||
*** New functions
|
||||
|
||||
&and <log> <log> Logical AND
|
||||
&or <log> <log> Logical OR
|
||||
&len <str> returns length of <str>
|
||||
&lower <str> lowercase <str>
|
||||
&upper <str> uppercase <str>
|
||||
&rnd <int> generate a random integer between 1 and <int>
|
||||
&sindex <str1> <str2> search for string 2 within string 1
|
||||
returning its position, or zero if it fails
|
||||
&env <str> return value of DOS environment
|
||||
variable <str>
|
||||
&bind <str> returns the function name bound to the
|
||||
key <str>
|
||||
&exist <str> Does file <str> exist?
|
||||
&find <str> find file <str> along the PATH
|
||||
&band <num> <num> bitwise and
|
||||
&bor <num> <num> bitwise or
|
||||
&bxor <num> <num> bitwise xor
|
||||
&bnot <num> bitwise not
|
||||
&xlate <str1> <str2> <str3>
|
||||
scan <str1> replacing characters in
|
||||
<str2> with the coresponding characters
|
||||
in <str3>
|
||||
|
||||
*** Advanced word processing commands
|
||||
|
||||
^X^T trim-line trim all trailing whitespace
|
||||
^X^E entab-line change all multiple char runs to tabs
|
||||
^X^D detab-line change all tabs to multiple spaces
|
||||
|
||||
*** Merged EGA driver
|
||||
|
||||
The EGA driver is now part of the IBM-PC driver. This driver now
|
||||
supports MONO, CGA and EGA cards/modes. (settable by using the $sres
|
||||
variable)
|
||||
|
||||
*** 8 bit characters fully supported
|
||||
|
||||
Eight bit characters (including foreign language and line
|
||||
drawing characters) are now supported on the various micro environments)
|
||||
|
||||
*** List Buffers expanded
|
||||
|
||||
Given a numeric argument, ^X^B (list-buffers) will now also list
|
||||
all the hidden internal buffers.
|
||||
|
||||
*** -k switch enhanced
|
||||
|
||||
If you use the -k (encrypted file) switch on the command line
|
||||
without a key immediatly following it, it will prompt you for the key to
|
||||
use to decrypt with.
|
||||
|
||||
*** word delete enhanced
|
||||
|
||||
with a zero (0) argument, M-D (delete-next-word) deletes the
|
||||
next word and not any intervening whitespace or special characters.
|
||||
|
||||
*** New File read hook
|
||||
|
||||
Whenever MicroEMACS reads a file from disk, right before it is
|
||||
read, whatever function is bound to M-FNR (which is an illegal
|
||||
keystroke) will execute. By default this would be (nop), but the
|
||||
standard emacs.rc binds this to a file that examines the file name and
|
||||
places the buffer int CMODE if the extension ends in a .c or .h. You can
|
||||
of course redefine this macro to taste.
|
||||
|
||||
*** Search Path modified
|
||||
|
||||
The order in which emacs looks for all .rc (startup) and
|
||||
.cmd (command macros) is as follows:
|
||||
|
||||
$HOME (the HOME environment variable if it exists)
|
||||
the current directory
|
||||
$PATH (executable PATH)
|
||||
default list contained in epath.h
|
||||
|
||||
*** Line length limits removed
|
||||
|
||||
Lines of arbitrary length may be read, edited, and written.
|
||||
|
||||
*** Out of memory handling improved
|
||||
|
||||
EMACS will announce "OUT OF MEMORY" when it runs out of dynamic
|
||||
memory while reading files or inserting new text. It should then be
|
||||
safe to save buffers out IF THE CONTENTS OF THE BUFFER ARE COMPLETE at
|
||||
that time. When a buffer has been truncated while reading, a pound sign
|
||||
"#" will appear in the first position of the mode line. Also a # will
|
||||
appear in a buffer listing. If you attempt to save a truncated buffer,
|
||||
EMACS will ask if you are certain before allowing the truncated file to
|
||||
be written. As before, still beware of killing blocks of text after you
|
||||
have run out of memory.
|
||||
|
||||
*** DENSE mode on the Atari ST
|
||||
|
||||
On an Atari ST monochrome monitor, setting $sres to "DENSE" will
|
||||
result in a 50 line display.
|
||||
|
||||
*** Execute command
|
||||
|
||||
Execute-program (^X-$) will execute an external program without
|
||||
calling up an intervening shell is possible.
|
||||
|
||||
*** Better close braces in CMODE
|
||||
|
||||
The name says it all, try it.
|
212
region.c
Normal file
212
region.c
Normal file
@ -0,0 +1,212 @@
|
||||
/* REGION.C
|
||||
*
|
||||
* The routines in this file
|
||||
* deal with the region, that magic space
|
||||
* between "." and mark. Some functions are
|
||||
* commands. Some functions are just for
|
||||
* internal use.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
/*
|
||||
* Kill the region. Ask "getregion"
|
||||
* to figure out the bounds of the region.
|
||||
* Move "." to the start, and kill the characters.
|
||||
* Bound to "C-W".
|
||||
*/
|
||||
killregion(f, n)
|
||||
{
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
if ((lastflag&CFKILL) == 0) /* This is a kill type */
|
||||
kdelete(); /* command, so do magic */
|
||||
thisflag |= CFKILL; /* kill buffer stuff. */
|
||||
curwp->w_dotp = region.r_linep;
|
||||
curwp->w_doto = region.r_offset;
|
||||
return (ldelete(region.r_size, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy all of the characters in the
|
||||
* region to the kill buffer. Don't move dot
|
||||
* at all. This is a bit like a kill region followed
|
||||
* by a yank. Bound to "M-W".
|
||||
*/
|
||||
copyregion(f, n)
|
||||
{
|
||||
register LINE *linep;
|
||||
register int loffs;
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
if ((lastflag&CFKILL) == 0) /* Kill type command. */
|
||||
kdelete();
|
||||
thisflag |= CFKILL;
|
||||
linep = region.r_linep; /* Current line. */
|
||||
loffs = region.r_offset; /* Current offset. */
|
||||
while (region.r_size--) {
|
||||
if (loffs == llength(linep)) { /* End of line. */
|
||||
if ((s=kinsert('\n')) != TRUE)
|
||||
return (s);
|
||||
linep = lforw(linep);
|
||||
loffs = 0;
|
||||
} else { /* Middle of line. */
|
||||
if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
|
||||
return (s);
|
||||
++loffs;
|
||||
}
|
||||
}
|
||||
mlwrite("(region copied)");
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lower case region. Zap all of the upper
|
||||
* case characters in the region to lower case. Use
|
||||
* the region code to set the limits. Scan the buffer,
|
||||
* doing the changes. Call "lchange" to ensure that
|
||||
* redisplay is done in all buffers. Bound to
|
||||
* "C-X C-L".
|
||||
*/
|
||||
lowerregion(f, n)
|
||||
{
|
||||
register LINE *linep;
|
||||
register int loffs;
|
||||
register int c;
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
lchange(WFHARD);
|
||||
linep = region.r_linep;
|
||||
loffs = region.r_offset;
|
||||
while (region.r_size--) {
|
||||
if (loffs == llength(linep)) {
|
||||
linep = lforw(linep);
|
||||
loffs = 0;
|
||||
} else {
|
||||
c = lgetc(linep, loffs);
|
||||
if (c>='A' && c<='Z')
|
||||
lputc(linep, loffs, c+'a'-'A');
|
||||
++loffs;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upper case region. Zap all of the lower
|
||||
* case characters in the region to upper case. Use
|
||||
* the region code to set the limits. Scan the buffer,
|
||||
* doing the changes. Call "lchange" to ensure that
|
||||
* redisplay is done in all buffers. Bound to
|
||||
* "C-X C-L".
|
||||
*/
|
||||
upperregion(f, n)
|
||||
{
|
||||
register LINE *linep;
|
||||
register int loffs;
|
||||
register int c;
|
||||
register int s;
|
||||
REGION region;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if ((s=getregion(®ion)) != TRUE)
|
||||
return (s);
|
||||
lchange(WFHARD);
|
||||
linep = region.r_linep;
|
||||
loffs = region.r_offset;
|
||||
while (region.r_size--) {
|
||||
if (loffs == llength(linep)) {
|
||||
linep = lforw(linep);
|
||||
loffs = 0;
|
||||
} else {
|
||||
c = lgetc(linep, loffs);
|
||||
if (c>='a' && c<='z')
|
||||
lputc(linep, loffs, c-'a'+'A');
|
||||
++loffs;
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine figures out the
|
||||
* bounds of the region in the current window, and
|
||||
* fills in the fields of the "REGION" structure pointed
|
||||
* to by "rp". Because the dot and mark are usually very
|
||||
* close together, we scan outward from dot looking for
|
||||
* mark. This should save time. Return a standard code.
|
||||
* Callers of this routine should be prepared to get
|
||||
* an "ABORT" status; we might make this have the
|
||||
* conform thing later.
|
||||
*/
|
||||
getregion(rp)
|
||||
register REGION *rp;
|
||||
{
|
||||
register LINE *flp;
|
||||
register LINE *blp;
|
||||
long fsize;
|
||||
long bsize;
|
||||
|
||||
if (curwp->w_markp == NULL) {
|
||||
mlwrite("No mark set in this window");
|
||||
return (FALSE);
|
||||
}
|
||||
if (curwp->w_dotp == curwp->w_markp) {
|
||||
rp->r_linep = curwp->w_dotp;
|
||||
if (curwp->w_doto < curwp->w_marko) {
|
||||
rp->r_offset = curwp->w_doto;
|
||||
rp->r_size = (long)(curwp->w_marko-curwp->w_doto);
|
||||
} else {
|
||||
rp->r_offset = curwp->w_marko;
|
||||
rp->r_size = (long)(curwp->w_doto-curwp->w_marko);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
blp = curwp->w_dotp;
|
||||
bsize = (long)curwp->w_doto;
|
||||
flp = curwp->w_dotp;
|
||||
fsize = (long)(llength(flp)-curwp->w_doto+1);
|
||||
while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
|
||||
if (flp != curbp->b_linep) {
|
||||
flp = lforw(flp);
|
||||
if (flp == curwp->w_markp) {
|
||||
rp->r_linep = curwp->w_dotp;
|
||||
rp->r_offset = curwp->w_doto;
|
||||
rp->r_size = fsize+curwp->w_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
fsize += llength(flp)+1;
|
||||
}
|
||||
if (lback(blp) != curbp->b_linep) {
|
||||
blp = lback(blp);
|
||||
bsize += llength(blp)+1;
|
||||
if (blp == curwp->w_markp) {
|
||||
rp->r_linep = blp;
|
||||
rp->r_offset = curwp->w_marko;
|
||||
rp->r_size = bsize - curwp->w_marko;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
mlwrite("Bug: lost mark");
|
||||
return (FALSE);
|
||||
}
|
||||
|
57
shell.cmd
Normal file
57
shell.cmd
Normal file
@ -0,0 +1,57 @@
|
||||
; OS shell interface, MS-DOS and UNIX
|
||||
|
||||
store-procedure prompt
|
||||
set $discmd FALSE
|
||||
end-of-file
|
||||
insert-string "shell% "
|
||||
set-mark
|
||||
set $discmd TRUE
|
||||
unmark-buffer
|
||||
!endm
|
||||
|
||||
store-procedure getline
|
||||
set $discmd FALSE
|
||||
end-of-file
|
||||
!force backward-character
|
||||
exchange-point-and-mark
|
||||
copy-region
|
||||
set %shline $kill
|
||||
end-of-file
|
||||
set $discmd TRUE
|
||||
!endm
|
||||
|
||||
store-procedure execline
|
||||
; shell-command "echo command not found > shtmp"
|
||||
shell-command &cat %shline " > shtmp"
|
||||
!force insert-file shtmp
|
||||
!endm
|
||||
|
||||
; prompt and execute a command
|
||||
|
||||
10 store-macro
|
||||
run getline
|
||||
!if ¬ &seq %shline ""
|
||||
run execline
|
||||
!endif
|
||||
run prompt
|
||||
!endm
|
||||
|
||||
11 store-macro
|
||||
set $discmd FALSE
|
||||
!if &seq $cbufname "*Shell*"
|
||||
bind-to-key execute-macro-10 ^M
|
||||
run prompt
|
||||
!else
|
||||
bind-to-key newline ^M
|
||||
!endif
|
||||
set $discmd TRUE
|
||||
!endm
|
||||
|
||||
store-procedure openshell
|
||||
set $discmd FALSE
|
||||
bind-to-key execute-macro-11 M-FNX
|
||||
select-buffer "*Shell*"
|
||||
set $discmd TRUE
|
||||
!endm
|
||||
|
||||
run openshell
|
628
spawn.c
Normal file
628
spawn.c
Normal file
@ -0,0 +1,628 @@
|
||||
/* SPAWN.C
|
||||
* various operating system access commands
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if VMS
|
||||
#define EFN 0 /* Event flag. */
|
||||
|
||||
#include <ssdef.h> /* Random headers. */
|
||||
#include <stsdef.h>
|
||||
#include <descrip.h>
|
||||
#include <iodef.h>
|
||||
|
||||
extern int oldmode[3]; /* In "termio.c" */
|
||||
extern int newmode[3]; /* In "termio.c" */
|
||||
extern short iochan; /* In "termio.c" */
|
||||
#endif
|
||||
|
||||
#if V7 | USG | BSD
|
||||
#include <signal.h>
|
||||
extern int vttidy();
|
||||
#ifdef SIGWINCH
|
||||
extern int chg_width, chg_height;
|
||||
extern void sizesignal();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MSDOS & (MSC | TURBO)
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create a subjob with a copy of the command intrepreter in it. When the
|
||||
* command interpreter exits, mark the screen as garbage so that you do a full
|
||||
* repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
|
||||
* Under some (unknown) condition, you don't get one free when DCL starts up.
|
||||
*/
|
||||
spawncli(f, n)
|
||||
{
|
||||
#if V7 | USG | BSD
|
||||
register char *cp;
|
||||
char *getenv();
|
||||
#endif
|
||||
|
||||
/* don't allow this command if restricted */
|
||||
if (restflag)
|
||||
return(resterr());
|
||||
|
||||
#if VMS
|
||||
movecursor(term.t_nrow, 0); /* In last line. */
|
||||
mlputs("(Starting DCL)\r\n");
|
||||
TTflush(); /* Ignore "ttcol". */
|
||||
sgarbf = TRUE;
|
||||
sys(NULL);
|
||||
sleep(1);
|
||||
mlputs("\r\n(Returning from DCL)\r\n");
|
||||
TTflush();
|
||||
sleep(1);
|
||||
return(TRUE);
|
||||
#endif
|
||||
#if MSDOS & (MSC | TURBO)
|
||||
movecursor(term.t_nrow, 0); /* Seek to last line. */
|
||||
TTflush();
|
||||
TTkclose();
|
||||
shellprog("");
|
||||
TTkopen();
|
||||
sgarbf = TRUE;
|
||||
return(TRUE);
|
||||
#endif
|
||||
#if V7 | USG | BSD
|
||||
movecursor(term.t_nrow, 0); /* Seek to last line. */
|
||||
TTflush();
|
||||
TTclose(); /* stty to old settings */
|
||||
if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
|
||||
system(cp);
|
||||
else
|
||||
#if BSD
|
||||
system("exec /bin/csh");
|
||||
#else
|
||||
system("exec /bin/sh");
|
||||
#endif
|
||||
sgarbf = TRUE;
|
||||
sleep(2);
|
||||
TTopen();
|
||||
TTkopen();
|
||||
#ifdef SIGWINCH
|
||||
/*
|
||||
* This fools the update routines to force a full
|
||||
* redraw with complete window size checking.
|
||||
* -lbt
|
||||
*/
|
||||
chg_width = term.t_ncol;
|
||||
chg_height = term.t_nrow+1;
|
||||
term.t_nrow = term.t_ncol = 0;
|
||||
#endif
|
||||
return(TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BSD | __hpux | SVR4
|
||||
|
||||
bktoshell() /* suspend MicroEMACS and wait to wake up */
|
||||
{
|
||||
int pid;
|
||||
|
||||
vttidy();
|
||||
/******************************
|
||||
pid = getpid();
|
||||
kill(pid,SIGTSTP);
|
||||
******************************/
|
||||
kill(0, SIGTSTP);
|
||||
}
|
||||
|
||||
rtfrmshell()
|
||||
{
|
||||
TTopen();
|
||||
curwp->w_flag = WFHARD;
|
||||
sgarbf = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Run a one-liner in a subjob. When the command returns, wait for a single
|
||||
* character to be typed, then mark the screen as garbage so a full repaint is
|
||||
* done. Bound to "C-X !".
|
||||
*/
|
||||
spawn(f, n)
|
||||
{
|
||||
register int s;
|
||||
char line[NLINE];
|
||||
|
||||
/* don't allow this command if restricted */
|
||||
if (restflag)
|
||||
return(resterr());
|
||||
|
||||
#if VMS
|
||||
if ((s=mlreply("!", line, NLINE)) != TRUE)
|
||||
return (s);
|
||||
movecursor(term.t_nrow, 0);
|
||||
TTflush();
|
||||
s = sys(line); /* Run the command. */
|
||||
if (clexec == FALSE) {
|
||||
mlputs("\r\n\n(End)"); /* Pause. */
|
||||
TTflush();
|
||||
tgetc();
|
||||
}
|
||||
sgarbf = TRUE;
|
||||
return (s);
|
||||
#endif
|
||||
#if MSDOS
|
||||
if ((s=mlreply("!", line, NLINE)) != TRUE)
|
||||
return(s);
|
||||
movecursor(term.t_nrow, 0);
|
||||
TTkclose();
|
||||
shellprog(line);
|
||||
TTkopen();
|
||||
/* if we are interactive, pause here */
|
||||
if (clexec == FALSE) {
|
||||
mlputs("\r\n(End)");
|
||||
tgetc();
|
||||
}
|
||||
sgarbf = TRUE;
|
||||
return (TRUE);
|
||||
#endif
|
||||
#if V7 | USG | BSD
|
||||
if ((s=mlreply("!", line, NLINE)) != TRUE)
|
||||
return (s);
|
||||
TTflush();
|
||||
TTclose(); /* stty to old modes */
|
||||
TTkclose();
|
||||
system(line);
|
||||
fflush(stdout); /* to be sure P.K. */
|
||||
TTopen();
|
||||
|
||||
if (clexec == FALSE) {
|
||||
mlputs("(End)"); /* Pause. */
|
||||
TTflush();
|
||||
while ((s = tgetc()) != '\r' && s != ' ')
|
||||
;
|
||||
mlputs("\r\n");
|
||||
}
|
||||
TTkopen();
|
||||
sgarbf = TRUE;
|
||||
return (TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Run an external program with arguments. When it returns, wait for a single
|
||||
* character to be typed, then mark the screen as garbage so a full repaint is
|
||||
* done. Bound to "C-X $".
|
||||
*/
|
||||
|
||||
execprg(f, n)
|
||||
|
||||
{
|
||||
register int s;
|
||||
char line[NLINE];
|
||||
|
||||
/* don't allow this command if restricted */
|
||||
if (restflag)
|
||||
return(resterr());
|
||||
|
||||
#if VMS
|
||||
if ((s=mlreply("!", line, NLINE)) != TRUE)
|
||||
return (s);
|
||||
TTflush();
|
||||
s = sys(line); /* Run the command. */
|
||||
mlputs("\r\n\n(End)"); /* Pause. */
|
||||
TTflush();
|
||||
tgetc();
|
||||
sgarbf = TRUE;
|
||||
return (s);
|
||||
#endif
|
||||
|
||||
#if MSDOS
|
||||
if ((s=mlreply("$", line, NLINE)) != TRUE)
|
||||
return(s);
|
||||
movecursor(term.t_nrow, 0);
|
||||
TTkclose();
|
||||
execprog(line);
|
||||
TTkopen();
|
||||
/* if we are interactive, pause here */
|
||||
if (clexec == FALSE) {
|
||||
mlputs("\r\n(End)");
|
||||
tgetc();
|
||||
}
|
||||
sgarbf = TRUE;
|
||||
return (TRUE);
|
||||
#endif
|
||||
|
||||
#if V7 | USG | BSD
|
||||
if ((s=mlreply("!", line, NLINE)) != TRUE)
|
||||
return (s);
|
||||
TTputc('\n'); /* Already have '\r' */
|
||||
TTflush();
|
||||
TTclose(); /* stty to old modes */
|
||||
system(line);
|
||||
fflush(stdout); /* to be sure P.K. */
|
||||
TTopen();
|
||||
mlputs("(End)"); /* Pause. */
|
||||
TTflush();
|
||||
while ((s = tgetc()) != '\r' && s != ' ')
|
||||
;
|
||||
sgarbf = TRUE;
|
||||
return (TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Pipe a one line command into a window
|
||||
* Bound to ^X @
|
||||
*/
|
||||
pipecmd(f, n)
|
||||
{
|
||||
register int s; /* return status from CLI */
|
||||
register WINDOW *wp; /* pointer to new window */
|
||||
register BUFFER *bp; /* pointer to buffer to zot */
|
||||
char line[NLINE]; /* command line send to shell */
|
||||
static char bname[] = "command";
|
||||
|
||||
static char filnam[NSTRING] = "command";
|
||||
|
||||
#if MSDOS
|
||||
char *tmp;
|
||||
char *getenv();
|
||||
FILE *fp;
|
||||
FILE *fopen();
|
||||
int len;
|
||||
#endif
|
||||
|
||||
/* don't allow this command if restricted */
|
||||
if (restflag)
|
||||
return(resterr());
|
||||
|
||||
#if MSDOS
|
||||
if ((tmp = getenv("TMP")) == NULL && (tmp = getenv("TEMP")) == NULL)
|
||||
strcpy(filnam, "command");
|
||||
else {
|
||||
strcpy(filnam, tmp);
|
||||
len = strlen(tmp);
|
||||
if (len <= 0 || filnam[len-1] != '\\' && filnam[len-1] != '/')
|
||||
strcat(filnam,"\\");
|
||||
strcat(filnam,"command");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VMS
|
||||
mlwrite("Not available under VMS");
|
||||
return(FALSE);
|
||||
#endif
|
||||
|
||||
/* get the command to pipe in */
|
||||
if ((s=mlreply("@", line, NLINE)) != TRUE)
|
||||
return(s);
|
||||
|
||||
/* get rid of the command output buffer if it exists */
|
||||
if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
|
||||
/* try to make sure we are off screen */
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_bufp == bp) {
|
||||
#if PKCODE
|
||||
if (wp == curwp)
|
||||
delwind(FALSE, 1);
|
||||
else
|
||||
onlywind(FALSE, 1);
|
||||
break;
|
||||
#else
|
||||
onlywind(FALSE, 1);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
if (zotbuf(bp) != TRUE)
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#if MSDOS
|
||||
strcat(line," >>");
|
||||
strcat(line,filnam);
|
||||
movecursor(term.t_nrow, 0);
|
||||
TTkclose();
|
||||
shellprog(line);
|
||||
TTkopen();
|
||||
sgarbf = TRUE;
|
||||
if ((fp = fopen(filnam, "r")) == NULL) {
|
||||
s = FALSE;
|
||||
} else {
|
||||
fclose(fp);
|
||||
s = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if V7 | USG | BSD
|
||||
TTflush();
|
||||
TTclose(); /* stty to old modes */
|
||||
strcat(line,">");
|
||||
strcat(line,filnam);
|
||||
system(line);
|
||||
TTopen();
|
||||
TTflush();
|
||||
sgarbf = TRUE;
|
||||
s = TRUE;
|
||||
#endif
|
||||
|
||||
if (s != TRUE)
|
||||
return(s);
|
||||
|
||||
/* split the current window to make room for the command output */
|
||||
if (splitwind(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
|
||||
/* and read the stuff in */
|
||||
if (getfile(filnam, FALSE) == FALSE)
|
||||
return(FALSE);
|
||||
|
||||
/* make this window in VIEW mode, update all mode lines */
|
||||
curwp->w_bufp->b_mode |= MDVIEW;
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
wp->w_flag |= WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
|
||||
/* and get rid of the temporary file */
|
||||
unlink(filnam);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* filter a buffer through an external DOS program
|
||||
* Bound to ^X #
|
||||
*/
|
||||
filter(f, n)
|
||||
|
||||
{
|
||||
register int s; /* return status from CLI */
|
||||
register BUFFER *bp; /* pointer to buffer to zot */
|
||||
char line[NLINE]; /* command line send to shell */
|
||||
char tmpnam[NFILEN]; /* place to store real file name */
|
||||
static char bname1[] = "fltinp";
|
||||
|
||||
static char filnam1[] = "fltinp";
|
||||
static char filnam2[] = "fltout";
|
||||
|
||||
/* don't allow this command if restricted */
|
||||
if (restflag)
|
||||
return(resterr());
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
|
||||
#if VMS
|
||||
mlwrite("Not available under VMS");
|
||||
return(FALSE);
|
||||
#endif
|
||||
|
||||
/* get the filter name and its args */
|
||||
if ((s=mlreply("#", line, NLINE)) != TRUE)
|
||||
return(s);
|
||||
|
||||
/* setup the proper file names */
|
||||
bp = curbp;
|
||||
strcpy(tmpnam, bp->b_fname); /* save the original name */
|
||||
strcpy(bp->b_fname, bname1); /* set it to our new one */
|
||||
|
||||
/* write it out, checking for errors */
|
||||
if (writeout(filnam1) != TRUE) {
|
||||
mlwrite("(Cannot write filter file)");
|
||||
strcpy(bp->b_fname, tmpnam);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#if MSDOS
|
||||
strcat(line," <fltinp >fltout");
|
||||
movecursor(term.t_nrow - 1, 0);
|
||||
TTkclose();
|
||||
shellprog(line);
|
||||
TTkopen();
|
||||
sgarbf = TRUE;
|
||||
s = TRUE;
|
||||
#endif
|
||||
|
||||
#if V7 | USG | BSD
|
||||
TTputc('\n'); /* Already have '\r' */
|
||||
TTflush();
|
||||
TTclose(); /* stty to old modes */
|
||||
strcat(line," <fltinp >fltout");
|
||||
system(line);
|
||||
TTopen();
|
||||
TTflush();
|
||||
sgarbf = TRUE;
|
||||
s = TRUE;
|
||||
#endif
|
||||
|
||||
/* on failure, escape gracefully */
|
||||
if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
|
||||
mlwrite("(Execution failed)");
|
||||
strcpy(bp->b_fname, tmpnam);
|
||||
unlink(filnam1);
|
||||
unlink(filnam2);
|
||||
return(s);
|
||||
}
|
||||
|
||||
/* reset file name */
|
||||
strcpy(bp->b_fname, tmpnam); /* restore name */
|
||||
bp->b_flag |= BFCHG; /* flag it as changed */
|
||||
|
||||
/* and get rid of the temporary file */
|
||||
unlink(filnam1);
|
||||
unlink(filnam2);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
#if VMS
|
||||
/*
|
||||
* Run a command. The "cmd" is a pointer to a command string, or NULL if you
|
||||
* want to run a copy of DCL in the subjob (this is how the standard routine
|
||||
* LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
|
||||
* and the way out, because DCL does not want the channel to be in raw mode.
|
||||
*/
|
||||
sys(cmd)
|
||||
register char *cmd;
|
||||
{
|
||||
struct dsc$descriptor cdsc;
|
||||
struct dsc$descriptor *cdscp;
|
||||
long status;
|
||||
long substatus;
|
||||
long iosb[2];
|
||||
|
||||
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
|
||||
oldmode, sizeof(oldmode), 0, 0, 0, 0);
|
||||
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
|
||||
return (FALSE);
|
||||
cdscp = NULL; /* Assume DCL. */
|
||||
if (cmd != NULL) { /* Build descriptor. */
|
||||
cdsc.dsc$a_pointer = cmd;
|
||||
cdsc.dsc$w_length = strlen(cmd);
|
||||
cdsc.dsc$b_dtype = DSC$K_DTYPE_T;
|
||||
cdsc.dsc$b_class = DSC$K_CLASS_S;
|
||||
cdscp = &cdsc;
|
||||
}
|
||||
status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
|
||||
if (status != SS$_NORMAL)
|
||||
substatus = status;
|
||||
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
|
||||
newmode, sizeof(newmode), 0, 0, 0, 0);
|
||||
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
|
||||
return (FALSE);
|
||||
if ((substatus&STS$M_SUCCESS) == 0) /* Command failed. */
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MSDOS & (TURBO | MSC)
|
||||
|
||||
/* SHELLPROG: Execute a command in a subshell */
|
||||
|
||||
shellprog(cmd)
|
||||
|
||||
char *cmd; /* Incoming command line to execute */
|
||||
|
||||
{
|
||||
char *shell; /* Name of system command processor */
|
||||
char *p; /* Temporary pointer */
|
||||
char swchar; /* switch character to use */
|
||||
union REGS regs; /* parameters for dos call */
|
||||
char comline[NSTRING]; /* constructed command line */
|
||||
char *getenv();
|
||||
|
||||
/* detect current switch character and set us up to use it */
|
||||
regs.h.ah = 0x37; /* get setting data */
|
||||
regs.h.al = 0x00; /* get switch character */
|
||||
intdos(®s, ®s);
|
||||
swchar = (char)regs.h.dl;
|
||||
|
||||
/* get name of system shell */
|
||||
if ((shell = getenv("COMSPEC")) == NULL) {
|
||||
return(FALSE); /* No shell located */
|
||||
}
|
||||
|
||||
/* trim leading whitespace off the command */
|
||||
while (*cmd == ' ' || *cmd == '\t') /* find out if null command */
|
||||
cmd++;
|
||||
|
||||
/** If the command line is not empty, bring up the shell **/
|
||||
/** and execute the command. Otherwise, bring up the **/
|
||||
/** shell in interactive mode. **/
|
||||
|
||||
if (*cmd) {
|
||||
strcpy(comline, shell);
|
||||
strcat(comline, " ");
|
||||
comline[strlen(comline) + 1] = 0;
|
||||
comline[strlen(comline)] = swchar;
|
||||
strcat(comline, "c ");
|
||||
strcat(comline, cmd);
|
||||
return(execprog(comline));
|
||||
} else
|
||||
return(execprog(shell));
|
||||
}
|
||||
|
||||
/* EXECPROG: A function to execute a named program
|
||||
with arguments
|
||||
*/
|
||||
|
||||
execprog(cmd)
|
||||
|
||||
char *cmd; /* Incoming command line to execute */
|
||||
|
||||
{
|
||||
char *sp; /* temporary string pointer */
|
||||
char f1[38]; /* FCB1 area (not initialized */
|
||||
char f2[38]; /* FCB2 area (not initialized */
|
||||
char prog[NSTRING]; /* program filespec */
|
||||
char tail[NSTRING]; /* command tail with length byte */
|
||||
union REGS regs; /* parameters for dos call */
|
||||
struct SREGS segreg; /* segment registers for dis call */
|
||||
struct pblock { /* EXEC parameter block */
|
||||
short envptr; /* 2 byte pointer to environment string */
|
||||
char *cline; /* 4 byte pointer to command line */
|
||||
char *fcb1; /* 4 byte pointer to FCB at PSP+5Ch */
|
||||
char *fcb2; /* 4 byte pointer to FCB at PSP+6Ch */
|
||||
} pblock;
|
||||
char *flook();
|
||||
|
||||
/* parse the command name from the command line */
|
||||
sp = prog;
|
||||
while (*cmd && (*cmd != ' ') && (*cmd != '\t'))
|
||||
*sp++ = *cmd++;
|
||||
*sp = 0;
|
||||
|
||||
/* and parse out the command tail */
|
||||
while (*cmd && ((*cmd == ' ') || (*cmd == '\t')))
|
||||
++cmd;
|
||||
*tail = (char)(strlen(cmd)); /* record the byte length */
|
||||
strcpy(&tail[1], cmd);
|
||||
strcat(&tail[1], "\r");
|
||||
|
||||
/* look up the program on the path trying various extentions */
|
||||
if ((sp = flook(prog, TRUE)) == NULL)
|
||||
if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) {
|
||||
strcpy(&prog[strlen(prog)-4], ".com");
|
||||
if ((sp = flook(prog, TRUE)) == NULL)
|
||||
return(FALSE);
|
||||
}
|
||||
strcpy(prog, sp);
|
||||
|
||||
/* get a pointer to this PSPs environment segment number */
|
||||
segread(&segreg);
|
||||
|
||||
/* set up the EXEC parameter block */
|
||||
pblock.envptr = 0; /* make the child inherit the parents env */
|
||||
pblock.fcb1 = f1; /* point to a blank FCB */
|
||||
pblock.fcb2 = f2; /* point to a blank FCB */
|
||||
pblock.cline = tail; /* parameter line pointer */
|
||||
|
||||
/* and make the call */
|
||||
regs.h.ah = 0x4b; /* EXEC Load or Execute a Program */
|
||||
regs.h.al = 0x00; /* load end execute function subcode */
|
||||
segreg.ds = ((unsigned long)(prog) >> 16); /* program name ptr */
|
||||
regs.x.dx = (unsigned int)(prog);
|
||||
segreg.es = ((unsigned long)(&pblock) >> 16); /* set up param block ptr */
|
||||
regs.x.bx = (unsigned int)(&pblock);
|
||||
#if TURBO | MSC
|
||||
intdosx(®s, ®s, &segreg);
|
||||
if (regs.x.cflag == 0) {
|
||||
regs.h.ah = 0x4d; /* get child process return code */
|
||||
intdos(®s, ®s); /* go do it */
|
||||
rval = regs.x.ax; /* save child's return code */
|
||||
} else
|
||||
#if MSC
|
||||
rval = -1;
|
||||
#else
|
||||
rval = -_doserrno; /* failed child call */
|
||||
#endif
|
||||
#endif
|
||||
return((rval < 0) ? FALSE : TRUE);
|
||||
}
|
||||
#endif
|
386
tcap.c
Normal file
386
tcap.c
Normal file
@ -0,0 +1,386 @@
|
||||
/* TCAP.C
|
||||
*
|
||||
* Unix V7 SysV and BS4 Termcap video driver
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
/*
|
||||
* defining this to 1 breaks tcapopen() - it doesn't check if the
|
||||
* sceen size has changed.
|
||||
* -lbt
|
||||
*/
|
||||
#define USE_BROKEN_OPTIMIZATION 0
|
||||
#define termdef 1 /* don't define "term" external */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if TERMCAP
|
||||
|
||||
#if UNIX
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#define MARGIN 8
|
||||
#define SCRSIZ 64
|
||||
#define NPAUSE 10 /* # times thru update to pause */
|
||||
#define BEL 0x07
|
||||
#define ESC 0x1B
|
||||
|
||||
extern int ttopen();
|
||||
extern int ttgetc();
|
||||
extern int ttputc();
|
||||
extern int tgetnum();
|
||||
extern int ttflush();
|
||||
extern int ttclose();
|
||||
extern int tcapkopen();
|
||||
extern int tcapkclose();
|
||||
extern int tcapmove();
|
||||
extern int tcapeeol();
|
||||
extern int tcapeeop();
|
||||
extern int tcapbeep();
|
||||
extern int tcaprev();
|
||||
extern int tcapcres();
|
||||
extern int tcapopen();
|
||||
#if PKCODE
|
||||
extern int tcapclose();
|
||||
#endif
|
||||
extern int tput();
|
||||
extern char *tgoto();
|
||||
#if COLOR
|
||||
extern int tcapfcol();
|
||||
extern int tcapbcol();
|
||||
#endif
|
||||
#if SCROLLCODE
|
||||
extern int tcapscroll_reg();
|
||||
extern int tcapscroll_delins();
|
||||
#endif
|
||||
|
||||
|
||||
#define TCAPSLEN 315
|
||||
char tcapbuf[TCAPSLEN];
|
||||
char *UP, PC, *CM, *CE, *CL, *SO, *SE;
|
||||
|
||||
#if PKCODE
|
||||
char *TI, *TE;
|
||||
int term_init_ok = 0;
|
||||
#endif
|
||||
|
||||
#if SCROLLCODE
|
||||
char *CS, *DL, *AL, *SF, *SR;
|
||||
#endif
|
||||
|
||||
TERM term = {
|
||||
0, /* these four values are set dynamically at open time */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
MARGIN,
|
||||
SCRSIZ,
|
||||
NPAUSE,
|
||||
tcapopen,
|
||||
#if PKCODE
|
||||
tcapclose,
|
||||
#else
|
||||
ttclose,
|
||||
#endif
|
||||
tcapkopen,
|
||||
tcapkclose,
|
||||
ttgetc,
|
||||
ttputc,
|
||||
ttflush,
|
||||
tcapmove,
|
||||
tcapeeol,
|
||||
tcapeeop,
|
||||
tcapbeep,
|
||||
tcaprev,
|
||||
tcapcres
|
||||
#if COLOR
|
||||
, tcapfcol,
|
||||
tcapbcol
|
||||
#endif
|
||||
#if SCROLLCODE
|
||||
, NULL /* set dynamically at open time */
|
||||
#endif
|
||||
};
|
||||
|
||||
tcapopen()
|
||||
|
||||
{
|
||||
char *getenv();
|
||||
char *t, *p, *tgetstr();
|
||||
char tcbuf[1024];
|
||||
char *tv_stype;
|
||||
char err_str[72];
|
||||
int int_col, int_row;
|
||||
|
||||
#if PKCODE && USE_BROKEN_OPTIMIZATION
|
||||
if (! term_init_ok)
|
||||
{
|
||||
#endif
|
||||
if ((tv_stype = getenv("TERM")) == NULL)
|
||||
{
|
||||
puts("Environment variable TERM not defined!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((tgetent(tcbuf, tv_stype)) != 1)
|
||||
{
|
||||
sprintf(err_str, "Unknown terminal type %s!", tv_stype);
|
||||
puts(err_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Get screen size from system, or else from termcap. */
|
||||
getscreensize(&int_col, &int_row);
|
||||
term.t_nrow = int_row-1;
|
||||
term.t_ncol = int_col;
|
||||
|
||||
if ((term.t_nrow <= 0) && (term.t_nrow=(short)tgetnum("li")-1) == -1){
|
||||
puts("termcap entry incomplete (lines)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((term.t_ncol <= 0) && (term.t_ncol=(short)tgetnum("co")) == -1){
|
||||
puts("Termcap entry incomplete (columns)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef SIGWINCH
|
||||
term.t_mrow = MAXROW;
|
||||
term.t_mcol = MAXCOL;
|
||||
#else
|
||||
term.t_mrow = term.t_nrow > MAXROW ? MAXROW : term.t_nrow;
|
||||
term.t_mcol = term.t_ncol > MAXCOL ? MAXCOL : term.t_ncol;
|
||||
#endif
|
||||
p = tcapbuf;
|
||||
t = tgetstr("pc", &p);
|
||||
if(t)
|
||||
PC = *t;
|
||||
else
|
||||
PC = 0;
|
||||
|
||||
CL = tgetstr("cl", &p);
|
||||
CM = tgetstr("cm", &p);
|
||||
CE = tgetstr("ce", &p);
|
||||
UP = tgetstr("up", &p);
|
||||
SE = tgetstr("se", &p);
|
||||
SO = tgetstr("so", &p);
|
||||
if (SO != NULL)
|
||||
revexist = TRUE;
|
||||
#if PKCODE
|
||||
if (tgetnum("sg") > 0) { /* can reverse be used? P.K. */
|
||||
revexist = FALSE;
|
||||
SE = NULL;
|
||||
SO = NULL;
|
||||
}
|
||||
TI = tgetstr("ti", &p); /* terminal init and exit */
|
||||
TE = tgetstr("te", &p);
|
||||
#endif
|
||||
|
||||
if(CL == NULL || CM == NULL || UP == NULL)
|
||||
{
|
||||
puts("Incomplete termcap entry\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (CE == NULL) /* will we be able to use clear to EOL? */
|
||||
eolexist = FALSE;
|
||||
#if SCROLLCODE
|
||||
CS = tgetstr("cs", &p);
|
||||
SF = tgetstr("sf", &p);
|
||||
SR = tgetstr("sr", &p);
|
||||
DL = tgetstr("dl", &p);
|
||||
AL = tgetstr("al", &p);
|
||||
|
||||
if (CS && SR) {
|
||||
if (SF == NULL) /* assume '\n' scrolls forward */
|
||||
SF = "\n";
|
||||
term.t_scroll = tcapscroll_reg;
|
||||
} else if (DL && AL) {
|
||||
term.t_scroll = tcapscroll_delins;
|
||||
} else {
|
||||
term.t_scroll = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p >= &tcapbuf[TCAPSLEN])
|
||||
{
|
||||
puts("Terminal description too big!\n");
|
||||
exit(1);
|
||||
}
|
||||
#if PKCODE && USE_BROKEN_OPTIMIZATION
|
||||
term_init_ok = 1;
|
||||
}
|
||||
#endif
|
||||
ttopen();
|
||||
}
|
||||
|
||||
#if PKCODE
|
||||
|
||||
tcapclose()
|
||||
|
||||
{
|
||||
putpad(tgoto(CM, 0, term.t_nrow));
|
||||
putpad(TE);
|
||||
ttflush();
|
||||
ttclose();
|
||||
}
|
||||
#endif
|
||||
|
||||
tcapkopen()
|
||||
|
||||
{
|
||||
#if PKCODE
|
||||
putpad(TI);
|
||||
ttflush();
|
||||
#endif
|
||||
strcpy(sres, "NORMAL");
|
||||
}
|
||||
|
||||
tcapkclose()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
tcapmove(row, col)
|
||||
register int row, col;
|
||||
{
|
||||
putpad(tgoto(CM, col, row));
|
||||
}
|
||||
|
||||
tcapeeol()
|
||||
{
|
||||
putpad(CE);
|
||||
}
|
||||
|
||||
tcapeeop()
|
||||
{
|
||||
putpad(CL);
|
||||
}
|
||||
|
||||
tcaprev(state) /* change reverse video status */
|
||||
|
||||
int state; /* FALSE = normal video, TRUE = reverse video */
|
||||
|
||||
{
|
||||
static int revstate = FALSE;
|
||||
if (state) {
|
||||
if (SO != NULL)
|
||||
putpad(SO);
|
||||
} else
|
||||
if (SE != NULL)
|
||||
putpad(SE);
|
||||
}
|
||||
|
||||
tcapcres() /* change screen resolution */
|
||||
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
#if SCROLLCODE
|
||||
|
||||
/* move howmanylines lines starting at from to to */
|
||||
tcapscroll_reg(from,to,howmanylines)
|
||||
{
|
||||
int i;
|
||||
if (to == from) return;
|
||||
if (to < from) {
|
||||
tcapscrollregion(to, from + howmanylines - 1);
|
||||
tcapmove(from + howmanylines - 1,0);
|
||||
for (i = from - to; i > 0; i--)
|
||||
putpad(SF);
|
||||
} else { /* from < to */
|
||||
tcapscrollregion(from, to + howmanylines - 1);
|
||||
tcapmove(from,0);
|
||||
for (i = to - from; i > 0; i--)
|
||||
putpad(SR);
|
||||
}
|
||||
tcapscrollregion(0, term.t_nrow);
|
||||
}
|
||||
|
||||
/* move howmanylines lines starting at from to to */
|
||||
tcapscroll_delins(from,to,howmanylines)
|
||||
{
|
||||
int i;
|
||||
if (to == from) return;
|
||||
if (to < from) {
|
||||
tcapmove(to,0);
|
||||
for (i = from - to; i > 0; i--)
|
||||
putpad(DL);
|
||||
tcapmove(to+howmanylines,0);
|
||||
for (i = from - to; i > 0; i--)
|
||||
putpad(AL);
|
||||
} else {
|
||||
tcapmove(from+howmanylines,0);
|
||||
for (i = to - from; i > 0; i--)
|
||||
putpad(DL);
|
||||
tcapmove(from,0);
|
||||
for (i = to - from; i > 0; i--)
|
||||
putpad(AL);
|
||||
}
|
||||
}
|
||||
|
||||
/* cs is set up just like cm, so we use tgoto... */
|
||||
tcapscrollregion(top,bot)
|
||||
{
|
||||
ttputc(PC);
|
||||
putpad(tgoto(CS, bot, top));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
spal(dummy) /* change palette string */
|
||||
|
||||
{
|
||||
/* Does nothing here */
|
||||
}
|
||||
|
||||
#if COLOR
|
||||
tcapfcol() /* no colors here, ignore this */
|
||||
{
|
||||
}
|
||||
|
||||
tcapbcol() /* no colors here, ignore this */
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
tcapbeep()
|
||||
{
|
||||
ttputc(BEL);
|
||||
}
|
||||
|
||||
putpad(str)
|
||||
char *str;
|
||||
{
|
||||
tputs(str, 1, ttputc);
|
||||
}
|
||||
|
||||
putnpad(str, n)
|
||||
char *str;
|
||||
{
|
||||
tputs(str, n, ttputc);
|
||||
}
|
||||
|
||||
|
||||
#if FNLABEL
|
||||
fnclabel(f, n) /* label a function key */
|
||||
|
||||
int f,n; /* default flag, numeric argument [unused] */
|
||||
|
||||
{
|
||||
/* on machines with no function keys...don't bother */
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
|
||||
hello()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
451
termio.c
Normal file
451
termio.c
Normal file
@ -0,0 +1,451 @@
|
||||
|
||||
/* TERMIO.C
|
||||
*
|
||||
* The functions in this file negotiate with the operating system for
|
||||
* characters, and write characters in a barely buffered fashion on the display.
|
||||
* All operating systems.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#ifndef POSIX
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if VMS
|
||||
#include <stsdef.h>
|
||||
#include <ssdef.h>
|
||||
#include <descrip.h>
|
||||
#include <iodef.h>
|
||||
#include <ttdef.h>
|
||||
#include <tt2def.h>
|
||||
|
||||
#define NIBUF 128 /* Input buffer size */
|
||||
#define NOBUF 1024 /* MM says bug buffers win! */
|
||||
#define EFN 0 /* Event flag */
|
||||
|
||||
char obuf[NOBUF]; /* Output buffer */
|
||||
int nobuf; /* # of bytes in above */
|
||||
char ibuf[NIBUF]; /* Input buffer */
|
||||
int nibuf; /* # of bytes in above */
|
||||
int ibufi; /* Read index */
|
||||
int oldmode[3]; /* Old TTY mode bits */
|
||||
int newmode[3]; /* New TTY mode bits */
|
||||
short iochan; /* TTY I/O channel */
|
||||
#endif
|
||||
|
||||
#if MSDOS & (MSC | TURBO)
|
||||
union REGS rg; /* cpu register for use of DOS calls */
|
||||
int nxtchar = -1; /* character held from type ahead */
|
||||
#endif
|
||||
|
||||
#if USG /* System V */
|
||||
#include <signal.h>
|
||||
#include <termio.h>
|
||||
#include <fcntl.h>
|
||||
int kbdflgs; /* saved keyboard fd flags */
|
||||
int kbdpoll; /* in O_NDELAY mode */
|
||||
int kbdqp; /* there is a char in kbdq */
|
||||
char kbdq; /* char we've already read */
|
||||
struct termio otermio; /* original terminal characteristics */
|
||||
struct termio ntermio; /* charactoristics to use inside */
|
||||
#if XONXOFF
|
||||
#define XXMASK 0016000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if V7 | BSD
|
||||
#include <sgtty.h> /* for stty/gtty functions */
|
||||
#include <signal.h>
|
||||
struct sgttyb ostate; /* saved tty state */
|
||||
struct sgttyb nstate; /* values for editor mode */
|
||||
struct tchars otchars; /* Saved terminal special character set */
|
||||
#if XONXOFF
|
||||
struct tchars ntchars = { 0xff, 0xff, 0x11, 0x13, 0xff, 0xff };
|
||||
/* A lot of nothing and XON/XOFF */
|
||||
#else
|
||||
struct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
/* A lot of nothing */
|
||||
#endif
|
||||
#if BSD & PKCODE
|
||||
struct ltchars oltchars; /* Saved terminal local special character set */
|
||||
struct ltchars nltchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
/* A lot of nothing */
|
||||
#endif
|
||||
|
||||
#if BSD
|
||||
#include <sys/ioctl.h> /* to get at the typeahead */
|
||||
extern int rtfrmshell(); /* return from suspended shell */
|
||||
#define TBUFSIZ 128
|
||||
char tobuf[TBUFSIZ]; /* terminal output buffer */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __hpux | SVR4
|
||||
extern int rtfrmshell(); /* return from suspended shell */
|
||||
#define TBUFSIZ 128
|
||||
char tobuf[TBUFSIZ]; /* terminal output buffer */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is called once to set up the terminal device streams.
|
||||
* On VMS, it translates TT until it finds the terminal, then assigns
|
||||
* a channel to it and sets it raw. On CPM it is a no-op.
|
||||
*/
|
||||
ttopen()
|
||||
{
|
||||
#if VMS
|
||||
struct dsc$descriptor idsc;
|
||||
struct dsc$descriptor odsc;
|
||||
char oname[40];
|
||||
int iosb[2];
|
||||
int status;
|
||||
|
||||
odsc.dsc$a_pointer = "TT";
|
||||
odsc.dsc$w_length = strlen(odsc.dsc$a_pointer);
|
||||
odsc.dsc$b_dtype = DSC$K_DTYPE_T;
|
||||
odsc.dsc$b_class = DSC$K_CLASS_S;
|
||||
idsc.dsc$b_dtype = DSC$K_DTYPE_T;
|
||||
idsc.dsc$b_class = DSC$K_CLASS_S;
|
||||
do {
|
||||
idsc.dsc$a_pointer = odsc.dsc$a_pointer;
|
||||
idsc.dsc$w_length = odsc.dsc$w_length;
|
||||
odsc.dsc$a_pointer = &oname[0];
|
||||
odsc.dsc$w_length = sizeof(oname);
|
||||
status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
|
||||
if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
|
||||
exit(status);
|
||||
if (oname[0] == 0x1B) {
|
||||
odsc.dsc$a_pointer += 4;
|
||||
odsc.dsc$w_length -= 4;
|
||||
}
|
||||
} while (status == SS$_NORMAL);
|
||||
status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
|
||||
if (status != SS$_NORMAL)
|
||||
exit(status);
|
||||
status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
|
||||
oldmode, sizeof(oldmode), 0, 0, 0, 0);
|
||||
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
|
||||
exit(status);
|
||||
newmode[0] = oldmode[0];
|
||||
newmode[1] = oldmode[1] | TT$M_NOECHO;
|
||||
#if XONXOFF
|
||||
#else
|
||||
newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
|
||||
#endif
|
||||
newmode[2] = oldmode[2] | TT2$M_PASTHRU;
|
||||
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
|
||||
newmode, sizeof(newmode), 0, 0, 0, 0);
|
||||
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
|
||||
exit(status);
|
||||
term.t_nrow = (newmode[1]>>24) - 1;
|
||||
term.t_ncol = newmode[0]>>16;
|
||||
|
||||
#endif
|
||||
|
||||
#if MSDOS & (TURBO | (PKCODE & MSC))
|
||||
/* kill the CONTROL-break interupt */
|
||||
rg.h.ah = 0x33; /* control-break check dos call */
|
||||
rg.h.al = 1; /* set the current state */
|
||||
rg.h.dl = 0; /* set it OFF */
|
||||
intdos(&rg, &rg); /* go for it! */
|
||||
#endif
|
||||
|
||||
#if USG
|
||||
ioctl(0, TCGETA, &otermio); /* save old settings */
|
||||
ntermio.c_iflag = 0; /* setup new settings */
|
||||
#if XONXOFF
|
||||
ntermio.c_iflag = otermio.c_iflag & XXMASK; /* save XON/XOFF P.K. */
|
||||
#endif
|
||||
ntermio.c_oflag = 0;
|
||||
ntermio.c_cflag = otermio.c_cflag;
|
||||
ntermio.c_lflag = 0;
|
||||
ntermio.c_line = otermio.c_line;
|
||||
ntermio.c_cc[VMIN] = 1;
|
||||
ntermio.c_cc[VTIME] = 0;
|
||||
#if PKCODE
|
||||
ioctl(0, TCSETAW, &ntermio); /* and activate them */
|
||||
#else
|
||||
ioctl(0, TCSETA, &ntermio); /* and activate them */
|
||||
#endif
|
||||
kbdflgs = fcntl( 0, F_GETFL, 0 );
|
||||
kbdpoll = FALSE;
|
||||
#endif
|
||||
|
||||
#if V7 | BSD
|
||||
gtty(0, &ostate); /* save old state */
|
||||
gtty(0, &nstate); /* get base of new state */
|
||||
#if XONXOFF
|
||||
nstate.sg_flags |= (CBREAK|TANDEM);
|
||||
#else
|
||||
nstate.sg_flags |= RAW;
|
||||
#endif
|
||||
nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */
|
||||
stty(0, &nstate); /* set mode */
|
||||
ioctl(0, TIOCGETC, &otchars); /* Save old characters */
|
||||
ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */
|
||||
#if BSD & PKCODE
|
||||
ioctl(0, TIOCGLTC, &oltchars); /* Save old local characters */
|
||||
ioctl(0, TIOCSLTC, &nltchars); /* New local characters */
|
||||
#endif
|
||||
#if BSD
|
||||
/* provide a smaller terminal output buffer so that
|
||||
the type ahead detection works better (more often) */
|
||||
setbuffer(stdout, &tobuf[0], TBUFSIZ);
|
||||
signal(SIGTSTP,SIG_DFL); /* set signals so that we can */
|
||||
signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __hpux | SVR4
|
||||
/* provide a smaller terminal output buffer so that
|
||||
the type ahead detection works better (more often) */
|
||||
setvbuf(stdout, &tobuf[0], _IOFBF, TBUFSIZ);
|
||||
signal(SIGTSTP,SIG_DFL); /* set signals so that we can */
|
||||
signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */
|
||||
TTflush();
|
||||
#endif /* __hpux */
|
||||
|
||||
/* on all screens we are not sure of the initial position
|
||||
of the cursor */
|
||||
ttrow = 999;
|
||||
ttcol = 999;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function gets called just before we go back home to the command
|
||||
* interpreter. On VMS it puts the terminal back in a reasonable state.
|
||||
* Another no-operation on CPM.
|
||||
*/
|
||||
ttclose()
|
||||
{
|
||||
#if VMS
|
||||
int status;
|
||||
int iosb[1];
|
||||
|
||||
ttflush();
|
||||
status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
|
||||
oldmode, sizeof(oldmode), 0, 0, 0, 0);
|
||||
if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
|
||||
exit(status);
|
||||
status = SYS$DASSGN(iochan);
|
||||
if (status != SS$_NORMAL)
|
||||
exit(status);
|
||||
#endif
|
||||
#if MSDOS & (TURBO | (PKCODE & MSC))
|
||||
/* restore the CONTROL-break interupt */
|
||||
rg.h.ah = 0x33; /* control-break check dos call */
|
||||
rg.h.al = 1; /* set the current state */
|
||||
rg.h.dl = 1; /* set it ON */
|
||||
intdos(&rg, &rg); /* go for it! */
|
||||
#endif
|
||||
|
||||
#if USG
|
||||
#if PKCODE
|
||||
ioctl(0, TCSETAW, &otermio); /* restore terminal settings */
|
||||
#else
|
||||
ioctl(0, TCSETA, &otermio); /* restore terminal settings */
|
||||
#endif
|
||||
fcntl(0, F_SETFL, kbdflgs);
|
||||
#endif
|
||||
|
||||
#if V7 | BSD
|
||||
stty(0, &ostate);
|
||||
ioctl(0, TIOCSETC, &otchars); /* Place old character into K */
|
||||
#if BSD & PKCODE
|
||||
ioctl(0, TIOCSLTC, &oltchars); /* Place old local character into K */
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a character to the display. On VMS, terminal output is buffered, and
|
||||
* we just put the characters in the big array, after checking for overflow.
|
||||
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
|
||||
* MS-DOS (use the very very raw console output routine).
|
||||
*/
|
||||
ttputc(c)
|
||||
{
|
||||
#if VMS
|
||||
if (nobuf >= NOBUF)
|
||||
ttflush();
|
||||
obuf[nobuf++] = c;
|
||||
#endif
|
||||
|
||||
#if MSDOS & ~IBMPC
|
||||
bdos(6, c, 0);
|
||||
#endif
|
||||
|
||||
#if V7 | USG | BSD
|
||||
fputc(c, stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush terminal buffer. Does real work where the terminal output is buffered
|
||||
* up. A no-operation on systems where byte at a time terminal I/O is done.
|
||||
*/
|
||||
ttflush()
|
||||
{
|
||||
#if VMS
|
||||
int status;
|
||||
int iosb[2];
|
||||
|
||||
status = SS$_NORMAL;
|
||||
if (nobuf != 0) {
|
||||
status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
|
||||
iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
|
||||
if (status == SS$_NORMAL)
|
||||
status = iosb[0] & 0xFFFF;
|
||||
nobuf = 0;
|
||||
}
|
||||
return (status);
|
||||
#endif
|
||||
|
||||
#if MSDOS
|
||||
#endif
|
||||
|
||||
#if V7 | USG | BSD
|
||||
/*
|
||||
* Add some terminal output success checking, sometimes an orphaned
|
||||
* process may be left looping on SunOS 4.1.
|
||||
*
|
||||
* How to recover here, or is it best just to exit and lose
|
||||
* everything?
|
||||
*
|
||||
* jph, 8-Oct-1993
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
int status;
|
||||
|
||||
status = fflush(stdout);
|
||||
|
||||
if (status != 0 && errno != EAGAIN) {
|
||||
exit(errno);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a character from the terminal, performing no editing and doing no echo
|
||||
* at all. More complex in VMS that almost anyplace else, which figures. Very
|
||||
* simple on CPM, because the system can do exactly what you want.
|
||||
*/
|
||||
ttgetc()
|
||||
{
|
||||
#if VMS
|
||||
int status;
|
||||
int iosb[2];
|
||||
int term[2];
|
||||
|
||||
while (ibufi >= nibuf) {
|
||||
ibufi = 0;
|
||||
term[0] = 0;
|
||||
term[1] = 0;
|
||||
status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
|
||||
iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
|
||||
if (status != SS$_NORMAL)
|
||||
exit(status);
|
||||
status = iosb[0] & 0xFFFF;
|
||||
if (status!=SS$_NORMAL && status!=SS$_TIMEOUT &&
|
||||
status!=SS$_DATAOVERUN)
|
||||
exit(status);
|
||||
nibuf = (iosb[0]>>16) + (iosb[1]>>16);
|
||||
if (nibuf == 0) {
|
||||
status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
|
||||
iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
|
||||
if (status != SS$_NORMAL
|
||||
|| (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
|
||||
if (status != SS$_DATAOVERUN)
|
||||
exit(status);
|
||||
nibuf = (iosb[0]>>16) + (iosb[1]>>16);
|
||||
}
|
||||
}
|
||||
return (ibuf[ibufi++] & 0xFF); /* Allow multinational */
|
||||
#endif
|
||||
|
||||
#if MSDOS & (MSC | TURBO)
|
||||
int c; /* character read */
|
||||
|
||||
/* if a char already is ready, return it */
|
||||
if (nxtchar >= 0) {
|
||||
c = nxtchar;
|
||||
nxtchar = -1;
|
||||
return(c);
|
||||
}
|
||||
|
||||
/* call the dos to get a char */
|
||||
rg.h.ah = 7; /* dos Direct Console Input call */
|
||||
intdos(&rg, &rg);
|
||||
c = rg.h.al; /* grab the char */
|
||||
return(c & 255);
|
||||
#endif
|
||||
|
||||
#if V7 | BSD
|
||||
return(255 & fgetc(stdin)); /* 8BIT P.K. */
|
||||
#endif
|
||||
|
||||
#if USG
|
||||
if( kbdqp )
|
||||
kbdqp = FALSE;
|
||||
else
|
||||
{
|
||||
if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
|
||||
return FALSE;
|
||||
kbdpoll = FALSE;
|
||||
while (read(0, &kbdq, 1) != 1)
|
||||
;
|
||||
}
|
||||
return ( kbdq & 255 );
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TYPEAH
|
||||
/* typahead: Check to see if any characters are already in the
|
||||
keyboard buffer
|
||||
*/
|
||||
|
||||
typahead()
|
||||
|
||||
{
|
||||
#if MSDOS & (MSC | TURBO)
|
||||
if (kbhit() != 0)
|
||||
return(TRUE);
|
||||
else
|
||||
return(FALSE);
|
||||
#endif
|
||||
|
||||
#if BSD
|
||||
int x; /* holds # of pending chars */
|
||||
|
||||
return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
|
||||
#endif
|
||||
|
||||
#if PKCODE & VMS
|
||||
return(ibufi < nibuf);
|
||||
#endif
|
||||
|
||||
#if USG
|
||||
if( !kbdqp )
|
||||
{
|
||||
if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
|
||||
return(FALSE);
|
||||
#if PKCODE
|
||||
kbdpoll = 1;
|
||||
#endif
|
||||
kbdqp = (1 == read( 0, &kbdq, 1 ));
|
||||
}
|
||||
return ( kbdqp );
|
||||
#endif
|
||||
|
||||
#if !UNIX & !VMS & !MSDOS
|
||||
return(FALSE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* not POSIX */
|
29
vmslink.com
Normal file
29
vmslink.com
Normal file
@ -0,0 +1,29 @@
|
||||
$ define lnk$library sys$library:vaxcrtl
|
||||
$ link /exec=emacs.exe -
|
||||
ANSI.OBJ+ -
|
||||
BASIC.OBJ+ -
|
||||
BIND.OBJ+ -
|
||||
BUFFER.OBJ+ -
|
||||
CRYPT.OBJ+ -
|
||||
DISPLAY.OBJ+ -
|
||||
EVAL.OBJ+ -
|
||||
EXEC.OBJ+ -
|
||||
FILE.OBJ+ -
|
||||
FILEIO.OBJ+ -
|
||||
IBMPC.OBJ+ -
|
||||
INPUT.OBJ+ -
|
||||
ISEARCH.OBJ+ -
|
||||
LINE.OBJ+ -
|
||||
LOCK.OBJ+ -
|
||||
MAIN.OBJ+ -
|
||||
RANDOM.OBJ+ -
|
||||
REGION.OBJ+ -
|
||||
SEARCH.OBJ+ -
|
||||
SPAWN.OBJ+ -
|
||||
TCAP.OBJ+ -
|
||||
TERMIO.OBJ+ -
|
||||
VMSVT.OBJ+ -
|
||||
VT52.OBJ+ -
|
||||
WINDOW.OBJ+ -
|
||||
WORD.OBJ+ -
|
||||
PKLOCK.OBJ
|
28
vmsmake.com
Normal file
28
vmsmake.com
Normal file
@ -0,0 +1,28 @@
|
||||
$ cc /define=(AUTOCONF) ANSI.c
|
||||
$ cc /define=(AUTOCONF) BASIC.c
|
||||
$ cc /define=(AUTOCONF) BIND.c
|
||||
$ cc /define=(AUTOCONF) BUFFER.c
|
||||
$ cc /define=(AUTOCONF) CRYPT.c
|
||||
$ cc /define=(AUTOCONF) DISPLAY.c
|
||||
$ cc /define=(AUTOCONF) EVAL.c
|
||||
$ cc /define=(AUTOCONF) EXEC.c
|
||||
$ cc /define=(AUTOCONF) FILE.c
|
||||
$ cc /define=(AUTOCONF) FILEIO.c
|
||||
$ cc /define=(AUTOCONF) IBMPC.c
|
||||
$ cc /define=(AUTOCONF) INPUT.c
|
||||
$ cc /define=(AUTOCONF) ISEARCH.c
|
||||
$ cc /define=(AUTOCONF) LINE.c
|
||||
$ cc /define=(AUTOCONF) LOCK.c
|
||||
$ cc /define=(AUTOCONF) MAIN.c
|
||||
$ cc /define=(AUTOCONF) RANDOM.c
|
||||
$ cc /define=(AUTOCONF) REGION.c
|
||||
$ cc /define=(AUTOCONF) SEARCH.c
|
||||
$ cc /define=(AUTOCONF) SPAWN.c
|
||||
$ cc /define=(AUTOCONF) TCAP.c
|
||||
$ cc /define=(AUTOCONF) TERMIO.c
|
||||
$ cc /define=(AUTOCONF) VMSVT.c
|
||||
$ cc /define=(AUTOCONF) VT52.c
|
||||
$ cc /define=(AUTOCONF) WINDOW.c
|
||||
$ cc /define=(AUTOCONF) WORD.c
|
||||
$ cc /define=(AUTOCONF) PKLOCK.c
|
||||
$ @vmslink
|
519
vmsvt.c
Normal file
519
vmsvt.c
Normal file
@ -0,0 +1,519 @@
|
||||
/* VMSVT.C
|
||||
*
|
||||
* Advanced VMS terminal driver
|
||||
*
|
||||
* Knows about any terminal defined in SMGTERMS.TXT and TERMTABLE.TXT
|
||||
* located in SYS$SYSTEM.
|
||||
*
|
||||
* Author: Curtis Smith
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* Standard I/O package */
|
||||
#include "estruct.h" /* Emacs' structures */
|
||||
#include "edef.h" /* Emacs' definitions */
|
||||
|
||||
#if VMSVT
|
||||
|
||||
#include <descrip.h> /* Descriptor definitions */
|
||||
|
||||
/* These would normally come from iodef.h and ttdef.h */
|
||||
#define IO$_SENSEMODE 0x27 /* Sense mode of terminal */
|
||||
#define TT$_UNKNOWN 0x00 /* Unknown terminal */
|
||||
#define TT$_VT100 96
|
||||
|
||||
/** Forward references **/
|
||||
int vmsopen(), ttclose(), vmskopen(), vmskclose(), ttgetc(), ttputc();
|
||||
int ttflush(), vmsmove(), vmseeol(), vmseeop(), vmsbeep(), vmsrev();
|
||||
int vmscres();
|
||||
extern int eolexist, revexist;
|
||||
extern char sres[];
|
||||
|
||||
#if COLOR
|
||||
int vmsfcol(), vmsbcol();
|
||||
#endif
|
||||
|
||||
/** SMG stuff **/
|
||||
static char * begin_reverse, * end_reverse, * erase_to_end_line;
|
||||
static char * erase_whole_display;
|
||||
static int termtype;
|
||||
|
||||
#define SMG$K_BEGIN_REVERSE 0x1bf
|
||||
#define SMG$K_END_REVERSE 0x1d6
|
||||
#define SMG$K_SET_CURSOR_ABS 0x23a
|
||||
#define SMG$K_ERASE_WHOLE_DISPLAY 0x1da
|
||||
#define SMG$K_ERASE_TO_END_LINE 0x1d9
|
||||
|
||||
#if SCROLLCODE
|
||||
|
||||
#define SMG$K_SCROLL_FORWARD 561 /* from sys$library:smgtrmptr.h */
|
||||
#define SMG$K_SCROLL_REVERSE 562
|
||||
#define SMG$K_SET_SCROLL_REGION 572
|
||||
|
||||
static char *scroll_forward, *scroll_reverse;
|
||||
|
||||
#endif
|
||||
|
||||
/* Dispatch table. All hard fields just point into the terminal I/O code. */
|
||||
TERM term = {
|
||||
#if PKCODE
|
||||
MAXROW,
|
||||
#else
|
||||
24 - 1, /* Max number of rows allowable */
|
||||
#endif
|
||||
/* Filled in */ - 1, /* Current number of rows used */
|
||||
MAXCOL, /* Max number of columns */
|
||||
/* Filled in */ 0, /* Current number of columns */
|
||||
64, /* Min margin for extended lines*/
|
||||
8, /* Size of scroll region */
|
||||
100, /* # times thru update to pause */
|
||||
vmsopen, /* Open terminal at the start */
|
||||
ttclose, /* Close terminal at end */
|
||||
vmskopen, /* Open keyboard */
|
||||
vmskclose, /* Close keyboard */
|
||||
ttgetc, /* Get character from keyboard */
|
||||
ttputc, /* Put character to display */
|
||||
ttflush, /* Flush output buffers */
|
||||
vmsmove, /* Move cursor, origin 0 */
|
||||
vmseeol, /* Erase to end of line */
|
||||
vmseeop, /* Erase to end of page */
|
||||
vmsbeep, /* Beep */
|
||||
vmsrev, /* Set reverse video state */
|
||||
vmscres /* Change screen resolution */
|
||||
#if COLOR
|
||||
, vmsfcol, /* Set forground color */
|
||||
vmsbcol /* Set background color */
|
||||
#endif
|
||||
#if SCROLLCODE
|
||||
, NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
/***
|
||||
* ttputs - Send a string to ttputc
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
ttputs(string)
|
||||
char * string; /* String to write */
|
||||
{
|
||||
if (string)
|
||||
while (*string != '\0')
|
||||
ttputc(*string++);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* vmsmove - Move the cursor (0 origin)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmsmove(row, col)
|
||||
int row; /* Row position */
|
||||
int col; /* Column position */
|
||||
{
|
||||
char buffer[32];
|
||||
int ret_length;
|
||||
static int request_code = SMG$K_SET_CURSOR_ABS;
|
||||
static int max_buffer_length = sizeof(buffer);
|
||||
static int arg_list[3] = { 2 };
|
||||
register char * cp;
|
||||
|
||||
register int i;
|
||||
|
||||
/* Set the arguments into the arg_list array
|
||||
* SMG assumes the row/column positions are 1 based (boo!)
|
||||
*/
|
||||
arg_list[1] = row + 1;
|
||||
arg_list[2] = col + 1;
|
||||
|
||||
if ((smg$get_term_data( /* Get terminal data */
|
||||
&termtype, /* Terminal table address */
|
||||
&request_code, /* Request code */
|
||||
&max_buffer_length, /* Maximum buffer length */
|
||||
&ret_length, /* Return length */
|
||||
buffer, /* Capability data buffer */
|
||||
arg_list) /* Argument list array */
|
||||
|
||||
/* We'll know soon enough if this doesn't work */
|
||||
& 1) == 0) {
|
||||
ttputs("OOPS");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send out resulting sequence */
|
||||
i = ret_length;
|
||||
cp = buffer;
|
||||
while (i-- > 0)
|
||||
ttputc(*cp++);
|
||||
}
|
||||
|
||||
#if SCROLLCODE
|
||||
|
||||
vmsscroll_reg(from,to,howmany)
|
||||
{
|
||||
int i;
|
||||
if (to == from) return;
|
||||
if (to < from) {
|
||||
vmsscrollregion(to, from + howmany - 1);
|
||||
vmsmove(from + howmany - 1,0);
|
||||
for (i = from - to; i > 0; i--)
|
||||
ttputs(scroll_forward);
|
||||
} else { /* from < to */
|
||||
vmsscrollregion(from, to + howmany - 1);
|
||||
vmsmove(from,0);
|
||||
for (i = to - from; i > 0; i--)
|
||||
ttputs(scroll_reverse);
|
||||
}
|
||||
vmsscrollregion(-1, -1);
|
||||
}
|
||||
|
||||
vmsscrollregion(top, bot)
|
||||
int top; /* Top position */
|
||||
int bot; /* Bottom position */
|
||||
{
|
||||
char buffer[32];
|
||||
int ret_length;
|
||||
static int request_code = SMG$K_SET_SCROLL_REGION;
|
||||
static int max_buffer_length = sizeof(buffer);
|
||||
static int arg_list[3] = { 2 };
|
||||
register char * cp;
|
||||
|
||||
register int i;
|
||||
|
||||
/* Set the arguments into the arg_list array
|
||||
* SMG assumes the row/column positions are 1 based (boo!)
|
||||
*/
|
||||
arg_list[1] = top + 1;
|
||||
arg_list[2] = bot + 1;
|
||||
|
||||
if ((smg$get_term_data( /* Get terminal data */
|
||||
&termtype, /* Terminal table address */
|
||||
&request_code, /* Request code */
|
||||
&max_buffer_length, /* Maximum buffer length */
|
||||
&ret_length, /* Return length */
|
||||
buffer, /* Capability data buffer */
|
||||
arg_list) /* Argument list array */
|
||||
|
||||
/* We'll know soon enough if this doesn't work */
|
||||
& 1) == 0) {
|
||||
ttputs("OOPS");
|
||||
return;
|
||||
}
|
||||
|
||||
ttputc(0);
|
||||
/* Send out resulting sequence */
|
||||
i = ret_length;
|
||||
cp = buffer;
|
||||
while (i-- > 0)
|
||||
ttputc(*cp++);
|
||||
}
|
||||
#endif
|
||||
|
||||
/***
|
||||
* vmsrev - Set the reverse video status
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmsrev(status)
|
||||
int status; /* TRUE if setting reverse */
|
||||
{
|
||||
if (status)
|
||||
ttputs(begin_reverse);
|
||||
else
|
||||
ttputs(end_reverse);
|
||||
}
|
||||
|
||||
/***
|
||||
* vmscres - Change screen resolution (which it doesn't)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmscres()
|
||||
{
|
||||
/* But it could. For vt100/vt200s, one could switch from
|
||||
80 and 132 columns modes */
|
||||
}
|
||||
|
||||
|
||||
#if COLOR
|
||||
/***
|
||||
* vmsfcol - Set the forground color (not implimented)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmsfcol()
|
||||
{
|
||||
}
|
||||
|
||||
/***
|
||||
* vmsbcol - Set the background color (not implimented)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmsbcol()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/***
|
||||
* vmseeol - Erase to end of line
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmseeol()
|
||||
{
|
||||
ttputs(erase_to_end_line);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* vmseeop - Erase to end of page (clear screen)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmseeop()
|
||||
{
|
||||
ttputs(erase_whole_display);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* vmsbeep - Ring the bell
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmsbeep()
|
||||
{
|
||||
ttputc('\007');
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* vmsgetstr - Get an SMG string capability by name
|
||||
*
|
||||
* Returns: Escape sequence
|
||||
* NULL No escape sequence available
|
||||
***/
|
||||
char * vmsgetstr(request_code)
|
||||
int request_code; /* Request code */
|
||||
{
|
||||
register char * result;
|
||||
static char seq_storage[1024];
|
||||
static char * buffer = seq_storage;
|
||||
static int arg_list[2] = { 1, 1 };
|
||||
int max_buffer_length, ret_length;
|
||||
|
||||
/* Precompute buffer length */
|
||||
|
||||
max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer;
|
||||
|
||||
/* Get terminal commands sequence from master table */
|
||||
|
||||
if ((smg$get_term_data( /* Get terminal data */
|
||||
&termtype, /* Terminal table address */
|
||||
&request_code, /* Request code */
|
||||
&max_buffer_length,/* Maximum buffer length */
|
||||
&ret_length, /* Return length */
|
||||
buffer, /* Capability data buffer */
|
||||
arg_list) /* Argument list array */
|
||||
|
||||
/* If this doesn't work, try again with no arguments */
|
||||
|
||||
& 1) == 0 &&
|
||||
|
||||
(smg$get_term_data( /* Get terminal data */
|
||||
&termtype, /* Terminal table address */
|
||||
&request_code, /* Request code */
|
||||
&max_buffer_length,/* Maximum buffer length */
|
||||
&ret_length, /* Return length */
|
||||
buffer) /* Capability data buffer */
|
||||
|
||||
/* Return NULL pointer if capability is not available */
|
||||
|
||||
& 1) == 0)
|
||||
return NULL;
|
||||
|
||||
/* Check for empty result */
|
||||
if (ret_length == 0)
|
||||
return NULL;
|
||||
|
||||
/* Save current position so we can return it to caller */
|
||||
|
||||
result = buffer;
|
||||
|
||||
/* NIL terminate the sequence for return */
|
||||
|
||||
buffer[ret_length] = 0;
|
||||
|
||||
/* Advance buffer */
|
||||
|
||||
buffer += ret_length + 1;
|
||||
|
||||
/* Return capability to user */
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** I/O information block definitions **/
|
||||
struct iosb { /* I/O status block */
|
||||
short i_cond; /* Condition value */
|
||||
short i_xfer; /* Transfer count */
|
||||
long i_info; /* Device information */
|
||||
};
|
||||
struct termchar { /* Terminal characteristics */
|
||||
char t_class; /* Terminal class */
|
||||
char t_type; /* Terminal type */
|
||||
short t_width; /* Terminal width in characters */
|
||||
long t_mandl; /* Terminal's mode and length */
|
||||
long t_extend; /* Extended terminal characteristics */
|
||||
};
|
||||
static struct termchar tc; /* Terminal characteristics */
|
||||
|
||||
/***
|
||||
* vmsgtty - Get terminal type from system control block
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmsgtty()
|
||||
{
|
||||
short fd;
|
||||
int status;
|
||||
struct iosb iostatus;
|
||||
$DESCRIPTOR(devnam, "SYS$INPUT");
|
||||
|
||||
/* Assign input to a channel */
|
||||
status = sys$assign(&devnam, &fd, 0, 0);
|
||||
if ((status & 1) == 0)
|
||||
exit (status);
|
||||
|
||||
/* Get terminal characteristics */
|
||||
status = sys$qiow( /* Queue and wait */
|
||||
0, /* Wait on event flag zero */
|
||||
fd, /* Channel to input terminal */
|
||||
IO$_SENSEMODE, /* Get current characteristic */
|
||||
&iostatus, /* Status after operation */
|
||||
0, 0, /* No AST service */
|
||||
&tc, /* Terminal characteristics buf */
|
||||
sizeof(tc), /* Size of the buffer */
|
||||
0, 0, 0, 0); /* P3-P6 unused */
|
||||
|
||||
/* De-assign the input device */
|
||||
if ((sys$dassgn(fd) & 1) == 0)
|
||||
exit(status);
|
||||
|
||||
/* Jump out if bad status */
|
||||
if ((status & 1) == 0)
|
||||
exit(status);
|
||||
if ((iostatus.i_cond & 1) == 0)
|
||||
exit(iostatus.i_cond);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* vmsopen - Get terminal type and open terminal
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmsopen()
|
||||
{
|
||||
/* Get terminal type */
|
||||
vmsgtty();
|
||||
if (tc.t_type == TT$_UNKNOWN) {
|
||||
printf("Terminal type is unknown!\n");
|
||||
printf("Try set your terminal type with SET TERMINAL/INQUIRE\n");
|
||||
printf("Or get help on SET TERMINAL/DEVICE_TYPE\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
/* Access the system terminal definition table for the */
|
||||
/* information of the terminal type returned by IO$_SENSEMODE */
|
||||
if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0)
|
||||
return -1;
|
||||
|
||||
/* Set sizes */
|
||||
term.t_nrow = ((unsigned int) tc.t_mandl >> 24) - 1;
|
||||
term.t_ncol = tc.t_width;
|
||||
|
||||
/* Get some capabilities */
|
||||
begin_reverse = vmsgetstr(SMG$K_BEGIN_REVERSE);
|
||||
end_reverse = vmsgetstr(SMG$K_END_REVERSE);
|
||||
revexist = begin_reverse != NULL && end_reverse != NULL;
|
||||
erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE);
|
||||
eolexist = erase_to_end_line != NULL;
|
||||
erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY);
|
||||
|
||||
#if SCROLLCODE
|
||||
scroll_forward = vmsgetstr(SMG$K_SCROLL_FORWARD);
|
||||
scroll_reverse = vmsgetstr(SMG$K_SCROLL_REVERSE);
|
||||
if (tc.t_type < TT$_VT100 || scroll_reverse == NULL ||
|
||||
scroll_forward == NULL)
|
||||
term.t_scroll = NULL;
|
||||
else
|
||||
term.t_scroll = vmsscroll_reg;
|
||||
#endif
|
||||
|
||||
/* Set resolution */
|
||||
strcpy(sres, "NORMAL");
|
||||
|
||||
/* Open terminal I/O drivers */
|
||||
ttopen();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* vmskopen - Open keyboard (not used)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmskopen()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* vmskclose - Close keyboard (not used)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
vmskclose()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* fnclabel - Label function keys (not used)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
#if FNLABEL
|
||||
fnclabel(f, n) /* label a function key */
|
||||
int f,n; /* default flag, numeric argument [unused] */
|
||||
{
|
||||
/* on machines with no function keys...don't bother */
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***
|
||||
* spal - Set palette type (Are you kidding?)
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
spal()
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/***
|
||||
* hellovms - Avoid error because of empty module
|
||||
*
|
||||
* Nothing returned
|
||||
***/
|
||||
hellovms()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
190
vt52.c
Normal file
190
vt52.c
Normal file
@ -0,0 +1,190 @@
|
||||
/* VT52.C
|
||||
*
|
||||
* The routines in this file
|
||||
* provide support for VT52 style terminals
|
||||
* over a serial line. The serial I/O services are
|
||||
* provided by routines in "termio.c". It compiles
|
||||
* into nothing if not a VT52 style device. The
|
||||
* bell on the VT52 is terrible, so the "beep"
|
||||
* routine is conditionalized on defining BEL.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#define termdef 1 /* don't define "term" external */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
#if VT52
|
||||
|
||||
#define NROW 24 /* Screen size. */
|
||||
#define NCOL 80 /* Edit if you want to. */
|
||||
#define MARGIN 8 /* size of minimim margin and */
|
||||
#define SCRSIZ 64 /* scroll size for extended lines */
|
||||
#define NPAUSE 100 /* # times thru update to pause */
|
||||
#define BIAS 0x20 /* Origin 0 coordinate bias. */
|
||||
#define ESC 0x1B /* ESC character. */
|
||||
#define BEL 0x07 /* ascii bell character */
|
||||
|
||||
extern int ttopen(); /* Forward references. */
|
||||
extern int ttgetc();
|
||||
extern int ttputc();
|
||||
extern int ttflush();
|
||||
extern int ttclose();
|
||||
extern int vt52move();
|
||||
extern int vt52eeol();
|
||||
extern int vt52eeop();
|
||||
extern int vt52beep();
|
||||
extern int vt52open();
|
||||
extern int vt52rev();
|
||||
extern int vt52cres();
|
||||
extern int vt52kopen();
|
||||
extern int vt52kclose();
|
||||
|
||||
#if COLOR
|
||||
extern int vt52fcol();
|
||||
extern int vt52bcol();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dispatch table. All the
|
||||
* hard fields just point into the
|
||||
* terminal I/O code.
|
||||
*/
|
||||
TERM term = {
|
||||
NROW-1,
|
||||
NROW-1,
|
||||
NCOL,
|
||||
NCOL,
|
||||
MARGIN,
|
||||
SCRSIZ,
|
||||
NPAUSE,
|
||||
&vt52open,
|
||||
&ttclose,
|
||||
&vt52kopen,
|
||||
&vt52kclose,
|
||||
&ttgetc,
|
||||
&ttputc,
|
||||
&ttflush,
|
||||
&vt52move,
|
||||
&vt52eeol,
|
||||
&vt52eeop,
|
||||
&vt52beep,
|
||||
&vt52rev,
|
||||
&vt52cres
|
||||
#if COLOR
|
||||
, &vt52fcol,
|
||||
&vt52bcol
|
||||
#endif
|
||||
#if SCROLLCODE
|
||||
, NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
vt52move(row, col)
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('Y');
|
||||
ttputc(row+BIAS);
|
||||
ttputc(col+BIAS);
|
||||
}
|
||||
|
||||
vt52eeol()
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('K');
|
||||
}
|
||||
|
||||
vt52eeop()
|
||||
{
|
||||
ttputc(ESC);
|
||||
ttputc('J');
|
||||
}
|
||||
|
||||
vt52rev(status) /* set the reverse video state */
|
||||
|
||||
int status; /* TRUE = reverse video, FALSE = normal video */
|
||||
|
||||
{
|
||||
/* can't do this here, so we won't */
|
||||
}
|
||||
|
||||
vt52cres() /* change screen resolution - (not here though) */
|
||||
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
spal() /* change palette string */
|
||||
|
||||
{
|
||||
/* Does nothing here */
|
||||
}
|
||||
|
||||
#if COLOR
|
||||
vt52fcol() /* set the forground color [NOT IMPLIMENTED] */
|
||||
{
|
||||
}
|
||||
|
||||
vt52bcol() /* set the background color [NOT IMPLIMENTED] */
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
vt52beep()
|
||||
{
|
||||
#ifdef BEL
|
||||
ttputc(BEL);
|
||||
ttflush();
|
||||
#endif
|
||||
}
|
||||
|
||||
vt52open()
|
||||
{
|
||||
#if V7 | BSD
|
||||
register char *cp;
|
||||
char *getenv();
|
||||
|
||||
if ((cp = getenv("TERM")) == NULL) {
|
||||
puts("Shell variable TERM not defined!");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) {
|
||||
puts("Terminal type not 'vt52'or 'z19' !");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
ttopen();
|
||||
}
|
||||
|
||||
vt52kopen()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
vt52kclose()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#if FNLABEL
|
||||
fnclabel(f, n) /* label a function key */
|
||||
|
||||
int f,n; /* default flag, numeric argument [unused] */
|
||||
|
||||
{
|
||||
/* on machines with no function keys...don't bother */
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
|
||||
vt52hello()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
733
window.c
Normal file
733
window.c
Normal file
@ -0,0 +1,733 @@
|
||||
/* WINDOW.C
|
||||
*
|
||||
* Window management. Some of the functions are internal, and some are
|
||||
* attached to keys that the user actually types.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
/*
|
||||
* Reposition dot in the current window to line "n". If the argument is
|
||||
* positive, it is that line. If it is negative it is that line from the
|
||||
* bottom. If it is 0 the window is centered (this is what the standard
|
||||
* redisplay code does). With no argument it defaults to 0. Bound to M-!.
|
||||
*/
|
||||
reposition(f, n)
|
||||
{
|
||||
if (f == FALSE) /* default to 0 to center screen */
|
||||
n = 0;
|
||||
curwp->w_force = n;
|
||||
curwp->w_flag |= WFFORCE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Refresh the screen. With no argument, it just does the refresh. With an
|
||||
* argument it recenters "." in the current window. Bound to "C-L".
|
||||
*/
|
||||
refresh(f, n)
|
||||
{
|
||||
if (f == FALSE)
|
||||
sgarbf = TRUE;
|
||||
else
|
||||
{
|
||||
curwp->w_force = 0; /* Center dot. */
|
||||
curwp->w_flag |= WFFORCE;
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The command make the next window (next => down the screen) the current
|
||||
* window. There are no real errors, although the command does nothing if
|
||||
* there is only 1 window on the screen. Bound to "C-X C-N".
|
||||
*
|
||||
* with an argument this command finds the <n>th window from the top
|
||||
*
|
||||
*/
|
||||
nextwind(f, n)
|
||||
|
||||
int f, n; /* default flag and numeric argument */
|
||||
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register int nwindows; /* total number of windows */
|
||||
|
||||
if (f) {
|
||||
|
||||
/* first count the # of windows */
|
||||
wp = wheadp;
|
||||
nwindows = 1;
|
||||
while (wp->w_wndp != NULL) {
|
||||
nwindows++;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
|
||||
/* if the argument is negative, it is the nth window
|
||||
from the bottom of the screen */
|
||||
if (n < 0)
|
||||
n = nwindows + n + 1;
|
||||
|
||||
/* if an argument, give them that window from the top */
|
||||
if (n > 0 && n <= nwindows) {
|
||||
wp = wheadp;
|
||||
while (--n)
|
||||
wp = wp->w_wndp;
|
||||
} else {
|
||||
mlwrite("Window number out of range");
|
||||
return(FALSE);
|
||||
}
|
||||
} else
|
||||
if ((wp = curwp->w_wndp) == NULL)
|
||||
wp = wheadp;
|
||||
curwp = wp;
|
||||
curbp = wp->w_bufp;
|
||||
cknewwindow();
|
||||
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.
|
||||
*/
|
||||
prevwind(f, n)
|
||||
{
|
||||
register WINDOW *wp1;
|
||||
register WINDOW *wp2;
|
||||
|
||||
/* if we have an argument, we mean the nth window from the bottom */
|
||||
if (f)
|
||||
return(nextwind(f, -n));
|
||||
|
||||
wp1 = wheadp;
|
||||
wp2 = curwp;
|
||||
|
||||
if (wp1 == wp2)
|
||||
wp2 = NULL;
|
||||
|
||||
while (wp1->w_wndp != wp2)
|
||||
wp1 = wp1->w_wndp;
|
||||
|
||||
curwp = wp1;
|
||||
curbp = wp1->w_bufp;
|
||||
cknewwindow();
|
||||
upmode();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This command moves the current window down by "arg" lines. Recompute the
|
||||
* top line in the window. The move up and move down code is almost completely
|
||||
* the same; most of the work has to do with reframing the window, and picking
|
||||
* a new dot. We share the code by having "move down" just be an interface to
|
||||
* "move up". Magic. Bound to "C-X C-N".
|
||||
*/
|
||||
mvdnwind(f, n)
|
||||
|
||||
int n;
|
||||
|
||||
{
|
||||
return (mvupwind(f, -n));
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the current window up by "arg" lines. Recompute the new top line of
|
||||
* the window. Look to see if "." is still on the screen. If it is, you win.
|
||||
* If it isn't, then move "." to center it in the new framing of the window
|
||||
* (this command does not really move "."; it moves the frame). Bound to
|
||||
* "C-X C-P".
|
||||
*/
|
||||
mvupwind(f, n)
|
||||
int n;
|
||||
|
||||
{
|
||||
register LINE *lp;
|
||||
register int i;
|
||||
|
||||
lp = curwp->w_linep;
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
while (n++ && lp!=curbp->b_linep)
|
||||
lp = lforw(lp);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (n-- && lback(lp)!=curbp->b_linep)
|
||||
lp = lback(lp);
|
||||
}
|
||||
|
||||
curwp->w_linep = lp;
|
||||
curwp->w_flag |= WFHARD; /* Mode line is OK. */
|
||||
|
||||
for (i = 0; i < curwp->w_ntrows; ++i)
|
||||
{
|
||||
if (lp == curwp->w_dotp)
|
||||
return (TRUE);
|
||||
if (lp == curbp->b_linep)
|
||||
break;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
|
||||
lp = curwp->w_linep;
|
||||
i = curwp->w_ntrows/2;
|
||||
|
||||
while (i-- && lp != curbp->b_linep)
|
||||
lp = lforw(lp);
|
||||
|
||||
curwp->w_dotp = lp;
|
||||
curwp->w_doto = 0;
|
||||
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.
|
||||
*/
|
||||
onlywind(f, n)
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register LINE *lp;
|
||||
register 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the current window, placing its space in the window above,
|
||||
* or, if it is the top window, the window below. Bound to C-X 0.
|
||||
*/
|
||||
|
||||
delwind(f,n)
|
||||
|
||||
int f, n; /* arguments are ignored for this command */
|
||||
|
||||
{
|
||||
register WINDOW *wp; /* window to recieve deleted space */
|
||||
register WINDOW *lwp; /* ptr window before curwp */
|
||||
register int target; /* target line to search for */
|
||||
|
||||
/* if there is only one window, don't delete it */
|
||||
if (wheadp->w_wndp == NULL) {
|
||||
mlwrite("Can not delete this window");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* find window before curwp in linked list */
|
||||
wp = wheadp;
|
||||
lwp = NULL;
|
||||
while (wp != NULL) {
|
||||
if (wp == curwp)
|
||||
break;
|
||||
lwp = wp;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
|
||||
/* find recieving window and give up our space */
|
||||
wp = wheadp;
|
||||
if (curwp->w_toprow == 0) {
|
||||
/* find the next window down */
|
||||
target = curwp->w_ntrows + 1;
|
||||
while (wp != NULL) {
|
||||
if (wp->w_toprow == target)
|
||||
break;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
if (wp == NULL)
|
||||
return(FALSE);
|
||||
wp->w_toprow = 0;
|
||||
wp->w_ntrows += target;
|
||||
} else {
|
||||
/* find the next window up */
|
||||
target = curwp->w_toprow - 1;
|
||||
while (wp != NULL) {
|
||||
if ((wp->w_toprow + wp->w_ntrows) == target)
|
||||
break;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
if (wp == NULL)
|
||||
return(FALSE);
|
||||
wp->w_ntrows += 1 + curwp->w_ntrows;
|
||||
}
|
||||
|
||||
/* get rid of the current window */
|
||||
if (--curwp->w_bufp->b_nwnd == 0) {
|
||||
curwp->w_bufp->b_dotp = curwp->w_dotp;
|
||||
curwp->w_bufp->b_doto = curwp->w_doto;
|
||||
curwp->w_bufp->b_markp = curwp->w_markp;
|
||||
curwp->w_bufp->b_marko = curwp->w_marko;
|
||||
}
|
||||
if (lwp == NULL)
|
||||
wheadp = curwp->w_wndp;
|
||||
else
|
||||
lwp->w_wndp = curwp->w_wndp;
|
||||
free((char *)curwp);
|
||||
curwp = wp;
|
||||
wp->w_flag |= WFHARD;
|
||||
curbp = wp->w_bufp;
|
||||
cknewwindow();
|
||||
upmode();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Split the current window. A window smaller than 3 lines cannot be
|
||||
split. An argument of 1 forces the cursor into the upper window, an
|
||||
argument of two forces the cursor to the lower window. The only other
|
||||
error that is possible is a "malloc" failure allocating the structure
|
||||
for the new window. Bound to "C-X 2".
|
||||
|
||||
*/
|
||||
splitwind(f, n)
|
||||
|
||||
int f, n; /* default flag and numeric argument */
|
||||
|
||||
{
|
||||
register WINDOW *wp;
|
||||
register LINE *lp;
|
||||
register int ntru;
|
||||
register int ntrl;
|
||||
register int ntrd;
|
||||
register WINDOW *wp1;
|
||||
register WINDOW *wp2;
|
||||
char *malloc();
|
||||
|
||||
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("(OUT OF MEMORY)");
|
||||
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;
|
||||
#if COLOR
|
||||
/* set the colors of the new window */
|
||||
wp->w_fcolor = gfcolor;
|
||||
wp->w_bcolor = gbcolor;
|
||||
#endif
|
||||
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 (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
|
||||
/* 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".
|
||||
*/
|
||||
enlargewind(f, n)
|
||||
{
|
||||
register WINDOW *adjwp;
|
||||
register LINE *lp;
|
||||
register 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;
|
||||
#if SCROLLCODE
|
||||
curwp->w_flag |= WFMODE|WFHARD|WFINS;
|
||||
adjwp->w_flag |= WFMODE|WFHARD|WFKILLS;
|
||||
#else
|
||||
curwp->w_flag |= WFMODE|WFHARD;
|
||||
adjwp->w_flag |= WFMODE|WFHARD;
|
||||
#endif
|
||||
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. Bound to
|
||||
* "C-X C-Z".
|
||||
*/
|
||||
shrinkwind(f, n)
|
||||
{
|
||||
register WINDOW *adjwp;
|
||||
register LINE *lp;
|
||||
register 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;
|
||||
#if SCROLLCODE
|
||||
curwp->w_flag |= WFMODE|WFHARD|WFKILLS;
|
||||
adjwp->w_flag |= WFMODE|WFHARD|WFINS;
|
||||
#else
|
||||
curwp->w_flag |= WFMODE|WFHARD;
|
||||
adjwp->w_flag |= WFMODE|WFHARD;
|
||||
#endif
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* Resize the current window to the requested size */
|
||||
|
||||
resize(f, n)
|
||||
|
||||
int f, n; /* default flag and numeric argument */
|
||||
|
||||
{
|
||||
int clines; /* current # of lines in window */
|
||||
|
||||
/* must have a non-default argument, else ignore call */
|
||||
if (f == FALSE)
|
||||
return(TRUE);
|
||||
|
||||
/* find out what to do */
|
||||
clines = curwp->w_ntrows;
|
||||
|
||||
/* already the right size? */
|
||||
if (clines == n)
|
||||
return(TRUE);
|
||||
|
||||
return(enlargewind(TRUE, n - clines));
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a window for a pop-up. Split the screen if there is only one window.
|
||||
* Pick the uppermost window that isn't the current window. An LRU algorithm
|
||||
* might be better. Return a pointer, or NULL on error.
|
||||
*/
|
||||
WINDOW *
|
||||
wpopup()
|
||||
{
|
||||
register 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);
|
||||
}
|
||||
|
||||
scrnextup(f, n) /* scroll the next window up (back) a page */
|
||||
|
||||
{
|
||||
nextwind(FALSE, 1);
|
||||
backpage(f, n);
|
||||
prevwind(FALSE, 1);
|
||||
}
|
||||
|
||||
scrnextdw(f, n) /* scroll the next window down (forward) a page */
|
||||
|
||||
{
|
||||
nextwind(FALSE, 1);
|
||||
forwpage(f, n);
|
||||
prevwind(FALSE, 1);
|
||||
}
|
||||
|
||||
savewnd(f, n) /* save ptr to current window */
|
||||
|
||||
{
|
||||
swindow = curwp;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
restwnd(f, n) /* restore the saved screen */
|
||||
|
||||
{
|
||||
register WINDOW *wp;
|
||||
|
||||
/* find the window */
|
||||
wp = wheadp;
|
||||
while (wp != NULL) {
|
||||
if (wp == swindow) {
|
||||
curwp = wp;
|
||||
curbp = wp->w_bufp;
|
||||
upmode();
|
||||
return (TRUE);
|
||||
}
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
|
||||
mlwrite("(No such window exists)");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
newsize(f, n) /* resize the screen, re-writing the screen */
|
||||
|
||||
int f; /* default flag */
|
||||
int n; /* numeric argument */
|
||||
|
||||
{
|
||||
WINDOW *wp; /* current window being examined */
|
||||
WINDOW *nextwp; /* next window to scan */
|
||||
WINDOW *lastwp; /* last window scanned */
|
||||
int lastline; /* screen line of last line of current window */
|
||||
|
||||
/* if the command defaults, assume the largest */
|
||||
if (f == FALSE)
|
||||
n = term.t_mrow + 1;
|
||||
|
||||
/* make sure it's in range */
|
||||
if (n < 3 || n > term.t_mrow + 1) {
|
||||
mlwrite("%%Screen size out of range");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (term.t_nrow == n - 1)
|
||||
return(TRUE);
|
||||
else if (term.t_nrow < n - 1) {
|
||||
|
||||
/* go to the last window */
|
||||
wp = wheadp;
|
||||
while (wp->w_wndp != NULL)
|
||||
wp = wp->w_wndp;
|
||||
|
||||
/* and enlarge it as needed */
|
||||
wp->w_ntrows = n - wp->w_toprow - 2;
|
||||
wp->w_flag |= WFHARD|WFMODE;
|
||||
|
||||
} else {
|
||||
|
||||
/* rebuild the window structure */
|
||||
nextwp = wheadp;
|
||||
wp = NULL;
|
||||
lastwp = NULL;
|
||||
while (nextwp != NULL) {
|
||||
wp = nextwp;
|
||||
nextwp = wp->w_wndp;
|
||||
|
||||
/* get rid of it if it is too low */
|
||||
if (wp->w_toprow > n - 2) {
|
||||
|
||||
/* save the point/mark if needed */
|
||||
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;
|
||||
}
|
||||
|
||||
/* update curwp and lastwp if needed */
|
||||
if (wp == curwp)
|
||||
curwp = wheadp;
|
||||
curbp = curwp->w_bufp;
|
||||
if (lastwp != NULL)
|
||||
lastwp->w_wndp = NULL;
|
||||
|
||||
/* free the structure */
|
||||
free((char *)wp);
|
||||
wp = NULL;
|
||||
|
||||
} else {
|
||||
/* need to change this window size? */
|
||||
lastline = wp->w_toprow + wp->w_ntrows - 1;
|
||||
if (lastline >= n - 2) {
|
||||
wp->w_ntrows = n - wp->w_toprow - 2;
|
||||
wp->w_flag |= WFHARD|WFMODE;
|
||||
}
|
||||
}
|
||||
|
||||
lastwp = wp;
|
||||
}
|
||||
}
|
||||
|
||||
/* screen is garbage */
|
||||
term.t_nrow = n - 1;
|
||||
sgarbf = TRUE;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
newwidth(f, n) /* resize the screen, re-writing the screen */
|
||||
|
||||
int f; /* default flag */
|
||||
int n; /* numeric argument */
|
||||
|
||||
{
|
||||
register WINDOW *wp;
|
||||
|
||||
/* if the command defaults, assume the largest */
|
||||
if (f == FALSE)
|
||||
n = term.t_mcol;
|
||||
|
||||
/* make sure it's in range */
|
||||
if (n < 10 || n > term.t_mcol) {
|
||||
mlwrite("%%Screen width out of range");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* otherwise, just re-width it (no big deal) */
|
||||
term.t_ncol = n;
|
||||
term.t_margin = n / 10;
|
||||
term.t_scrsiz = n - (term.t_margin * 2);
|
||||
|
||||
/* florce all windows to redraw */
|
||||
wp = wheadp;
|
||||
while (wp) {
|
||||
wp->w_flag |= WFHARD | WFMOVE | WFMODE;
|
||||
wp = wp->w_wndp;
|
||||
}
|
||||
sgarbf = TRUE;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
int getwpos() /* get screen offset of current line in current window */
|
||||
|
||||
{
|
||||
register int sline; /* screen line from top of window */
|
||||
register LINE *lp; /* scannile line pointer */
|
||||
|
||||
/* search down the line we want */
|
||||
lp = curwp->w_linep;
|
||||
sline = 1;
|
||||
while (lp != curwp->w_dotp) {
|
||||
++sline;
|
||||
lp = lforw(lp);
|
||||
}
|
||||
|
||||
/* and return the value */
|
||||
return(sline);
|
||||
}
|
||||
|
||||
cknewwindow()
|
||||
{
|
||||
execute(META|SPEC|'X', FALSE, 1);
|
||||
}
|
||||
|
717
word.c
Normal file
717
word.c
Normal file
@ -0,0 +1,717 @@
|
||||
/* WORD.C
|
||||
*
|
||||
* The routines in this file implement commands that work word or a
|
||||
* paragraph at a time. There are all sorts of word mode commands. If I
|
||||
* do any sentence mode commands, they are likely to be put in this file.
|
||||
*
|
||||
* modified by Petri Kutvonen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "estruct.h"
|
||||
#include "edef.h"
|
||||
|
||||
/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
|
||||
* line and stop on the first word-break or the beginning of the line. If we
|
||||
* reach the beginning of the line, jump back to the end of the word and start
|
||||
* a new line. Otherwise, break the line at the word-break, eat it, and jump
|
||||
* back to the end of the word.
|
||||
* Returns TRUE on success, FALSE on errors.
|
||||
*/
|
||||
wrapword(f, n)
|
||||
|
||||
int f; /* default flag */
|
||||
int n; /* numeric argument */
|
||||
|
||||
{
|
||||
register int cnt; /* size of word wrapped to next line */
|
||||
register int c; /* charector temporary */
|
||||
|
||||
/* backup from the <NL> 1 char */
|
||||
if (!backchar(0, 1))
|
||||
return(FALSE);
|
||||
|
||||
/* back up until we aren't in a word,
|
||||
make sure there is a break in the line */
|
||||
cnt = 0;
|
||||
while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
|
||||
&& (c != '\t')) {
|
||||
cnt++;
|
||||
if (!backchar(0, 1))
|
||||
return(FALSE);
|
||||
/* if we make it to the beginning, start a new line */
|
||||
if (curwp->w_doto == 0) {
|
||||
gotoeol(FALSE, 0);
|
||||
return(lnewline());
|
||||
}
|
||||
}
|
||||
|
||||
/* delete the forward white space */
|
||||
if (!forwdel(0, 1))
|
||||
return(FALSE);
|
||||
|
||||
/* put in a end of line */
|
||||
if (!lnewline())
|
||||
return(FALSE);
|
||||
|
||||
/* and past the first word */
|
||||
while (cnt-- > 0) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor backward by "n" words. All of the details of motion are
|
||||
* performed by the "backchar" and "forwchar" routines. Error if you try to
|
||||
* move beyond the buffers.
|
||||
*/
|
||||
backword(f, n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (forwword(f, -n));
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
while (n--) {
|
||||
while (inword() == FALSE) {
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
while (inword() != FALSE) {
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (forwchar(FALSE, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forward by the specified number of words. All of the motion
|
||||
* is done by "forwchar". Error if you try and move beyond the buffer's end.
|
||||
*/
|
||||
forwword(f, n)
|
||||
{
|
||||
if (n < 0)
|
||||
return (backword(f, -n));
|
||||
while (n--) {
|
||||
while (inword() == TRUE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
while (inword() == FALSE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forward by the specified number of words. As you move,
|
||||
* convert any characters to upper case. Error if you try and move beyond the
|
||||
* end of the buffer. Bound to "M-U".
|
||||
*/
|
||||
upperword(f, n)
|
||||
{
|
||||
register int c;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
while (n--) {
|
||||
while (inword() == FALSE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
while (inword() != FALSE) {
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
#if PKCODE
|
||||
if (islower(c)) {
|
||||
#else
|
||||
if (c>='a' && c<='z') {
|
||||
#endif
|
||||
c -= 'a'-'A';
|
||||
lputc(curwp->w_dotp, curwp->w_doto, c);
|
||||
lchange(WFHARD);
|
||||
}
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forward by the specified number of words. As you move
|
||||
* convert characters to lower case. Error if you try and move over the end of
|
||||
* the buffer. Bound to "M-L".
|
||||
*/
|
||||
lowerword(f, n)
|
||||
{
|
||||
register int c;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
while (n--) {
|
||||
while (inword() == FALSE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
while (inword() != FALSE) {
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
#if PKCODE
|
||||
if (isupper(c)) {
|
||||
#else
|
||||
if (c>='A' && c<='Z') {
|
||||
#endif
|
||||
c += 'a'-'A';
|
||||
lputc(curwp->w_dotp, curwp->w_doto, c);
|
||||
lchange(WFHARD);
|
||||
}
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the cursor forward by the specified number of words. As you move
|
||||
* convert the first character of the word to upper case, and subsequent
|
||||
* characters to lower case. Error if you try and move past the end of the
|
||||
* buffer. Bound to "M-C".
|
||||
*/
|
||||
capword(f, n)
|
||||
{
|
||||
register int c;
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
while (n--) {
|
||||
while (inword() == FALSE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
if (inword() != FALSE) {
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
#if PKCODE
|
||||
if (islower(c)) {
|
||||
#else
|
||||
if (c>='a' && c<='z') {
|
||||
#endif
|
||||
c -= 'a'-'A';
|
||||
lputc(curwp->w_dotp, curwp->w_doto, c);
|
||||
lchange(WFHARD);
|
||||
}
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
while (inword() != FALSE) {
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
#if PKCODE
|
||||
if (isupper(c)) {
|
||||
#else
|
||||
if (c>='A' && c<='Z') {
|
||||
#endif
|
||||
c += 'a'-'A';
|
||||
lputc(curwp->w_dotp, curwp->w_doto, c);
|
||||
lchange(WFHARD);
|
||||
}
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Kill forward by "n" words. Remember the location of dot. Move forward by
|
||||
* the right number of words. Put dot back where it was and issue the kill
|
||||
* command for the right number of characters. With a zero argument, just
|
||||
* kill one word and no whitespace. Bound to "M-D".
|
||||
*/
|
||||
delfword(f, n)
|
||||
{
|
||||
register LINE *dotp; /* original cursor line */
|
||||
register int doto; /* and row */
|
||||
register int c; /* temp char */
|
||||
long size; /* # of chars to delete */
|
||||
|
||||
/* don't allow this command if we are in read only mode */
|
||||
if (curbp->b_mode&MDVIEW)
|
||||
return(rdonly());
|
||||
|
||||
/* ignore the command if there is a negative argument */
|
||||
if (n < 0)
|
||||
return (FALSE);
|
||||
|
||||
/* Clear the kill buffer if last command wasn't a kill */
|
||||
if ((lastflag&CFKILL) == 0)
|
||||
kdelete();
|
||||
thisflag |= CFKILL; /* this command is a kill */
|
||||
|
||||
/* save the current cursor position */
|
||||
dotp = curwp->w_dotp;
|
||||
doto = curwp->w_doto;
|
||||
|
||||
/* figure out how many characters to give the axe */
|
||||
size = 0;
|
||||
|
||||
/* get us into a word.... */
|
||||
while (inword() == FALSE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
++size;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
/* skip one word, no whitespace! */
|
||||
while (inword() == TRUE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
++size;
|
||||
}
|
||||
} else {
|
||||
/* skip n words.... */
|
||||
while (n--) {
|
||||
|
||||
/* if we are at EOL; skip to the beginning of the next */
|
||||
while (curwp->w_doto == llength(curwp->w_dotp)) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
++size;
|
||||
}
|
||||
|
||||
/* move forward till we are at the end of the word */
|
||||
while (inword() == TRUE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
++size;
|
||||
}
|
||||
|
||||
/* if there are more words, skip the interword stuff */
|
||||
if (n != 0)
|
||||
while (inword() == FALSE) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return(FALSE);
|
||||
++size;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip whitespace and newlines */
|
||||
while ((curwp->w_doto == llength(curwp->w_dotp)) ||
|
||||
((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') ||
|
||||
(c == '\t')) {
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
break;
|
||||
++size;
|
||||
}
|
||||
}
|
||||
|
||||
/* restore the original position and delete the words */
|
||||
curwp->w_dotp = dotp;
|
||||
curwp->w_doto = doto;
|
||||
return (ldelete(size, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Kill backwards by "n" words. Move backwards by the desired number of words,
|
||||
* counting the characters. When dot is finally moved to its resting place,
|
||||
* fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
|
||||
*/
|
||||
delbword(f, n)
|
||||
{
|
||||
long size;
|
||||
|
||||
/* don't allow this command if we are in read only mode */
|
||||
if (curbp->b_mode&MDVIEW)
|
||||
return(rdonly());
|
||||
|
||||
/* ignore the command if there is a nonpositive argument */
|
||||
if (n <= 0)
|
||||
return (FALSE);
|
||||
|
||||
/* Clear the kill buffer if last command wasn't a kill */
|
||||
if ((lastflag&CFKILL) == 0)
|
||||
kdelete();
|
||||
thisflag |= CFKILL; /* this command is a kill */
|
||||
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
size = 0;
|
||||
while (n--) {
|
||||
while (inword() == FALSE) {
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
++size;
|
||||
}
|
||||
while (inword() != FALSE) {
|
||||
++size;
|
||||
if (backchar(FALSE, 1) == FALSE)
|
||||
goto bckdel;
|
||||
}
|
||||
}
|
||||
if (forwchar(FALSE, 1) == FALSE)
|
||||
return (FALSE);
|
||||
bckdel: return (ldelete(size, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if the character at dot is a character that is considered to be
|
||||
* part of a word. The word character list is hard coded. Should be setable.
|
||||
*/
|
||||
inword()
|
||||
{
|
||||
register int c;
|
||||
|
||||
if (curwp->w_doto == llength(curwp->w_dotp))
|
||||
return (FALSE);
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
#if PKCODE
|
||||
if (isletter(c))
|
||||
#else
|
||||
if (c>='a' && c<='z')
|
||||
return (TRUE);
|
||||
if (c>='A' && c<='Z')
|
||||
#endif
|
||||
return (TRUE);
|
||||
if (c>='0' && c<='9')
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
#if WORDPRO
|
||||
fillpara(f, n) /* Fill the current paragraph according to the current
|
||||
fill column */
|
||||
|
||||
int f, n; /* deFault flag and Numeric argument */
|
||||
|
||||
{
|
||||
register int c; /* current char durring scan */
|
||||
register int wordlen; /* length of current word */
|
||||
register int clength; /* position on line during fill */
|
||||
register int i; /* index during word copy */
|
||||
register int newlength; /* tentative new line length */
|
||||
register int eopflag; /* Are we at the End-Of-Paragraph? */
|
||||
register int firstflag; /* first word? (needs no space) */
|
||||
register LINE *eopline; /* pointer to line just past EOP */
|
||||
register int dotflag; /* was the last char a period? */
|
||||
char wbuf[NSTRING]; /* buffer for current word */
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if (fillcol == 0) { /* no fill column set */
|
||||
mlwrite("No fill column set");
|
||||
return(FALSE);
|
||||
}
|
||||
#if PKCODE
|
||||
justflag = FALSE;
|
||||
#endif
|
||||
|
||||
/* record the pointer to the line just past the EOP */
|
||||
gotoeop(FALSE, 1);
|
||||
eopline = lforw(curwp->w_dotp);
|
||||
|
||||
/* and back top the beginning of the paragraph */
|
||||
gotobop(FALSE, 1);
|
||||
|
||||
/* initialize various info */
|
||||
clength = curwp->w_doto;
|
||||
if (clength && curwp->w_dotp->l_text[0] == TAB)
|
||||
clength = 8;
|
||||
wordlen = 0;
|
||||
dotflag = FALSE;
|
||||
|
||||
/* scan through lines, filling words */
|
||||
firstflag = TRUE;
|
||||
eopflag = FALSE;
|
||||
while (!eopflag) {
|
||||
/* get the next character in the paragraph */
|
||||
if (curwp->w_doto == llength(curwp->w_dotp)) {
|
||||
c = ' ';
|
||||
if (lforw(curwp->w_dotp) == eopline)
|
||||
eopflag = TRUE;
|
||||
} else
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
|
||||
/* and then delete it */
|
||||
ldelete(1L, FALSE);
|
||||
|
||||
/* if not a separator, just add it in */
|
||||
if (c != ' ' && c != '\t') {
|
||||
dotflag = (c == '.'); /* was it a dot */
|
||||
if (wordlen < NSTRING - 1)
|
||||
wbuf[wordlen++] = c;
|
||||
} else if (wordlen) {
|
||||
/* at a word break with a word waiting */
|
||||
/* calculate tentitive new length with word added */
|
||||
newlength = clength + 1 + wordlen;
|
||||
if (newlength <= fillcol) {
|
||||
/* add word to current line */
|
||||
if (!firstflag) {
|
||||
linsert(1, ' '); /* the space */
|
||||
++clength;
|
||||
}
|
||||
firstflag = FALSE;
|
||||
} else {
|
||||
/* start a new line */
|
||||
lnewline();
|
||||
clength = 0;
|
||||
}
|
||||
|
||||
/* and add the word in in either case */
|
||||
for (i=0; i<wordlen; i++) {
|
||||
linsert(1, wbuf[i]);
|
||||
++clength;
|
||||
}
|
||||
if (dotflag) {
|
||||
linsert(1, ' ');
|
||||
++clength;
|
||||
}
|
||||
wordlen = 0;
|
||||
}
|
||||
}
|
||||
/* and add a last newline for the end of our new paragraph */
|
||||
lnewline();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
#if PKCODE
|
||||
justpara(f, n) /* Fill the current paragraph according to the current
|
||||
fill column and cursor position */
|
||||
|
||||
int f, n; /* deFault flag and Numeric argument */
|
||||
|
||||
{
|
||||
register int c; /* current char durring scan */
|
||||
register int wordlen; /* length of current word */
|
||||
register int clength; /* position on line during fill */
|
||||
register int i; /* index during word copy */
|
||||
register int newlength; /* tentative new line length */
|
||||
register int eopflag; /* Are we at the End-Of-Paragraph? */
|
||||
register int firstflag; /* first word? (needs no space) */
|
||||
register LINE *eopline; /* pointer to line just past EOP */
|
||||
char wbuf[NSTRING]; /* buffer for current word */
|
||||
int leftmarg; /* left marginal */
|
||||
|
||||
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
|
||||
return(rdonly()); /* we are in read only mode */
|
||||
if (fillcol == 0) { /* no fill column set */
|
||||
mlwrite("No fill column set");
|
||||
return(FALSE);
|
||||
}
|
||||
justflag = TRUE;
|
||||
leftmarg = curwp->w_doto;
|
||||
if (leftmarg+10 > fillcol) {
|
||||
leftmarg = 0;
|
||||
mlwrite("Column too narrow");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* record the pointer to the line just past the EOP */
|
||||
gotoeop(FALSE, 1);
|
||||
eopline = lforw(curwp->w_dotp);
|
||||
|
||||
/* and back top the beginning of the paragraph */
|
||||
gotobop(FALSE, 1);
|
||||
|
||||
/* initialize various info */
|
||||
if (leftmarg < llength(curwp->w_dotp))
|
||||
curwp->w_doto = leftmarg;
|
||||
|
||||
clength = curwp->w_doto;
|
||||
if (clength && curwp->w_dotp->l_text[0] == TAB)
|
||||
clength = 8;
|
||||
|
||||
wordlen = 0;
|
||||
|
||||
/* scan through lines, filling words */
|
||||
firstflag = TRUE;
|
||||
eopflag = FALSE;
|
||||
while (!eopflag) {
|
||||
/* get the next character in the paragraph */
|
||||
if (curwp->w_doto == llength(curwp->w_dotp)) {
|
||||
c = ' ';
|
||||
if (lforw(curwp->w_dotp) == eopline)
|
||||
eopflag = TRUE;
|
||||
} else
|
||||
c = lgetc(curwp->w_dotp, curwp->w_doto);
|
||||
|
||||
/* and then delete it */
|
||||
ldelete(1L, FALSE);
|
||||
|
||||
/* if not a separator, just add it in */
|
||||
if (c != ' ' && c != '\t') {
|
||||
if (wordlen < NSTRING - 1)
|
||||
wbuf[wordlen++] = c;
|
||||
} else if (wordlen) {
|
||||
/* at a word break with a word waiting */
|
||||
/* calculate tentitive new length with word added */
|
||||
newlength = clength + 1 + wordlen;
|
||||
if (newlength <= fillcol) {
|
||||
/* add word to current line */
|
||||
if (!firstflag) {
|
||||
linsert(1, ' '); /* the space */
|
||||
++clength;
|
||||
}
|
||||
firstflag = FALSE;
|
||||
} else {
|
||||
/* start a new line */
|
||||
lnewline();
|
||||
for (i=0; i<leftmarg; i++)
|
||||
linsert(1, ' ');
|
||||
clength = leftmarg;
|
||||
}
|
||||
|
||||
/* and add the word in in either case */
|
||||
for (i=0; i<wordlen; i++) {
|
||||
linsert(1, wbuf[i]);
|
||||
++clength;
|
||||
}
|
||||
wordlen = 0;
|
||||
}
|
||||
}
|
||||
/* and add a last newline for the end of our new paragraph */
|
||||
lnewline();
|
||||
|
||||
forwword(FALSE, 1);
|
||||
if (llength(curwp->w_dotp) > leftmarg)
|
||||
curwp->w_doto = leftmarg;
|
||||
else
|
||||
curwp->w_doto = llength(curwp->w_dotp);
|
||||
|
||||
justflag = FALSE;
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
killpara(f, n) /* delete n paragraphs starting with the current one */
|
||||
|
||||
int f; /* default flag */
|
||||
int n; /* # of paras to delete */
|
||||
|
||||
{
|
||||
register int status; /* returned status of functions */
|
||||
|
||||
while (n--) { /* for each paragraph to delete */
|
||||
|
||||
/* mark out the end and beginning of the para to delete */
|
||||
gotoeop(FALSE, 1);
|
||||
|
||||
/* set the mark here */
|
||||
curwp->w_markp = curwp->w_dotp;
|
||||
curwp->w_marko = curwp->w_doto;
|
||||
|
||||
/* go to the beginning of the paragraph */
|
||||
gotobop(FALSE, 1);
|
||||
curwp->w_doto = 0; /* force us to the beginning of line */
|
||||
|
||||
/* and delete it */
|
||||
if ((status = killregion(FALSE, 1)) != TRUE)
|
||||
return(status);
|
||||
|
||||
/* and clean up the 2 extra lines */
|
||||
ldelete(2L, TRUE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/* wordcount: count the # of words in the marked region,
|
||||
along with average word sizes, # of chars, etc,
|
||||
and report on them. */
|
||||
|
||||
wordcount(f, n)
|
||||
|
||||
int f, n; /* ignored numeric arguments */
|
||||
|
||||
{
|
||||
register LINE *lp; /* current line to scan */
|
||||
register int offset; /* current char to scan */
|
||||
long size; /* size of region left to count */
|
||||
register int ch; /* current character to scan */
|
||||
register int wordflag; /* are we in a word now? */
|
||||
register int lastword; /* were we just in a word? */
|
||||
long nwords; /* total # of words */
|
||||
long nchars; /* total number of chars */
|
||||
int nlines; /* total number of lines in region */
|
||||
int avgch; /* average number of chars/word */
|
||||
int status; /* status return code */
|
||||
REGION region; /* region to look at */
|
||||
|
||||
#if PKCODE
|
||||
struct {
|
||||
long pk_1;
|
||||
long pk_2;
|
||||
int pk_3;
|
||||
int pk_4;
|
||||
} pk_mlrec;
|
||||
#endif
|
||||
|
||||
/* make sure we have a region to count */
|
||||
if ((status = getregion(®ion)) != TRUE)
|
||||
return(status);
|
||||
lp = region.r_linep;
|
||||
offset = region.r_offset;
|
||||
size = region.r_size;
|
||||
|
||||
/* count up things */
|
||||
lastword = FALSE;
|
||||
nchars = 0L;
|
||||
nwords = 0L;
|
||||
nlines = 0;
|
||||
while (size--) {
|
||||
|
||||
/* get the current character */
|
||||
if (offset == llength(lp)) { /* end of line */
|
||||
ch = '\n';
|
||||
lp = lforw(lp);
|
||||
offset = 0;
|
||||
++nlines;
|
||||
} else {
|
||||
ch = lgetc(lp, offset);
|
||||
++offset;
|
||||
}
|
||||
|
||||
/* and tabulate it */
|
||||
wordflag = (
|
||||
#if PKCODE
|
||||
(isletter(ch)) ||
|
||||
#else
|
||||
(ch >= 'a' && ch <= 'z') ||
|
||||
(ch >= 'A' && ch <= 'Z') ||
|
||||
#endif
|
||||
(ch >= '0' && ch <= '9'));
|
||||
if (wordflag == TRUE && lastword == FALSE)
|
||||
++nwords;
|
||||
lastword = wordflag;
|
||||
++nchars;
|
||||
}
|
||||
|
||||
/* and report on the info */
|
||||
if (nwords > 0L)
|
||||
avgch = (int)((100L * nchars) / nwords);
|
||||
else
|
||||
avgch = 0;
|
||||
|
||||
#if PKCODE
|
||||
pk_mlrec.pk_1 = nwords;
|
||||
pk_mlrec.pk_2 = nchars;
|
||||
pk_mlrec.pk_3 = nlines + 1;
|
||||
pk_mlrec.pk_4 = avgch;
|
||||
mlwrite("%*Words %D Chars %D Lines %d Avg chars/word %f",
|
||||
&pk_mlrec);
|
||||
#else
|
||||
mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
|
||||
nwords, nchars, nlines + 1, avgch);
|
||||
#endif
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user