Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 809 lines (695 sloc) 19.741 kB
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
1 /* exedit.c */
2 /* Copyright 1995 by Steve Kirkendall */
3
4
5 #include "elvis.h"
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
6 #ifdef FEATURE_RCSID
2fe6e17 @mbert Import Elvis 2.2_1 (written by Steve Kirkendall)
authored
7 char id_exedit[] = "$Id: exedit.c,v 2.71 2004/03/19 16:28:59 steve Exp $";
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
8 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
9
10
11 /* This command implements the :insert, :append, and :change commands */
12 RESULT ex_append(xinf)
13 EXINFO *xinf;
14 {
15 MARK where;
16
17 assert(xinf->command == EX_APPEND || xinf->command == EX_CHANGE
18 || xinf->command == EX_INSERT);
19
20 /* different behavior, depending on the command... */
21 if (xinf->command == EX_CHANGE)
22 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
23 cutyank('\0', xinf->fromaddr, xinf->toaddr, 'L', 'd');
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
24 where = markdup(xinf->fromaddr);
25 }
26 else if (xinf->command == EX_APPEND)
27 {
28 where = markdup(xinf->toaddr);
29 }
30 else
31 {
32 where = markdup(xinf->fromaddr);
33 }
34
35 /* Was the new text given as an argument to the command? */
36 if (xinf->rhs)
37 {
38 /* yes, insert the new text at the appropriate place */
39 bufreplace(where, where, xinf->rhs, (long)CHARlen(xinf->rhs));
40 }
41 xinf->newcurs = where;
42 return RESULT_COMPLETE;
43 }
44
45
46 /* This function implements the :delete and :yank command */
47 RESULT ex_delete(xinf)
48 EXINFO *xinf;
49 {
50 /* check the cut buffer name */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
51 if (xinf->cutbuf && !elvalnum(xinf->cutbuf) &&
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
52 xinf->cutbuf != '^' && xinf->cutbuf != '<' && xinf->cutbuf != '>')
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
53 {
54 msg(MSG_ERROR, "bad cut buffer");
55 return RESULT_ERROR;
56 }
57
58 /* do the command */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
59 cutyank(xinf->cutbuf, xinf->fromaddr, xinf->toaddr, (CHAR)'L', (ELVBOOL)(xinf->command == EX_DELETE) ? 'd' : 'y');
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
60 return RESULT_COMPLETE;
61 }
62
63
64 RESULT ex_global(xinf)
65 EXINFO *xinf;
66 {
67 CHAR *cp;
68 long lenln, endln;
69 RESULT ret = RESULT_COMPLETE;
70 MARK cursor;
71 MARK orig;
72 MARKBUF thisln;
3a9bb55 @mbert Import Elvis 2.1_3 (written by Steve Kirkendall)
authored
73 long origlines;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
74
75 assert(xinf->command == EX_GLOBAL || xinf->command == EX_VGLOBAL);
76
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
77 /* Default command is p, which should NOT be required */
78 if (!xinf->rhs)
79 xinf->rhs = CHARdup(toCHAR("p"));
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
80
81 /* ":g!" is like ":v" */
82 if (xinf->bang)
83 xinf->command = EX_VGLOBAL;
84
85 /* remember the cursor's original position. Inside the following loop,
86 * we'll force the cursor onto each matching line; when we're done,
87 * we'll move the cursor back and return the final position so the
88 * experform() function can move the cursor there in the conventional
89 * way -- that will be important if we switch buffers.
90 */
91 if (xinf->window->state->acton)
92 cursor = xinf->window->state->acton->cursor;
93 else
94 cursor = xinf->window->cursor;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
95 orig = markdup(cursor);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
96 if (markbuffer(cursor) != markbuffer(xinf->fromaddr))
97 {
98 marksetbuffer(cursor, markbuffer(xinf->fromaddr));
99 marksetoffset(cursor, markoffset(xinf->fromaddr));
100 }
101
3a9bb55 @mbert Import Elvis 2.1_3 (written by Steve Kirkendall)
authored
102 /* remember the number of lines before any changes... */
103 origlines = o_buflines(markbuffer(xinf->fromaddr));
104
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
105 #ifdef FEATURE_AUTOCMD
106 /* we want to trigger Edit events for change, even though we only save
107 * an undo version before the first change.
108 */
109 markbuffer(cursor)->eachedit = ElvTrue;
110 #endif
111
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
112 /* for each line... */
113 (void)scanalloc(&cp, xinf->fromaddr);
114 ret = RESULT_COMPLETE;
115 while (cp && markoffset(xinf->fromaddr) < markoffset(xinf->toaddr))
116 {
117 /* find the end of this line */
118 for (lenln = 0; cp && *cp != '\n'; lenln++)
119 (void)scannext(&cp);
120 if (cp)
121 {
122 (void)scannext(&cp);
123 lenln++;
124 }
125
126 /* move "fromaddr" to end of this line (start of next line) */
127 thisln = *xinf->fromaddr;
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
128 endln = cp ? markoffset(scanmark(&cp)) : markoffset(xinf->toaddr);
129 marksetoffset(xinf->fromaddr, endln);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
130
131 /* is this a selected line? */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
132 if ((regexec(xinf->re, &thisln, ElvTrue) ? EX_GLOBAL : EX_VGLOBAL)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
133 == xinf->command)
134 {
135
136 /* move the cursor to the matching line */
137 marksetoffset(cursor, endln - lenln);
138
139 /* free the scan pointer -- can't make changes
140 * while scanning.
141 */
142 scanfree(&cp);
143
144 /* execute the command */
3a9bb55 @mbert Import Elvis 2.1_3 (written by Steve Kirkendall)
authored
145 ret = exstring(xinf->window, xinf->rhs, NULL);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
146
147 /* reallocate the scan pointer */
148 (void)scanalloc(&cp, xinf->fromaddr);
149
150 /* if the ex command failed, then exit */
151 if (ret != RESULT_COMPLETE)
152 break;
153 }
154
155 /* if user wants to abort operation, then exit */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
156 if (guipoll(ElvFalse))
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
157 break;
158 }
159 scanfree(&cp);
160
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
161 #ifdef FEATURE_AUTOCMD
162 /* Revert to normal behavior of 1 Edit per "undo" version */
163 markbuffer(cursor)->eachedit = ElvTrue;
164 #endif
165
3a9bb55 @mbert Import Elvis 2.1_3 (written by Steve Kirkendall)
authored
166 /* report any change in the number of lines */
167 if (o_report != 0)
168 {
169 origlines -= o_buflines(markbuffer(cursor));
170 if (origlines >= o_report)
171 msg(MSG_INFO, "[d]$1 fewer lines", origlines);
172 else if (-origlines >= o_report)
173 msg(MSG_INFO, "[d]$1 more lines", -origlines);
174 }
175
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
176 /* move the cursor back to its original position, and then return
177 * the final position so the cursor will be moved there in a graceful
178 * way.
179 */
180 xinf->newcurs = markdup(cursor);
181 if (markbuffer(cursor) != markbuffer(orig))
182 marksetbuffer(cursor, markbuffer(orig));
183 marksetoffset(cursor, markoffset(orig));
184 markfree(orig);
185 return ret;
186 }
187
188
189 RESULT ex_join(xinf)
190 EXINFO *xinf;
191 {
192 CHAR prevchar; /* character before newline */
193 CHAR *cp; /* used while scanning for newlines */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
194 long njoined; /* number of lines joined */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
195 long newlines; /* number of newlines to be clobbered */
196 long nspaces; /* number of spaces to insert */
197 MARK start, end; /* region around a newline */
198 long offset; /* position of last change */
199 CHAR *endlist; /* string of sentence ending punctuation */
200 static CHAR spaces[3] = {' ', ' ', ' '};
201
202 /* initialize "offset" just to silence a compiler warning */
203 offset = 0;
204
205 /* initialize endlist from options (if set) or literals */
206 endlist = (o_sentenceend ? o_sentenceend : toCHAR(".!?"));
207
208 /* We're going to be replacing newlines with blanks. The number of
209 * newlines we want to replace is equal to the number lines affected
210 * minus one... except that if the user requested a "join" of a single
211 * line then we should assume we're supposed to join two lines.
212 */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
213 newlines = xinf->to - xinf->from;
2fe6e17 @mbert Import Elvis 2.2_1 (written by Steve Kirkendall)
authored
214 if (newlines == 0)
215 newlines = 1;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
216 if (xinf->from + newlines > o_buflines(markbuffer(xinf->fromaddr)))
217 {
218 msg(MSG_ERROR, "nothing to join with this line");
219 return RESULT_ERROR;;
220 }
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
221 njoined = newlines + 1;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
222
223 /* scan the text for newlines */
224 prevchar = ' ';
225 for (scanalloc(&cp, xinf->fromaddr); cp && newlines > 0; scannext(&cp))
226 {
227 /* if newline, then clobber it */
228 if (*cp == '\n')
229 {
230 start = markdup(scanmark(&cp));
231 offset = markoffset(start);
232 if (scannext(&cp))
233 {
234 /* figure out how many spaces to insert */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
235 if (xinf->bang || *cp == ')' || elvspace(prevchar))
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
236 nspaces = 0;
237 else if (CHARchr(toCHAR(endlist), prevchar))
238 nspaces = o_sentencegap;
239 else
240 nspaces = 1;
241
242 /* skip any leading whitespace in next line */
243 while (!xinf->bang && cp && (*cp == ' ' || *cp == '\t'))
244 {
245 scannext(&cp);
246 }
247
248 /* Find the end mark */
249 end = (cp ? markdup(scanmark(&cp))
250 : markalloc(markbuffer(start), o_bufchars(markbuffer(start))));
251
252 /* free the scan context during the change;
253 * can't mix scanning & updates.
254 */
255 scanfree(&cp);
256
257 /* replace the newline (and trailing whitespace)
258 * with a given number of spaces.
259 */
260 bufreplace(start, end, spaces, nspaces);
261 marksetoffset(end, offset + nspaces - 1);
262 /* NOTE: the "- 1" is to compensate for
263 * the scannext() at the top of the loop
264 */
265
266 /* resume scanning */
267 scanalloc(&cp, end);
268 markfree(end);
269 if (nspaces > 0)
270 {
271 prevchar = ' ';
272 }
273 }
274 markfree(start);
275
276 /* All that to clobber one newline! */
277 newlines--;
278 }
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
279 else if ((*cp != '"' && *cp != ')') || elvspace(prevchar))
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
280 {
281 /* remember the character. When we hit a newline,
282 * the previous character will be checked to determine
283 * how many spaces to insert. Note that we ignore
284 * quote and parenthesis characters except after a
285 * blank.
286 */
287 prevchar = *cp;
288 }
289 }
290 scanfree(&cp);
291
292 /* Choose a new cursor position: at the start of last joint */
293 xinf->newcurs = markalloc(markbuffer(xinf->fromaddr), offset);
294
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
295 /* Report it */
296 if (o_report != 0 && njoined >= o_report)
297 {
298 msg(MSG_INFO, "[d]$1 lines joined", njoined);
299 }
300
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
301 return RESULT_COMPLETE;
302 }
303
304
305 RESULT ex_move(xinf)
306 EXINFO *xinf;
307 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
308 long oldfrom, oldto, olddest, len;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
309
310 /* detect errors */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
311 oldfrom = markoffset(xinf->fromaddr);
312 oldto = markoffset(xinf->toaddr);
313 olddest = markoffset(xinf->destaddr);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
314 if (markbuffer(xinf->fromaddr) == markbuffer(xinf->destaddr)
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
315 && oldfrom < olddest
316 && olddest < oldto)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
317 {
318 msg(MSG_ERROR, "destination can't be inside source");
319 return RESULT_ERROR;
320 }
321
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
322 /* copy the text. Adjust the offsets explicitly */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
323 bufpaste(xinf->destaddr, xinf->fromaddr, xinf->toaddr);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
324 len = oldto - oldfrom;
325 if (olddest <= oldfrom)
326 {
327 oldfrom += len;
328 oldto += len;
329 }
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
330
331 /* leave the cursor on the last line of the destination */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
332 xinf->newcurs = markalloc(markbuffer(xinf->fromaddr), olddest+len-1);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
333 marksetoffset(xinf->newcurs, markoffset(
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
334 (*dmnormal.move)(xinf->window, xinf->newcurs, 0L, 0L, ElvFalse)));
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
335
336 /* If moving (not copying) then delete source */
337 if (xinf->command == EX_MOVE)
338 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
339 marksetoffset(xinf->fromaddr, oldfrom);
340 marksetoffset(xinf->toaddr, oldto);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
341 bufreplace(xinf->fromaddr, xinf->toaddr, NULL, 0);
342 }
343
344 return RESULT_COMPLETE;
345 }
346
347
348 RESULT ex_print(xinf)
349 EXINFO *xinf;
350 {
351 long last; /* offset of start of last line */
352 PFLAG pflag; /* how to print */
353
354 /* generate a pflag from the command name and any supplied pflag */
355 switch (xinf->pflag)
356 {
357 case PF_NONE:
358 case PF_PRINT:
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
359 pflag = (xinf->command == EX_NUMBER || o_number(xinf->window))
360 ? ((xinf->command == EX_LIST || o_list(xinf->window)) ? PF_NUMLIST : PF_NUMBER)
361 : ((xinf->command == EX_LIST || o_list(xinf->window)) ? PF_LIST : PF_PRINT);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
362 break;
363
364 case PF_LIST:
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
365 pflag = (xinf->command == EX_NUMBER || o_number(xinf->window)) ? PF_NUMLIST : PF_LIST;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
366 break;
367
368 case PF_NUMBER:
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
369 pflag = (xinf->command == EX_LIST || o_list(xinf->window))? PF_NUMLIST : PF_NUMBER;
370 break;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
371
372 default:
373 pflag = PF_NUMLIST;
374 break;
375 }
376
377 /* print the lines */
378 last = exprintlines(xinf->window, xinf->fromaddr, xinf->to - xinf->from + 1, pflag);
379
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
380 /* disable autoprinting for this command */
381 xinf->pflag = PF_NONE;
382
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
383 /* leave the cursor at the start of the last line */
384 xinf->newcurs = markalloc(markbuffer(xinf->fromaddr), last);
385 return RESULT_COMPLETE;
386 }
387
388
389 RESULT ex_put(xinf)
390 EXINFO *xinf;
391 {
392 MARK newcurs;
393
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
394 newcurs = cutput(xinf->cutbuf, xinf->window, xinf->fromaddr, (ELVBOOL)(xinf->from > 0), ElvFalse, ElvFalse);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
395 if (newcurs)
396 {
397 xinf->newcurs = markdup(newcurs);
398 return RESULT_COMPLETE;
399 }
400 return RESULT_ERROR;
401 }
402
403
404 RESULT ex_read(xinf)
405 EXINFO *xinf;
406 {
407 long offset;
408
409 if (!xinf->rhs && xinf->nfiles != 1)
410 {
411 msg(MSG_ERROR, "filename required");
412 return RESULT_ERROR;
413 }
414
415 /* remember where we started inserting */
416 offset = markoffset(xinf->toaddr);
417 xinf->newcurs = markdup(xinf->toaddr);
418
419 /* read in the text */
420 if (!bufread(xinf->toaddr, xinf->rhs ? tochar8(xinf->rhs) : xinf->file[0]))
421 {
422 return RESULT_ERROR;
423 }
424
425 /* Choose a place to leave the cursor. If reading due to visual <:>
426 * command, this should be the start of the first line read; else it
427 * should be the start of the last line read.
428 */
2fe6e17 @mbert Import Elvis 2.2_1 (written by Steve Kirkendall)
authored
429 if (xinf->window)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
430 {
2fe6e17 @mbert Import Elvis 2.2_1 (written by Steve Kirkendall)
authored
431 if (xinf->window->state->flags & ELVIS_1LINE)
432 {
433 marksetoffset(xinf->newcurs, offset);
434 }
435 else
436 {
437 marksetoffset(xinf->newcurs, markoffset(
438 (*xinf->window->md->move)(xinf->window, xinf->newcurs, -1, 0, ElvFalse)));
439 }
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
440 }
441 return RESULT_COMPLETE;
442 }
443
444
445 /* This function implements the :< and :> commands. It is also used to do
446 * the real work for the visual <<> and <>> operators.
447 */
448 RESULT ex_shift(xinf)
449 EXINFO *xinf;
450 {
451 long ws; /* amount of whitespace currently */
452 CHAR *cp; /* used for scanning through a line's whitespace */
453 long line; /* used for counting through line numbers */
454 MARKBUF start; /* start of the line */
455 MARKBUF end; /* end of the line's whitespace */
456 CHAR str[50];/* buffer for holding whitespace */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
457 short *sw; /* shiftwidth table */
458 short *ts; /* tabstop table */
459 long i, col;
460 long multi;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
461
462 /* for each line... */
463 start = xinf->defaddr;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
464 sw = o_shiftwidth(markbuffer(&start));
465 ts = o_tabstop(markbuffer(&start));
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
466 for (line = xinf->from; line <= xinf->to; line++)
467 {
468 /* count the current whitespace */
469 scanalloc(&cp, marksetline(&start, line));
470 for (ws = 0; cp && (*cp == ' ' || *cp == '\t'); scannext(&cp))
471 {
472 if (*cp == ' ')
473 ws++;
474 else
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
475 ws += opt_totab(ts, ws);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
476 }
477 end = *scanmark(&cp);
478
479 /* if this is an empty line, and no ! was given on the command
480 * line, then do nothing to this line.
481 */
482 if (ws == 0 && *cp == '\n' && !xinf->bang)
483 {
484 scanfree(&cp);
485 continue;
486 }
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
487
488 /* if this is a preprocessor line, then don't shift it
489 * unless "!" was given.
490 */
491 if (!xinf->bang
492 && xinf->window
493 && *cp == dmspreprocessor(xinf->window))
494 {
495 scanfree(&cp);
496 continue;
497 }
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
498 scanfree(&cp);
499
500 /* compute the amount of whitespace we want to have */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
501 if (xinf->bang)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
502 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
503 /* For the ^T/^D commands, align the text with the
504 * next shift column.
505 */
506 if (xinf->command == EX_SHIFTL)
507 {
508 do
509 {
510 ws--;
511 } while (ws > 0 && !opt_istab(sw, ws));
512 }
513 else
514 ws += opt_totab(sw, ws);
515 }
516 else if (xinf->command == EX_SHIFTL)
517 {
518 for (multi = xinf->multi; ws > 0 && --multi >= 0; )
519 {
520 /* For the :< command, or < visual
521 * operator, subtract this columns width
522 * unless we're on the first char of the
523 * column, in which case use the width of
524 * the previous column.
525 */
526 for (col = ws - 1; col > 0 && !opt_istab(sw, col); col--)
527 {
528 }
529 ws -= opt_totab(sw, col);
530 }
531 if (ws < 0)
532 ws = 0;
533 }
534 else /* xinf->command == EX_SHIFTR */
535 {
536 for (multi = xinf->multi; --multi >= 0; )
537 {
538 /* For the :> command, or > visual
539 * operator, add this shift column's width.
540 * To do that, we must first find its
541 * width.
542 */
543 for (col = ws; col > 0 && !opt_istab(sw, col); col--)
544 {
545 }
546 ws += opt_totab(sw, col);
547 }
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
548 }
549
550 /* Replace the old whitespace with new whitespace. Since our
551 * buffer for holding new whitespace is of limited size, we
552 * may need to make several bufreplace() calls to do this.
553 */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
554 col = 0;
555 while (markoffset(&start) != markoffset(&end) || ws > col)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
556 {
557 /* build new whitespace (as much of it as possible) */
558 i = 0;
559 if (o_autotab(markbuffer(&xinf->defaddr)))
560 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
561 while (ws >= col + opt_totab(ts, col)
562 && i < QTY(str))
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
563 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
564 str[i++] = '\t';
565 col += opt_totab(ts, col);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
566 }
567 }
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
568 while (ws > col && i < QTY(str))
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
569 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
570 str[i++] = ' ';
571 col++;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
572 }
573
574 /* replace old whitespace with new */
575 bufreplace(&start, &end, str, i);
576 markaddoffset(&start, i);
577 marksetoffset(&end, markoffset(&start));
578 }
579 }
580
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
581 if (o_report != 0 && xinf->to - xinf->from + 1 >= o_report)
582 msg(MSG_INFO,"[ds]$1 lines $2ed",
583 xinf->to - xinf->from + 1, xinf->cmdname);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
584
585 return RESULT_COMPLETE;
586 }
587
588
589 RESULT ex_undo(xinf)
590 EXINFO *xinf;
591 {
592 long l = 1;
593
594 assert(xinf->command == EX_UNDO || xinf->command == EX_REDO);
595
596 /* choose an undo/redo level to recover */
597 if (xinf->lhs)
598 {
599 if (!calcnumber(xinf->lhs) || (l = CHAR2long(xinf->lhs)) < 1)
600 {
601 msg(MSG_ERROR, "bad undo level");
602 return RESULT_ERROR;
603 }
604 }
605
606 /* if redo, then negate the undo value */
607 if (xinf->command == EX_REDO)
608 l = -l;
609
610 /* try to revert to the undo level */
611 l = bufundo(xinf->window->cursor, l);
612
613 /* if successful, adjust the cursor position */
614 if (l >= 0)
615 {
616 marksetoffset(xinf->window->cursor, l);
617 return RESULT_COMPLETE;
618 }
619
620 return RESULT_ERROR;
621 }
622
623
624 RESULT ex_write(xinf)
625 EXINFO *xinf;
626 {
627 char *name;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
628 ELVBOOL success;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
629
630 if (xinf->rhs)
631 {
632 name = tochar8(xinf->rhs);
633 }
2fe6e17 @mbert Import Elvis 2.2_1 (written by Steve Kirkendall)
authored
634 else
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
635 {
636 assert(xinf->nfiles == 1);
637 name = xinf->file[0];
638 }
639
640 /* if writing to a different filename, remember that name */
641 if (name[0] != '!'
642 && o_filename(markbuffer(xinf->fromaddr))
643 && CHARcmp(name, o_filename(markbuffer(xinf->fromaddr))))
644 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
645 if (name[0] == '>' && name[1] == '>')
646 optprevfile(toCHAR(name + 2), 1);
647 else
648 optprevfile(toCHAR(name), 1);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
649 }
650
651 /* actually write the file */
652 success = bufwrite(xinf->fromaddr, xinf->toaddr, name, xinf->bang);
653 return success ? RESULT_COMPLETE : RESULT_ERROR;
654 }
655
656
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
657 #ifdef FEATURE_MISC
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
658 RESULT ex_z(xinf)
659 EXINFO *xinf;
660 {
661 CHAR type = '+'; /* type of window to show */
662 long count = o_window; /* number of lines to show */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
663 PFLAG pflag; /* how to show */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
664 long line = xinf->from; /* first line to show */
665 long offset;
666 CHAR *scan;
667
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
668 /* choose a default printing style, from options */
669 if (o_number(xinf->window))
670 if (o_list(xinf->window))
671 pflag = PF_NUMLIST;
672 else
673 pflag = PF_NUMBER;
674 else
675 if (o_list(xinf->window))
676 pflag = PF_LIST;
677 else
678 pflag = PF_NUMBER;
679
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
680 /* If we were given arguments, then parse them */
681 for (scan = xinf->rhs; scan && *scan; scan++)
682 {
683 switch (*scan)
684 {
685 case '-':
686 case '+':
687 case '.':
688 case '^':
689 case '=':
690 type = *scan;
691 break;
692
693 case '0':
694 case '1':
695 case '2':
696 case '3':
697 case '4':
698 case '5':
699 case '6':
700 case '7':
701 case '8':
702 case '9':
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
703 for (count = 0; elvdigit(*scan); scan++)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
704 {
705 count = count * 10 + *scan - '0';
706 }
707 scan--; /* we went one character too far */
708 break;
709
710 case 'l':
711 if (pflag == PF_NUMBER || pflag == PF_NUMLIST)
712 pflag = PF_NUMLIST;
713 else
714 pflag = PF_LIST;
715 break;
716
717 case '#':
718 if (pflag == PF_LIST || pflag == PF_NUMLIST)
719 pflag = PF_NUMLIST;
720 else
721 pflag = PF_NUMBER;
722 break;
723
724 case ' ':
725 case '\t':
726 case 'p':
727 /* ignore */
728 break;
729
730 default:
731 msg(MSG_ERROR, "bad argument to :z");
732 return RESULT_ERROR;
733 }
734 }
735
736 /* choose the first line, based on the type */
737 switch (type)
738 {
739 case '-': /* show the given line at the bottom */
740 line = xinf->from - count + 1;
741 break;
742
743 case '+': /* show the given line at the top */
744 line = xinf->from;
745 break;
746
747 case '.': /* show the given line in the middle */
748 line = xinf->from - count/2;
749 break;
750
751 case '^': /* show the window before the current line */
752 line = xinf->from - count * 2 + 1;
753 break;
754
755 case '=': /* show it in the middle, surrounded by lines of hyphens */
756 count -= 2;
757 line = xinf->from - count / 2;
758 break;
759 }
760
761 /* protect against readed past top or bottom of buffer */
762 if (line < 1)
763 {
764 count -= 1 - line;
765 line = 1;
766 }
767 if (line + count > o_buflines(markbuffer(xinf->fromaddr)))
768 {
769 count -= line - o_buflines(markbuffer(xinf->fromaddr));
770 }
771
772 /* construct a mark for the first line */
773 xinf->newcurs = markdup(xinf->fromaddr);
774 marksetline(xinf->newcurs, line);
775
776 /* print the lines */
777 if (type == '=')
778 {
779 /* for '=', we need to add lines of hyphens around given line */
780 if (line < xinf->from)
781 {
782 exprintlines(xinf->window, xinf->newcurs, xinf->from - line, pflag);
783 }
784 drawextext(xinf->window, toCHAR("-------------------------------------------------------------------------------\n"), 80);
785 exprintlines(xinf->window, xinf->fromaddr, 1, pflag);
786 drawextext(xinf->window, toCHAR("-------------------------------------------------------------------------------\n"), 80);
787 count -= (xinf->from - line) + 1;
788 if (count > 0)
789 {
790 marksetline(xinf->newcurs, xinf->from + 1);
791 exprintlines(xinf->window, xinf->newcurs, count, pflag);
792 }
793
794 /* leave the cursor on the given line */
795 marksetoffset(xinf->newcurs, markoffset(xinf->fromaddr));
796 }
797 else
798 {
799 /* print the lines all at once */
800 offset = exprintlines(xinf->window, xinf->newcurs, count, pflag);
801
802 /* leave the cursor at the start of the last line */
803 marksetoffset(xinf->newcurs, offset);
804 }
805
806 return RESULT_COMPLETE;
807 }
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
808 #endif /* FEATURE_MISC */
Something went wrong with that request. Please try again.