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