delete.c revision 1.3.4.2 1 1.3.4.2 yamt /* $NetBSD: delete.c,v 1.3.4.2 2014/05/22 15:50:33 yamt Exp $ */
2 1.3.4.2 yamt /*-
3 1.3.4.2 yamt * Copyright (c) 1992, 1993, 1994
4 1.3.4.2 yamt * The Regents of the University of California. All rights reserved.
5 1.3.4.2 yamt * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 1.3.4.2 yamt * Keith Bostic. All rights reserved.
7 1.3.4.2 yamt *
8 1.3.4.2 yamt * See the LICENSE file for redistribution information.
9 1.3.4.2 yamt */
10 1.3.4.2 yamt
11 1.3.4.2 yamt #include "config.h"
12 1.3.4.2 yamt
13 1.3.4.2 yamt #include <sys/cdefs.h>
14 1.3.4.2 yamt #if 0
15 1.3.4.2 yamt #ifndef lint
16 1.3.4.2 yamt static const char sccsid[] = "Id: delete.c,v 10.17 2001/06/25 15:19:09 skimo Exp (Berkeley) Date: 2001/06/25 15:19:09 ";
17 1.3.4.2 yamt #endif /* not lint */
18 1.3.4.2 yamt #else
19 1.3.4.2 yamt __RCSID("$NetBSD: delete.c,v 1.3.4.2 2014/05/22 15:50:33 yamt Exp $");
20 1.3.4.2 yamt #endif
21 1.3.4.2 yamt
22 1.3.4.2 yamt #include <sys/types.h>
23 1.3.4.2 yamt #include <sys/queue.h>
24 1.3.4.2 yamt
25 1.3.4.2 yamt #include <bitstring.h>
26 1.3.4.2 yamt #include <errno.h>
27 1.3.4.2 yamt #include <limits.h>
28 1.3.4.2 yamt #include <stdio.h>
29 1.3.4.2 yamt #include <stdlib.h>
30 1.3.4.2 yamt #include <string.h>
31 1.3.4.2 yamt
32 1.3.4.2 yamt #include "common.h"
33 1.3.4.2 yamt
34 1.3.4.2 yamt /*
35 1.3.4.2 yamt * del --
36 1.3.4.2 yamt * Delete a range of text.
37 1.3.4.2 yamt *
38 1.3.4.2 yamt * PUBLIC: int del __P((SCR *, MARK *, MARK *, int));
39 1.3.4.2 yamt */
40 1.3.4.2 yamt int
41 1.3.4.2 yamt del(SCR *sp, MARK *fm, MARK *tm, int lmode)
42 1.3.4.2 yamt {
43 1.3.4.2 yamt db_recno_t lno;
44 1.3.4.2 yamt size_t blen, len, nlen, tlen;
45 1.3.4.2 yamt CHAR_T *bp, *p;
46 1.3.4.2 yamt int eof, rval;
47 1.3.4.2 yamt
48 1.3.4.2 yamt bp = NULL;
49 1.3.4.2 yamt
50 1.3.4.2 yamt /* Case 1 -- delete in line mode. */
51 1.3.4.2 yamt if (lmode) {
52 1.3.4.2 yamt for (lno = tm->lno; lno >= fm->lno; --lno) {
53 1.3.4.2 yamt if (db_delete(sp, lno))
54 1.3.4.2 yamt return (1);
55 1.3.4.2 yamt ++sp->rptlines[L_DELETED];
56 1.3.4.2 yamt if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
57 1.3.4.2 yamt break;
58 1.3.4.2 yamt }
59 1.3.4.2 yamt goto done;
60 1.3.4.2 yamt }
61 1.3.4.2 yamt
62 1.3.4.2 yamt /*
63 1.3.4.2 yamt * Case 2 -- delete to EOF. This is a special case because it's
64 1.3.4.2 yamt * easier to pick it off than try and find it in the other cases.
65 1.3.4.2 yamt */
66 1.3.4.2 yamt if (db_last(sp, &lno))
67 1.3.4.2 yamt return (1);
68 1.3.4.2 yamt if (tm->lno >= lno) {
69 1.3.4.2 yamt if (tm->lno == lno) {
70 1.3.4.2 yamt if (db_get(sp, lno, DBG_FATAL, &p, &len))
71 1.3.4.2 yamt return (1);
72 1.3.4.2 yamt eof = tm->cno != ENTIRE_LINE && tm->cno >= len ? 1 : 0;
73 1.3.4.2 yamt } else
74 1.3.4.2 yamt eof = 1;
75 1.3.4.2 yamt if (eof) {
76 1.3.4.2 yamt for (lno = tm->lno; lno > fm->lno; --lno) {
77 1.3.4.2 yamt if (db_delete(sp, lno))
78 1.3.4.2 yamt return (1);
79 1.3.4.2 yamt ++sp->rptlines[L_DELETED];
80 1.3.4.2 yamt if (lno %
81 1.3.4.2 yamt INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
82 1.3.4.2 yamt break;
83 1.3.4.2 yamt }
84 1.3.4.2 yamt if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
85 1.3.4.2 yamt return (1);
86 1.3.4.2 yamt GET_SPACE_RETW(sp, bp, blen, fm->cno);
87 1.3.4.2 yamt MEMCPYW(bp, p, fm->cno);
88 1.3.4.2 yamt if (db_set(sp, fm->lno, bp, fm->cno))
89 1.3.4.2 yamt return (1);
90 1.3.4.2 yamt goto done;
91 1.3.4.2 yamt }
92 1.3.4.2 yamt }
93 1.3.4.2 yamt
94 1.3.4.2 yamt /* Case 3 -- delete within a single line. */
95 1.3.4.2 yamt if (tm->lno == fm->lno) {
96 1.3.4.2 yamt if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
97 1.3.4.2 yamt return (1);
98 1.3.4.2 yamt GET_SPACE_RETW(sp, bp, blen, len);
99 1.3.4.2 yamt if (fm->cno != 0)
100 1.3.4.2 yamt MEMCPYW(bp, p, fm->cno);
101 1.3.4.2 yamt MEMCPYW(bp + fm->cno, p + (tm->cno + 1),
102 1.3.4.2 yamt len - (tm->cno + 1));
103 1.3.4.2 yamt if (db_set(sp, fm->lno,
104 1.3.4.2 yamt bp, len - ((tm->cno - fm->cno) + 1)))
105 1.3.4.2 yamt goto err;
106 1.3.4.2 yamt goto done;
107 1.3.4.2 yamt }
108 1.3.4.2 yamt
109 1.3.4.2 yamt /*
110 1.3.4.2 yamt * Case 4 -- delete over multiple lines.
111 1.3.4.2 yamt *
112 1.3.4.2 yamt * Copy the start partial line into place.
113 1.3.4.2 yamt */
114 1.3.4.2 yamt if ((tlen = fm->cno) != 0) {
115 1.3.4.2 yamt if (db_get(sp, fm->lno, DBG_FATAL, &p, NULL))
116 1.3.4.2 yamt return (1);
117 1.3.4.2 yamt GET_SPACE_RETW(sp, bp, blen, tlen + 256);
118 1.3.4.2 yamt MEMCPYW(bp, p, tlen);
119 1.3.4.2 yamt }
120 1.3.4.2 yamt
121 1.3.4.2 yamt /* Copy the end partial line into place. */
122 1.3.4.2 yamt if (db_get(sp, tm->lno, DBG_FATAL, &p, &len))
123 1.3.4.2 yamt goto err;
124 1.3.4.2 yamt if (len != 0 && tm->cno != len - 1) {
125 1.3.4.2 yamt /*
126 1.3.4.2 yamt * XXX
127 1.3.4.2 yamt * We can overflow memory here, if the total length is greater
128 1.3.4.2 yamt * than SIZE_T_MAX. The only portable way I've found to test
129 1.3.4.2 yamt * is depending on the overflow being less than the value.
130 1.3.4.2 yamt */
131 1.3.4.2 yamt nlen = (len - (tm->cno + 1)) + tlen;
132 1.3.4.2 yamt if (tlen > nlen) {
133 1.3.4.2 yamt msgq(sp, M_ERR, "002|Line length overflow");
134 1.3.4.2 yamt goto err;
135 1.3.4.2 yamt }
136 1.3.4.2 yamt if (tlen == 0) {
137 1.3.4.2 yamt GET_SPACE_RETW(sp, bp, blen, nlen);
138 1.3.4.2 yamt } else
139 1.3.4.2 yamt ADD_SPACE_RETW(sp, bp, blen, nlen);
140 1.3.4.2 yamt
141 1.3.4.2 yamt MEMCPYW(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1));
142 1.3.4.2 yamt tlen += len - (tm->cno + 1);
143 1.3.4.2 yamt }
144 1.3.4.2 yamt
145 1.3.4.2 yamt /* Set the current line. */
146 1.3.4.2 yamt if (db_set(sp, fm->lno, bp, tlen))
147 1.3.4.2 yamt goto err;
148 1.3.4.2 yamt
149 1.3.4.2 yamt /* Delete the last and intermediate lines. */
150 1.3.4.2 yamt for (lno = tm->lno; lno > fm->lno; --lno) {
151 1.3.4.2 yamt if (db_delete(sp, lno))
152 1.3.4.2 yamt goto err;
153 1.3.4.2 yamt ++sp->rptlines[L_DELETED];
154 1.3.4.2 yamt if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
155 1.3.4.2 yamt break;
156 1.3.4.2 yamt }
157 1.3.4.2 yamt
158 1.3.4.2 yamt done: rval = 0;
159 1.3.4.2 yamt if (0)
160 1.3.4.2 yamt err: rval = 1;
161 1.3.4.2 yamt if (bp != NULL)
162 1.3.4.2 yamt FREE_SPACEW(sp, bp, blen);
163 1.3.4.2 yamt return (rval);
164 1.3.4.2 yamt }
165