119304Speter/*- 219304Speter * Copyright (c) 1992, 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 13254225Speterstatic const char sccsid[] = "$Id: v_right.c,v 10.8 2001/06/25 15:19:34 skimo Exp $"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter#include <sys/time.h> 1919304Speter 2019304Speter#include <bitstring.h> 2119304Speter#include <limits.h> 2219304Speter#include <stdio.h> 2319304Speter 2419304Speter#include "../common/common.h" 2519304Speter#include "vi.h" 2619304Speter 2719304Speter/* 2819304Speter * v_right -- [count]' ', [count]l 2919304Speter * Move right by columns. 3019304Speter * 31281373Sbapt * PUBLIC: int v_right(SCR *, VICMD *); 3219304Speter */ 3319304Speterint 34254225Speterv_right(SCR *sp, VICMD *vp) 3519304Speter{ 3619304Speter size_t len; 3719304Speter int isempty; 3819304Speter 3919304Speter if (db_eget(sp, vp->m_start.lno, NULL, &len, &isempty)) { 4019304Speter if (isempty) 4119304Speter goto eol; 4219304Speter return (1); 4319304Speter } 4419304Speter 4519304Speter /* It's always illegal to move right on empty lines. */ 4619304Speter if (len == 0) { 4719304Spetereol: v_eol(sp, NULL); 4819304Speter return (1); 4919304Speter } 5019304Speter 5119304Speter /* 5219304Speter * Non-motion commands move to the end of the range. Delete and 5319304Speter * yank stay at the start. Ignore others. Adjust the end of the 5419304Speter * range for motion commands. 5519304Speter * 5619304Speter * !!! 5719304Speter * Historically, "[cdsy]l" worked at the end of a line. Also, 5819304Speter * EOL is a count sink. 5919304Speter */ 6019304Speter vp->m_stop.cno = vp->m_start.cno + 6119304Speter (F_ISSET(vp, VC_C1SET) ? vp->count : 1); 6219304Speter if (vp->m_start.cno == len - 1 && !ISMOTION(vp)) { 6319304Speter v_eol(sp, NULL); 6419304Speter return (1); 6519304Speter } 6619304Speter if (vp->m_stop.cno >= len) { 6719304Speter vp->m_stop.cno = len - 1; 6819304Speter vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop; 6919304Speter } else if (ISMOTION(vp)) { 7019304Speter --vp->m_stop.cno; 7119304Speter vp->m_final = vp->m_start; 7219304Speter } else 7319304Speter vp->m_final = vp->m_stop; 7419304Speter return (0); 7519304Speter} 7619304Speter 7719304Speter/* 7819304Speter * v_dollar -- [count]$ 7919304Speter * Move to the last column. 8019304Speter * 81281373Sbapt * PUBLIC: int v_dollar(SCR *, VICMD *); 8219304Speter */ 8319304Speterint 84254225Speterv_dollar(SCR *sp, VICMD *vp) 8519304Speter{ 8619304Speter size_t len; 8719304Speter int isempty; 8819304Speter 8919304Speter /* 9019304Speter * !!! 9119304Speter * A count moves down count - 1 rows, so, "3$" is the same as "2j$". 9219304Speter */ 9319304Speter if ((F_ISSET(vp, VC_C1SET) ? vp->count : 1) != 1) { 9419304Speter /* 9519304Speter * !!! 9619304Speter * Historically, if the $ is a motion, and deleting from 9719304Speter * at or before the first non-blank of the line, it's a 9819304Speter * line motion, and the line motion flag is set. 9919304Speter */ 10019304Speter vp->m_stop.cno = 0; 10119304Speter if (nonblank(sp, vp->m_start.lno, &vp->m_stop.cno)) 10219304Speter return (1); 10319304Speter if (ISMOTION(vp) && vp->m_start.cno <= vp->m_stop.cno) 10419304Speter F_SET(vp, VM_LMODE); 10519304Speter 10619304Speter --vp->count; 10719304Speter if (v_down(sp, vp)) 10819304Speter return (1); 10919304Speter } 11019304Speter 11119304Speter /* 11219304Speter * !!! 11319304Speter * Historically, it was illegal to use $ as a motion command on 11419304Speter * an empty line. Unfortunately, even though C was historically 11519304Speter * aliased to c$, it (and not c$) was special cased to work on 11619304Speter * empty lines. Since we alias C to c$ too, we have a problem. 11719304Speter * To fix it, we let c$ go through, on the assumption that it's 11819304Speter * not a problem for it to work. 11919304Speter */ 12019304Speter if (db_eget(sp, vp->m_stop.lno, NULL, &len, &isempty)) { 12119304Speter if (!isempty) 12219304Speter return (1); 12319304Speter len = 0; 12419304Speter } 12519304Speter 12619304Speter if (len == 0) { 12719304Speter if (ISMOTION(vp) && !ISCMD(vp->rkp, 'c')) { 12819304Speter v_eol(sp, NULL); 12919304Speter return (1); 13019304Speter } 13119304Speter return (0); 13219304Speter } 13319304Speter 13419304Speter /* 13519304Speter * Non-motion commands move to the end of the range. Delete 13619304Speter * and yank stay at the start. Ignore others. 13719304Speter */ 13819304Speter vp->m_stop.cno = len ? len - 1 : 0; 13919304Speter vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop; 14019304Speter return (0); 14119304Speter} 142