static char rcsid[] = "$Id: basic.c,v 1.1 1992/10/03 01:35:00 mike Exp $"; /* $Log: basic.c,v $ * Revision 1.1 1992/10/03 01:35:00 mike * Initial revision * */ /* * BASIC.C MODULE * * The routines in this file move the cursor around on the screen. They * compute a new value for the cursor, then adjust dot. 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. */ /* Copyright 1990, 1991, 1992 Craig Durland * Distributed under the terms of the GNU General Public License. * Distributed "as is", without warranties of any kind, but comments, * suggestions and bug reports are welcome. */ #include #include "me2.h" extern int curcol; /* Cursor column (in display.c) */ /* ******************************************************************** */ /* *********** Cursor movement **************************************** */ /* ******************************************************************** */ /* Move dot n lines. If 0 < n, move towards the end of the buffer, else * move towards the beginning. The dot is always left at the start of * a line. * Return: TRUE if all OK, FALSE if couldn't move that far. */ next_line(n) register int n; { register Line *lp; lp = the_dot->line; if (0 <= n) { register Line *last_line; last_line = BUFFER_LAST_LINE(curbp); while (lp != last_line && n--) lp = lforw(lp); } else { register Line *first_line; n = -n; first_line = BUFFER_FIRST_LINE(curbp); while (lp != first_line && n--) lp = lback(lp); } the_dot->line = lp; the_dot->offset = 0; dot_moved(); return (n <= 0); } int curgoal = 0; /* current goal column */ /* * Move the cursor to the beginning of the current line. Trivial. */ goto_BoL(f,n) { the_dot->offset = 0; return TRUE; } /* * Move the cursor to the end of the current line. Trivial. No errors. */ goto_EoL(f,n) { the_dot->offset = llength(the_dot->line); return TRUE; } /* * Move the cursor forward by n characters. If n is less than zero, move the * cursor backwards. * While backing up over each and every char would seem like a very * slow way of doing things, you usually only backup 1 char * and in practice I could not measure much difference between * calculated backup and looping (CD). * Returns: * TRUE: Everything went as expected. * FALSE: Tried to move out of the buffer. */ next_character(n) register int n; { if (n < 0) /* move backwards */ { while (n++) if (the_dot->offset == 0) /* at the start of the line */ { if (!next_line(-1)) return FALSE; /* hit BoB */ goto_EoL(FALSE,1); } else the_dot->offset--; } else /* move forwards */ { while (n--) if (the_dot->offset == llength(the_dot->line)) /* at end of line */ { if (!next_line(1)) return FALSE; } /* hit EoB */ else the_dot->offset++; } return TRUE; } /* * Move the cursor backwards by n characters. * Bound to "C-b". */ backchar(f,n) { return next_character(-n); } /* * Move the cursor forward by n characters. * Bound to "C-f". */ forwchar(f,n) { return next_character(n); } /* * Goto the beginning of the current 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-<". */ goto_BoB(f,n) int f,n; { the_dot->line = BUFFER_FIRST_LINE(curbp); the_dot->offset = 0; dot_moved(); 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->". */ goto_EoB(f,n) int f,n; { the_dot->line = BUFFER_LAST_LINE(curbp); the_dot->offset = 0; dot_moved(); return TRUE; } /* Goto the nth line of the current buffer. First line of the buffer is 1. * If n is negative, got the nth line from the end of the buffer. * Note that line 0 does not really exist so (goto-line 0) returns FALSE. * All that just to save one "if (n)". If you ignore the error, * (goto-line 0) is the same as (goto-line 1). * Returns: TRUE if the nth line exists, FALSE otherwise (and the dot is * left at one end of the buffer or the other). */ goto_line(n) { if (n < 0) goto_EoB(FALSE,0); /* goto end of buffer */ else { goto_BoB(FALSE,0); n--; } /* goto beginning of buffer */ return next_line(n); } /* * Move forward by full lines. If n<0 move backwards. * The last command controls how the goal column is set. * Bound to "C-n". * Return FALSE if try to move off end of buffer. */ forwline(f,n) int f,n; { /* Reset goal if last key not C-p or C-n*/ if ((lastflag & CFLINE) == 0) curgoal = curcol; thisflag |= CFLINE; n = next_line(n); the_dot->offset = getgoal(the_dot->line,curgoal); return n; } /* * This function is like "forwline", but goes backwards. * Error if try to move out of buffer. * Bound to "C-P". */ backline(f,n) { return forwline(f,-n); } /* * 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,goal) register Line *dlp; { register unsigned char c; register int newcol = 0, dbo = 0; while (dbo != llength(dlp)) { c = lgetc(dlp,dbo); if (c == '\t') newcol = NEXT_TAB_COLUMN_MINUS_1(newcol); else if (iscntrl(c)) ++newcol; /* control chars == 2 display chars */ if (++newcol>goal) break; ++dbo; } return dbo; }