291 lines
6.1 KiB
C
291 lines
6.1 KiB
C
/* This file is in the public domain. */
|
|
|
|
/*
|
|
* This file contains the command processing functions for a number of random
|
|
* commands. There is no functional grouping here, for sure.
|
|
*/
|
|
|
|
#include "estruct.h"
|
|
#include "edef.h"
|
|
|
|
extern void mlwrite();
|
|
extern void lchange(int);
|
|
extern int lnewline();
|
|
extern int linsert(int, int);
|
|
extern int backchar(int, int);
|
|
extern void kdelete();
|
|
extern int ldelete(int, int);
|
|
extern int kremove(int);
|
|
|
|
int setfillcol(int, int);
|
|
int getccol(int);
|
|
int twiddle(int, int);
|
|
int quote(int, int);
|
|
int tab(int, int);
|
|
int openline(int, int);
|
|
int newline(int, int);
|
|
int forwdel(int, int);
|
|
int backdel(int, int);
|
|
int killtext(int, int);
|
|
int yank(int, int);
|
|
|
|
/*
|
|
* Set fill column to n.
|
|
*/
|
|
int setfillcol(int f, int n)
|
|
{
|
|
fillcol = n;
|
|
mlwrite("[Fill column is %d]", n);
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* Return current column. Stop at first non-blank given TRUE argument.
|
|
*/
|
|
int getccol(int bflg)
|
|
{
|
|
int c, i, col;
|
|
|
|
col = 0;
|
|
for (i = 0; i < curwp->w_doto; ++i)
|
|
{
|
|
c = lgetc(curwp->w_dotp, i);
|
|
if (c != ' ' && c != '\t' && bflg)
|
|
break;
|
|
if (c == '\t')
|
|
col |= 0x07;
|
|
else if (c < 0x20 || c == 0x7F)
|
|
++col;
|
|
++col;
|
|
}
|
|
return (col);
|
|
}
|
|
|
|
/*
|
|
* Twiddle the two characters on either side of dot. If dot is at the end of
|
|
* the line twiddle the two characters before it. Return with an error if dot
|
|
* is at the beginning of line; it seems to be a bit pointless to make this
|
|
* work. This fixes up a very common typo with a single stroke. Normally bound
|
|
* to "C-T". This always works within a line, so "WFEDIT" is good enough
|
|
*/
|
|
int twiddle(int f, int n)
|
|
{
|
|
LINE *dotp;
|
|
int doto, cl, cr;
|
|
|
|
dotp = curwp->w_dotp;
|
|
doto = curwp->w_doto;
|
|
if (doto == llength(dotp) && --doto < 0)
|
|
return (FALSE);
|
|
cr = lgetc(dotp, doto);
|
|
if (--doto < 0)
|
|
return (FALSE);
|
|
cl = lgetc(dotp, doto);
|
|
lputc(dotp, doto + 0, cr);
|
|
lputc(dotp, doto + 1, cl);
|
|
lchange(WFEDIT);
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* Quote the next character, and insert it into the buffer. All the characters
|
|
* are taken literally, with the exception of the newline, which always has
|
|
* its line splitting meaning. The character is always read, even if it is
|
|
* inserted 0 times, for regularity. Bound to "C-Q"
|
|
*/
|
|
int quote(int f, int n)
|
|
{
|
|
int s, c;
|
|
|
|
c = (*term.t_getchar) ();
|
|
if (n < 0)
|
|
return (FALSE);
|
|
if (n == 0)
|
|
return (TRUE);
|
|
if (c == '\n')
|
|
{
|
|
do
|
|
{
|
|
s = lnewline();
|
|
}
|
|
while (s == TRUE && --n);
|
|
return (s);
|
|
}
|
|
return (linsert(n, c));
|
|
}
|
|
|
|
/*
|
|
* Insert a tab into file.
|
|
* Bound to "C-I"
|
|
*/
|
|
int tab(int f, int n)
|
|
{
|
|
if (n < 0)
|
|
return (FALSE);
|
|
return (linsert(n, 9));
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
* processors. They even handle the looping. Normally this is bound to "C-O"
|
|
*/
|
|
int openline(int f, int n)
|
|
{
|
|
int i, s;
|
|
|
|
if (n < 0)
|
|
return (FALSE);
|
|
if (n == 0)
|
|
return (TRUE);
|
|
i = n; /* Insert newlines */
|
|
do
|
|
{
|
|
s = lnewline();
|
|
}
|
|
while (s == TRUE && --i);
|
|
if (s == TRUE) /* Then back up overtop */
|
|
s = backchar(f, n); /* of them all */
|
|
return (s);
|
|
}
|
|
|
|
/*
|
|
* Insert a newline. Bound to "C-M".
|
|
*/
|
|
int newline(int f, int n)
|
|
{
|
|
int s;
|
|
|
|
if (n < 0)
|
|
return (FALSE);
|
|
|
|
/* insert some lines */
|
|
while (n--)
|
|
{
|
|
if ((s = lnewline()) != TRUE)
|
|
return (s);
|
|
}
|
|
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"
|
|
*/
|
|
int forwdel(int f, int n)
|
|
{
|
|
if (n < 0)
|
|
return (backdel(f, -n));
|
|
if (f != FALSE)
|
|
{ /* Really a kill */
|
|
if ((lastflag & CFKILL) == 0)
|
|
kdelete();
|
|
thisflag |= CFKILL;
|
|
}
|
|
return (ldelete(n, f));
|
|
}
|
|
|
|
/*
|
|
* 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. Bound to
|
|
* both "RUBOUT" and "C-H"
|
|
*/
|
|
int backdel(int f, int n)
|
|
{
|
|
int s;
|
|
|
|
if (n < 0)
|
|
return (forwdel(f, -n));
|
|
if (f != FALSE)
|
|
{ /* Really a kill */
|
|
if ((lastflag & CFKILL) == 0)
|
|
kdelete();
|
|
thisflag |= CFKILL;
|
|
}
|
|
if ((s = backchar(f, n)) == TRUE)
|
|
s = ldelete(n, f);
|
|
return (s);
|
|
}
|
|
|
|
/*
|
|
* Kill text. 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
|
|
* backwards that number of newlines. Normally bound to "C-K"
|
|
*/
|
|
int killtext(int f, int n)
|
|
{
|
|
LINE *nextp;
|
|
int chunk;
|
|
|
|
if ((lastflag & CFKILL) == 0)/* Clear kill buffer if last wasn't a kill */
|
|
kdelete();
|
|
thisflag |= CFKILL;
|
|
if (f == FALSE)
|
|
{
|
|
chunk = llength(curwp->w_dotp) - curwp->w_doto;
|
|
if (chunk == 0)
|
|
chunk = 1;
|
|
}
|
|
else if (n == 0)
|
|
{
|
|
chunk = curwp->w_doto;
|
|
curwp->w_doto = 0;
|
|
}
|
|
else if (n > 0)
|
|
{
|
|
chunk = llength(curwp->w_dotp) - curwp->w_doto + 1;
|
|
nextp = lforw(curwp->w_dotp);
|
|
while (--n)
|
|
{
|
|
if (nextp == curbp->b_linep)
|
|
return (FALSE);
|
|
chunk += llength(nextp) + 1;
|
|
nextp = lforw(nextp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mlwrite("neg kill");
|
|
return (FALSE);
|
|
}
|
|
return (ldelete(chunk, 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"
|
|
*/
|
|
int yank(int f, int n)
|
|
{
|
|
int c, i;
|
|
|
|
if (n < 0)
|
|
return (FALSE);
|
|
while (n--)
|
|
{
|
|
i = 0;
|
|
while ((c = kremove(i)) >= 0)
|
|
{
|
|
if (c == '\n')
|
|
{
|
|
if (lnewline(FALSE, 1) == FALSE)
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
if (linsert(1, c) == FALSE)
|
|
return (FALSE);
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|