This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.bin / vi / delete.c
CommitLineData
1e64b3ba 1/*-
304585c1 2 * Copyright (c) 1992, 1993, 1994
1e64b3ba
JH
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
304585c1 35static char sccsid[] = "@(#)delete.c 8.9 (Berkeley) 3/8/94";
1e64b3ba
JH
36#endif /* not lint */
37
38#include <sys/types.h>
304585c1
AM
39#include <queue.h>
40#include <sys/time.h>
1e64b3ba 41
304585c1 42#include <bitstring.h>
1e64b3ba 43#include <errno.h>
304585c1
AM
44#include <limits.h>
45#include <signal.h>
46#include <stdio.h>
1e64b3ba
JH
47#include <stdlib.h>
48#include <string.h>
304585c1
AM
49#include <termios.h>
50
51#include <db.h>
52#include <regex.h>
1e64b3ba
JH
53
54#include "vi.h"
55
56/*
57 * delete --
58 * Delete a range of text.
59 */
60int
61delete(sp, ep, fm, tm, lmode)
62 SCR *sp;
63 EXF *ep;
64 MARK *fm, *tm;
65 int lmode;
66{
67 recno_t lno;
68 size_t blen, len, tlen;
69 char *bp, *p;
70 int eof;
71
1e64b3ba
JH
72 bp = NULL;
73
74 /* Case 1 -- delete in line mode. */
75 if (lmode) {
76 for (lno = tm->lno; lno >= fm->lno; --lno)
77 if (file_dline(sp, ep, lno))
78 return (1);
79 goto vdone;
80 }
81
82 /*
83 * Case 2 -- delete to EOF. This is a special case because it's
84 * easier to pick it off than try and find it in the other cases.
85 */
86 if (file_lline(sp, ep, &lno))
87 return (1);
88 if (tm->lno >= lno) {
89 if (tm->lno == lno) {
90 if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
91 GETLINE_ERR(sp, lno);
92 return (1);
93 }
94 eof = tm->cno >= len ? 1 : 0;
95 } else
96 eof = 1;
97 if (eof) {
98 for (lno = tm->lno; lno > fm->lno; --lno) {
99 if (file_dline(sp, ep, lno))
100 return (1);
101 ++sp->rptlines[L_DELETED];
102 }
103 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
104 GETLINE_ERR(sp, fm->lno);
105 return (1);
106 }
107 GET_SPACE_RET(sp, bp, blen, fm->cno);
108 memmove(bp, p, fm->cno);
109 if (file_sline(sp, ep, fm->lno, bp, fm->cno))
110 return (1);
111 goto done;
112 }
113 }
114
115 /* Case 3 -- delete within a single line. */
116 if (tm->lno == fm->lno) {
117 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
118 GETLINE_ERR(sp, fm->lno);
119 return (1);
120 }
121 GET_SPACE_RET(sp, bp, blen, len);
304585c1
AM
122 if (fm->cno != 0)
123 memmove(bp, p, fm->cno);
124 memmove(bp + fm->cno, p + (tm->cno + 1), len - (tm->cno + 1));
125 if (file_sline(sp, ep, fm->lno,
126 bp, len - ((tm->cno - fm->cno) + 1)))
1e64b3ba
JH
127 goto err;
128 goto done;
129 }
130
131 /*
132 * Case 4 -- delete over multiple lines.
133 *
134 * Figure out how big a buffer we need.
135 */
136 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
137 GETLINE_ERR(sp, fm->lno);
138 return (1);
139 }
140 tlen = len;
141 if ((p = file_gline(sp, ep, tm->lno, &len)) == NULL) {
142 GETLINE_ERR(sp, tm->lno);
143 return (1);
144 }
145
146 /*
147 * XXX
148 * We can overflow memory here, if (len + tlen) > SIZE_T_MAX. The
149 * only portable way I've found to test is to depend on the overflow
150 * being less than the value.
151 */
152 tlen += len;
153 if (len > tlen) {
154 msgq(sp, M_ERR, "Error: line length overflow");
155 return (1);
156 }
157
158 GET_SPACE_RET(sp, bp, blen, tlen);
159
160 /* Copy the start partial line into place. */
161 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
162 GETLINE_ERR(sp, fm->lno);
163 goto err;
164 }
165 memmove(bp, p, fm->cno);
166 tlen = fm->cno;
167
168 /* Copy the end partial line into place. */
169 if ((p = file_gline(sp, ep, tm->lno, &len)) == NULL) {
170 GETLINE_ERR(sp, tm->lno);
171 goto err;
172 }
304585c1
AM
173 memmove(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1));
174 tlen += len - (tm->cno + 1);
1e64b3ba
JH
175
176 /* Set the current line. */
177 if (file_sline(sp, ep, fm->lno, bp, tlen))
178 goto err;
179
180 /* Delete the last and intermediate lines. */
181 for (lno = tm->lno; lno > fm->lno; --lno)
182 if (file_dline(sp, ep, lno))
183 return (1);
184
185 /* Reporting. */
186vdone: sp->rptlines[L_DELETED] += tm->lno - fm->lno + 1;
187
188done: if (bp != NULL)
189 FREE_SPACE(sp, bp, blen);
190
191 return (0);
192
193 /* Free memory. */
194err: FREE_SPACE(sp, bp, blen);
195
196 return (1);
197}