Annotation of src/usr.bin/vim/ops.c, Revision 1.1.1.1
1.1 downsj 1: /* $OpenBSD$ */
2: /* vi:set ts=4 sw=4:
3: *
4: * VIM - Vi IMproved by Bram Moolenaar
5: *
6: * Do ":help uganda" in Vim to read copying and usage conditions.
7: * Do ":help credits" in Vim to see a list of people who contributed.
8: */
9:
10: /*
11: * ops.c: implementation of various operators: do_shift, do_delete, do_tilde,
12: * do_change, do_yank, do_put, do_join
13: */
14:
15: #include "vim.h"
16: #include "globals.h"
17: #include "proto.h"
18: #include "option.h"
19: #include "ops.h"
20:
21: /*
22: * Number of registers.
23: * 0 = unnamed register, for normal yanks and puts
24: * 1..9 = number registers, for deletes
25: * 10..35 = named registers
26: * 36 = delete register (-)
27: * 37 = GUI selection register (*). Only if USE_GUI defined
28: */
29: #ifdef USE_GUI
30: # define NUM_REGISTERS 38
31: #else
32: # define NUM_REGISTERS 37
33: #endif
34:
35: /*
36: * Symbolic names for some registers.
37: */
38: #define DELETION_REGISTER 36
39: #ifdef USE_GUI
40: # define GUI_SELECTION_REGISTER 37
41: #endif
42:
43: /*
44: * Each yank buffer is an array of pointers to lines.
45: */
46: static struct yankbuf
47: {
48: char_u **y_array; /* pointer to array of line pointers */
49: linenr_t y_size; /* number of lines in y_array */
50: char_u y_type; /* MLINE, MCHAR or MBLOCK */
51: } y_buf[NUM_REGISTERS];
52:
53: static struct yankbuf *y_current; /* ptr to current yank buffer */
54: static int yankappend; /* TRUE when appending */
55: static struct yankbuf *y_previous = NULL; /* ptr to last written yank buffr */
56:
57: /*
58: * structure used by block_prep, do_delete and do_yank for blockwise operators
59: */
60: struct block_def
61: {
62: int startspaces;
63: int endspaces;
64: int textlen;
65: char_u *textstart;
66: colnr_t textcol;
67: };
68:
69: static void get_yank_buffer __ARGS((int));
70: static int stuff_yank __ARGS((int, char_u *));
71: static void free_yank __ARGS((long));
72: static void free_yank_all __ARGS((void));
73: static void block_prep __ARGS((struct block_def *, linenr_t, int));
74: static int same_leader __ARGS((int, char_u *, int, char_u *));
75: static int fmt_end_block __ARGS((linenr_t, int *, char_u **));
76:
77: /*
78: * do_shift - handle a shift operation
79: */
80: void
81: do_shift(op, curs_top, amount)
82: int op;
83: int curs_top;
84: int amount;
85: {
86: register long i;
87: int first_char;
88:
89: if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
90: (linenr_t)(curwin->w_cursor.lnum + op_line_count)) == FAIL)
91: return;
92: for (i = op_line_count; --i >= 0; )
93: {
94: first_char = *ml_get_curline();
95: if (first_char == NUL) /* empty line */
96: curwin->w_cursor.col = 0;
97: /*
98: * Don't move the line right if it starts with # and p_si is set.
99: */
100: else
101: #if defined(SMARTINDENT) || defined(CINDENT)
102: if (first_char != '#' || (
103: # ifdef SMARTINDENT
104: !curbuf->b_p_si
105: # endif
106: # if defined(SMARTINDENT) && defined(CINDENT)
107: &&
108: # endif
109: # ifdef CINDENT
110: (!curbuf->b_p_cin || !in_cinkeys('#', ' ', TRUE))
111: # endif
112: ))
113: #endif
114: {
115: /* if (op_block_mode)
116: shift the block, not the whole line
117: else */
118: shift_line(op == LSHIFT, p_sr, amount);
119: }
120: ++curwin->w_cursor.lnum;
121: }
122:
123: if (curs_top) /* put cursor on first line, for ">>" */
124: {
125: curwin->w_cursor.lnum -= op_line_count;
126: beginline(MAYBE); /* shift_line() may have changed cursor.col */
127: }
128: else
129: --curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */
130: updateScreen(CURSUPD);
131:
132: if (op_line_count > p_report)
133: smsg((char_u *)"%ld line%s %ced %d time%s", op_line_count,
134: plural(op_line_count), (op == RSHIFT) ? '>' : '<',
135: amount, plural((long)amount));
136: }
137:
138: /*
139: * shift the current line one shiftwidth left (if left != 0) or right
140: * leaves cursor on first blank in the line
141: */
142: void
143: shift_line(left, round, amount)
144: int left;
145: int round;
146: int amount;
147: {
148: register int count;
149: register int i, j;
150: int p_sw = (int)curbuf->b_p_sw;
151:
152: count = get_indent(); /* get current indent */
153:
154: if (round) /* round off indent */
155: {
156: i = count / p_sw; /* number of p_sw rounded down */
157: j = count % p_sw; /* extra spaces */
158: if (j && left) /* first remove extra spaces */
159: --amount;
160: if (left)
161: {
162: i -= amount;
163: if (i < 0)
164: i = 0;
165: }
166: else
167: i += amount;
168: count = i * p_sw;
169: }
170: else /* original vi indent */
171: {
172: if (left)
173: {
174: count -= p_sw * amount;
175: if (count < 0)
176: count = 0;
177: }
178: else
179: count += p_sw * amount;
180: }
181: set_indent(count, TRUE); /* set new indent */
182: }
183:
184: #if defined(LISPINDENT) || defined(CINDENT)
185: /*
186: * do_reindent - handle reindenting a block of lines for C or lisp.
187: *
188: * mechanism copied from do_shift, above
189: */
190: void
191: do_reindent(how)
192: int (*how) __ARGS((void));
193: {
194: register long i;
195: char_u *l;
196: int count;
197:
198: if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
199: (linenr_t)(curwin->w_cursor.lnum + op_line_count)) == FAIL)
200: return;
201:
202: for (i = op_line_count; --i >= 0 && !got_int; )
203: {
204: /* it's a slow thing to do, so give feedback so there's no worry that
205: * the computer's just hung. */
206:
207: if ((i % 50 == 0 || i == op_line_count - 1) && op_line_count > p_report)
208: smsg((char_u *)"%ld line%s to indent... ", i, plural(i));
209:
210: /*
211: * Be vi-compatible: For lisp indenting the first line is not
212: * indented, unless there is only one line.
213: */
214: #ifdef LISPINDENT
215: if (i != op_line_count - 1 || op_line_count == 1 ||
216: how != get_lisp_indent)
217: #endif
218: {
219: l = skipwhite(ml_get_curline());
220: if (*l == NUL) /* empty or blank line */
221: count = 0;
222: else
223: count = how(); /* get the indent for this line */
224:
225: set_indent(count, TRUE);
226: }
227: ++curwin->w_cursor.lnum;
228: }
229:
230: /* put cursor on first non-blank of indented line */
231: curwin->w_cursor.lnum -= op_line_count;
232: beginline(MAYBE);
233:
234: updateScreen(CURSUPD);
235:
236: if (op_line_count > p_report)
237: {
238: i = op_line_count - (i + 1);
239: smsg((char_u *)"%ld line%s indented ", i, plural(i));
240: }
241: }
242: #endif /* defined(LISPINDENT) || defined(CINDENT) */
243:
244: /*
245: * check if character is name of yank buffer
246: * Note: There is no check for 0 (default register), caller should do this
247: */
248: int
249: is_yank_buffer(c, writing)
250: int c;
251: int writing; /* if TRUE check for writable buffers */
252: {
253: if (c > '~')
254: return FALSE;
255: if (isalnum(c) || (!writing && vim_strchr((char_u *)".%:", c) != NULL) ||
256: c == '"' || c == '-'
257: #ifdef USE_GUI
258: || (gui.in_use && c == '*')
259: #endif
260: )
261: return TRUE;
262: return FALSE;
263: }
264:
265: /*
266: * Set y_current and yankappend, according to the value of yankbuffer.
267: *
268: * If yankbuffer is 0 and writing, use buffer 0
269: * If yankbuffer is 0 and reading, use previous buffer
270: */
271: static void
272: get_yank_buffer(writing)
273: int writing;
274: {
275: register int i;
276:
277: yankappend = FALSE;
278: if (((yankbuffer == 0 && !writing) || yankbuffer == '"') &&
279: y_previous != NULL)
280: {
281: y_current = y_previous;
282: return;
283: }
284: i = yankbuffer;
285: if (isdigit(i))
286: i -= '0';
287: else if (islower(i))
288: i -= 'a' - 10;
289: else if (isupper(i))
290: {
291: i -= 'A' - 10;
292: yankappend = TRUE;
293: }
294: else if (yankbuffer == '-')
295: i = DELETION_REGISTER;
296: #ifdef USE_GUI
297: else if (gui.in_use && yankbuffer == '*')
298: i = GUI_SELECTION_REGISTER;
299: #endif
300: else /* not 0-9, a-z, A-Z or '-': use buffer 0 */
301: i = 0;
302: y_current = &(y_buf[i]);
303: if (writing) /* remember the buffer we write into for do_put() */
304: y_previous = y_current;
305: }
306:
307: /*
308: * return TRUE if the current yank buffer has type MLINE
309: */
310: int
311: yank_buffer_mline()
312: {
313: if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, FALSE))
314: return FALSE;
315: get_yank_buffer(FALSE);
316: return (y_current->y_type == MLINE);
317: }
318:
319: /*
320: * start or stop recording into a yank buffer
321: *
322: * return FAIL for failure, OK otherwise
323: */
324: int
325: do_record(c)
326: int c;
327: {
328: char_u *p;
329: static int bufname;
330: int retval;
331:
332: if (Recording == FALSE) /* start recording */
333: {
334: /* registers 0-9, a-z and " are allowed */
335: if (c > '~' || (!isalnum(c) && c != '"'))
336: retval = FAIL;
337: else
338: {
339: Recording = TRUE;
340: showmode();
341: bufname = c;
342: retval = OK;
343: }
344: }
345: else /* stop recording */
346: {
347: Recording = FALSE;
348: MSG("");
349: p = get_recorded();
350: if (p == NULL)
351: retval = FAIL;
352: else
353: retval = (stuff_yank(bufname, p));
354: }
355: return retval;
356: }
357:
358: /*
359: * stuff string 'p' into yank buffer 'bufname' (append if uppercase)
360: * 'p' is assumed to be alloced.
361: *
362: * return FAIL for failure, OK otherwise
363: */
364: static int
365: stuff_yank(bufname, p)
366: int bufname;
367: char_u *p;
368: {
369: char_u *lp;
370: char_u **pp;
371:
372: yankbuffer = bufname;
373: /* check for read-only buffer */
374: if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, TRUE))
375: return FAIL;
376: get_yank_buffer(TRUE);
377: if (yankappend && y_current->y_array != NULL)
378: {
379: pp = &(y_current->y_array[y_current->y_size - 1]);
380: lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
381: if (lp == NULL)
382: {
383: vim_free(p);
384: return FAIL;
385: }
386: STRCPY(lp, *pp);
387: STRCAT(lp, p);
388: vim_free(p);
389: vim_free(*pp);
390: *pp = lp;
391: }
392: else
393: {
394: free_yank_all();
395: if ((y_current->y_array =
396: (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
397: {
398: vim_free(p);
399: return FAIL;
400: }
401: y_current->y_array[0] = p;
402: y_current->y_size = 1;
403: y_current->y_type = MCHAR; /* used to be MLINE, why? */
404: }
405: return OK;
406: }
407:
408: /*
409: * execute a yank buffer (register): copy it into the stuff buffer
410: *
411: * return FAIL for failure, OK otherwise
412: */
413: int
414: do_execbuf(c, colon, addcr)
415: int c;
416: int colon; /* insert ':' before each line */
417: int addcr; /* always add '\n' to end of line */
418: {
419: static int lastc = NUL;
420: long i;
421: char_u *p;
422: int truncated;
423: int retval;
424:
425:
426: if (c == '@') /* repeat previous one */
427: c = lastc;
428: if (c == '%' || !is_yank_buffer(c, FALSE)) /* check for valid buffer */
429: return FAIL;
430: lastc = c;
431:
432: if (c == ':') /* use last command line */
433: {
434: if (last_cmdline == NULL)
435: {
436: EMSG(e_nolastcmd);
437: return FAIL;
438: }
439: vim_free(new_last_cmdline); /* don't keep the cmdline containing @: */
440: new_last_cmdline = NULL;
441: if (ins_typebuf((char_u *)"\n", FALSE, 0, TRUE) == FAIL)
442: return FAIL;
443: if (ins_typebuf(last_cmdline, FALSE, 0, TRUE) == FAIL)
444: return FAIL;
445: if (ins_typebuf((char_u *)":", FALSE, 0, TRUE) == FAIL)
446: return FAIL;
447: }
448: else if (c == '.') /* use last inserted text */
449: {
450: p = get_last_insert();
451: if (p == NULL)
452: {
453: EMSG(e_noinstext);
454: return FAIL;
455: }
456: i = STRLEN(p);
457: if (i > 0 && p[i - 1] == ESC) /* remove trailing ESC */
458: {
459: p[i - 1] = NUL;
460: truncated = TRUE;
461: }
462: else
463: truncated = FALSE;
464: retval = ins_typebuf(p, FALSE, 0, TRUE);
465: if (truncated)
466: p[i - 1] = ESC;
467: return retval;
468: }
469: else
470: {
471: yankbuffer = c;
472: get_yank_buffer(FALSE);
473: if (y_current->y_array == NULL)
474: return FAIL;
475:
476: /*
477: * Insert lines into typeahead buffer, from last one to first one.
478: */
479: for (i = y_current->y_size; --i >= 0; )
480: {
481: /* insert newline between lines and after last line if type is MLINE */
482: if (y_current->y_type == MLINE || i < y_current->y_size - 1
483: || addcr)
484: {
485: if (ins_typebuf((char_u *)"\n", FALSE, 0, TRUE) == FAIL)
486: return FAIL;
487: }
488: if (ins_typebuf(y_current->y_array[i], FALSE, 0, TRUE) == FAIL)
489: return FAIL;
490: if (colon && ins_typebuf((char_u *)":", FALSE, 0, TRUE) == FAIL)
491: return FAIL;
492: }
493: Exec_reg = TRUE; /* disable the 'q' command */
494: }
495: return OK;
496: }
497:
498: /*
499: * Insert a yank buffer: copy it into the Read buffer.
500: * Used by CTRL-R command and middle mouse button in insert mode.
501: *
502: * return FAIL for failure, OK otherwise
503: */
504: int
505: insertbuf(c)
506: int c;
507: {
508: long i;
509: int retval = OK;
510:
511: /*
512: * It is possible to get into an endless loop by having CTRL-R a in
513: * register a and then, in insert mode, doing CTRL-R a.
514: * If you hit CTRL-C, the loop will be broken here.
515: */
516: mch_breakcheck();
517: if (got_int)
518: return FAIL;
519:
520: /* check for valid buffer */
521: if (c != NUL && !is_yank_buffer(c, FALSE))
522: return FAIL;
523:
524: #ifdef USE_GUI
525: if (c == '*')
526: gui_get_selection(); /* may fill * register */
527: #endif
528:
529: if (c == '.') /* insert last inserted text */
530: retval = stuff_inserted(NUL, 1L, TRUE);
531: else if (c == '%') /* insert file name */
532: {
533: if (check_fname() == FAIL)
534: return FAIL;
535: stuffReadbuff(curbuf->b_xfilename);
536: }
537: else if (c == ':') /* insert last command line */
538: {
539: if (last_cmdline == NULL)
540: {
541: EMSG(e_nolastcmd);
542: return FAIL;
543: }
544: stuffReadbuff(last_cmdline);
545: }
546: else /* name or number register */
547: {
548: yankbuffer = c;
549: get_yank_buffer(FALSE);
550: if (y_current->y_array == NULL)
551: retval = FAIL;
552: else
553: {
554:
555: for (i = 0; i < y_current->y_size; ++i)
556: {
557: stuffReadbuff(y_current->y_array[i]);
558: /* insert newline between lines and after last line if type is
559: * MLINE */
560: if (y_current->y_type == MLINE || i < y_current->y_size - 1)
561: stuffReadbuff((char_u *)"\n");
562: }
563: }
564: }
565:
566: return retval;
567: }
568:
569: /*
570: * paste a yank buffer into the command line.
571: * used by CTRL-R command in command-line mode
572: * insertbuf() can't be used here, because special characters from the
573: * register contents will be interpreted as commands.
574: *
575: * return FAIL for failure, OK otherwise
576: */
577: int
578: cmdline_paste(c)
579: int c;
580: {
581: long i;
582:
583: if (!is_yank_buffer(c, FALSE)) /* check for valid buffer */
584: return FAIL;
585:
586: #ifdef USE_GUI
587: if (c == '*')
588: gui_get_selection();
589: #endif
590:
591: if (c == '.') /* insert last inserted text */
592: return FAIL; /* Unimplemented */
593:
594: if (c == '%') /* insert file name */
595: {
596: if (check_fname() == FAIL)
597: return FAIL;
598: return put_on_cmdline(curbuf->b_xfilename, -1, TRUE);
599: }
600:
601: if (c == ':') /* insert last command line */
602: {
603: if (last_cmdline == NULL)
604: return FAIL;
605: return put_on_cmdline(last_cmdline, -1, TRUE);
606: }
607:
608: yankbuffer = c;
609: get_yank_buffer(FALSE);
610: if (y_current->y_array == NULL)
611: return FAIL;
612:
613: for (i = 0; i < y_current->y_size; ++i)
614: {
615: put_on_cmdline(y_current->y_array[i], -1, FALSE);
616:
617: /* insert ^M between lines and after last line if type is MLINE */
618: if (y_current->y_type == MLINE || i < y_current->y_size - 1)
619: put_on_cmdline((char_u *)"\r", 1, FALSE);
620: }
621: return OK;
622: }
623:
624: /*
625: * do_delete - handle a delete operation
626: */
627: void
628: do_delete()
629: {
630: register int n;
631: linenr_t lnum;
632: char_u *ptr;
633: char_u *newp, *oldp;
634: linenr_t old_lcount = curbuf->b_ml.ml_line_count;
635: int did_yank = FALSE;
636: struct block_def bd;
637:
638: if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to do */
639: return;
640:
641: /*
642: * Imitate the strange Vi behaviour: If the delete spans more than one line
643: * and op_motion_type == MCHAR and the result is a blank line, make the delete
644: * linewise. Don't do this for the change command.
645: */
646: if (op_motion_type == MCHAR && op_line_count > 1 && op_type == DELETE)
647: {
648: ptr = ml_get(curbuf->b_op_end.lnum) + curbuf->b_op_end.col +
649: op_inclusive;
650: ptr = skipwhite(ptr);
651: if (*ptr == NUL && inindent(0))
652: op_motion_type = MLINE;
653: }
654:
655: /*
656: * Check for trying to delete (e.g. "D") in an empty line.
657: * Note: For change command it is ok.
658: */
659: if (op_motion_type == MCHAR && op_line_count == 1 &&
660: op_type == DELETE && *ml_get(curbuf->b_op_start.lnum) == NUL)
661: {
662: beep_flush();
663: return;
664: }
665:
666: /*
667: * Do a yank of whatever we're about to delete.
668: * If a yank buffer was specified, put the deleted text into that buffer
669: */
670: if (yankbuffer != 0)
671: {
672: /* check for read-only buffer */
673: if (!is_yank_buffer(yankbuffer, TRUE))
674: {
675: beep_flush();
676: return;
677: }
678: get_yank_buffer(TRUE); /* yank into specified buffer */
679: if (do_yank(TRUE, FALSE) == OK) /* yank without message */
680: did_yank = TRUE;
681: }
682:
683: /*
684: * Put deleted text into register 1 and shift number buffers if
685: * the delete contains a line break, or when a yankbuffer has been specified!
686: */
687: if (yankbuffer != 0 || op_motion_type == MLINE || op_line_count > 1)
688: {
689: y_current = &y_buf[9];
690: free_yank_all(); /* free buffer nine */
691: for (n = 9; n > 1; --n)
692: y_buf[n] = y_buf[n - 1];
693: y_previous = y_current = &y_buf[1];
694: y_buf[1].y_array = NULL; /* set buffer one to empty */
695: yankbuffer = 0;
696: }
697: else if (yankbuffer == 0) /* yank into unnamed buffer */
698: {
699: yankbuffer = '-'; /* use special delete buffer */
700: get_yank_buffer(TRUE);
701: yankbuffer = 0;
702: }
703:
704: if (yankbuffer == 0 && do_yank(TRUE, FALSE) == OK)
705: did_yank = TRUE;
706:
707: /*
708: * If there's too much stuff to fit in the yank buffer, then get a
709: * confirmation before doing the delete. This is crude, but simple. And it
710: * avoids doing a delete of something we can't put back if we want.
711: */
712: if (!did_yank)
713: {
714: if (ask_yesno((char_u *)"cannot yank; delete anyway", TRUE) != 'y')
715: {
716: emsg(e_abort);
717: return;
718: }
719: }
720:
721: /*
722: * block mode delete
723: */
724: if (op_block_mode)
725: {
726: if (u_save((linenr_t)(curbuf->b_op_start.lnum - 1),
727: (linenr_t)(curbuf->b_op_end.lnum + 1)) == FAIL)
728: return;
729:
730: for (lnum = curwin->w_cursor.lnum;
731: curwin->w_cursor.lnum <= curbuf->b_op_end.lnum;
732: ++curwin->w_cursor.lnum)
733: {
734: block_prep(&bd, curwin->w_cursor.lnum, TRUE);
735: if (bd.textlen == 0) /* nothing to delete */
736: continue;
737:
738: /*
739: * If we delete a TAB, it may be replaced by several characters.
740: * Thus the number of characters may increase!
741: */
742: n = bd.textlen - bd.startspaces - bd.endspaces; /* number of chars deleted */
743: oldp = ml_get_curline();
744: newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
745: if (newp == NULL)
746: continue;
747: /* copy up to deleted part */
748: vim_memmove(newp, oldp, (size_t)bd.textcol);
749: /* insert spaces */
750: copy_spaces(newp + bd.textcol, (size_t)(bd.startspaces + bd.endspaces));
751: /* copy the part after the deleted part */
752: oldp += bd.textcol + bd.textlen;
753: vim_memmove(newp + bd.textcol + bd.startspaces + bd.endspaces,
754: oldp, STRLEN(oldp) + 1);
755: /* replace the line */
756: ml_replace(curwin->w_cursor.lnum, newp, FALSE);
757: }
758: curwin->w_cursor.lnum = lnum;
759: CHANGED;
760: updateScreen(VALID_TO_CURSCHAR);
761: op_line_count = 0; /* no lines deleted */
762: }
763: else if (op_motion_type == MLINE)
764: {
765: if (op_type == CHANGE)
766: {
767: /* Delete the lines except the first one.
768: * Temporarily move the cursor to the next line.
769: * Save the current line number, if the last line is deleted
770: * it may be changed.
771: */
772: if (op_line_count > 1)
773: {
774: lnum = curwin->w_cursor.lnum;
775: ++curwin->w_cursor.lnum;
776: dellines((long)(op_line_count - 1), TRUE, TRUE);
777: curwin->w_cursor.lnum = lnum;
778: }
779: if (u_save_cursor() == FAIL)
780: return;
781: if (curbuf->b_p_ai) /* don't delete indent */
782: {
783: beginline(TRUE); /* put cursor on first non-white */
784: did_ai = TRUE; /* delete the indent when ESC hit */
785: }
786: truncate_line(FALSE);
787: if (curwin->w_cursor.col > 0)
788: --curwin->w_cursor.col; /* put cursor on last char in line */
789: }
790: else
791: {
792: dellines(op_line_count, TRUE, TRUE);
793: }
794: u_clearline(); /* "U" command should not be possible after "dd" */
795: beginline(TRUE);
796: }
797: else if (op_line_count == 1) /* delete characters within one line */
798: {
799: if (u_save_cursor() == FAIL)
800: return;
801: /* if 'cpoptions' contains '$', display '$' at end of change */
802: if (vim_strchr(p_cpo, CPO_DOLLAR) != NULL && op_type == CHANGE &&
803: curbuf->b_op_end.lnum == curwin->w_cursor.lnum && !op_is_VIsual)
804: display_dollar(curbuf->b_op_end.col - !op_inclusive);
805: n = curbuf->b_op_end.col - curbuf->b_op_start.col + 1 - !op_inclusive;
806: while (n-- > 0)
807: if (delchar(TRUE) == FAIL)
808: break;
809: }
810: else /* delete characters between lines */
811: {
812: if (u_save_cursor() == FAIL) /* save first line for undo */
813: return;
814: truncate_line(TRUE); /* delete from cursor to end of line */
815:
816: curbuf->b_op_start = curwin->w_cursor; /* remember curwin->w_cursor */
817: ++curwin->w_cursor.lnum;
818: /* includes save for undo */
819: dellines((long)(op_line_count - 2), TRUE, TRUE);
820:
821: if (u_save_cursor() == FAIL) /* save last line for undo */
822: return;
823: n = curbuf->b_op_end.col - !op_inclusive;
824: curwin->w_cursor.col = 0;
825: while (n-- >= 0) /* delete from start of line until op_end */
826: if (delchar(TRUE) == FAIL)
827: break;
828: curwin->w_cursor = curbuf->b_op_start; /* restore curwin->w_cursor */
829: (void)do_join(FALSE, curs_rows() == OK);
830: }
831:
832: if ((op_motion_type == MCHAR && op_line_count == 1) || op_type == CHANGE)
833: {
834: if (dollar_vcol)
835: must_redraw = 0; /* don't want a redraw now */
836: cursupdate();
837: if (!dollar_vcol)
838: updateline();
839: }
840: else if (!global_busy) /* no need to update screen for :global */
841: updateScreen(CURSUPD);
842:
843: msgmore(curbuf->b_ml.ml_line_count - old_lcount);
844:
845: /* correct op_end for deleted text (for "']" command) */
846: if (op_block_mode)
847: curbuf->b_op_end.col = curbuf->b_op_start.col;
848: else
849: curbuf->b_op_end = curbuf->b_op_start;
850: }
851:
852: /*
853: * do_tilde - handle the (non-standard vi) tilde operator
854: */
855: void
856: do_tilde()
857: {
858: FPOS pos;
859: struct block_def bd;
860:
861: if (u_save((linenr_t)(curbuf->b_op_start.lnum - 1),
862: (linenr_t)(curbuf->b_op_end.lnum + 1)) == FAIL)
863: return;
864:
865: pos = curbuf->b_op_start;
866: if (op_block_mode) /* Visual block mode */
867: {
868: for (; pos.lnum <= curbuf->b_op_end.lnum; ++pos.lnum)
869: {
870: block_prep(&bd, pos.lnum, FALSE);
871: pos.col = bd.textcol;
872: while (--bd.textlen >= 0)
873: {
874: swapchar(&pos);
875: if (inc(&pos) == -1) /* at end of file */
876: break;
877: }
878: }
879: }
880: else /* not block mode */
881: {
882: if (op_motion_type == MLINE)
883: {
884: pos.col = 0;
885: curbuf->b_op_end.col = STRLEN(ml_get(curbuf->b_op_end.lnum));
886: if (curbuf->b_op_end.col)
887: --curbuf->b_op_end.col;
888: }
889: else if (!op_inclusive)
890: dec(&(curbuf->b_op_end));
891:
892: while (ltoreq(pos, curbuf->b_op_end))
893: {
894: swapchar(&pos);
895: if (inc(&pos) == -1) /* at end of file */
896: break;
897: }
898: }
899:
900: if (op_motion_type == MCHAR && op_line_count == 1 && !op_block_mode)
901: {
902: cursupdate();
903: updateline();
904: }
905: else
906: updateScreen(CURSUPD);
907:
908: if (op_line_count > p_report)
909: smsg((char_u *)"%ld line%s ~ed",
910: op_line_count, plural(op_line_count));
911: }
912:
913: /*
914: * If op_type == UPPER: make uppercase,
915: * if op_type == LOWER: make lowercase,
916: * else swap case of character at 'pos'
917: */
918: void
919: swapchar(pos)
920: FPOS *pos;
921: {
922: int c;
923:
924: c = gchar(pos);
925: if (islower(c) && op_type != LOWER)
926: {
927: pchar(*pos, toupper(c));
928: CHANGED;
929: }
930: else if (isupper(c) && op_type != UPPER)
931: {
932: pchar(*pos, tolower(c));
933: CHANGED;
934: }
935: }
936:
937: /*
938: * do_change - handle a change operation
939: *
940: * return TRUE if edit() returns because of a CTRL-O command
941: */
942: int
943: do_change()
944: {
945: register colnr_t l;
946:
947: l = curbuf->b_op_start.col;
948: if (op_motion_type == MLINE)
949: {
950: l = 0;
951: can_si = TRUE; /* It's like opening a new line, do si */
952: }
953:
954: if (!op_empty)
955: do_delete(); /* delete the text and take care of undo */
956:
957: if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum))
958: inc_cursor();
959:
960: #ifdef LISPINDENT
961: if (op_motion_type == MLINE)
962: {
963: if (curbuf->b_p_lisp && curbuf->b_p_ai)
964: fixthisline(get_lisp_indent);
965: # ifdef CINDENT
966: else if (curbuf->b_p_cin)
967: fixthisline(get_c_indent);
968: # endif
969: }
970: #endif
971:
972: op_type = NOP; /* don't want op_type == CHANGED in Insert mode */
973: return edit(NUL, FALSE, (linenr_t)1);
974: }
975:
976: /*
977: * set all the yank buffers to empty (called from main())
978: */
979: void
980: init_yank()
981: {
982: register int i;
983:
984: for (i = 0; i < NUM_REGISTERS; ++i)
985: y_buf[i].y_array = NULL;
986: }
987:
988: /*
989: * Free "n" lines from the current yank buffer.
990: * Called for normal freeing and in case of error.
991: */
992: static void
993: free_yank(n)
994: long n;
995: {
996: if (y_current->y_array != NULL)
997: {
998: register long i;
999:
1000: for (i = n; --i >= 0; )
1001: {
1002: if ((i & 1023) == 1023) /* this may take a while */
1003: {
1004: /*
1005: * This message should never cause a hit-return message.
1006: * Overwrite this message with any next message.
1007: */
1008: ++no_wait_return;
1009: smsg((char_u *)"freeing %ld lines", i + 1);
1010: --no_wait_return;
1011: msg_didout = FALSE;
1012: msg_col = 0;
1013: }
1014: vim_free(y_current->y_array[i]);
1015: }
1016: vim_free(y_current->y_array);
1017: y_current->y_array = NULL;
1018: if (n >= 1000)
1019: MSG("");
1020: }
1021: }
1022:
1023: static void
1024: free_yank_all()
1025: {
1026: free_yank(y_current->y_size);
1027: }
1028:
1029: /*
1030: * Yank the text between curwin->w_cursor and startpos into a yank buffer.
1031: * If we are to append ("uppercase), we first yank into a new yank buffer and
1032: * then concatenate the old and the new one (so we keep the old one in case
1033: * of out-of-memory).
1034: *
1035: * return FAIL for failure, OK otherwise
1036: */
1037: int
1038: do_yank(deleting, mess)
1039: int deleting;
1040: int mess;
1041: {
1042: long i; /* index in y_array[] */
1043: struct yankbuf *curr; /* copy of y_current */
1044: struct yankbuf newbuf; /* new yank buffer when appending */
1045: char_u **new_ptr;
1046: register linenr_t lnum; /* current line number */
1047: long j;
1048: int yanktype = op_motion_type;
1049: long yanklines = op_line_count;
1050: linenr_t yankendlnum = curbuf->b_op_end.lnum;
1051:
1052: char_u *pnew;
1053: struct block_def bd;
1054:
1055: /* check for read-only buffer */
1056: if (yankbuffer != 0 && !is_yank_buffer(yankbuffer, TRUE))
1057: {
1058: beep_flush();
1059: return FAIL;
1060: }
1061: if (!deleting) /* do_delete() already set y_current */
1062: get_yank_buffer(TRUE);
1063:
1064: curr = y_current;
1065: /* append to existing contents */
1066: if (yankappend && y_current->y_array != NULL)
1067: y_current = &newbuf;
1068: else
1069: free_yank_all(); /* free previously yanked lines */
1070:
1071: /*
1072: * If the cursor was in column 1 before and after the movement, and the
1073: * operator is not inclusive, the yank is always linewise.
1074: */
1075: if (op_motion_type == MCHAR && curbuf->b_op_start.col == 0 &&
1076: !op_inclusive && curbuf->b_op_end.col == 0 && yanklines > 1)
1077: {
1078: yanktype = MLINE;
1079: --yankendlnum;
1080: --yanklines;
1081: }
1082:
1083: y_current->y_size = yanklines;
1084: y_current->y_type = yanktype; /* set the yank buffer type */
1085: y_current->y_array = (char_u **)lalloc((long_u)(sizeof(char_u *) *
1086: yanklines), TRUE);
1087:
1088: if (y_current->y_array == NULL)
1089: {
1090: y_current = curr;
1091: return FAIL;
1092: }
1093:
1094: i = 0;
1095: lnum = curbuf->b_op_start.lnum;
1096:
1097: /*
1098: * Visual block mode
1099: */
1100: if (op_block_mode)
1101: {
1102: y_current->y_type = MBLOCK; /* set the yank buffer type */
1103: for ( ; lnum <= yankendlnum; ++lnum)
1104: {
1105: block_prep(&bd, lnum, FALSE);
1106:
1107: if ((pnew = alloc(bd.startspaces + bd.endspaces +
1108: bd.textlen + 1)) == NULL)
1109: goto fail;
1110: y_current->y_array[i++] = pnew;
1111:
1112: copy_spaces(pnew, (size_t)bd.startspaces);
1113: pnew += bd.startspaces;
1114:
1115: vim_memmove(pnew, bd.textstart, (size_t)bd.textlen);
1116: pnew += bd.textlen;
1117:
1118: copy_spaces(pnew, (size_t)bd.endspaces);
1119: pnew += bd.endspaces;
1120:
1121: *pnew = NUL;
1122: }
1123: }
1124: else
1125: {
1126: /*
1127: * there are three parts for non-block mode:
1128: * 1. if yanktype != MLINE yank last part of the top line
1129: * 2. yank the lines between op_start and op_end, inclusive when
1130: * yanktype == MLINE
1131: * 3. if yanktype != MLINE yank first part of the bot line
1132: */
1133: if (yanktype != MLINE)
1134: {
1135: if (yanklines == 1) /* op_start and op_end on same line */
1136: {
1137: j = curbuf->b_op_end.col - curbuf->b_op_start.col +
1138: 1 - !op_inclusive;
1139: if ((y_current->y_array[0] = strnsave(ml_get(lnum) +
1140: curbuf->b_op_start.col, (int)j)) == NULL)
1141: {
1142: fail:
1143: free_yank(i); /* free the allocated lines */
1144: y_current = curr;
1145: return FAIL;
1146: }
1147: goto success;
1148: }
1149: if ((y_current->y_array[0] = strsave(ml_get(lnum++) +
1150: curbuf->b_op_start.col)) == NULL)
1151: goto fail;
1152: ++i;
1153: }
1154:
1155: while (yanktype == MLINE ? (lnum <= yankendlnum) : (lnum < yankendlnum))
1156: {
1157: if ((y_current->y_array[i] = strsave(ml_get(lnum++))) == NULL)
1158: goto fail;
1159: ++i;
1160: }
1161: if (yanktype != MLINE)
1162: {
1163: if ((y_current->y_array[i] = strnsave(ml_get(yankendlnum),
1164: curbuf->b_op_end.col + 1 - !op_inclusive)) == NULL)
1165: goto fail;
1166: }
1167: }
1168:
1169: success:
1170: if (curr != y_current) /* append the new block to the old block */
1171: {
1172: new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) *
1173: (curr->y_size + y_current->y_size)), TRUE);
1174: if (new_ptr == NULL)
1175: goto fail;
1176: for (j = 0; j < curr->y_size; ++j)
1177: new_ptr[j] = curr->y_array[j];
1178: vim_free(curr->y_array);
1179: curr->y_array = new_ptr;
1180:
1181: if (yanktype == MLINE) /* MLINE overrides MCHAR and MBLOCK */
1182: curr->y_type = MLINE;
1183:
1184: /* concatenate the last line of the old block with the first line of
1185: * the new block */
1186: if (curr->y_type == MCHAR)
1187: {
1188: pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1])
1189: + STRLEN(y_current->y_array[0]) + 1), TRUE);
1190: if (pnew == NULL)
1191: {
1192: i = y_current->y_size - 1;
1193: goto fail;
1194: }
1195: STRCPY(pnew, curr->y_array[--j]);
1196: STRCAT(pnew, y_current->y_array[0]);
1197: vim_free(curr->y_array[j]);
1198: vim_free(y_current->y_array[0]);
1199: curr->y_array[j++] = pnew;
1200: i = 1;
1201: }
1202: else
1203: i = 0;
1204: while (i < y_current->y_size)
1205: curr->y_array[j++] = y_current->y_array[i++];
1206: curr->y_size = j;
1207: vim_free(y_current->y_array);
1208: y_current = curr;
1209: }
1210: if (mess) /* Display message about yank? */
1211: {
1212: if (yanktype == MCHAR && !op_block_mode)
1213: --yanklines;
1214: if (yanklines > p_report)
1215: {
1216: cursupdate(); /* redisplay now, so message is not deleted */
1217: smsg((char_u *)"%ld line%s yanked", yanklines, plural(yanklines));
1218: }
1219: }
1220:
1221: return OK;
1222: }
1223:
1224: /*
1225: * put contents of register into the text
1226: * For ":put" command count == -1.
1227: */
1228: void
1229: do_put(dir, count, fix_indent)
1230: int dir; /* BACKWARD for 'P', FORWARD for 'p' */
1231: long count;
1232: int fix_indent; /* make indent look nice */
1233: {
1234: char_u *ptr;
1235: char_u *newp, *oldp;
1236: int yanklen;
1237: int oldlen;
1238: int totlen = 0; /* init for gcc */
1239: linenr_t lnum;
1240: colnr_t col;
1241: long i; /* index in y_array[] */
1242: int y_type;
1243: long y_size;
1244: char_u **y_array;
1245: long nr_lines = 0;
1246: colnr_t vcol;
1247: int delcount;
1248: int incr = 0;
1249: long j;
1250: FPOS new_cursor;
1251: int indent;
1252: int orig_indent = 0; /* init for gcc */
1253: int indent_diff = 0; /* init for gcc */
1254: int first_indent = TRUE;
1255: FPOS old_pos;
1256: struct block_def bd;
1257: char_u *insert_string = NULL;
1258:
1259: #ifdef USE_GUI
1260: if (yankbuffer == '*')
1261: gui_get_selection();
1262: #endif
1263:
1264: if (fix_indent)
1265: orig_indent = get_indent();
1266:
1267: curbuf->b_op_start = curwin->w_cursor; /* default for "'[" command */
1268: if (dir == FORWARD)
1269: curbuf->b_op_start.col++;
1270: curbuf->b_op_end = curwin->w_cursor; /* default for "']" command */
1271:
1272: /*
1273: * Using inserted text works differently, because the buffer includes
1274: * special characters (newlines, etc.).
1275: */
1276: if (yankbuffer == '.')
1277: {
1278: (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
1279: (count == -1 ? 'O' : 'i')), count, FALSE);
1280: return;
1281: }
1282:
1283: /*
1284: * For '%' (file name) and ':' (last command line) we have to create a
1285: * fake yank buffer.
1286: */
1287: if (yankbuffer == '%') /* use file name */
1288: {
1289: if (check_fname() == FAIL)
1290: return;
1291: insert_string = curbuf->b_xfilename;
1292: }
1293: else if (yankbuffer == ':') /* use last command line */
1294: {
1295: if (last_cmdline == NULL)
1296: {
1297: EMSG(e_nolastcmd);
1298: return;
1299: }
1300: insert_string = last_cmdline;
1301: }
1302:
1303: if (insert_string != NULL)
1304: {
1305: y_type = MCHAR; /* use fake one-line yank buffer */
1306: y_size = 1;
1307: y_array = &insert_string;
1308: }
1309: else
1310: {
1311: get_yank_buffer(FALSE);
1312:
1313: y_type = y_current->y_type;
1314: y_size = y_current->y_size;
1315: y_array = y_current->y_array;
1316: }
1317:
1318: if (count == -1) /* :put command */
1319: {
1320: y_type = MLINE;
1321: count = 1;
1322: }
1323:
1324: if (y_size == 0 || y_array == NULL)
1325: {
1326: EMSG2("Nothing in register %s", transchar(yankbuffer));
1327: return;
1328: }
1329:
1330: if (y_type == MBLOCK)
1331: {
1332: lnum = curwin->w_cursor.lnum + y_size + 1;
1333: if (lnum > curbuf->b_ml.ml_line_count)
1334: lnum = curbuf->b_ml.ml_line_count + 1;
1335: if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
1336: return;
1337: }
1338: else if (u_save_cursor() == FAIL)
1339: return;
1340:
1341: yanklen = STRLEN(y_array[0]);
1342: CHANGED;
1343:
1344: lnum = curwin->w_cursor.lnum;
1345: col = curwin->w_cursor.col;
1346:
1347: /*
1348: * block mode
1349: */
1350: if (y_type == MBLOCK)
1351: {
1352: if (dir == FORWARD && gchar_cursor() != NUL)
1353: {
1354: getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
1355: ++col;
1356: ++curwin->w_cursor.col;
1357: }
1358: else
1359: getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
1360: for (i = 0; i < y_size; ++i)
1361: {
1362: bd.startspaces = 0;
1363: bd.endspaces = 0;
1364: bd.textcol = 0;
1365: vcol = 0;
1366: delcount = 0;
1367:
1368: /* add a new line */
1369: if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
1370: {
1371: ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
1372: (colnr_t)1, FALSE);
1373: ++nr_lines;
1374: }
1375: oldp = ml_get_curline();
1376: oldlen = STRLEN(oldp);
1377: for (ptr = oldp; vcol < col && *ptr; ++ptr)
1378: {
1379: /* Count a tab for what it's worth (if list mode not on) */
1380: incr = lbr_chartabsize(ptr, (colnr_t)vcol);
1381: vcol += incr;
1382: ++bd.textcol;
1383: }
1384: if (vcol < col) /* line too short, padd with spaces */
1385: {
1386: bd.startspaces = col - vcol;
1387: }
1388: else if (vcol > col)
1389: {
1390: bd.endspaces = vcol - col;
1391: bd.startspaces = incr - bd.endspaces;
1392: --bd.textcol;
1393: delcount = 1;
1394: }
1395: yanklen = STRLEN(y_array[i]);
1396: totlen = count * yanklen + bd.startspaces + bd.endspaces;
1397: newp = alloc_check((unsigned)totlen + oldlen + 1);
1398: if (newp == NULL)
1399: break;
1400: /* copy part up to cursor to new line */
1401: ptr = newp;
1402: vim_memmove(ptr, oldp, (size_t)bd.textcol);
1403: ptr += bd.textcol;
1404: /* may insert some spaces before the new text */
1405: copy_spaces(ptr, (size_t)bd.startspaces);
1406: ptr += bd.startspaces;
1407: /* insert the new text */
1408: for (j = 0; j < count; ++j)
1409: {
1410: vim_memmove(ptr, y_array[i], (size_t)yanklen);
1411: ptr += yanklen;
1412: }
1413: /* may insert some spaces after the new text */
1414: copy_spaces(ptr, (size_t)bd.endspaces);
1415: ptr += bd.endspaces;
1416: /* move the text after the cursor to the end of the line. */
1417: vim_memmove(ptr, oldp + bd.textcol + delcount,
1418: (size_t)(oldlen - bd.textcol - delcount + 1));
1419: ml_replace(curwin->w_cursor.lnum, newp, FALSE);
1420:
1421: ++curwin->w_cursor.lnum;
1422: if (i == 0)
1423: curwin->w_cursor.col += bd.startspaces;
1424: }
1425: /* for "']" command */
1426: curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
1427: curbuf->b_op_end.col = bd.textcol + totlen - 1;
1428: curwin->w_cursor.lnum = lnum;
1429: cursupdate();
1430: updateScreen(VALID_TO_CURSCHAR);
1431: }
1432: else /* not block mode */
1433: {
1434: if (y_type == MCHAR)
1435: {
1436: /* if type is MCHAR, FORWARD is the same as BACKWARD on the next char */
1437: if (dir == FORWARD && gchar_cursor() != NUL)
1438: {
1439: ++col;
1440: if (yanklen)
1441: {
1442: ++curwin->w_cursor.col;
1443: ++curbuf->b_op_end.col;
1444: }
1445: }
1446: new_cursor = curwin->w_cursor;
1447: }
1448: else if (dir == BACKWARD)
1449: /* if type is MLINE, BACKWARD is the same as FORWARD on the previous line */
1450: --lnum;
1451:
1452: /*
1453: * simple case: insert into current line
1454: */
1455: if (y_type == MCHAR && y_size == 1)
1456: {
1457: totlen = count * yanklen;
1458: if (totlen)
1459: {
1460: oldp = ml_get(lnum);
1461: newp = alloc_check((unsigned)(STRLEN(oldp) + totlen + 1));
1462: if (newp == NULL)
1463: return; /* alloc() will give error message */
1464: vim_memmove(newp, oldp, (size_t)col);
1465: ptr = newp + col;
1466: for (i = 0; i < count; ++i)
1467: {
1468: vim_memmove(ptr, y_array[0], (size_t)yanklen);
1469: ptr += yanklen;
1470: }
1471: vim_memmove(ptr, oldp + col, STRLEN(oldp + col) + 1);
1472: ml_replace(lnum, newp, FALSE);
1473: /* put cursor on last putted char */
1474: curwin->w_cursor.col += (colnr_t)(totlen - 1);
1475: }
1476: curbuf->b_op_end = curwin->w_cursor;
1477: updateline();
1478: }
1479: else
1480: {
1481: while (--count >= 0)
1482: {
1483: i = 0;
1484: if (y_type == MCHAR)
1485: {
1486: /*
1487: * Split the current line in two at the insert position.
1488: * First insert y_array[size - 1] in front of second line.
1489: * Then append y_array[0] to first line.
1490: */
1491: ptr = ml_get(lnum) + col;
1492: totlen = STRLEN(y_array[y_size - 1]);
1493: newp = alloc_check((unsigned)(STRLEN(ptr) + totlen + 1));
1494: if (newp == NULL)
1495: goto error;
1496: STRCPY(newp, y_array[y_size - 1]);
1497: STRCAT(newp, ptr);
1498: /* insert second line */
1499: ml_append(lnum, newp, (colnr_t)0, FALSE);
1500: vim_free(newp);
1501:
1502: oldp = ml_get(lnum);
1503: newp = alloc_check((unsigned)(col + yanklen + 1));
1504: if (newp == NULL)
1505: goto error;
1506: /* copy first part of line */
1507: vim_memmove(newp, oldp, (size_t)col);
1508: /* append to first line */
1509: vim_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
1510: ml_replace(lnum, newp, FALSE);
1511:
1512: curwin->w_cursor.lnum = lnum;
1513: i = 1;
1514: }
1515:
1516: while (i < y_size)
1517: {
1518: if ((y_type != MCHAR || i < y_size - 1) &&
1519: ml_append(lnum, y_array[i], (colnr_t)0, FALSE) == FAIL)
1520: goto error;
1521: lnum++;
1522: i++;
1523: if (fix_indent)
1524: {
1525: old_pos = curwin->w_cursor;
1526: curwin->w_cursor.lnum = lnum;
1527: ptr = ml_get(lnum);
1528: #if defined(SMARTINDENT) || defined(CINDENT)
1529: if (*ptr == '#'
1530: # ifdef SMARTINDENT
1531: && curbuf->b_p_si
1532: # endif
1533: # ifdef CINDENT
1534: && curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE)
1535: # endif
1536: )
1537:
1538: indent = 0; /* Leave # lines at start */
1539: else
1540: #endif
1541: if (*ptr == NUL)
1542: indent = 0; /* Ignore empty lines */
1543: else if (first_indent)
1544: {
1545: indent_diff = orig_indent - get_indent();
1546: indent = orig_indent;
1547: first_indent = FALSE;
1548: }
1549: else if ((indent = get_indent() + indent_diff) < 0)
1550: indent = 0;
1551: set_indent(indent, TRUE);
1552: curwin->w_cursor = old_pos;
1553: }
1554: ++nr_lines;
1555: }
1556: }
1557:
1558: /* put '] at last inserted character */
1559: curbuf->b_op_end.lnum = lnum;
1560: col = STRLEN(y_array[y_size - 1]);
1561: if (col > 1)
1562: curbuf->b_op_end.col = col - 1;
1563: else
1564: curbuf->b_op_end.col = 0;
1565:
1566: if (y_type == MLINE)
1567: {
1568: curwin->w_cursor.col = 0;
1569: if (dir == FORWARD)
1570: {
1571: updateScreen(NOT_VALID); /* recomp. curwin->w_botline */
1572: ++curwin->w_cursor.lnum;
1573: }
1574: /* put cursor on first non-blank in last inserted line */
1575: beginline(TRUE);
1576: }
1577: else /* put cursor on first inserted character */
1578: {
1579: curwin->w_cursor = new_cursor;
1580: }
1581:
1582: error:
1583: if (y_type == MLINE) /* for '[ */
1584: {
1585: curbuf->b_op_start.col = 0;
1586: if (dir == FORWARD)
1587: curbuf->b_op_start.lnum++;
1588: }
1589: mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
1590: MAXLNUM, nr_lines, 0L);
1591: updateScreen(CURSUPD);
1592: }
1593: }
1594:
1595: msgmore(nr_lines);
1596: curwin->w_set_curswant = TRUE;
1597: }
1598:
1599: /* Return the character name of the register with the given number */
1600: int
1601: get_register_name(num)
1602: int num;
1603: {
1604: if (num == -1)
1605: return '"';
1606: else if (num < 10)
1607: return num + '0';
1608: else if (num == DELETION_REGISTER)
1609: return '-';
1610: #ifdef USE_GUI
1611: else if (num == GUI_SELECTION_REGISTER)
1612: return '*';
1613: #endif
1614: else
1615: return num + 'a' - 10;
1616: }
1617:
1618: /*
1619: * display the contents of the yank buffers
1620: */
1621: void
1622: do_dis(arg)
1623: char_u *arg;
1624: {
1625: register int i, n;
1626: register long j;
1627: register char_u *p;
1628: register struct yankbuf *yb;
1629: char_u name;
1630:
1631: if (arg != NULL && *arg == NUL)
1632: arg = NULL;
1633:
1634: set_highlight('t'); /* Highlight title */
1635: start_highlight();
1636: MSG_OUTSTR("\n--- Registers ---");
1637: stop_highlight();
1638: for (i = -1; i < NUM_REGISTERS; ++i)
1639: {
1640: if (i == -1)
1641: {
1642: if (y_previous != NULL)
1643: yb = y_previous;
1644: else
1645: yb = &(y_buf[0]);
1646: }
1647: else
1648: yb = &(y_buf[i]);
1649: name = get_register_name(i);
1650: if (yb->y_array != NULL && (arg == NULL ||
1651: vim_strchr(arg, name) != NULL))
1652: {
1653: msg_outchar('\n');
1654: msg_outchar('"');
1655: msg_outchar(name);
1656: MSG_OUTSTR(" ");
1657:
1658: n = (int)Columns - 6;
1659: for (j = 0; j < yb->y_size && n > 1; ++j)
1660: {
1661: if (j)
1662: {
1663: MSG_OUTSTR("^J");
1664: n -= 2;
1665: }
1666: for (p = yb->y_array[j]; *p && (n -= charsize(*p)) >= 0; ++p)
1667: msg_outtrans_len(p, 1);
1668: }
1669: flushbuf(); /* show one line at a time */
1670: }
1671: }
1672:
1673: /*
1674: * display last inserted text
1675: */
1676: if ((p = get_last_insert()) != NULL &&
1677: (arg == NULL || vim_strchr(arg, '.') != NULL))
1678: {
1679: MSG_OUTSTR("\n\". ");
1680: dis_msg(p, TRUE);
1681: }
1682:
1683: /*
1684: * display last command line
1685: */
1686: if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL))
1687: {
1688: MSG_OUTSTR("\n\": ");
1689: dis_msg(last_cmdline, FALSE);
1690: }
1691:
1692: /*
1693: * display current file name
1694: */
1695: if (curbuf->b_xfilename != NULL &&
1696: (arg == NULL || vim_strchr(arg, '%') != NULL))
1697: {
1698: MSG_OUTSTR("\n\"% ");
1699: dis_msg(curbuf->b_xfilename, FALSE);
1700: }
1701: }
1702:
1703: /*
1704: * display a string for do_dis()
1705: * truncate at end of screen line
1706: */
1707: void
1708: dis_msg(p, skip_esc)
1709: char_u *p;
1710: int skip_esc; /* if TRUE, ignore trailing ESC */
1711: {
1712: int n;
1713:
1714: n = (int)Columns - 6;
1715: while (*p && !(*p == ESC && skip_esc && *(p + 1) == NUL) &&
1716: (n -= charsize(*p)) >= 0)
1717: msg_outtrans_len(p++, 1);
1718: }
1719:
1720: /*
1721: * join 'count' lines (minimal 2), including u_save()
1722: */
1723: void
1724: do_do_join(count, insert_space, redraw)
1725: long count;
1726: int insert_space;
1727: int redraw; /* can redraw, curwin->w_col valid */
1728: {
1729: if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
1730: (linenr_t)(curwin->w_cursor.lnum + count)) == FAIL)
1731: return;
1732:
1733: if (count > 10)
1734: redraw = FALSE; /* don't redraw each small change */
1735: while (--count > 0)
1736: {
1737: line_breakcheck();
1738: if (got_int || do_join(insert_space, redraw) == FAIL)
1739: {
1740: beep_flush();
1741: break;
1742: }
1743: }
1744: if (redraw)
1745: redraw_later(VALID_TO_CURSCHAR);
1746: else
1747: redraw_later(NOT_VALID);
1748:
1749: /*
1750: * Need to update the screen if the line where the cursor is became too
1751: * long to fit on the screen.
1752: */
1753: cursupdate();
1754: }
1755:
1756: /*
1757: * Join two lines at the cursor position.
1758: *
1759: * return FAIL for failure, OK ohterwise
1760: */
1761: int
1762: do_join(insert_space, redraw)
1763: int insert_space;
1764: int redraw; /* should only be TRUE when curwin->w_row valid */
1765: {
1766: char_u *curr;
1767: char_u *next;
1768: char_u *newp;
1769: int endcurr1, endcurr2;
1770: int currsize; /* size of the current line */
1771: int nextsize; /* size of the next line */
1772: int spaces; /* number of spaces to insert */
1773: int rows_to_del = 0;/* number of rows on screen to delete */
1774: linenr_t t;
1775:
1776: if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
1777: return FAIL; /* can't join on last line */
1778:
1779: if (redraw)
1780: rows_to_del = plines_m(curwin->w_cursor.lnum,
1781: curwin->w_cursor.lnum + 1);
1782:
1783: curr = ml_get_curline();
1784: currsize = STRLEN(curr);
1785: endcurr1 = endcurr2 = NUL;
1786: if (currsize > 0)
1787: {
1788: endcurr1 = *(curr + currsize - 1);
1789: if (currsize > 1)
1790: endcurr2 = *(curr + currsize - 2);
1791: }
1792:
1793: next = ml_get((linenr_t)(curwin->w_cursor.lnum + 1));
1794: spaces = 0;
1795: if (insert_space)
1796: {
1797: next = skipwhite(next);
1798: spaces = 1;
1799: if (*next == ')' || currsize == 0)
1800: spaces = 0;
1801: else
1802: {
1803: if (endcurr1 == ' ' || endcurr1 == TAB)
1804: {
1805: spaces = 0;
1806: if (currsize > 1)
1807: endcurr1 = endcurr2;
1808: }
1809: if (p_js && vim_strchr((char_u *)".!?", endcurr1) != NULL)
1810: spaces = 2;
1811: }
1812: }
1813: nextsize = STRLEN(next);
1814:
1815: newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1));
1816: if (newp == NULL)
1817: return FAIL;
1818:
1819: /*
1820: * Insert the next line first, because we already have that pointer.
1821: * Curr has to be obtained again, because getting next will have
1822: * invalidated it.
1823: */
1824: vim_memmove(newp + currsize + spaces, next, (size_t)(nextsize + 1));
1825:
1826: curr = ml_get_curline();
1827: vim_memmove(newp, curr, (size_t)currsize);
1828:
1829: copy_spaces(newp + currsize, (size_t)spaces);
1830:
1831: ml_replace(curwin->w_cursor.lnum, newp, FALSE);
1832:
1833: /*
1834: * Delete the following line. To do this we move the cursor there
1835: * briefly, and then move it back. After dellines() the cursor may
1836: * have moved up (last line deleted), so the current lnum is kept in t.
1837: */
1838: t = curwin->w_cursor.lnum;
1839: ++curwin->w_cursor.lnum;
1840: dellines(1L, FALSE, FALSE);
1841: curwin->w_cursor.lnum = t;
1842:
1843: /*
1844: * the number of rows on the screen is reduced by the difference
1845: * in number of rows of the two old lines and the one new line
1846: */
1847: if (redraw)
1848: {
1849: rows_to_del -= plines(curwin->w_cursor.lnum);
1850: if (rows_to_del > 0)
1851: win_del_lines(curwin, curwin->w_cline_row + curwin->w_cline_height,
1852: rows_to_del, TRUE, TRUE);
1853: }
1854:
1855: /*
1856: * go to first character of the joined line
1857: */
1858: if (currsize == 0)
1859: curwin->w_cursor.col = 0;
1860: else
1861: {
1862: curwin->w_cursor.col = currsize - 1;
1863: (void)oneright();
1864: }
1865: CHANGED;
1866:
1867: return OK;
1868: }
1869:
1870: /*
1871: * Return TRUE if the two comment leaders given are the same. The cursor is
1872: * in the first line. White-space is ignored. Note that the whole of
1873: * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
1874: */
1875: static int
1876: same_leader(leader1_len, leader1_flags, leader2_len, leader2_flags)
1877: int leader1_len;
1878: char_u *leader1_flags;
1879: int leader2_len;
1880: char_u *leader2_flags;
1881: {
1882: int idx1 = 0, idx2 = 0;
1883: char_u *p;
1884: char_u *line1;
1885: char_u *line2;
1886:
1887: if (leader1_len == 0)
1888: return (leader2_len == 0);
1889:
1890: /*
1891: * If first leader has 'f' flag, the lines can be joined only if the
1892: * second line does not have a leader.
1893: * If first leader has 'e' flag, the lines can never be joined.
1894: * If fist leader has 's' flag, the lines can only be joined if there is
1895: * some text after it and the second line has the 'm' flag.
1896: */
1897: if (leader1_flags != NULL)
1898: {
1899: for (p = leader1_flags; *p && *p != ':'; ++p)
1900: {
1901: if (*p == COM_FIRST)
1902: return (leader2_len == 0);
1903: if (*p == COM_END)
1904: return FALSE;
1905: if (*p == COM_START)
1906: {
1907: if (*(ml_get_curline() + leader1_len) == NUL)
1908: return FALSE;
1909: if (leader2_flags == NULL || leader2_len == 0)
1910: return FALSE;
1911: for (p = leader2_flags; *p && *p != ':'; ++p)
1912: if (*p == COM_MIDDLE)
1913: return TRUE;
1914: return FALSE;
1915: }
1916: }
1917: }
1918:
1919: /*
1920: * Get current line and next line, compare the leaders.
1921: * The first line has to be saved, only one line can be locked at a time.
1922: */
1923: line1 = strsave(ml_get_curline());
1924: if (line1 != NULL)
1925: {
1926: for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1)
1927: ;
1928: line2 = ml_get(curwin->w_cursor.lnum + 1);
1929: for (idx2 = 0; idx2 < leader2_len; ++idx2)
1930: {
1931: if (!vim_iswhite(line2[idx2]))
1932: {
1933: if (line1[idx1++] != line2[idx2])
1934: break;
1935: }
1936: else
1937: while (vim_iswhite(line1[idx1]))
1938: ++idx1;
1939: }
1940: vim_free(line1);
1941: }
1942: return (idx2 == leader2_len && idx1 == leader1_len);
1943: }
1944:
1945: /*
1946: * implementation of the format operator 'Q'
1947: */
1948: void
1949: do_format()
1950: {
1951: long old_line_count = curbuf->b_ml.ml_line_count;
1952: int prev_is_blank = FALSE;
1953: int is_end_block = TRUE;
1954: int next_is_end_block;
1955: int leader_len = 0; /* init for gcc */
1956: int next_leader_len;
1957: char_u *leader_flags = NULL;
1958: char_u *next_leader_flags;
1959: int advance = TRUE;
1960: int second_indent = -1;
1961: int do_second_indent;
1962: int first_par_line = TRUE;
1963:
1964: if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
1965: (linenr_t)(curwin->w_cursor.lnum + op_line_count)) == FAIL)
1966: return;
1967:
1968: /* check for 'q' and '2' in 'formatoptions' */
1969: fo_do_comments = has_format_option(FO_Q_COMS);
1970: do_second_indent = has_format_option(FO_Q_SECOND);
1971:
1972: /*
1973: * get info about the previous and current line.
1974: */
1975: if (curwin->w_cursor.lnum > 1)
1976: is_end_block = fmt_end_block(curwin->w_cursor.lnum - 1,
1977: &next_leader_len, &next_leader_flags);
1978: next_is_end_block = fmt_end_block(curwin->w_cursor.lnum,
1979: &next_leader_len, &next_leader_flags);
1980:
1981: curwin->w_cursor.lnum--;
1982: while (--op_line_count >= 0)
1983: {
1984: /*
1985: * Advance to next block.
1986: */
1987: if (advance)
1988: {
1989: curwin->w_cursor.lnum++;
1990: prev_is_blank = is_end_block;
1991: is_end_block = next_is_end_block;
1992: leader_len = next_leader_len;
1993: leader_flags = next_leader_flags;
1994: }
1995:
1996: /*
1997: * The last line to be formatted.
1998: */
1999: if (op_line_count == 0)
2000: {
2001: next_is_end_block = TRUE;
2002: next_leader_len = 0;
2003: next_leader_flags = NULL;
2004: }
2005: else
2006: next_is_end_block = fmt_end_block(curwin->w_cursor.lnum + 1,
2007: &next_leader_len, &next_leader_flags);
2008: advance = TRUE;
2009:
2010: /*
2011: * For the first line of a paragraph, check indent of second line.
2012: * Don't do this for comments and empty lines.
2013: */
2014: if (first_par_line && do_second_indent &&
2015: prev_is_blank && !is_end_block &&
2016: curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count &&
2017: leader_len == 0 && next_leader_len == 0 &&
2018: !lineempty(curwin->w_cursor.lnum + 1))
2019: second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);
2020:
2021: /*
2022: * Skip end-of-block (blank) lines
2023: */
2024: if (is_end_block)
2025: {
2026: }
2027: /*
2028: * If we have got to the end of a paragraph, format it.
2029: */
2030: else if (next_is_end_block || !same_leader(leader_len, leader_flags,
2031: next_leader_len, next_leader_flags))
2032: {
2033: /* replace indent in first line with minimal number of tabs and
2034: * spaces, according to current options */
2035: set_indent(get_indent(), TRUE);
2036:
2037: /* put cursor on last non-space */
2038: coladvance(MAXCOL);
2039: while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
2040: dec_cursor();
2041: curs_columns(FALSE); /* update curwin->w_virtcol */
2042:
2043: /* do the formatting */
2044: State = INSERT; /* for Opencmd() */
2045: insertchar(NUL, TRUE, second_indent);
2046: State = NORMAL;
2047: first_par_line = TRUE;
2048: second_indent = -1;
2049: }
2050: else
2051: {
2052: /*
2053: * Still in same paragraph, so join the lines together.
2054: * But first delete the comment leader from the second line.
2055: */
2056: advance = FALSE;
2057: curwin->w_cursor.lnum++;
2058: curwin->w_cursor.col = 0;
2059: while (next_leader_len--)
2060: delchar(FALSE);
2061: curwin->w_cursor.lnum--;
2062: if (do_join(TRUE, FALSE) == FAIL)
2063: {
2064: beep_flush();
2065: break;
2066: }
2067: first_par_line = FALSE;
2068: }
2069: }
2070: fo_do_comments = FALSE;
2071: /*
2072: * Leave the cursor at the first non-blank of the last formatted line.
2073: * If the cursor was move one line back (e.g. with "Q}") go to the next
2074: * line, so "." will do the next lines.
2075: */
2076: if (op_end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
2077: ++curwin->w_cursor.lnum;
2078: beginline(TRUE);
2079: updateScreen(NOT_VALID);
2080: msgmore(curbuf->b_ml.ml_line_count - old_line_count);
2081: }
2082:
2083: /*
2084: * Blank lines, and lines containing only the comment leader, are left
2085: * untouched by the formatting. The function returns TRUE in this
2086: * case. It also returns TRUE when a line starts with the end of a comment
2087: * ('e' in comment flags), so that this line is skipped, and not joined to the
2088: * previous line. A new paragraph starts after a blank line, or when the
2089: * comment leader changes -- webb.
2090: */
2091: static int
2092: fmt_end_block(lnum, leader_len, leader_flags)
2093: linenr_t lnum;
2094: int *leader_len;
2095: char_u **leader_flags;
2096: {
2097: char_u *flags = NULL; /* init for GCC */
2098: char_u *ptr;
2099:
2100: ptr = ml_get(lnum);
2101: *leader_len = get_leader_len(ptr, leader_flags);
2102:
2103: if (*leader_len > 0)
2104: {
2105: /*
2106: * Search for 'e' flag in comment leader flags.
2107: */
2108: flags = *leader_flags;
2109: while (*flags && *flags != ':' && *flags != COM_END)
2110: ++flags;
2111: }
2112:
2113: return (ptr[*leader_len] == NUL ||
2114: (*leader_len > 0 && *flags == COM_END) ||
2115: startPS(lnum, NUL, FALSE));
2116: }
2117:
2118: /*
2119: * prepare a few things for block mode yank/delete/tilde
2120: *
2121: * for delete:
2122: * - textlen includes the first/last char to be (partly) deleted
2123: * - start/endspaces is the number of columns that are taken by the
2124: * first/last deleted char minus the number of columns that have to be deleted.
2125: * for yank and tilde:
2126: * - textlen includes the first/last char to be wholly yanked
2127: * - start/endspaces is the number of columns of the first/last yanked char
2128: * that are to be yanked.
2129: */
2130: static void
2131: block_prep(bd, lnum, is_del)
2132: struct block_def *bd;
2133: linenr_t lnum;
2134: int is_del;
2135: {
2136: colnr_t vcol;
2137: int incr = 0;
2138: char_u *pend;
2139: char_u *pstart;
2140:
2141: bd->startspaces = 0;
2142: bd->endspaces = 0;
2143: bd->textlen = 0;
2144: bd->textcol = 0;
2145: vcol = 0;
2146: pstart = ml_get(lnum);
2147: while (vcol < op_start_vcol && *pstart)
2148: {
2149: /* Count a tab for what it's worth (if list mode not on) */
2150: incr = lbr_chartabsize(pstart, (colnr_t)vcol);
2151: vcol += incr;
2152: ++pstart;
2153: ++bd->textcol;
2154: }
2155: if (vcol < op_start_vcol) /* line too short */
2156: {
2157: if (!is_del)
2158: bd->endspaces = op_end_vcol - op_start_vcol + 1;
2159: }
2160: else /* vcol >= op_start_vcol */
2161: {
2162: bd->startspaces = vcol - op_start_vcol;
2163: if (is_del && vcol > op_start_vcol)
2164: bd->startspaces = incr - bd->startspaces;
2165: pend = pstart;
2166: if (vcol > op_end_vcol) /* it's all in one character */
2167: {
2168: bd->startspaces = op_end_vcol - op_start_vcol + 1;
2169: if (is_del)
2170: bd->startspaces = incr - bd->startspaces;
2171: }
2172: else
2173: {
2174: while (vcol <= op_end_vcol && *pend)
2175: {
2176: /* Count a tab for what it's worth (if list mode not on) */
2177: incr = lbr_chartabsize(pend, (colnr_t)vcol);
2178: vcol += incr;
2179: ++pend;
2180: }
2181: if (vcol < op_end_vcol && !is_del) /* line too short */
2182: {
2183: bd->endspaces = op_end_vcol - vcol;
2184: }
2185: else if (vcol > op_end_vcol)
2186: {
2187: bd->endspaces = vcol - op_end_vcol - 1;
2188: if (!is_del && pend != pstart && bd->endspaces)
2189: --pend;
2190: }
2191: }
2192: if (is_del && bd->startspaces)
2193: {
2194: --pstart;
2195: --bd->textcol;
2196: }
2197: bd->textlen = (int)(pend - pstart);
2198: }
2199: bd->textstart = pstart;
2200: }
2201:
2202: #define NUMBUFLEN 30
2203:
2204: /*
2205: * add or subtract 'Prenum1' from a number in a line
2206: * 'command' is CTRL-A for add, CTRL-X for subtract
2207: *
2208: * return FAIL for failure, OK otherwise
2209: */
2210: int
2211: do_addsub(command, Prenum1)
2212: int command;
2213: linenr_t Prenum1;
2214: {
2215: register int col;
2216: char_u buf[NUMBUFLEN];
2217: int hex; /* 'X': hexadecimal; '0': octal */
2218: static int hexupper = FALSE; /* 0xABC */
2219: long n;
2220: char_u *ptr;
2221: int i;
2222: int c;
2223: int zeros = 0; /* number of leading zeros */
2224: int digits = 0; /* number of digits in the number */
2225:
2226: ptr = ml_get_curline();
2227: col = curwin->w_cursor.col;
2228:
2229: /* first check if we are on a hexadecimal number */
2230: while (col > 0 && isxdigit(ptr[col]))
2231: --col;
2232: if (col > 0 && (ptr[col] == 'X' || ptr[col] == 'x') &&
2233: ptr[col - 1] == '0' && isxdigit(ptr[col + 1]))
2234: --col; /* found hexadecimal number */
2235: else
2236: {
2237: /* first search forward and then backward for start of number */
2238: col = curwin->w_cursor.col;
2239:
2240: while (ptr[col] != NUL && !isdigit(ptr[col]))
2241: ++col;
2242:
2243: while (col > 0 && isdigit(ptr[col - 1]))
2244: --col;
2245: }
2246:
2247: if (isdigit(ptr[col]) && u_save_cursor() == OK)
2248: {
2249: ptr = ml_get_curline(); /* get it again, because
2250: u_save may have changed it */
2251: curwin->w_set_curswant = TRUE;
2252:
2253: hex = 0; /* default is decimal */
2254: if (ptr[col] == '0') /* could be hex or octal */
2255: {
2256: hex = TO_UPPER(ptr[col + 1]); /* assume hexadecimal */
2257: if (hex != 'X' || !isxdigit(ptr[col + 2]))
2258: {
2259: if (isdigit(hex))
2260: hex = '0'; /* octal */
2261: else
2262: hex = 0; /* 0 by itself is decimal */
2263: }
2264: }
2265:
2266: if (!hex && col > 0 && ptr[col - 1] == '-')
2267: --col;
2268:
2269: ptr += col;
2270: /*
2271: * we copy the number into a buffer because some versions of sscanf
2272: * cannot handle characters with the upper bit set, making some special
2273: * characters handled like digits.
2274: */
2275: for (i = 0; *ptr && !(*ptr & 0x80) && i < NUMBUFLEN - 1; ++i)
2276: buf[i] = *ptr++;
2277: buf[i] = NUL;
2278:
2279: if (hex == '0')
2280: sscanf((char *)buf, "%lo", &n);
2281: else if (hex)
2282: sscanf((char *)buf + 2, "%lx", &n); /* "%X" doesn't work! */
2283: else
2284: n = atol((char *)buf);
2285:
2286: if (command == Ctrl('A'))
2287: n += Prenum1;
2288: else
2289: n -= Prenum1;
2290:
2291: if (hex == 'X') /* skip the '0x' */
2292: col += 2;
2293: else if (hex == '0')
2294: col++; /* skip the '0' */
2295: curwin->w_cursor.col = col;
2296:
2297: c = gchar_cursor();
2298: do /* delete the old number */
2299: {
2300: if (digits == 0 && c == '0')
2301: ++zeros; /* count the number of leading zeros */
2302: else
2303: ++digits; /* count the number of digits */
2304: if (isalpha(c))
2305: {
2306: if (isupper(c))
2307: hexupper = TRUE;
2308: else
2309: hexupper = FALSE;
2310: }
2311: (void)delchar(FALSE);
2312: c = gchar_cursor();
2313: }
2314: while (hex ? (hex == '0' ? c >= '0' && c <= '7' :
2315: isxdigit(c)) : isdigit(c));
2316:
2317: if (hex == 0)
2318: sprintf((char *)buf, "%ld", n);
2319: else
2320: {
2321: if (hex == '0')
2322: sprintf((char *)buf, "%lo", n);
2323: else if (hex && hexupper)
2324: sprintf((char *)buf, "%lX", n);
2325: else if (hex)
2326: sprintf((char *)buf, "%lx", n);
2327: /* adjust number of zeros to the new number of digits, so the
2328: * total length of the number remains the same */
2329: if (zeros)
2330: {
2331: zeros += digits - STRLEN(buf);
2332: if (zeros > 0)
2333: {
2334: vim_memmove(buf + zeros, buf, STRLEN(buf) + 1);
2335: for (col = 0; zeros > 0; --zeros)
2336: buf[col++] = '0';
2337: }
2338: }
2339: }
2340: ins_str(buf); /* insert the new number */
2341: --curwin->w_cursor.col;
2342: updateline();
2343: return OK;
2344: }
2345: else
2346: {
2347: beep_flush();
2348: return FAIL;
2349: }
2350: }
2351:
2352: #ifdef VIMINFO
2353: int
2354: read_viminfo_register(line, fp, force)
2355: char_u *line;
2356: FILE *fp;
2357: int force;
2358: {
2359: int eof;
2360: int do_it = TRUE;
2361: int size;
2362: int limit;
2363: int i;
2364: int set_prev = FALSE;
2365: char_u *str;
2366: char_u **array = NULL;
2367:
2368: /* We only get here (hopefully) if line[0] == '"' */
2369: str = line + 1;
2370: if (*str == '"')
2371: {
2372: set_prev = TRUE;
2373: str++;
2374: }
2375: if (!isalnum(*str) && *str != '-')
2376: {
2377: EMSG2("viminfo: Illegal register name in line %s", line);
2378: do_it = FALSE;
2379: }
2380: yankbuffer = *str++;
2381: get_yank_buffer(FALSE);
2382: yankbuffer = 0;
2383: if (!force && y_current->y_array != NULL)
2384: do_it = FALSE;
2385: size = 0;
2386: limit = 100; /* Optimized for registers containing <= 100 lines */
2387: if (do_it)
2388: {
2389: if (set_prev)
2390: y_previous = y_current;
2391: vim_free(y_current->y_array);
2392: array = y_current->y_array =
2393: (char_u **)alloc((unsigned)(limit * sizeof(char_u *)));
2394: str = skipwhite(str);
2395: if (STRNCMP(str, "CHAR", 4) == 0)
2396: y_current->y_type = MCHAR;
2397: else if (STRNCMP(str, "BLOCK", 5) == 0)
2398: y_current->y_type = MBLOCK;
2399: else
2400: y_current->y_type = MLINE;
2401: }
2402: while (!(eof = vim_fgets(line, LSIZE, fp)) && line[0] == TAB)
2403: {
2404: if (do_it)
2405: {
2406: if (size >= limit)
2407: {
2408: y_current->y_array = (char_u **)
2409: alloc((unsigned)(limit * 2 * sizeof(char_u *)));
2410: for (i = 0; i < limit; i++)
2411: y_current->y_array[i] = array[i];
2412: vim_free(array);
2413: limit *= 2;
2414: array = y_current->y_array;
2415: }
2416: viminfo_readstring(line);
2417: str = strsave(line + 1);
2418: if (str != NULL)
2419: array[size++] = str;
2420: else
2421: do_it = FALSE;
2422: }
2423: }
2424: if (do_it)
2425: {
2426: if (size == 0)
2427: {
2428: vim_free(array);
2429: y_current->y_array = NULL;
2430: }
2431: else if (size < limit)
2432: {
2433: y_current->y_array =
2434: (char_u **)alloc((unsigned)(size * sizeof(char_u *)));
2435: for (i = 0; i < size; i++)
2436: y_current->y_array[i] = array[i];
2437: vim_free(array);
2438: }
2439: y_current->y_size = size;
2440: }
2441: return eof;
2442: }
2443:
2444: void
2445: write_viminfo_registers(fp)
2446: FILE *fp;
2447: {
2448: int i, j;
2449: char_u *type;
2450: char_u c;
2451: int num_lines;
2452: int max_num_lines;
2453:
2454: fprintf(fp, "\n# Registers:\n");
2455:
2456: max_num_lines = get_viminfo_parameter('"');
2457: if (max_num_lines == 0)
2458: return;
2459: for (i = 0; i < NUM_REGISTERS; i++)
2460: {
2461: if (y_buf[i].y_array == NULL)
2462: continue;
2463: #ifdef USE_GUI
2464: /* Skip '*' register, we don't want it back next time */
2465: if (i == GUI_SELECTION_REGISTER)
2466: continue;
2467: #endif
2468: switch (y_buf[i].y_type)
2469: {
2470: case MLINE:
2471: type = (char_u *)"LINE";
2472: break;
2473: case MCHAR:
2474: type = (char_u *)"CHAR";
2475: break;
2476: case MBLOCK:
2477: type = (char_u *)"BLOCK";
2478: break;
2479: default:
2480: sprintf((char *)IObuff, "Unknown register type %d",
2481: y_buf[i].y_type);
2482: emsg(IObuff);
2483: type = (char_u *)"LINE";
2484: break;
2485: }
2486: if (y_previous == &y_buf[i])
2487: fprintf(fp, "\"");
2488: if (i == DELETION_REGISTER)
2489: c = '-';
2490: else if (i < 10)
2491: c = '0' + i;
2492: else
2493: c = 'a' + i - 10;
2494: fprintf(fp, "\"%c\t%s\n", c, type);
2495: num_lines = y_buf[i].y_size;
2496:
2497: /* If max_num_lines < 0, then we save ALL the lines in the register */
2498: if (max_num_lines > 0 && num_lines > max_num_lines)
2499: num_lines = max_num_lines;
2500: for (j = 0; j < num_lines; j++)
2501: {
2502: putc('\t', fp);
2503: viminfo_writestring(fp, y_buf[i].y_array[j]);
2504: }
2505: }
2506: }
2507: #endif /* VIMINFO */
2508:
2509: #if defined(USE_GUI) || defined(PROTO)
2510: /*
2511: * Text selection stuff that uses the GUI selection register '*'. When using a
2512: * GUI this may be text from another window, otherwise it is the last text we
2513: * had highlighted with VIsual mode. With mouse support, clicking the middle
2514: * button performs the paste, otherwise you will need to do <"*p>.
2515: */
2516:
2517: void
2518: gui_free_selection()
2519: {
2520: struct yankbuf *y_ptr = y_current;
2521:
2522: y_current = &y_buf[GUI_SELECTION_REGISTER]; /* '*' register */
2523: free_yank_all();
2524: y_current->y_size = 0;
2525: y_current = y_ptr;
2526: }
2527:
2528: /*
2529: * Get the selected text and put it in the gui text register '*'.
2530: */
2531: void
2532: gui_get_selection()
2533: {
2534: struct yankbuf *old_y_previous, *old_y_current;
2535: char_u old_yankbuffer;
2536: FPOS old_cursor, old_visual;
2537: int old_op_type;
2538:
2539: if (gui.selection.owned)
2540: {
2541: if (y_buf[GUI_SELECTION_REGISTER].y_array != NULL)
2542: return;
2543:
2544: /* Get the text between gui.selection.start & gui.selection.end */
2545: old_y_previous = y_previous;
2546: old_y_current = y_current;
2547: old_yankbuffer = yankbuffer;
2548: old_cursor = curwin->w_cursor;
2549: old_visual = VIsual;
2550: old_op_type = op_type;
2551: yankbuffer = '*';
2552: op_type = YANK;
2553: do_pending_operator('y', NUL, FALSE, NULL, NULL, 0, TRUE, TRUE);
2554: y_previous = old_y_previous;
2555: y_current = old_y_current;
2556: yankbuffer = old_yankbuffer;
2557: curwin->w_cursor = old_cursor;
2558: VIsual = old_visual;
2559: op_type = old_op_type;
2560: }
2561: else
2562: {
2563: gui_free_selection();
2564:
2565: /* Try to get selected text from another window */
2566: gui_request_selection();
2567: }
2568: }
2569:
2570: /* Convert from the GUI selection string into the '*' register */
2571: void
2572: gui_yank_selection(type, str, len)
2573: int type;
2574: char_u *str;
2575: long_u len;
2576: {
2577: struct yankbuf *y_ptr = &y_buf[GUI_SELECTION_REGISTER]; /* '*' register */
2578: int lnum;
2579: int start;
2580: int i;
2581:
2582: gui_free_selection();
2583:
2584: /* Count the number of lines within the string */
2585: y_ptr->y_size = 1;
2586: for (i = 0; i < len; i++)
2587: if (str[i] == '\n')
2588: y_ptr->y_size++;
2589:
2590: if (type != MCHAR && i > 0 && str[i - 1] == '\n')
2591: y_ptr->y_size--;
2592:
2593: y_ptr->y_array = (char_u **)lalloc(y_ptr->y_size * sizeof(char_u *), TRUE);
2594: if (y_ptr->y_array == NULL)
2595: return;
2596: y_ptr->y_type = type;
2597: lnum = 0;
2598: start = 0;
2599: for (i = 0; i < len; i++)
2600: {
2601: if (str[i] == NUL)
2602: str[i] = '\n';
2603: else if (str[i] == '\n')
2604: {
2605: str[i] = NUL;
2606: if (type == MCHAR || i != len - 1)
2607: {
2608: if ((y_ptr->y_array[lnum] = strsave(str + start)) == NULL)
2609: {
2610: y_ptr->y_size = lnum;
2611: return;
2612: }
2613: lnum++;
2614: start = i + 1;
2615: }
2616: }
2617: }
2618: if ((y_ptr->y_array[lnum] = alloc(i - start + 1)) == NULL)
2619: return;
2620: if (i - start > 0)
2621: STRNCPY(y_ptr->y_array[lnum], str + start, i - start);
2622: y_ptr->y_array[lnum][i - start] = NUL;
2623: y_ptr->y_size = lnum + 1;
2624: }
2625:
2626: /*
2627: * Convert the '*' register into a GUI selection string returned in *str with
2628: * length *len.
2629: */
2630: int
2631: gui_convert_selection(str, len)
2632: char_u **str;
2633: long_u *len;
2634: {
2635: struct yankbuf *y_ptr = &y_buf[GUI_SELECTION_REGISTER]; /* '*' register */
2636: char_u *p;
2637: int lnum;
2638: int i, j;
2639:
2640: *str = NULL;
2641: *len = 0;
2642: if (y_ptr->y_array == NULL)
2643: return -1;
2644:
2645: for (i = 0; i < y_ptr->y_size; i++)
2646: *len += STRLEN(y_ptr->y_array[i]) + 1;
2647:
2648: /*
2649: * Don't want newline character at end of last line if we're in MCHAR mode.
2650: */
2651: if (y_ptr->y_type == MCHAR && *len > 1)
2652: (*len)--;
2653:
2654: p = *str = lalloc(*len, TRUE);
2655: if (p == NULL)
2656: return -1;
2657: lnum = 0;
2658: for (i = 0, j = 0; i < *len; i++, j++)
2659: {
2660: if (y_ptr->y_array[lnum][j] == '\n')
2661: p[i] = NUL;
2662: else if (y_ptr->y_array[lnum][j] == NUL)
2663: {
2664: p[i] = '\n';
2665: lnum++;
2666: j = -1;
2667: }
2668: else
2669: p[i] = y_ptr->y_array[lnum][j];
2670: }
2671: return y_ptr->y_type;
2672: }
2673: #endif /* USE_GUI || PROTO */