/* * v_cfirst -- [count]_ * Move to the first non-blank character in a line. * * PUBLIC: int v_cfirst __P((SCR *, VICMD *)); */ int v_cfirst(SCR *sp, VICMD *vp) { db_recno_t cnt, lno; /* * !!! * If the _ is a motion component, it makes the command a line motion * e.g. "d_" deletes the line. It also means that the cursor doesn't * move. * * The _ command never failed in the first column. */ if (ISMOTION(vp)) F_SET(vp, VM_LMODE); /* * !!! * Historically a specified count makes _ move down count - 1 * rows, so, "3_" is the same as "2j_". */ cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; if (cnt != 1) { --vp->count; return (v_down(sp, vp)); } /* * Move to the first non-blank. * * Can't just use RCM_SET_FNB, in case _ is used as the motion * component of another command. */ vp->m_stop.cno = 0; if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno)) return (1); /* * !!! * The _ command has to fail if the file is empty and we're doing * a delete. If deleting line 1, and 0 is the first nonblank, * make the check. */ if (vp->m_stop.lno == 1 && vp->m_stop.cno == 0 && ISCMD(vp->rkp, 'd')) { if (db_last(sp, &lno)) return (1); if (lno == 0) { v_sol(sp); return (1); } } /* * Delete and non-motion commands move to the end of the range, * yank stays at the start. Ignore others. */ vp->m_final = ISMOTION(vp) && ISCMD(vp->rkp, 'y') ? vp->m_start : vp->m_stop; return (0); }
/* * v_dollar -- [count]$ * Move to the last column. * * PUBLIC: int v_dollar __P((SCR *, VICMD *)); */ int v_dollar(SCR *sp, VICMD *vp) { size_t len; int isempty; /* * !!! * A count moves down count - 1 rows, so, "3$" is the same as "2j$". */ if ((F_ISSET(vp, VC_C1SET) ? vp->count : 1) != 1) { /* * !!! * Historically, if the $ is a motion, and deleting from * at or before the first non-blank of the line, it's a * line motion, and the line motion flag is set. */ vp->m_stop.cno = 0; if (nonblank(sp, vp->m_start.lno, &vp->m_stop.cno)) return (1); if (ISMOTION(vp) && vp->m_start.cno <= vp->m_stop.cno) F_SET(vp, VM_LMODE); --vp->count; if (v_down(sp, vp)) return (1); } /* * !!! * Historically, it was illegal to use $ as a motion command on * an empty line. Unfortunately, even though C was historically * aliased to c$, it (and not c$) was special cased to work on * empty lines. Since we alias C to c$ too, we have a problem. * To fix it, we let c$ go through, on the assumption that it's * not a problem for it to work. */ if (db_eget(sp, vp->m_stop.lno, NULL, &len, &isempty)) { if (!isempty) return (1); len = 0; } if (len == 0) { if (ISMOTION(vp) && !ISCMD(vp->rkp, 'c')) { v_eol(sp, NULL); return (1); } return (0); } /* * Non-motion commands move to the end of the range. Delete * and yank stay at the start. Ignore others. */ vp->m_stop.cno = len ? len - 1 : 0; vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop; return (0); }
/* * v_cr -- [count]^M * In a script window, send the line to the shell. * In a regular window, move down by lines. * * PUBLIC: int v_cr(SCR *, VICMD *); */ int v_cr(SCR *sp, VICMD *vp) { /* If it's a colon command-line edit window, it's an ex command. */ if (F_ISSET(sp, SC_COMEDIT)) return (v_ecl_exec(sp)); /* If it's a script window, exec the line. */ if (F_ISSET(sp, SC_SCRIPT)) return (sscr_exec(sp, vp->m_start.lno)); /* Otherwise, it's the same as v_down(). */ return (v_down(sp, vp)); }