1 |
|
|
/* $OpenBSD: v_itxt.c,v 1.8 2014/11/12 04:28:41 bentley Exp $ */ |
2 |
|
|
|
3 |
|
|
/*- |
4 |
|
|
* Copyright (c) 1992, 1993, 1994 |
5 |
|
|
* The Regents of the University of California. All rights reserved. |
6 |
|
|
* Copyright (c) 1992, 1993, 1994, 1995, 1996 |
7 |
|
|
* Keith Bostic. All rights reserved. |
8 |
|
|
* |
9 |
|
|
* See the LICENSE file for redistribution information. |
10 |
|
|
*/ |
11 |
|
|
|
12 |
|
|
#include "config.h" |
13 |
|
|
|
14 |
|
|
#include <sys/types.h> |
15 |
|
|
#include <sys/queue.h> |
16 |
|
|
#include <sys/time.h> |
17 |
|
|
|
18 |
|
|
#include <bitstring.h> |
19 |
|
|
#include <ctype.h> |
20 |
|
|
#include <errno.h> |
21 |
|
|
#include <limits.h> |
22 |
|
|
#include <stdio.h> |
23 |
|
|
#include <stdlib.h> |
24 |
|
|
#include <string.h> |
25 |
|
|
|
26 |
|
|
#include "../common/common.h" |
27 |
|
|
#include "vi.h" |
28 |
|
|
|
29 |
|
|
/* |
30 |
|
|
* !!! |
31 |
|
|
* Repeated input in the historic vi is mostly wrong and this isn't very |
32 |
|
|
* backward compatible. For example, if the user entered "3Aab\ncd" in |
33 |
|
|
* the historic vi, the "ab" was repeated 3 times, and the "\ncd" was then |
34 |
|
|
* appended to the result. There was also a hack which I don't remember |
35 |
|
|
* right now, where "3o" would open 3 lines and then let the user fill them |
36 |
|
|
* in, to make screen movements on 300 baud modems more tolerable. I don't |
37 |
|
|
* think it's going to be missed. |
38 |
|
|
* |
39 |
|
|
* !!! |
40 |
|
|
* There's a problem with the way that we do logging for change commands with |
41 |
|
|
* implied motions (e.g. A, I, O, cc, etc.). Since the main vi loop logs the |
42 |
|
|
* starting cursor position before the change command "moves" the cursor, the |
43 |
|
|
* cursor position to which we return on undo will be where the user entered |
44 |
|
|
* the change command, not the start of the change. Several of the following |
45 |
|
|
* routines re-log the cursor to make this work correctly. Historic vi tried |
46 |
|
|
* to do the same thing, and mostly got it right. (The only spectacular way |
47 |
|
|
* it fails is if the user entered 'o' from anywhere but the last character of |
48 |
|
|
* the line, the undo returned the cursor to the start of the line. If the |
49 |
|
|
* user was on the last character of the line, the cursor returned to that |
50 |
|
|
* position.) We also check for mapped keys waiting, i.e. if we're in the |
51 |
|
|
* middle of a map, don't bother logging the cursor. |
52 |
|
|
*/ |
53 |
|
|
#define LOG_CORRECT { \ |
54 |
|
|
if (!MAPPED_KEYS_WAITING(sp)) \ |
55 |
|
|
(void)log_cursor(sp); \ |
56 |
|
|
} |
57 |
|
|
|
58 |
|
|
static u_int32_t set_txt_std(SCR *, VICMD *, u_int32_t); |
59 |
|
|
|
60 |
|
|
/* |
61 |
|
|
* v_iA -- [count]A |
62 |
|
|
* Append text to the end of the line. |
63 |
|
|
* |
64 |
|
|
* PUBLIC: int v_iA(SCR *, VICMD *); |
65 |
|
|
*/ |
66 |
|
|
int |
67 |
|
|
v_iA(SCR *sp, VICMD *vp) |
68 |
|
|
{ |
69 |
|
|
size_t len; |
70 |
|
|
|
71 |
|
|
if (!db_get(sp, vp->m_start.lno, 0, NULL, &len)) |
72 |
|
|
sp->cno = len == 0 ? 0 : len - 1; |
73 |
|
|
|
74 |
|
|
LOG_CORRECT; |
75 |
|
|
|
76 |
|
|
return (v_ia(sp, vp)); |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
/* |
80 |
|
|
* v_ia -- [count]a |
81 |
|
|
* [count]A |
82 |
|
|
* Append text to the cursor position. |
83 |
|
|
* |
84 |
|
|
* PUBLIC: int v_ia(SCR *, VICMD *); |
85 |
|
|
*/ |
86 |
|
|
int |
87 |
|
|
v_ia(SCR *sp, VICMD *vp) |
88 |
|
|
{ |
89 |
|
|
size_t len; |
90 |
|
|
u_int32_t flags; |
91 |
|
|
int isempty; |
92 |
|
|
char *p; |
93 |
|
|
|
94 |
|
|
flags = set_txt_std(sp, vp, 0); |
95 |
|
|
sp->showmode = SM_APPEND; |
96 |
|
|
sp->lno = vp->m_start.lno; |
97 |
|
|
|
98 |
|
|
/* Move the cursor one column to the right and repaint the screen. */ |
99 |
|
|
if (db_eget(sp, sp->lno, &p, &len, &isempty)) { |
100 |
|
|
if (!isempty) |
101 |
|
|
return (1); |
102 |
|
|
len = 0; |
103 |
|
|
LF_SET(TXT_APPENDEOL); |
104 |
|
|
} else if (len) { |
105 |
|
|
if (len == sp->cno + 1) { |
106 |
|
|
sp->cno = len; |
107 |
|
|
LF_SET(TXT_APPENDEOL); |
108 |
|
|
} else |
109 |
|
|
++sp->cno; |
110 |
|
|
} else |
111 |
|
|
LF_SET(TXT_APPENDEOL); |
112 |
|
|
|
113 |
|
|
return (v_txt(sp, vp, NULL, p, len, |
114 |
|
|
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags)); |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
/* |
118 |
|
|
* v_iI -- [count]I |
119 |
|
|
* Insert text at the first nonblank. |
120 |
|
|
* |
121 |
|
|
* PUBLIC: int v_iI(SCR *, VICMD *); |
122 |
|
|
*/ |
123 |
|
|
int |
124 |
|
|
v_iI(SCR *sp, VICMD *vp) |
125 |
|
|
{ |
126 |
|
|
sp->cno = 0; |
127 |
|
|
if (nonblank(sp, vp->m_start.lno, &sp->cno)) |
128 |
|
|
return (1); |
129 |
|
|
|
130 |
|
|
LOG_CORRECT; |
131 |
|
|
|
132 |
|
|
return (v_ii(sp, vp)); |
133 |
|
|
} |
134 |
|
|
|
135 |
|
|
/* |
136 |
|
|
* v_ii -- [count]i |
137 |
|
|
* [count]I |
138 |
|
|
* Insert text at the cursor position. |
139 |
|
|
* |
140 |
|
|
* PUBLIC: int v_ii(SCR *, VICMD *); |
141 |
|
|
*/ |
142 |
|
|
int |
143 |
|
|
v_ii(SCR *sp, VICMD *vp) |
144 |
|
|
{ |
145 |
|
|
size_t len; |
146 |
|
|
u_int32_t flags; |
147 |
|
|
int isempty; |
148 |
|
|
char *p; |
149 |
|
|
|
150 |
|
|
flags = set_txt_std(sp, vp, 0); |
151 |
|
|
sp->showmode = SM_INSERT; |
152 |
|
|
sp->lno = vp->m_start.lno; |
153 |
|
|
|
154 |
|
|
if (db_eget(sp, sp->lno, &p, &len, &isempty)) { |
155 |
|
|
if (!isempty) |
156 |
|
|
return (1); |
157 |
|
|
len = 0; |
158 |
|
|
} |
159 |
|
|
|
160 |
|
|
if (len == 0) |
161 |
|
|
LF_SET(TXT_APPENDEOL); |
162 |
|
|
return (v_txt(sp, vp, NULL, p, len, |
163 |
|
|
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags)); |
164 |
|
|
} |
165 |
|
|
|
166 |
|
|
enum which { o_cmd, O_cmd }; |
167 |
|
|
static int io(SCR *, VICMD *, enum which); |
168 |
|
|
|
169 |
|
|
/* |
170 |
|
|
* v_iO -- [count]O |
171 |
|
|
* Insert text above this line. |
172 |
|
|
* |
173 |
|
|
* PUBLIC: int v_iO(SCR *, VICMD *); |
174 |
|
|
*/ |
175 |
|
|
int |
176 |
|
|
v_iO(SCR *sp, VICMD *vp) |
177 |
|
|
{ |
178 |
|
|
return (io(sp, vp, O_cmd)); |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
/* |
182 |
|
|
* v_io -- [count]o |
183 |
|
|
* Insert text after this line. |
184 |
|
|
* |
185 |
|
|
* PUBLIC: int v_io(SCR *, VICMD *); |
186 |
|
|
*/ |
187 |
|
|
int |
188 |
|
|
v_io(SCR *sp, VICMD *vp) |
189 |
|
|
{ |
190 |
|
|
return (io(sp, vp, o_cmd)); |
191 |
|
|
} |
192 |
|
|
|
193 |
|
|
static int |
194 |
|
|
io(SCR *sp, VICMD *vp, enum which cmd) |
195 |
|
|
{ |
196 |
|
|
recno_t ai_line, lno; |
197 |
|
|
size_t len; |
198 |
|
|
u_int32_t flags; |
199 |
|
|
char *p; |
200 |
|
|
|
201 |
|
|
flags = set_txt_std(sp, vp, TXT_ADDNEWLINE | TXT_APPENDEOL); |
202 |
|
|
sp->showmode = SM_INSERT; |
203 |
|
|
|
204 |
|
|
if (sp->lno == 1) { |
205 |
|
|
if (db_last(sp, &lno)) |
206 |
|
|
return (1); |
207 |
|
|
if (lno != 0) |
208 |
|
|
goto insert; |
209 |
|
|
p = NULL; |
210 |
|
|
len = 0; |
211 |
|
|
ai_line = OOBLNO; |
212 |
|
|
} else { |
213 |
|
|
insert: p = ""; |
214 |
|
|
sp->cno = 0; |
215 |
|
|
LOG_CORRECT; |
216 |
|
|
|
217 |
|
|
if (cmd == O_cmd) { |
218 |
|
|
if (db_insert(sp, sp->lno, p, 0)) |
219 |
|
|
return (1); |
220 |
|
|
if (db_get(sp, sp->lno, DBG_FATAL, &p, &len)) |
221 |
|
|
return (1); |
222 |
|
|
ai_line = sp->lno + 1; |
223 |
|
|
} else { |
224 |
|
|
if (db_append(sp, 1, sp->lno, p, 0)) |
225 |
|
|
return (1); |
226 |
|
|
if (db_get(sp, ++sp->lno, DBG_FATAL, &p, &len)) |
227 |
|
|
return (1); |
228 |
|
|
ai_line = sp->lno - 1; |
229 |
|
|
} |
230 |
|
|
} |
231 |
|
|
return (v_txt(sp, vp, NULL, p, len, |
232 |
|
|
0, ai_line, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags)); |
233 |
|
|
} |
234 |
|
|
|
235 |
|
|
/* |
236 |
|
|
* v_change -- [buffer][count]c[count]motion |
237 |
|
|
* [buffer][count]C |
238 |
|
|
* [buffer][count]S |
239 |
|
|
* Change command. |
240 |
|
|
* |
241 |
|
|
* PUBLIC: int v_change(SCR *, VICMD *); |
242 |
|
|
*/ |
243 |
|
|
int |
244 |
|
|
v_change(SCR *sp, VICMD *vp) |
245 |
|
|
{ |
246 |
|
|
size_t blen, len; |
247 |
|
|
u_int32_t flags; |
248 |
|
|
int isempty, lmode, rval; |
249 |
|
|
char *bp, *p; |
250 |
|
|
|
251 |
|
|
/* |
252 |
|
|
* 'c' can be combined with motion commands that set the resulting |
253 |
|
|
* cursor position, i.e. "cG". Clear the VM_RCM flags and make the |
254 |
|
|
* resulting cursor position stick, inserting text has its own rules |
255 |
|
|
* for cursor positioning. |
256 |
|
|
*/ |
257 |
|
|
F_CLR(vp, VM_RCM_MASK); |
258 |
|
|
F_SET(vp, VM_RCM_SET); |
259 |
|
|
|
260 |
|
|
/* |
261 |
|
|
* Find out if the file is empty, it's easier to handle it as a |
262 |
|
|
* special case. |
263 |
|
|
*/ |
264 |
|
|
if (vp->m_start.lno == vp->m_stop.lno && |
265 |
|
|
db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) { |
266 |
|
|
if (!isempty) |
267 |
|
|
return (1); |
268 |
|
|
return (v_ia(sp, vp)); |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
flags = set_txt_std(sp, vp, 0); |
272 |
|
|
sp->showmode = SM_CHANGE; |
273 |
|
|
|
274 |
|
|
/* |
275 |
|
|
* Move the cursor to the start of the change. Note, if autoindent |
276 |
|
|
* is turned on, the cc command in line mode changes from the first |
277 |
|
|
* *non-blank* character of the line, not the first character. And, |
278 |
|
|
* to make it just a bit more exciting, the initial space is handled |
279 |
|
|
* as auto-indent characters. |
280 |
|
|
*/ |
281 |
|
|
lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0; |
282 |
|
|
if (lmode) { |
283 |
|
|
vp->m_start.cno = 0; |
284 |
|
|
if (O_ISSET(sp, O_AUTOINDENT)) { |
285 |
|
|
if (nonblank(sp, vp->m_start.lno, &vp->m_start.cno)) |
286 |
|
|
return (1); |
287 |
|
|
LF_SET(TXT_AICHARS); |
288 |
|
|
} |
289 |
|
|
} |
290 |
|
|
sp->lno = vp->m_start.lno; |
291 |
|
|
sp->cno = vp->m_start.cno; |
292 |
|
|
|
293 |
|
|
LOG_CORRECT; |
294 |
|
|
|
295 |
|
|
/* |
296 |
|
|
* If not in line mode and changing within a single line, copy the |
297 |
|
|
* text and overwrite it. |
298 |
|
|
*/ |
299 |
|
|
if (!lmode && vp->m_start.lno == vp->m_stop.lno) { |
300 |
|
|
/* |
301 |
|
|
* !!! |
302 |
|
|
* Historic practice, c did not cut into the numeric buffers, |
303 |
|
|
* only the unnamed one. |
304 |
|
|
*/ |
305 |
|
|
if (cut(sp, |
306 |
|
|
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, |
307 |
|
|
&vp->m_start, &vp->m_stop, lmode)) |
308 |
|
|
return (1); |
309 |
|
|
if (len == 0) |
310 |
|
|
LF_SET(TXT_APPENDEOL); |
311 |
|
|
LF_SET(TXT_EMARK | TXT_OVERWRITE); |
312 |
|
|
return (v_txt(sp, vp, &vp->m_stop, p, len, |
313 |
|
|
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags)); |
314 |
|
|
} |
315 |
|
|
|
316 |
|
|
/* |
317 |
|
|
* It's trickier if in line mode or changing over multiple lines. If |
318 |
|
|
* we're in line mode delete all of the lines and insert a replacement |
319 |
|
|
* line which the user edits. If there was leading whitespace in the |
320 |
|
|
* first line being changed, we copy it and use it as the replacement. |
321 |
|
|
* If we're not in line mode, we delete the text and start inserting. |
322 |
|
|
* |
323 |
|
|
* !!! |
324 |
|
|
* Copy the text. Historic practice, c did not cut into the numeric |
325 |
|
|
* buffers, only the unnamed one. |
326 |
|
|
*/ |
327 |
|
|
if (cut(sp, |
328 |
|
|
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, |
329 |
|
|
&vp->m_start, &vp->m_stop, lmode)) |
330 |
|
|
return (1); |
331 |
|
|
|
332 |
|
|
/* If replacing entire lines and there's leading text. */ |
333 |
|
|
if (lmode && vp->m_start.cno) { |
334 |
|
|
/* |
335 |
|
|
* Get a copy of the first line changed, and copy out the |
336 |
|
|
* leading text. |
337 |
|
|
*/ |
338 |
|
|
if (db_get(sp, vp->m_start.lno, DBG_FATAL, &p, &len)) |
339 |
|
|
return (1); |
340 |
|
|
GET_SPACE_RET(sp, bp, blen, vp->m_start.cno); |
341 |
|
|
memmove(bp, p, vp->m_start.cno); |
342 |
|
|
} else |
343 |
|
|
bp = NULL; |
344 |
|
|
|
345 |
|
|
/* Delete the text. */ |
346 |
|
|
if (del(sp, &vp->m_start, &vp->m_stop, lmode)) |
347 |
|
|
return (1); |
348 |
|
|
|
349 |
|
|
/* If replacing entire lines, insert a replacement line. */ |
350 |
|
|
if (lmode) { |
351 |
|
|
if (db_insert(sp, vp->m_start.lno, bp, vp->m_start.cno)) |
352 |
|
|
return (1); |
353 |
|
|
sp->lno = vp->m_start.lno; |
354 |
|
|
len = sp->cno = vp->m_start.cno; |
355 |
|
|
} |
356 |
|
|
|
357 |
|
|
/* Get the line we're editing. */ |
358 |
|
|
if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) { |
359 |
|
|
if (!isempty) |
360 |
|
|
return (1); |
361 |
|
|
len = 0; |
362 |
|
|
} |
363 |
|
|
|
364 |
|
|
/* Check to see if we're appending to the line. */ |
365 |
|
|
if (vp->m_start.cno >= len) |
366 |
|
|
LF_SET(TXT_APPENDEOL); |
367 |
|
|
|
368 |
|
|
rval = v_txt(sp, vp, NULL, p, len, |
369 |
|
|
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags); |
370 |
|
|
|
371 |
|
|
if (bp != NULL) |
372 |
|
|
FREE_SPACE(sp, bp, blen); |
373 |
|
|
return (rval); |
374 |
|
|
} |
375 |
|
|
|
376 |
|
|
/* |
377 |
|
|
* v_Replace -- [count]R |
378 |
|
|
* Overwrite multiple characters. |
379 |
|
|
* |
380 |
|
|
* PUBLIC: int v_Replace(SCR *, VICMD *); |
381 |
|
|
*/ |
382 |
|
|
int |
383 |
|
|
v_Replace(SCR *sp, VICMD *vp) |
384 |
|
|
{ |
385 |
|
|
size_t len; |
386 |
|
|
u_int32_t flags; |
387 |
|
|
int isempty; |
388 |
|
|
char *p; |
389 |
|
|
|
390 |
|
|
flags = set_txt_std(sp, vp, 0); |
391 |
|
|
sp->showmode = SM_REPLACE; |
392 |
|
|
|
393 |
|
|
if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) { |
394 |
|
|
if (!isempty) |
395 |
|
|
return (1); |
396 |
|
|
len = 0; |
397 |
|
|
LF_SET(TXT_APPENDEOL); |
398 |
|
|
} else { |
399 |
|
|
if (len == 0) |
400 |
|
|
LF_SET(TXT_APPENDEOL); |
401 |
|
|
LF_SET(TXT_OVERWRITE | TXT_REPLACE); |
402 |
|
|
} |
403 |
|
|
vp->m_stop.lno = vp->m_start.lno; |
404 |
|
|
vp->m_stop.cno = len ? len - 1 : 0; |
405 |
|
|
|
406 |
|
|
return (v_txt(sp, vp, &vp->m_stop, p, len, |
407 |
|
|
0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags)); |
408 |
|
|
} |
409 |
|
|
|
410 |
|
|
/* |
411 |
|
|
* v_subst -- [buffer][count]s |
412 |
|
|
* Substitute characters. |
413 |
|
|
* |
414 |
|
|
* PUBLIC: int v_subst(SCR *, VICMD *); |
415 |
|
|
*/ |
416 |
|
|
int |
417 |
|
|
v_subst(SCR *sp, VICMD *vp) |
418 |
|
|
{ |
419 |
|
|
size_t len; |
420 |
|
|
u_int32_t flags; |
421 |
|
|
int isempty; |
422 |
|
|
char *p; |
423 |
|
|
|
424 |
|
|
flags = set_txt_std(sp, vp, 0); |
425 |
|
|
sp->showmode = SM_CHANGE; |
426 |
|
|
|
427 |
|
|
if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) { |
428 |
|
|
if (!isempty) |
429 |
|
|
return (1); |
430 |
|
|
len = 0; |
431 |
|
|
LF_SET(TXT_APPENDEOL); |
432 |
|
|
} else { |
433 |
|
|
if (len == 0) |
434 |
|
|
LF_SET(TXT_APPENDEOL); |
435 |
|
|
LF_SET(TXT_EMARK | TXT_OVERWRITE); |
436 |
|
|
} |
437 |
|
|
|
438 |
|
|
vp->m_stop.lno = vp->m_start.lno; |
439 |
|
|
vp->m_stop.cno = |
440 |
|
|
vp->m_start.cno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0); |
441 |
|
|
if (vp->m_stop.cno > len - 1) |
442 |
|
|
vp->m_stop.cno = len - 1; |
443 |
|
|
|
444 |
|
|
if (p != NULL && cut(sp, |
445 |
|
|
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, |
446 |
|
|
&vp->m_start, &vp->m_stop, 0)) |
447 |
|
|
return (1); |
448 |
|
|
|
449 |
|
|
return (v_txt(sp, vp, &vp->m_stop, p, len, 0, OOBLNO, 1, flags)); |
450 |
|
|
} |
451 |
|
|
|
452 |
|
|
/* |
453 |
|
|
* set_txt_std -- |
454 |
|
|
* Initialize text processing flags. |
455 |
|
|
*/ |
456 |
|
|
static u_int32_t |
457 |
|
|
set_txt_std(SCR *sp, VICMD *vp, u_int32_t flags) |
458 |
|
|
{ |
459 |
|
|
LF_SET(TXT_CNTRLT | |
460 |
|
|
TXT_ESCAPE | TXT_MAPINPUT | TXT_RECORD | TXT_RESOLVE); |
461 |
|
|
|
462 |
|
|
if (F_ISSET(vp, VC_ISDOT)) |
463 |
|
|
LF_SET(TXT_REPLAY); |
464 |
|
|
|
465 |
|
|
if (O_ISSET(sp, O_ALTWERASE)) |
466 |
|
|
LF_SET(TXT_ALTWERASE); |
467 |
|
|
if (O_ISSET(sp, O_AUTOINDENT)) |
468 |
|
|
LF_SET(TXT_AUTOINDENT); |
469 |
|
|
if (O_ISSET(sp, O_BEAUTIFY)) |
470 |
|
|
LF_SET(TXT_BEAUTIFY); |
471 |
|
|
if (O_ISSET(sp, O_SHOWMATCH)) |
472 |
|
|
LF_SET(TXT_SHOWMATCH); |
473 |
|
|
if (F_ISSET(sp, SC_SCRIPT)) |
474 |
|
|
LF_SET(TXT_CR); |
475 |
|
|
if (O_ISSET(sp, O_TTYWERASE)) |
476 |
|
|
LF_SET(TXT_TTYWERASE); |
477 |
|
|
|
478 |
|
|
/* |
479 |
|
|
* !!! |
480 |
|
|
* Mapped keys were sometimes unaffected by the wrapmargin option |
481 |
|
|
* in the historic 4BSD vi. Consider the following commands, where |
482 |
|
|
* each is executed on an empty line, in an 80 column screen, with |
483 |
|
|
* the wrapmargin value set to 60. |
484 |
|
|
* |
485 |
|
|
* aABC DEF <ESC>.... |
486 |
|
|
* :map K aABC DEF ^V<ESC><CR>KKKKK |
487 |
|
|
* :map K 5aABC DEF ^V<ESC><CR>K |
488 |
|
|
* |
489 |
|
|
* The first and second commands are affected by wrapmargin. The |
490 |
|
|
* third is not. (If the inserted text is itself longer than the |
491 |
|
|
* wrapmargin value, i.e. if the "ABC DEF " string is replaced by |
492 |
|
|
* something that's longer than 60 columns from the beginning of |
493 |
|
|
* the line, the first two commands behave as before, but the third |
494 |
|
|
* command gets fairly strange.) The problem is that people wrote |
495 |
|
|
* macros that depended on the third command NOT being affected by |
496 |
|
|
* wrapmargin, as in this gem which centers lines: |
497 |
|
|
* |
498 |
|
|
* map #c $mq81a ^V^[81^V^V|D`qld0:s/ / /g^V^M$p |
499 |
|
|
* |
500 |
|
|
* For compatibility reasons, we try and make it all work here. I |
501 |
|
|
* offer no hope that this is right, but it's probably pretty close. |
502 |
|
|
* |
503 |
|
|
* XXX |
504 |
|
|
* Once I work my courage up, this is all gonna go away. It's too |
505 |
|
|
* evil to survive. |
506 |
|
|
*/ |
507 |
|
|
if ((O_ISSET(sp, O_WRAPLEN) || O_ISSET(sp, O_WRAPMARGIN)) && |
508 |
|
|
(!MAPPED_KEYS_WAITING(sp) || !F_ISSET(vp, VC_C1SET))) |
509 |
|
|
LF_SET(TXT_WRAPMARGIN); |
510 |
|
|
return (flags); |
511 |
|
|
} |