ftp.nice.ch/pub/next/unix/editor/me.3.10.N.bs.tar.gz#/me-3.10.N.bs/src/basic.c

This is basic.c in view mode; [Download] [Up]

/*
 * 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	<stdio.h>
#include	"estruct.h"
#include	"etype.h"
#include	"edef.h"
#include	"elang.h"

/*
 * Move the cursor to the
 * beginning of the current line.
 * Trivial.
 */
PASCAL NEAR 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.
 */
PASCAL NEAR 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.
 */
PASCAL NEAR 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.
 */
PASCAL NEAR 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);
}

PASCAL NEAR 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(TEXT7, arg, NSTRING)) != TRUE) {
/*                                    "Line to GOTO: " */
			mlwrite(TEXT8);
/*                              "[Aborted]" */
			return(status);
		}
		n = asc_int(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-<".
 */
PASCAL NEAR 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->".
 */
PASCAL NEAR gotoeob(f, n)
{
        curwp->w_dotp  = curbp->b_linep;
        curwp->w_doto  = 0;
        curwp->w_flag |= WFHARD;
        return(TRUE);
}

#if	KEEPPOS

/*
 * Move to the top of the screen.  The standsrd screen code does most of the
 * hard parts of update.
 *
 */
PASCAL NEAR gotobos(f, n)
{
        curwp->w_dotp  = curwp->w_linep;
        curwp->w_doto  = 0;
        curwp->w_flag |= WFHARD;
        return(TRUE);
} /* gotobos */


/*
 * Goto the end of the screen.
 */
PASCAL NEAR gotoeos(f, n)
{
register LINE   *lp;
int	currow;

	lp = curwp->w_linep;
	currow = curwp->w_ntrows - 1;
        while (currow-- && lp!=curbp->b_linep) lp = lforw(lp);
        curwp->w_dotp  = lp;
        curwp->w_doto  = 0;
        curwp->w_flag |= WFHARD;
        return(TRUE);
} /* gotoeos */

#endif


/*
 * 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.
 */
PASCAL NEAR 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".
 */
PASCAL NEAR 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
PASCAL NEAR 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 &&
			    lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
			    lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
				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);
}

PASCAL NEAR 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 &&
			    lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
			    lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
				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".
 */
PASCAL NEAR 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 += -(newcol % tabsize) + (tabsize - 1);
                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.
 */
PASCAL NEAR forwpage(f, n)
register int    n;
{
        register LINE   *lp;

#if	KEEPPOS
	int	currow;
        register LINE   *lp1;
#endif

        if (f == FALSE) {
                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;
        
#if	KEEPPOS
        if ((lastflag&CFCPCN) == 0)
                curgoal = getccol(FALSE);
	/* flag this command as a line move */
        thisflag |= CFCPCN;
        lp1 = lp;
        currow = 0;
        while (lp1 != curwp->w_dotp ) {
        	currow++;
        	lp1 = lforw(lp1);
        }
#endif

        while (n-- && lp!=curbp->b_linep)
                lp = lforw(lp);
        curwp->w_linep = lp;

#if	KEEPPOS
	while (currow-- && lp!=curbp->b_linep) lp = lforw(lp);
	curwp->w_doto = getgoal(lp);
#else  
        curwp->w_doto  = 0;
#endif

        curwp->w_dotp  = lp;
        curwp->w_flag |= WFHARD;
        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.
 */
PASCAL NEAR backpage(f, n)

register int f;
register int n;

{
        register LINE   *lp;
        
#if	KEEPPOS
	int	currow;
        register LINE   *lp1;
#endif

        if (f == FALSE) {
                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;

#if	KEEPPOS
        if ((lastflag&CFCPCN) == 0)
                curgoal = getccol(FALSE);
	/* flag this command as a line move */
        thisflag |= CFCPCN;
        lp1 = lp;
        currow = 0;
        while (lp1 != curwp->w_dotp ) {
        	currow++;
        	lp1 = lforw(lp1);
        }
#endif

        while (n-- && lback(lp)!=curbp->b_linep)
                lp = lback(lp);
        curwp->w_linep = lp;
        
#if	KEEPPOS
        while (currow-- && lp!=curbp->b_linep) lp = lforw(lp);
	curwp->w_doto = getgoal(lp);
#else
        curwp->w_doto  = 0;
#endif

        curwp->w_dotp  = lp;
        curwp->w_flag |= WFHARD;
        return(TRUE);
}

/*
 * Set the mark in the current window to the value of "." in the window. No
 * errors are possible. Bound to "M-.".
 */
PASCAL NEAR setmark(f, n)
{
	/* make sure it is in range */
	if (f == FALSE)
		n = 0;
	n %= NMARKS;

        curwp->w_markp[n] = curwp->w_dotp;
        curwp->w_marko[n] = curwp->w_doto;
        mlwrite(TEXT9, n);
/*              "[Mark %d set]" */
        return(TRUE);
}

/*
 * Remove the mark in the current window.
 * Bound to ^X <space> 
 */
PASCAL NEAR remmark(f, n)
{
	/* make sure it is in range */
	if (f == FALSE)
		n = 0;
	n %= NMARKS;

        curwp->w_markp[n] = NULL;
        curwp->w_marko[n] = 0;
        mlwrite(TEXT10, n);
/*              "[Mark %d removed]" */
        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".
 */
PASCAL NEAR swapmark(f, n)
{
        register LINE   *odotp;
        register int    odoto;

	/* make sure it is in range */
	if (f == FALSE)
		n = 0;
	n %= NMARKS;

        if (curwp->w_markp[n] == NULL) {
                mlwrite(TEXT11, n);
/*                      "No mark %d in this window" */
                return(FALSE);
        }
        odotp = curwp->w_dotp;
        odoto = curwp->w_doto;
        curwp->w_dotp  = curwp->w_markp[n];
        curwp->w_doto  = curwp->w_marko[n];
        curwp->w_markp[n] = odotp;
        curwp->w_marko[n] = odoto;
        curwp->w_flag |= WFMOVE;
        return(TRUE);
}

/*
 * Goto a 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 "M-^G".
 */
PASCAL NEAR gotomark(f, n)

int f, n;	/* default and nemeric args */

{
	/* make sure it is in range */
	if (f == FALSE)
		n = 0;
	n %= NMARKS;

        if (curwp->w_markp[n] == NULL) {
                mlwrite(TEXT11, n);
/*                      "No mark %d in this window" */
                return(FALSE);
        }
        curwp->w_dotp  = curwp->w_markp[n];
        curwp->w_doto  = curwp->w_marko[n];
        curwp->w_flag |= WFMOVE;
        return(TRUE);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.