v_left.c revision 254225
152419Sjulian/*- 252419Sjulian * Copyright (c) 1992, 1993, 1994 352419Sjulian * The Regents of the University of California. All rights reserved. 452419Sjulian * Copyright (c) 1992, 1993, 1994, 1995, 1996 552419Sjulian * Keith Bostic. All rights reserved. 652419Sjulian * 752419Sjulian * See the LICENSE file for redistribution information. 852419Sjulian */ 952419Sjulian 1052419Sjulian#include "config.h" 1152419Sjulian 1252419Sjulian#ifndef lint 1352419Sjulianstatic const char sccsid[] = "$Id: v_left.c,v 10.9 2001/06/25 15:19:32 skimo Exp $"; 1452419Sjulian#endif /* not lint */ 1552419Sjulian 1652419Sjulian#include <sys/types.h> 1752419Sjulian#include <sys/queue.h> 1852419Sjulian#include <sys/time.h> 1952419Sjulian 2052419Sjulian#include <bitstring.h> 2152419Sjulian#include <limits.h> 2252419Sjulian#include <stdio.h> 2352419Sjulian 2452419Sjulian#include "../common/common.h" 2552419Sjulian#include "vi.h" 2652419Sjulian 2752419Sjulian/* 2852419Sjulian * v_left -- [count]^H, [count]h 2952419Sjulian * Move left by columns. 3052419Sjulian * 3152419Sjulian * PUBLIC: int v_left __P((SCR *, VICMD *)); 3252419Sjulian */ 3352419Sjulianint 3452419Sjulianv_left(SCR *sp, VICMD *vp) 3552419Sjulian{ 3652419Sjulian recno_t cnt; 3752419Sjulian 3852419Sjulian /* 3952419Sjulian * !!! 4052752Sjulian * The ^H and h commands always failed in the first column. 4152419Sjulian */ 4252419Sjulian if (vp->m_start.cno == 0) { 4352419Sjulian v_sol(sp); 4452419Sjulian return (1); 4552419Sjulian } 4652419Sjulian 4752419Sjulian /* Find the end of the range. */ 4852419Sjulian cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; 4952419Sjulian if (vp->m_start.cno > cnt) 5052419Sjulian vp->m_stop.cno = vp->m_start.cno - cnt; 5152419Sjulian else 5252419Sjulian vp->m_stop.cno = 0; 5352419Sjulian 5452419Sjulian /* 5552419Sjulian * All commands move to the end of the range. Motion commands 5652419Sjulian * adjust the starting point to the character before the current 5752419Sjulian * one. 5852419Sjulian */ 5952419Sjulian if (ISMOTION(vp)) 6052419Sjulian --vp->m_start.cno; 6152419Sjulian vp->m_final = vp->m_stop; 6252419Sjulian return (0); 6352419Sjulian} 6452419Sjulian 6552419Sjulian/* 6652419Sjulian * v_cfirst -- [count]_ 6752419Sjulian * Move to the first non-blank character in a line. 6852419Sjulian * 6952419Sjulian * PUBLIC: int v_cfirst __P((SCR *, VICMD *)); 7052419Sjulian */ 7152419Sjulianint 7252419Sjulianv_cfirst(SCR *sp, VICMD *vp) 7352419Sjulian{ 7452419Sjulian recno_t cnt, lno; 7552419Sjulian 7652419Sjulian /* 7752419Sjulian * !!! 7852419Sjulian * If the _ is a motion component, it makes the command a line motion 7952419Sjulian * e.g. "d_" deletes the line. It also means that the cursor doesn't 8052419Sjulian * move. 8152419Sjulian * 8252419Sjulian * The _ command never failed in the first column. 8352419Sjulian */ 8452419Sjulian if (ISMOTION(vp)) 8552419Sjulian F_SET(vp, VM_LMODE); 8652419Sjulian /* 8752419Sjulian * !!! 8852419Sjulian * Historically a specified count makes _ move down count - 1 8952419Sjulian * rows, so, "3_" is the same as "2j_". 9052419Sjulian */ 9152419Sjulian cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; 9252419Sjulian if (cnt != 1) { 9352419Sjulian --vp->count; 9452419Sjulian return (v_down(sp, vp)); 9552419Sjulian } 9652419Sjulian 9752419Sjulian /* 9852419Sjulian * Move to the first non-blank. 9952885Sjulian * 10052885Sjulian * Can't just use RCM_SET_FNB, in case _ is used as the motion 10152885Sjulian * component of another command. 10252885Sjulian */ 10352885Sjulian vp->m_stop.cno = 0; 10452885Sjulian if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno)) 10552885Sjulian return (1); 10652885Sjulian 10752885Sjulian /* 10852885Sjulian * !!! 10952885Sjulian * The _ command has to fail if the file is empty and we're doing 11052885Sjulian * a delete. If deleting line 1, and 0 is the first nonblank, 11152885Sjulian * make the check. 11252885Sjulian */ 11352885Sjulian if (vp->m_stop.lno == 1 && 11452885Sjulian vp->m_stop.cno == 0 && ISCMD(vp->rkp, 'd')) { 11552885Sjulian if (db_last(sp, &lno)) 11652885Sjulian return (1); 11752419Sjulian if (lno == 0) { 11852752Sjulian v_sol(sp); 11952752Sjulian return (1); 12052752Sjulian } 12152752Sjulian } 12252752Sjulian 12352885Sjulian /* 12452419Sjulian * Delete and non-motion commands move to the end of the range, 12552419Sjulian * yank stays at the start. Ignore others. 12652419Sjulian */ 12752419Sjulian vp->m_final = 12852419Sjulian ISMOTION(vp) && ISCMD(vp->rkp, 'y') ? vp->m_start : vp->m_stop; 12952419Sjulian return (0); 13052419Sjulian} 13152419Sjulian 13252419Sjulian/* 13352419Sjulian * v_first -- ^ 13452419Sjulian * Move to the first non-blank character in this line. 13552419Sjulian * 13652419Sjulian * PUBLIC: int v_first __P((SCR *, VICMD *)); 13752419Sjulian */ 13852419Sjulianint 13952419Sjulianv_first(SCR *sp, VICMD *vp) 14052419Sjulian{ 14152419Sjulian /* 14252419Sjulian * !!! 14352419Sjulian * Yielding to none in our quest for compatibility with every 14452419Sjulian * historical blemish of vi, no matter how strange it might be, 14552419Sjulian * we permit the user to enter a count and then ignore it. 14652419Sjulian */ 14752419Sjulian 14852419Sjulian /* 14952419Sjulian * Move to the first non-blank. 15052419Sjulian * 15152419Sjulian * Can't just use RCM_SET_FNB, in case ^ is used as the motion 15252419Sjulian * component of another command. 15352885Sjulian */ 15452419Sjulian vp->m_stop.cno = 0; 15552419Sjulian if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno)) 15652419Sjulian return (1); 15752419Sjulian 15852419Sjulian /* 15952419Sjulian * !!! 16052419Sjulian * The ^ command succeeded if used as a command when the cursor was 16152419Sjulian * on the first non-blank in the line, but failed if used as a motion 16252419Sjulian * component in the same situation. 16352419Sjulian */ 16452419Sjulian if (ISMOTION(vp) && vp->m_start.cno == vp->m_stop.cno) { 16552419Sjulian v_sol(sp); 16652419Sjulian return (1); 16752419Sjulian } 16852419Sjulian 16952419Sjulian /* 17052419Sjulian * If moving right, non-motion commands move to the end of the range. 17152419Sjulian * Delete and yank stay at the start. Motion commands adjust the 17252419Sjulian * ending point to the character before the current ending charcter. 17352419Sjulian * 17452419Sjulian * If moving left, all commands move to the end of the range. Motion 17552419Sjulian * commands adjust the starting point to the character before the 17652419Sjulian * current starting character. 17752419Sjulian */ 17852419Sjulian if (vp->m_start.cno < vp->m_stop.cno) 17952419Sjulian if (ISMOTION(vp)) { 18052419Sjulian --vp->m_stop.cno; 18152419Sjulian vp->m_final = vp->m_start; 18252419Sjulian } else 18352419Sjulian vp->m_final = vp->m_stop; 18452419Sjulian else { 18552419Sjulian if (ISMOTION(vp)) 18652419Sjulian --vp->m_start.cno; 18752419Sjulian vp->m_final = vp->m_stop; 18852419Sjulian } 18952419Sjulian return (0); 19052419Sjulian} 19152419Sjulian 19252419Sjulian/* 19352419Sjulian * v_ncol -- [count]| 19452419Sjulian * Move to column count or the first column on this line. If the 19552419Sjulian * requested column is past EOL, move to EOL. The nasty part is 19652419Sjulian * that we have to know character column widths to make this work. 19752419Sjulian * 19852419Sjulian * PUBLIC: int v_ncol __P((SCR *, VICMD *)); 19952419Sjulian */ 20052419Sjulianint 20152419Sjulianv_ncol(SCR *sp, VICMD *vp) 20252419Sjulian{ 20352419Sjulian if (F_ISSET(vp, VC_C1SET) && vp->count > 1) { 20452419Sjulian --vp->count; 20552419Sjulian vp->m_stop.cno = 20652419Sjulian vs_colpos(sp, vp->m_start.lno, (size_t)vp->count); 20752419Sjulian /* 20852419Sjulian * !!! 20952419Sjulian * The | command succeeded if used as a command and the cursor 21052419Sjulian * didn't move, but failed if used as a motion component in the 21152419Sjulian * same situation. 21252419Sjulian */ 21352419Sjulian if (ISMOTION(vp) && vp->m_stop.cno == vp->m_start.cno) { 21452419Sjulian v_nomove(sp); 21552419Sjulian return (1); 21652419Sjulian } 21752419Sjulian } else { 21852419Sjulian /* 21952419Sjulian * !!! 22052419Sjulian * The | command succeeded if used as a command in column 0 22152419Sjulian * without a count, but failed if used as a motion component 22252419Sjulian * in the same situation. 22352419Sjulian */ 22452419Sjulian if (ISMOTION(vp) && vp->m_start.cno == 0) { 22552419Sjulian v_sol(sp); 22652419Sjulian return (1); 22752419Sjulian } 22852419Sjulian vp->m_stop.cno = 0; 22952419Sjulian } 23052419Sjulian 23152419Sjulian /* 23252419Sjulian * If moving right, non-motion commands move to the end of the range. 23352419Sjulian * Delete and yank stay at the start. Motion commands adjust the 23452419Sjulian * ending point to the character before the current ending charcter. 23552419Sjulian * 23652419Sjulian * If moving left, all commands move to the end of the range. Motion 23752419Sjulian * commands adjust the starting point to the character before the 23852419Sjulian * current starting character. 23952419Sjulian */ 24052419Sjulian if (vp->m_start.cno < vp->m_stop.cno) 24152419Sjulian if (ISMOTION(vp)) { 24252419Sjulian --vp->m_stop.cno; 24352419Sjulian vp->m_final = vp->m_start; 24452419Sjulian } else 24552419Sjulian vp->m_final = vp->m_stop; 24652419Sjulian else { 24752419Sjulian if (ISMOTION(vp)) 24852419Sjulian --vp->m_start.cno; 24952419Sjulian vp->m_final = vp->m_stop; 25052419Sjulian } 25152419Sjulian return (0); 25252419Sjulian} 25352419Sjulian 25452419Sjulian/* 25552419Sjulian * v_zero -- 0 25652419Sjulian * Move to the first column on this line. 25752419Sjulian * 25852419Sjulian * PUBLIC: int v_zero __P((SCR *, VICMD *)); 25952419Sjulian */ 26052419Sjulianint 26152419Sjulianv_zero(SCR *sp, VICMD *vp) 26252419Sjulian{ 26352419Sjulian /* 26452419Sjulian * !!! 26552419Sjulian * The 0 command succeeded if used as a command in the first column 26652419Sjulian * but failed if used as a motion component in the same situation. 26752419Sjulian */ 26852419Sjulian if (ISMOTION(vp) && vp->m_start.cno == 0) { 26952419Sjulian v_sol(sp); 27052419Sjulian return (1); 27152419Sjulian } 27252419Sjulian 27352419Sjulian /* 27452419Sjulian * All commands move to the end of the range. Motion commands 27552419Sjulian * adjust the starting point to the character before the current 27652419Sjulian * one. 27752419Sjulian */ 27852419Sjulian vp->m_stop.cno = 0; 27952419Sjulian if (ISMOTION(vp)) 28052419Sjulian --vp->m_start.cno; 28152419Sjulian vp->m_final = vp->m_stop; 28252419Sjulian return (0); 28352419Sjulian} 28452419Sjulian