ex_docmd.c
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:169k
源码类别:

编辑器/阅读器

开发平台:

DOS

  1. /*
  2.  * start editing a new file
  3.  *
  4.  *     fnum: file number; if zero use ffname/sfname
  5.  *   ffname: the file name
  6.  * - full path if sfname used,
  7.  * - any file name if sfname is NULL
  8.  * - empty string to re-edit with the same file name (but may be
  9.  *     in a different directory)
  10.  * - NULL to start an empty buffer
  11.  *   sfname: the short file name (or NULL)
  12.  *  command: the command to be executed after loading the file
  13.  *  newlnum: put cursor on this line number (if possible)
  14.  *    flags:
  15.  *    ECMD_HIDE: if TRUE don't free the current buffer
  16.  *     ECMD_SET_HELP: set b_help flag of (new) buffer before opening file
  17.  *  ECMD_OLDBUF: use existing buffer if it exists
  18.  * ECMD_FORCEIT: ! used for Ex command
  19.  * ECMD_ADDBUF : don't edit, just add to buffer list
  20.  *
  21.  * return FAIL for failure, OK otherwise
  22.  */
  23.     int
  24. do_ecmd(fnum, ffname, sfname, command, newlnum, flags)
  25.     int fnum;
  26.     char_u *ffname;
  27.     char_u *sfname;
  28.     char_u *command;
  29.     linenr_t newlnum;
  30.     int flags;
  31. {
  32.     int other_file; /* TRUE if editing another file */
  33.     int oldbuf; /* TRUE if using existing buffer */
  34. #ifdef AUTOCMD
  35.     int auto_buf = FALSE; /* TRUE if autocommands brought us
  36.    into the buffer unexpectedly */
  37. #endif
  38.     BUF *buf;
  39.     char_u *free_fname = NULL;
  40. #ifdef USE_BROWSE
  41.     char_u *browse_file = NULL;
  42. #endif
  43.     int retval = FAIL;
  44.     long n;
  45.     if (fnum != 0)
  46.     {
  47. if (fnum == curbuf->b_fnum) /* file is already being edited */
  48.     return OK; /* nothing to do */
  49. other_file = TRUE;
  50.     }
  51.     else
  52.     {
  53. #ifdef USE_BROWSE
  54. if (browse)
  55. {
  56.     browse_file = do_browse(FALSE, (char_u *)"Edit File", NULL,
  57.   NULL, ffname, NULL, curbuf);
  58.     if (browse_file == NULL)
  59. goto theend;
  60.     ffname = browse_file;
  61. }
  62. #endif
  63.     /* if no short name given, use ffname for short name */
  64. if (sfname == NULL)
  65.     sfname = ffname;
  66. #ifdef USE_FNAME_CASE
  67. # ifdef USE_LONG_FNAME
  68. if (USE_LONG_FNAME)
  69. # endif
  70.     fname_case(sfname);     /* set correct case for short file name */
  71. #endif
  72. if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))
  73.     goto theend;
  74. if (ffname == NULL)
  75.     other_file = TRUE;
  76.     /* there is no file name */
  77. else if (*ffname == NUL && curbuf->b_ffname == NULL)
  78.     other_file = FALSE;
  79. else
  80. {
  81.     if (*ffname == NUL)     /* re-edit with same file name */
  82.     {
  83. ffname = curbuf->b_ffname;
  84. sfname = curbuf->b_fname;
  85.     }
  86.     free_fname = fix_fname(ffname); /* may expand to full path name */
  87.     if (free_fname != NULL)
  88. ffname = free_fname;
  89.     other_file = otherfile(ffname);
  90. }
  91.     }
  92. /*
  93.  * if the file was changed we may not be allowed to abandon it
  94.  * - if we are going to re-edit the same file
  95.  * - or if we are the only window on this file and if ECMD_HIDE is FALSE
  96.  */
  97.     if (  ((!other_file && !(flags & ECMD_OLDBUF))
  98.     || (curbuf->b_nwindows == 1
  99. && !(flags & (ECMD_HIDE | ECMD_ADDBUF))))
  100. && check_changed(curbuf, FALSE, !other_file,
  101. (flags & ECMD_FORCEIT), FALSE))
  102.     {
  103. if (fnum == 0 && other_file && ffname != NULL)
  104.     setaltfname(ffname, sfname, newlnum);
  105. goto theend;
  106.     }
  107. /*
  108.  * End Visual mode before switching to another buffer, so the text can be
  109.  * copied into the GUI selection buffer.
  110.  */
  111.     if (VIsual_active)
  112.     {
  113. end_visual_mode();
  114. VIsual_reselect = FALSE;
  115.     }
  116. /*
  117.  * If we are starting to edit another file, open a (new) buffer.
  118.  * Otherwise we re-use the current buffer.
  119.  */
  120.     if (other_file)
  121.     {
  122. if (!(flags & ECMD_ADDBUF))
  123. {
  124.     curwin->w_alt_fnum = curbuf->b_fnum;
  125.     buflist_altfpos();
  126. }
  127. if (fnum)
  128.     buf = buflist_findnr(fnum);
  129. else
  130. {
  131.     if (flags & ECMD_ADDBUF)
  132.     {
  133. linenr_t tlnum = 1L;
  134. if (command != NULL)
  135. {
  136.     tlnum = atol((char *)command);
  137.     if (tlnum <= 0)
  138. tlnum = 1L;
  139. }
  140. (void)buflist_new(ffname, sfname, tlnum, FALSE);
  141. goto theend;
  142.     }
  143.     else
  144. buf = buflist_new(ffname, sfname, 1L, TRUE);
  145. }
  146. if (buf == NULL)
  147.     goto theend;
  148. if (buf->b_ml.ml_mfp == NULL) /* no memfile yet */
  149. {
  150.     oldbuf = FALSE;
  151.     buf->b_nwindows = 0;
  152. }
  153. else /* existing memfile */
  154. {
  155.     oldbuf = TRUE;
  156.     buf_check_timestamp(buf);
  157. }
  158. /*
  159.  * Make the (new) buffer the one used by the current window.
  160.  * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE.
  161.  * If the current buffer was empty and has no file name, curbuf
  162.  * is returned by buflist_new().
  163.  */
  164. if (buf != curbuf)
  165. {
  166. #ifdef AUTOCMD
  167.     BUF     *old_curbuf;
  168.     char_u  *new_name = NULL;
  169.     /*
  170.      * Be careful: The autocommands may delete any buffer and change
  171.      * the current buffer.
  172.      * - If the buffer we are going to edit is deleted, give up.
  173.      * - If we ended up in the new buffer already, need to skip a few
  174.      *  things, set auto_buf.
  175.      */
  176.     old_curbuf = curbuf;
  177.     if (buf->b_fname != NULL)
  178. new_name = vim_strsave(buf->b_fname);
  179.     apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
  180.     if (!buf_valid(buf)) /* new buffer has been deleted */
  181.     {
  182. EMSG2("Autocommands unexpectedly deleted new buffer %s",
  183. new_name == NULL ? (char_u *)"" : new_name);
  184. vim_free(new_name);
  185. goto theend;
  186.     }
  187.     vim_free(new_name);
  188.     if (buf == curbuf) /* already in new buffer */
  189. auto_buf = TRUE;
  190.     else
  191.     {
  192. if (curbuf == old_curbuf)
  193. #endif
  194.     buf_copy_options(curbuf, buf, BCO_ENTER);
  195. close_buffer(curwin, curbuf, !(flags & ECMD_HIDE), FALSE);
  196. curwin->w_buffer = buf;
  197. curbuf = buf;
  198. ++curbuf->b_nwindows;
  199. /* set 'fileformat' */
  200. if (*p_ffs && !oldbuf)
  201.     set_fileformat(default_fileformat());
  202. #ifdef AUTOCMD
  203.     }
  204. #endif
  205. }
  206. else
  207.     ++curbuf->b_nwindows;
  208. curwin->w_pcmark.lnum = 1;
  209. curwin->w_pcmark.col = 0;
  210.     }
  211.     else
  212.     {
  213. if ((flags & ECMD_ADDBUF) || check_fname() == FAIL)
  214.     goto theend;
  215. oldbuf = (flags & ECMD_OLDBUF);
  216.     }
  217. /*
  218.  * If we get here we are sure to start editing
  219.  */
  220.     /* don't redraw until the cursor is in the right line */
  221.     ++RedrawingDisabled;
  222.     if (flags & ECMD_SET_HELP)
  223.     {
  224. curbuf->b_help = TRUE;
  225. curbuf->b_p_bin = FALSE; /* reset 'bin' before reading file */
  226.     }
  227. /*
  228.  * other_file oldbuf
  229.  *  FALSE FALSE     re-edit same file, buffer is re-used
  230.  *  FALSE TRUE     re-edit same file, nothing changes
  231.  *  TRUE FALSE     start editing new file, new buffer
  232.  *  TRUE TRUE     start editing in existing buffer (nothing to do)
  233.  */
  234.     if (!other_file && !oldbuf) /* re-use the buffer */
  235.     {
  236. if (newlnum == 0)
  237.     newlnum = curwin->w_cursor.lnum;
  238. buf_freeall(curbuf, FALSE); /* free all things for buffer */
  239. buf_clear(curbuf);
  240. curbuf->b_op_start.lnum = 0; /* clear '[ and '] marks */
  241. curbuf->b_op_end.lnum = 0;
  242.     }
  243.     /*
  244.      * Reset cursor position, could be used by autocommands.
  245.      */
  246.     adjust_cursor();
  247.     /*
  248.      * Check if we are editing the w_arg_idx file in the argument list.
  249.      */
  250.     check_arg_idx();
  251. #ifdef AUTOCMD
  252.     if (!auto_buf)
  253. #endif
  254.     {
  255. /*
  256.  * Set cursor and init window before reading the file and executing
  257.  * autocommands.  This allows for the autocommands to position the
  258.  * cursor.
  259.  */
  260. win_init(curwin);
  261. /*
  262.  * Careful: open_buffer() and apply_autocmds() may change the current
  263.  * buffer and window.
  264.  */
  265. if (!oldbuf)     /* need to read the file */
  266. {
  267.     curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
  268.     (void)open_buffer(FALSE);
  269. }
  270. #ifdef AUTOCMD
  271. else
  272.     apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
  273. check_arg_idx();
  274. #endif
  275. maketitle();
  276.     }
  277.     if (command == NULL)
  278.     {
  279. if (newlnum)
  280. {
  281.     curwin->w_cursor.lnum = newlnum;
  282.     check_cursor_lnum();
  283.     beginline(BL_SOL | BL_FIX);
  284. }
  285. else
  286. {
  287.     if (exmode_active)
  288.     {
  289. curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  290. check_cursor_lnum();
  291.     }
  292.     beginline(BL_WHITE | BL_FIX);
  293. }
  294.     }
  295.     /* Check if cursors in other windows on the same buffer are still valid */
  296.     check_lnums(FALSE);
  297.     /*
  298.      * Did not read the file, need to show some info about the file.
  299.      * Do this after setting the cursor.
  300.      */
  301.     if (oldbuf
  302. #ifdef AUTOCMD
  303. && !auto_buf
  304. #endif
  305.     )
  306. fileinfo(FALSE, TRUE, FALSE);
  307.     if (command != NULL)
  308. do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
  309.     --RedrawingDisabled;
  310.     if (!skip_redraw)
  311.     {
  312. n = p_so;
  313. if (command == NULL)
  314.     p_so = 999; /* force cursor halfway the window */
  315. update_topline();
  316. p_so = n;
  317. update_curbuf(NOT_VALID); /* redraw now */
  318.     }
  319.     if (p_im)
  320. need_start_insertmode = TRUE;
  321.     retval = OK;
  322. theend:
  323. #ifdef USE_BROWSE
  324.     vim_free(browse_file);
  325. #endif
  326.     vim_free(free_fname);
  327.     return retval;
  328. }
  329. #ifdef QUICKFIX
  330.     static void
  331. do_make(arg, errorformat)
  332.     char_u *arg;
  333.     char_u *errorformat;
  334. {
  335.     char_u *name;
  336.     autowrite_all();
  337.     name = get_mef_name(TRUE);
  338.     if (name == NULL)
  339. return;
  340.     mch_remove(name);     /* in case it's not unique */
  341.     /*
  342.      * If 'shellpipe' empty: don't redirect to 'errorfile'.
  343.      */
  344.     if (*p_sp == NUL)
  345. sprintf((char *)IObuff, "%s%s%s", p_shq, arg, p_shq);
  346.     else
  347. sprintf((char *)IObuff, "%s%s%s %s %s", p_shq, arg, p_shq, p_sp, name);
  348.     /*
  349.      * Output a newline if there's something else than the :make command that
  350.      * was typed (in which case the cursor is in column 0).
  351.      */
  352.     if (msg_col != 0)
  353. msg_putchar('n');
  354.     MSG_PUTS(":!");
  355.     msg_outtrans(IObuff); /* show what we are doing */
  356.     /* let the shell know if we are redirecting output or not */
  357.     do_shell(IObuff, *p_sp ? SHELL_DOOUT : 0);
  358. #ifdef AMIGA
  359.     out_flush();
  360. /* read window status report and redraw before message */
  361.     (void)char_avail();
  362. #endif
  363.     if (qf_init(name, errorformat) > 0)
  364. qf_jump(0, 0, FALSE); /* display first error */
  365.     mch_remove(name);
  366.     vim_free(name);
  367. }
  368. /*
  369.  * Return the name for the errorfile, in allocated memory.
  370.  * When "newname" is TRUE, find a new unique name when 'makeef' contains
  371.  * "##".  Returns NULL for error.
  372.  */
  373.     static char_u *
  374. get_mef_name(newname)
  375.     int newname;
  376. {
  377.     char_u *p;
  378.     char_u *name;
  379.     static int start = -1;
  380.     static int off = 0;
  381.     if (*p_mef == NUL)
  382.     {
  383. EMSG("makeef option not set");
  384. return NULL;
  385.     }
  386.     for (p = p_mef; *p; ++p)
  387. if (p[0] == '#' && p[1] == '#')
  388.     break;
  389.     if (*p == NUL)
  390. return vim_strsave(p_mef);
  391.     /* When "newname" set: keep trying until the name doesn't exist yet. */
  392.     for (;;)
  393.     {
  394. if (newname)
  395. {
  396.     if (start == -1)
  397. start = mch_get_pid();
  398.     ++off;
  399. }
  400. name = alloc((unsigned)STRLEN(p_mef) + 30);
  401. if (name == NULL)
  402.     break;
  403. STRCPY(name, p_mef);
  404. sprintf((char *)name + (p - p_mef), "%d%d", start, off);
  405. STRCAT(name, p + 2);
  406. if (!newname || mch_getperm(name) < 0)
  407.     break;
  408. vim_free(name);
  409.     }
  410.     return name;
  411. }
  412. /*
  413.  * ":cfile" command.
  414.  */
  415.     static void
  416. do_cfile(eap)
  417.     EXARG *eap;
  418. {
  419.     if (*eap->arg != NUL)
  420. set_string_option_direct((char_u *)"ef", -1, eap->arg, TRUE);
  421.     if (qf_init(p_ef, p_efm) > 0)
  422. qf_jump(0, 0, eap->forceit); /* display first error */
  423. }
  424. #endif /* QUICKFIX */
  425. /*
  426.  * Redefine the argument list to 'str'.
  427.  *
  428.  * Return FAIL for failure, OK otherwise.
  429.  */
  430.     static int
  431. do_arglist(str)
  432.     char_u *str;
  433. {
  434.     int     new_count = 0;
  435.     char_u  **new_files = NULL;
  436.     int     exp_count;
  437.     char_u  **exp_files;
  438.     char_u  **t;
  439.     char_u  *p;
  440.     int     inquote;
  441.     int     i;
  442.     while (*str)
  443.     {
  444. /*
  445.  * create a new entry in new_files[]
  446.  */
  447. t = (char_u **)lalloc((long_u)(sizeof(char_u *) * (new_count + 1)),
  448. TRUE);
  449. if (t != NULL)
  450.     for (i = new_count; --i >= 0; )
  451. t[i] = new_files[i];
  452. vim_free(new_files);
  453. if (t == NULL)
  454.     return FAIL;
  455. new_files = t;
  456. new_files[new_count++] = str;
  457. /*
  458.  * isolate one argument, taking quotes
  459.  */
  460. inquote = FALSE;
  461. for (p = str; *str; ++str)
  462. {
  463.     /*
  464.      * for MSDOS et.al. a backslash is part of a file name.
  465.      * Only skip ", space and tab.
  466.      */
  467.     if (rem_backslash(str))
  468. *p++ = *++str;
  469.     else
  470.     {
  471. if (!inquote && vim_isspace(*str))
  472.     break;
  473. if (*str == '"')
  474.     inquote ^= TRUE;
  475. else
  476.     *p++ = *str;
  477.     }
  478. }
  479. str = skipwhite(str);
  480. *p = NUL;
  481.     }
  482.     i = expand_wildcards(new_count, new_files, &exp_count, &exp_files,
  483.   EW_DIR|EW_FILE|EW_NOTFOUND);
  484.     vim_free(new_files);
  485.     if (i == FAIL)
  486. return FAIL;
  487.     if (exp_count == 0)
  488.     {
  489. emsg(e_nomatch);
  490. return FAIL;
  491.     }
  492.     FreeWild(arg_file_count, arg_files);
  493.     arg_files = exp_files;
  494.     arg_file_count = exp_count;
  495.     arg_had_last = FALSE;
  496.     /*
  497.      * put all file names in the buffer list
  498.      */
  499.     for (i = 0; i < arg_file_count; ++i)
  500. (void)buflist_add(arg_files[i]);
  501.     return OK;
  502. }
  503. /*
  504.  * Check if we are editing the w_arg_idx file in the argument list.
  505.  */
  506.     void
  507. check_arg_idx()
  508. {
  509.     if (arg_file_count > 1
  510.     && (curbuf->b_ffname == NULL
  511. || curwin->w_arg_idx >= arg_file_count
  512. || !(fullpathcmp(arg_files[curwin->w_arg_idx],
  513.  curbuf->b_ffname, TRUE) & FPC_SAME)))
  514. curwin->w_arg_idx_invalid = TRUE;
  515.     else
  516. curwin->w_arg_idx_invalid = FALSE;
  517. }
  518.     int
  519. ends_excmd(c)
  520.     int     c;
  521. {
  522.     return (c == NUL || c == '|' || c == '"' || c == 'n');
  523. }
  524. /*
  525.  * Return the next command, after the first '|' or 'n'.
  526.  * Return NULL if not found.
  527.  */
  528.     char_u *
  529. find_nextcmd(p)
  530.     char_u *p;
  531. {
  532.     while (*p != '|' && *p != 'n')
  533.     {
  534. if (*p == NUL)
  535.     return NULL;
  536. ++p;
  537.     }
  538.     return (p + 1);
  539. }
  540. /*
  541.  * Check if *p is a separator between Ex commands.
  542.  * Return NULL if it isn't, (p + 1) if it is.
  543.  */
  544.     char_u *
  545. check_nextcmd(p)
  546.     char_u *p;
  547. {
  548.     p = skipwhite(p);
  549.     if (*p == '|' || *p == 'n')
  550. return (p + 1);
  551.     else
  552. return NULL;
  553. }
  554. /*
  555.  * - if there are more files to edit
  556.  * - and this is the last window
  557.  * - and forceit not used
  558.  * - and not repeated twice on a row
  559.  *    return FAIL and give error message if 'message' TRUE
  560.  * return OK otherwise
  561.  */
  562.     static int
  563. check_more(message, forceit)
  564.     int message;     /* when FALSE check only, no messages */
  565.     int forceit;
  566. {
  567.     int     n = arg_file_count - curwin->w_arg_idx - 1;
  568.     if (!forceit && only_one_window() && arg_file_count > 1 && !arg_had_last
  569. && n >= 0 && quitmore == 0)
  570.     {
  571. if (message)
  572. {
  573. #if defined(GUI_DIALOG) || defined(CON_DIALOG)
  574.     if ((p_confirm || confirm) && curbuf->b_fname != NULL)
  575.     {
  576. char_u buff[IOSIZE];
  577. sprintf((char *)buff, "%d more files to edit.  Quit anyway?",
  578.    n);
  579. if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES)
  580.     return OK;
  581. return FAIL;
  582.     }
  583. #endif
  584.     EMSGN("%ld more files to edit", n);
  585.     quitmore = 2;     /* next try to quit is allowed */
  586. }
  587. return FAIL;
  588.     }
  589.     return OK;
  590. }
  591. /*
  592.  * Structure used to store info for each sourced file.
  593.  * It is shared between do_source() and getsourceline().
  594.  * This is required, because it needs to be handed to do_cmdline() and
  595.  * sourcing can be done recursively.
  596.  */
  597. struct source_cookie
  598. {
  599.     FILE *fp; /* opened file for sourcing */
  600. #ifdef USE_CRNL
  601.     int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
  602.     int error; /* TRUE if LF found after CR-LF */
  603. #endif
  604. };
  605. /*
  606.  * do_source: Read the file "fname" and execute its lines as EX commands.
  607.  *
  608.  * This function may be called recursively!
  609.  *
  610.  * return FAIL if file could not be opened, OK otherwise
  611.  */
  612.     int
  613. do_source(fname, check_other, is_vimrc)
  614.     char_u *fname;
  615.     int check_other;     /* check for .vimrc and _vimrc */
  616.     int is_vimrc;     /* call vimrc_found() when file exists */
  617. {
  618.     struct source_cookie    cookie;
  619.     char_u     *save_sourcing_name;
  620.     linenr_t     save_sourcing_lnum;
  621.     char_u     *p;
  622.     char_u     *fname_exp;
  623.     int     retval = FAIL;
  624. #ifdef WANT_EVAL
  625.     void     *save_funccalp;
  626. #endif
  627. #ifdef RISCOS
  628.     fname_exp = mch_munge_fname(fname);
  629. #else
  630.     fname_exp = expand_env_save(fname);
  631. #endif
  632.     if (fname_exp == NULL)
  633. goto theend;
  634. #ifdef macintosh
  635.     slash_n_colon_adjust(fname_exp);
  636. #endif
  637.     cookie.fp = fopen((char *)fname_exp, READBIN);
  638.     if (cookie.fp == NULL && check_other)
  639.     {
  640. /*
  641.  * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
  642.  * and ".exrc" by "_exrc" or vice versa.
  643.  */
  644. p = gettail(fname_exp);
  645. if ((*p == '.' || *p == '_') &&
  646. (STRICMP(p + 1, "vimrc") == 0 ||
  647.  STRICMP(p + 1, "gvimrc") == 0 ||
  648.  STRICMP(p + 1, "exrc") == 0))
  649. {
  650.     if (*p == '_')
  651. *p = '.';
  652.     else
  653. *p = '_';
  654.     cookie.fp = fopen((char *)fname_exp, READBIN);
  655. }
  656.     }
  657.     if (cookie.fp == NULL)
  658.     {
  659. if (p_verbose > 0)
  660.     smsg((char_u *)"could not source "%s"", fname);
  661. goto theend;
  662.     }
  663.     /*
  664.      * The file exists.
  665.      * - In verbose mode, give a message.
  666.      * - For a vimrc file, may want to set 'compatible', call vimrc_found().
  667.      */
  668.     if (p_verbose > 0)
  669. smsg((char_u *)"sourcing "%s"", fname);
  670.     if (is_vimrc)
  671. vimrc_found();
  672. #ifdef USE_CRNL
  673.     /* If no automatic file format: Set default to CR-NL. */
  674.     if (*p_ffs == NUL)
  675. cookie.fileformat = EOL_DOS;
  676.     else
  677. cookie.fileformat = EOL_UNKNOWN;
  678.     cookie.error = FALSE;
  679. #endif
  680.     /*
  681.      * Keep the sourcing name, for recursive calls.
  682.      */
  683.     save_sourcing_name = sourcing_name;
  684.     save_sourcing_lnum = sourcing_lnum;
  685.     sourcing_name = fname_exp;
  686.     sourcing_lnum = 0;
  687. #ifdef WANT_EVAL
  688.     /* Don't use local function variables, if called from a function */
  689.     save_funccalp = save_funccal();
  690. #endif
  691.     /*
  692.      * Call do_cmdline, which will call getsourceline() to get the lines.
  693.      */
  694.     do_cmdline(NULL, getsourceline, (void *)&cookie,
  695.      DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
  696.     retval = OK;
  697.     fclose(cookie.fp);
  698.     if (got_int)
  699. emsg(e_interr);
  700.     sourcing_name = save_sourcing_name;
  701.     sourcing_lnum = save_sourcing_lnum;
  702. #ifdef WANT_EVAL
  703.     restore_funccal(save_funccalp);
  704. #endif
  705. theend:
  706.     vim_free(fname_exp);
  707.     return retval;
  708. }
  709. /*
  710.  * Get one full line from a sourced file.
  711.  * Called by do_source() and do_cmdline().
  712.  *
  713.  * Return a pointer to the line in allocated memory.
  714.  * Return NULL for end-of-file or some error.
  715.  */
  716. /* ARGSUSED */
  717.     char_u *
  718. getsourceline(c, cookie, indent)
  719.     int     c;     /* not used */
  720.     void    *cookie;
  721.     int     indent;     /* not used */
  722. {
  723.     struct source_cookie    *sp = (struct source_cookie *)cookie;
  724.     struct growarray     ga;
  725.     int     len;
  726.     char_u     *buf;
  727. #ifdef USE_CRNL
  728.     int     has_cr;     /* CR-LF found */
  729. #endif
  730.     int     have_read = FALSE;
  731.     /* use a growarray to store the sourced line */
  732.     ga_init2(&ga, 1, 200);
  733.     /*
  734.      * Loop until there is a finished line (or end-of-file).
  735.      */
  736.     sourcing_lnum++;
  737.     for (;;)
  738.     {
  739. /* make room to read at least 80 (more) characters */
  740. if (ga_grow(&ga, 80) == FAIL)
  741.     break;
  742. buf = (char_u *)ga.ga_data;
  743. if (fgets((char *)buf + ga.ga_len, ga.ga_room, sp->fp) == NULL
  744.    || got_int)
  745.     break;
  746. len = STRLEN(buf);
  747. #ifdef USE_CRNL
  748. /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
  749.  * CTRL-Z by its own, or after a NL. */
  750. if (    (len == 1 || (len >= 2 && buf[len - 2] == 'n'))
  751. && sp->fileformat == EOL_DOS
  752. && buf[len - 1] == Ctrl('Z'))
  753. {
  754.     buf[len - 1] = NUL;
  755.     break;
  756. }
  757. #endif
  758. have_read = TRUE;
  759. ga.ga_room -= len - ga.ga_len;
  760. ga.ga_len = len;
  761. /* If the line was longer than the buffer, read more. */
  762. if (ga.ga_room == 1 && buf[len - 1] != 'n')
  763.     continue;
  764. if (len >= 1 && buf[len - 1] == 'n') /* remove trailing NL */
  765. {
  766. #ifdef USE_CRNL
  767.     has_cr = (len >= 2 && buf[len - 2] == 'r');
  768.     if (sp->fileformat == EOL_UNKNOWN)
  769.     {
  770. if (has_cr)
  771.     sp->fileformat = EOL_DOS;
  772. else
  773.     sp->fileformat = EOL_UNIX;
  774.     }
  775.     if (sp->fileformat == EOL_DOS)
  776.     {
  777. if (has_cr)     /* replace trailing CR */
  778. {
  779.     buf[len - 2] = 'n';
  780.     --len;
  781.     --ga.ga_len;
  782.     ++ga.ga_room;
  783. }
  784. else     /* lines like ":map xx yy^M" will have failed */
  785. {
  786.     if (!sp->error)
  787. EMSG("Warning: Wrong line separator, ^M may be missing");
  788.     sp->error = TRUE;
  789.     sp->fileformat = EOL_UNIX;
  790. }
  791.     }
  792. #endif
  793.     /* The 'n' is escaped if there is an odd number of ^V's just
  794.      * before it, first set "c" just before the 'V's and then check
  795.      * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
  796.     for (c = len - 2; c >= 0 && buf[c] == Ctrl('V'); c--)
  797. ;
  798.     if ((len & 1) != (c & 1)) /* escaped NL, read more */
  799.     {
  800. sourcing_lnum++;
  801. continue;
  802.     }
  803.     buf[len - 1] = NUL; /* remove the NL */
  804. }
  805. /*
  806.  * Check for ^C here now and then, so recursive :so can be broken.
  807.  */
  808. line_breakcheck();
  809. break;
  810.     }
  811.     if (have_read)
  812. return (char_u *)ga.ga_data;
  813.     vim_free(ga.ga_data);
  814.     return NULL;
  815. }
  816. /*
  817.  * Function given to ExpandGeneric() to obtain the list of command names.
  818.  */
  819.     char_u *
  820. get_command_name(idx)
  821.     int idx;
  822. {
  823. #ifdef USER_COMMANDS
  824.     if (idx >= (int)CMD_SIZE)
  825.     {
  826. int i = idx - (int)CMD_SIZE;
  827. if (i >= ucmds.ga_len)
  828.     return NULL;
  829. return USER_CMD(i)->uc_name;
  830.     }
  831. #else
  832.     if (idx >= (int)CMD_SIZE)
  833. return NULL;
  834. #endif
  835.     return cmdnames[idx].cmd_name;
  836. }
  837. /*
  838.  * Call this function if we thought we were going to exit, but we won't
  839.  * (because of an error).  May need to restore the terminal mode.
  840.  */
  841.     void
  842. not_exiting()
  843. {
  844.     exiting = FALSE;
  845.     settmode(TMODE_RAW);
  846. }
  847. /*
  848.  * ":quit": quit current window, quit Vim if closed the last window.
  849.  */
  850.     static void
  851. do_quit(eap)
  852.     EXARG *eap;
  853. {
  854.     /*
  855.      * If there are more files or windows we won't exit.
  856.      */
  857.     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
  858. exiting = TRUE;
  859.     if ((!p_hid && check_changed(curbuf, FALSE, FALSE, eap->forceit, FALSE))
  860.     || check_more(TRUE, eap->forceit) == FAIL
  861.     || (only_one_window() && check_changed_any(eap->forceit)))
  862.     {
  863. not_exiting();
  864.     }
  865.     else
  866.     {
  867. if (only_one_window())     /* quit last window */
  868.     getout(0);
  869. #ifdef USE_GUI
  870. need_mouse_correct = TRUE;
  871. #endif
  872. close_window(curwin, !p_hid || eap->forceit); /* may free buffer */
  873.     }
  874. }
  875. /*
  876.  * ":qall": try to quit all windows
  877.  */
  878.     static void
  879. do_quit_all(forceit)
  880.     int forceit;
  881. {
  882.     exiting = TRUE;
  883.     if (forceit || !check_changed_any(FALSE))
  884. getout(0);
  885.     not_exiting();
  886. }
  887. /*
  888.  * ":close": close current window, unless it is the last one
  889.  */
  890.     static void
  891. do_close(eap)
  892.     EXARG *eap;
  893. {
  894.     int     need_hide;
  895.     need_hide = (buf_changed(curbuf) && curbuf->b_nwindows <= 1);
  896.     if (need_hide && !p_hid && !eap->forceit)
  897.     {
  898. #if defined(GUI_DIALOG) || defined(CON_DIALOG)
  899. if (p_confirm || confirm)
  900. {
  901.     dialog_changed(curbuf, FALSE);
  902.     if (buf_changed(curbuf))
  903. return;
  904. }
  905. else
  906. #endif
  907. {
  908.     emsg(e_nowrtmsg);
  909.     return;
  910. }
  911.     }
  912. #ifdef USE_GUI
  913.     need_mouse_correct = TRUE;
  914. #endif
  915.     close_window(curwin, !need_hide);     /* may free buffer */
  916. }
  917. /*
  918.  * ":stop" and ":suspend": Suspend Vim.
  919.  */
  920.     static void
  921. do_suspend(forceit)
  922.     int forceit;
  923. {
  924.     /*
  925.      * Disallow suspending for "rvim".
  926.      */
  927.     if (!check_restricted()
  928. #ifdef WIN32
  929. /*
  930.  * Check if external commands are allowed now.
  931.  */
  932. && can_end_termcap_mode(TRUE)
  933. #endif
  934. )
  935.     {
  936. if (!forceit)
  937.     autowrite_all();
  938. windgoto((int)Rows - 1, 0);
  939. out_char('n');
  940. out_flush();
  941. stoptermcap();
  942. mch_restore_title(3); /* restore window titles */
  943. ui_suspend(); /* call machine specific function */
  944. maketitle();
  945. starttermcap();
  946. scroll_start(); /* scroll screen before redrawing */
  947. must_redraw = CLEAR;
  948. set_winsize(0, 0, FALSE); /* May have resized window */
  949.     }
  950. }
  951. /*
  952.  * ":exit", ":xit" and ":wq": Write file and exit Vim.
  953.  */
  954.     static void
  955. do_exit(eap)
  956.     EXARG *eap;
  957. {
  958.     /*
  959.      * if more files or windows we won't exit
  960.      */
  961.     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
  962. exiting = TRUE;
  963.     if (       ((eap->cmdidx == CMD_wq
  964.     || curbuf_changed())
  965. && do_write(eap) == FAIL)
  966.     || check_more(TRUE, eap->forceit) == FAIL
  967.     || (only_one_window() && check_changed_any(eap->forceit)))
  968.     {
  969. not_exiting();
  970.     }
  971.     else
  972.     {
  973. if (only_one_window())     /* quit last window, exit Vim */
  974.     getout(0);
  975. #ifdef USE_GUI
  976. need_mouse_correct = TRUE;
  977. #endif
  978. close_window(curwin, !p_hid); /* quit current window, may free buffer */
  979.     }
  980. }
  981. /*
  982.  * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
  983.  */
  984.     static void
  985. do_wqall(eap)
  986.     EXARG *eap;
  987. {
  988.     BUF     *buf;
  989.     int     error = 0;
  990.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  991.     {
  992. if (buf_changed(buf))
  993. {
  994.     if (buf->b_ffname == NULL)
  995.     {
  996. emsg(e_noname);
  997. ++error;
  998.     }
  999.     else if (!eap->forceit && buf->b_p_ro)
  1000.     {
  1001. EMSG2(""%s" is readonly, use ! to write anyway",
  1002. buf->b_fname);
  1003. ++error;
  1004.     }
  1005.     else
  1006.     {
  1007. if (buf_write_all(buf) == FAIL)
  1008.     ++error;
  1009. #ifdef AUTOCMD
  1010. /* an autocommand may have deleted the buffer */
  1011. if (!buf_valid(buf))
  1012.     buf = firstbuf;
  1013. #endif
  1014.     }
  1015. }
  1016.     }
  1017.     if (exiting)
  1018.     {
  1019. if (!error)
  1020.     getout(0); /* exit Vim */
  1021. not_exiting();
  1022.     }
  1023. }
  1024.     static void
  1025. do_print(eap)
  1026.     EXARG *eap;
  1027. {
  1028.     for ( ;!got_int; ui_breakcheck())
  1029.     {
  1030. print_line(eap->line1,
  1031.    (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound));
  1032. if (++eap->line1 > eap->line2)
  1033.     break;
  1034. out_flush();     /* show one line at a time */
  1035.     }
  1036.     setpcmark();
  1037.     /* put cursor at last line */
  1038.     curwin->w_cursor.lnum = eap->line2;
  1039.     beginline(BL_SOL | BL_FIX);
  1040.     ex_no_reprint = TRUE;
  1041. }
  1042. /*
  1043.  * Edit file "argn" from the arguments.
  1044.  */
  1045.     static void
  1046. do_argfile(eap, argn)
  1047.     EXARG   *eap;
  1048.     int     argn;
  1049. {
  1050.     int other;
  1051.     char_u *p;
  1052.     char_u *ffname;
  1053.     BUF *buf;
  1054.     if (argn < 0 || argn >= arg_file_count)
  1055.     {
  1056. if (arg_file_count <= 1)
  1057.     EMSG("There is only one file to edit");
  1058. else if (argn < 0)
  1059.     EMSG("Cannot go before first file");
  1060. else
  1061.     EMSG("Cannot go beyond last file");
  1062.     }
  1063.     else
  1064.     {
  1065. setpcmark();
  1066. #ifdef USE_GUI
  1067. need_mouse_correct = TRUE;
  1068. #endif
  1069. if (*eap->cmd == 's')     /* split window first */
  1070. {
  1071.     if (win_split(0, FALSE, FALSE) == FAIL)
  1072. return;
  1073. }
  1074. else
  1075. {
  1076.     /*
  1077.      * if 'hidden' set, only check for changed file when re-editing
  1078.      * the same buffer
  1079.      */
  1080.     other = TRUE;
  1081.     if (p_hid)
  1082.     {
  1083. p = fix_fname(arg_files[argn]);
  1084. other = otherfile(p);
  1085. vim_free(p);
  1086.     }
  1087.     if ((!p_hid || !other)
  1088.   && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
  1089. return;
  1090. }
  1091. curwin->w_arg_idx = argn;
  1092. if (argn == arg_file_count - 1)
  1093.     arg_had_last = TRUE;
  1094. /*
  1095.  * If no line number given, use the last known line number.
  1096.  */
  1097. if (eap->do_ecmd_lnum == 0)
  1098. {
  1099.     ffname = fix_fname(arg_files[curwin->w_arg_idx]);
  1100.     if (ffname != NULL)
  1101.     {
  1102. buf = buflist_findname(ffname);
  1103. if (buf != NULL)
  1104.     eap->do_ecmd_lnum = buflist_findlnum(buf);
  1105. vim_free(ffname);
  1106.     }
  1107. }
  1108. (void)do_ecmd(0, arg_files[curwin->w_arg_idx],
  1109.       NULL, eap->do_ecmd_cmd, eap->do_ecmd_lnum,
  1110.       (p_hid ? ECMD_HIDE : 0) +
  1111.    (eap->forceit ? ECMD_FORCEIT : 0));
  1112.     }
  1113. }
  1114. /*
  1115.  * Do ":next" command, and commands that behave like it.
  1116.  */
  1117.     static void
  1118. do_next(eap)
  1119.     EXARG *eap;
  1120. {
  1121.     int     i;
  1122.     /*
  1123.      * check for changed buffer now, if this fails the argument list is not
  1124.      * redefined.
  1125.      */
  1126.     if (       p_hid
  1127.     || eap->cmdidx == CMD_snext
  1128.     || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
  1129.     {
  1130. if (*eap->arg != NUL)     /* redefine file list */
  1131. {
  1132.     if (do_arglist(eap->arg) == FAIL)
  1133. return;
  1134.     i = 0;
  1135. }
  1136. else
  1137.     i = curwin->w_arg_idx + (int)eap->line2;
  1138. do_argfile(eap, i);
  1139.     }
  1140. }
  1141. #if defined(USE_GUI_WIN32) || defined(USE_GUI_BEOS) || defined(PROTO) || defined(macintosh)
  1142. /*
  1143.  * Handle a file drop. The code is here because a drop is *nearly* like an
  1144.  * :args command, but not quite (we have a list of exact filenames, so we
  1145.  * don't want to (a) parse a command line, or (b) expand wildcards. So the
  1146.  * code is very similar to :args and hence needs access to a lot of the static
  1147.  * functions in this file.
  1148.  *
  1149.  * Arguments:
  1150.  * FILEC => the number of files dropped
  1151.  * FILEV => the list of files dropped
  1152.  *
  1153.  * The list should be allocated using vim_alloc(), as should each item in the
  1154.  * list. This function takes over responsibility for freeing the list.
  1155.  *
  1156.  * XXX The list is made into the arg_files list. This is freed using
  1157.  * FreeWild(), which does a series of vim_free() calls, unless the two defines
  1158.  * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a
  1159.  * routine _fnexplodefree() is used. This may cause problems, but as the drop
  1160.  * file functionality is (currently) Win32-specific (where these defines are
  1161.  * not set), this is not presently a problem.
  1162.  */
  1163. void
  1164. handle_drop(filec, filev)
  1165.     int filec;
  1166.     char_u **filev;
  1167. {
  1168.     EXARG ea;
  1169.     int i;
  1170.     int split = FALSE;
  1171.     /* Check whether the current buffer is changed. If so, we will need
  1172.      * to split the current window or data could be lost.
  1173.      * We don't need to check if the 'hidden' option is set, as in this
  1174.      * case the buffer won't be lost.
  1175.      */
  1176.     if (!p_hid)
  1177.     {
  1178. int old_emsg = emsg_off;
  1179. emsg_off = TRUE;
  1180. split = check_changed(curbuf, TRUE, FALSE, FALSE, FALSE);
  1181. emsg_off = old_emsg;
  1182.     }
  1183.     /*
  1184.      * Set up the new argument list.
  1185.      * This code is copied from the tail end of do_arglist()
  1186.      */
  1187.     FreeWild(arg_file_count, arg_files);
  1188.     arg_file_count = filec;
  1189.     arg_files = filev;
  1190.     arg_had_last = FALSE;
  1191.     for (i = 0; i < arg_file_count; ++i)
  1192. if (arg_files[i] != NULL)
  1193.     (void)buflist_add(arg_files[i]);
  1194.     /*
  1195.      * Move to the first file.
  1196.      */
  1197.     /* Fake up a minimal "[s]next" command for do_argfile() */
  1198.     ea.cmd = (char_u *)(split ? "snext" : "next");
  1199.     ea.forceit = FALSE;
  1200.     ea.do_ecmd_cmd = NULL;
  1201.     ea.do_ecmd_lnum = 0;
  1202.     do_argfile(&ea, 0);
  1203. }
  1204. #endif
  1205. /*
  1206.  * Handle ":recover" command.
  1207.  */
  1208.     static void
  1209. do_recover(eap)
  1210.     EXARG *eap;
  1211. {
  1212.     recoverymode = TRUE;
  1213.     if (!check_changed(curbuf, FALSE, TRUE, eap->forceit, FALSE)
  1214. && (*eap->arg == NUL || setfname(eap->arg, NULL, TRUE) == OK))
  1215. ml_recover();
  1216.     recoverymode = FALSE;
  1217. }
  1218. /*
  1219.  * Handle ":args" command.
  1220.  */
  1221.     static void
  1222. do_args(eap)
  1223.     EXARG *eap;
  1224. {
  1225.     int     i;
  1226.     /* ":args file": handle like :next */
  1227.     if (!ends_excmd(*eap->arg))
  1228. do_next(eap);
  1229.     else
  1230.     {
  1231. if (arg_file_count == 0)     /* no file name list */
  1232. {
  1233.     if (check_fname() == OK)     /* check for no file name */
  1234. smsg((char_u *)"[%s]", curbuf->b_ffname);
  1235. }
  1236. else
  1237. {
  1238.     /*
  1239.      * Overwrite the command, in most cases there is no scrolling
  1240.      * required and no wait_return().
  1241.      */
  1242.     gotocmdline(TRUE);
  1243.     for (i = 0; i < arg_file_count; ++i)
  1244.     {
  1245. if (i == curwin->w_arg_idx)
  1246.     msg_putchar('[');
  1247. msg_outtrans(arg_files[i]);
  1248. if (i == curwin->w_arg_idx)
  1249.     msg_putchar(']');
  1250. msg_putchar(' ');
  1251.     }
  1252. }
  1253.     }
  1254. }
  1255. /*
  1256.  * Handle ":wnext", ":wNext" and ":wprevious" commands.
  1257.  */
  1258.     static void
  1259. do_wnext(eap)
  1260.     EXARG *eap;
  1261. {
  1262.     int i;
  1263.     if (eap->cmd[1] == 'n')
  1264. i = curwin->w_arg_idx + (int)eap->line2;
  1265.     else
  1266. i = curwin->w_arg_idx - (int)eap->line2;
  1267.     eap->line1 = 1;
  1268.     eap->line2 = curbuf->b_ml.ml_line_count;
  1269.     if (do_write(eap) != FAIL)
  1270. do_argfile(eap, i);
  1271. }
  1272. /*
  1273.  * :sview [+command] file   split window with new file, read-only
  1274.  * :split [[+command] file] split window with current or new file
  1275.  * :new [[+command] file]   split window with no or new file
  1276.  */
  1277.     static void
  1278. do_splitview(eap)
  1279.     EXARG *eap;
  1280. {
  1281.     WIN *old_curwin;
  1282. #ifdef USE_BROWSE
  1283.     char_u *browseFile = NULL;
  1284. #endif
  1285.     old_curwin = curwin;
  1286. #ifdef USE_GUI
  1287.     need_mouse_correct = TRUE;
  1288. #endif
  1289. #ifdef USE_BROWSE
  1290.     if (browse && eap->cmdidx != CMD_new)
  1291.     {
  1292. browseFile = do_browse(FALSE, (char_u *)"Edit File in new window",
  1293.   NULL, NULL, eap->arg, NULL, curbuf);
  1294. if (browseFile == NULL)
  1295.     goto theend;
  1296. eap->arg = browseFile;
  1297.     }
  1298. #endif
  1299.     if (win_split(eap->addr_count ? (int)eap->line2 : 0, FALSE, FALSE) != FAIL)
  1300. do_exedit(eap, old_curwin);
  1301. #ifdef USE_BROWSE
  1302. theend:
  1303.     vim_free(browseFile);
  1304. #endif
  1305. }
  1306. /*
  1307.  * Handle ":resize" command.
  1308.  * set, increment or decrement current window height
  1309.  */
  1310.     static void
  1311. do_resize(eap)
  1312.     EXARG *eap;
  1313. {
  1314.     int n;
  1315. #ifdef USE_GUI
  1316.     need_mouse_correct = TRUE;
  1317. #endif
  1318.     n = atol((char *)eap->arg);
  1319.     if (*eap->arg == '-' || *eap->arg == '+')
  1320. n += curwin->w_height;
  1321.     else if (n == 0)     /* default is very high */
  1322. n = 9999;
  1323.     win_setheight((int)n);
  1324. }
  1325.     static void
  1326. do_exedit(eap, old_curwin)
  1327.     EXARG *eap;
  1328.     WIN *old_curwin;
  1329. {
  1330.     int     n;
  1331.     /*
  1332.      * ":vi" command ends Ex mode.
  1333.      */
  1334.     if (exmode_active && (eap->cmdidx == CMD_visual || eap->cmdidx == CMD_view))
  1335.     {
  1336. exmode_active = FALSE;
  1337. if (*eap->arg == NUL)
  1338.     return;
  1339.     }
  1340.     if ((eap->cmdidx == CMD_new) && *eap->arg == NUL)
  1341.     {
  1342. setpcmark();
  1343. (void)do_ecmd(0, NULL, NULL, eap->do_ecmd_cmd, (linenr_t)1,
  1344.        ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0));
  1345.     }
  1346.     else if (eap->cmdidx != CMD_split || *eap->arg != NUL
  1347. #ifdef USE_BROWSE
  1348.     || browse
  1349. #endif
  1350.     )
  1351.     {
  1352. n = readonlymode;
  1353. if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
  1354.     readonlymode = TRUE;
  1355. setpcmark();
  1356. (void)do_ecmd(0, eap->arg, NULL, eap->do_ecmd_cmd, eap->do_ecmd_lnum,
  1357.       (p_hid ? ECMD_HIDE : 0) +
  1358.       (eap->forceit ? ECMD_FORCEIT : 0) +
  1359.       (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 ));
  1360. readonlymode = n;
  1361.     }
  1362.     else
  1363.     {
  1364. if (eap->do_ecmd_cmd != NULL)
  1365.     do_cmdline(eap->do_ecmd_cmd, NULL, NULL, DOCMD_VERBOSE);
  1366. update_screen(NOT_VALID);
  1367.     }
  1368.     /*
  1369.      * if ":split file" worked, set alternate file name in old window to new
  1370.      * file
  1371.      */
  1372.     if (       (eap->cmdidx == CMD_new
  1373. || eap->cmdidx == CMD_split)
  1374.     && *eap->arg != NUL
  1375.     && curwin != old_curwin
  1376.     && win_valid(old_curwin)
  1377.     && old_curwin->w_buffer != curbuf)
  1378. old_curwin->w_alt_fnum = curbuf->b_fnum;
  1379.     ex_no_reprint = TRUE;
  1380. }
  1381. #ifdef USE_GUI
  1382. /*
  1383.  * Handle ":gui" or ":gvim" command.
  1384.  */
  1385.     static void
  1386. do_gui(eap)
  1387.     EXARG *eap;
  1388. {
  1389.     /*
  1390.      * Check for "-f" argument: foreground, don't fork.
  1391.      */
  1392.     if (eap->arg[0] == '-' && eap->arg[1] == 'f' &&
  1393.      (eap->arg[2] == NUL || vim_iswhite(eap->arg[2])))
  1394.     {
  1395. gui.dofork = FALSE;
  1396. eap->arg = skipwhite(eap->arg + 2);
  1397.     }
  1398.     else
  1399. gui.dofork = TRUE;
  1400.     if (!gui.in_use)
  1401.     {
  1402. /* Clear the command.  Needed for when forking+exiting, to avoid part
  1403.  * of the argument ending up after the shell prompt. */
  1404. msg_clr_eos();
  1405. gui_start();
  1406.     }
  1407.     if (!ends_excmd(*eap->arg))
  1408. do_next(eap);
  1409. }
  1410. #endif
  1411.     static void
  1412. do_swapname()
  1413. {
  1414.     if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL)
  1415. MSG("No swap file");
  1416.     else
  1417. msg(curbuf->b_ml.ml_mfp->mf_fname);
  1418. }
  1419.     static void
  1420. do_read(eap)
  1421.     EXARG *eap;
  1422. {
  1423.     int     i;
  1424.     if (eap->usefilter) /* :r!cmd */
  1425. do_bang(1, eap->line1, eap->line2, FALSE, eap->arg, FALSE, TRUE);
  1426.     else
  1427.     {
  1428. if (u_save(eap->line2, (linenr_t)(eap->line2 + 1)) == FAIL)
  1429.     return;
  1430. #ifdef USE_BROWSE
  1431. if (browse)
  1432. {
  1433.     char_u *browseFile;
  1434.     browseFile = do_browse(FALSE, (char_u *)"Append File", NULL,
  1435. NULL, eap->arg, NULL, curbuf);
  1436.     if (browseFile != NULL)
  1437.     {
  1438. i = readfile(browseFile, NULL,
  1439.        eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
  1440. vim_free(browseFile);
  1441.     }
  1442.     else
  1443. i = OK;
  1444. }
  1445. else
  1446. #endif
  1447.      if (*eap->arg == NUL)
  1448. {
  1449.     if (check_fname() == FAIL) /* check for no file name */
  1450. return;
  1451.     i = readfile(curbuf->b_ffname, curbuf->b_fname,
  1452.        eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
  1453. }
  1454. else
  1455. {
  1456.     if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL)
  1457. setaltfname(eap->arg, eap->arg, (linenr_t)1);
  1458.     i = readfile(eap->arg, NULL,
  1459.        eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
  1460. }
  1461. if (i == FAIL)
  1462.     emsg2(e_notopen, eap->arg);
  1463. else
  1464.     update_screen(NOT_VALID);
  1465.     }
  1466. }
  1467.     static void
  1468. do_cd(eap)
  1469.     EXARG *eap;
  1470. {
  1471. #ifdef UNIX
  1472.     /*
  1473.      * for UNIX ":cd" means: go to home directory
  1474.      */
  1475.     if (*eap->arg == NUL)    /* use NameBuff for home directory name */
  1476.     {
  1477. expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
  1478. eap->arg = NameBuff;
  1479.     }
  1480. #endif
  1481.     if (*eap->arg == NUL)
  1482. do_pwd();
  1483.     else
  1484.     {
  1485. if (mch_chdir((char *)eap->arg))
  1486.     emsg(e_failed);
  1487. else
  1488.     shorten_fnames();
  1489.     }
  1490. }
  1491.     static void
  1492. do_pwd()
  1493. {
  1494.     if (mch_dirname(NameBuff, MAXPATHL) == OK)
  1495. msg(NameBuff);
  1496.     else
  1497. emsg(e_unknown);
  1498. }
  1499.     static void
  1500. do_sleep(eap)
  1501.     EXARG *eap;
  1502. {
  1503.     int     n;
  1504.     if (cursor_valid())
  1505.     {
  1506. n = curwin->w_winpos + curwin->w_wrow - msg_scrolled;
  1507. if (n >= 0)
  1508.     windgoto((int)n, curwin->w_wcol);
  1509.     }
  1510.     cursor_on();
  1511.     out_flush();
  1512.     ui_delay(eap->line2 * (*eap->arg == 'm' ? 1L : 1000L), TRUE);
  1513. }
  1514.     static void
  1515. do_exmap(eap, isabbrev)
  1516.     EXARG *eap;
  1517.     int isabbrev;
  1518. {
  1519.     int     mode;
  1520.     char_u  *cmdp;
  1521.     cmdp = eap->cmd;
  1522.     mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
  1523.     switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'),
  1524.     eap->arg, mode, isabbrev))
  1525.     {
  1526. case 1: emsg(e_invarg);
  1527. break;
  1528. case 2: emsg(e_nomap);
  1529. break;
  1530. case 3: emsg(e_ambmap);
  1531. break;
  1532.     }
  1533. }
  1534. /*
  1535.  * ":winsize" command (obsolete).
  1536.  */
  1537.     static void
  1538. do_winsize(arg)
  1539.     char_u *arg;
  1540. {
  1541.     int     w, h;
  1542.     w = getdigits(&arg);
  1543.     arg = skipwhite(arg);
  1544.     h = getdigits(&arg);
  1545.     set_winsize(w, h, TRUE);
  1546. }
  1547. /*
  1548.  * Handle command that work like operators: ":delete", ":yank", ":>" and ":<".
  1549.  */
  1550.     static void
  1551. do_exops(eap)
  1552.     EXARG *eap;
  1553. {
  1554.     OPARG oa;
  1555.     clear_oparg(&oa);
  1556.     oa.regname = eap->regname;
  1557.     oa.start.lnum = eap->line1;
  1558.     oa.end.lnum = eap->line2;
  1559.     oa.line_count = eap->line2 - eap->line1 + 1;
  1560.     oa.motion_type = MLINE;
  1561.     if (eap->cmdidx != CMD_yank) /* position cursor for undo */
  1562.     {
  1563. setpcmark();
  1564. curwin->w_cursor.lnum = eap->line1;
  1565. beginline(BL_SOL | BL_FIX);
  1566.     }
  1567.     switch (eap->cmdidx)
  1568.     {
  1569. case CMD_delete:
  1570.     oa.op_type = OP_DELETE;
  1571.     op_delete(&oa);
  1572.     break;
  1573. case CMD_yank:
  1574.     oa.op_type = OP_YANK;
  1575.     (void)op_yank(&oa, FALSE, TRUE);
  1576.     break;
  1577. default:    /* CMD_rshift or CMD_lshift */
  1578.     if ((eap->cmdidx == CMD_rshift)
  1579. #ifdef RIGHTLEFT
  1580.     ^ curwin->w_p_rl
  1581. #endif
  1582.     )
  1583. oa.op_type = OP_RSHIFT;
  1584.     else
  1585. oa.op_type = OP_LSHIFT;
  1586.     op_shift(&oa, FALSE, eap->amount);
  1587.     break;
  1588.     }
  1589. }
  1590. /*
  1591.  * Handle ":copy" and ":move".
  1592.  */
  1593.     static void
  1594. do_copymove(eap)
  1595.     EXARG *eap;
  1596. {
  1597.     long n;
  1598.     n = get_address(&eap->arg, FALSE);
  1599.     if (eap->arg == NULL)     /* error detected */
  1600.     {
  1601. eap->nextcmd = NULL;
  1602. return;
  1603.     }
  1604.     /*
  1605.      * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
  1606.      */
  1607.     if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
  1608.     {
  1609. emsg(e_invaddr);
  1610. return;
  1611.     }
  1612.     if (eap->cmdidx == CMD_move)
  1613.     {
  1614. if (do_move(eap->line1, eap->line2, n) == FAIL)
  1615.     return;
  1616.     }
  1617.     else
  1618. do_copy(eap->line1, eap->line2, n);
  1619.     u_clearline();
  1620.     beginline(BL_SOL | BL_FIX);
  1621.     update_screen(NOT_VALID);
  1622. }
  1623. /*
  1624.  * Handle ":join" command.
  1625.  */
  1626.     static void
  1627. do_exjoin(eap)
  1628.     EXARG *eap;
  1629. {
  1630.     curwin->w_cursor.lnum = eap->line1;
  1631.     if (eap->line1 == eap->line2)
  1632.     {
  1633. if (eap->addr_count >= 2)   /* :2,2join does nothing */
  1634.     return;
  1635. if (eap->line2 == curbuf->b_ml.ml_line_count)
  1636. {
  1637.     beep_flush();
  1638.     return;
  1639. }
  1640. ++eap->line2;
  1641.     }
  1642.     do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit, FALSE);
  1643.     beginline(BL_WHITE | BL_FIX);
  1644. }
  1645. /*
  1646.  * Handle ":@" or ":*" command, execute from register.
  1647.  */
  1648.     static void
  1649. do_exat(eap)
  1650.     EXARG *eap;
  1651. {
  1652.     int c;
  1653.     curwin->w_cursor.lnum = eap->line2;
  1654. #ifdef USE_GUI_WIN32
  1655.     dont_scroll = TRUE; /* disallow scrolling here */
  1656. #endif
  1657.     /* get the register name.  No name means to use the previous one */
  1658.     c = *eap->arg;
  1659.     if (c == NUL || c == '*')
  1660. c = '@';
  1661.     /* put the register in mapbuf */
  1662.     if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL)
  1663. beep_flush();
  1664.     else
  1665.     {
  1666. /* execute from the mapbuf */
  1667. while (vpeekc() == ':')
  1668. {
  1669.     (void)vgetc();
  1670.     (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
  1671. }
  1672.     }
  1673. }
  1674. /*
  1675.  * Handle ":redir" command, start/stop redirection.
  1676.  */
  1677.     static void
  1678. do_redir(eap)
  1679.     EXARG *eap;
  1680. {
  1681.     char *mode;
  1682. #ifdef USE_BROWSE
  1683.     char_u *browseFile = NULL;
  1684. #endif
  1685.     if (STRICMP(eap->arg, "END") == 0)
  1686. close_redir();
  1687.     else
  1688.     {
  1689. if (*eap->arg == '>')
  1690. {
  1691.     ++eap->arg;
  1692.     if (*eap->arg == '>')
  1693.     {
  1694. ++eap->arg;
  1695. mode = "a";
  1696.     }
  1697.     else
  1698. mode = "w";
  1699.     eap->arg = skipwhite(eap->arg);
  1700.     close_redir();
  1701. #ifdef USE_BROWSE
  1702.     if (browse)
  1703.     {
  1704. browseFile = do_browse(TRUE, (char_u *)"Save Redirection",
  1705.        NULL, NULL, eap->arg, BROWSE_FILTER_ALL_FILES, curbuf);
  1706. if (browseFile == NULL)
  1707.     return; /* operation cancelled */
  1708. eap->arg = browseFile;
  1709. eap->forceit = TRUE; /* since dialog already asked */
  1710.     }
  1711. #endif /* USE_BROWSE */
  1712.     redir_fd = open_exfile(eap, mode);
  1713. #ifdef USE_BROWSE
  1714.     vim_free(browseFile);
  1715. #endif
  1716. }
  1717. /* TODO: redirect to a buffer */
  1718. /* TODO: redirect to an internal variable */
  1719. else
  1720.     EMSG(e_invarg);
  1721.     }
  1722. }
  1723.     static void
  1724. close_redir()
  1725. {
  1726.     if (redir_fd != NULL)
  1727.     {
  1728. fclose(redir_fd);
  1729. redir_fd = NULL;
  1730.     }
  1731. }
  1732. /*
  1733.  * Handle ":mkexrc", ":mkvimrc" and ":mksession" commands.
  1734.  */
  1735.     static void
  1736. do_mkrc(eap, defname)
  1737.     EXARG *eap;
  1738.     char_u *defname; /* default file name */
  1739. {
  1740.     FILE *fd;
  1741.     int failed;
  1742. #ifdef USE_BROWSE
  1743.     char_u *browseFile = NULL;
  1744. #endif
  1745.     if (*eap->arg == NUL)
  1746. eap->arg = defname;
  1747. #ifdef USE_BROWSE
  1748.     if (browse)
  1749.     {
  1750. browseFile = do_browse(TRUE,
  1751. STRCMP(defname, SESSION_FILE) == 0 ? (char_u *)"Save Session"
  1752.    : (char_u *)"Save Setup",
  1753. NULL, (char_u *)"vim", eap->arg, BROWSE_FILTER_MACROS, curbuf);
  1754. if (browseFile == NULL)
  1755.     return; /* operation cancelled */
  1756. eap->arg = browseFile;
  1757. eap->forceit = TRUE; /* since dialog already asked */
  1758.     }
  1759. #endif /* USE_BROWSE */
  1760.     fd = open_exfile(eap, WRITEBIN);
  1761.     if (fd != NULL)
  1762.     {
  1763. /* Write the version command for :mkvimrc and :mksession */
  1764. if (eap->cmdidx == CMD_mkvimrc || eap->cmdidx == CMD_mksession)
  1765. {
  1766.     fprintf(fd, "version 5.0");
  1767.     (void)put_eol(fd);
  1768. }
  1769. /* Write setting 'compatible' first, because it has side effects */
  1770. if (p_cp)
  1771.     fprintf(fd, "set compatible");
  1772. else
  1773.     fprintf(fd, "set nocompatible");
  1774. (void)put_eol(fd);
  1775. if ((eap->cmdidx != CMD_mksession)
  1776. || (vim_strchr(p_sessopt, 'o') != NULL)) /* "options" */
  1777.     failed = (makemap(fd) == FAIL || makeset(fd) == FAIL);
  1778. else
  1779.     failed = FALSE;
  1780. if (eap->cmdidx == CMD_mksession && !failed)
  1781. {
  1782.     /* save current dir*/
  1783.     char_u dirnow[MAXPATHL];
  1784.     if (mch_dirname(dirnow, MAXPATHL) == FAIL)
  1785. *dirnow = NUL;
  1786.     /*
  1787.      * Change to session file's dir.
  1788.      */
  1789.     (void)vim_chdirfile(eap->arg);
  1790.     shorten_fnames();
  1791.     failed |= (makeopens(fd) == FAIL);
  1792.     /* restore original dir */
  1793.     if (*dirnow)
  1794.     {
  1795. (void)mch_chdir((char *)dirnow);
  1796. shorten_fnames();
  1797.     }
  1798. }
  1799. failed |= fclose(fd);
  1800. if (failed)
  1801.     emsg(e_write);
  1802. #ifdef WANT_EVAL
  1803. else if (eap->cmdidx == CMD_mksession)
  1804. {
  1805.     /* successful session write - set this_session var */
  1806.     char_u tbuf[MAXPATHL];
  1807.     if (mch_FullName(eap->arg, tbuf, MAXPATHL, FALSE) == OK)
  1808. set_internal_string_var((char_u *)"this_session", tbuf);
  1809. }
  1810. #endif
  1811.     }
  1812. #ifdef USE_BROWSE
  1813.     vim_free(browseFile);
  1814. #endif
  1815. }
  1816. /*
  1817.  * Open a file for writing for an Ex command, with some checks.
  1818.  * Return file descriptor, or NULL on failure.
  1819.  */
  1820.     static FILE *
  1821. open_exfile(eap, mode)
  1822.     EXARG *eap;
  1823.     char *mode;     /* "w" for create new file or "a" for append */
  1824. {
  1825.     FILE *fd;
  1826. #ifdef UNIX
  1827.     /* with Unix it is possible to open a directory */
  1828.     if (mch_isdir(eap->arg))
  1829.     {
  1830. EMSG2(""%s" is a directory", eap->arg);
  1831. return NULL;
  1832.     }
  1833. #endif
  1834.     if (!eap->forceit && *mode != 'a' && vim_fexists(eap->arg))
  1835.     {
  1836. EMSG2(""%s" exists (use ! to override)", eap->arg);
  1837. return NULL;
  1838.     }
  1839.     if ((fd = fopen((char *)eap->arg, mode)) == NULL)
  1840. EMSG2("Cannot open "%s" for writing", eap->arg);
  1841.     return fd;
  1842. }
  1843. /*
  1844.  * Handle ":mark" or ":k" command.
  1845.  */
  1846.     static void
  1847. do_setmark(eap)
  1848.     EXARG *eap;
  1849. {
  1850.     FPOS pos;
  1851.     pos = curwin->w_cursor;     /* save curwin->w_cursor */
  1852.     curwin->w_cursor.lnum = eap->line2;
  1853.     beginline(BL_WHITE | BL_FIX);
  1854.     (void)setmark(*eap->arg);     /* set mark */
  1855.     curwin->w_cursor = pos;     /* restore curwin->w_cursor */
  1856. }
  1857. #ifdef EX_EXTRA
  1858. /*
  1859.  * Handle ":normal[!] {commands}" - execute normal mode commands
  1860.  * Often used for ":autocmd".
  1861.  */
  1862.     static void
  1863. do_normal(eap)
  1864.     EXARG *eap;
  1865. {
  1866.     OPARG oa;
  1867.     int len;
  1868.     int save_msg_scroll = msg_scroll;
  1869.     int save_restart_edit = restart_edit;
  1870.     int save_msg_didout = msg_didout;
  1871.     static int depth = 0;
  1872.     if (depth >= p_mmd)
  1873.     {
  1874. EMSG("Recursive use of :normal too deep");
  1875. return;
  1876.     }
  1877.     ++depth;
  1878.     msg_scroll = FALSE;     /* no msg scrolling in Normal mode */
  1879.     restart_edit = 0;     /* don't go to Insert mode */
  1880.     /*
  1881.      * Repeat the :normal command for each line in the range.  When no range
  1882.      * given, execute it just once, without positioning the cursor first.
  1883.      */
  1884.     do
  1885.     {
  1886. clear_oparg(&oa);
  1887. if (eap->addr_count != 0)
  1888. {
  1889.     curwin->w_cursor.lnum = eap->line1++;
  1890.     curwin->w_cursor.col = 0;
  1891. }
  1892. /*
  1893.  * Stuff the argument into the typeahead buffer.
  1894.  * Execute normal_cmd() until there is no more
  1895.  * typeahead than there was before this command.
  1896.  */
  1897. len = typelen;
  1898. ins_typebuf(eap->arg, eap->forceit ? -1 : 0, 0, TRUE);
  1899. while (    (!stuff_empty()
  1900. || (!typebuf_typed()
  1901.     && typelen > len))
  1902. && !got_int)
  1903. {
  1904.     adjust_cursor(); /* put cursor on valid line */
  1905.     /* Make sure w_topline and w_leftcol are correct. */
  1906.     update_topline();
  1907.     if (!curwin->w_p_wrap)
  1908. validate_cursor();
  1909.     update_curswant();
  1910.     normal_cmd(&oa, FALSE); /* execute a Normal mode cmd */
  1911. }
  1912.     }
  1913.     while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int);
  1914.     --depth;
  1915.     msg_scroll = save_msg_scroll;
  1916.     restart_edit = save_restart_edit;
  1917.     msg_didout |= save_msg_didout; /* don't reset msg_didout now */
  1918. }
  1919. #endif
  1920. #ifdef FIND_IN_PATH
  1921.     static char_u *
  1922. do_findpat(eap, action)
  1923.     EXARG *eap;
  1924.     int action;
  1925. {
  1926.     int whole = TRUE;
  1927.     long n;
  1928.     char_u *p;
  1929.     char_u *errormsg = NULL;
  1930.     n = 1;
  1931.     if (isdigit(*eap->arg)) /* get count */
  1932.     {
  1933. n = getdigits(&eap->arg);
  1934. eap->arg = skipwhite(eap->arg);
  1935.     }
  1936.     if (*eap->arg == '/')   /* Match regexp, not just whole words */
  1937.     {
  1938. whole = FALSE;
  1939. ++eap->arg;
  1940. p = skip_regexp(eap->arg, '/', p_magic);
  1941. if (*p)
  1942. {
  1943.     *p++ = NUL;
  1944.     p = skipwhite(p);
  1945.     /* Check for trailing illegal characters */
  1946.     if (!ends_excmd(*p))
  1947. errormsg = e_trailing;
  1948.     else
  1949. eap->nextcmd = check_nextcmd(p);
  1950. }
  1951.     }
  1952.     if (!eap->skip)
  1953. find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
  1954.     whole, !eap->forceit,
  1955.     *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
  1956.     n, action, eap->line1, eap->line2);
  1957.     return errormsg;
  1958. }
  1959. #endif
  1960.     static void
  1961. do_ex_tag(eap, dt)
  1962.     EXARG *eap;
  1963.     int dt;
  1964. {
  1965.     do_tag((char_u *)"", dt, eap->addr_count ? (int)eap->line2
  1966.      : 1, eap->forceit, TRUE);
  1967. }
  1968. #ifdef WANT_EVAL
  1969.     static char_u *
  1970. do_if(eap, cstack)
  1971.     EXARG *eap;
  1972.     struct condstack *cstack;
  1973. {
  1974.     char_u *errormsg = NULL;
  1975.     int error;
  1976.     int skip;
  1977.     int result;
  1978.     if (cstack->cs_idx == CSTACK_LEN - 1)
  1979. errormsg = (char_u *)":if nesting too deep";
  1980.     else
  1981.     {
  1982. ++cstack->cs_idx;
  1983. cstack->cs_flags[cstack->cs_idx] = 0;
  1984. /*
  1985.  * Don't do something when there is a surrounding conditional and it
  1986.  * was not active.
  1987.  */
  1988. skip = (cstack->cs_idx > 0
  1989. && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
  1990. if (skip)
  1991.     ++emsg_off;
  1992. result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
  1993. if (skip)
  1994.     --emsg_off;
  1995. if (!skip)
  1996. {
  1997.     if (result)
  1998. cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
  1999.     if (error)
  2000. --cstack->cs_idx;
  2001. }
  2002.     }
  2003.     return errormsg;
  2004. }
  2005. /*
  2006.  * Handle ":else" and ":elseif" commands.
  2007.  */
  2008.     static char_u *
  2009. do_else(eap, cstack)
  2010.     EXARG *eap;
  2011.     struct condstack *cstack;
  2012. {
  2013.     char_u *errormsg = NULL;
  2014.     int error;
  2015.     int skip;
  2016.     int result;
  2017.     if (cstack->cs_idx < 0 || (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  2018.     {
  2019. if (eap->cmdidx == CMD_else)
  2020.     errormsg = (char_u *)":else without :if";
  2021. else
  2022.     errormsg = (char_u *)":elseif without :if";
  2023.     }
  2024.     else
  2025.     {
  2026. /*
  2027.  * Don't do something when there is a surrounding conditional and it
  2028.  * was not active.
  2029.  */
  2030. skip = (cstack->cs_idx > 0
  2031. && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
  2032. if (!skip)
  2033. {
  2034.     /* if the ":if" was TRUE, reset active, otherwise set it */
  2035.     if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE)
  2036. cstack->cs_flags[cstack->cs_idx] = CSF_TRUE;
  2037.     else
  2038. cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE;
  2039. }
  2040. if (eap->cmdidx == CMD_elseif)
  2041. {
  2042.     if (skip)
  2043. ++emsg_off;
  2044.     result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
  2045.     if (skip)
  2046. --emsg_off;
  2047.     if (!skip && (cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE))
  2048.     {
  2049. if (result)
  2050.     cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
  2051. else
  2052.     cstack->cs_flags[cstack->cs_idx] = 0;
  2053. if (error)
  2054.     --cstack->cs_idx;
  2055.     }
  2056. }
  2057.     }
  2058.     return errormsg;
  2059. }
  2060. /*
  2061.  * Handle ":while".
  2062.  */
  2063.     static char_u *
  2064. do_while(eap, cstack)
  2065.     EXARG *eap;
  2066.     struct condstack *cstack;
  2067. {
  2068.     char_u *errormsg = NULL;
  2069.     int error;
  2070.     int skip;
  2071.     int result;
  2072.     if (cstack->cs_idx == CSTACK_LEN - 1)
  2073. errormsg = (char_u *)":while nesting too deep";
  2074.     else
  2075.     {
  2076. /*
  2077.  * cs_had_while is set when we have jumped back from the matching
  2078.  * ":endwhile".  When not set, need to init this cstack entry.
  2079.  */
  2080. if (!cstack->cs_had_while)
  2081. {
  2082.     ++cstack->cs_idx;
  2083.     ++cstack->cs_whilelevel;
  2084. }
  2085. cstack->cs_flags[cstack->cs_idx] = CSF_WHILE;
  2086. /*
  2087.  * Don't do something when there is a surrounding conditional and it
  2088.  * was not active.
  2089.  */
  2090. skip = (cstack->cs_idx > 0
  2091. && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
  2092. if (skip)
  2093.     ++emsg_off;
  2094. result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
  2095. if (skip)
  2096.     --emsg_off;
  2097. if (!skip)
  2098. {
  2099.     if (result)
  2100. cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE;
  2101.     if (error)
  2102. --cstack->cs_idx;
  2103.     else
  2104. /*
  2105.  * Set cs_had_while flag, so do_cmdline() will set the line
  2106.  * number in cs_line[].
  2107.  */
  2108. cstack->cs_had_while = TRUE;
  2109. }
  2110.     }
  2111.     return errormsg;
  2112. }
  2113. /*
  2114.  * Handle ":continue".
  2115.  */
  2116.     static char_u *
  2117. do_continue(cstack)
  2118.     struct condstack *cstack;
  2119. {
  2120.     char_u *errormsg = NULL;
  2121.     if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
  2122. errormsg = (char_u *)":continue without :while";
  2123.     else
  2124.     {
  2125. /* Find the matching ":while". */
  2126. while (cstack->cs_idx > 0
  2127.     && !(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  2128.     --cstack->cs_idx;
  2129. /*
  2130.  * Set cs_had_continue, so do_cmdline() will jump back to the matching
  2131.  * ":while".
  2132.  */
  2133. cstack->cs_had_continue = TRUE;     /* let do_cmdline() handle it */
  2134.     }
  2135.     return errormsg;
  2136. }
  2137. /*
  2138.  * Handle ":break".
  2139.  */
  2140.     static char_u *
  2141. do_break(cstack)
  2142.     struct condstack *cstack;
  2143. {
  2144.     char_u *errormsg = NULL;
  2145.     int idx;
  2146.     if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
  2147. errormsg = (char_u *)":break without :while";
  2148.     else
  2149.     {
  2150. /* Find the matching ":while". */
  2151. for (idx = cstack->cs_idx; idx >= 0; --idx)
  2152. {
  2153.     cstack->cs_flags[idx] &= ~CSF_ACTIVE;
  2154.     if (cstack->cs_flags[idx] & CSF_WHILE)
  2155. break;
  2156. }
  2157.     }
  2158.     return errormsg;
  2159. }
  2160. /*
  2161.  * Handle ":endwhile".
  2162.  */
  2163.     static char_u *
  2164. do_endwhile(cstack)
  2165.     struct condstack *cstack;
  2166. {
  2167.     char_u *errormsg = NULL;
  2168.     if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
  2169. errormsg = (char_u *)":endwhile without :while";
  2170.     else
  2171.     {
  2172. if (!(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  2173. {
  2174.     errormsg = (char_u *)":endwhile without :while";
  2175.     while (cstack->cs_idx > 0
  2176.     && !(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  2177. --cstack->cs_idx;
  2178. }
  2179. /*
  2180.  * Set cs_had_endwhile, so do_cmdline() will jump back to the matching
  2181.  * ":while".
  2182.  */
  2183. cstack->cs_had_endwhile = TRUE;
  2184.     }
  2185.     return errormsg;
  2186. }
  2187. /*
  2188.  * Return TRUE if the string "p" looks like a ":while" command.
  2189.  */
  2190.     static int
  2191. has_while_cmd(p)
  2192.     char_u *p;
  2193. {
  2194.     p = skipwhite(p);
  2195.     while (*p == ':')
  2196. ++p;
  2197.     p = skipwhite(p);
  2198.     if (p[0] == 'w' && p[1] == 'h')
  2199. return TRUE;
  2200.     return FALSE;
  2201. }
  2202. #endif /* WANT_EVAL */
  2203. /*
  2204.  * Evaluate cmdline variables.
  2205.  *
  2206.  * change '%'     to curbuf->b_ffname
  2207.  *   '#'     to curwin->w_altfile
  2208.  *   '<cword>' to word under the cursor
  2209.  *   '<cWORD>' to WORD under the cursor
  2210.  *   '<cfile>' to path name under the cursor
  2211.  *   '<sfile>" to sourced file name"
  2212.  *   '<afile>' to file name for autocommand
  2213.  *   '<abuf>'  to buffer number for autocommand
  2214.  *
  2215.  * When an error is detected, "errormsg" is set to a non-NULL pointer (may be
  2216.  * "" for error without a message) and NULL is returned.
  2217.  * Returns an allocated string if a valid match was found.
  2218.  * Returns NULL if no match was found. "usedlen" then still contains the
  2219.  * number of characters to skip.
  2220.  */
  2221.     char_u *
  2222. eval_vars(src, usedlen, lnump, errormsg, srcstart)
  2223.     char_u *src; /* pointer into commandline */
  2224.     int *usedlen; /* characters after src that are used */
  2225.     linenr_t *lnump; /* line number for :e command, or NULL */
  2226.     char_u **errormsg; /* error message, or NULL */
  2227.     char_u *srcstart; /* beginning of valid memory for src */
  2228. {
  2229.     int i;
  2230.     char_u *s;
  2231.     char_u *result;
  2232.     char_u *resultbuf = NULL;
  2233.     int resultlen;
  2234.     BUF *buf;
  2235.     int valid = VALID_HEAD + VALID_PATH;    /* assume valid result */
  2236.     int spec_idx;
  2237.     static char *(spec_str[]) =
  2238. {
  2239.     "%",
  2240. #define SPEC_PERC   0
  2241.     "#",
  2242. #define SPEC_HASH   1
  2243.     "<cword>", /* cursor word */
  2244. #define SPEC_CWORD  2
  2245.     "<cWORD>", /* cursor WORD */
  2246. #define SPEC_CCWORD 3
  2247.     "<cfile>", /* cursor path name */
  2248. #define SPEC_CFILE  4
  2249.     "<sfile>", /* ":so" file name */
  2250. #define SPEC_SFILE  5
  2251. #ifdef AUTOCMD
  2252.     "<afile>", /* autocommand file name */
  2253. # define SPEC_AFILE 6
  2254.     "<abuf>" /* autocommand buffer number */
  2255. # define SPEC_ABUF  7
  2256. #endif
  2257. };
  2258. #define SPEC_COUNT  (sizeof(spec_str) / sizeof(char *))
  2259. #ifdef AUTOCMD
  2260.     char_u abuf_nr[30];
  2261. #endif
  2262.     *errormsg = NULL;
  2263.     /*
  2264.      * Check if there is something to do.
  2265.      */
  2266.     for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx)
  2267.     {
  2268. *usedlen = strlen(spec_str[spec_idx]);
  2269. if (STRNCMP(src, spec_str[spec_idx], *usedlen) == 0)
  2270.     break;
  2271.     }
  2272.     if (spec_idx == SPEC_COUNT)     /* no match */
  2273.     {
  2274. *usedlen = 1;
  2275. return NULL;
  2276.     }
  2277.     /*
  2278.      * Skip when preceded with a backslash "%" and "#".
  2279.      * Note: In "\%" the % is also not recognized!
  2280.      */
  2281.     if ((src > srcstart) && (*(src - 1) == '\'))
  2282.     {
  2283. *usedlen = 0;
  2284. STRCPY(src - 1, src); /* remove backslash */
  2285. return NULL;
  2286.     }
  2287.     /*
  2288.      * word or WORD under cursor
  2289.      */
  2290.     if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD)
  2291.     {
  2292. resultlen = find_ident_under_cursor(&result, spec_idx == SPEC_CWORD ?
  2293.       (FIND_IDENT|FIND_STRING) : FIND_STRING);
  2294. if (resultlen == 0)
  2295. {
  2296.     *errormsg = (char_u *)"";
  2297.     return NULL;
  2298. }
  2299.     }
  2300.     /*
  2301.      * '#': Alternate file name
  2302.      * '%': Current file name
  2303.      *     File name under the cursor
  2304.      *     File name for autocommand
  2305.      * and following modifiers
  2306.      */
  2307.     else
  2308.     {
  2309. switch (spec_idx)
  2310. {
  2311. case SPEC_PERC: /* '%': current file */
  2312. if (curbuf->b_fname == NULL)
  2313. {
  2314.     result = (char_u *)"";
  2315.     valid = 0;     /* Must have ":p:h" to be valid */
  2316. }
  2317. else
  2318. #ifdef RISCOS
  2319.     /* Always use the full path for RISC OS if possible. */
  2320.     result = curbuf->b_ffname;
  2321.     if (result == NULL)
  2322. result = curbuf->b_fname;
  2323. #else
  2324.     result = curbuf->b_fname;
  2325. #endif
  2326. break;
  2327. case SPEC_HASH: /* '#' or "#99": alternate file */
  2328. s = src + 1;
  2329. i = (int)getdigits(&s);
  2330. *usedlen = s - src; /* length of what we expand */
  2331. buf = buflist_findnr(i);
  2332. if (buf == NULL)
  2333. {
  2334.     *errormsg = (char_u *)"No alternate file name to substitute for '#'";
  2335.     return NULL;
  2336. }
  2337. if (lnump != NULL)
  2338.     *lnump = buflist_findlnum(buf);
  2339. if (buf->b_fname == NULL)
  2340. {
  2341.     result = (char_u *)"";
  2342.     valid = 0;     /* Must have ":p:h" to be valid */
  2343. }
  2344. else
  2345.     result = buf->b_fname;
  2346. break;
  2347. #ifdef FILE_IN_PATH
  2348. case SPEC_CFILE: /* file name under cursor */
  2349. result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L);
  2350. if (result == NULL)
  2351. {
  2352.     *errormsg = (char_u *)"";
  2353.     return NULL;
  2354. }
  2355. resultbuf = result;     /* remember allocated string */
  2356. break;
  2357. #endif
  2358. #ifdef AUTOCMD
  2359. case SPEC_AFILE: /* file name for autocommand */
  2360. result = autocmd_fname;
  2361. if (result == NULL)
  2362. {
  2363.     *errormsg = (char_u *)"no autocommand file name to substitute for "<afile>"";
  2364.     return NULL;
  2365. }
  2366. break;
  2367. case SPEC_ABUF: /* buffer number for autocommand */
  2368. if (autocmd_bufnr <= 0)
  2369. {
  2370.     *errormsg = (char_u *)"no autocommand buffer number to substitute for "<abuf>"";
  2371.     return NULL;
  2372. }
  2373. sprintf((char *)abuf_nr, "%d", autocmd_bufnr);
  2374. result = abuf_nr;
  2375. break;
  2376. #endif
  2377. case SPEC_SFILE: /* file name for ":so" command */
  2378. result = sourcing_name;
  2379. if (result == NULL)
  2380. {
  2381.     *errormsg = (char_u *)"no :source file name to substitute for "<sfile>"";
  2382.     return NULL;
  2383. }
  2384. break;
  2385. }
  2386. resultlen = STRLEN(result); /* length of new string */
  2387. if (src[*usedlen] == '<') /* remove the file name extension */
  2388. {
  2389.     ++*usedlen;
  2390. #ifdef RISCOS
  2391.     if ((s = vim_strrchr(result, '/')) != NULL && s >= gettail(result))
  2392. #else
  2393.     if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result))
  2394. #endif
  2395. resultlen = s - result;
  2396. }
  2397. #ifdef WANT_MODIFY_FNAME
  2398. else
  2399. {
  2400.     valid |= modify_fname(src, usedlen, &result, &resultbuf,
  2401.   &resultlen);
  2402.     if (result == NULL)
  2403.     {
  2404. *errormsg = (char_u *)"";
  2405. return NULL;
  2406.     }
  2407. }
  2408. #endif
  2409.     }
  2410.     if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH)
  2411.     {
  2412. if (valid != VALID_HEAD + VALID_PATH)
  2413.     *errormsg = (char_u *)"Empty file name for '%' or '#', only works with ":p:h"";
  2414. else
  2415.     *errormsg = (char_u *)"Evaluates to an empty string";
  2416. result = NULL;
  2417.     }
  2418.     else
  2419. result = vim_strnsave(result, resultlen);
  2420.     vim_free(resultbuf);
  2421.     return result;
  2422. }
  2423. /*
  2424.  * Expand the <sfile> string in "arg".
  2425.  *
  2426.  * Returns an allocated string, or NULL for any error.
  2427.  */
  2428.     char_u *
  2429. expand_sfile(arg)
  2430.     char_u *arg;
  2431. {
  2432.     char_u *errormsg;
  2433.     int len;
  2434.     char_u *result;
  2435.     char_u *newres;
  2436.     char_u *repl;
  2437.     int srclen;
  2438.     char_u *p;
  2439.     linenr_t dummy;
  2440.     result = vim_strsave(arg);
  2441.     if (result == NULL)
  2442. return NULL;
  2443.     for (p = result; *p; )
  2444.     {
  2445. if (STRNCMP(p, "<sfile>", 7))
  2446.     ++p;
  2447. else
  2448. {
  2449.     /* replace "<sfile>" with the sourced file name, and do ":" stuff */
  2450.     repl = eval_vars(p, &srclen, &dummy, &errormsg, result);
  2451.     if (errormsg != NULL)
  2452.     {
  2453. if (*errormsg)
  2454.     emsg(errormsg);
  2455. vim_free(result);
  2456. return NULL;
  2457.     }
  2458.     if (repl == NULL) /* no match (cannot happen) */
  2459.     {
  2460. p += srclen;
  2461. continue;
  2462.     }
  2463.     len = STRLEN(result) - srclen + STRLEN(repl) + 1;
  2464.     newres = alloc(len);
  2465.     if (newres == NULL)
  2466.     {
  2467. vim_free(repl);
  2468. vim_free(result);
  2469. return NULL;
  2470.     }
  2471.     mch_memmove(newres, result, (size_t)(p - result));
  2472.     STRCPY(newres + (p - result), repl);
  2473.     len = STRLEN(newres);
  2474.     STRCAT(newres, p + srclen);
  2475.     vim_free(result);
  2476.     result = newres;
  2477.     p = newres + len; /* continue after the match */
  2478. }
  2479.     }
  2480.     return result;
  2481. }
  2482. /*
  2483.  * Write openfile commands for the current buffers to an .exrc file.
  2484.  * Return FAIL on error, OK otherwise.
  2485.  */
  2486.     static int
  2487. makeopens(fd)
  2488.     FILE *fd;
  2489. {
  2490.     BUF *buf;
  2491.     /*
  2492.      * Begin by setting the this_session variable.
  2493.      */
  2494. #ifdef WANT_EVAL
  2495.     if (fprintf(fd, "let this_session=expand("<sfile>:p")") < 0
  2496.     || put_eol(fd) == FAIL)
  2497. return FAIL;
  2498. #endif
  2499.     /*
  2500.      * Next a command to unload current buffers.
  2501.      */
  2502.     if (fprintf(fd, "1,999bd") < 0 || put_eol(fd) == FAIL)
  2503. return FAIL;
  2504.     /*
  2505.      * Now a :cd command to the current directory
  2506.      */
  2507.     if (fprintf(fd, "execute "cd " . expand("<sfile>:p:h")") < 0
  2508.     || put_eol(fd) == FAIL)
  2509. return FAIL;
  2510.     /*
  2511.      * Now save the current files, current buffer first.
  2512.      */
  2513.     if (fprintf(fd, "let shmsave = &shortmess | set shortmess=aoO") < 0
  2514.     || put_eol(fd) == FAIL)
  2515. return FAIL;
  2516.     if (curbuf->b_fname != NULL)
  2517.     {
  2518. /* current buffer - must load */
  2519. if (fprintf(fd, "e +%ld ", curwin->w_cursor.lnum ) < 0)
  2520.     return FAIL;
  2521. if (fprintf(fd, (curbuf->b_sfname != NULL)
  2522.     ?  (char *)curbuf->b_sfname
  2523.     : (char *)curbuf->b_ffname) < 0
  2524. || put_eol(fd) == FAIL)
  2525.     return FAIL;
  2526.     }
  2527.     /* Now put the other buffers into the buffer list */
  2528.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  2529. if (buf->b_fname != NULL && buf != curbuf)
  2530. {
  2531.     if (fprintf(fd, "badd +%ld ", buf->b_winfpos->wl_fpos.lnum) < 0)
  2532. return FAIL;
  2533.     if (fprintf(fd, (buf->b_sfname != NULL)
  2534. ?  (char *)buf->b_sfname
  2535. : (char *)buf->b_ffname) < 0
  2536.     || put_eol(fd) == FAIL)
  2537. return FAIL;
  2538. }
  2539.     if (vim_strchr(p_sessopt, 'r') != NULL) /* "resize" */
  2540.     {
  2541. /* Note: after the restore we still check it worked!*/
  2542. if (fprintf(fd, "set lines=%ld" , Rows) < 0 || put_eol(fd) == FAIL)
  2543.     return FAIL;
  2544. if (fprintf(fd, "set columns=%ld" , Columns) < 0 || put_eol(fd) == FAIL)
  2545.     return FAIL;
  2546.     }
  2547.     /*
  2548.      * Save current windows and cursor pos
  2549.      */
  2550.     if (vim_strchr(p_sessopt, 'w') != NULL) /* "winsize" */
  2551.     {
  2552. int nr = 0;
  2553. int cnr = 0;
  2554. WIN *wp;
  2555. if (fprintf(fd, "let sbsave = &splitbelow | set splitbelow") < 0
  2556. || put_eol(fd) == FAIL)
  2557.     return FAIL;
  2558. for (wp = firstwin; wp != NULL; wp = wp->w_next)
  2559. {
  2560.     ++nr;
  2561.     if (wp->w_buffer->b_fname == NULL)
  2562.     {
  2563. /* create new, empty window, except for first window */
  2564. if (nr != 1 && fprintf(fd, "new") < 0)
  2565.     return FAIL;
  2566.     }
  2567.     else
  2568.     {
  2569. if (nr == 1)
  2570. {
  2571.     /* First window, i.e. already exists*/
  2572.     if (fprintf(fd, "b ") < 0)
  2573. return FAIL;
  2574. }
  2575. else
  2576. {
  2577.     /* create a new window */
  2578.     if (fprintf(fd, "sb ") < 0)
  2579. return FAIL;
  2580. }
  2581. if (wp->w_buffer->b_sfname)
  2582. {
  2583.     if (fprintf(fd, (char *)wp->w_buffer->b_sfname) < 0)
  2584. return FAIL;
  2585. }
  2586. else if (wp->w_buffer->b_ffname)
  2587. {
  2588.     if (fprintf(fd, (char *)wp->w_buffer->b_ffname) < 0)
  2589. return FAIL;
  2590. }
  2591.     }
  2592.     if (put_eol(fd) == FAIL)
  2593. return FAIL;
  2594.     if (wp->w_buffer->b_fname != NULL
  2595.     && (fprintf(fd, "normal %ldG%d|zz", (long)wp->w_cursor.lnum,
  2596.     wp->w_cursor.col + 1) < 0
  2597.     || put_eol(fd) == FAIL))
  2598. return FAIL;
  2599.     if (curwin == wp)
  2600. cnr = nr;
  2601. }
  2602. if (fprintf(fd, "let &splitbelow = sbsave") <0 || put_eol(fd) == FAIL)
  2603.     return FAIL;
  2604. /*
  2605.  * if more than one window, see if sizes can be restored
  2606.  */
  2607. if (nr > 1)
  2608. {
  2609.     if (fprintf(fd,
  2610. "if (&lines == %ld)" , Rows) < 0 || put_eol(fd) == FAIL)
  2611. return FAIL;
  2612.     if (fprintf(fd, "  normal 27t") < 0 || put_eol(fd) == FAIL)
  2613. return FAIL;
  2614.     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  2615.     {
  2616. if (fprintf(fd, "  resize %ld", (long)wp->w_height) < 0
  2617.     || put_eol(fd) == FAIL)
  2618.     return FAIL;
  2619. if (fprintf(fd, "  normal zz27j") < 0 || put_eol(fd) == FAIL)
  2620.     return FAIL;
  2621.     }
  2622.     if (fprintf(fd, "else") < 0 || put_eol(fd) == FAIL)
  2623. return FAIL;
  2624.     if (fprintf(fd, "  normal 27=") < 0 || put_eol(fd) == FAIL)
  2625. return FAIL;
  2626.     if (fprintf(fd, "endif") < 0 || put_eol(fd) == FAIL)
  2627. return FAIL;
  2628. }
  2629. if (fprintf(fd, "normal %d27w", cnr) < 0 || put_eol(fd) == FAIL)
  2630.     return FAIL;
  2631.     }
  2632.     if (fprintf(fd, "let &shortmess = shmsave") < 0 || put_eol(fd) == FAIL)
  2633. return FAIL;
  2634.     /*
  2635.      * Lastly, execute the x.vim file if it exists.
  2636.      */
  2637.     if (fprintf(fd, "let sessionextra=expand("<sfile>:p:r")."x.vim"") < 0
  2638.     || put_eol(fd) == FAIL)
  2639. return FAIL;
  2640.     if (fprintf(fd, "if file_readable(sessionextra)") < 0
  2641.     || put_eol(fd) == FAIL)
  2642. return FAIL;
  2643.     if (fprintf(fd, "texecute "source " . sessionextra") < 0
  2644.     || put_eol(fd) == FAIL)
  2645. return FAIL;
  2646.     if (fprintf(fd, "endif") < 0 || put_eol(fd) == FAIL)
  2647. return FAIL;
  2648.     return OK;
  2649. }
  2650.     static int
  2651. put_eol(fd)
  2652.     FILE *fd;
  2653. {
  2654.     if
  2655. #ifdef USE_CRNL
  2656. ((putc('r', fd) < 0) ||
  2657. #endif
  2658. (putc('n', fd) < 0)
  2659. #ifdef USE_CRNL
  2660. )
  2661. #endif
  2662. return FAIL;
  2663.     return OK;
  2664. }
  2665.     static void
  2666. cmd_source(fname, forceit)
  2667.     char_u *fname;
  2668.     int forceit;
  2669. {
  2670.     if (forceit) /* :so! read vi commands */
  2671. (void)openscript(fname);
  2672.     /* :so read ex commands */
  2673.     else if (do_source(fname, FALSE, FALSE) == FAIL)
  2674. emsg2(e_notopen, fname);
  2675. }
  2676. #ifdef USER_COMMANDS
  2677.     static int
  2678. uc_add_command(name, name_len, rep, argt, def, compl, force)
  2679.     char_u *name;
  2680.     size_t name_len;
  2681.     char_u *rep;
  2682.     long argt;
  2683.     long def;
  2684.     int compl;
  2685.     int force;
  2686. {
  2687.     UCMD *cmd;
  2688.     char_u *p;
  2689.     int i;
  2690.     int cmp = 1;
  2691.     char_u *rep_buf = NULL;
  2692.     replace_termcodes(rep, &rep_buf, FALSE, FALSE);
  2693.     if (rep_buf == NULL)
  2694.     {
  2695. /* Can't replace termcodes - try using the string as is */
  2696. rep_buf = vim_strsave(rep);
  2697. /* Give up if out of memory */
  2698. if (rep_buf == NULL)
  2699.     return FAIL;
  2700.     }
  2701.     /* Search for the command */
  2702.     cmd = USER_CMD(0);
  2703.     i = 0;
  2704.     while (i < ucmds.ga_len)
  2705.     {
  2706. size_t len = STRLEN(cmd->uc_name);
  2707. cmp = STRNCMP(name, cmd->uc_name, name_len);
  2708. if (cmp == 0)
  2709. {
  2710.     if (name_len < len)
  2711. cmp = -1;
  2712.     else if (name_len > len)
  2713. cmp = 1;
  2714. }
  2715. if (cmp == 0)
  2716. {
  2717.     if (!force)
  2718.     {
  2719. EMSG("Command already exists: use ! to redefine");
  2720. goto fail;
  2721.     }
  2722.     vim_free(cmd->uc_rep);
  2723.     cmd->uc_rep = 0;
  2724.     break;
  2725. }
  2726. /* Stop as soon as we pass the name to add */
  2727. if (cmp < 0)
  2728.     break;
  2729. ++cmd;
  2730. ++i;
  2731.     }
  2732.     /* Extend the array unless we're replacing an existing command */
  2733.     if (cmp != 0)
  2734.     {
  2735. if (ga_grow(&ucmds, 1) != OK)
  2736.     goto fail;
  2737. if ((p = vim_strnsave(name, (int)name_len)) == NULL)
  2738.     goto fail;
  2739. cmd = USER_CMD(i);
  2740. mch_memmove(cmd + 1, cmd, (ucmds.ga_len - i) * sizeof(UCMD));
  2741. ++ucmds.ga_len;
  2742. --ucmds.ga_room;
  2743. cmd->uc_name = p;
  2744.     }
  2745.     cmd->uc_rep = rep_buf;
  2746.     cmd->uc_argt = argt;
  2747.     cmd->uc_def = def;
  2748.     cmd->uc_compl = compl;
  2749.     return OK;
  2750. fail:
  2751.     vim_free(rep_buf);
  2752.     return FAIL;
  2753. }
  2754.     static void
  2755. uc_list(name, name_len)
  2756.     char_u *name;
  2757.     size_t name_len;
  2758. {
  2759.     int i;
  2760.     int found = FALSE;
  2761.     char *s;
  2762.     for (i = 0; i < ucmds.ga_len; ++i)
  2763.     {
  2764. UCMD *cmd = USER_CMD(i);
  2765. int len;
  2766. long a = cmd->uc_argt;
  2767. /* Skip commands which don't match the requested prefix */
  2768. if (STRNCMP(name, cmd->uc_name, name_len) != 0)
  2769.     continue;
  2770. /* Put out the title first time */
  2771. if (!found)
  2772.     MSG_PUTS_TITLE("n   Name        Args Range Complete  Definition");
  2773. found = TRUE;
  2774. msg_putchar('n');
  2775. /* Special cases */
  2776. msg_putchar(a & BANG ? '!' : ' ');
  2777. msg_putchar(a & REGSTR ? '"' : ' ');
  2778. msg_putchar(' ');
  2779. msg_outtrans_attr(cmd->uc_name, hl_attr(HLF_D));
  2780. len = STRLEN(cmd->uc_name) + 3;
  2781. do {
  2782.     msg_putchar(' ');
  2783.     ++len;
  2784. } while (len < 15);
  2785. len = 0;
  2786. /* Arguments */
  2787. switch (a & (EXTRA|NOSPC|NEEDARG))
  2788. {
  2789. case 0:     IObuff[len++] = '0'; break;
  2790. case (EXTRA):     IObuff[len++] = '*'; break;
  2791. case (EXTRA|NOSPC):     IObuff[len++] = '?'; break;
  2792. case (EXTRA|NEEDARG):     IObuff[len++] = '+'; break;
  2793. case (EXTRA|NOSPC|NEEDARG): IObuff[len++] = '1'; break;
  2794. }
  2795. do {
  2796.     IObuff[len++] = ' ';
  2797. } while (len < 5);
  2798. /* Range */
  2799. if (a & (RANGE|COUNT))
  2800. {
  2801.     if (a & COUNT)
  2802.     {
  2803. /* -count=N */
  2804. sprintf((char *)IObuff + len, "%ldc", cmd->uc_def);
  2805. len += STRLEN(IObuff + len);
  2806.     }
  2807.     else if (a & DFLALL)
  2808. IObuff[len++] = '%';
  2809.     else if (cmd->uc_def >= 0)
  2810.     {
  2811. /* -range=N */
  2812. sprintf((char *)IObuff + len, "%ld", cmd->uc_def);
  2813. len += STRLEN(IObuff + len);
  2814.     }
  2815.     else
  2816. IObuff[len++] = '.';
  2817. }
  2818. do {
  2819.     IObuff[len++] = ' ';
  2820. } while (len < 11);
  2821. /* Completion */
  2822. switch (cmd->uc_compl)
  2823. {
  2824.     case EXPAND_AUGROUP: s = "augroup"; break;
  2825.     case EXPAND_BUFFERS: s = "buffer"; break;
  2826.     case EXPAND_COMMANDS: s = "command"; break;
  2827.     case EXPAND_DIRECTORIES: s = "dir"; break;
  2828.     case EXPAND_EVENTS: s = "event"; break;
  2829.     case EXPAND_FILES: s = "file"; break;
  2830.     case EXPAND_HELP: s = "help"; break;
  2831.     case EXPAND_HIGHLIGHT: s = "highlight"; break;
  2832.     case EXPAND_MENUS: s = "menu"; break;
  2833.     case EXPAND_SETTINGS: s = "option"; break;
  2834.     case EXPAND_TAGS: s = "tag"; break;
  2835.     case EXPAND_USER_VARS: s = "var"; break;
  2836.     default: s = NULL; break;
  2837. }
  2838. if (s != NULL)
  2839. {
  2840.     STRCPY(IObuff + len, s);
  2841.     len += STRLEN(s);
  2842. }
  2843. do {
  2844.     IObuff[len++] = ' ';
  2845. } while (len < 21);
  2846. IObuff[len] = '';
  2847. msg_outtrans(IObuff);
  2848. msg_outtrans(cmd->uc_rep);
  2849. out_flush();
  2850. ui_breakcheck();
  2851.     }
  2852.     if (!found)
  2853. MSG("No user-defined commands found");
  2854. }
  2855.     static int
  2856. uc_scan_attr(attr, len, argt, def, compl)
  2857.     char_u *attr;
  2858.     size_t len;
  2859.     long *argt;
  2860.     long *def;
  2861.     int *compl;
  2862. {
  2863.     char_u *p;
  2864.     if (len == 0)
  2865.     {
  2866. EMSG("No attribute specified");
  2867. return FAIL;
  2868.     }
  2869.     /* First, try the simple attributes (no arguments) */
  2870.     if (STRNICMP(attr, "bang", len) == 0)
  2871. *argt |= BANG;
  2872.     else if (STRNICMP(attr, "register", len) == 0)
  2873. *argt |= REGSTR;
  2874.     else
  2875.     {
  2876. size_t i;
  2877. char_u *val = NULL;
  2878. size_t vallen = 0;
  2879. size_t attrlen = len;
  2880. /* Look for the attribute name - which is the part before any '=' */
  2881. for (i = 0; i < len; ++i)
  2882. {
  2883.     if (attr[i] == '=')
  2884.     {
  2885. val = &attr[i+1];
  2886. vallen = len - i - 1;
  2887. attrlen = i;
  2888. break;
  2889.     }
  2890. }
  2891. if (STRNICMP(attr, "nargs", attrlen) == 0)
  2892. {
  2893.     if (vallen == 1)
  2894.     {
  2895. if (*val == '0')
  2896.     /* Do nothing - this is the default */;
  2897. else if (*val == '1')
  2898.     *argt |= (EXTRA | NOSPC | NEEDARG);
  2899. else if (*val == '*')
  2900.     *argt |= EXTRA;
  2901. else if (*val == '?')
  2902.     *argt |= (EXTRA | NOSPC);
  2903. else if (*val == '+')
  2904.     *argt |= (EXTRA | NEEDARG);
  2905. else
  2906.     goto wrong_nargs;
  2907.     }
  2908.     else
  2909.     {
  2910. wrong_nargs:
  2911. EMSG("Invalid number of arguments");
  2912. return FAIL;
  2913.     }
  2914. }
  2915. else if (STRNICMP(attr, "range", attrlen) == 0)
  2916. {
  2917.     *argt |= RANGE;
  2918.     if (vallen == 1 && *val == '%')
  2919. *argt |= DFLALL;
  2920.     else if (val != NULL)
  2921.     {
  2922. p = val;
  2923. if (*def >= 0)
  2924. {
  2925. two_count:
  2926.     EMSG("Count cannot be specified twice");
  2927.     return FAIL;
  2928. }
  2929. *def = getdigits(&p);
  2930. *argt |= (ZEROR | NOTADR);
  2931. if (p != val + vallen)
  2932. {
  2933. invalid_count:
  2934.     EMSG("Invalid default value for count");
  2935.     return FAIL;
  2936. }
  2937.     }
  2938. }
  2939. else if (STRNICMP(attr, "count", attrlen) == 0)
  2940. {
  2941.     *argt |= (COUNT | ZEROR | NOTADR);
  2942.     if (val != NULL)
  2943.     {
  2944. p = val;
  2945. if (*def >= 0)
  2946.     goto two_count;
  2947. *def = getdigits(&p);
  2948. if (p != val + vallen)
  2949.     goto invalid_count;
  2950.     }
  2951.     if (*def < 0)
  2952. *def = 0;
  2953. }
  2954. else if (STRNICMP(attr, "complete", attrlen) == 0)
  2955. {
  2956.     if (val == NULL)
  2957.     {
  2958. EMSG("argument required for complete");
  2959. return FAIL;
  2960.     }
  2961.     if (STRNCMP(val, "augroup", vallen) == 0)
  2962. *compl = EXPAND_AUGROUP;
  2963.     else if (STRNICMP(val, "buffer", vallen) == 0)
  2964.     {
  2965. *argt |= BUFNAME;
  2966. *compl = EXPAND_BUFFERS;
  2967.     }
  2968.     else if (STRNCMP(val, "command", vallen) == 0)
  2969. *compl = EXPAND_COMMANDS;
  2970.     else if (STRNCMP(val, "dir", vallen) == 0)
  2971. *compl = EXPAND_DIRECTORIES;
  2972.     else if (STRNCMP(val, "event", vallen) == 0)
  2973. *compl = EXPAND_EVENTS;
  2974.     else if (STRNICMP(val, "file", vallen) == 0)
  2975.     {
  2976. *argt |= XFILE;
  2977. *compl = EXPAND_FILES;
  2978.     }
  2979.     else if (STRNCMP(val, "help", vallen) == 0)
  2980. *compl = EXPAND_HELP;
  2981.     else if (STRNCMP(val, "highlight", vallen) == 0)
  2982. *compl = EXPAND_HIGHLIGHT;
  2983.     else if (STRNCMP(val, "menu", vallen) == 0)
  2984. *compl = EXPAND_MENUS;
  2985.     else if (STRNCMP(val, "option", vallen) == 0)
  2986. *compl = EXPAND_SETTINGS;
  2987.     else if (STRNCMP(val, "tag", vallen) == 0)
  2988. *compl = EXPAND_TAGS;
  2989.     else if (STRNCMP(val, "var", vallen) == 0)
  2990. *compl = EXPAND_USER_VARS;
  2991.     else
  2992.     {
  2993. EMSG2("Invalid complete value: %s", val);
  2994. return FAIL;
  2995.     }
  2996. }
  2997. else
  2998. {
  2999.     char_u ch = attr[len];
  3000.     attr[len] = '';
  3001.     EMSG2("Invalid attribute: %s", attr);
  3002.     attr[len] = ch;
  3003.     return FAIL;
  3004. }
  3005.     }
  3006.     return OK;
  3007. }
  3008.     static void
  3009. do_command(eap)
  3010.     EXARG   *eap;
  3011. {
  3012.     char_u  *name;
  3013.     char_u  *end;
  3014.     char_u  *p;
  3015.     long    argt = 0;
  3016.     long    def = -1;
  3017.     int     compl = EXPAND_NOTHING;
  3018.     int     has_attr = (eap->arg[0] == '-');
  3019.     p = eap->arg;
  3020.     /* Check for attributes */
  3021.     while (*p == '-')
  3022.     {
  3023. ++p;
  3024. end = skiptowhite(p);
  3025. if (uc_scan_attr(p, end - p, &argt, &def, &compl) == FAIL)
  3026.     return;
  3027. p = skipwhite(end);
  3028.     }
  3029.     /* Get the name (if any) and skip to the following argument */
  3030.     name = p;
  3031.     while (isalpha(*p))
  3032. ++p;
  3033.     if (!ends_excmd(*p) && !vim_iswhite(*p))
  3034.     {
  3035. EMSG("Invalid command name");
  3036. return;
  3037.     }
  3038.     end = p;
  3039.     /* If there is nothing after the name, and no attributes were specified,
  3040.      * we are listing commands
  3041.      */
  3042.     p = skipwhite(end);
  3043.     if (!has_attr && ends_excmd(*p))
  3044.     {
  3045. uc_list(name, end - name);
  3046. return;
  3047.     }
  3048.     if (!isupper(*name))
  3049.     {
  3050. EMSG("User defined commands must start with an uppercase letter");
  3051. return;
  3052.     }
  3053.     uc_add_command(name, end - name, p, argt, def, compl, eap->forceit);
  3054. }
  3055.     static void
  3056. do_comclear()
  3057. {
  3058.     int i;
  3059.     UCMD *cmd;
  3060.     for (i = 0; i < ucmds.ga_len; ++i)
  3061.     {
  3062. cmd = USER_CMD(i);
  3063. vim_free(cmd->uc_name);
  3064. vim_free(cmd->uc_rep);
  3065.     }
  3066.     ga_clear(&ucmds);
  3067. }
  3068.     static void
  3069. do_delcommand(eap)
  3070.     EXARG *eap;
  3071. {
  3072.     int i = 0;
  3073.     UCMD *cmd = USER_CMD(0);
  3074.     int cmp = -1;
  3075.     while (i < ucmds.ga_len)
  3076.     {
  3077. cmp = STRCMP(eap->arg, cmd->uc_name);
  3078. if (cmp <= 0)
  3079.     break;
  3080. ++i;
  3081. ++cmd;
  3082.     }
  3083.     if (cmp != 0)
  3084.     {
  3085. EMSG2("No such user-defined command: %s", eap->arg);
  3086. return;
  3087.     }
  3088.     vim_free(cmd->uc_name);
  3089.     vim_free(cmd->uc_rep);
  3090.     --ucmds.ga_len;
  3091.     ++ucmds.ga_room;
  3092.     if (i < ucmds.ga_len)
  3093. mch_memmove(cmd, cmd + 1, (ucmds.ga_len - i) * sizeof(UCMD));
  3094. }
  3095.     static char_u *
  3096. uc_split_args(arg, lenp)
  3097.     char_u *arg;
  3098.     size_t *lenp;
  3099. {
  3100.     char_u *buf;
  3101.     char_u *p;
  3102.     char_u *q;
  3103.     int len;
  3104.     /* Precalculate length */
  3105.     p = arg;
  3106.     len = 2; /* Initial and final quotes */
  3107.     while (*p)
  3108.     {
  3109. if (p[0] == '\' && p[1] == ' ')
  3110. {
  3111.     len += 1;
  3112.     p += 2;
  3113. }
  3114. else if (*p == '\' || *p == '"')
  3115. {
  3116.     len += 2;
  3117.     p += 1;
  3118. }
  3119. else if (*p == ' ')
  3120. {
  3121.     len += 3; /* "," */
  3122.     while (*p == ' ')
  3123. ++p;
  3124. }
  3125. else
  3126. {
  3127.     ++len;
  3128.     ++p;
  3129. }
  3130.     }
  3131.     buf = alloc(len + 1);
  3132.     if (buf == NULL)
  3133.     {
  3134. *lenp = 0;
  3135. return buf;
  3136.     }
  3137.     p = arg;
  3138.     q = buf;
  3139.     *q++ = '"';
  3140.     while (*p)
  3141.     {
  3142. if (p[0] == '\' && p[1] == ' ')
  3143. {
  3144.     *q++ = p[1];
  3145.     p += 2;
  3146. }
  3147. else if (*p == '\' || *p == '"')
  3148. {
  3149.     *q++ = '\';
  3150.     *q++ = *p++;
  3151. }
  3152. else if (*p == ' ')
  3153. {
  3154.     *q++ = '"';
  3155.     *q++ = ',';
  3156.     *q++ = '"';
  3157.     while (*p == ' ')
  3158. ++p;
  3159. }
  3160. else
  3161. {
  3162.     *q++ = *p++;
  3163. }
  3164.     }
  3165.     *q++ = '"';
  3166.     *q = 0;
  3167.     *lenp = len;
  3168.     return buf;
  3169. }
  3170.     static size_t
  3171. uc_check_code(code, len, buf, cmd, eap, split_buf, split_len)
  3172.     char_u *code;
  3173.     size_t len;
  3174.     char_u *buf;
  3175.     UCMD *cmd;
  3176.     EXARG *eap;
  3177.     char_u **split_buf;
  3178.     size_t *split_len;
  3179. {
  3180.     size_t result = 0;
  3181.     char_u *p = code + 1;
  3182.     size_t l = len - 2;
  3183.     int quote = 0;
  3184.     enum {
  3185. ct_ARGS, ct_BANG, ct_COUNT,
  3186. ct_LINE1, ct_LINE2, ct_REGISTER,
  3187. ct_LT, ct_NONE
  3188.     } type = ct_NONE;
  3189.     if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-')
  3190.     {
  3191. quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
  3192. p += 2;
  3193. l -= 2;
  3194.     }
  3195.     if (STRNICMP(p, "args", l) == 0)
  3196. type = ct_ARGS;
  3197.     else if (STRNICMP(p, "bang", l) == 0)
  3198. type = ct_BANG;
  3199.     else if (STRNICMP(p, "count", l) == 0)
  3200. type = ct_COUNT;
  3201.     else if (STRNICMP(p, "line1", l) == 0)
  3202. type = ct_LINE1;
  3203.     else if (STRNICMP(p, "line2", l) == 0)
  3204. type = ct_LINE2;
  3205.     else if (STRNICMP(p, "lt", l) == 0)
  3206. type = ct_LT;
  3207.     else if (STRNICMP(p, "register", l) == 0)
  3208. type = ct_REGISTER;
  3209.     switch (type)
  3210.     {
  3211.     case ct_ARGS:
  3212. /* Simple case first */
  3213. if (eap->arg == NUL)
  3214. {
  3215.     if (quote == 1)
  3216.     {
  3217. result = 2;
  3218. if (buf)
  3219.     STRCPY(buf, "''");
  3220.     }
  3221. }
  3222. switch (quote)
  3223. {
  3224. case 0: /* No quoting, no splitting */
  3225.     result = STRLEN(eap->arg);
  3226.     if (buf)
  3227. STRCPY(buf, eap->arg);
  3228.     break;
  3229. case 1: /* Quote, but don't split */
  3230.     result = STRLEN(eap->arg) + 2;
  3231.     for (p = eap->arg; *p; ++p)
  3232.     {
  3233. if (*p == '\' || *p == '"')
  3234.     ++result;
  3235.     }
  3236.     if (buf)
  3237.     {
  3238. *buf++ = '"';
  3239. for (p = eap->arg; *p; ++p)
  3240. {
  3241.     if (*p == '\' || *p == '"')
  3242. *buf++ = '\';
  3243.     *buf++ = *p;
  3244. }
  3245. *buf = '"';
  3246.     }
  3247.     break;
  3248. case 2: /* Quote and split */
  3249.     /* This is hard, so only do it once, and cache the result */
  3250.     if (*split_buf == NULL)
  3251. *split_buf = uc_split_args(eap->arg, split_len);
  3252.     result = *split_len;
  3253.     if (buf && result != 0)
  3254. STRCPY(buf, *split_buf);
  3255.     break;
  3256. }
  3257. break;
  3258.     case ct_BANG:
  3259. result = eap->forceit ? 1 : 0;
  3260. if (quote)
  3261.     result += 2;
  3262. if (buf)
  3263. {
  3264.     if (quote)
  3265. *buf++ = '"';
  3266.     if (eap->forceit)
  3267. *buf++ = '!';
  3268.     if (quote)
  3269. *buf = '"';
  3270. }
  3271. break;
  3272.     case ct_LINE1:
  3273.     case ct_LINE2:
  3274.     case ct_COUNT:
  3275.     {
  3276. char num_buf[20];
  3277. long num = (type == ct_LINE1) ? eap->line1 :
  3278.    (type == ct_LINE2) ? eap->line2 :
  3279.    (eap->addr_count > 0) ? eap->line2 : cmd->uc_def;
  3280. size_t num_len;
  3281. sprintf(num_buf, "%ld", num);
  3282. num_len = STRLEN(num_buf);
  3283. result = num_len;
  3284. if (quote)
  3285.     result += 2;
  3286. if (buf)
  3287. {
  3288.     if (quote)
  3289. *buf++ = '"';
  3290.     STRCPY(buf, num_buf);
  3291.     buf += num_len;
  3292.     if (quote)
  3293. *buf = '"';
  3294. }
  3295. break;
  3296.     }
  3297.     case ct_REGISTER:
  3298. result = eap->regname ? 1 : 0;
  3299. if (quote)
  3300.     result += 2;
  3301. if (buf)
  3302. {
  3303.     if (quote)
  3304. *buf++ = ''';
  3305.     if (eap->regname)
  3306. *buf++ = eap->regname;
  3307.     if (quote)
  3308. *buf = ''';
  3309. }
  3310. break;
  3311.     case ct_LT:
  3312. result = 1;
  3313. if (buf)
  3314.     *buf = '<';
  3315. break;
  3316.     default:
  3317. result = len;
  3318. if (buf)
  3319.     STRNCPY(buf, code, len);
  3320. break;
  3321.     }
  3322.     return result;
  3323. }
  3324.     static void
  3325. do_ucmd(cmd, eap)
  3326.     UCMD *cmd;
  3327.     EXARG *eap;
  3328. {
  3329.     char_u *buf;
  3330.     char_u *p;
  3331.     char_u *q;
  3332.     char_u *start;
  3333.     char_u *end;
  3334.     size_t len, totlen;
  3335.     size_t split_len = 0;
  3336.     char_u *split_buf = NULL;
  3337.     /*
  3338.      * Replace <> in the command by the arguments.
  3339.      */
  3340.     buf = NULL;
  3341.     for (;;)
  3342.     {
  3343. p = cmd->uc_rep;
  3344. q = buf;
  3345. totlen = 0;
  3346. while ((start = vim_strchr(p, '<')) != NULL
  3347.        && (end = vim_strchr(start + 1, '>')) != NULL)
  3348. {
  3349.     /* Include the '>' */
  3350.     ++end;
  3351.     /* Take everything up to the '<' */
  3352.     len = start - p;
  3353.     if (buf == NULL)
  3354. totlen += len;
  3355.     else
  3356.     {
  3357. mch_memmove(q, p, len);
  3358. q += len;
  3359.     }
  3360.     len = uc_check_code(start, end - start, q, cmd, eap,
  3361.      &split_buf, &split_len);
  3362.     if (buf == NULL)
  3363. totlen += len;
  3364.     else
  3365. q += len;
  3366.     p = end;
  3367. }
  3368. if (buf != NULL)     /* second time here, finished */
  3369. {
  3370.     STRCPY(q, p);
  3371.     break;
  3372. }
  3373. totlen += STRLEN(p);     /* Add on the trailing characters */
  3374. buf = alloc((unsigned)(totlen + 1));
  3375. if (buf == NULL)
  3376. {
  3377.     vim_free(split_buf);
  3378.     return;
  3379. }
  3380.     }
  3381.     do_cmdline(buf, NULL, NULL, DOCMD_VERBOSE + DOCMD_NOWAIT);
  3382.     vim_free(buf);
  3383.     vim_free(split_buf);
  3384. }
  3385. #endif
  3386. #if defined(GUI_DIALOG) || defined(CON_DIALOG)
  3387.     static void
  3388. dialog_msg(buff, format, fname)
  3389.     char_u *buff;
  3390.     char *format;
  3391.     char_u *fname;
  3392. {
  3393.     int len;
  3394.     if (fname == NULL)
  3395. fname = (char_u *)"Untitled";
  3396.     len = STRLEN(format) + STRLEN(fname);
  3397.     if (len >= IOSIZE)
  3398. sprintf((char *)buff, format, (int)(IOSIZE - STRLEN(format)), fname);
  3399.     else
  3400. sprintf((char *)buff, format, (int)STRLEN(fname), fname);
  3401. }
  3402. #endif
  3403. /*
  3404.  * ":behave {mswin,xterm}"
  3405.  */
  3406.     static void
  3407. ex_behave(arg)
  3408.     char_u *arg;
  3409. {
  3410.     if (STRCMP(arg, "mswin") == 0)
  3411.     {
  3412. set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive");
  3413. set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key");
  3414. set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup");
  3415. set_option_value((char_u *)"keymodel", 0L,
  3416. (char_u *)"startsel,stopsel");
  3417.     }
  3418.     else if (STRCMP(arg, "xterm") == 0)
  3419.     {
  3420. set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive");
  3421. set_option_value((char_u *)"selectmode", 0L, (char_u *)"");
  3422. set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend");
  3423. set_option_value((char_u *)"keymodel", 0L, (char_u *)"");
  3424.     }
  3425.     else
  3426. EMSG2(e_invarg2, arg);
  3427. }