/* * 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 #include "ed.h" /* * Move the cursor to the * beginning of the current line. * Trivial. */ 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. */ 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. */ gotoeol(f, n) { curwp->w_doto = llength(curwp->w_dotp); return (TRUE); } /* * Move the cursor forwwards 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. */ 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); } /* * 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-<". */ 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->". */ gotoeob(f, n) { curwp->w_dotp = curbp->b_linep; curwp->w_doto = 0; curwp->w_flag |= WFHARD; 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. */ forwline(f, n) { register LINE *dlp; if (n < 0) return (backline(f, -n)); if ((lastflag&CFCPCN) == 0) /* Reset goal if last */ curgoal = curcol; /* not C-P or C-N */ thisflag |= CFCPCN; dlp = curwp->w_dotp; while (n-- && dlp!=curbp->b_linep) dlp = lforw(dlp); 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". */ backline(f, n) { register LINE *dlp; if (n < 0) return (forwline(f, -n)); if ((lastflag&CFCPCN) == 0) /* Reset goal if the */ curgoal = curcol; /* 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_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_flag |= WFMOVE; return (TRUE); } /* * 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) 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 |= 0x07; 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. */ forwpage(f, n) register int n; { register LINE *lp; 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; while (n-- && lp!=curbp->b_linep) lp = lforw(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; 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. */ backpage(f, n) register int n; { register LINE *lp; 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; while (n-- && lback(lp)!=curbp->b_linep) lp = lback(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; 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-.". */ setmark(f, n) { curwp->w_markp = curwp->w_dotp; curwp->w_marko = curwp->w_doto; mlwrite("[Mark set]"); 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". */ swapmark(f, n) { register LINE *odotp; register int odoto; if (curwp->w_markp == NULL) { mlwrite("No mark in this window"); return (FALSE); } odotp = curwp->w_dotp; odoto = curwp->w_doto; curwp->w_dotp = curwp->w_markp; curwp->w_doto = curwp->w_marko; curwp->w_markp = odotp; curwp->w_marko = odoto; curwp->w_flag |= WFMOVE; return (TRUE); }