/* ARGSUSED */ int gotomos(int f GCC_UNUSED, int n) { LINE *last = DOT.l; LINE *lp, *head; int half = (curwp->w_ntrows + 1) / 2; head = buf_head(curbp); for (n = 0, lp = curwp->w_line.l; lp != head; lp = lforw(lp)) { if (n < half) DOT.l = lp; if ((n += line_height(curwp, lp)) >= curwp->w_ntrows) break; } if (n < curwp->w_ntrows) { /* then we hit eof before eos */ half = (n + 1) / 2; /* go back up */ for (n = 0, lp = curwp->w_line.l; lp != head; lp = lforw(lp)) { DOT.l = lp; if ((n += line_height(curwp, lp)) >= half) break; } } if (DOT.l != last) curwp->w_flag |= WFMOVE; return firstnonwhite(FALSE, 1); }
/* * Implements the vi "L" command. * * Move to the last (or nth last) line in window */ int gotoeos(int f, int n) { LINE *last = DOT.l; int nn; n = need_at_least(f, n, 1); /* first get to the end */ DOT.l = curwp->w_line.l; nn = curwp->w_ntrows; while ((nn -= line_height(curwp, DOT.l)) > 0) { if (is_last_line(DOT, curbp)) break; DOT.l = lforw(DOT.l); } #ifdef WMDLINEWRAP /* adjust if we pointed to a line-fragment */ if (w_val(curwp, WMDLINEWRAP) && nn < 0 && DOT.l != curwp->w_line.l) DOT.l = lback(DOT.l); #endif /* and then go back up */ /* (we're either at eos or eof) */ while (--n != 0) { if (sameline(DOT, curwp->w_line)) break; DOT.l = lback(DOT.l); } if (DOT.l != last) curwp->w_flag |= WFMOVE; return firstnonwhite(FALSE, 1); }
/* ARGSUSED */ int gotoeob(int f GCC_UNUSED, int n GCC_UNUSED) { DOT.l = lback(buf_head(curbp)); curwp->w_flag |= WFMOVE; return firstnonwhite(FALSE, 1); }
/* * Move to a particular line (the argument). Count from bottom of file if * argument is negative. */ int vl_gotoline(int n) { int status = TRUE; /* status return */ MARK odot; if (n == 0) /* if a bogus argument...then leave */ return (FALSE); odot = DOT; DOT.o = w_left_margin(curwp); if (n < 0) { DOT.l = lback(buf_head(curbp)); status = backline(TRUE, -n - 1); } else { DOT.l = lforw(buf_head(curbp)); status = forwline(TRUE, n - 1); } if (status != TRUE) { DOT = odot; return status; } (void) firstnonwhite(FALSE, 1); curwp->w_flag |= WFMOVE; return TRUE; }
/* * Implements the vi "^U" command. * * This command is like "forwpage", but it goes backwards. It returns false * only if the cursor is on the first line of the buffer. * * Unlike vi, the OPT_CVMVAS option causes the repeat-count to be interpreted as * half-pages, rather than lines. */ int backhpage(int f, int n) { LINE *llp, *dlp; int status; if ((n = half_pages(f, n)) < 0) return forwhpage(f, -n); llp = curwp->w_line.l; dlp = DOT.l; if ((status = (lback(dlp) != buf_head(curbp))) == TRUE) { n -= line_height(curwp, dlp); while (lback(dlp) != buf_head(curbp)) { llp = lback(llp); dlp = lback(dlp); if ((n -= line_height(curwp, dlp)) < 0) break; } curwp->w_line.l = llp; DOT.l = dlp; curwp->w_flag |= WFHARD | WFINS; } (void) firstnonwhite(FALSE, 1); return status; }
/* * Implements the vi "^F" command. * * Scroll forward by a specified number of lines, or by a full page if no * argument. */ int forwpage(int f, int n) { LINE *lp; int status; if ((n = full_pages(f, n)) < 0) return backpage(f, -n); if ((status = (lforw(DOT.l) != buf_head(curbp))) == TRUE) { lp = curwp->w_line.l; n -= line_height(curwp, lp); while (lp != buf_head(curbp)) { lp = lforw(lp); if ((n -= line_height(curwp, lp)) < 0) break; } if (n < 0) curwp->w_line.l = lp; DOT.l = lp; (void) firstnonwhite(FALSE, 1); curwp->w_flag |= WFHARD | WFMODE; } return status; }
/* * Implements the vi "-" command. * * Like 'backline()', but goes to the first non-white character position. */ int backbline(int f, int n) { int s; n = need_a_count(f, n, 1); if ((s = backline(f, n)) != TRUE) return (s); return firstnonwhite(FALSE, 1); }
/* * Implements the vi "H" command. * * Move to first (or nth) line in window */ int gotobos(int f, int n) { LINE *last = DOT.l; int nn = curwp->w_ntrows; n = need_at_least(f, n, 1); DOT.l = curwp->w_line.l; while (--n != 0) { if (is_last_line(DOT, curbp)) break; nn -= line_height(curwp, DOT.l); DOT.l = lforw(DOT.l); } if (DOT.l != last) curwp->w_flag |= WFMOVE; return firstnonwhite(FALSE, 1); }
/* For the "operator" commands -- the following command is a motion, or * the operator itself is repeated. All operate on regions. */ int vile_op(int f, int n, OpsFunc fn, const char *str) { int c = 0; int thiskey; int status; const CMDFUNC *cfp; /* function to execute */ const CMDFUNC *save_cmd_motion = cmd_motion; BUFFER *ourbp; #if OPT_MOUSE WINDOW *wp0 = curwp; #endif TRACE((T_CALLED "vile_op(%s)\n", str)); doingopcmd = TRUE; pre_op_dot = DOT; ourbp = curbp; if (havemotion != NULL) { cfp = havemotion; havemotion = NULL; } else { TBUFF *tok = 0; mlwrite("%s operation pending...", str); (void) update(FALSE); /* get the next command from the keyboard */ /* or a command line, as approp. */ if (clexec) { char *value = mac_unquotedarg(&tok); /* get the next token */ if (value != 0 && strcmp(value, "lines")) cfp = engl2fnc(value); else cfp = &f_godotplus; } else { thiskey = lastkey; c = kbd_seq(); #if OPT_MOUSE if (curwp != wp0) { unkeystroke(c); doingopcmd = FALSE; returnCode(FALSE); } #endif /* allow second chance for entering counts */ do_repeats(&c, &f, &n); if (thiskey == lastkey) cfp = &f_godotplus; else cfp = DefaultKeyBinding(c); } if (cfp != 0) { mlerase(); } else { if (!clexec) { char temp[NSTRING]; lsprintf(temp, "(%d)", c); tb_scopy(&tok, temp); } (void) no_such_function(tb_values(tok)); } tb_free(&tok); } if (!cfp) { status = FALSE; } else if ((cfp->c_flags & MOTION) == 0) { kbd_alarm(); status = ABORT; } else { /* motion is interpreted as affecting full lines */ if (regionshape == rgn_EXACT) { if (cfp->c_flags & FL) regionshape = rgn_FULLLINE; if (cfp->c_flags & VL_RECT) regionshape = rgn_RECTANGLE; } /* and execute the motion */ if ((status = execute(cfp, f, n)) == TRUE) { post_op_dot = DOT; } else { mlforce("[Motion failed]"); status = FALSE; } } if (status == TRUE) { opcmd = 0; MK = pre_op_dot; /* we've successfully set up a region */ if (!fn) { /* be defensive */ mlforce("BUG -- null func pointer in operator"); status = FALSE; } else if (fn == user_operator) { swapmark(); cmd_motion = cfp; status = dobuf(find_b_name(str), 1, f ? n : 1); } else { status = (fn) (); } if (ourbp == curbp) /* in case the func switched buffers on us */ swapmark(); if (regionshape == rgn_FULLLINE) (void) firstnonwhite(FALSE, 1); } regionshape = rgn_EXACT; doingopcmd = FALSE; haveregion = FALSE; cmd_motion = save_cmd_motion; returnCode(status); }
/* For the "operator" commands -- the following command is a motion, or * the operator itself is repeated. All operate on regions. */ int operator(int f, int n, OpsFunc fn, const char *str) { int c; int thiskey; int status; const CMDFUNC *cfp; /* function to execute */ char tok[NSTRING]; /* command incoming */ BUFFER *ourbp; #if OPT_MOUSE WINDOW *wp0 = curwp; #endif doingopcmd = TRUE; pre_op_dot = DOT; ourbp = curbp; if (havemotion != NULL) { cfp = havemotion; havemotion = NULL; } else { mlwrite("%s operation pending...",str); (void)update(FALSE); /* get the next command from the keyboard */ /* or a command line, as approp. */ if (clexec) { macarg(tok); /* get the next token */ if (!strcmp(tok,"lines")) cfp = &f_godotplus; else cfp = engl2fnc(tok); } else { thiskey = lastkey; c = kbd_seq(); #if OPT_MOUSE if (curwp != wp0) { unkeystroke(c); doingopcmd = FALSE; return FALSE; } #endif /* allow second chance for entering counts */ do_repeats(&c,&f,&n); if (thiskey == lastkey) cfp = &f_godotplus; else cfp = kcod2fnc(c); } if (cfp) mlerase(); else mlforce("[No such function]"); } if (!cfp) { doingopcmd = FALSE; return FALSE; } if ((cfp->c_flags & MOTION) == 0) { kbd_alarm(); doingopcmd = FALSE; return(ABORT); } /* motion is interpreted as affecting full lines */ if (regionshape == EXACT) { if (cfp->c_flags & FL) regionshape = FULLLINE; if (cfp->c_flags & RECT) regionshape = RECTANGLE; } /* and execute the motion */ status = execute(cfp, f,n); if (status != TRUE) { doingopcmd = FALSE; regionshape = EXACT; mlforce("[Motion failed]"); return FALSE; } opcmd = 0; MK = pre_op_dot; /* we've successfully set up a region */ if (!fn) { /* be defensive */ mlforce("BUG -- null func pointer in operator"); status = FALSE; } else { status = (fn)(); } if (ourbp == curbp) /* in case the func switched buffers on us */ swapmark(); if (regionshape == FULLLINE) (void)firstnonwhite(FALSE,1); regionshape = EXACT; doingopcmd = FALSE; haveregion = FALSE; return status; }