Files
retrobsd/src/cmd/emg/basic.c
Brian Callahan e050ac6ee6 Update to emg-2.0
2015-12-18 01:13:00 -05:00

290 lines
6.4 KiB
C

/* This file is in the public domain. */
/*
* 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.
*/
#include <stdlib.h> /* atoi(3), ugh */
#include "estruct.h"
#include "edef.h"
extern int getccol(int);
extern void mlwrite();
extern int mlreplyt();
int forwchar(int, int);
int backchar(int, int);
int forwline(int, int);
int backline(int, int);
int pagedown(int, int);
int pageup(int, int);
/*
* 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".
*/
long getgoal(LINE *dlp)
{
int col = 0;
int dbo = 0;
int newcol, c;
while (dbo != llength(dlp))
{
c = lgetc(dlp, dbo);
newcol = col;
if (c == '\t')
newcol |= 0x07;
else if (c < 0x20 || c == 0x7F)
++newcol;
++newcol;
if (newcol > curgoal)
break;
col = newcol;
++dbo;
}
return (dbo);
}
/*
* Move the cursor to the
* beginning of the current line.
* Trivial.
*/
/* ARGSUSED0 */
int gotobol(int f, int n)
{
curwp->w_doto = 0;
return (TRUE);
}
/*
* Move the cursor to the end of the current line. Trivial. No errors.
*/
/* ARGSUSED0 */
int gotoeol(int f, int n)
{
curwp->w_doto = llength(curwp->w_dotp);
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.
*/
int backchar(int f, int n)
{
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;
curwp->w_dotline--;
}
else
curwp->w_doto--;
}
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.
*/
int forwchar(int f, 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;
curwp->w_dotline++;
}
else
curwp->w_doto++;
}
return (TRUE);
}
/*
* move to a particular line. argument (n) must be a positive integer for this
* to actually do anything
*/
int gotoline(int f, int n)
{
if ((n < 1) || (n > curwp->w_bufp->b_lines)) /* if a bogus argument...then leave */
return (FALSE); /* but we should never get here */
/* first, we go to the start of the buffer */
curwp->w_dotp = lforw(curbp->b_linep);
curwp->w_doto = 0;
curwp->w_dotline = 0; /* and reset the line number */
return (forwline(f, n - 1));
}
/*
* Prompt for which line number we want to go to, then execute gotoline()
* with that number as its argument.
*
* Make sure the bounds are within the file.
*
* Bound to M-G
*/
int setline(int f, int n)
{
char setl[6];
int l;
(void)mlreplyt("Go to line: ", setl, 6, 10);
l = atoi(setl); /* XXX: This sucks! */
if (l < 1)
l = 1;
else if (l > curwp->w_bufp->b_lines)
l = curwp->w_bufp->b_lines;
gotoline(f, l);
return (TRUE);
}
/*
* 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-<".
*/
/* ARGSUSED0 */
int gotobob(int f, int n)
{
curwp->w_dotp = lforw(curbp->b_linep);
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
curwp->w_dotline = 0;
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->".
*/
/* ARGSUSED0 */
int gotoeob(int f, int n)
{
curwp->w_dotp = curbp->b_linep;
curwp->w_doto = 0;
curwp->w_flag |= WFHARD;
curwp->w_dotline = curwp->w_bufp->b_lines;
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.
*/
int forwline(int f, int n)
{
LINE *dlp;
if (n < 0)
return (backline(f, -n));
if ((lastflag & CFCPCN) == 0)/* Reset goal if last */
curgoal = getccol(FALSE); /* not C-P or C-N */
thisflag |= CFCPCN;
dlp = curwp->w_dotp;
while (n-- && dlp != curbp->b_linep)
{
dlp = lforw(dlp);
curwp->w_dotline++;
}
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".
*/
int backline(int f, int n)
{
LINE *dlp;
if (n < 0)
return (forwline(f, -n));
if ((lastflag & CFCPCN) == 0)/* Reset goal if the */
curgoal = getccol(FALSE); /* last isn't C-P, C-N */
thisflag |= CFCPCN;
dlp = curwp->w_dotp;
while (n-- && lback(dlp) != curbp->b_linep)
{
dlp = lback(dlp);
curwp->w_dotline--;
}
curwp->w_dotp = dlp;
curwp->w_doto = getgoal(dlp);
curwp->w_flag |= WFMOVE;
return (TRUE);
}
/*
* PgDn. Scroll down (rows / 2).
* Just forwline(f, (rows / 2))
* Bound to C-V
*/
int pagedown(int f, int n)
{
forwline(f, (rows / 2));
return (TRUE);
}
/*
* PgUp. Scroll up (rows / 2).
* Just backline(f, (rows / 2))
* Bound to M-V
*/
int pageup(int f, int n)
{
backline(f, (rows / 2));
return (TRUE);
}
/*
* Set the mark in the current window to the value of "." in the window. No
* errors are possible. Bound to "M-.".
*/
/* ARGSUSED0 */
int setmark(int f, int n)
{
curwp->w_markp = curwp->w_dotp;
curwp->w_marko = curwp->w_doto;
mlwrite("[Mark set]");
return (TRUE);
}