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_delete.c,v 10.11 2001/06/25 15:19:31 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_delete -- [buffer][count]d[count]motion
2919304Speter *	       [buffer][count]D
3019304Speter *	Delete a range of text.
3119304Speter *
32281373Sbapt * PUBLIC: int v_delete(SCR *, VICMD *);
3319304Speter */
3419304Speterint
35254225Speterv_delete(SCR *sp, VICMD *vp)
3619304Speter{
3719304Speter	recno_t nlines;
3819304Speter	size_t len;
3919304Speter	int lmode;
4019304Speter
4119304Speter	lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
4219304Speter
4319304Speter	/* Yank the lines. */
4419304Speter	if (cut(sp, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
4519304Speter	    &vp->m_start, &vp->m_stop,
4619304Speter	    lmode | (F_ISSET(vp, VM_CUTREQ) ? CUT_NUMREQ : CUT_NUMOPT)))
4719304Speter		return (1);
4819304Speter
4919304Speter	/* Delete the lines. */
5019304Speter	if (del(sp, &vp->m_start, &vp->m_stop, lmode))
5119304Speter		return (1);
5219304Speter
5319304Speter	/*
5419304Speter	 * Check for deletion of the entire file.  Try to check a close
5519304Speter	 * by line so we don't go to the end of the file unnecessarily.
5619304Speter	 */
5719304Speter	if (!db_exist(sp, vp->m_final.lno + 1)) {
5819304Speter		if (db_last(sp, &nlines))
5919304Speter			return (1);
6019304Speter		if (nlines == 0) {
6119304Speter			vp->m_final.lno = 1;
6219304Speter			vp->m_final.cno = 0;
6319304Speter			return (0);
6419304Speter		}
6519304Speter	}
6619304Speter
6719304Speter	/*
6819304Speter	 * One special correction, in case we've deleted the current line or
6919304Speter	 * character.  We check it here instead of checking in every command
7019304Speter	 * that can be a motion component.
7119304Speter	 */
7219304Speter	if (db_get(sp, vp->m_final.lno, 0, NULL, &len)) {
7319304Speter		if (db_get(sp, nlines, DBG_FATAL, NULL, &len))
7419304Speter			return (1);
7519304Speter		vp->m_final.lno = nlines;
7619304Speter	}
7719304Speter
7819304Speter	/*
7919304Speter	 * !!!
8019304Speter	 * Cursor movements, other than those caused by a line mode command
8119304Speter	 * moving to another line, historically reset the relative position.
8219304Speter	 *
8319304Speter	 * This currently matches the check made in v_yank(), I'm hoping that
8419304Speter	 * they should be consistent...
8519304Speter	 */
8619304Speter	if (!F_ISSET(vp, VM_LMODE)) {
8719304Speter		F_CLR(vp, VM_RCM_MASK);
8819304Speter		F_SET(vp, VM_RCM_SET);
8919304Speter
9019304Speter		/* Make sure the set cursor position exists. */
9119304Speter		if (vp->m_final.cno >= len)
9219304Speter			vp->m_final.cno = len ? len - 1 : 0;
9319304Speter	}
9419304Speter
9519304Speter	/*
9619304Speter	 * !!!
9719304Speter	 * The "dd" command moved to the first non-blank; "d<motion>"
9819304Speter	 * didn't.
9919304Speter	 */
10019304Speter	if (F_ISSET(vp, VM_LDOUBLE)) {
10119304Speter		F_CLR(vp, VM_RCM_MASK);
10219304Speter		F_SET(vp, VM_RCM_SETFNB);
10319304Speter	}
10419304Speter	return (0);
10519304Speter}
106