Annotation of src/usr.bin/vim/cmdcmds.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: * cmdcmds.c: functions for command line commands
12: */
13:
14: #include "vim.h"
15: #include "globals.h"
16: #include "proto.h"
17: #include "option.h"
18:
19: #ifdef USE_TMPNAM
20: # define mktemp(a) tmpnam(a)
21: #endif
22:
23: extern char *mktemp __ARGS((char *));
24:
25: #ifdef OS2
26: static void check_tmpenv __ARGS((void));
27: #endif
28:
29: #ifdef VIMINFO
30: static char_u *viminfo_filename __ARGS((char_u *));
31: static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info, int want_marks, int force_read));
32: static int read_viminfo_up_to_marks __ARGS((char_u *line, FILE *fp, int force));
33: #endif /* VIMINFO */
34:
35: void
36: do_ascii()
37: {
38: int c;
39: char buf1[20];
40: char buf2[20];
41: char_u buf3[3];
42:
43: c = gchar_cursor();
44: if (c == NL) /* NUL is stored as NL */
45: c = NUL;
46: if (isprintchar(c) && (c < ' ' || c > '~'))
47: {
48: transchar_nonprint(buf3, c);
49: sprintf(buf1, " <%s>", (char *)buf3);
50: }
51: else
52: buf1[0] = NUL;
53: if (c >= 0x80)
54: sprintf(buf2, " <M-%s>", transchar(c & 0x7f));
55: else
56: buf2[0] = NUL;
57: sprintf((char *)IObuff, "<%s>%s%s %d, Hex %02x, Octal %03o",
58: transchar(c), buf1, buf2, c, c, c);
59: msg(IObuff);
60: }
61:
62: /*
63: * align text:
64: * type = -1 left aligned
65: * type = 0 centered
66: * type = 1 right aligned
67: */
68: void
69: do_align(start, end, width, type)
70: linenr_t start;
71: linenr_t end;
72: int width;
73: int type;
74: {
75: FPOS pos;
76: int len;
77: int indent = 0;
78: int new_indent = 0; /* init for GCC */
79: char_u *first;
80: char_u *last;
81: int save;
82:
83: #ifdef RIGHTLEFT
84: if (curwin->w_p_rl)
85: type = -type; /* switch left and right aligning */
86: #endif
87:
88: pos = curwin->w_cursor;
89: if (type == -1) /* left align: width is used for new indent */
90: {
91: if (width >= 0)
92: indent = width;
93: }
94: else
95: {
96: /*
97: * if 'textwidth' set, use it
98: * else if 'wrapmargin' set, use it
99: * if invalid value, use 80
100: */
101: if (width <= 0)
102: width = curbuf->b_p_tw;
103: if (width == 0 && curbuf->b_p_wm > 0)
104: width = Columns - curbuf->b_p_wm;
105: if (width <= 0)
106: width = 80;
107: }
108:
109: if (u_save((linenr_t)(start - 1), (linenr_t)(end + 1)) == FAIL)
110: return;
111: for (curwin->w_cursor.lnum = start;
112: curwin->w_cursor.lnum <= end; ++curwin->w_cursor.lnum)
113: {
114: /* find the first non-blank character */
115: first = skipwhite(ml_get_curline());
116: /* find the character after the last non-blank character */
117: for (last = first + STRLEN(first);
118: last > first && vim_iswhite(last[-1]); --last)
119: ;
120: save = *last;
121: *last = NUL;
122: len = linetabsize(first); /* get line length */
123: *last = save;
124: if (len == 0) /* skip blank lines */
125: continue;
126: switch (type)
127: {
128: case -1: new_indent = indent; /* left align */
129: break;
130: case 0: new_indent = (width - len) / 2; /* center */
131: break;
132: case 1: new_indent = width - len; /* right align */
133: break;
134: }
135: if (new_indent < 0)
136: new_indent = 0;
137: set_indent(new_indent, TRUE); /* set indent */
138: }
139: curwin->w_cursor = pos;
140: beginline(TRUE);
141: updateScreen(NOT_VALID);
142: }
143:
144: void
145: do_retab(start, end, new_ts, force)
146: linenr_t start;
147: linenr_t end;
148: int new_ts;
149: int force;
150: {
151: linenr_t lnum;
152: int got_tab = FALSE;
153: long num_spaces = 0;
154: long num_tabs;
155: long len;
156: long col;
157: long vcol;
158: long start_col = 0; /* For start of white-space string */
159: long start_vcol = 0; /* For start of white-space string */
160: int temp;
161: long old_len;
162: char_u *ptr;
163: char_u *new_line = (char_u *)1; /* init to non-NULL */
164: int did_something = FALSE;
165: int did_undo; /* called u_save for current line */
166:
167: if (new_ts == 0)
168: new_ts = curbuf->b_p_ts;
169: for (lnum = start; !got_int && lnum <= end; ++lnum)
170: {
171: ptr = ml_get(lnum);
172: col = 0;
173: vcol = 0;
174: did_undo = FALSE;
175: for (;;)
176: {
177: if (vim_iswhite(ptr[col]))
178: {
179: if (!got_tab && num_spaces == 0)
180: {
181: /* First consecutive white-space */
182: start_vcol = vcol;
183: start_col = col;
184: }
185: if (ptr[col] == ' ')
186: num_spaces++;
187: else
188: got_tab = TRUE;
189: }
190: else
191: {
192: if (got_tab || (force && num_spaces > 1))
193: {
194: /* Retabulate this string of white-space */
195:
196: /* len is virtual length of white string */
197: len = num_spaces = vcol - start_vcol;
198: num_tabs = 0;
199: if (!curbuf->b_p_et)
200: {
201: temp = new_ts - (start_vcol % new_ts);
202: if (num_spaces >= temp)
203: {
204: num_spaces -= temp;
205: num_tabs++;
206: }
207: num_tabs += num_spaces / new_ts;
208: num_spaces -= (num_spaces / new_ts) * new_ts;
209: }
210: if (curbuf->b_p_et || got_tab ||
211: (num_spaces + num_tabs < len))
212: {
213: if (did_undo == FALSE)
214: {
215: did_undo = TRUE;
216: if (u_save((linenr_t)(lnum - 1),
217: (linenr_t)(lnum + 1)) == FAIL)
218: {
219: new_line = NULL; /* flag out-of-memory */
220: break;
221: }
222: }
223:
224: /* len is actual number of white characters used */
225: len = num_spaces + num_tabs;
226: old_len = STRLEN(ptr);
227: new_line = lalloc(old_len - col + start_col + len + 1,
228: TRUE);
229: if (new_line == NULL)
230: break;
231: if (start_col > 0)
232: vim_memmove(new_line, ptr, (size_t)start_col);
233: vim_memmove(new_line + start_col + len,
234: ptr + col, (size_t)(old_len - col + 1));
235: ptr = new_line + start_col;
236: for (col = 0; col < len; col++)
237: ptr[col] = (col < num_tabs) ? '\t' : ' ';
238: ml_replace(lnum, new_line, FALSE);
239: did_something = TRUE;
240: ptr = new_line;
241: col = start_col + len;
242: }
243: }
244: got_tab = FALSE;
245: num_spaces = 0;
246: }
247: if (ptr[col] == NUL)
248: break;
249: vcol += chartabsize(ptr[col++], (colnr_t)vcol);
250: }
251: if (new_line == NULL) /* out of memory */
252: break;
253: line_breakcheck();
254: }
255: if (got_int)
256: emsg(e_interr);
257: if (did_something)
258: CHANGED;
259: curbuf->b_p_ts = new_ts;
260: coladvance(curwin->w_curswant);
261: }
262:
263: /*
264: * :move command - move lines line1-line2 to line n
265: *
266: * return FAIL for failure, OK otherwise
267: */
268: int
269: do_move(line1, line2, n)
270: linenr_t line1;
271: linenr_t line2;
272: linenr_t n;
273: {
274: char_u *str;
275: linenr_t l;
276: linenr_t extra; /* Num lines added before line1 */
277: linenr_t num_lines; /* Num lines moved */
278: linenr_t last_line; /* Last line in file after adding new text */
279: int has_mark;
280:
281: if (n >= line1 && n < line2)
282: {
283: EMSG("Move lines into themselves");
284: return FAIL;
285: }
286:
287: num_lines = line2 - line1 + 1;
288:
289: /*
290: * First we copy the old text to its new location -- webb
291: */
292: if (u_save(n, n + 1) == FAIL)
293: return FAIL;
294: for (extra = 0, l = line1; l <= line2; l++)
295: {
296: str = strsave(ml_get(l + extra));
297: if (str != NULL)
298: {
299: has_mark = ml_has_mark(l + extra);
300: ml_append(n + l - line1, str, (colnr_t)0, FALSE);
301: vim_free(str);
302: if (has_mark)
303: ml_setmarked(n + l - line1 + 1);
304: if (n < line1)
305: extra++;
306: }
307: }
308:
309: /*
310: * Now we must be careful adjusting our marks so that we don't overlap our
311: * mark_adjust() calls.
312: *
313: * We adjust the marks within the old text so that they refer to the
314: * last lines of the file (temporarily), because we know no other marks
315: * will be set there since these line numbers did not exist until we added
316: * our new lines.
317: *
318: * Then we adjust the marks on lines between the old and new text positions
319: * (either forwards or backwards).
320: *
321: * And Finally we adjust the marks we put at the end of the file back to
322: * their final destination at the new text position -- webb
323: */
324: last_line = curbuf->b_ml.ml_line_count;
325: mark_adjust(line1, line2, last_line - line2, 0L);
326: if (n >= line2)
327: mark_adjust(line2 + 1, n, -num_lines, 0L);
328: else
329: mark_adjust(n + 1, line1 - 1, num_lines, 0L);
330: mark_adjust(last_line - num_lines + 1, last_line,
331: -(last_line - n - extra), 0L);
332:
333: /*
334: * Now we delete the original text -- webb
335: */
336: if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
337: return FAIL;
338:
339: for (l = line1; l <= line2; l++)
340: ml_delete(line1 + extra, TRUE);
341:
342: CHANGED;
343: if (!global_busy && num_lines > p_report)
344: smsg((char_u *)"%ld line%s moved", num_lines, plural(num_lines));
345: return OK;
346: }
347:
348: /*
349: * :copy command - copy lines line1-line2 to line n
350: */
351: void
352: do_copy(line1, line2, n)
353: linenr_t line1;
354: linenr_t line2;
355: linenr_t n;
356: {
357: linenr_t lnum;
358: char_u *p;
359:
360: mark_adjust(n + 1, MAXLNUM, line2 - line1 + 1, 0L);
361:
362: /*
363: * there are three situations:
364: * 1. destination is above line1
365: * 2. destination is between line1 and line2
366: * 3. destination is below line2
367: *
368: * n = destination (when starting)
369: * curwin->w_cursor.lnum = destination (while copying)
370: * line1 = start of source (while copying)
371: * line2 = end of source (while copying)
372: */
373: if (u_save(n, n + 1) == FAIL)
374: return;
375: curwin->w_cursor.lnum = n;
376: lnum = line2 - line1 + 1;
377: while (line1 <= line2)
378: {
379: /* need to use strsave() because the line will be unlocked
380: within ml_append */
381: p = strsave(ml_get(line1));
382: if (p != NULL)
383: {
384: ml_append(curwin->w_cursor.lnum, p, (colnr_t)0, FALSE);
385: vim_free(p);
386: }
387: /* situation 2: skip already copied lines */
388: if (line1 == n)
389: line1 = curwin->w_cursor.lnum;
390: ++line1;
391: if (curwin->w_cursor.lnum < line1)
392: ++line1;
393: if (curwin->w_cursor.lnum < line2)
394: ++line2;
395: ++curwin->w_cursor.lnum;
396: }
397: CHANGED;
398: msgmore((long)lnum);
399: }
400:
401: /*
402: * Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
403: * Bangs in the argument are replaced with the previously entered command.
404: * Remember the argument.
405: */
406: void
407: do_bang(addr_count, line1, line2, forceit, arg, do_in, do_out)
408: int addr_count;
409: linenr_t line1, line2;
410: int forceit;
411: char_u *arg;
412: int do_in, do_out;
413: {
414: static char_u *prevcmd = NULL; /* the previous command */
415: char_u *newcmd = NULL; /* the new command */
416: int ins_prevcmd;
417: char_u *t;
418: char_u *p;
419: char_u *trailarg;
420: int len;
421: int scroll_save = msg_scroll;
422:
423: /*
424: * Disallow shell commands from .exrc and .vimrc in current directory for
425: * security reasons.
426: */
427: if (secure)
428: {
429: secure = 2;
430: emsg(e_curdir);
431: return;
432: }
433:
434: if (addr_count == 0) /* :! */
435: {
436: msg_scroll = FALSE; /* don't scroll here */
437: autowrite_all();
438: msg_scroll = scroll_save;
439: }
440:
441: /*
442: * Try to find an embedded bang, like in :!<cmd> ! [args]
443: * (:!! is indicated by the 'forceit' variable)
444: */
445: ins_prevcmd = forceit;
446: trailarg = arg;
447: do
448: {
449: len = STRLEN(trailarg) + 1;
450: if (newcmd != NULL)
451: len += STRLEN(newcmd);
452: if (ins_prevcmd)
453: {
454: if (prevcmd == NULL)
455: {
456: emsg(e_noprev);
457: vim_free(newcmd);
458: return;
459: }
460: len += STRLEN(prevcmd);
461: }
462: if ((t = alloc(len)) == NULL)
463: {
464: vim_free(newcmd);
465: return;
466: }
467: *t = NUL;
468: if (newcmd != NULL)
469: STRCAT(t, newcmd);
470: if (ins_prevcmd)
471: STRCAT(t, prevcmd);
472: p = t + STRLEN(t);
473: STRCAT(t, trailarg);
474: vim_free(newcmd);
475: newcmd = t;
476:
477: /*
478: * Scan the rest of the argument for '!', which is replaced by the
479: * previous command. "\!" is replaced by "!" (this is vi compatible).
480: */
481: trailarg = NULL;
482: while (*p)
483: {
484: if (*p == '!')
485: {
486: if (p > newcmd && p[-1] == '\\')
487: vim_memmove(p - 1, p, (size_t)(STRLEN(p) + 1));
488: else
489: {
490: trailarg = p;
491: *trailarg++ = NUL;
492: ins_prevcmd = TRUE;
493: break;
494: }
495: }
496: ++p;
497: }
498: } while (trailarg != NULL);
499:
500: vim_free(prevcmd);
501: prevcmd = newcmd;
502:
503: if (bangredo) /* put cmd in redo buffer for ! command */
504: {
505: AppendToRedobuff(prevcmd);
506: AppendToRedobuff((char_u *)"\n");
507: bangredo = FALSE;
508: }
509: if (addr_count == 0) /* :! */
510: {
511: /* echo the command */
512: msg_start();
513: msg_outchar(':');
514: msg_outchar('!');
515: msg_outtrans(prevcmd);
516: msg_clr_eos();
517: windgoto(msg_row, msg_col);
518:
519: do_shell(prevcmd);
520: }
521: else /* :range! */
522: do_filter(line1, line2, prevcmd, do_in, do_out);
523: }
524:
525: /*
526: * call a shell to execute a command
527: */
528: void
529: do_shell(cmd)
530: char_u *cmd;
531: {
532: BUF *buf;
533: int save_nwr;
534:
535: /*
536: * Disallow shell commands from .exrc and .vimrc in current directory for
537: * security reasons.
538: */
539: if (secure)
540: {
541: secure = 2;
542: emsg(e_curdir);
543: msg_end();
544: return;
545: }
546:
547: #ifdef WIN32
548: /*
549: * Check if external commands are allowed now.
550: */
551: if (can_end_termcap_mode(TRUE) == FALSE)
552: return;
553: #endif
554:
555: /*
556: * For autocommands we want to get the output on the current screen, to
557: * avoid having to type return below.
558: */
559: msg_outchar('\r'); /* put cursor at start of line */
560: #ifdef AUTOCMD
561: if (!autocmd_busy)
562: #endif
563: stoptermcap();
564: msg_outchar('\n'); /* may shift screen one line up */
565:
566: /* warning message before calling the shell */
567: if (p_warn
568: #ifdef AUTOCMD
569: && !autocmd_busy
570: #endif
571: )
572: for (buf = firstbuf; buf; buf = buf->b_next)
573: if (buf->b_changed)
574: {
575: MSG_OUTSTR("[No write since last change]\n");
576: break;
577: }
578:
579: /* This windgoto is required for when the '\n' resulted in a "delete line 1"
580: * command to the terminal. */
581:
582: windgoto(msg_row, msg_col);
583: cursor_on();
584: (void)call_shell(cmd, SHELL_COOKED);
585: need_check_timestamps = TRUE;
586:
587: /*
588: * put the message cursor at the end of the screen, avoids wait_return() to
589: * overwrite the text that the external command showed
590: */
591: msg_pos((int)Rows - 1, 0);
592:
593: #ifdef AUTOCMD
594: if (!autocmd_busy)
595: #endif
596: {
597: /*
598: * If K_TI is defined, we assume that we switch screens when
599: * starttermcap() is called. In that case we really want to wait for
600: * "hit return to continue".
601: */
602: save_nwr = no_wait_return;
603: if (*T_TI != NUL)
604: no_wait_return = FALSE;
605: #ifdef AMIGA
606: wait_return(term_console ? -1 : TRUE); /* see below */
607: #else
608: wait_return(TRUE);
609: #endif
610: no_wait_return = save_nwr;
611: starttermcap(); /* start termcap if not done by wait_return() */
612:
613: /*
614: * In an Amiga window redrawing is caused by asking the window size.
615: * If we got an interrupt this will not work. The chance that the
616: * window size is wrong is very small, but we need to redraw the
617: * screen. Don't do this if ':' hit in wait_return(). THIS IS UGLY
618: * but it saves an extra redraw.
619: */
620: #ifdef AMIGA
621: if (skip_redraw) /* ':' hit in wait_return() */
622: must_redraw = CLEAR;
623: else if (term_console)
624: {
625: OUTSTR("\033[0 q"); /* get window size */
626: if (got_int)
627: must_redraw = CLEAR; /* if got_int is TRUE, redraw needed */
628: else
629: must_redraw = 0; /* no extra redraw needed */
630: }
631: #endif /* AMIGA */
632: }
633: #ifdef AUTOCMD
634: else
635: must_redraw = CLEAR;
636: #endif
637: }
638:
639: /*
640: * do_filter: filter lines through a command given by the user
641: *
642: * We use temp files and the call_shell() routine here. This would normally
643: * be done using pipes on a UNIX machine, but this is more portable to
644: * non-unix machines. The call_shell() routine needs to be able
645: * to deal with redirection somehow, and should handle things like looking
646: * at the PATH env. variable, and adding reasonable extensions to the
647: * command name given by the user. All reasonable versions of call_shell()
648: * do this.
649: * We use input redirection if do_in is TRUE.
650: * We use output redirection if do_out is TRUE.
651: */
652: void
653: do_filter(line1, line2, buff, do_in, do_out)
654: linenr_t line1, line2;
655: char_u *buff;
656: int do_in, do_out;
657: {
658: #ifdef USE_TMPNAM
659: char_u itmp[L_tmpnam]; /* use tmpnam() */
660: char_u otmp[L_tmpnam];
661: #else
662: char_u itmp[TMPNAMELEN];
663: char_u otmp[TMPNAMELEN];
664: #endif
665: linenr_t linecount;
666: FPOS cursor_save;
667:
668: /*
669: * Disallow shell commands from .exrc and .vimrc in current directory for
670: * security reasons.
671: */
672: if (secure)
673: {
674: secure = 2;
675: emsg(e_curdir);
676: return;
677: }
678: if (*buff == NUL) /* no filter command */
679: return;
680:
681: #ifdef WIN32
682: /*
683: * Check if external commands are allowed now.
684: */
685: if (can_end_termcap_mode(TRUE) == FALSE)
686: return;
687: #endif
688:
689: cursor_save = curwin->w_cursor;
690: linecount = line2 - line1 + 1;
691: curwin->w_cursor.lnum = line1;
692: curwin->w_cursor.col = 0;
693:
694: /*
695: * 1. Form temp file names
696: * 2. Write the lines to a temp file
697: * 3. Run the filter command on the temp file
698: * 4. Read the output of the command into the buffer
699: * 5. Delete the original lines to be filtered
700: * 6. Remove the temp files
701: */
702:
703: #ifndef USE_TMPNAM /* tmpnam() will make its own name */
704: # ifdef OS2
705: check_tmpenv();
706: expand_env(TMPNAME1, itmp, TMPNAMELEN);
707: expand_env(TMPNAME2, otmp, TMPNAMELEN);
708: # else
709: STRCPY(itmp, TMPNAME1);
710: STRCPY(otmp, TMPNAME2);
711: # endif
712: #endif
713:
714: if ((do_in && *mktemp((char *)itmp) == NUL) ||
715: (do_out && *mktemp((char *)otmp) == NUL))
716: {
717: emsg(e_notmp);
718: return;
719: }
720:
721: /*
722: * The writing and reading of temp files will not be shown.
723: * Vi also doesn't do this and the messages are not very informative.
724: */
725: ++no_wait_return; /* don't call wait_return() while busy */
726: if (do_in && buf_write(curbuf, itmp, NULL, line1, line2,
727: FALSE, 0, FALSE, TRUE) == FAIL)
728: {
729: msg_outchar('\n'); /* keep message from buf_write() */
730: --no_wait_return;
731: (void)emsg2(e_notcreate, itmp); /* will call wait_return */
732: goto filterend;
733: }
734: if (!do_out)
735: msg_outchar('\n');
736:
737: #if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2)
738: /*
739: * put braces around the command (for concatenated commands)
740: */
741: sprintf((char *)IObuff, "(%s)", (char *)buff);
742: if (do_in)
743: {
744: STRCAT(IObuff, " < ");
745: STRCAT(IObuff, itmp);
746: }
747: #else
748: /*
749: * for shells that don't understand braces around commands, at least allow
750: * the use of commands in a pipe.
751: */
752: STRCPY(IObuff, buff);
753: if (do_in)
754: {
755: char_u *p;
756: /*
757: * If there is a pipe, we have to put the '<' in front of it
758: */
759: p = vim_strchr(IObuff, '|');
760: if (p)
761: *p = NUL;
762: STRCAT(IObuff, " < ");
763: STRCAT(IObuff, itmp);
764: p = vim_strchr(buff, '|');
765: if (p)
766: STRCAT(IObuff, p);
767: }
768: #endif
769: if (do_out)
770: {
771: char_u *p;
772:
773: if ((p = vim_strchr(p_srr, '%')) != NULL && p[1] == 's')
774: {
775: p = IObuff + STRLEN(IObuff);
776: *p++ = ' '; /* not really needed? Not with sh, ksh or bash */
777: sprintf((char *)p, (char *)p_srr, (char *)otmp);
778: }
779: else
780: sprintf((char *)IObuff + STRLEN(IObuff), " %s %s",
781: (char *)p_srr, (char *)otmp);
782: }
783:
784: windgoto((int)Rows - 1, 0);
785: cursor_on();
786:
787: /*
788: * When not redirecting the output the command can write anything to the
789: * screen. If 'shellredir' is equal to ">", screen may be messed up by
790: * stderr output of external command. Clear the screen later.
791: * If do_in is FALSE, this could be something like ":r !cat", which may
792: * also mess up the screen, clear it later.
793: */
794: if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
795: must_redraw = CLEAR;
796: else
797: redraw_later(NOT_VALID);
798:
799: /*
800: * When call_shell() fails wait_return() is called to give the user a
801: * chance to read the error messages. Otherwise errors are ignored, so you
802: * can see the error messages from the command that appear on stdout; use
803: * 'u' to fix the text
804: * Switch to cooked mode when not redirecting stdin, avoids that something
805: * like ":r !cat" hangs.
806: */
807: if (call_shell(IObuff, SHELL_FILTER | SHELL_COOKED) == FAIL)
808: {
809: must_redraw = CLEAR;
810: wait_return(FALSE);
811: }
812: need_check_timestamps = TRUE;
813:
814: if (do_out)
815: {
816: if (u_save((linenr_t)(line2), (linenr_t)(line2 + 1)) == FAIL)
817: {
818: goto error;
819: }
820: if (readfile(otmp, NULL, line2, FALSE, (linenr_t)0, MAXLNUM, TRUE)
821: == FAIL)
822: {
823: msg_outchar('\n');
824: emsg2(e_notread, otmp);
825: goto error;
826: }
827:
828: if (do_in)
829: {
830: /* put cursor on first filtered line for ":range!cmd" */
831: curwin->w_cursor.lnum = line1;
832: dellines(linecount, TRUE, TRUE);
833: curbuf->b_op_start.lnum -= linecount; /* adjust '[ */
834: curbuf->b_op_end.lnum -= linecount; /* adjust '] */
835: }
836: else
837: {
838: /* put cursor on last new line for ":r !cmd" */
839: curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
840: linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
841: }
842: beginline(TRUE); /* cursor on first non-blank */
843: --no_wait_return;
844:
845: if (linecount > p_report)
846: {
847: if (do_in)
848: {
849: sprintf((char *)msg_buf, "%ld lines filtered", (long)linecount);
850: if (msg(msg_buf) && !msg_scroll)
851: keep_msg = msg_buf; /* display message after redraw */
852: }
853: else
854: msgmore((long)linecount);
855: }
856: }
857: else
858: {
859: error:
860: /* put cursor back in same position for ":w !cmd" */
861: curwin->w_cursor = cursor_save;
862: --no_wait_return;
863: wait_return(FALSE);
864: }
865:
866: filterend:
867: vim_remove(itmp);
868: vim_remove(otmp);
869: }
870:
871: #ifdef OS2
872: /*
873: * If $TMP is not defined, construct a sensible default.
874: * This is required for TMPNAME1 and TMPNAME2 to work.
875: */
876: static void
877: check_tmpenv()
878: {
879: char_u *envent;
880:
881: if (getenv("TMP") == NULL)
882: {
883: envent = alloc(8);
884: if (envent != NULL)
885: {
886: strcpy(envent, "TMP=C:/");
887: putenv(envent);
888: }
889: }
890: }
891: #endif /* OS2 */
892:
893: #ifdef VIMINFO
894:
895: static int no_viminfo __ARGS((void));
896:
897: static int
898: no_viminfo()
899: {
900: /* "vim -i NONE" does not read or write a viminfo file */
901: return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
902: }
903:
904: /*
905: * read_viminfo() -- Read the viminfo file. Registers etc. which are already
906: * set are not over-written unless force is TRUE. -- webb
907: */
908: int
909: read_viminfo(file, want_info, want_marks, force)
910: char_u *file;
911: int want_info;
912: int want_marks;
913: int force;
914: {
915: FILE *fp;
916:
917: if (no_viminfo())
918: return FAIL;
919:
920: file = viminfo_filename(file); /* may set to default if NULL */
921: if ((fp = fopen((char *)file, READBIN)) == NULL)
922: return FAIL;
923:
924: do_viminfo(fp, NULL, want_info, want_marks, force);
925:
926: fclose(fp);
927:
928: return OK;
929: }
930:
931: /*
932: * write_viminfo() -- Write the viminfo file. The old one is read in first so
933: * that effectively a merge of current info and old info is done. This allows
934: * multiple vims to run simultaneously, without losing any marks etc. If
935: * force is TRUE, then the old file is not read in, and only internal info is
936: * written to the file. -- webb
937: */
938: void
939: write_viminfo(file, force)
940: char_u *file;
941: int force;
942: {
943: FILE *fp_in = NULL;
944: FILE *fp_out = NULL;
945: #ifdef USE_TMPNAM
946: char_u tmpname[L_tmpnam]; /* use tmpnam() */
947: #else
948: char_u tmpname[TMPNAMELEN];
949: #endif
950:
951: if (no_viminfo())
952: return;
953:
954: #ifndef USE_TMPNAM /* tmpnam() will make its own name */
955: # ifdef OS2
956: check_tmpenv();
957: expand_env(TMPNAME2, tmpname, TMPNAMELEN);
958: # else
959: STRCPY(tmpname, TMPNAME2);
960: # endif
961: #endif
962:
963: file = viminfo_filename(file); /* may set to default if NULL */
964: file = strsave(file); /* make a copy, don't want NameBuff */
965: if (file != NULL)
966: {
967: fp_in = fopen((char *)file, READBIN);
968: if (fp_in == NULL)
969: fp_out = fopen((char *)file, WRITEBIN);
970: else if (*mktemp((char *)tmpname) != NUL)
971: fp_out = fopen((char *)tmpname, WRITEBIN);
972: }
973: if (file == NULL || fp_out == NULL)
974: {
975: EMSG2("Can't write viminfo file %s!", file == NULL ? (char_u *)"" :
976: fp_in == NULL ? file : tmpname);
977: if (fp_in != NULL)
978: fclose(fp_in);
979: vim_free(file);
980: return;
981: }
982:
983: do_viminfo(fp_in, fp_out, !force, !force, FALSE);
984:
985: fclose(fp_out); /* errors are ignored !? */
986: if (fp_in != NULL)
987: {
988: fclose(fp_in);
989: if (vim_rename(tmpname, file) == -1)
990: vim_remove(tmpname);
991: }
992: vim_free(file);
993: }
994:
995: static char_u *
996: viminfo_filename(file)
997: char_u *file;
998: {
999: if (file == NULL || *file == NUL)
1000: {
1001: expand_env(use_viminfo == NULL ? (char_u *)VIMINFO_FILE : use_viminfo,
1002: NameBuff, MAXPATHL);
1003: return NameBuff;
1004: }
1005: return file;
1006: }
1007:
1008: /*
1009: * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
1010: */
1011: static void
1012: do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
1013: FILE *fp_in;
1014: FILE *fp_out;
1015: int want_info;
1016: int want_marks;
1017: int force_read;
1018: {
1019: int count = 0;
1020: int eof = FALSE;
1021: char_u *line;
1022:
1023: if ((line = alloc(LSIZE)) == NULL)
1024: return;
1025:
1026: if (fp_in != NULL)
1027: {
1028: if (want_info)
1029: eof = read_viminfo_up_to_marks(line, fp_in, force_read);
1030: else
1031: /* Skip info, find start of marks */
1032: while (!(eof = vim_fgets(line, LSIZE, fp_in)) && line[0] != '>')
1033: ;
1034: }
1035: if (fp_out != NULL)
1036: {
1037: /* Write the info: */
1038: fprintf(fp_out, "# This viminfo file was generated by vim\n");
1039: fprintf(fp_out, "# You may edit it if you're careful!\n\n");
1040: write_viminfo_search_pattern(fp_out);
1041: write_viminfo_sub_string(fp_out);
1042: write_viminfo_history(fp_out);
1043: write_viminfo_registers(fp_out);
1044: write_viminfo_filemarks(fp_out);
1045: count = write_viminfo_marks(fp_out);
1046: }
1047: if (fp_in != NULL && want_marks)
1048: copy_viminfo_marks(line, fp_in, fp_out, count, eof);
1049: vim_free(line);
1050: }
1051:
1052: /*
1053: * read_viminfo_up_to_marks() -- Only called from do_viminfo(). Reads in the
1054: * first part of the viminfo file which contains everything but the marks that
1055: * are local to a file. Returns TRUE when end-of-file is reached. -- webb
1056: */
1057: static int
1058: read_viminfo_up_to_marks(line, fp, force)
1059: char_u *line;
1060: FILE *fp;
1061: int force;
1062: {
1063: int eof;
1064:
1065: prepare_viminfo_history(force ? 9999 : 0);
1066: eof = vim_fgets(line, LSIZE, fp);
1067: while (!eof && line[0] != '>')
1068: {
1069: switch (line[0])
1070: {
1071: case NUL:
1072: case '\r':
1073: case '\n':
1074: case '#': /* A comment */
1075: eof = vim_fgets(line, LSIZE, fp);
1076: break;
1077: case '"':
1078: eof = read_viminfo_register(line, fp, force);
1079: break;
1080: case '/': /* Search string */
1081: case '&': /* Substitute search string */
1082: case '~': /* Last search string, followed by '/' or '&' */
1083: eof = read_viminfo_search_pattern(line, fp, force);
1084: break;
1085: case '$':
1086: eof = read_viminfo_sub_string(line, fp, force);
1087: break;
1088: case ':':
1089: case '?':
1090: eof = read_viminfo_history(line, fp);
1091: break;
1092: case '\'':
1093: /* How do we have a file mark when the file is not in the
1094: * buffer list?
1095: */
1096: eof = read_viminfo_filemark(line, fp, force);
1097: break;
1098: #if 0
1099: case '+':
1100: /* eg: "+40 /path/dir file", for running vim with no args */
1101: eof = vim_fgets(line, LSIZE, fp);
1102: break;
1103: #endif
1104: default:
1105: EMSG2("viminfo: Illegal starting char in line %s", line);
1106: eof = vim_fgets(line, LSIZE, fp);
1107: break;
1108: }
1109: }
1110: finish_viminfo_history();
1111: return eof;
1112: }
1113:
1114: /*
1115: * check string read from viminfo file
1116: * remove '\n' at the end of the line
1117: * - replace CTRL-V CTRL-V with CTRL-V
1118: * - replace CTRL-V 'n' with '\n'
1119: */
1120: void
1121: viminfo_readstring(p)
1122: char_u *p;
1123: {
1124: while (*p != NUL && *p != '\n')
1125: {
1126: if (*p == Ctrl('V'))
1127: {
1128: if (p[1] == 'n')
1129: p[0] = '\n';
1130: vim_memmove(p + 1, p + 2, STRLEN(p));
1131: }
1132: ++p;
1133: }
1134: *p = NUL;
1135: }
1136:
1137: /*
1138: * write string to viminfo file
1139: * - replace CTRL-V with CTRL-V CTRL-V
1140: * - replace '\n' with CTRL-V 'n'
1141: * - add a '\n' at the end
1142: */
1143: void
1144: viminfo_writestring(fd, p)
1145: FILE *fd;
1146: char_u *p;
1147: {
1148: register int c;
1149:
1150: while ((c = *p++) != NUL)
1151: {
1152: if (c == Ctrl('V') || c == '\n')
1153: {
1154: putc(Ctrl('V'), fd);
1155: if (c == '\n')
1156: c = 'n';
1157: }
1158: putc(c, fd);
1159: }
1160: putc('\n', fd);
1161: }
1162: #endif /* VIMINFO */
1163:
1164: /*
1165: * Implementation of ":fixdel", also used by get_stty().
1166: * <BS> resulting <Del>
1167: * ^? ^H
1168: * not ^? ^?
1169: */
1170: void
1171: do_fixdel()
1172: {
1173: char_u *p;
1174:
1175: p = find_termcode((char_u *)"kb");
1176: add_termcode((char_u *)"kD", p != NULL && *p == 0x7f ?
1177: (char_u *)"\010" : (char_u *)"\177");
1178: }
1179:
1180: void
1181: print_line(lnum, use_number)
1182: linenr_t lnum;
1183: int use_number;
1184: {
1185: char_u numbuf[20];
1186:
1187: msg_outchar('\n');
1188: if (curwin->w_p_nu || use_number)
1189: {
1190: sprintf((char *)numbuf, "%7ld ", (long)lnum);
1191: set_highlight('n'); /* Highlight line numbers */
1192: start_highlight();
1193: msg_outstr(numbuf);
1194: stop_highlight();
1195: }
1196: msg_prt_line(ml_get(lnum));
1197: }
1198:
1199: /*
1200: * Implementation of ":file [fname]".
1201: */
1202: void
1203: do_file(arg, forceit)
1204: char_u *arg;
1205: int forceit;
1206: {
1207: char_u *fname, *sfname;
1208: BUF *buf;
1209:
1210: if (*arg != NUL)
1211: {
1212: /*
1213: * The name of the current buffer will be changed.
1214: * A new buffer entry needs to be made to hold the old
1215: * file name, which will become the alternate file name.
1216: */
1217: fname = curbuf->b_filename;
1218: sfname = curbuf->b_sfilename;
1219: curbuf->b_filename = NULL;
1220: curbuf->b_sfilename = NULL;
1221: if (setfname(arg, NULL, TRUE) == FAIL)
1222: {
1223: curbuf->b_filename = fname;
1224: curbuf->b_sfilename = sfname;
1225: return;
1226: }
1227: curbuf->b_notedited = TRUE;
1228: buf = buflist_new(fname, sfname, curwin->w_cursor.lnum, FALSE);
1229: if (buf != NULL)
1230: curwin->w_alt_fnum = buf->b_fnum;
1231: vim_free(fname);
1232: vim_free(sfname);
1233: }
1234: /* print full filename if :cd used */
1235: fileinfo(did_cd, FALSE, forceit);
1236: }