v02i051: Unify TEXT fields from ACCELL Part 2/5
Mark Hargrove
ustel at well.UUCP
Thu Feb 11 10:46:35 AEST 1988
Comp.sources.misc: Volume 2, Issue 51
Submitted-By: "Mark Hargrove" <ustel at well.UUCP>
Archive-Name: accell-text/Part2
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./fileio.c`
then
echo "writing ./fileio.c"
cat > ./fileio.c << '\Rogue\Monster\'
/*
* Name: MicroEMACS
* System V file I/O
*/
#include "def.h"
# ifndef F_OK
# define F_OK 0
# define X_OK 1
# define W_OK 2
# define R_OK 4
# endif
/*
* Move bytes, overlaps OK (daveb).
*
* Doesn't really belong here, but it's system specific since it
* is in assembler in some C libraries.
*/
bcopy( from, to, cnt )
char *from;
char *to;
int cnt;
{
if ( from == to )
return;
if( from > to )
{
while( cnt-- )
*to++ = *from++;
}
else
{
to += cnt;
from += cnt;
while( cnt-- )
*--to = *--from;
}
}
static FILE *ffp;
/*
* Open a file for reading.
*/
ffropen(fn)
char *fn;
{
if ((ffp=fopen(fn, "r")) == NULL)
return (FIOFNF);
return (FIOSUC);
}
/*
* Open a file for writing.
* Return TRUE if all is well, and
* FALSE on error (cannot create).
*/
ffwopen(fn)
char *fn;
{
if ((ffp=fopen(fn, "w")) == NULL) {
ewprintf("Cannot open file for writing");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Close a file.
* Should look at the status.
*/
ffclose()
{
(VOID) fclose(ffp);
return (FIOSUC);
}
/*
* 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)
register char buf[];
{
register int i;
for (i=0; i<nbuf; ++i)
putc(buf[i]&0xFF, ffp);
putc('\n', ffp);
if (ferror(ffp) != FALSE) {
ewprintf("Write I/O error");
return (FIOERR);
}
return (FIOSUC);
}
/*
* Read a line from a file, and store the bytes
* in the supplied buffer. Stop on end of file or end of
* line. Don't get upset by files that don't have an end of
* line on the last line; this seem to be common on CP/M-86 and
* MS-DOS (the suspected culprit is VAX/VMS kermit, but this
* has not been confirmed. If this is sufficiently researched
* it may be possible to pull this kludge). Delete any CR
* followed by an LF. This is mainly for runoff documents,
* both on VMS and on Ultrix (they get copied over from
* VMS systems with DECnet).
*/
ffgetline(buf, nbuf)
register char buf[];
{
register int c;
register int i;
i = 0;
for (;;) {
c = getc(ffp);
if (c == '\r') { /* Delete any non-stray */
c = getc(ffp); /* carriage returns. */
if (c != '\n') {
if (i >= nbuf-1) {
ewprintf("File has long line");
return (FIOERR);
}
buf[i++] = '\r';
}
}
if (c==EOF || c=='\n') /* End of line. */
break;
if (i >= nbuf-1) {
ewprintf("File has long line");
return (FIOERR);
}
buf[i++] = c;
}
if (c == EOF) { /* End of file. */
if (ferror(ffp) != FALSE) {
ewprintf("File read error");
return (FIOERR);
}
if (i == 0) /* Don't get upset if */
return (FIOEOF); /* no newline at EOF. */
}
buf[i] = 0;
return (FIOSUC);
}
#if BACKUP
/*
* Rename the file "fname" into a backup
* copy. On Unix the backup has the same name as the
* original file, with a "~" on the end; this seems to
* be newest of the new-speak. The error handling is
* all in "file.c". The "unlink" is perhaps not the
* right thing here; I don't care that much as
* I don't enable backups myself.
*/
fbackupfile(fname)
char *fname;
{
register char *nname;
if ((nname=malloc(strlen(fname)+1+1)) == NULL)
return (ABORT);
(void) strcpy(nname, fname);
(void) strcat(nname, "~");
(void) unlink(nname); /* Ignore errors. */
/* no rename on System V, so do it dangerous way. */
if ( link(fname, nname) < 0 || unlink(fname) < 0 ) {
free(nname);
return (FALSE);
}
free(nname);
return (TRUE);
}
#endif
/*
* The string "fn" is a file name.
* Perform any required case adjustments. All sustems
* we deal with so far have case insensitive file systems.
* We zap everything to lower case. The problem we are trying
* to solve is getting 2 buffers holding the same file if
* you visit one of them with the "caps lock" key down.
* On UNIX file names are dual case, so we leave
* everything alone.
*/
/*ARGSUSED*/
adjustcase(fn)
register char *fn;
{
#if 0
register int c;
while ((c = *fn) != 0) {
if (c>='A' && c<='Z')
*fn = c + 'a' - 'A';
++fn;
}
#endif
}
#ifdef STARTUP
#include <sys/types.h>
#include <sys/file.h>
/*
* find the users startup file, and return it's name. Check for
* $HOME/.mg then for $HOME/.emacs, then give up.
*/
char *
startupfile()
{
register char *file;
static char home[NFILEN];
char *getenv();
if ( (file = getenv("HOME")) == NULL
|| strlen(file)+7 >= NFILEN - 1 )
return NULL;
(VOID) strcpy(home, file);
file = &(home[strlen(home)]);
*file++ = '/';
(VOID) strcpy(file, ".mg");
if (access(home, F_OK ) == 0) return home;
(VOID) strcpy(file, ".emacs");
if (access(home, F_OK) == 0) return home;
return NULL;
}
#endif
\Rogue\Monster\
else
echo "will not over write ./fileio.c"
fi
if `test ! -s ./kbd.c`
then
echo "writing ./kbd.c"
cat > ./kbd.c << '\Rogue\Monster\'
/*
* Terminal independent keyboard handling.
*/
#include "def.h"
static mapin();
#ifdef DPROMPT
#define PROMPTL 80
char prompt[PROMPTL], *promptp;
#endif
/*
* All input from the user (should!) go through
* getkey. Quotep is true to get raw keys, false to
* get 11-bit code keys.
* Getkey is responsible for putting keystrokes away
* for macros. It also takes keystrokes out of the macro,
* though other input routines will can also do this.
* Read in a key, doing the terminal
* independent prefix handling. The terminal specific
* "getkbd" routine gets the first swing, and may return
* one of the special codes used by the special keys
* on the keyboard. The "getkbd" routine returns the
* C0 controls as received; this routine moves them to
* the right spot in 11 bit code.
* If the KPROMPT bit in the flags is set and DPROMPT is
* defined, do delayed prompting. (dprompt routine is
* in sys/???/ttyio.c)
*/
KEY
getkey(f)
register int f;
{
register KEY c;
KEY keychar();
int getkbd(), ttgetc();
if (kbdmop != NULL)
return *kbdmop++;
#ifdef DPROMPT
if(!(f&KPROMPT))
prompt[0] = '\0';
#endif
c = (KEY) mapin(getkbd);
#ifdef DPROMPT
if(f&KPROMPT)
{
if(promptp > prompt)
*(promptp-1) = ' ';
if(promptp >= &prompt[PROMPTL-8])
f &= ~KPROMPT;
/* must have a lot of prefixes.... */
}
#endif
if ((f&KQUOTE) == 0)
{
#ifdef DO_METAKEY
if ((c & ~KCHAR) == KCTRL) /* Function key */
c = ((char) c) & KCHAR;/* remove wrapping */
else if ((c >= 0x80) && (c <= 0xFF))
{ /* real meta key */
c = ((char) c) & 0x7f; /* Get the key and mode map it */
if ((mode&MFLOW) != 0)
if (c == CCHR('^')) c = CCHR('Q');
else if (c == CCHR('\\')) c = CCHR('S');
if ((mode&MBSMAP) != 0)
if (c == CCHR('H')) c = 0x7f;
else if (c == 0x7f) c = CCHR('H');
c = KMETA | keychar(c & ~0x80, TRUE);
}
#endif
#ifdef DPROMPT
if(f&KPROMPT)
{
keyname(promptp, (c<=0x1F && c>=0x00)?KCTRL|(c+'@'):c);
strcat(promptp, "-");
}
#endif
if (c == METACH) /* M- */
c = KMETA | keychar(mapin(ttgetc), TRUE);
else if (c == CTRLCH) /* C- */
c = KCTRL | keychar(mapin(ttgetc), TRUE);
else if (c == CTMECH) /* C-M- */
c = KCTRL | KMETA | keychar(mapin(ttgetc), TRUE);
else if (c<=0x1F && c>=0x00) /* Relocate control. */
c = KCTRL | (c+'@');
if (c == (KCTRL|'X')) /* C-X */
c = KCTLX | keychar(mapin(ttgetc), TRUE);
}
if ((f&KNOMAC) == 0 && kbdmip != NULL)
{
if (kbdmip+1 > &kbdm[NKBDM-3])
{ /* macro overflow */
(VOID) ctrlg(FALSE, 0, KRANDOM);
ewprintf("Keyboard macro overflow");
ttflush();
return (KCTRL|'G'); /* ^G it for us */
}
*kbdmip++ = c;
}
#ifdef DPROMPT
if(f&KPROMPT)
{
keyname(promptp, c);
promptp += strlen(promptp);
*promptp++ = '-';
*promptp = '\0';
}
#endif
return (c);
}
/*
* go get a key, and run it through whatever mapping the modes
* specify.
*/
static mapin(get) int (*get)();
{
register int c;
#ifdef DPROMPT
if(prompt[0]!='\0' && ttwait())
{
ewprintf("%s", prompt); /* avoid problems with % */
update(); /* put the cursor back */
epresf = KPROMPT;
}
#endif
c = (*get)();
if ((mode&MFLOW) != 0)
{
while (c == CCHR('S') || c == CCHR('Q'))
c = (*get)();
if (c == CCHR('^')) c = CCHR('Q');
else if (c == CCHR('\\')) c = CCHR('S');
}
if ((mode&MBSMAP) != 0)
if (c == CCHR('H')) c = 0x7f;
else if (c == 0x7f) c = CCHR('H');
return c;
}
/*
* Transform a key code into a name,
* using a table for the special keys and combination
* of some hard code and some general processing for
* the rest. None of this code is terminal specific any
* more. This makes adding keys easier.
*/
VOID
keyname(cp, k) register char *cp; register int k;
{
register char *np;
register int c;
char nbuf[3];
static char hex[] = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'A', 'B',
'C', 'D', 'E', 'F'
};
if ((k&KCTLX) != 0) { /* C-X prefix. */
*cp++ = 'C';
*cp++ = '-';
*cp++ = 'x';
*cp++ = ' ';
}
if ((k&KMETA) != 0) { /* Add M- mark. */
*cp++ = 'E';
*cp++ = 'S';
*cp++ = 'C';
*cp++ = ' ';
}
if ((k&KCHAR)>=KFIRST && (k&KCHAR)<=KLAST)
{
if ((np=keystrings[(k&KCHAR)-KFIRST]) != NULL)
{
if ((k&KCTRL) != 0)
{
*cp++ = 'C';
*cp++ = '-';
}
(VOID) strcpy(cp, np);
return;
}
}
c = k & ~(KMETA|KCTLX);
if (c == (KCTRL|'I')) /* Some specials. */
np = "TAB";
else if (c == (KCTRL|'M'))
np = "RET";
else if (c == (KCTRL|'J'))
np = "LFD";
else if (c == ' ')
np = "SPC";
else if (c == 0x7F)
np = "DEL";
else if (c == (KCTRL|'['))
np = "ESC";
else
{
if ((k&KCTRL) != 0)
{ /* Add C- mark. */
*cp++ = 'C';
*cp++ = '-';
}
if ((k&(KCTRL|KMETA|KCTLX)) != 0 && ISUPPER(k&KCHAR) != FALSE)
k = TOLOWER(k&KCHAR);
np = &nbuf[0];
if (((k&KCHAR)>=0x20 && (k&KCHAR)<=0x7E)
|| ((k&KCHAR)>=0xA0 && (k&KCHAR)<=0xFE))
{
nbuf[0] = k&KCHAR; /* Graphic. */
nbuf[1] = 0;
}
else
{ /* Non graphic. */
nbuf[0] = hex[(k>>4)&0x0F];
nbuf[1] = hex[k&0x0F];
nbuf[2] = 0;
}
}
(VOID) strcpy(cp, np);
}
/*
* turn a key into an internal char.
*/
KEY
keychar(c, f) register int c, f;
{
if (f == TRUE && ISLOWER(c) != FALSE)
c = TOUPPER(c);
else if (c>=0x00 && c<=0x1F) /* Relocate control. */
c = (KCTRL|(c+'@'));
return (KEY) c;
}
\Rogue\Monster\
else
echo "will not over write ./kbd.c"
fi
if `test ! -s ./line.c`
then
echo "writing ./line.c"
cat > ./line.c << '\Rogue\Monster\'
/*
* Text line handling.
* 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 "def.h"
#define NBLOCK 16 /* Line block chunk size */
#ifndef KBLOCK
#define KBLOCK 256 /* Kill buffer block size. */
#endif
static char *kbufp = NULL; /* Kill buffer data. */
static RSIZE kused = 0; /* # of bytes used in KB. */
static RSIZE ksize = 0; /* # of bytes allocated in KB. */
static RSIZE kstart = 0; /* # of first used byte in KB. */
char *malloc();
/*
* 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 RSIZE used;
{
register LINE *lp;
register int size;
/*NOSTRICT*/
size = (NBLOCK-1+used) & ~(NBLOCK-1);
if (size == 0) /* Assume that an empty */
size = NBLOCK; /* line is for type-in. */
/*NOSTRICT*/
if ((lp=(LINE *)malloc(sizeof(LINE)+size)) == NULL)
{
ewprintf("Can't get %d bytes", sizeof(LINE) + size);
return (NULL);
}
lp->l_size = size;
/*NOSTRICT*/
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.
*/
VOID
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 to
* HARD. Set MODE if the mode line needs to be
* updated (the "*" has to be set).
* Modified by Walter Bright to reduce update times.
*/
VOID
lchange(flag) register int flag;
{
register WINDOW *wp;
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;
if (wp != curwp) wp->w_flag |= WFHARD;
}
wp = wp->w_wndp;
}
}
/*
* 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.
*
* Added 11-1-87 by s.k.henry: overstrike mode for text insertion.
* Not too hard, mostly just modifies the meaning of 'n'.
*/
linsert(n, c) RSIZE n;
{
register char *cp1;
register char *cp2;
register LINE *lp1;
LINE *lp2;
LINE *lp3;
register int doto;
register RSIZE i;
WINDOW *wp;
#ifndef max
#define max(a,b) ((a) > (b)) ? (a) : (b)
#endif
lchange(WFEDIT);
lp1 = curwp->w_dotp; /* Current line */
if (lp1 == curbp->b_linep) /* At the end: special */
{
if (curwp->w_doto != 0)
{
ewprintf("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;
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->w_markp == lp1)
wp->w_markp = lp2;
wp = wp->w_wndp;
}
/*NOSTRICT*/
curwp->w_doto = n;
return (TRUE);
}
doto = curwp->w_doto; /* Save for later. */
#define INS_MODE ((mode & MOVRSTK) == 0)
#define OVR_MODE ((mode & MOVRSTK) == MOVRSTK)
/*NOSTRICT*/
if ((OVR_MODE && (doto+n > lp1->l_size))
|| (INS_MODE && (lp1->l_used+n > lp1->l_size)))
{ /* Hard: reallocate */
if ((lp2=lalloc((RSIZE) (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++;
if (INS_MODE)
{
/*NOSTRICT*/
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 */
if (INS_MODE)
{
/*NOSTRICT*/
lp2->l_used += n;
cp2 = &lp1->l_text[lp1->l_used];
cp1 = cp2-n;
while (cp1 != &lp1->l_text[doto])
*--cp2 = *--cp1;
}
else
{
/*NOSTRICT*/
lp2->l_used = max( (doto+n), (lp2->l_used));
}
}
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)
/*NOSTRICT*/
wp->w_doto += n;
}
if (wp->w_markp == lp1)
{
wp->w_markp = lp2;
if (wp->w_marko > doto)
/*NOSTRICT*/
wp->w_marko += n;
}
wp = wp->w_wndp;
}
return (TRUE);
}
/*
* 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;
LINE *lp2;
register int doto;
WINDOW *wp;
lchange(WFHARD);
lp1 = curwp->w_dotp; /* Get the address and */
doto = curwp->w_doto; /* offset of "." */
if ((lp2=lalloc((RSIZE) 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" indicates either no insertion,
* or direction of insertion into the kill buffer.
*/
ldelete(n, kflag) RSIZE n;
{
register char *cp1;
register char *cp2;
register LINE *dotp;
register int doto;
register RSIZE chunk;
WINDOW *wp;
/*
* HACK - doesn't matter, and fixes back-over-nl bug for empty
* kill buffers.
*/
if (kused == kstart) kflag = KFORW;
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. */
lchange(WFHARD);
if (ldelnewline() == FALSE
|| (kflag!=KNONE && kinsert('\n', kflag)==FALSE))
return (FALSE);
--n;
continue;
}
lchange(WFEDIT);
cp1 = &dotp->l_text[doto]; /* Scrunch text. */
cp2 = cp1 + chunk;
if (kflag == KFORW)
{
while (ksize - kused < chunk)
if (kgrow(FALSE) == FALSE) return FALSE;
bcopy(cp1, &(kbufp[kused]), (int) chunk);
kused += chunk;
}
else if (kflag == KBACK)
{
while (kstart < chunk)
if (kgrow(TRUE) == FALSE) return FALSE;
bcopy(cp1, &(kbufp[kstart-chunk]), (int) chunk);
kstart -= chunk;
} else if (kflag != KNONE) panic("broken ldelete call");
while (cp2 != &dotp->l_text[dotp->l_used])
*cp1++ = *cp2++;
dotp->l_used -= (int) chunk;
wp = wheadp; /* Fix windows */
while (wp != NULL)
{
if (wp->w_dotp==dotp && wp->w_doto>=doto)
{
/*NOSTRICT*/
wp->w_doto -= chunk;
if (wp->w_doto < doto)
wp->w_doto = doto;
}
if (wp->w_markp==dotp && wp->w_marko>=doto)
{
/*NOSTRICT*/
wp->w_marko -= chunk;
if (wp->w_marko < doto)
wp->w_marko = doto;
}
wp = wp->w_wndp;
}
n -= chunk;
}
return (TRUE);
}
/*
* 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.
*/
ldelnewline()
{
register char *cp1;
register char *cp2;
register LINE *lp1;
LINE *lp2;
LINE *lp3;
WINDOW *wp;
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((RSIZE) (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);
}
/*
* Replace plen characters before dot with argument string.
* Control-J characters in st are interpreted as newlines.
* There is a casehack disable flag (normally it likes to match
* case of replacement to what was there).
*/
lreplace(plen, st, f)
register RSIZE plen; /* length to remove */
char *st; /* replacement string */
int f; /* case hack disable */
{
register RSIZE rlen; /* replacement length */
register int rtype; /* capitalization */
register int c; /* used for random characters */
register int doto; /* offset into line */
/*
* Find the capitalization of the word that was found.
* f says use exact case of replacement string (same thing that
* happens with lowercase found), so bypass check.
*/
/*NOSTRICT*/
(VOID) backchar(TRUE, (int) plen, KRANDOM);
rtype = _L;
c = lgetc(curwp->w_dotp, curwp->w_doto);
if (ISUPPER(c)!=FALSE && f==FALSE)
{
rtype = _U|_L;
if (curwp->w_doto+1 < llength(curwp->w_dotp))
{
c = lgetc(curwp->w_dotp, curwp->w_doto+1);
if (ISUPPER(c) != FALSE)
{
rtype = _U;
}
}
}
/*
* make the string lengths match (either pad the line
* so that it will fit, or scrunch out the excess).
* be careful with dot's offset.
*/
rlen = strlen(st);
doto = curwp->w_doto;
if (plen > rlen)
(VOID) ldelete((RSIZE) (plen-rlen), KNONE);
else if (plen < rlen)
{
if (linsert((RSIZE) (rlen-plen), ' ') == FALSE)
return (FALSE);
}
curwp->w_doto = doto;
/*
* do the replacement: If was capital, then place first
* char as if upper, and subsequent chars as if lower.
* If inserting upper, check replacement for case.
*/
while ((c = *st++&0xff) != '\0')
{
if ((rtype&_U)!=0 && ISLOWER(c)!=0)
c = TOUPPER(c);
if (rtype == (_U|_L))
rtype = _L;
if (c == SEOL)
{
if (curwp->w_doto == llength(curwp->w_dotp))
(VOID) forwchar(FALSE, 1, KRANDOM);
else
{
if (ldelete((RSIZE) 1, KNONE) != FALSE)
(VOID) lnewline();
}
}
else if (curwp->w_dotp == curbp->b_linep)
{
(VOID) linsert((RSIZE) 1, c);
}
else if (curwp->w_doto == llength(curwp->w_dotp))
{
if (ldelete((RSIZE) 1, KNONE) != FALSE)
(VOID) linsert((RSIZE) 1, c);
} else
lputc(curwp->w_dotp, curwp->w_doto++, c);
}
lchange(WFHARD);
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.
*/
VOID
kdelete()
{
if (kbufp != NULL)
{
free((char *) kbufp);
kbufp = NULL;
kstart = kused = ksize = 0;
}
}
/*
* Insert a character to the kill buffer,
* enlarging the buffer if there isn't any room. Always
* grow the buffer in chunks, on the assumption that if you
* put something in the kill buffer you are going to put
* more stuff there too later. Return TRUE if all is
* well, and FALSE on errors. Print a message on
* errors. Dir says whether to put it at back or front.
*/
kinsert(c, dir)
{
if (kused == ksize && dir == KFORW && kgrow(FALSE) == FALSE)
return FALSE;
if (kstart == 0 && dir == KBACK && kgrow(TRUE) == FALSE)
return FALSE;
if (dir == KFORW) kbufp[kused++] = c;
else if (dir == KBACK) kbufp[--kstart] = c;
else panic("broken kinsert call"); /* Oh shit! */
return (TRUE);
}
/*
* kgrow - just get more kill buffer for the callee. back is true if
* we are trying to get space at the beginning of the kill buffer.
*/
kgrow(back)
{
register int nstart;
register char *nbufp;
if ((nbufp=malloc((int)(ksize+KBLOCK))) == NULL)
{
ewprintf("Can't get %ld bytes", (long)(ksize+KBLOCK));
return (FALSE);
}
nstart = (back == TRUE) ? (kstart + KBLOCK) : (KBLOCK / 4) ;
bcopy(&(kbufp[kstart]), &(nbufp[nstart]), (int) (kused-kstart));
if (kbufp != NULL)
free((char *) kbufp);
kbufp = nbufp;
ksize += KBLOCK;
kused = kused - kstart + nstart;
kstart = nstart;
return TRUE;
}
/*
* This function gets characters from
* the kill buffer. If the character index "n" is
* off the end, it returns "-1". This lets the caller
* just scan along until it gets a "-1" back.
*/
kremove(n)
{
if (n < 0 || n + kstart >= kused)
return (-1);
return (kbufp[n + kstart] & 0xFF);
}
\Rogue\Monster\
else
echo "will not over write ./line.c"
fi
if `test ! -s ./main.c`
then
echo "writing ./main.c"
cat > ./main.c << '\Rogue\Monster\'
/*
* Mainline, macro commands.
*/
#include "def.h"
int thisflag; /* Flags, this command */
int lastflag; /* Flags, last command */
int curgoal; /* Goal column */
BUFFER *curbp; /* Current buffer */
WINDOW *curwp; /* Current window */
BUFFER *bheadp; /* BUFFER listhead */
WINDOW *wheadp = (WINDOW *)NULL; /* WINDOW listhead */
KEY kbdm[NKBDM] = {(KCTLX|')')}; /* Macro */
KEY *kbdmip; /* Input for above */
KEY *kbdmop; /* Output for above */
char pat[NPAT]; /* Pattern */
#ifdef HASH
SYMBOL *symbol[NSHASH]; /* Symbol table listhead. */
#else
/* should really be a *symbol, but don't want to break the hash code yet */
SYMBOL *symbol[1] = {(SYMBOL *)NULL};
#endif
SYMBOL *binding[NKEYS]; /* Key bindings. */
#ifdef DPROMPT
extern char prompt[], *promptp; /* delayed prompting */
#endif
VOID edinit();
VOID
main(argc, argv)
int argc;
char *argv[];
{
register KEY c;
register int f;
register int n;
register int mflag;
#ifdef STARTUP
char *sfile, *startupfile();
#endif
char bname[NBUFN];
#ifdef SYSINIT
SYSINIT; /* system dependent. */
#endif
vtinit(); /* Virtual terminal. */
edinit(); /* Buffers, windows. */
keymapinit(); /* Symbols, bindings. */
/* doing update() before reading files causes the error messages from
* the file I/O show up on the screen. (and also an extra display
* of the mode line if there are files specified on the command line.)
*/
update();
#ifdef STARTUP /* User startup file. */
if ((sfile = startupfile()) != NULL)
(VOID) load(sfile);
#endif
while (--argc > 0) {
adjustcase(*++argv);
makename(bname, *argv);
curbp = bfind(bname, TRUE);
(VOID) showbuffer(curbp, curwp, 0);
(VOID) readin(*argv);
}
lastflag = 0; /* Fake last flags. */
loop:
#ifdef DPROMPT
*(promptp = prompt) = '\0';
if(epresf == KPROMPT) eerase();
#endif
update(); /* Fix up the screen. */
c = getkey(KPROMPT);
if (epresf == TRUE)
{
eerase();
update();
}
f = FALSE;
n = 1;
if (((KMETA|'0') <= c && c <= (KMETA|'9')) || c == (KMETA|'-'))
{
f = TRUE;
c = c & ~KMETA;
}
else if (c == (KCTRL|'U'))
{
f = TRUE;
n = 4;
while ((c=getkey(KNOMAC | KPROMPT)) == (KCTRL|'U'))
n *= 4;
}
if (f == TRUE)
{
if ((c>='0' && c<='9') || c=='-')
{
if (c == '-')
{
n = 0;
mflag = TRUE;
}
else
{
n = ((int) c) - '0';
mflag = FALSE;
}
while ((c=getkey(KNOMAC | KPROMPT))>='0' && c<='9')
n = 10*n + ((int) c) - '0';
if (mflag != FALSE)
n = -n;
}
}
if (kbdmip != NULL)
{ /* Terminate macros. */
if (c!=(KCTLX|')') && kbdmip>&kbdm[NKBDM-6])
{
(VOID) ctrlg(FALSE, 0, KRANDOM);
goto loop;
}
if (f != FALSE)
{
kbdmip[-1] = (KEY) (KCTRL|'U');/* overwrite ESC */
*kbdmip++ = (KEY) n;
*kbdmip++ = (KEY) c;
}
}
switch (execute(c, f, n))
{ /* Do it. */
case TRUE: break;
case ABORT:
ewprintf("Quit"); /* and fall through */
case FALSE:
default:
ttbeep();
if (kbdmip != NULL)
{
kbdm[0] = (KEY) (KCTLX|')');
kbdmip = NULL;
}
}
goto loop;
}
/*
* Command execution. Look up the binding in the the
* binding array, and do what it says. Return a very bad status
* if there is no binding, or if the symbol has a type that
* is not usable (there is no way to get this into a symbol table
* entry now). Also fiddle with the flags.
*/
execute(c, f, n)
KEY c;
{
register SYMBOL *sp;
register int status;
if ((sp=binding[c]) != NULL)
{
thisflag = 0;
status = (*sp->s_funcp)(f, n, c);
lastflag = thisflag;
return (status);
}
lastflag = 0;
return (FALSE);
}
/*
* 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.
*/
VOID
edinit()
{
register BUFFER *bp;
register WINDOW *wp;
bheadp = NULL;
bp = bfind("*scratch*", TRUE); /* Text buffer. */
wp = (WINDOW *)malloc(sizeof(WINDOW)); /* Initial window. */
if (bp==NULL || wp==NULL) panic("edinit");
curbp = bp; /* Current ones. */
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;
wp->w_ntrows = nrow-2; /* 2 = mode, echo. */
wp->w_force = 0;
wp->w_flag = WFMODE|WFHARD; /* Full. */
}
/*
* 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".
*/
/*ARGSUSED*/
quit(f, n, k)
{
register int s;
if (f == FALSE)
{
if ((s = anycb(FALSE)) == ABORT)
return ABORT;
if (s == FALSE
|| eyesno("The text is modified, really exit") == TRUE)
{
vttidy();
exit(GOOD);
}
}
else
{
vttidy();
exit(GOOD);
}
return TRUE;
}
/*
* User abort. Should be called by any input routine that sees a C-g
* to abort whatever C-g is aborting these days. Currently does
* nothing.
*/
/*ARGSUSED*/
ctrlg(f, n, k)
{
return (ABORT);
}
\Rogue\Monster\
else
echo "will not over write ./main.c"
fi
if `test ! -s ./match.c`
then
echo "writing ./match.c"
cat > ./match.c << '\Rogue\Monster\'
/*
* Name: MicroEMACS
* Limited parenthesis matching routines
* Version: Gnu30
* Last edit: 13-Jul-86
* Created: 19-May-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
*
* The hacks in this file implement automatic matching
* of (), [], {}, and other characters. It would be
* better to have a full-blown syntax table, but there's
* enough overhead in the editor as it is.
*
* Since I often edit Scribe code, I've made it possible to
* blink arbitrary characters -- just bind delimiter characters
* to "blink-matching-paren-hack"
*/
#include "def.h"
#ifndef TINY
static int balance();
static displaymatch();
/* Balance table. When balance() encounters a character
* that is to be matched, it first searches this table
* for a balancing left-side character. If the character
* is not in the table, the character is balanced by itself.
* This is to allow delimiters in Scribe documents to be matched.
*/
static struct balance {
char left, right;
} bal[] = {
{ '(', ')' },
{ '[', ']' },
{ '{', '}' },
{ '<', '>' },
{ '\0','\0'}
};
/*
* Fake the GNU "blink-matching-paren" variable.
* If the argument exists, nonzero means show,
* zero means don't. If it doesn't exist,
* pretend it's nonzero.
*/
blinkparen(f, n, k)
{
register char *command;
register SYMBOL *sp;
if (f == FALSE)
n = 1;
command = (n == 0) ? "self-insert-command" :
"blink-matching-paren-hack";
if ((sp=symlookup(command)) == NULL)
{
ewprintf("blinkparen: no binding for %s",command);
return (FALSE);
}
binding[(KEY) ')'] = sp; /* rebind paren */
return (TRUE);
}
/*
* Self-insert character, then show matching character,
* if any. Bound to "blink-matching-paren-command".
*/
showmatch(f, n, k)
{
register int i, s;
if (k == KRANDOM)
return(FALSE);
for (i = 0; i < n; i++)
{
if ((s = selfinsert(f, 1, k)) != TRUE)
return(s);
if (balance(k) != TRUE) /* unbalanced -- warn user */
ttbeep();
}
return (TRUE);
}
/*
* Search for and display a matching character.
*
* This routine does the real work of searching backward
* for a balancing character. If such a balancing character
* is found, it uses displaymatch() to display the match.
*/
static balance(k)
int k;
{
register LINE *clp;
register int cbo;
int c;
int i;
int rbal, lbal;
int depth;
rbal = k & KCHAR;
if ((k&KCTRL)!=0 && rbal>='@' && rbal<='_') /* ASCII-ify. */
rbal -= '@';
/* See if there is a matching character -- default to the same */
lbal = rbal;
for (i = 0; bal[i].right != '\0'; i++)
if (bal[i].right == rbal)
{
lbal = bal[i].left;
break;
}
/* Move behind the inserted character. We are always guaranteed */
/* that there is at least one character on the line, since one was */
/* just self-inserted by blinkparen. */
clp = curwp->w_dotp;
cbo = curwp->w_doto - 1;
depth = 0; /* init nesting depth */
for (;;)
{
if (cbo == 0)
{ /* beginning of line */
clp = lback(clp);
if (clp == curbp->b_linep)
return (FALSE);
cbo = llength(clp)+1;
}
if (--cbo == llength(clp)) /* end of line */
c = '\n';
else
c = lgetc(clp,cbo); /* somewhere in middle */
/* Check for a matching character. If still in a nested */
/* level, pop out of it and continue search. This check */
/* is done before the nesting check so single-character */
/* matches will work too. */
if (c == lbal)
{
if (depth == 0)
{
displaymatch(clp,cbo);
return (TRUE);
}
else
depth--;
}
/* Check for another level of nesting. */
if (c == rbal)
depth++;
}
/*NOTREACHED*/
}
/*
* Display matching character.
* Matching characters that are not in the current window
* are displayed in the echo line. If in the current
* window, move dot to the matching character,
* sit there a while, then move back.
*/
static displaymatch(clp, cbo)
register LINE *clp;
register int cbo;
{
register LINE *tlp;
register int tbo;
register int cp;
register int bufo;
register int c;
int inwindow;
char buf[NLINE];
/* Figure out if matching char is in current window by */
/* searching from the top of the window to dot. */
inwindow = FALSE;
for (tlp = curwp->w_linep; tlp != lforw(curwp->w_dotp); tlp = lforw(tlp))
if (tlp == clp)
inwindow = TRUE;
if (inwindow == TRUE)
{
tlp = curwp->w_dotp; /* save current position */
tbo = curwp->w_doto;
curwp->w_dotp = clp; /* move to new position */
curwp->w_doto = cbo;
curwp->w_flag |= WFMOVE;
update(); /* show match */
sleep(1); /* wait a bit */
curwp->w_dotp = tlp; /* return to old position */
curwp->w_doto = tbo;
curwp->w_flag |= WFMOVE;
update();
}
else
{ /* match not in this window so display line in echo area */
bufo = 0;
for (cp = 0; cp < llength(clp); cp++)
{ /* expand tabs */
c = lgetc(clp,cp);
if (
#ifdef NOTAB
(mode&MNOTAB) ||
#endif
c != '\t')
if(ISCTRL(c))
{
buf[bufo++] = '^';
buf[bufo++] = c ^ 0x40;
} else buf[bufo++] = c;
else
do {
buf[bufo++] = ' ';
} while (bufo & 7);
}
buf[bufo++] = '\0';
ewprintf("Matches %s",buf);
}
return (TRUE);
}
#endif
\Rogue\Monster\
else
echo "will not over write ./match.c"
fi
if `test ! -s ./newlog.c`
then
echo "writing ./newlog.c"
cat > ./newlog.c << '\Rogue\Monster\'
/*************************************************************************
*
* newlog - set up a header for a new log entry
*
**************************************************************************/
#ifdef MISLOG
#include "def.h"
#include <stdio.h>
#include <pwd.h>
#include <time.h>
int newlog( f, n, k)
int f, n, k;
{
FILE *fp, *fopen();
struct passwd *pw_entry, *getpwnam();
char *fs_file, basename[80], author[80], date[80],
*getlogin(), *asctime(), *login_name, buf[80],
*tmpnam();
struct tm *timenow, *localtime();
long clock, time();
int n;
login_name = getlogin();
pw_entry = getpwnam(login_name);
strcpy(author, pw_entry->pw_gecos);
clock = time((long *) 0);
timenow = localtime(&clock);
fs_file = tmpnam();
fp = fopen(fs_file, "w");
sprintf(date, "%s", asctime(timenow));
fprintf(fp,
"----------------------------------------------------------------------\n");
date[strlen(date) - 1] = '\0';
fprintf(fp, "%s %s\n\n", date, author);
fclose(fp);
gotoeob( FALSE, 0, 0);
insertfile( fs_file, (char *)0);
unlink( fs_file);
gotoeob( FALSE, 0, 0);
return TRUE;
}
#endif
\Rogue\Monster\
else
echo "will not over write ./newlog.c"
fi
if `test ! -s ./paragraph.c`
then
echo "writing ./paragraph.c"
cat > ./paragraph.c << '\Rogue\Monster\'
/*
* Code for dealing with paragraphs and filling. Adapted from MicroEMACS 3.6
* and GNU-ified by mwm at ucbvax. Several bug fixes by blarson at usc-oberon.
*/
#include "def.h"
static int fillcol = 70 ;
#define MAXWORD 256
/*
* go back to the begining of the current paragraph
* here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
* combination to delimit the begining of a paragraph
*/
/*ARGSUSED*/
gotobop(f, n, k)
{
register int suc; /* success of last backchar */
if (n < 0) /* the other way...*/
return(gotoeop(f, -n, KRANDOM));
while (n-- > 0)
{ /* for each one asked for */
/* first scan back until we are in a word */
suc = backchar(FALSE, 1, KRANDOM);
while (!inword() && suc)
suc = backchar(FALSE, 1, KRANDOM);
curwp->w_doto = 0; /* and go to the B-O-Line */
/* and scan back until we hit a <NL><SP> <NL><TAB> or <NL><NL> */
while (lback(curwp->w_dotp) != curbp->b_linep)
if (llength(lback(curwp->w_dotp))
&& lgetc(curwp->w_dotp,0) != ' '
&& lgetc(curwp->w_dotp,0) != '\t')
curwp->w_dotp = lback(curwp->w_dotp);
else
break;
}
curwp->w_flag |= WFMOVE; /* force screen update */
return TRUE;
}
/*
* 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 begining of a paragraph
*/
/*ARGSUSED*/
gotoeop(f, n, k)
{
register int suc; /* success of last backchar */
if (n < 0) /* the other way...*/
return(gotobop(f, -n, KRANDOM));
while (n-- > 0)
{ /* for each one asked for */
/* Find the first word on/after the current line */
curwp->w_doto = 0;
suc = forwchar(FALSE, 1, KRANDOM);
while (!inword() && suc)
suc = forwchar(FALSE, 1, KRANDOM);
curwp->w_doto = 0;
if (curwp->w_dotp == curbp->b_linep)
break; /* check for eob */
curwp->w_dotp = lforw(curwp->w_dotp);
/* and scan forword until we hit a <NL><SP> or ... */
while (curwp->w_dotp != curbp->b_linep)
{
if (llength(curwp->w_dotp)
&& lgetc(curwp->w_dotp,0) != ' '
&& lgetc(curwp->w_dotp,0) != '\t')
curwp->w_dotp = lforw(curwp->w_dotp);
else
break;
}
}
curwp->w_flag |= WFMOVE; /* force screen update */
return TRUE;
}
/*
* Fill the current paragraph according to the current
* fill column
*/
/*ARGSUSED*/
fillpara(f, n, k)
{
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 eopflag; /* Are we at the End-Of-Paragraph? */
int firstflag; /* first word? (needs no space) */
int newlength; /* tentative new line length */
int eolflag; /* was at end of line */
LINE *eopline; /* pointer to line just past EOP */
char wbuf[MAXWORD]; /* buffer for current word */
int old_mode; /* saved mode value */
/* save the mode and put into insert mode for duration of fill */
old_mode = mode;
mode &= !MOVRSTK;
/* record the pointer to the line just past the EOP */
(VOID) gotoeop(FALSE, 1, KRANDOM);
eopline = curwp->w_dotp;
/* and back top the begining of the paragraph */
(VOID) gotobop(FALSE, 1, KRANDOM);
/* initialize various info */
i = TRUE;
while (i == TRUE && !inword())
i = forwchar(FALSE, 1, KRANDOM);
clength = curwp->w_doto;
wordlen = 0;
/* scan through lines, filling words */
firstflag = TRUE;
eopflag = FALSE;
while (!eopflag)
{
/* get the next character in the paragraph */
if (eolflag=(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 */
if (ldelete((RSIZE) 1, KNONE) == FALSE)
{
mode = old_mode;
return FALSE ;
}
/* if not a separator, just add it in */
if (c != ' ' && c != '\t')
{
if (wordlen < MAXWORD - 1)
wbuf[wordlen++] = c;
else
{
/* You loose chars beyond MAXWORD if the word
* is to long. I'm to lazy to fix it now; it
* just silently truncated the word before, so
* I get to feel smug.
*/
ewprintf("Word too long!");
}
}
else if (wordlen)
{
/* calculate tenatitive new length with word added */
newlength = clength + 1 + wordlen;
/* if at end of line or at doublespace and previous
* character was one of '.','?','!' doublespace here.
*/
if((eolflag || curwp->w_doto==llength(curwp->w_dotp)
|| (c=lgetc(curwp->w_dotp,curwp->w_doto))==' '
|| c=='\t')
&& ISEOSP(wbuf[wordlen-1])
&& wordlen<MAXWORD-1)
wbuf[wordlen++] = ' ';
/* at a word break with a word waiting */
if (newlength <= fillcol)
{
/* add word to current line */
if (!firstflag)
{
(VOID) linsert((RSIZE) 1, ' ');
++clength;
}
firstflag = FALSE;
}
else
{
if(curwp->w_doto > 0 &&
lgetc(curwp->w_dotp,curwp->w_doto-1)==' ')
{
curwp->w_doto -= 1;
(VOID) ldelete((RSIZE) 1, KNONE);
}
/* start a new line */
(VOID) lnewline();
clength = 0;
}
/* and add the word in in either case */
for (i=0; i<wordlen; i++)
{
(VOID) linsert((RSIZE) 1, wbuf[i]);
++clength;
}
wordlen = 0;
}
}
/* and add a last newline for the end of our new paragraph */
(VOID) lnewline();
/* we realy should wind up where we started, (which is hard to keep
* track of) but I think the end of the last line is better than the
* begining of the blank line. */
(VOID) backchar(FALSE, 1, KRANDOM);
mode = old_mode;
return TRUE;
}
/* delete n paragraphs starting with the current one */
/*ARGSUSED*/
killpara(f, n, k)
{
register int status; /* returned status of functions */
while (n--)
{ /* for each paragraph to delete */
/* mark out the end and begining of the para to delete */
(VOID) gotoeop(FALSE, 1, KRANDOM);
/* set the mark here */
curwp->w_markp = curwp->w_dotp;
curwp->w_marko = curwp->w_doto;
/* go to the begining of the paragraph */
(VOID) gotobop(FALSE, 1, KRANDOM);
curwp->w_doto = 0; /* force us to the begining of line */
/* and delete it */
if ((status = killregion(FALSE, 1, KRANDOM)) != TRUE)
return(status);
/* and clean up the 2 extra lines */
(VOID) ldelete((RSIZE) 1, KFORW);
}
return(TRUE);
}
/*
* check to see if we're past fillcol, and if so,
* justify this line. As a last step, justify the line.
*/
/*ARGSUSED*/
fillword(f, n, k)
{
register char c;
register int col, i, nce;
for (i = col = 0; col <= fillcol; ++i, ++col)
{
if (i == curwp->w_doto) return selfinsert(f, n, k) ;
c = lgetc(curwp->w_dotp, i);
if (
#ifdef NOTAB
!(mode&MNOTAB) &&
#endif
c == '\t') col |= 0x07;
else if (ISCTRL(c) != FALSE) ++col;
}
if (curwp->w_doto != llength(curwp->w_dotp))
{
(VOID) selfinsert(f, n, k);
nce = llength(curwp->w_dotp) - curwp->w_doto;
}
else nce = 0;
curwp->w_doto = i;
if ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' && c != '\t')
do {
(VOID) backchar(FALSE, 1, KRANDOM);
} while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' '
&& c != '\t' && curwp->w_doto > 0);
if (curwp->w_doto == 0)
do {
(VOID) forwchar(FALSE, 1, KRANDOM);
} while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' '
&& c != '\t' && curwp->w_doto < llength(curwp->w_dotp));
(VOID) delwhite(FALSE, 1, KRANDOM);
(VOID) lnewline();
curwp->w_doto = llength(curwp->w_dotp) - nce;
curwp->w_flag |= WFMOVE;
if (nce == 0 && curwp->w_doto != 0) return fillword(f, n, k);
return TRUE;
}
/* Set fill column to n. */
/*ARGSUSED*/
setfillcol(f, n, k)
{
extern int getcolpos() ;
fillcol = ((f == FALSE) ? getcolpos() : n);
if (kbdmop == NULL)
ewprintf("Fill column set to %d", fillcol);
return(TRUE);
}
\Rogue\Monster\
else
echo "will not over write ./paragraph.c"
fi
if `test ! -s ./prefix.c`
then
echo "writing ./prefix.c"
cat > ./prefix.c << '\Rogue\Monster\'
/*
* This code is a kludge for the two prefix sequences from GNU (well,
* the two I want) that uemacs doesn't have. Rather than quadruple the table
* space for keys, plus have to test for them everywhere, I'll just kludge
* it with functions that are bound to those keys. Later, maybe I'll do
* prefixes right.
*/
#include "def.h"
#ifndef TINY
/*ARGSUSED*/
ctlx4hack(f, n, k)
{
register KEY c;
if ((c = getkey(KPROMPT)) == 'b' || c == 'B')
return poptobuffer(f, n, KRANDOM);
if (c == 'f' || c == (KCTRL|'F') || c == 'F')
return poptofile(f, n, KRANDOM);
if (c == (KCTRL|'G') || c == (KCTLX|KCTRL|'G')
|| c == (KMETA|KCTRL|'G'))
{
(VOID) ctrlg(FALSE, 1, KRANDOM);
return ABORT;
}
return FALSE;
}
/*ARGSUSED*/
help(f, n, k)
{
register KEY c;
c = getkey(KPROMPT);
while (c == (KCTRL|'H'))
{
ewprintf("B C: ");
c = getkey(0);
}
if (c == 'b' || c == 'B')
return wallchart(f, n, KRANDOM);
if (c == 'c' || c == 'C')
return desckey(f, n, KRANDOM);
if (c == (KCTRL|'G') || c == (KCTLX|KCTRL|'G')
|| c == (KMETA|KCTRL|'G'))
{
(VOID) ctrlg(FALSE, 1, KRANDOM);
return ABORT;
}
return FALSE;
}
#endif
\Rogue\Monster\
else
echo "will not over write ./prefix.c"
fi
if `test ! -s ./random.c`
then
echo "writing ./random.c"
cat > ./random.c << '\Rogue\Monster\'
/*
* Assorted commands.
* The file contains the command
* processors for a large assortment of unrelated
* commands. The only thing they have in common is
* that they are all command processors.
*/
#include "def.h"
/*
* Display a bunch of useful information about
* the current location of dot. The character under the
* cursor (in octal), the current line, row, and column, and
* approximate position of the cursor in the file (as a percentage)
* is displayed. The column position assumes an infinite position
* display; it does not truncate just because the screen does.
* This is normally bound to "C-X =".
*/
/*ARGSUSED*/
showcpos(f, n, k)
{
register LINE *clp;
register long nchar;
long cchar;
register int nline, row;
int cline, cbyte; /* Current line/char/byte */
int ratio;
KEY keychar();
clp = lforw(curbp->b_linep); /* Collect the data. */
nchar = 0;
nline = 0;
for (;;)
{
++nline; /* Count this line */
if (clp == curwp->w_dotp)
{
cline = nline; /* Mark line */
cchar = nchar + curwp->w_doto;
if (curwp->w_doto == llength(clp))
cbyte = '\n';
else
cbyte = lgetc(clp, curwp->w_doto);
}
nchar += llength(clp) + 1; /* Now count the chars */
if (clp == curbp->b_linep) break ;
clp = lforw(clp);
}
row = curwp->w_toprow; /* Determine row. */
clp = curwp->w_linep;
while (clp!=curbp->b_linep && clp!=curwp->w_dotp)
{
++row;
clp = lforw(clp);
}
++row; /* Convert to origin 1. */
/*NOSTRICT*/
/* nchar can't be zero (because of the "bonus" \n at end of file) */
ratio = (100L*cchar) / nchar;
ewprintf("Char: %c (0%o) point=%ld(%d%%) line=%d row=%d col=%d",
(int) keychar(cbyte, FALSE), cbyte, cchar, ratio, cline, row,
getcolpos());
return (TRUE);
}
getcolpos()
{
register int col, i, c;
col = 0; /* Determine column. */
for (i=0; i<curwp->w_doto; ++i)
{
c = lgetc(curwp->w_dotp, i);
if (
#ifdef NOTAB
!(mode & MNOTAB) &&
#endif
c == '\t')
col |= 0x07;
else if (ISCTRL(c) != FALSE)
++col;
++col;
}
return col + 1; /* Convert to origin 1. */
}
/*
* Ordinary text characters are bound to this function,
* which inserts them into the buffer. Characters marked as control
* characters (using the CTRL flag) may be remapped to their ASCII
* equivalent. This makes TAB (C-I) work right, and also makes the
* world look reasonable if a control character is bound to this
* this routine by hand. Any META or CTLX flags on the character
* are discarded. This is the only routine that actually looks
* the the "k" argument.
*/
/*ARGSUSED*/
selfinsert(f, n, k)
{
register int c;
if (n < 0)
return (FALSE);
if (n == 0)
return (TRUE);
c = k & KCHAR;
if ((k&KCTRL)!=0 && c>='@' && c<='_') /* ASCII-ify. */
c -= '@';
return (linsert((RSIZE) n, c));
}
/*
* Open up some blank space. The basic plan
* is to insert a bunch of newlines, and then back
* up over them. Everything is done by the subcommand
* procerssors. They even handle the looping. Normally
* this is bound to "C-O".
*/
/*ARGSUSED*/
openline(f, n, k)
{
register int i;
register int s;
if (n < 0)
return (FALSE);
if (n == 0)
return (TRUE);
gotobol( FALSE, 0, KRANDOM);
i = n; /* Insert newlines. */
do {
s = lnewline();
} while (s==TRUE && --i);
if (s == TRUE) /* Then back up overtop */
s = backchar(f, n, KRANDOM); /* of them all. */
return (s);
}
/*
* Insert a newline.
* If you are at the end of the line and the
* next line is a blank line, just move into the
* blank line. This makes "C-O" and "C-X C-O" work
* nicely, and reduces the ammount of screen
* update that has to be done. This would not be
* as critical if screen update were a lot
* more efficient.
*/
/*ARGSUSED*/
newline(f, n, k)
{
register LINE *lp;
register int s;
if (n < 0)
return (FALSE);
while (n--)
{
lp = curwp->w_dotp;
if (llength(lp) == curwp->w_doto
&& lp != curbp->b_linep
&& llength(lforw(lp)) == 0)
{
if ((s=forwchar(FALSE, 1, KRANDOM)) != TRUE)
return (s);
} else if ((s=lnewline()) != TRUE)
return (s);
}
return (TRUE);
}
/*
* Delete any whitespace around dot.
*/
/*ARGSUSED*/
delwhite(f, n, k)
{
register int col, c, s;
col = curwp->w_doto;
while ((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
++col;
do
if ((s = backchar(FALSE, 1, KRANDOM)) == FALSE) break;
while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t') ;
if (s == TRUE) (VOID) forwchar(FALSE, 1, KRANDOM);
(VOID) ldelete((RSIZE)(col - curwp->w_doto), KNONE);
return (TRUE);
}
/*
* Delete forward. This is real
* easy, because the basic delete routine does
* all of the work. Watches for negative arguments,
* and does the right thing. If any argument is
* present, it kills rather than deletes, to prevent
* loss of text if typed with a big argument.
* Normally bound to "C-D".
*/
/*ARGSUSED*/
forwdel(f, n, k)
{
if (n < 0)
return (backdel(f, -n, KRANDOM));
if (f != FALSE)
{ /* Really a kill. */
if ((lastflag&CFKILL) == 0)
kdelete();
thisflag |= CFKILL;
}
return (ldelete((RSIZE) n, f ? KFORW : KNONE));
}
/*
* Delete backwards. This is quite easy too,
* because it's all done with other functions. Just
* move the cursor back, and delete forwards.
* Like delete forward, this actually does a kill
* if presented with an argument.
*/
/*ARGSUSED*/
backdel(f, n, k)
{
register int s;
if (n < 0)
return (forwdel(f, -n, KRANDOM));
if (f != FALSE)
{ /* Really a kill. */
if ((lastflag&CFKILL) == 0)
kdelete();
thisflag |= CFKILL;
}
if ((s=backchar(f, n, KRANDOM)) == TRUE)
s = ldelete((RSIZE) n, f ? KFORW : KNONE);
return (s);
}
/*
* Kill line. If called without an argument,
* it kills from dot to the end of the line, unless it
* is at the end of the line, when it kills the newline.
* If called with an argument of 0, it kills from the
* start of the line to dot. If called with a positive
* argument, it kills from dot forward over that number
* of newlines. If called with a negative argument it
* kills any text before dot on the current line,
* then it kills back abs(arg) lines.
*/
/*ARGSUSED*/
killline(f, n, k)
{
register RSIZE chunk;
register LINE *nextp;
register int i, c;
if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
kdelete(); /* last wasn't a kill. */
thisflag |= CFKILL;
if (f == FALSE)
{
for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
break;
if (i == llength(curwp->w_dotp))
chunk = llength(curwp->w_dotp)-curwp->w_doto + 1;
else
{
chunk = llength(curwp->w_dotp)-curwp->w_doto;
if (chunk == 0)
chunk = 1;
}
}
else if (n > 0)
{
chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
nextp = lforw(curwp->w_dotp);
i = n;
while (--i)
{
if (nextp == curbp->b_linep)
break;
chunk += llength(nextp)+1;
nextp = lforw(nextp);
}
}
else
{ /* n <= 0 */
chunk = curwp->w_doto;
curwp->w_doto = 0;
i = n;
while (i++)
{
if (lback(curwp->w_dotp) == curbp->b_linep)
break;
curwp->w_dotp = lback(curwp->w_dotp);
curwp->w_flag |= WFMOVE;
chunk += llength(curwp->w_dotp)+1;
}
}
/*
* KFORW here is a bug. Should be KBACK/KFORW, but we need to
* rewrite the ldelete code (later)?
*/
return (ldelete(chunk, KFORW));
}
/*
* Commands to toggle the five modes. Without an argument, sets the
* mode on, with an argument, sets the mode off.
*/
/*ARGSUSED*/
bsmapmode(f, n, k)
{
if ((mode&MBSMAP) != MBSMAP)
mode |= MBSMAP;
else
mode &= ~MBSMAP;
upmodes((BUFFER *) NULL);
return TRUE;
}
/*ARGSUSED*/
flowmode(f, n, k)
{
if ((mode&MFLOW) != MFLOW)
mode |= MFLOW;
else
mode &= ~MFLOW;
upmodes((BUFFER *) NULL);
return TRUE;
}
/*ARGSUSED*/
fillmode(f, n, k)
{
if ((mode&MFILL) != MFILL)
{
mode |= MFILL;
if ((binding[' '] = symlookup("insert-with-wrap")) == NULL)
panic("no insert-with-wrap in fillmode");
} else
{
mode &= ~MFILL;
if ((binding[' '] = symlookup("self-insert-command")) == NULL)
panic("no self-insert-command in fillmode");
}
upmodes((BUFFER *) NULL);
return TRUE;
}
#ifdef NOTAB
space_tabpos(f, n, k)
int f, n;
{
int stat;
if(n<0)
return FALSE;
if(n==0)
return TRUE;
return linsert(((RSIZE)n<<3) - (curwp->w_doto & 7), ' ');
}
notabmode(f, n, k)
{
if((mode&MNOTAB) != MNOTAB)
{
mode |= MNOTAB;
if ((binding[KCTRL|'I'] = symlookup("space-to-tabstop")) == NULL)
panic("no space-to-tabstop in notabmode");
}
else
{
mode &= ~ MNOTAB;
if ((binding[KCTRL|'I'] = symlookup("self-insert-command")) == NULL)
panic("no self-insert-command in notabmode");
}
upmodes((BUFFER *) NULL);
return TRUE;
}
#endif
/*
* This function toggles the state of the
* insert/overstrike flag. The editor will come up in
* one mode or the other, and can be changed by this
* function. No argument or 0 will toggle the value, >0 will
* set to insert mode, <0 will set to overstrike.
*/
/*ARGSUSED*/
insovrmode( f, n, k)
{
if (f == FALSE || n == 0)
{
if ((mode & MOVRSTK) == MOVRSTK)
mode &= ~MOVRSTK;
else
mode |= MOVRSTK;
}
else if (n > 0)
mode &= ~MOVRSTK;
else
mode |= MOVRSTK;
upmodes((BUFFER *) NULL);
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. The blank
* lines are inserted with a call to "newline"
* instead of a call to "lnewline" so that the magic
* stuff that happens when you type a carriage
* return also happens when a carriage return is
* yanked back from the kill buffer.
* An attempt has been made to fix the cosmetic bug
* associated with a yank when dot is on the top line of
* the window (nothing moves, because all of the new
* text landed off screen).
*/
/*ARGSUSED*/
yank(f, n, k)
{
register int c;
register int i;
register LINE *lp;
register int nline;
if (n < 0)
return (FALSE);
nline = 0; /* Newline counting. */
while (n--) {
isetmark(); /* mark around last yank */
i = 0;
while ((c=kremove(i)) >= 0) {
if (c == '\n') {
if (newline(FALSE, 1, KRANDOM) == FALSE)
return (FALSE);
++nline;
} else {
if (linsert((RSIZE) 1, c) == FALSE)
return (FALSE);
}
++i;
}
}
lp = curwp->w_linep; /* Cosmetic adjustment */
if (curwp->w_dotp == lp) { /* if offscreen insert. */
while (nline-- && lback(lp)!=curbp->b_linep)
lp = lback(lp);
curwp->w_linep = lp; /* Adjust framing. */
curwp->w_flag |= WFHARD;
}
return (TRUE);
}
\Rogue\Monster\
else
echo "will not over write ./random.c"
fi
echo "Finished archive 2 of 5"
exit
--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Mark A. Hargrove U.S. TeleCenters
Voice: 408-496-1800 Santa Clara, CA
uucp : {dual, hoptoad, hplabs, portal, ptsfa}!well!ustel
More information about the Comp.sources.misc
mailing list