Annotation of src/usr.bin/vim/cmdcmds.c, Revision 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: }