home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / unix / vim-6.2.tar.bz2 / vim-6.2.tar / vim62 / src / ex_docmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-24  |  204.2 KB  |  9,222 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * ex_docmd.c: functions for executing an Ex command line.
  12.  */
  13.  
  14. #include "vim.h"
  15.  
  16. #ifdef HAVE_FCNTL_H
  17. # include <fcntl.h>        /* for chdir() */
  18. #endif
  19.  
  20. static int    quitmore = 0;
  21. static int    ex_pressedreturn = FALSE;
  22. #ifndef FEAT_PRINTER
  23. # define ex_hardcopy    ex_ni
  24. #endif
  25.  
  26. #ifdef FEAT_USR_CMDS
  27. typedef struct ucmd
  28. {
  29.     char_u    *uc_name;    /* The command name */
  30.     long_u    uc_argt;    /* The argument type */
  31.     char_u    *uc_rep;    /* The command's replacement string */
  32.     long    uc_def;        /* The default value for a range/count */
  33.     scid_T    uc_scriptID;    /* SID where the command was defined */
  34.     int        uc_compl;    /* completion type */
  35.     char_u    *uc_compl_arg;    /* completion argument if any */
  36. } ucmd_T;
  37.  
  38. #define UC_BUFFER    1    /* -buffer: local to current buffer */
  39.  
  40. garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL};
  41.  
  42. #define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
  43. #define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
  44.  
  45. static void do_ucmd __ARGS((exarg_T *eap));
  46. static void ex_command __ARGS((exarg_T *eap));
  47. static void ex_comclear __ARGS((exarg_T *eap));
  48. static void ex_delcommand __ARGS((exarg_T *eap));
  49. # ifdef FEAT_CMDL_COMPL
  50. static char_u *get_user_command_name __ARGS((int idx));
  51. # endif
  52.  
  53. #else
  54. # define ex_command    ex_ni
  55. # define ex_comclear    ex_ni
  56. # define ex_delcommand    ex_ni
  57. #endif
  58.  
  59. #ifdef FEAT_EVAL
  60. static void    free_cmdlines __ARGS((garray_T *gap));
  61. static char_u    *do_one_cmd __ARGS((char_u **, int, struct condstack *, char_u *(*getline)(int, void *, int), void *cookie));
  62. #else
  63. static char_u    *do_one_cmd __ARGS((char_u **, int, char_u *(*getline)(int, void *, int), void *cookie));
  64. static int    if_level = 0;        /* depth in :if */
  65. #endif
  66. static int    checkforcmd __ARGS((char_u **pp, char *cmd, int len));
  67. static char_u    *find_command __ARGS((exarg_T *eap, int *full));
  68.  
  69. static void    ex_abbreviate __ARGS((exarg_T *eap));
  70. static void    ex_map __ARGS((exarg_T *eap));
  71. static void    ex_unmap __ARGS((exarg_T *eap));
  72. static void    ex_mapclear __ARGS((exarg_T *eap));
  73. static void    ex_abclear __ARGS((exarg_T *eap));
  74. #ifndef FEAT_MENU
  75. # define ex_emenu        ex_ni
  76. # define ex_menu        ex_ni
  77. # define ex_menutranslate    ex_ni
  78. #endif
  79. #ifdef FEAT_AUTOCMD
  80. static void    ex_autocmd __ARGS((exarg_T *eap));
  81. static void    ex_doautocmd __ARGS((exarg_T *eap));
  82. #else
  83. # define ex_autocmd        ex_ni
  84. # define ex_doautocmd        ex_ni
  85. # define ex_doautoall        ex_ni
  86. #endif
  87. #ifdef FEAT_LISTCMDS
  88. static void    ex_bunload __ARGS((exarg_T *eap));
  89. static void    ex_buffer __ARGS((exarg_T *eap));
  90. static void    ex_bmodified __ARGS((exarg_T *eap));
  91. static void    ex_bnext __ARGS((exarg_T *eap));
  92. static void    ex_bprevious __ARGS((exarg_T *eap));
  93. static void    ex_brewind __ARGS((exarg_T *eap));
  94. static void    ex_blast __ARGS((exarg_T *eap));
  95. #else
  96. # define ex_bunload        ex_ni
  97. # define ex_buffer        ex_ni
  98. # define ex_bmodified        ex_ni
  99. # define ex_bnext        ex_ni
  100. # define ex_bprevious        ex_ni
  101. # define ex_brewind        ex_ni
  102. # define ex_blast        ex_ni
  103. # define buflist_list        ex_ni
  104. # define ex_checktime        ex_ni
  105. #endif
  106. #if !defined(FEAT_LISTCMDS) || !defined(FEAT_WINDOWS)
  107. # define ex_buffer_all        ex_ni
  108. #endif
  109. static char_u    *getargcmd __ARGS((char_u **));
  110. static char_u    *skip_cmd_arg __ARGS((char_u *p, int rembs));
  111. static int    getargopt __ARGS((exarg_T *eap));
  112. #ifndef FEAT_QUICKFIX
  113. # define ex_make        ex_ni
  114. # define ex_cc            ex_ni
  115. # define ex_cnext        ex_ni
  116. # define ex_cfile        ex_ni
  117. # define qf_list        ex_ni
  118. # define qf_age            ex_ni
  119. # define ex_helpgrep        ex_ni
  120. #endif
  121. #if !defined(FEAT_QUICKFIX) || !defined(FEAT_WINDOWS)
  122. # define ex_cclose        ex_ni
  123. # define ex_copen        ex_ni
  124. # define ex_cwindow        ex_ni
  125. #endif
  126.  
  127. static int    check_more __ARGS((int, int));
  128. static linenr_T get_address __ARGS((char_u **, int skip, int otherfile));
  129. static char_u    *invalid_range __ARGS((exarg_T *eap));
  130. static void    correct_range __ARGS((exarg_T *eap));
  131. static char_u    *repl_cmdline __ARGS((exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep));
  132. static void    ex_highlight __ARGS((exarg_T *eap));
  133. static void    ex_colorscheme __ARGS((exarg_T *eap));
  134. static void    ex_quit __ARGS((exarg_T *eap));
  135. static void    ex_cquit __ARGS((exarg_T *eap));
  136. static void    ex_quit_all __ARGS((exarg_T *eap));
  137. #ifdef FEAT_WINDOWS
  138. static void    ex_close __ARGS((exarg_T *eap));
  139. static void    ex_win_close __ARGS((exarg_T *eap, win_T *win));
  140. static void    ex_only __ARGS((exarg_T *eap));
  141. static void    ex_all __ARGS((exarg_T *eap));
  142. static void    ex_resize __ARGS((exarg_T *eap));
  143. static void    ex_stag __ARGS((exarg_T *eap));
  144. #else
  145. # define ex_close        ex_ni
  146. # define ex_only        ex_ni
  147. # define ex_all            ex_ni
  148. # define ex_resize        ex_ni
  149. # define ex_splitview        ex_ni
  150. # define ex_stag        ex_ni
  151. #endif
  152. #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
  153. static void    ex_pclose __ARGS((exarg_T *eap));
  154. static void    ex_ptag __ARGS((exarg_T *eap));
  155. static void    ex_pedit __ARGS((exarg_T *eap));
  156. #else
  157. # define ex_pclose        ex_ni
  158. # define ex_ptag        ex_ni
  159. # define ex_pedit        ex_ni
  160. #endif
  161. static void    ex_hide __ARGS((exarg_T *eap));
  162. static void    ex_stop __ARGS((exarg_T *eap));
  163. static void    ex_exit __ARGS((exarg_T *eap));
  164. static void    ex_print __ARGS((exarg_T *eap));
  165. #ifdef FEAT_BYTEOFF
  166. static void    ex_goto __ARGS((exarg_T *eap));
  167. #else
  168. # define ex_goto        ex_ni
  169. #endif
  170. static void    ex_shell __ARGS((exarg_T *eap));
  171. static void    ex_preserve __ARGS((exarg_T *eap));
  172. static void    ex_recover __ARGS((exarg_T *eap));
  173. #ifndef FEAT_LISTCMDS
  174. # define ex_argedit        ex_ni
  175. # define ex_argadd        ex_ni
  176. # define ex_argdelete        ex_ni
  177. # define ex_listdo        ex_ni
  178. #endif
  179. static void    ex_mode __ARGS((exarg_T *eap));
  180. static void    ex_wrongmodifier __ARGS((exarg_T *eap));
  181. static void    ex_find __ARGS((exarg_T *eap));
  182. static void    ex_edit __ARGS((exarg_T *eap));
  183. #if !defined(FEAT_GUI) && !defined(FEAT_CLIENTSERVER)
  184. # define ex_drop        ex_ni
  185. #endif
  186. #ifndef FEAT_GUI
  187. # define ex_gui            ex_nogui
  188. static void    ex_nogui __ARGS((exarg_T *eap));
  189. #endif
  190. #if defined(FEAT_GUI_W32) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
  191. static void    ex_tearoff __ARGS((exarg_T *eap));
  192. #else
  193. # define ex_tearoff        ex_ni
  194. #endif
  195. #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)) && defined(FEAT_MENU)
  196. static void    ex_popup __ARGS((exarg_T *eap));
  197. #else
  198. # define ex_popup        ex_ni
  199. #endif
  200. #ifndef FEAT_GUI_MSWIN
  201. # define ex_simalt        ex_ni
  202. #endif
  203. #if !defined(FEAT_GUI_MSWIN) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF)
  204. # define gui_mch_find_dialog    ex_ni
  205. # define gui_mch_replace_dialog ex_ni
  206. #endif
  207. #ifndef FEAT_GUI_GTK
  208. # define ex_helpfind        ex_ni
  209. #endif
  210. #ifndef FEAT_CSCOPE
  211. # define do_cscope        ex_ni
  212. # define do_scscope        ex_ni
  213. # define do_cstag        ex_ni
  214. #endif
  215. #ifndef FEAT_SYN_HL
  216. # define ex_syntax        ex_ni
  217. #endif
  218. #ifndef FEAT_PERL
  219. # define ex_perl        ex_ni
  220. # define ex_perldo        ex_ni
  221. #endif
  222. #ifndef FEAT_PYTHON
  223. # define ex_python        ex_ni
  224. # define ex_pyfile        ex_ni
  225. #endif
  226. #ifndef FEAT_TCL
  227. # define ex_tcl            ex_ni
  228. # define ex_tcldo        ex_ni
  229. # define ex_tclfile        ex_ni
  230. #endif
  231. #ifndef FEAT_RUBY
  232. # define ex_ruby        ex_ni
  233. # define ex_rubydo        ex_ni
  234. # define ex_rubyfile        ex_ni
  235. #endif
  236. #ifndef FEAT_SNIFF
  237. # define ex_sniff        ex_ni
  238. #endif
  239. #ifndef FEAT_KEYMAP
  240. # define ex_loadkeymap        ex_ni
  241. #endif
  242. static void    ex_swapname __ARGS((exarg_T *eap));
  243. static void    ex_syncbind __ARGS((exarg_T *eap));
  244. static void    ex_read __ARGS((exarg_T *eap));
  245. static void    ex_cd __ARGS((exarg_T *eap));
  246. static void    ex_pwd __ARGS((exarg_T *eap));
  247. static void    ex_equal __ARGS((exarg_T *eap));
  248. static void    ex_sleep __ARGS((exarg_T *eap));
  249. static void    do_exmap __ARGS((exarg_T *eap, int isabbrev));
  250. static void    ex_winsize __ARGS((exarg_T *eap));
  251. #ifdef FEAT_WINDOWS
  252. static void    ex_wincmd __ARGS((exarg_T *eap));
  253. #else
  254. # define ex_wincmd        ex_ni
  255. #endif
  256. #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS)
  257. static void    ex_winpos __ARGS((exarg_T *eap));
  258. #else
  259. # define ex_winpos        ex_ni
  260. #endif
  261. static void    ex_operators __ARGS((exarg_T *eap));
  262. static void    ex_put __ARGS((exarg_T *eap));
  263. static void    ex_copymove __ARGS((exarg_T *eap));
  264. static void    ex_submagic __ARGS((exarg_T *eap));
  265. static void    ex_join __ARGS((exarg_T *eap));
  266. static void    ex_at __ARGS((exarg_T *eap));
  267. static void    ex_bang __ARGS((exarg_T *eap));
  268. static void    ex_undo __ARGS((exarg_T *eap));
  269. static void    ex_redo __ARGS((exarg_T *eap));
  270. static void    ex_redir __ARGS((exarg_T *eap));
  271. static void    ex_redraw __ARGS((exarg_T *eap));
  272. static void    close_redir __ARGS((void));
  273. static void    ex_mkrc __ARGS((exarg_T *eap));
  274. static void    ex_mark __ARGS((exarg_T *eap));
  275. #ifdef FEAT_USR_CMDS
  276. static char_u    *uc_fun_cmd __ARGS((void));
  277. #endif
  278. #ifdef FEAT_EX_EXTRA
  279. static void    ex_normal __ARGS((exarg_T *eap));
  280. static void    ex_startinsert __ARGS((exarg_T *eap));
  281. static void    ex_stopinsert __ARGS((exarg_T *eap));
  282. #else
  283. # define ex_normal        ex_ni
  284. # define ex_align        ex_ni
  285. # define ex_retab        ex_ni
  286. # define ex_startinsert        ex_ni
  287. # define ex_stopinsert        ex_ni
  288. # define ex_helptags        ex_ni
  289. #endif
  290. #ifdef FEAT_FIND_ID
  291. static void    ex_checkpath __ARGS((exarg_T *eap));
  292. static void    ex_findpat __ARGS((exarg_T *eap));
  293. #else
  294. # define ex_findpat        ex_ni
  295. # define ex_checkpath        ex_ni
  296. #endif
  297. #if defined(FEAT_FIND_ID) && defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
  298. static void    ex_psearch __ARGS((exarg_T *eap));
  299. #else
  300. # define ex_psearch        ex_ni
  301. #endif
  302. static void    ex_tag __ARGS((exarg_T *eap));
  303. static void    ex_tag_cmd __ARGS((exarg_T *eap, char_u *name));
  304. #ifndef FEAT_EVAL
  305. # define ex_scriptnames        ex_ni
  306. # define ex_finish        ex_ni
  307. # define ex_echo        ex_ni
  308. # define ex_echohl        ex_ni
  309. # define ex_execute        ex_ni
  310. # define ex_call        ex_ni
  311. # define ex_if            ex_ni
  312. # define ex_endif        ex_ni
  313. # define ex_else        ex_ni
  314. # define ex_while        ex_ni
  315. # define ex_continue        ex_ni
  316. # define ex_break        ex_ni
  317. # define ex_endwhile        ex_ni
  318. # define ex_throw        ex_ni
  319. # define ex_try            ex_ni
  320. # define ex_catch        ex_ni
  321. # define ex_finally        ex_ni
  322. # define ex_endtry        ex_ni
  323. # define ex_endfunction        ex_ni
  324. # define ex_let            ex_ni
  325. # define ex_unlet        ex_ni
  326. # define ex_function        ex_ni
  327. # define ex_delfunction        ex_ni
  328. # define ex_return        ex_ni
  329. #endif
  330. static char_u    *arg_all __ARGS((void));
  331. #ifdef FEAT_SESSION
  332. static int    makeopens __ARGS((FILE *fd, char_u *dirnow));
  333. static int    put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp));
  334. static void    ex_loadview __ARGS((exarg_T *eap));
  335. static char_u    *get_view_file __ARGS((int c));
  336. #else
  337. # define ex_loadview        ex_ni
  338. #endif
  339. #ifndef FEAT_EVAL
  340. # define ex_compiler        ex_ni
  341. #endif
  342. #ifdef FEAT_VIMINFO
  343. static void    ex_viminfo __ARGS((exarg_T *eap));
  344. #else
  345. # define ex_viminfo        ex_ni
  346. #endif
  347. static void    ex_behave __ARGS((exarg_T *eap));
  348. #ifdef FEAT_AUTOCMD
  349. static void    ex_filetype __ARGS((exarg_T *eap));
  350. static void    ex_setfiletype  __ARGS((exarg_T *eap));
  351. #else
  352. # define ex_filetype        ex_ni
  353. # define ex_setfiletype        ex_ni
  354. #endif
  355. #ifndef FEAT_DIFF
  356. # define ex_diffpatch        ex_ni
  357. # define ex_diffgetput        ex_ni
  358. # define ex_diffsplit        ex_ni
  359. # define ex_diffthis        ex_ni
  360. # define ex_diffupdate        ex_ni
  361. #endif
  362. static void    ex_digraphs __ARGS((exarg_T *eap));
  363. static void    ex_set __ARGS((exarg_T *eap));
  364. #if !defined(FEAT_EVAL) || !defined(FEAT_AUTOCMD)
  365. # define ex_options        ex_ni
  366. #endif
  367. #ifdef FEAT_SEARCH_EXTRA
  368. static void    ex_nohlsearch __ARGS((exarg_T *eap));
  369. static void    ex_match __ARGS((exarg_T *eap));
  370. #else
  371. # define ex_nohlsearch        ex_ni
  372. # define ex_match        ex_ni
  373. #endif
  374. #ifdef FEAT_CRYPT
  375. static void    ex_X __ARGS((exarg_T *eap));
  376. #else
  377. # define ex_X            ex_ni
  378. #endif
  379. #ifdef FEAT_FOLDING
  380. static void    ex_fold __ARGS((exarg_T *eap));
  381. static void    ex_foldopen __ARGS((exarg_T *eap));
  382. static void    ex_folddo __ARGS((exarg_T *eap));
  383. #else
  384. # define ex_fold        ex_ni
  385. # define ex_foldopen        ex_ni
  386. # define ex_folddo        ex_ni
  387. #endif
  388. #if !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
  389.     && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)))
  390. # define ex_language        ex_ni
  391. #endif
  392. #ifndef FEAT_SIGNS
  393. # define ex_sign        ex_ni
  394. #endif
  395. #ifndef FEAT_SUN_WORKSHOP
  396. # define ex_wsverb        ex_ni
  397. #endif
  398.  
  399. #ifndef FEAT_EVAL
  400. # define ex_debug        ex_ni
  401. # define ex_breakadd        ex_ni
  402. # define ex_debuggreedy        ex_ni
  403. # define ex_breakdel        ex_ni
  404. # define ex_breaklist        ex_ni
  405. #endif
  406.  
  407. #ifndef FEAT_CMDHIST
  408. # define ex_history        ex_ni
  409. #endif
  410. #ifndef FEAT_JUMPLIST
  411. # define ex_jumps        ex_ni
  412. #endif
  413.  
  414. /*
  415.  * Declare cmdnames[].
  416.  */
  417. #define DO_DECLARE_EXCMD
  418. #include "ex_cmds.h"
  419.  
  420. /*
  421.  * Table used to quickly search for a command, based on its first character.
  422.  */
  423. cmdidx_T cmdidxs[27] =
  424. {
  425.     CMD_append,
  426.     CMD_buffer,
  427.     CMD_change,
  428.     CMD_delete,
  429.     CMD_edit,
  430.     CMD_file,
  431.     CMD_global,
  432.     CMD_help,
  433.     CMD_insert,
  434.     CMD_join,
  435.     CMD_k,
  436.     CMD_list,
  437.     CMD_move,
  438.     CMD_next,
  439.     CMD_open,
  440.     CMD_print,
  441.     CMD_quit,
  442.     CMD_read,
  443.     CMD_substitute,
  444.     CMD_t,
  445.     CMD_undo,
  446.     CMD_vglobal,
  447.     CMD_write,
  448.     CMD_xit,
  449.     CMD_yank,
  450.     CMD_z,
  451.     CMD_bang
  452. };
  453.  
  454. static char_u dollar_command[2] = {'$', 0};
  455.  
  456.  
  457. /*
  458.  * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi"
  459.  * command is given.
  460.  */
  461.     void
  462. do_exmode(improved)
  463.     int        improved;        /* TRUE for "improved Ex" mode */
  464. {
  465.     int        save_msg_scroll;
  466.     int        prev_msg_row;
  467.     linenr_T    prev_line;
  468.  
  469.     save_msg_scroll = msg_scroll;
  470.     ++RedrawingDisabled;        /* don't redisplay the window */
  471.     ++no_wait_return;            /* don't wait for return */
  472.     if (improved)
  473.     exmode_active = EXMODE_VIM;
  474.     else
  475.     {
  476.     settmode(TMODE_COOK);
  477.     exmode_active = EXMODE_NORMAL;
  478.     }
  479.  
  480.     State = NORMAL;
  481. #ifdef FEAT_GUI
  482.     /* Ignore scrollbar and mouse events in Ex mode */
  483.     ++hold_gui_events;
  484. #endif
  485. #ifdef FEAT_SNIFF
  486.     want_sniff_request = 0;    /* No K_SNIFF wanted */
  487. #endif
  488.  
  489.     MSG(_("Entering Ex mode.  Type \"visual\" to go to Normal mode."));
  490.     while (exmode_active)
  491.     {
  492.     msg_scroll = TRUE;
  493.     need_wait_return = FALSE;
  494.     ex_pressedreturn = FALSE;
  495.     ex_no_reprint = FALSE;
  496.     prev_msg_row = msg_row;
  497.     prev_line = curwin->w_cursor.lnum;
  498. #ifdef FEAT_SNIFF
  499.     ProcessSniffRequests();
  500. #endif
  501.     if (improved)
  502.     {
  503.         cmdline_row = msg_row;
  504.         do_cmdline(NULL, getexline, NULL, 0);
  505.     }
  506.     else
  507.         do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT);
  508.     lines_left = Rows - 1;
  509.  
  510.     if (prev_line != curwin->w_cursor.lnum && !ex_no_reprint)
  511.     {
  512.         if (ex_pressedreturn)
  513.         {
  514.         /* go up one line, to overwrite the ":<CR>" line, so the
  515.          * output doensn't contain empty lines. */
  516.         msg_row = prev_msg_row;
  517.         if (prev_msg_row == Rows - 1)
  518.             msg_row--;
  519.         }
  520.         msg_col = 0;
  521.         print_line_no_prefix(curwin->w_cursor.lnum, FALSE);
  522.         msg_clr_eos();
  523.     }
  524.     else if (ex_pressedreturn)    /* must be at EOF */
  525.         EMSG(_("E501: At end-of-file"));
  526.     }
  527.  
  528. #ifdef FEAT_GUI
  529.     --hold_gui_events;
  530. #endif
  531.     if (!improved)
  532.     settmode(TMODE_RAW);
  533.     --RedrawingDisabled;
  534.     --no_wait_return;
  535.     update_screen(CLEAR);
  536.     need_wait_return = FALSE;
  537.     msg_scroll = save_msg_scroll;
  538. }
  539.  
  540. /*
  541.  * Execute a simple command line.  Used for translated commands like "*".
  542.  */
  543.     int
  544. do_cmdline_cmd(cmd)
  545.     char_u    *cmd;
  546. {
  547.     return do_cmdline(cmd, NULL, NULL,
  548.                    DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
  549. }
  550.  
  551. /* Struct for storing a line inside a while loop */
  552. typedef struct
  553. {
  554.     char_u    *line;        /* command line */
  555.     linenr_T    lnum;        /* sourcing_lnum of the line */
  556. } wcmd_T;
  557.  
  558. /*
  559.  * do_cmdline(): execute one Ex command line
  560.  *
  561.  * 1. Execute "cmdline" when it is not NULL.
  562.  *    If "cmdline" is NULL, or more lines are needed, getline() is used.
  563.  * 2. Split up in parts separated with '|'.
  564.  *
  565.  * This function can be called recursively!
  566.  *
  567.  * flags:
  568.  * DOCMD_VERBOSE  - The command will be included in the error message.
  569.  * DOCMD_NOWAIT   - Don't call wait_return() and friends.
  570.  * DOCMD_REPEAT   - Repeat execution until getline() returns NULL.
  571.  * DOCMD_KEYTYPED - Don't reset KeyTyped.
  572.  * DOCMD_EXCRESET - Reset the exception environment (used for debugging).
  573.  *
  574.  * return FAIL if cmdline could not be executed, OK otherwise
  575.  */
  576.     int
  577. do_cmdline(cmdline, getline, cookie, flags)
  578.     char_u    *cmdline;
  579.     char_u    *(*getline) __ARGS((int, void *, int));
  580.     void    *cookie;        /* argument for getline() */
  581.     int        flags;
  582. {
  583.     char_u    *next_cmdline;        /* next cmd to execute */
  584.     char_u    *cmdline_copy = NULL;    /* copy of cmd line */
  585.     static int    recursive = 0;        /* recursive depth */
  586.     int        msg_didout_before_start = 0;
  587.     int        count = 0;        /* line number count */
  588.     int        did_inc = FALSE;    /* incremented RedrawingDisabled */
  589.     int        retval = OK;
  590. #ifdef FEAT_EVAL
  591.     struct condstack cstack;        /* conditional stack */
  592.     garray_T    lines_ga;        /* keep lines for ":while" */
  593.     int        current_line = 0;    /* active line in lines_ga */
  594.     int        saved_trylevel = 0;
  595.     int        saved_force_abort = 0;
  596.     except_T    *saved_caught_stack = NULL;
  597.     char_u    *saved_vv_exception = NULL;
  598.     char_u    *saved_vv_throwpoint = NULL;
  599.     int        saved_did_emsg = 0;
  600.     int        saved_got_int = 0;
  601.     int        saved_did_throw = 0;
  602.     int        saved_need_rethrow = 0;
  603.     int        saved_check_cstack = 0;
  604.     except_T    *saved_current_exception = NULL;
  605.     int        initial_trylevel;
  606.     struct msglist    **saved_msg_list = NULL;
  607.     struct msglist    *private_msg_list;
  608. #endif
  609.     static int    call_depth = 0;        /* recursiveness */
  610.  
  611. #ifdef FEAT_EVAL
  612.     /* For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
  613.      * location for storing error messages to be converted to an exception.
  614.      * This ensures that the do_errthrow() call in do_one_cmd() does not combine
  615.      * the messages stored by an earlier invocation of do_one_cmd() with the
  616.      * command name of the later one.  This would happen when BufWritePost
  617.      * autocommands are executed after a write error. */
  618.     saved_msg_list = msg_list;
  619.     msg_list = &private_msg_list;
  620.     private_msg_list = NULL;
  621. #endif
  622.  
  623.     /* It's possible to create an endless loop with ":execute", catch that
  624.      * here.  The value of 200 allows nested function calls, ":source", etc. */
  625.     if (call_depth == 200)
  626.     {
  627.     EMSG(_("E169: Command too recursive"));
  628. #ifdef FEAT_EVAL
  629.     /* When converting to an exception, we do not include the command name
  630.      * since this is not an error of the specific command. */
  631.     do_errthrow((struct condstack *)NULL, (char_u *)NULL);
  632. #endif
  633.     return FAIL;
  634.     }
  635.     ++call_depth;
  636.  
  637. #ifdef FEAT_EVAL
  638.     cstack.cs_idx = -1;
  639.     cstack.cs_whilelevel = 0;
  640.     cstack.cs_trylevel = 0;
  641.     cstack.cs_emsg_silent_list = NULL;
  642.     cstack.cs_had_while = FALSE;
  643.     cstack.cs_had_endwhile = FALSE;
  644.     cstack.cs_had_continue = FALSE;
  645.     cstack.cs_had_finally = FALSE;
  646.     ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10);
  647.  
  648.     /* Inside a function use a higher nesting level. */
  649.     if (getline == get_func_line && ex_nesting_level == func_level(cookie))
  650.     ++ex_nesting_level;
  651.  
  652.     /*
  653.      * Initialize "force_abort"  and "suppress_errthrow" at the top level.
  654.      */
  655.     if (!recursive)
  656.     {
  657.     force_abort = FALSE;
  658.     suppress_errthrow = FALSE;
  659.     }
  660.  
  661.     /*
  662.      * If requested, store and reset the global values controlling the
  663.      * exception handling (used when debugging).
  664.      */
  665.     else if (flags & DOCMD_EXCRESET)
  666.     {
  667.     saved_trylevel        = trylevel;        trylevel = 0;
  668.     saved_force_abort    = force_abort;        force_abort = FALSE;
  669.     saved_caught_stack    = caught_stack;        caught_stack = NULL;
  670.     saved_vv_exception    = v_exception(NULL);
  671.     saved_vv_throwpoint    = v_throwpoint(NULL);
  672.     /* Necessary for debugging an inactive ":catch", ":finally", or
  673.      * ":endtry": */
  674.     saved_did_emsg        = did_emsg,        did_emsg     = FALSE;
  675.     saved_got_int        = got_int,        got_int         = FALSE;
  676.     saved_did_throw        = did_throw,        did_throw    = FALSE;
  677.     saved_need_rethrow    = need_rethrow,        need_rethrow = FALSE;
  678.     saved_check_cstack    = check_cstack,        check_cstack = FALSE;
  679.     saved_current_exception = current_exception;    current_exception=NULL;
  680.     }
  681.  
  682.     initial_trylevel = trylevel;
  683.  
  684.     /*
  685.      * "did_throw" will be set to TRUE when an exception is being thrown.
  686.      */
  687.     did_throw = FALSE;
  688. #endif
  689.     /*
  690.      * "did_emsg" will be set to TRUE when emsg() is used, in which case we
  691.      * cancel the whole command line, and any if/endif while/endwhile loop.
  692.      * If force_abort is set, we cancel everything.
  693.      */
  694.     did_emsg = FALSE;
  695.  
  696.     /*
  697.      * KeyTyped is only set when calling vgetc().  Reset it here when not
  698.      * calling vgetc() (sourced command lines).
  699.      */
  700.     if (!(flags & DOCMD_KEYTYPED) && getline != getexline)
  701.     KeyTyped = FALSE;
  702.  
  703.     /*
  704.      * Continue executing command lines:
  705.      * - when inside an ":if" or ":while"
  706.      * - for multiple commands on one line, separated with '|'
  707.      * - when repeating until there are no more lines (for ":source")
  708.      */
  709.     next_cmdline = cmdline;
  710.     do
  711.     {
  712.     /* stop skipping cmds for an error msg after all endifs and endwhiles */
  713.     if (next_cmdline == NULL
  714. #ifdef FEAT_EVAL
  715.         && !force_abort
  716.         && cstack.cs_idx < 0
  717.         && !(getline == get_func_line && func_has_abort(cookie))
  718. #endif
  719.                             )
  720.         did_emsg = FALSE;
  721.  
  722.     /*
  723.      * 1. If repeating a line with ":while", get a line from lines_ga.
  724.      * 2. If no line given: Get an allocated line with getline().
  725.      * 3. If a line is given: Make a copy, so we can mess with it.
  726.      */
  727.  
  728. #ifdef FEAT_EVAL
  729.     /* 1. If repeating, get a previous line from lines_ga. */
  730.     if (cstack.cs_whilelevel && current_line < lines_ga.ga_len)
  731.     {
  732.         /* Each '|' separated command is stored separately in lines_ga, to
  733.          * be able to jump to it.  Don't use next_cmdline now. */
  734.         vim_free(cmdline_copy);
  735.         cmdline_copy = NULL;
  736.  
  737.         /* Check if a function has returned or, unless it has an unclosed
  738.          * try conditional, aborted. */
  739.         if (getline == get_func_line && func_has_ended(cookie))
  740.         {
  741.         retval = FAIL;
  742.         break;
  743.         }
  744.  
  745.         /* Check if a sourced file hit a ":finish" command. */
  746.         if (getline == getsourceline && source_finished(cookie))
  747.         {
  748.         retval = FAIL;
  749.         break;
  750.         }
  751.  
  752.         next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line;
  753.         sourcing_lnum = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum;
  754.     }
  755. #endif
  756.  
  757.     /* 2. If no line given, get an allocated line with getline(). */
  758.     if (next_cmdline == NULL)
  759.     {
  760.         /*
  761.          * Need to set msg_didout for the first line after an ":if",
  762.          * otherwise the ":if" will be overwritten.
  763.          */
  764.         if (count == 1 && getline == getexline)
  765.         msg_didout = TRUE;
  766.         if (getline == NULL || (next_cmdline = getline(':', cookie,
  767. #ifdef FEAT_EVAL
  768.             cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2
  769. #else
  770.             0
  771. #endif
  772.                 )) == NULL)
  773.         {
  774.         /* Don't call wait_return for aborted command line.  The NULL
  775.          * returned for the end of a sourced file or executed function
  776.          * doesn't do this. */
  777.         if (KeyTyped && !(flags & DOCMD_REPEAT))
  778.             need_wait_return = FALSE;
  779.         retval = FAIL;
  780.         break;
  781.         }
  782.     }
  783.  
  784.     /* 3. Make a copy of the command so we can mess with it. */
  785.     else if (cmdline_copy == NULL)
  786.     {
  787.         next_cmdline = vim_strsave(next_cmdline);
  788.         if (next_cmdline == NULL)
  789.         {
  790.         EMSG(_(e_outofmem));
  791.         retval = FAIL;
  792.         break;
  793.         }
  794.     }
  795.     cmdline_copy = next_cmdline;
  796.  
  797. #ifdef FEAT_EVAL
  798.     /*
  799.      * Save the current line when inside a ":while", and when the command
  800.      * looks like a ":while", because we may need it later.
  801.      * When there is a '|' and another command, it is stored separately,
  802.      * because we need to be able to jump back to it from an :endwhile.
  803.      */
  804.     if (       current_line == lines_ga.ga_len
  805.         && (cstack.cs_whilelevel || has_while_cmd(next_cmdline)))
  806.     {
  807.         if (ga_grow(&lines_ga, 1) == FAIL)
  808.         {
  809.         EMSG(_(e_outofmem));
  810.         retval = FAIL;
  811.         break;
  812.         }
  813.         ((wcmd_T *)(lines_ga.ga_data))[current_line].line =
  814.                             vim_strsave(next_cmdline);
  815.         ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum = sourcing_lnum;
  816.         ++lines_ga.ga_len;
  817.         --lines_ga.ga_room;
  818.     }
  819.     did_endif = FALSE;
  820. #endif
  821.  
  822.     if (count++ == 0)
  823.     {
  824.         /*
  825.          * All output from the commands is put below each other, without
  826.          * waiting for a return. Don't do this when executing commands
  827.          * from a script or when being called recursive (e.g. for ":e
  828.          * +command file").
  829.          */
  830.         if (!(flags & DOCMD_NOWAIT) && !recursive)
  831.         {
  832.         msg_didout_before_start = msg_didout;
  833.         msg_didany = FALSE; /* no output yet */
  834.         msg_start();
  835.         msg_scroll = TRUE;  /* put messages below each other */
  836.         ++no_wait_return;   /* dont wait for return until finished */
  837.         ++RedrawingDisabled;
  838.         did_inc = TRUE;
  839.         }
  840.     }
  841.  
  842.     if (p_verbose >= 15 && sourcing_name != NULL)
  843.     {
  844.         int    c = -1;
  845.  
  846.         ++no_wait_return;
  847.         msg_scroll = TRUE;        /* always scroll up, don't overwrite */
  848.         /* Truncate long lines, smsg() can't handle that. */
  849.         if (STRLEN(cmdline_copy) > 200)
  850.         {
  851.         c = cmdline_copy[200];
  852.         cmdline_copy[200] = NUL;
  853.         }
  854.         smsg((char_u *)_("line %ld: %s"),
  855.                        (long)sourcing_lnum, cmdline_copy);
  856.         msg_puts((char_u *)"\n");   /* don't overwrite this either */
  857.         if (c >= 0)
  858.         cmdline_copy[200] = c;
  859.         cmdline_row = msg_row;
  860.         --no_wait_return;
  861.     }
  862.  
  863.     /*
  864.      * 2. Execute one '|' separated command.
  865.      *    do_one_cmd() will return NULL if there is no trailing '|'.
  866.      *    "cmdline_copy" can change, e.g. for '%' and '#' expansion.
  867.      */
  868.     ++recursive;
  869.     next_cmdline = do_one_cmd(&cmdline_copy, flags & DOCMD_VERBOSE,
  870. #ifdef FEAT_EVAL
  871.                 &cstack,
  872. #endif
  873.                 getline, cookie);
  874.     --recursive;
  875.     if (next_cmdline == NULL)
  876.     {
  877.         vim_free(cmdline_copy);
  878.         cmdline_copy = NULL;
  879. #ifdef FEAT_CMDHIST
  880.         /*
  881.          * If the command was typed, remember it for the ':' register.
  882.          * Do this AFTER executing the command to make :@: work.
  883.          */
  884.         if (getline == getexline && new_last_cmdline != NULL)
  885.         {
  886.         vim_free(last_cmdline);
  887.         last_cmdline = new_last_cmdline;
  888.         new_last_cmdline = NULL;
  889.         }
  890. #endif
  891.     }
  892.     else
  893.     {
  894.         /* need to copy the command after the '|' to cmdline_copy, for the
  895.          * next do_one_cmd() */
  896.         mch_memmove(cmdline_copy, next_cmdline, STRLEN(next_cmdline) + 1);
  897.         next_cmdline = cmdline_copy;
  898.     }
  899.  
  900.  
  901. #ifdef FEAT_EVAL
  902.     /* reset did_emsg for a function that is not aborted by an error */
  903.     if (did_emsg && !force_abort
  904.         && getline == get_func_line && !func_has_abort(cookie))
  905.         did_emsg = FALSE;
  906.  
  907.     if (cstack.cs_whilelevel)
  908.     {
  909.         ++current_line;
  910.  
  911.         /*
  912.          * An ":endwhile" and ":continue" is handled here.
  913.          * If we were executing commands, jump back to the ":while".
  914.          * If we were not executing commands, decrement whilelevel.
  915.          */
  916.         if (cstack.cs_had_endwhile || cstack.cs_had_continue)
  917.         {
  918.         if (cstack.cs_had_endwhile)
  919.             cstack.cs_had_endwhile = FALSE;
  920.         else
  921.             cstack.cs_had_continue = FALSE;
  922.  
  923.         /* Jump back to the matching ":while".  Be careful not to use
  924.          * a cs_line[] from an entry that isn't a ":while": It would
  925.          * make "current_line" invalid and can cause a crash. */
  926.         if (!did_emsg && !got_int && !did_throw
  927.             && cstack.cs_idx >= 0
  928.             && (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE)
  929.             && cstack.cs_line[cstack.cs_idx] >= 0
  930.             && (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE))
  931.         {
  932.             current_line = cstack.cs_line[cstack.cs_idx];
  933.             cstack.cs_had_while = TRUE;    /* note we jumped there */
  934.             line_breakcheck();        /* check if CTRL-C typed */
  935.         }
  936.         else /* can only get here with ":endwhile" */
  937.         {
  938.             --cstack.cs_whilelevel;
  939.             if (cstack.cs_idx >= 0)
  940.             --cstack.cs_idx;
  941.         }
  942.         }
  943.  
  944.         /*
  945.          * For a ":while" we need to remember the line number.
  946.          */
  947.         else if (cstack.cs_had_while)
  948.         {
  949.         cstack.cs_had_while = FALSE;
  950.         cstack.cs_line[cstack.cs_idx] = current_line - 1;
  951.         }
  952.     }
  953.  
  954.     /*
  955.      * When not inside any ":while" loop, clear remembered lines.
  956.      */
  957.     if (!cstack.cs_whilelevel)
  958.     {
  959.         if (lines_ga.ga_len > 0)
  960.         {
  961.         sourcing_lnum =
  962.                ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
  963.         free_cmdlines(&lines_ga);
  964.         }
  965.         current_line = 0;
  966.     }
  967.  
  968.     /*
  969.      * A ":finally" makes did_emsg, got_int, and did_throw pending for being
  970.      * restored at the ":endtry".  Reset them here and set the ACTIVE and
  971.      * FINALLY flags, so that the finally clause gets executed.  This
  972.      * includes the case where a missing ":endif" or ":endwhile" was
  973.      * detected by the ":finally" itself.
  974.      */
  975.     if (cstack.cs_had_finally)
  976.     {
  977.         cstack.cs_had_finally = FALSE;
  978.         report_make_pending(cstack.cs_pending[cstack.cs_idx] &
  979.             (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW),
  980.             did_throw ? (void *)current_exception : NULL);
  981.         did_emsg = got_int = did_throw = FALSE;
  982.         cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
  983.     }
  984.  
  985.     /* Update global "trylevel" for recursive calls to do_cmdline() from
  986.      * within this loop. */
  987.     trylevel = initial_trylevel + cstack.cs_trylevel;
  988.  
  989.     /*
  990.      * If the outermost try conditional (accross function calls and sourced
  991.      * files) is aborted because of an error, an interrupt, or an uncaught
  992.      * exception, cancel everything.  If it is left normally, reset
  993.      * force_abort to get the non-EH compatible abortion behavior for
  994.      * the rest of the script.
  995.      */
  996.     if (trylevel == 0 && !did_emsg && !got_int && !did_throw)
  997.         force_abort = FALSE;
  998.  
  999.     /* Convert an interrupt to an exception if appropriate. */
  1000.     (void)do_intthrow(&cstack);
  1001. #endif /* FEAT_EVAL */
  1002.  
  1003.     }
  1004.     /*
  1005.      * Continue executing command lines when:
  1006.      * - no CTRL-C typed, no aborting error, no exception thrown or try
  1007.      *   conditionals need to be checked for executing finally clauses or
  1008.      *   catching an interrupt exception
  1009.      * - didn't get an error message or lines are not typed
  1010.      * - there is a command after '|', inside a :if, :while, or :try, or
  1011.      *   looping for ":source" command or function call.
  1012.      */
  1013.     while (!((got_int
  1014. #ifdef FEAT_EVAL
  1015.             || (did_emsg && force_abort) || did_throw
  1016. #endif
  1017.          )
  1018. #ifdef FEAT_EVAL
  1019.         && cstack.cs_trylevel == 0
  1020. #endif
  1021.         )
  1022.         && !(did_emsg && (getline == getexmodeline || getline == getexline))
  1023.         && (next_cmdline != NULL
  1024. #ifdef FEAT_EVAL
  1025.             || cstack.cs_idx >= 0
  1026. #endif
  1027.             || (flags & DOCMD_REPEAT)));
  1028.  
  1029.     vim_free(cmdline_copy);
  1030. #ifdef FEAT_EVAL
  1031.     free_cmdlines(&lines_ga);
  1032.     ga_clear(&lines_ga);
  1033.  
  1034.     if (cstack.cs_idx >= 0)
  1035.     {
  1036.     /*
  1037.      * If a sourced file or executed function ran to its end, report the
  1038.      * unclosed conditional.
  1039.      */
  1040.     if (!got_int && !did_throw
  1041.         && ((getline == getsourceline && !source_finished(cookie))
  1042.             || (getline == get_func_line && !func_has_ended(cookie))))
  1043.     {
  1044.         if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY)
  1045.         EMSG(_(e_endtry));
  1046.         else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE)
  1047.         EMSG(_(e_endwhile));
  1048.         else
  1049.         EMSG(_(e_endif));
  1050.     }
  1051.  
  1052.     /*
  1053.      * Reset "trylevel" in case of a ":finish" or ":return" or a missing
  1054.      * ":endtry" in a sourced file or executed function.  If the try
  1055.      * conditional is in its finally clause, ignore anything pending.
  1056.      * If it is in a catch clause, finish the caught exception.
  1057.      */
  1058.     do
  1059.         cstack.cs_idx = cleanup_conditionals(&cstack, 0, TRUE);
  1060.     while (--cstack.cs_idx >= 0);
  1061.     trylevel = initial_trylevel;
  1062.     }
  1063.  
  1064.     /* If a missing ":endtry", ":endwhile", or ":endif" or a memory lack
  1065.      * was reported above and the error message is to be converted to an
  1066.      * exception, do this now after rewinding the cstack. */
  1067.     do_errthrow(&cstack, getline == get_func_line
  1068.                   ? (char_u *)"endfunction" : (char_u *)NULL);
  1069.  
  1070.     if (trylevel == 0)
  1071.     {
  1072.     /*
  1073.      * When an exception is being thrown out of the outermost try
  1074.      * conditional, discard the uncaught exception, disable the conversion
  1075.      * of interrupts or errors to exceptions, and ensure that no more
  1076.      * commands are executed.
  1077.      */
  1078.     if (did_throw)
  1079.     {
  1080.         void    *p = NULL;
  1081.         char_u    *saved_sourcing_name;
  1082.         int        saved_sourcing_lnum;
  1083.         struct msglist    *messages = NULL, *next;
  1084.  
  1085.         /*
  1086.          * If the uncaught exception is a user exception, report it as an
  1087.          * error.  If it is an error exception, display the saved error
  1088.          * message now.  For an interrupt exception, do nothing; the
  1089.          * interrupt message is given elsewhere.
  1090.          */
  1091.         switch (current_exception->type)
  1092.         {
  1093.         case ET_USER:
  1094.             sprintf((char *)IObuff, _("E605: Exception not caught: %s"),
  1095.                 current_exception->value);
  1096.             p = vim_strsave(IObuff);
  1097.             break;
  1098.         case ET_ERROR:
  1099.             messages = current_exception->messages;
  1100.             current_exception->messages = NULL;
  1101.             break;
  1102.         case ET_INTERRUPT:
  1103.             break;
  1104.         default:
  1105.             p = vim_strsave((char_u *)_(e_internal));
  1106.         }
  1107.  
  1108.         saved_sourcing_name = sourcing_name;
  1109.         saved_sourcing_lnum = sourcing_lnum;
  1110.         sourcing_name = current_exception->throw_name;
  1111.         sourcing_lnum = current_exception->throw_lnum;
  1112.         current_exception->throw_name = NULL;
  1113.  
  1114.         discard_current_exception();    /* uses IObuff if 'verbose' */
  1115.         suppress_errthrow = TRUE;
  1116.         force_abort = TRUE;
  1117.  
  1118.         if (messages != NULL)
  1119.         {
  1120.         do
  1121.         {
  1122.             next = messages->next;
  1123.             emsg(messages->msg);
  1124.             vim_free(messages->msg);
  1125.             vim_free(messages);
  1126.             messages = next;
  1127.         }
  1128.         while (messages != NULL);
  1129.         }
  1130.         else if (p != NULL)
  1131.         {
  1132.         emsg(p);
  1133.         vim_free(p);
  1134.         }
  1135.         sourcing_name = saved_sourcing_name;
  1136.         sourcing_lnum = saved_sourcing_lnum;
  1137.     }
  1138.  
  1139.     /*
  1140.      * On an interrupt or an aborting error not converted to an exception,
  1141.      * disable the conversion of errors to exceptions.  (Interrupts are not
  1142.      * converted any more, here.) This enables also the interrupt message
  1143.      * when force_abort is set and did_emsg unset in case of an interrupt
  1144.      * from a finally clause after an error.
  1145.      */
  1146.     else if (got_int || (did_emsg && force_abort))
  1147.         suppress_errthrow = TRUE;
  1148.     }
  1149.  
  1150.     /*
  1151.      * The current cstack will be freed when do_cmdline() returns.  An uncaught
  1152.      * exception will have to be rethrown in the previous cstack.  If a function
  1153.      * has just returned or a script file was just finished and the previous
  1154.      * cstack belongs to the same function or, respectively, script file, it
  1155.      * will have to be checked for finally clauses to be executed due to the
  1156.      * ":return" or ":finish".  This is done in do_one_cmd().
  1157.      */
  1158.     if (did_throw)
  1159.     need_rethrow = TRUE;
  1160.     if ((getline == getsourceline
  1161.         && ex_nesting_level > source_level(cookie))
  1162.         || (getline == get_func_line
  1163.         && ex_nesting_level > func_level(cookie) + 1))
  1164.     {
  1165.     if (!did_throw)
  1166.         check_cstack = TRUE;
  1167.     }
  1168.     else
  1169.     {
  1170.     /* When leaving a function, reduce nesting level. */
  1171.     if (getline == get_func_line)
  1172.         --ex_nesting_level;
  1173.     /*
  1174.      * Go to debug mode when returning from a function in which we are
  1175.      * single-stepping.
  1176.      */
  1177.     if ((getline == getsourceline || getline == get_func_line)
  1178.         && ex_nesting_level + 1 <= debug_break_level)
  1179.         do_debug(getline == getsourceline
  1180.             ? (char_u *)_("End of sourced file")
  1181.             : (char_u *)_("End of function"));
  1182.     }
  1183.  
  1184.     /*
  1185.      * Restore the exception environment (done after returning from the
  1186.      * debugger).
  1187.      */
  1188.     if (flags & DOCMD_EXCRESET)
  1189.     {
  1190.     suppress_errthrow = FALSE;
  1191.     trylevel = saved_trylevel;
  1192.     force_abort = saved_force_abort;
  1193.     caught_stack = saved_caught_stack;
  1194.     (void)v_exception(saved_vv_exception);
  1195.     (void)v_throwpoint(saved_vv_throwpoint);
  1196.     /* Necessary for debugging an inactive ":catch", ":finally", or
  1197.      * ":endtry": */
  1198.     did_emsg = saved_did_emsg;
  1199.     got_int = saved_got_int;
  1200.     did_throw = saved_did_throw;
  1201.     need_rethrow = saved_need_rethrow;
  1202.     check_cstack = saved_check_cstack;
  1203.     current_exception = saved_current_exception;
  1204.     }
  1205.  
  1206.     msg_list = saved_msg_list;
  1207. #endif /* FEAT_EVAL */
  1208.  
  1209.     /*
  1210.      * If there was too much output to fit on the command line, ask the user to
  1211.      * hit return before redrawing the screen. With the ":global" command we do
  1212.      * this only once after the command is finished.
  1213.      */
  1214.     if (did_inc)
  1215.     {
  1216.     --RedrawingDisabled;
  1217.     --no_wait_return;
  1218.     msg_scroll = FALSE;
  1219.  
  1220.     /*
  1221.      * When just finished an ":if"-":else" which was typed, no need to
  1222.      * wait for hit-return.  Also for an error situation.
  1223.      */
  1224.     if (retval == FAIL
  1225. #ifdef FEAT_EVAL
  1226.         || (did_endif && KeyTyped && !did_emsg)
  1227. #endif
  1228.                         )
  1229.     {
  1230.         need_wait_return = FALSE;
  1231.         msg_didany = FALSE;        /* don't wait when restarting edit */
  1232.     }
  1233.     else if (need_wait_return)
  1234.     {
  1235.         /*
  1236.          * The msg_start() above clears msg_didout. The wait_return we do
  1237.          * here should not overwrite the command that may be shown before
  1238.          * doing that.
  1239.          */
  1240.         msg_didout |= msg_didout_before_start;
  1241.         wait_return(FALSE);
  1242.     }
  1243.     }
  1244.  
  1245. #ifndef FEAT_EVAL
  1246.     /*
  1247.      * Reset if_level, in case a sourced script file contains more ":if" than
  1248.      * ":endif" (could be ":if x | foo | endif").
  1249.      */
  1250.     if_level = 0;
  1251. #endif
  1252.  
  1253.     --call_depth;
  1254.     return retval;
  1255. }
  1256.  
  1257. #ifdef FEAT_EVAL
  1258.     static void
  1259. free_cmdlines(gap)
  1260.     garray_T    *gap;
  1261. {
  1262.     while (gap->ga_len > 0)
  1263.     {
  1264.     vim_free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line);
  1265.     --gap->ga_len;
  1266.     ++gap->ga_room;
  1267.     }
  1268. }
  1269. #endif
  1270.  
  1271. /*
  1272.  * Execute one Ex command.
  1273.  *
  1274.  * If 'sourcing' is TRUE, the command will be included in the error message.
  1275.  *
  1276.  * 1. skip comment lines and leading space
  1277.  * 2. handle command modifiers
  1278.  * 3. parse range
  1279.  * 4. parse command
  1280.  * 5. parse arguments
  1281.  * 6. switch on command name
  1282.  *
  1283.  * Note: "getline" can be NULL.
  1284.  *
  1285.  * This function may be called recursively!
  1286.  */
  1287. #if (_MSC_VER == 1200)
  1288. /*
  1289.  * Optimisation bug in VC++ version 6.0
  1290.  * TODO: check this is still present after each service pack
  1291.  */
  1292. #pragma optimize( "g", off )
  1293. #endif
  1294.     static char_u *
  1295. do_one_cmd(cmdlinep, sourcing,
  1296. #ifdef FEAT_EVAL
  1297.                 cstack,
  1298. #endif
  1299.                     getline, cookie)
  1300.     char_u        **cmdlinep;
  1301.     int            sourcing;
  1302. #ifdef FEAT_EVAL
  1303.     struct condstack    *cstack;
  1304. #endif
  1305.     char_u        *(*getline) __ARGS((int, void *, int));
  1306.     void        *cookie;        /* argument for getline() */
  1307. {
  1308.     char_u        *p;
  1309.     linenr_T        lnum;
  1310.     long        n;
  1311.     char_u        *errormsg = NULL;    /* error message */
  1312.     exarg_T        ea;            /* Ex command arguments */
  1313.     long        verbose_save = -1;
  1314.     int            save_msg_scroll = 0;
  1315.     int            did_silent = 0;
  1316.     int            did_esilent = 0;
  1317.     cmdmod_T        save_cmdmod;
  1318.     int            ni;            /* set when Not Implemented */
  1319.  
  1320.     vim_memset(&ea, 0, sizeof(ea));
  1321.     ea.line1 = 1;
  1322.     ea.line2 = 1;
  1323. #ifdef FEAT_EVAL
  1324.     ++ex_nesting_level;
  1325. #endif
  1326.  
  1327.     /* when not editing the last file :q has to be typed twice */
  1328.     if (quitmore
  1329. #ifdef FEAT_EVAL
  1330.         /* avoid that a function call in 'statusline' does this */
  1331.         && getline != get_func_line
  1332. #endif
  1333.         )
  1334.     --quitmore;
  1335.  
  1336.     /*
  1337.      * Reset browse, confirm, etc..  They are restored when returning, for
  1338.      * recursive calls.
  1339.      */
  1340.     save_cmdmod = cmdmod;
  1341.     vim_memset(&cmdmod, 0, sizeof(cmdmod));
  1342.  
  1343.     /*
  1344.      * Repeat until no more command modifiers are found.
  1345.      */
  1346.     ea.cmd = *cmdlinep;
  1347.     for (;;)
  1348.     {
  1349. /*
  1350.  * 1. skip comment lines and leading white space and colons
  1351.  */
  1352.     while (*ea.cmd == ' ' || *ea.cmd == '\t' || *ea.cmd == ':')
  1353.         ++ea.cmd;
  1354.  
  1355.     /* in ex mode, an empty line works like :+ */
  1356.     if (*ea.cmd == NUL && exmode_active
  1357.             && (getline == getexmodeline || getline == getexline))
  1358.     {
  1359.         ea.cmd = (char_u *)"+";
  1360.         ex_pressedreturn = TRUE;
  1361.     }
  1362.  
  1363.     /* ignore comment and empty lines */
  1364.     if (*ea.cmd == '"' || *ea.cmd == NUL)
  1365.         goto doend;
  1366.  
  1367. /*
  1368.  * 2. handle command modifiers.
  1369.  */
  1370.     p = ea.cmd;
  1371.     if (isdigit(*ea.cmd))
  1372.         p = skipwhite(skipdigits(ea.cmd));
  1373.     switch (*p)
  1374.     {
  1375.         case 'a':    if (!checkforcmd(&ea.cmd, "aboveleft", 3))
  1376.                 break;
  1377. #ifdef FEAT_WINDOWS
  1378.             cmdmod.split |= WSP_ABOVE;
  1379. #endif
  1380.             continue;
  1381.  
  1382.         case 'b':    if (checkforcmd(&ea.cmd, "belowright", 3))
  1383.             {
  1384. #ifdef FEAT_WINDOWS
  1385.                 cmdmod.split |= WSP_BELOW;
  1386. #endif
  1387.                 continue;
  1388.             }
  1389.             if (checkforcmd(&ea.cmd, "browse", 3))
  1390.             {
  1391. #ifdef FEAT_BROWSE
  1392.                 cmdmod.browse = TRUE;
  1393. #endif
  1394.                 continue;
  1395.             }
  1396.             if (!checkforcmd(&ea.cmd, "botright", 2))
  1397.                 break;
  1398. #ifdef FEAT_WINDOWS
  1399.             cmdmod.split |= WSP_BOT;
  1400. #endif
  1401.             continue;
  1402.  
  1403.         case 'c':    if (!checkforcmd(&ea.cmd, "confirm", 4))
  1404.                 break;
  1405. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  1406.             cmdmod.confirm = TRUE;
  1407. #endif
  1408.             continue;
  1409.  
  1410.             /* ":hide" and ":hide | cmd" are not modifiers */
  1411.         case 'h':    if (p != ea.cmd || !checkforcmd(&p, "hide", 3)
  1412.                            || *p == NUL || ends_excmd(*p))
  1413.                 break;
  1414.             ea.cmd = p;
  1415.             cmdmod.hide = TRUE;
  1416.             continue;
  1417.  
  1418.         case 'l':    if (!checkforcmd(&ea.cmd, "leftabove", 5))
  1419.                 break;
  1420. #ifdef FEAT_WINDOWS
  1421.             cmdmod.split |= WSP_ABOVE;
  1422. #endif
  1423.             continue;
  1424.  
  1425.         case 'r':    if (!checkforcmd(&ea.cmd, "rightbelow", 6))
  1426.                 break;
  1427. #ifdef FEAT_WINDOWS
  1428.             cmdmod.split |= WSP_BELOW;
  1429. #endif
  1430.             continue;
  1431.  
  1432.         case 's':    if (!checkforcmd(&ea.cmd, "silent", 3))
  1433.                 break;
  1434.             ++did_silent;
  1435.             ++msg_silent;
  1436.             save_msg_scroll = msg_scroll;
  1437.             if (*ea.cmd == '!' && !vim_iswhite(ea.cmd[-1]))
  1438.             {
  1439.                 /* ":silent!", but not "silent !cmd" */
  1440.                 ea.cmd = skipwhite(ea.cmd + 1);
  1441.                 ++emsg_silent;
  1442.                 ++did_esilent;
  1443.             }
  1444.             continue;
  1445.  
  1446.         case 't':    if (!checkforcmd(&ea.cmd, "topleft", 2))
  1447.                 break;
  1448. #ifdef FEAT_WINDOWS
  1449.             cmdmod.split |= WSP_TOP;
  1450. #endif
  1451.             continue;
  1452.  
  1453.         case 'v':    if (checkforcmd(&ea.cmd, "vertical", 4))
  1454.             {
  1455. #ifdef FEAT_VERTSPLIT
  1456.                 cmdmod.split |= WSP_VERT;
  1457. #endif
  1458.                 continue;
  1459.             }
  1460.             if (!checkforcmd(&p, "verbose", 4))
  1461.                 break;
  1462.             if (verbose_save < 0)
  1463.                 verbose_save = p_verbose;
  1464.             p_verbose = atoi((char *)ea.cmd);
  1465.             if (p_verbose == 0)
  1466.                 p_verbose = 1;
  1467.             ea.cmd = p;
  1468.             continue;
  1469.     }
  1470.     break;
  1471.     }
  1472.  
  1473. #ifdef FEAT_EVAL
  1474.     ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0
  1475.              && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE));
  1476. #else
  1477.     ea.skip = (if_level > 0);
  1478. #endif
  1479.  
  1480. #ifdef FEAT_EVAL
  1481.     /* May go to debug mode.  If this happens and the ">quit" debug command is
  1482.      * used, throw an interrupt exception and skip the next command. */
  1483.     dbg_check_breakpoint(&ea);
  1484.     if (!ea.skip && got_int)
  1485.     {
  1486.     ea.skip = TRUE;
  1487.     (void)do_intthrow(cstack);
  1488.     }
  1489. #endif
  1490.  
  1491. /*
  1492.  * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
  1493.  *
  1494.  * where 'addr' is:
  1495.  *
  1496.  * %          (entire file)
  1497.  * $  [+-NUM]
  1498.  * 'x [+-NUM] (where x denotes a currently defined mark)
  1499.  * .  [+-NUM]
  1500.  * [+-NUM]..
  1501.  * NUM
  1502.  *
  1503.  * The ea.cmd pointer is updated to point to the first character following the
  1504.  * range spec. If an initial address is found, but no second, the upper bound
  1505.  * is equal to the lower.
  1506.  */
  1507.  
  1508.     /* repeat for all ',' or ';' separated addresses */
  1509.     for (;;)
  1510.     {
  1511.     ea.line1 = ea.line2;
  1512.     ea.line2 = curwin->w_cursor.lnum;   /* default is current line number */
  1513.     ea.cmd = skipwhite(ea.cmd);
  1514.     lnum = get_address(&ea.cmd, ea.skip, ea.addr_count == 0);
  1515.     if (ea.cmd == NULL)            /* error detected */
  1516.         goto doend;
  1517.     if (lnum == MAXLNUM)
  1518.     {
  1519.         if (*ea.cmd == '%')            /* '%' - all lines */
  1520.         {
  1521.         ++ea.cmd;
  1522.         ea.line1 = 1;
  1523.         ea.line2 = curbuf->b_ml.ml_line_count;
  1524.         ++ea.addr_count;
  1525.         }
  1526.                         /* '*' - visual area */
  1527.         else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
  1528.         {
  1529.         pos_T        *fp;
  1530.  
  1531.         ++ea.cmd;
  1532.         if (!ea.skip)
  1533.         {
  1534.             fp = getmark('<', FALSE);
  1535.             if (check_mark(fp) == FAIL)
  1536.             goto doend;
  1537.             ea.line1 = fp->lnum;
  1538.             fp = getmark('>', FALSE);
  1539.             if (check_mark(fp) == FAIL)
  1540.             goto doend;
  1541.             ea.line2 = fp->lnum;
  1542.             ++ea.addr_count;
  1543.         }
  1544.         }
  1545.     }
  1546.     else
  1547.         ea.line2 = lnum;
  1548.     ea.addr_count++;
  1549.  
  1550.     if (*ea.cmd == ';')
  1551.     {
  1552.         if (!ea.skip)
  1553.         curwin->w_cursor.lnum = ea.line2;
  1554.     }
  1555.     else if (*ea.cmd != ',')
  1556.         break;
  1557.     ++ea.cmd;
  1558.     }
  1559.  
  1560.     /* One address given: set start and end lines */
  1561.     if (ea.addr_count == 1)
  1562.     {
  1563.     ea.line1 = ea.line2;
  1564.         /* ... but only implicit: really no address given */
  1565.     if (lnum == MAXLNUM)
  1566.         ea.addr_count = 0;
  1567.     }
  1568.  
  1569.     /* Don't leave the cursor on an illegal line (caused by ';') */
  1570.     check_cursor_lnum();
  1571.  
  1572. /*
  1573.  * 4. parse command
  1574.  */
  1575.  
  1576.     /*
  1577.      * Skip ':' and any white space
  1578.      */
  1579.     ea.cmd = skipwhite(ea.cmd);
  1580.     while (*ea.cmd == ':')
  1581.     ea.cmd = skipwhite(ea.cmd + 1);
  1582.  
  1583.     /*
  1584.      * If we got a line, but no command, then go to the line.
  1585.      * If we find a '|' or '\n' we set ea.nextcmd.
  1586.      */
  1587.     if (*ea.cmd == NUL || *ea.cmd == '"' ||
  1588.                    (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
  1589.     {
  1590.     /*
  1591.      * strange vi behaviour:
  1592.      * ":3"        jumps to line 3
  1593.      * ":3|..."    prints line 3
  1594.      * ":|"        prints current line
  1595.      */
  1596.     if (ea.skip)        /* skip this if inside :if */
  1597.         goto doend;
  1598.     if (*ea.cmd == '|')
  1599.     {
  1600.         ea.cmdidx = CMD_print;
  1601.         ea.argt = RANGE+COUNT+TRLBAR;
  1602.         if ((errormsg = invalid_range(&ea)) == NULL)
  1603.         {
  1604.         correct_range(&ea);
  1605.         ex_print(&ea);
  1606.         }
  1607.     }
  1608.     else if (ea.addr_count != 0)
  1609.     {
  1610.         if (ea.line2 < 0)
  1611.         errormsg = invalid_range(&ea);
  1612.         else
  1613.         {
  1614.         if (ea.line2 == 0)
  1615.             curwin->w_cursor.lnum = 1;
  1616.         else if (ea.line2 > curbuf->b_ml.ml_line_count)
  1617.             curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  1618.         else
  1619.             curwin->w_cursor.lnum = ea.line2;
  1620.         beginline(BL_SOL | BL_FIX);
  1621.         }
  1622.     }
  1623.     goto doend;
  1624.     }
  1625.  
  1626.     /* Find the command and let "p" point to after it. */
  1627.     p = find_command(&ea, NULL);
  1628.  
  1629. #ifdef FEAT_USR_CMDS
  1630.     if (p == NULL)
  1631.     {
  1632.     if (!ea.skip)
  1633.         errormsg = (char_u *)_("E464: Ambiguous use of user-defined command");
  1634.     goto doend;
  1635.     }
  1636.     /* Check for wrong commands. */
  1637.     if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78)
  1638.     {
  1639.     errormsg = uc_fun_cmd();
  1640.     goto doend;
  1641.     }
  1642. #endif
  1643.     if (ea.cmdidx == CMD_SIZE)
  1644.     {
  1645.     if (!ea.skip)
  1646.     {
  1647.         STRCPY(IObuff, _("E492: Not an editor command"));
  1648.         if (!sourcing)
  1649.         {
  1650.         STRCAT(IObuff, ": ");
  1651.         STRNCAT(IObuff, *cmdlinep, 40);
  1652.         }
  1653.         errormsg = IObuff;
  1654.     }
  1655.     goto doend;
  1656.     }
  1657.  
  1658.     ni = (
  1659. #ifdef FEAT_USR_CMDS
  1660.         !USER_CMDIDX(ea.cmdidx) &&
  1661. #endif
  1662.         cmdnames[ea.cmdidx].cmd_func == ex_ni);
  1663.  
  1664. #ifndef FEAT_EVAL
  1665.     /*
  1666.      * When the expression evaluation is disabled, recognize the ":if" and
  1667.      * ":endif" commands and ignore everything in between it.
  1668.      */
  1669.     if (ea.cmdidx == CMD_if)
  1670.     ++if_level;
  1671.     if (if_level)
  1672.     {
  1673.     if (ea.cmdidx == CMD_endif)
  1674.         --if_level;
  1675.     goto doend;
  1676.     }
  1677.  
  1678. #endif
  1679.  
  1680.     if (*p == '!' && ea.cmdidx != CMD_substitute)    /* forced commands */
  1681.     {
  1682.     ++p;
  1683.     ea.forceit = TRUE;
  1684.     }
  1685.     else
  1686.     ea.forceit = FALSE;
  1687.  
  1688. /*
  1689.  * 5. parse arguments
  1690.  */
  1691. #ifdef FEAT_USR_CMDS
  1692.     if (!USER_CMDIDX(ea.cmdidx))
  1693. #endif
  1694.     ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
  1695.  
  1696.     if (!ea.skip)
  1697.     {
  1698. #ifdef HAVE_SANDBOX
  1699.     if (sandbox != 0 && !(ea.argt & SBOXOK))
  1700.     {
  1701.         /* Command not allowed in sandbox. */
  1702.         errormsg = (char_u *)_(e_sandbox);
  1703.         goto doend;
  1704.     }
  1705. #endif
  1706.     if (!curbuf->b_p_ma && (ea.argt & MODIFY))
  1707.     {
  1708.         /* Command not allowed in non-'modifiable' buffer */
  1709.         errormsg = (char_u *)_(e_modifiable);
  1710.         goto doend;
  1711.     }
  1712. #ifdef FEAT_CMDWIN
  1713.     if (cmdwin_type != 0 && !(ea.argt & CMDWIN)
  1714. # ifdef FEAT_USR_CMDS
  1715.         && !USER_CMDIDX(ea.cmdidx)
  1716. # endif
  1717.        )
  1718.     {
  1719.         /* Command not allowed in cmdline window. */
  1720.         errormsg = (char_u *)_(e_cmdwin);
  1721.         goto doend;
  1722.     }
  1723. #endif
  1724.  
  1725.     if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0)
  1726.     {
  1727.         /* no range allowed */
  1728.         errormsg = (char_u *)_(e_norange);
  1729.         goto doend;
  1730.     }
  1731.     }
  1732.  
  1733.     if (!ni && !(ea.argt & BANG) && ea.forceit)    /* no <!> allowed */
  1734.     {
  1735.     errormsg = (char_u *)_(e_nobang);
  1736.     if (ea.cmdidx == CMD_help)
  1737.         errormsg = (char_u *)_("E478: Don't panic!");
  1738.     goto doend;
  1739.     }
  1740.  
  1741.     /*
  1742.      * Don't complain about the range if it is not used
  1743.      * (could happen if line_count is accidentally set to 0).
  1744.      */
  1745.     if (!ea.skip && !ni)
  1746.     {
  1747.     /*
  1748.      * If the range is backwards, ask for confirmation and, if given, swap
  1749.      * ea.line1 & ea.line2 so it's forwards again.
  1750.      * When global command is busy, don't ask, will fail below.
  1751.      */
  1752.     if (!global_busy && ea.line1 > ea.line2)
  1753.     {
  1754.         if (sourcing)
  1755.         {
  1756.         errormsg = (char_u *)_("E493: Backwards range given");
  1757.         goto doend;
  1758.         }
  1759.         else
  1760.         {
  1761.         int    msg_silent_save = msg_silent;
  1762.  
  1763.         msg_silent = 0;
  1764.         if (ask_yesno((char_u *)
  1765.             _("Backwards range given, OK to swap"), FALSE) != 'y')
  1766.         goto doend;
  1767.         msg_silent = msg_silent_save;
  1768.         }
  1769.         lnum = ea.line1;
  1770.         ea.line1 = ea.line2;
  1771.         ea.line2 = lnum;
  1772.     }
  1773.     if ((errormsg = invalid_range(&ea)) != NULL)
  1774.         goto doend;
  1775.     }
  1776.  
  1777.     if ((ea.argt & NOTADR) && ea.addr_count == 0) /* default is 1, not cursor */
  1778.     ea.line2 = 1;
  1779.  
  1780.     correct_range(&ea);
  1781.  
  1782. #ifdef FEAT_FOLDING
  1783.     if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy)
  1784.     {
  1785.     /* Put the first line at the start of a closed fold, put the last line
  1786.      * at the end of a closed fold. */
  1787.     (void)hasFolding(ea.line1, &ea.line1, NULL);
  1788.     (void)hasFolding(ea.line2, NULL, &ea.line2);
  1789.     }
  1790. #endif
  1791.  
  1792. #ifdef FEAT_QUICKFIX
  1793.     /*
  1794.      * For the :make and :grep commands we insert the 'makeprg'/'grepprg'
  1795.      * option here, so things like % get expanded.
  1796.      */
  1797.     if (ea.cmdidx == CMD_make || ea.cmdidx == CMD_grep
  1798.                           || ea.cmdidx == CMD_grepadd)
  1799.     {
  1800.     char_u        *new_cmdline;
  1801.     char_u        *program;
  1802.     char_u        *pos;
  1803.     char_u        *ptr;
  1804.     int        len;
  1805.     int        i;
  1806.  
  1807.     if (ea.cmdidx == CMD_grep || ea.cmdidx == CMD_grepadd)
  1808.     {
  1809.         if (*curbuf->b_p_gp == NUL)
  1810.         program = p_gp;
  1811.         else
  1812.         program = curbuf->b_p_gp;
  1813.     }
  1814.     else
  1815.     {
  1816.         if (*curbuf->b_p_mp == NUL)
  1817.         program = p_mp;
  1818.         else
  1819.         program = curbuf->b_p_mp;
  1820.     }
  1821.  
  1822.     p = skipwhite(p);
  1823.  
  1824.     if ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
  1825.     {                /* replace $* by given arguments */
  1826.         i = 1;
  1827.         while ((pos = (char_u *)strstr((char *)pos + 2, "$*")) != NULL)
  1828.         ++i;
  1829.         len = (int)STRLEN(p);
  1830.         new_cmdline = alloc((int)(STRLEN(program) + i * (len - 2) + 1));
  1831.         if (new_cmdline == NULL)
  1832.         goto doend;            /* out of memory */
  1833.         ptr = new_cmdline;
  1834.         while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
  1835.         {
  1836.         i = (int)(pos - program);
  1837.         STRNCPY(ptr, program, i);
  1838.         STRCPY(ptr += i, p);
  1839.         ptr += len;
  1840.         program = pos + 2;
  1841.         }
  1842.         STRCPY(ptr, program);
  1843.     }
  1844.     else
  1845.     {
  1846.         new_cmdline = alloc((int)(STRLEN(program) + STRLEN(p) + 2));
  1847.         if (new_cmdline == NULL)
  1848.         goto doend;            /* out of memory */
  1849.         STRCPY(new_cmdline, program);
  1850.         STRCAT(new_cmdline, " ");
  1851.         STRCAT(new_cmdline, p);
  1852.     }
  1853.     msg_make(p);
  1854.     /* 'ea.cmd' is not set here, because it is not used at CMD_make */
  1855.     vim_free(*cmdlinep);
  1856.     *cmdlinep = new_cmdline;
  1857.     p = new_cmdline;
  1858.     }
  1859. #endif
  1860.  
  1861.     /*
  1862.      * Skip to start of argument.
  1863.      * Don't do this for the ":!" command, because ":!! -l" needs the space.
  1864.      */
  1865.     if (ea.cmdidx == CMD_bang)
  1866.     ea.arg = p;
  1867.     else
  1868.     ea.arg = skipwhite(p);
  1869.  
  1870.     if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
  1871.     {
  1872.     if (*ea.arg == '>')            /* append */
  1873.     {
  1874.         if (*++ea.arg != '>')        /* typed wrong */
  1875.         {
  1876.         errormsg = (char_u *)_("E494: Use w or w>>");
  1877.         goto doend;
  1878.         }
  1879.         ea.arg = skipwhite(ea.arg + 1);
  1880.         ea.append = TRUE;
  1881.     }
  1882.     else if (*ea.arg == '!' && ea.cmdidx == CMD_write)  /* :w !filter */
  1883.     {
  1884.         ++ea.arg;
  1885.         ea.usefilter = TRUE;
  1886.     }
  1887.     }
  1888.  
  1889.     if (ea.cmdidx == CMD_read)
  1890.     {
  1891.     if (ea.forceit)
  1892.     {
  1893.         ea.usefilter = TRUE;        /* :r! filter if ea.forceit */
  1894.         ea.forceit = FALSE;
  1895.     }
  1896.     else if (*ea.arg == '!')        /* :r !filter */
  1897.     {
  1898.         ++ea.arg;
  1899.         ea.usefilter = TRUE;
  1900.     }
  1901.     }
  1902.  
  1903.     if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift)
  1904.     {
  1905.     ea.amount = 1;
  1906.     while (*ea.arg == *ea.cmd)        /* count number of '>' or '<' */
  1907.     {
  1908.         ++ea.arg;
  1909.         ++ea.amount;
  1910.     }
  1911.     ea.arg = skipwhite(ea.arg);
  1912.     }
  1913.  
  1914.     /*
  1915.      * Check for "++opt=val" argument.
  1916.      */
  1917.     if (ea.argt & ARGOPT)
  1918.     while (ea.arg[0] == '+' && ea.arg[1] == '+')
  1919.         if (getargopt(&ea) == FAIL && !ni)
  1920.         {
  1921.         errormsg = (char_u *)_(e_invarg);
  1922.         goto doend;
  1923.         }
  1924.  
  1925.     /*
  1926.      * Check for "+command" argument, before checking for next command.
  1927.      * Don't do this for ":read !cmd" and ":write !cmd".
  1928.      */
  1929.     if ((ea.argt & EDITCMD) && !ea.usefilter)
  1930.     ea.do_ecmd_cmd = getargcmd(&ea.arg);
  1931.  
  1932.     /*
  1933.      * Check for '|' to separate commands and '"' to start comments.
  1934.      * Don't do this for ":read !cmd" and ":write !cmd".
  1935.      */
  1936.     if ((ea.argt & TRLBAR) && !ea.usefilter)
  1937.     separate_nextcmd(&ea);
  1938.  
  1939.     /*
  1940.      * Check for <newline> to end a shell command.
  1941.      * Also do this for ":read !cmd" and ":write !cmd".
  1942.      */
  1943.     else if (ea.cmdidx == CMD_bang || ea.usefilter)
  1944.     {
  1945.     for (p = ea.arg; *p; ++p)
  1946.     {
  1947.         /* Remove one backslash before a newline, so that it's possible to
  1948.          * pass a newline to the shell and also a newline that is preceded
  1949.          * with a backslash.  This makes it impossible to end a shell
  1950.          * command in a backslash, but that doesn't appear useful.
  1951.          * Halving the number of backslashes is incompatible with previous
  1952.          * versions. */
  1953.         if (*p == '\\' && p[1] == '\n')
  1954.         mch_memmove(p, p + 1, STRLEN(p));
  1955.         else if (*p == '\n')
  1956.         {
  1957.         ea.nextcmd = p + 1;
  1958.         *p = NUL;
  1959.         break;
  1960.         }
  1961.     }
  1962.     }
  1963.  
  1964.     if ((ea.argt & DFLALL) && ea.addr_count == 0)
  1965.     {
  1966.     ea.line1 = 1;
  1967.     ea.line2 = curbuf->b_ml.ml_line_count;
  1968.     }
  1969.  
  1970.     /* accept numbered register only when no count allowed (:put) */
  1971.     if (       (ea.argt & REGSTR)
  1972.         && *ea.arg != NUL
  1973. #ifdef FEAT_USR_CMDS
  1974.         && valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put
  1975.                            && USER_CMDIDX(ea.cmdidx)))
  1976.         /* Do not allow register = for user commands */
  1977.         && (!USER_CMDIDX(ea.cmdidx) || *ea.arg != '=')
  1978. #else
  1979.         && valid_yank_reg(*ea.arg, ea.cmdidx != CMD_put)
  1980. #endif
  1981.         && !((ea.argt & COUNT) && isdigit(*ea.arg)))
  1982.     {
  1983.     ea.regname = *ea.arg++;
  1984. #ifdef FEAT_EVAL
  1985.     /* for '=' register: accept the rest of the line as an expression */
  1986.     if (ea.arg[-1] == '=' && ea.arg[0] != NUL)
  1987.     {
  1988.         set_expr_line(vim_strsave(ea.arg));
  1989.         ea.arg += STRLEN(ea.arg);
  1990.     }
  1991. #endif
  1992.     ea.arg = skipwhite(ea.arg);
  1993.     }
  1994.  
  1995.     /*
  1996.      * Check for a count.  When accepting a BUFNAME, don't use "123foo" as a
  1997.      * count, it's a buffer name.
  1998.      */
  1999.     if ((ea.argt & COUNT) && isdigit(*ea.arg)
  2000.         && (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
  2001.                               || vim_iswhite(*p)))
  2002.     {
  2003.     n = getdigits(&ea.arg);
  2004.     ea.arg = skipwhite(ea.arg);
  2005.     if (n <= 0 && !ni)
  2006.     {
  2007.         errormsg = (char_u *)_(e_zerocount);
  2008.         goto doend;
  2009.     }
  2010.     if (ea.argt & NOTADR)    /* e.g. :buffer 2, :sleep 3 */
  2011.     {
  2012.         ea.line2 = n;
  2013.         if (ea.addr_count == 0)
  2014.         ea.addr_count = 1;
  2015.     }
  2016.     else
  2017.     {
  2018.         ea.line1 = ea.line2;
  2019.         ea.line2 += n - 1;
  2020.         ++ea.addr_count;
  2021.         /*
  2022.          * Be vi compatible: no error message for out of range.
  2023.          */
  2024.         if (ea.line2 > curbuf->b_ml.ml_line_count)
  2025.         ea.line2 = curbuf->b_ml.ml_line_count;
  2026.     }
  2027.     }
  2028.                         /* no arguments allowed */
  2029.     if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL &&
  2030.                  vim_strchr((char_u *)"|\"", *ea.arg) == NULL)
  2031.     {
  2032.     errormsg = (char_u *)_(e_trailing);
  2033.     goto doend;
  2034.     }
  2035.  
  2036.     if (!ni && (ea.argt & NEEDARG) && *ea.arg == NUL)
  2037.     {
  2038.     errormsg = (char_u *)_(e_argreq);
  2039.     goto doend;
  2040.     }
  2041.  
  2042. #ifdef FEAT_EVAL
  2043.     /*
  2044.      * Skip the command when it's not going to be executed.
  2045.      * The commands like :if, :endif, etc. always need to be executed.
  2046.      * Also make an exception for commands that handle a trailing command
  2047.      * themselves.
  2048.      */
  2049.     if (ea.skip)
  2050.     {
  2051.     switch (ea.cmdidx)
  2052.     {
  2053.         /* commands that need evaluation */
  2054.         case CMD_while:
  2055.         case CMD_endwhile:
  2056.         case CMD_if:
  2057.         case CMD_elseif:
  2058.         case CMD_else:
  2059.         case CMD_endif:
  2060.         case CMD_try:
  2061.         case CMD_catch:
  2062.         case CMD_finally:
  2063.         case CMD_endtry:
  2064.         case CMD_function:
  2065.                 break;
  2066.  
  2067.         /* Commands that handle '|' themselves.  Check: A command should
  2068.          * either have the TRLBAR flag, appear in this list or appear in
  2069.          * the list at ":help :bar". */
  2070.         case CMD_aboveleft:
  2071.         case CMD_and:
  2072.         case CMD_belowright:
  2073.         case CMD_botright:
  2074.         case CMD_browse:
  2075.         case CMD_call:
  2076.         case CMD_confirm:
  2077.         case CMD_delfunction:
  2078.         case CMD_djump:
  2079.         case CMD_dlist:
  2080.         case CMD_dsearch:
  2081.         case CMD_dsplit:
  2082.         case CMD_echo:
  2083.         case CMD_echoerr:
  2084.         case CMD_echomsg:
  2085.         case CMD_echon:
  2086.         case CMD_execute:
  2087.         case CMD_help:
  2088.         case CMD_hide:
  2089.         case CMD_ijump:
  2090.         case CMD_ilist:
  2091.         case CMD_isearch:
  2092.         case CMD_isplit:
  2093.         case CMD_leftabove:
  2094.         case CMD_let:
  2095.         case CMD_match:
  2096.         case CMD_psearch:
  2097.         case CMD_return:
  2098.         case CMD_throw:
  2099.         case CMD_rightbelow:
  2100.         case CMD_silent:
  2101.         case CMD_smagic:
  2102.         case CMD_snomagic:
  2103.         case CMD_substitute:
  2104.         case CMD_syntax:
  2105.         case CMD_tilde:
  2106.         case CMD_topleft:
  2107.         case CMD_unlet:
  2108.         case CMD_verbose:
  2109.         case CMD_vertical:
  2110.                 break;
  2111.  
  2112.         default:        goto doend;
  2113.     }
  2114.     }
  2115. #endif
  2116.  
  2117.     if (ea.argt & XFILE)
  2118.     {
  2119.     if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
  2120.         goto doend;
  2121.     }
  2122.  
  2123. #ifdef FEAT_LISTCMDS
  2124.     /*
  2125.      * Accept buffer name.  Cannot be used at the same time with a buffer
  2126.      * number.  Don't do this for a user command.
  2127.      */
  2128.     if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
  2129. # ifdef FEAT_USR_CMDS
  2130.         && !USER_CMDIDX(ea.cmdidx)
  2131. # endif
  2132.         )
  2133.     {
  2134.     /*
  2135.      * :bdelete, :bwipeout and :bunload take several arguments, separated
  2136.      * by spaces: find next space (skipping over escaped characters).
  2137.      * The others take one argument: ignore trailing spaces.
  2138.      */
  2139.     if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bwipeout
  2140.                           || ea.cmdidx == CMD_bunload)
  2141.         p = skiptowhite_esc(ea.arg);
  2142.     else
  2143.     {
  2144.         p = ea.arg + STRLEN(ea.arg);
  2145.         while (p > ea.arg && vim_iswhite(p[-1]))
  2146.         --p;
  2147.     }
  2148.     ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & BUFUNL) != 0, FALSE);
  2149.     if (ea.line2 < 0)        /* failed */
  2150.         goto doend;
  2151.     ea.addr_count = 1;
  2152.     ea.arg = skipwhite(p);
  2153.     }
  2154. #endif
  2155.  
  2156. /*
  2157.  * 6. switch on command name
  2158.  *
  2159.  * The "ea" structure holds the arguments that can be used.
  2160.  */
  2161.     ea.cmdlinep = cmdlinep;
  2162.     ea.getline = getline;
  2163.     ea.cookie = cookie;
  2164. #ifdef FEAT_EVAL
  2165.     ea.cstack = cstack;
  2166. #endif
  2167.  
  2168. #ifdef FEAT_USR_CMDS
  2169.     if (USER_CMDIDX(ea.cmdidx))
  2170.     {
  2171.     /*
  2172.      * Execute a user-defined command.
  2173.      */
  2174.     do_ucmd(&ea);
  2175.     }
  2176.     else
  2177. #endif
  2178.     {
  2179.     /*
  2180.      * Call the function to execute the command.
  2181.      */
  2182.     ea.errmsg = NULL;
  2183.     (cmdnames[ea.cmdidx].cmd_func)(&ea);
  2184.     if (ea.errmsg != NULL)
  2185.         errormsg = (char_u *)_(ea.errmsg);
  2186.     }
  2187.  
  2188. #ifdef FEAT_EVAL
  2189.     /*
  2190.      * If the command just executed called do_cmdline(), any throw or ":return"
  2191.      * or ":finish" encountered there must also check the cstack of the still
  2192.      * active do_cmdline() that called this do_one_cmd().  Rethrow an uncaught
  2193.      * exception, or reanimate a returned function or finished script file and
  2194.      * return or finish it again.
  2195.      */
  2196.     if (need_rethrow)
  2197.     do_throw(cstack);
  2198.     else if (check_cstack)
  2199.     {
  2200.     if (getline == getsourceline && source_finished(cookie))
  2201.         do_finish(&ea, TRUE);
  2202.     else if (getline == get_func_line && current_func_returned())
  2203.         do_return(&ea, TRUE, FALSE, NULL);
  2204.     }
  2205.     need_rethrow = check_cstack = FALSE;
  2206. #endif
  2207.  
  2208. doend:
  2209.     if (curwin->w_cursor.lnum == 0)    /* can happen with zero line number */
  2210.     curwin->w_cursor.lnum = 1;
  2211.  
  2212.     if (errormsg != NULL && *errormsg != NUL && !did_emsg)
  2213.     {
  2214.     if (sourcing)
  2215.     {
  2216.         if (errormsg != IObuff)
  2217.         {
  2218.         STRCPY(IObuff, errormsg);
  2219.         errormsg = IObuff;
  2220.         }
  2221.         STRCAT(errormsg, ": ");
  2222.         STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff));
  2223.     }
  2224.     emsg(errormsg);
  2225.     }
  2226. #ifdef FEAT_EVAL
  2227.     do_errthrow(cstack,
  2228.         (ea.cmdidx != CMD_SIZE
  2229. # ifdef FEAT_USR_CMDS
  2230.          && !USER_CMDIDX(ea.cmdidx)
  2231. # endif
  2232.         ) ? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
  2233. #endif
  2234.  
  2235.     if (verbose_save >= 0)
  2236.     p_verbose = verbose_save;
  2237.  
  2238.     cmdmod = save_cmdmod;
  2239.  
  2240.     if (did_silent > 0)
  2241.     {
  2242.     /* messages could be enabled for a serious error, need to check if the
  2243.      * counters don't become negative */
  2244.     msg_silent -= did_silent;
  2245.     if (msg_silent < 0)
  2246.         msg_silent = 0;
  2247.     emsg_silent -= did_esilent;
  2248.     if (emsg_silent < 0)
  2249.         emsg_silent = 0;
  2250.     /* Restore msg_scroll, it's set by file I/O commands, even when no
  2251.      * message is actually displayed. */
  2252.     msg_scroll = save_msg_scroll;
  2253.     }
  2254.  
  2255.     if (ea.nextcmd && *ea.nextcmd == NUL)    /* not really a next command */
  2256.     ea.nextcmd = NULL;
  2257.  
  2258. #ifdef FEAT_EVAL
  2259.     --ex_nesting_level;
  2260. #endif
  2261.  
  2262.     return ea.nextcmd;
  2263. }
  2264. #if (_MSC_VER == 1200)
  2265. #pragma optimize( "", on )
  2266. #endif
  2267.  
  2268. /*
  2269.  * Check for a command modifier command with optional tail.
  2270.  * If there is a match advance "pp" to the argument and return TRUE.
  2271.  */
  2272.     static int
  2273. checkforcmd(pp, cmd, len)
  2274.     char_u    **pp;        /* start of command line */
  2275.     char    *cmd;        /* name of command */
  2276.     int        len;        /* required length */
  2277. {
  2278.     int        i;
  2279.  
  2280.     for (i = 0; cmd[i] != NUL; ++i)
  2281.     if (cmd[i] != (*pp)[i])
  2282.         break;
  2283.     if (i >= len && !isalpha((*pp)[i]))
  2284.     {
  2285.     *pp = skipwhite(*pp + i);
  2286.     return TRUE;
  2287.     }
  2288.     return FALSE;
  2289. }
  2290.  
  2291. /*
  2292.  * Find an Ex command by its name, either built-in or user.
  2293.  * Name can be found at eap->cmd.
  2294.  * Returns pointer to char after the command name.
  2295.  * Returns NULL for an ambiguous user command.
  2296.  */
  2297. /*ARGSUSED*/
  2298.     static char_u *
  2299. find_command(eap, full)
  2300.     exarg_T    *eap;
  2301.     int        *full;
  2302. {
  2303.     int        len;
  2304.     char_u    *p;
  2305.  
  2306.     /*
  2307.      * Isolate the command and search for it in the command table.
  2308.      * Exeptions:
  2309.      * - the 'k' command can directly be followed by any character.
  2310.      * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
  2311.      *        but :sre[wind] is another command, as are :scrip[tnames],
  2312.      *        :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
  2313.      */
  2314.     p = eap->cmd;
  2315.     if (*p == 'k')
  2316.     {
  2317.     eap->cmdidx = CMD_k;
  2318.     ++p;
  2319.     }
  2320.     else if (p[0] == 's'
  2321.         && ((p[1] == 'c' && p[2] != 's' && p[2] != 'r' && p[3] != 'i' && p[4] != 'p')
  2322.         || p[1] == 'g'
  2323.         || (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
  2324.         || p[1] == 'I'
  2325.         || (p[1] == 'r' && p[2] != 'e')))
  2326.     {
  2327.     eap->cmdidx = CMD_substitute;
  2328.     ++p;
  2329.     }
  2330.     else
  2331.     {
  2332.     while (ASCII_ISALPHA(*p))
  2333.         ++p;
  2334.     /* check for non-alpha command */
  2335.     if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
  2336.         ++p;
  2337.     len = (int)(p - eap->cmd);
  2338.  
  2339.     if (ASCII_ISLOWER(*eap->cmd))
  2340.         eap->cmdidx = cmdidxs[CharOrdLow(*eap->cmd)];
  2341.     else
  2342.         eap->cmdidx = cmdidxs[26];
  2343.  
  2344.     for ( ; (int)eap->cmdidx < (int)CMD_SIZE;
  2345.                    eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1))
  2346.         if (STRNCMP(cmdnames[(int)eap->cmdidx].cmd_name, (char *)eap->cmd,
  2347.                                 (size_t)len) == 0)
  2348.         {
  2349. #ifdef FEAT_EVAL
  2350.         if (full != NULL
  2351.                && cmdnames[(int)eap->cmdidx].cmd_name[len] == NUL)
  2352.             *full = TRUE;
  2353. #endif
  2354.         break;
  2355.         }
  2356.  
  2357. #ifdef FEAT_USR_CMDS
  2358.     /* Look for a user defined command as a last resort */
  2359.     if (eap->cmdidx == CMD_SIZE && *eap->cmd >= 'A' && *eap->cmd <= 'Z')
  2360.     {
  2361.         ucmd_T    *cmd;
  2362.         int        j, k, matchlen = 0;
  2363.         int        found = FALSE, possible = FALSE;
  2364.         char_u    *cp, *np;    /* Point into typed cmd and test name */
  2365.         garray_T    *gap;
  2366.         int        amb_local = FALSE; /* Found ambiguous buffer-local
  2367.                           command, only full match global
  2368.                           is accepted. */
  2369.  
  2370.         /* User defined commands may contain numbers */
  2371.         while (ASCII_ISALNUM(*p))
  2372.         ++p;
  2373.         len = (int)(p - eap->cmd);
  2374.  
  2375.         /*
  2376.          * Look for buffer-local user commands first, then global ones.
  2377.          */
  2378.         gap = &curbuf->b_ucmds;
  2379.         for (;;)
  2380.         {
  2381.         cmd = USER_CMD_GA(gap, 0);
  2382.  
  2383.         for (j = 0; j < gap->ga_len; ++j, ++cmd)
  2384.         {
  2385.             cp = eap->cmd;
  2386.             np = cmd->uc_name;
  2387.             k = 0;
  2388.             while (k < len && *np != NUL && *cp++ == *np++)
  2389.             k++;
  2390.             if (k == len || (*np == NUL && isdigit(eap->cmd[k])))
  2391.             {
  2392.             /* If finding a second match, the command is
  2393.              * ambiguous.  But not if a buffer-local command
  2394.              * wasn't a full match and a global command is a full
  2395.              * match. */
  2396.             if (k == len && found && *np != NUL)
  2397.             {
  2398.                 if (gap == &ucmds)
  2399.                 return NULL;
  2400.                 amb_local = TRUE;
  2401.             }
  2402.  
  2403.             if (!found || (k == len && *np == NUL))
  2404.             {
  2405.                 /* If we matched up to a digit, then there could
  2406.                  * be another command including the digit that we
  2407.                  * should use instead.
  2408.                  */
  2409.                 if (k == len)
  2410.                 found = TRUE;
  2411.                 else
  2412.                 possible = TRUE;
  2413.  
  2414.                 if (gap == &ucmds)
  2415.                 eap->cmdidx = CMD_USER;
  2416.                 else
  2417.                 eap->cmdidx = CMD_USER_BUF;
  2418.                 eap->argt = cmd->uc_argt;
  2419.                 eap->useridx = j;
  2420.  
  2421.                 /* Do not search for further abbreviations
  2422.                  * if this is an exact match. */
  2423.                 matchlen = k;
  2424.                 if (k == len && *np == NUL)
  2425.                 {
  2426.                 if (full != NULL)
  2427.                     *full = TRUE;
  2428.                 amb_local = FALSE;
  2429.                 break;
  2430.                 }
  2431.             }
  2432.             }
  2433.         }
  2434.  
  2435.         /* Stop if we found a full match or searched all. */
  2436.         if (j < gap->ga_len || gap == &ucmds)
  2437.             break;
  2438.         gap = &ucmds;
  2439.         }
  2440.  
  2441.         /* Only found ambiguous matches. */
  2442.         if (amb_local)
  2443.         return NULL;
  2444.  
  2445.         /* The match we found may be followed immediately by a
  2446.          * number.  Move *p back to point to it.
  2447.          */
  2448.         if (found || possible)
  2449.         p += matchlen - len;
  2450.     }
  2451. #endif
  2452.  
  2453.     if (len == 0)
  2454.         eap->cmdidx = CMD_SIZE;
  2455.     }
  2456.  
  2457.     return p;
  2458. }
  2459.  
  2460. #if defined(FEAT_EVAL) || defined(PROTO)
  2461. /*
  2462.  * Return > 0 if an Ex command "name" exists.
  2463.  * Return 2 if there is an exact match.
  2464.  * Return 3 if there is an ambiguous match.
  2465.  */
  2466.     int
  2467. cmd_exists(name)
  2468.     char_u    *name;
  2469. {
  2470.     exarg_T    ea;
  2471.     int        full = FALSE;
  2472.  
  2473.     ea.cmd = name;
  2474.     ea.cmdidx = (cmdidx_T)0;
  2475.     if (find_command(&ea, &full) == NULL)
  2476.     return 3;
  2477.     return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1));
  2478. }
  2479. #endif
  2480.  
  2481. /*
  2482.  * This is all pretty much copied from do_one_cmd(), with all the extra stuff
  2483.  * we don't need/want deleted.    Maybe this could be done better if we didn't
  2484.  * repeat all this stuff.  The only problem is that they may not stay
  2485.  * perfectly compatible with each other, but then the command line syntax
  2486.  * probably won't change that much -- webb.
  2487.  */
  2488.     char_u *
  2489. set_one_cmd_context(xp, buff)
  2490.     expand_T    *xp;
  2491.     char_u    *buff;        /* buffer for command string */
  2492. {
  2493.     char_u        *p;
  2494.     char_u        *cmd, *arg;
  2495.     int            i = 0;
  2496.     cmdidx_T        cmdidx;
  2497.     long_u        argt = 0;
  2498. #if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
  2499.     int            compl = EXPAND_NOTHING;
  2500. #endif
  2501. #ifdef FEAT_CMDL_COMPL
  2502.     int            delim;
  2503. #endif
  2504.     int            forceit = FALSE;
  2505.     int            usefilter = FALSE;  /* filter instead of file name */
  2506.  
  2507.     xp->xp_pattern = buff;
  2508.     xp->xp_context = EXPAND_COMMANDS;    /* Default until we get past command */
  2509.     xp->xp_backslash = XP_BS_NONE;
  2510.     xp->xp_arg = NULL;
  2511.  
  2512. /*
  2513.  * 2. skip comment lines and leading space, colons or bars
  2514.  */
  2515.     for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
  2516.     ;
  2517.     xp->xp_pattern = cmd;
  2518.  
  2519.     if (*cmd == NUL)
  2520.     return NULL;
  2521.     if (*cmd == '"')        /* ignore comment lines */
  2522.     {
  2523.     xp->xp_context = EXPAND_NOTHING;
  2524.     return NULL;
  2525.     }
  2526.  
  2527. /*
  2528.  * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
  2529.  */
  2530.     cmd = skip_range(cmd, &xp->xp_context);
  2531.  
  2532. /*
  2533.  * 4. parse command
  2534.  */
  2535.  
  2536.     cmd = skipwhite(cmd);
  2537.     xp->xp_pattern = cmd;
  2538.     if (*cmd == NUL)
  2539.     return NULL;
  2540.     if (*cmd == '"')
  2541.     {
  2542.     xp->xp_context = EXPAND_NOTHING;
  2543.     return NULL;
  2544.     }
  2545.  
  2546.     if (*cmd == '|' || *cmd == '\n')
  2547.     return cmd + 1;            /* There's another command */
  2548.  
  2549.     /*
  2550.      * Isolate the command and search for it in the command table.
  2551.      * Exceptions:
  2552.      * - the 'k' command can directly be followed by any character.
  2553.      * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
  2554.      */
  2555.     if (*cmd == 'k')
  2556.     {
  2557.     cmdidx = CMD_k;
  2558.     p = cmd + 1;
  2559.     }
  2560.     else
  2561.     {
  2562.     p = cmd;
  2563.     while (ASCII_ISALPHA(*p) || *p == '*')    /* Allow * wild card */
  2564.         ++p;
  2565.     /* check for non-alpha command */
  2566.     if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
  2567.         ++p;
  2568.     i = (int)(p - cmd);
  2569.  
  2570.     if (i == 0)
  2571.     {
  2572.         xp->xp_context = EXPAND_UNSUCCESSFUL;
  2573.         return NULL;
  2574.     }
  2575.     for (cmdidx = (cmdidx_T)0; (int)cmdidx < (int)CMD_SIZE;
  2576.                      cmdidx = (cmdidx_T)((int)cmdidx + 1))
  2577.         if (STRNCMP(cmdnames[(int)cmdidx].cmd_name, cmd, (size_t)i) == 0)
  2578.         break;
  2579. #ifdef FEAT_USR_CMDS
  2580.  
  2581.     if (cmd[0] >= 'A' && cmd[0] <= 'Z')
  2582.     {
  2583.         while (ASCII_ISALNUM(*p) || *p == '*')    /* Allow * wild card */
  2584.         ++p;
  2585.         i = (int)(p - cmd);
  2586.     }
  2587. #endif
  2588.     }
  2589.  
  2590.     /*
  2591.      * If the cursor is touching the command, and it ends in an alpha-numeric
  2592.      * character, complete the command name.
  2593.      */
  2594.     if (*p == NUL && ASCII_ISALNUM(p[-1]))
  2595.     return NULL;
  2596.  
  2597.     if (cmdidx == CMD_SIZE)
  2598.     {
  2599.     if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL)
  2600.     {
  2601.         cmdidx = CMD_substitute;
  2602.         p = cmd + 1;
  2603.     }
  2604. #ifdef FEAT_USR_CMDS
  2605.     else if (cmd[0] >= 'A' && cmd[0] <= 'Z')
  2606.     {
  2607.         /* Look for a user defined command as a last resort */
  2608.         ucmd_T    *uc;
  2609.         int        j, k, matchlen = 0;
  2610.         int        found = FALSE, possible = FALSE;
  2611.         char_u    *cp, *np;    /* Point into typed cmd and test name */
  2612.         garray_T    *gap;
  2613.  
  2614.         gap = &curbuf->b_ucmds;
  2615.         for (;;)
  2616.         {
  2617.         uc = USER_CMD_GA(gap, 0);
  2618.         for (j = 0; j < gap->ga_len; ++j, ++uc)
  2619.         {
  2620.             cp = cmd;
  2621.             np = uc->uc_name;
  2622.             k = 0;
  2623.             while (k < i && *np != NUL && *cp++ == *np++)
  2624.             k++;
  2625.             if (k == i || (*np == NUL && isdigit(cmd[k])))
  2626.             {
  2627.             if (k == i && found)
  2628.             {
  2629.                 /* Ambiguous abbreviation */
  2630.                 xp->xp_context = EXPAND_UNSUCCESSFUL;
  2631.                 return NULL;
  2632.             }
  2633.             if (!found)
  2634.             {
  2635.                 /* If we matched up to a digit, then there could
  2636.                  * be another command including the digit that we
  2637.                  * should use instead.
  2638.                  */
  2639.                 if (k == i)
  2640.                 found = TRUE;
  2641.                 else
  2642.                 possible = TRUE;
  2643.  
  2644.                 if (gap == &ucmds)
  2645.                 cmdidx = CMD_USER;
  2646.                 else
  2647.                 cmdidx = CMD_USER_BUF;
  2648.                 argt = uc->uc_argt;
  2649. #ifdef FEAT_CMDL_COMPL
  2650.                 compl = uc->uc_compl;
  2651.                 xp->xp_arg = uc->uc_compl_arg;
  2652. #endif
  2653.                 /* Do not search for further abbreviations
  2654.                  * if this is an exact match
  2655.                  */
  2656.                 matchlen = k;
  2657.                 if (k == i && *np == NUL)
  2658.                 break;
  2659.             }
  2660.             }
  2661.         }
  2662.         if (gap == &ucmds || j < gap->ga_len)
  2663.             break;
  2664.         gap = &ucmds;
  2665.         }
  2666.  
  2667.         /* The match we found may be followed immediately by a
  2668.          * number.  Move *p back to point to it.
  2669.          */
  2670.         if (found || possible)
  2671.         p += matchlen - i;
  2672.     }
  2673. #endif
  2674.     }
  2675.     if (cmdidx == CMD_SIZE)
  2676.     {
  2677.     /* Not still touching the command and it was an illegal one */
  2678.     xp->xp_context = EXPAND_UNSUCCESSFUL;
  2679.     return NULL;
  2680.     }
  2681.  
  2682.     xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */
  2683.  
  2684.     if (*p == '!')            /* forced commands */
  2685.     {
  2686.     forceit = TRUE;
  2687.     ++p;
  2688.     }
  2689.  
  2690. /*
  2691.  * 5. parse arguments
  2692.  */
  2693. #ifdef FEAT_USR_CMDS
  2694.     if (!USER_CMDIDX(cmdidx))
  2695. #endif
  2696.     argt = cmdnames[(int)cmdidx].cmd_argt;
  2697.  
  2698.     arg = skipwhite(p);
  2699.  
  2700.     if (cmdidx == CMD_write || cmdidx == CMD_update)
  2701.     {
  2702.     if (*arg == '>')            /* append */
  2703.     {
  2704.         if (*++arg == '>')
  2705.         ++arg;
  2706.         arg = skipwhite(arg);
  2707.     }
  2708.     else if (*arg == '!' && cmdidx == CMD_write)    /* :w !filter */
  2709.     {
  2710.         ++arg;
  2711.         usefilter = TRUE;
  2712.     }
  2713.     }
  2714.  
  2715.     if (cmdidx == CMD_read)
  2716.     {
  2717.     usefilter = forceit;            /* :r! filter if forced */
  2718.     if (*arg == '!')            /* :r !filter */
  2719.     {
  2720.         ++arg;
  2721.         usefilter = TRUE;
  2722.     }
  2723.     }
  2724.  
  2725.     if (cmdidx == CMD_lshift || cmdidx == CMD_rshift)
  2726.     {
  2727.     while (*arg == *cmd)        /* allow any number of '>' or '<' */
  2728.         ++arg;
  2729.     arg = skipwhite(arg);
  2730.     }
  2731.  
  2732.     /* Does command allow "+command"? */
  2733.     if ((argt & EDITCMD) && !usefilter && *arg == '+')
  2734.     {
  2735.     /* Check if we're in the +command */
  2736.     p = arg + 1;
  2737.     arg = skip_cmd_arg(arg, FALSE);
  2738.  
  2739.     /* Still touching the command after '+'? */
  2740.     if (*arg == NUL)
  2741.         return p;
  2742.  
  2743.     /* Skip space(s) after +command to get to the real argument */
  2744.     arg = skipwhite(arg);
  2745.     }
  2746.  
  2747.     /*
  2748.      * Check for '|' to separate commands and '"' to start comments.
  2749.      * Don't do this for ":read !cmd" and ":write !cmd".
  2750.      */
  2751.     if ((argt & TRLBAR) && !usefilter)
  2752.     {
  2753.     p = arg;
  2754.     /* ":redir @" is not the start of a comment */
  2755.     if (cmdidx == CMD_redir && p[0] == '@' && p[1] == '"')
  2756.         p += 2;
  2757.     while (*p)
  2758.     {
  2759.         if (*p == Ctrl_V)
  2760.         {
  2761.         if (p[1] != NUL)
  2762.             ++p;
  2763.         }
  2764.         else if ( (*p == '"' && !(argt & NOTRLCOM))
  2765.             || *p == '|' || *p == '\n')
  2766.         {
  2767.         if (*(p - 1) != '\\')
  2768.         {
  2769.             if (*p == '|' || *p == '\n')
  2770.             return p + 1;
  2771.             return NULL;    /* It's a comment */
  2772.         }
  2773.         }
  2774. #ifdef FEAT_MBYTE
  2775.         if (has_mbyte)
  2776.         p += (*mb_ptr2len_check)(p);
  2777.         else
  2778. #endif
  2779.         ++p;
  2780.     }
  2781.     }
  2782.  
  2783.                         /* no arguments allowed */
  2784.     if (!(argt & EXTRA) && *arg != NUL &&
  2785.                     vim_strchr((char_u *)"|\"", *arg) == NULL)
  2786.     return NULL;
  2787.  
  2788.     /* Find start of last argument (argument just before cursor): */
  2789.     p = buff + STRLEN(buff);
  2790.     while (p != arg && *p != ' ' && *p != TAB)
  2791.     p--;
  2792.     if (*p == ' ' || *p == TAB)
  2793.     p++;
  2794.     xp->xp_pattern = p;
  2795.  
  2796.     if (argt & XFILE)
  2797.     {
  2798.     int in_quote = FALSE;
  2799.     char_u *bow = NULL;    /* Beginning of word */
  2800.  
  2801.     /*
  2802.      * Allow spaces within back-quotes to count as part of the argument
  2803.      * being expanded.
  2804.      */
  2805.     xp->xp_pattern = skipwhite(arg);
  2806.     for (p = xp->xp_pattern; *p; )
  2807.     {
  2808.         if (*p == '\\' && p[1])
  2809.         ++p;
  2810. #ifdef SPACE_IN_FILENAME
  2811.         else if (vim_iswhite(*p) && (!(argt & NOSPC) || usefilter))
  2812. #else
  2813.         else if (vim_iswhite(*p))
  2814. #endif
  2815.         {
  2816.         p = skipwhite(p);
  2817.         if (in_quote)
  2818.             bow = p;
  2819.         else
  2820.             xp->xp_pattern = p;
  2821.         --p;
  2822.         }
  2823.         else if (*p == '`')
  2824.         {
  2825.         if (!in_quote)
  2826.         {
  2827.             xp->xp_pattern = p;
  2828.             bow = p + 1;
  2829.         }
  2830.         in_quote = !in_quote;
  2831.         }
  2832. #ifdef FEAT_MBYTE
  2833.         if (has_mbyte)
  2834.         p += (*mb_ptr2len_check)(p);
  2835.         else
  2836. #endif
  2837.         ++p;
  2838.     }
  2839.  
  2840.     /*
  2841.      * If we are still inside the quotes, and we passed a space, just
  2842.      * expand from there.
  2843.      */
  2844.     if (bow != NULL && in_quote)
  2845.         xp->xp_pattern = bow;
  2846.     xp->xp_context = EXPAND_FILES;
  2847.  
  2848.     /* Check for environment variable */
  2849.     if (*xp->xp_pattern == '$'
  2850. #if defined(MSDOS) || defined(MSWIN) || defined(OS2)
  2851.         || *xp->xp_pattern == '%'
  2852. #endif
  2853.         )
  2854.     {
  2855.         for (p = xp->xp_pattern + 1; *p != NUL; ++p)
  2856.         if (!vim_isIDc(*p))
  2857.             break;
  2858.         if (*p == NUL)
  2859.         {
  2860.         xp->xp_context = EXPAND_ENV_VARS;
  2861.         ++xp->xp_pattern;
  2862.         }
  2863.     }
  2864.     }
  2865.  
  2866. /*
  2867.  * 6. switch on command name
  2868.  */
  2869.     switch (cmdidx)
  2870.     {
  2871.     case CMD_cd:
  2872.     case CMD_chdir:
  2873.     case CMD_lcd:
  2874.     case CMD_lchdir:
  2875.         if (xp->xp_context == EXPAND_FILES)
  2876.         xp->xp_context = EXPAND_DIRECTORIES;
  2877.         break;
  2878.     case CMD_help:
  2879.         xp->xp_context = EXPAND_HELP;
  2880.         xp->xp_pattern = arg;
  2881.         break;
  2882.  
  2883.     /* Command modifiers: return the argument. */
  2884.     case CMD_aboveleft:
  2885.     case CMD_belowright:
  2886.     case CMD_botright:
  2887.     case CMD_browse:
  2888.     case CMD_confirm:
  2889.     case CMD_folddoclosed:
  2890.     case CMD_folddoopen:
  2891.     case CMD_hide:
  2892.     case CMD_leftabove:
  2893.     case CMD_rightbelow:
  2894.     case CMD_silent:
  2895.     case CMD_topleft:
  2896.     case CMD_verbose:
  2897.     case CMD_vertical:
  2898.         return arg;
  2899.  
  2900. #ifdef FEAT_SEARCH_EXTRA
  2901.     case CMD_match:
  2902.         if (*arg == NUL || !ends_excmd(*arg))
  2903.         {
  2904.         /* Dummy call to clear variables. */
  2905.         set_context_in_highlight_cmd(xp, (char_u *)"link n");
  2906.         xp->xp_context = EXPAND_HIGHLIGHT;
  2907.         xp->xp_pattern = arg;
  2908.         arg = skipwhite(skiptowhite(arg));
  2909.         if (*arg != NUL)
  2910.         {
  2911.             xp->xp_context = EXPAND_NOTHING;
  2912.             arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
  2913.         }
  2914.         }
  2915.         return find_nextcmd(arg);
  2916. #endif
  2917.  
  2918. #ifdef FEAT_CMDL_COMPL
  2919. /*
  2920.  * All completion for the +cmdline_compl feature goes here.
  2921.  */
  2922.  
  2923. # ifdef FEAT_USR_CMDS
  2924.     case CMD_command:
  2925.         /* Check for attributes */
  2926.         while (*arg == '-')
  2927.         {
  2928.         arg++;        /* Skip "-" */
  2929.         p = skiptowhite(arg);
  2930.         if (*p == NUL)
  2931.         {
  2932.             /* Cursor is still in the attribute */
  2933.             p = vim_strchr(arg, '=');
  2934.             if (p == NULL)
  2935.             {
  2936.             /* No "=", so complete attribute names */
  2937.             xp->xp_context = EXPAND_USER_CMD_FLAGS;
  2938.             xp->xp_pattern = arg;
  2939.             return NULL;
  2940.             }
  2941.  
  2942.             /* For the -complete and -nargs attributes, we complete
  2943.              * their arguments as well.
  2944.              */
  2945.             if (STRNICMP(arg, "complete", p - arg) == 0)
  2946.             {
  2947.             xp->xp_context = EXPAND_USER_COMPLETE;
  2948.             xp->xp_pattern = p + 1;
  2949.             return NULL;
  2950.             }
  2951.             else if (STRNICMP(arg, "nargs", p - arg) == 0)
  2952.             {
  2953.             xp->xp_context = EXPAND_USER_NARGS;
  2954.             xp->xp_pattern = p + 1;
  2955.             return NULL;
  2956.             }
  2957.             return NULL;
  2958.         }
  2959.         arg = skipwhite(p);
  2960.         }
  2961.  
  2962.         /* After the attributes comes the new command name */
  2963.         p = skiptowhite(arg);
  2964.         if (*p == NUL)
  2965.         {
  2966.         xp->xp_context = EXPAND_USER_COMMANDS;
  2967.         xp->xp_pattern = arg;
  2968.         break;
  2969.         }
  2970.  
  2971.         /* And finally comes a normal command */
  2972.         return skipwhite(p);
  2973.  
  2974.     case CMD_delcommand:
  2975.         xp->xp_context = EXPAND_USER_COMMANDS;
  2976.         xp->xp_pattern = arg;
  2977.         break;
  2978. # endif
  2979.  
  2980.     case CMD_global:
  2981.     case CMD_vglobal:
  2982.         delim = *arg;        /* get the delimiter */
  2983.         if (delim)
  2984.         ++arg;            /* skip delimiter if there is one */
  2985.  
  2986.         while (arg[0] != NUL && arg[0] != delim)
  2987.         {
  2988.         if (arg[0] == '\\' && arg[1] != NUL)
  2989.             ++arg;
  2990.         ++arg;
  2991.         }
  2992.         if (arg[0] != NUL)
  2993.         return arg + 1;
  2994.         break;
  2995.     case CMD_and:
  2996.     case CMD_substitute:
  2997.         delim = *arg;
  2998.         if (delim)
  2999.         {
  3000.         /* skip "from" part */
  3001.         ++arg;
  3002.         arg = skip_regexp(arg, delim, p_magic, NULL);
  3003.         }
  3004.         /* skip "to" part */
  3005.         while (arg[0] != NUL && arg[0] != delim)
  3006.         {
  3007.         if (arg[0] == '\\' && arg[1] != NUL)
  3008.             ++arg;
  3009.         ++arg;
  3010.         }
  3011.         if (arg[0] != NUL)    /* skip delimiter */
  3012.         ++arg;
  3013.         while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
  3014.         ++arg;
  3015.         if (arg[0] != NUL)
  3016.         return arg;
  3017.         break;
  3018.     case CMD_isearch:
  3019.     case CMD_dsearch:
  3020.     case CMD_ilist:
  3021.     case CMD_dlist:
  3022.     case CMD_ijump:
  3023.     case CMD_psearch:
  3024.     case CMD_djump:
  3025.     case CMD_isplit:
  3026.     case CMD_dsplit:
  3027.         arg = skipwhite(skipdigits(arg));        /* skip count */
  3028.         if (*arg == '/')    /* Match regexp, not just whole words */
  3029.         {
  3030.         for (++arg; *arg && *arg != '/'; arg++)
  3031.             if (*arg == '\\' && arg[1] != NUL)
  3032.             arg++;
  3033.         if (*arg)
  3034.         {
  3035.             arg = skipwhite(arg + 1);
  3036.  
  3037.             /* Check for trailing illegal characters */
  3038.             if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
  3039.             xp->xp_context = EXPAND_NOTHING;
  3040.             else
  3041.             return arg;
  3042.         }
  3043.         }
  3044.         break;
  3045. #ifdef FEAT_AUTOCMD
  3046.     case CMD_autocmd:
  3047.         return set_context_in_autocmd(xp, arg, FALSE);
  3048.  
  3049.     case CMD_doautocmd:
  3050.         return set_context_in_autocmd(xp, arg, TRUE);
  3051. #endif
  3052.     case CMD_set:
  3053.         set_context_in_set_cmd(xp, arg, 0);
  3054.         break;
  3055.     case CMD_setglobal:
  3056.         set_context_in_set_cmd(xp, arg, OPT_GLOBAL);
  3057.         break;
  3058.     case CMD_setlocal:
  3059.         set_context_in_set_cmd(xp, arg, OPT_LOCAL);
  3060.         break;
  3061.     case CMD_tag:
  3062.     case CMD_stag:
  3063.     case CMD_ptag:
  3064.     case CMD_tselect:
  3065.     case CMD_stselect:
  3066.     case CMD_ptselect:
  3067.     case CMD_tjump:
  3068.     case CMD_stjump:
  3069.     case CMD_ptjump:
  3070.         xp->xp_context = EXPAND_TAGS;
  3071.         xp->xp_pattern = arg;
  3072.         break;
  3073.     case CMD_augroup:
  3074.         xp->xp_context = EXPAND_AUGROUP;
  3075.         xp->xp_pattern = arg;
  3076.         break;
  3077. #ifdef FEAT_SYN_HL
  3078.     case CMD_syntax:
  3079.         set_context_in_syntax_cmd(xp, arg);
  3080.         break;
  3081. #endif
  3082. #ifdef FEAT_EVAL
  3083.     case CMD_let:
  3084.     case CMD_if:
  3085.     case CMD_elseif:
  3086.     case CMD_while:
  3087.     case CMD_echo:
  3088.     case CMD_echon:
  3089.     case CMD_execute:
  3090.     case CMD_echomsg:
  3091.     case CMD_echoerr:
  3092.     case CMD_call:
  3093.     case CMD_return:
  3094.         set_context_for_expression(xp, arg, cmdidx);
  3095.         break;
  3096.  
  3097.     case CMD_unlet:
  3098.         while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
  3099.         arg = xp->xp_pattern + 1;
  3100.         xp->xp_context = EXPAND_USER_VARS;
  3101.         xp->xp_pattern = arg;
  3102.         break;
  3103.  
  3104.     case CMD_function:
  3105.     case CMD_delfunction:
  3106.         xp->xp_context = EXPAND_USER_FUNC;
  3107.         xp->xp_pattern = arg;
  3108.         break;
  3109.  
  3110.     case CMD_echohl:
  3111.         xp->xp_context = EXPAND_HIGHLIGHT;
  3112.         xp->xp_pattern = arg;
  3113.         break;
  3114. #endif
  3115.     case CMD_highlight:
  3116.         set_context_in_highlight_cmd(xp, arg);
  3117.         break;
  3118. #ifdef FEAT_LISTCMDS
  3119.     case CMD_bdelete:
  3120.     case CMD_bwipeout:
  3121.     case CMD_bunload:
  3122.         while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
  3123.         arg = xp->xp_pattern + 1;
  3124.         /*FALLTHROUGH*/
  3125.     case CMD_buffer:
  3126.     case CMD_sbuffer:
  3127.     case CMD_checktime:
  3128.         xp->xp_context = EXPAND_BUFFERS;
  3129.         xp->xp_pattern = arg;
  3130.         break;
  3131. #endif
  3132. #ifdef FEAT_USR_CMDS
  3133.     case CMD_USER:
  3134.     case CMD_USER_BUF:
  3135.         if (compl != EXPAND_NOTHING)
  3136.         {
  3137.         /* XFILE: file names are handled above */
  3138.         if (!(argt & XFILE))
  3139.         {
  3140. # ifdef FEAT_MENU
  3141.             if (compl == EXPAND_MENUS)
  3142.             return set_context_in_menu_cmd(xp, cmd, arg, forceit);
  3143. # endif
  3144.             if (compl == EXPAND_COMMANDS)
  3145.             return arg;
  3146.             if (compl == EXPAND_MAPPINGS)
  3147.             return set_context_in_map_cmd(xp, (char_u *)"map",
  3148.                      arg, forceit, FALSE, FALSE, CMD_map);
  3149.             while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
  3150.             arg = xp->xp_pattern + 1;
  3151.             xp->xp_pattern = arg;
  3152.         }
  3153.         xp->xp_context = compl;
  3154.         }
  3155.         break;
  3156. #endif
  3157.     case CMD_map:        case CMD_noremap:
  3158.     case CMD_nmap:        case CMD_nnoremap:
  3159.     case CMD_vmap:        case CMD_vnoremap:
  3160.     case CMD_omap:        case CMD_onoremap:
  3161.     case CMD_imap:        case CMD_inoremap:
  3162.     case CMD_cmap:        case CMD_cnoremap:
  3163.         return set_context_in_map_cmd(xp, cmd, arg, forceit,
  3164.                             FALSE, FALSE, cmdidx);
  3165.     case CMD_unmap:
  3166.     case CMD_nunmap:
  3167.     case CMD_vunmap:
  3168.     case CMD_ounmap:
  3169.     case CMD_iunmap:
  3170.     case CMD_cunmap:
  3171.         return set_context_in_map_cmd(xp, cmd, arg, forceit,
  3172.                              FALSE, TRUE, cmdidx);
  3173.     case CMD_abbreviate:    case CMD_noreabbrev:
  3174.     case CMD_cabbrev:    case CMD_cnoreabbrev:
  3175.     case CMD_iabbrev:    case CMD_inoreabbrev:
  3176.         return set_context_in_map_cmd(xp, cmd, arg, forceit,
  3177.                              TRUE, FALSE, cmdidx);
  3178.     case CMD_unabbreviate:
  3179.     case CMD_cunabbrev:
  3180.     case CMD_iunabbrev:
  3181.         return set_context_in_map_cmd(xp, cmd, arg, forceit,
  3182.                               TRUE, TRUE, cmdidx);
  3183. #ifdef FEAT_MENU
  3184.     case CMD_menu:        case CMD_noremenu:        case CMD_unmenu:
  3185.     case CMD_amenu:        case CMD_anoremenu:        case CMD_aunmenu:
  3186.     case CMD_nmenu:        case CMD_nnoremenu:        case CMD_nunmenu:
  3187.     case CMD_vmenu:        case CMD_vnoremenu:        case CMD_vunmenu:
  3188.     case CMD_omenu:        case CMD_onoremenu:        case CMD_ounmenu:
  3189.     case CMD_imenu:        case CMD_inoremenu:        case CMD_iunmenu:
  3190.     case CMD_cmenu:        case CMD_cnoremenu:        case CMD_cunmenu:
  3191.     case CMD_tmenu:                    case CMD_tunmenu:
  3192.     case CMD_popup:        case CMD_tearoff:        case CMD_emenu:
  3193.         return set_context_in_menu_cmd(xp, cmd, arg, forceit);
  3194. #endif
  3195.  
  3196.     case CMD_colorscheme:
  3197.         xp->xp_context = EXPAND_COLORS;
  3198.         xp->xp_pattern = arg;
  3199.         break;
  3200.  
  3201.     case CMD_compiler:
  3202.         xp->xp_context = EXPAND_COMPILER;
  3203.         xp->xp_pattern = arg;
  3204.         break;
  3205.  
  3206. #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
  3207.     && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
  3208.     case CMD_language:
  3209.         if (*skiptowhite(arg) == NUL)
  3210.         {
  3211.         xp->xp_context = EXPAND_LANGUAGE;
  3212.         xp->xp_pattern = arg;
  3213.         }
  3214.         else
  3215.         xp->xp_context = EXPAND_NOTHING;
  3216.         break;
  3217. #endif
  3218.  
  3219. #endif /* FEAT_CMDL_COMPL */
  3220.  
  3221.     default:
  3222.         break;
  3223.     }
  3224.     return NULL;
  3225. }
  3226.  
  3227. /*
  3228.  * skip a range specifier of the form: addr [,addr] [;addr] ..
  3229.  *
  3230.  * Backslashed delimiters after / or ? will be skipped, and commands will
  3231.  * not be expanded between /'s and ?'s or after "'".
  3232.  *
  3233.  * Returns the "cmd" pointer advanced to beyond the range.
  3234.  */
  3235.     char_u *
  3236. skip_range(cmd, ctx)
  3237.     char_u    *cmd;
  3238.     int        *ctx;    /* pointer to xp_context or NULL */
  3239. {
  3240.     int        delim;
  3241.  
  3242.     while (*cmd != NUL && (vim_isspace(*cmd) || isdigit(*cmd) ||
  3243.                 vim_strchr((char_u *)".$%'/?-+,;", *cmd) != NULL))
  3244.     {
  3245.     if (*cmd == '\'')
  3246.     {
  3247.         if (*++cmd == NUL && ctx != NULL)
  3248.         *ctx = EXPAND_NOTHING;
  3249.     }
  3250.     else if (*cmd == '/' || *cmd == '?')
  3251.     {
  3252.         delim = *cmd++;
  3253.         while (*cmd != NUL && *cmd != delim)
  3254.         if (*cmd++ == '\\' && *cmd != NUL)
  3255.             ++cmd;
  3256.         if (*cmd == NUL && ctx != NULL)
  3257.         *ctx = EXPAND_NOTHING;
  3258.     }
  3259.     if (*cmd != NUL)
  3260.         ++cmd;
  3261.     }
  3262.     return cmd;
  3263. }
  3264.  
  3265. /*
  3266.  * get a single EX address
  3267.  *
  3268.  * Set ptr to the next character after the part that was interpreted.
  3269.  * Set ptr to NULL when an error is encountered.
  3270.  *
  3271.  * Return MAXLNUM when no Ex address was found.
  3272.  */
  3273.     static linenr_T
  3274. get_address(ptr, skip, otherfile)
  3275.     char_u    **ptr;
  3276.     int        skip;        /* only skip the address, don't use it */
  3277.     int        otherfile;  /* flag: may jump to other file */
  3278. {
  3279.     int        c;
  3280.     int        i;
  3281.     long    n;
  3282.     char_u    *cmd;
  3283.     pos_T    pos;
  3284.     pos_T    *fp;
  3285.     linenr_T    lnum;
  3286.  
  3287.     cmd = skipwhite(*ptr);
  3288.     lnum = MAXLNUM;
  3289.     do
  3290.     {
  3291.     switch (*cmd)
  3292.     {
  3293.         case '.':                /* '.' - Cursor position */
  3294.             ++cmd;
  3295.             lnum = curwin->w_cursor.lnum;
  3296.             break;
  3297.  
  3298.         case '$':                /* '$' - last line */
  3299.             ++cmd;
  3300.             lnum = curbuf->b_ml.ml_line_count;
  3301.             break;
  3302.  
  3303.         case '\'':                /* ''' - mark */
  3304.             if (*++cmd == NUL)
  3305.             {
  3306.                 cmd = NULL;
  3307.                 goto error;
  3308.             }
  3309.             if (skip)
  3310.                 ++cmd;
  3311.             else
  3312.             {
  3313.                 /* Only accept a mark in another file when it is
  3314.                  * used by itself: ":'M". */
  3315.                 fp = getmark(*cmd, otherfile && cmd[1] == NUL);
  3316.                 ++cmd;
  3317.                 if (fp == (pos_T *)-1)
  3318.                 /* Jumped to another file. */
  3319.                 lnum = curwin->w_cursor.lnum;
  3320.                 else
  3321.                 {
  3322.                 if (check_mark(fp) == FAIL)
  3323.                 {
  3324.                     cmd = NULL;
  3325.                     goto error;
  3326.                 }
  3327.                 lnum = fp->lnum;
  3328.                 }
  3329.             }
  3330.             break;
  3331.  
  3332.         case '/':
  3333.         case '?':            /* '/' or '?' - search */
  3334.             c = *cmd++;
  3335.             if (skip)    /* skip "/pat/" */
  3336.             {
  3337.                 cmd = skip_regexp(cmd, c, (int)p_magic, NULL);
  3338.                 if (*cmd == c)
  3339.                 ++cmd;
  3340.             }
  3341.             else
  3342.             {
  3343.                 pos = curwin->w_cursor; /* save curwin->w_cursor */
  3344.                 /*
  3345.                  * When '/' or '?' follows another address, start
  3346.                  * from there.
  3347.                  */
  3348.                 if (lnum != MAXLNUM)
  3349.                 curwin->w_cursor.lnum = lnum;
  3350.                 /*
  3351.                  * Start a forward search at the end of the line.
  3352.                  * Start a backward search at the start of the line.
  3353.                  * This makes sure we never match in the current
  3354.                  * line, and can match anywhere in the
  3355.                  * next/previous line.
  3356.                  */
  3357.                 if (c == '/')
  3358.                 curwin->w_cursor.col = MAXCOL;
  3359.                 else
  3360.                 curwin->w_cursor.col = 0;
  3361.                 searchcmdlen = 0;
  3362.                 if (!do_search(NULL, c, cmd, 1L,
  3363.                       SEARCH_HIS + SEARCH_MSG + SEARCH_START))
  3364.                 {
  3365.                 curwin->w_cursor = pos;
  3366.                 cmd = NULL;
  3367.                 goto error;
  3368.                 }
  3369.                 lnum = curwin->w_cursor.lnum;
  3370.                 curwin->w_cursor = pos;
  3371.                 /* adjust command string pointer */
  3372.                 cmd += searchcmdlen;
  3373.             }
  3374.             break;
  3375.  
  3376.         case '\\':            /* "\?", "\/" or "\&", repeat search */
  3377.             ++cmd;
  3378.             if (*cmd == '&')
  3379.                 i = RE_SUBST;
  3380.             else if (*cmd == '?' || *cmd == '/')
  3381.                 i = RE_SEARCH;
  3382.             else
  3383.             {
  3384.                 EMSG(_(e_backslash));
  3385.                 cmd = NULL;
  3386.                 goto error;
  3387.             }
  3388.  
  3389.             if (!skip)
  3390.             {
  3391.                 /*
  3392.                  * When search follows another address, start from
  3393.                  * there.
  3394.                  */
  3395.                 if (lnum != MAXLNUM)
  3396.                 pos.lnum = lnum;
  3397.                 else
  3398.                 pos.lnum = curwin->w_cursor.lnum;
  3399.  
  3400.                 /*
  3401.                  * Start the search just like for the above
  3402.                  * do_search().
  3403.                  */
  3404.                 if (*cmd != '?')
  3405.                 pos.col = MAXCOL;
  3406.                 else
  3407.                 pos.col = 0;
  3408.                 if (searchit(curwin, curbuf, &pos,
  3409.                     *cmd == '?' ? BACKWARD : FORWARD,
  3410.                     (char_u *)"", 1L,
  3411.                     SEARCH_MSG + SEARCH_START, i) != FAIL)
  3412.                 lnum = pos.lnum;
  3413.                 else
  3414.                 {
  3415.                 cmd = NULL;
  3416.                 goto error;
  3417.                 }
  3418.             }
  3419.             ++cmd;
  3420.             break;
  3421.  
  3422.         default:
  3423.             if (isdigit(*cmd))    /* absolute line number */
  3424.                 lnum = getdigits(&cmd);
  3425.     }
  3426.  
  3427.     for (;;)
  3428.     {
  3429.         cmd = skipwhite(cmd);
  3430.         if (*cmd != '-' && *cmd != '+' && !isdigit(*cmd))
  3431.         break;
  3432.  
  3433.         if (lnum == MAXLNUM)
  3434.         lnum = curwin->w_cursor.lnum;    /* "+1" is same as ".+1" */
  3435.         if (isdigit(*cmd))
  3436.         i = '+';        /* "number" is same as "+number" */
  3437.         else
  3438.         i = *cmd++;
  3439.         if (!isdigit(*cmd))        /* '+' is '+1', but '+0' is not '+1' */
  3440.         n = 1;
  3441.         else
  3442.         n = getdigits(&cmd);
  3443.         if (i == '-')
  3444.         lnum -= n;
  3445.         else
  3446.         lnum += n;
  3447.     }
  3448.     } while (*cmd == '/' || *cmd == '?');
  3449.  
  3450. error:
  3451.     *ptr = cmd;
  3452.     return lnum;
  3453. }
  3454.  
  3455. /*
  3456.  * Function called for command which is Not Implemented.  NI!
  3457.  */
  3458.     void
  3459. ex_ni(eap)
  3460.     exarg_T    *eap;
  3461. {
  3462.     if (!eap->skip)
  3463.     eap->errmsg = (char_u *)N_("E319: Sorry, the command is not available in this version");
  3464. }
  3465.  
  3466. /*
  3467.  * Check range in Ex command for validity.
  3468.  * Return NULL when valid, error message when invalid.
  3469.  */
  3470.     static char_u *
  3471. invalid_range(eap)
  3472.     exarg_T    *eap;
  3473. {
  3474.     if (       eap->line1 < 0
  3475.         || eap->line2 < 0
  3476.         || eap->line1 > eap->line2
  3477.         || ((eap->argt & RANGE)
  3478.         && !(eap->argt & NOTADR)
  3479.         && eap->line2 > curbuf->b_ml.ml_line_count
  3480. #ifdef FEAT_DIFF
  3481.             + (eap->cmdidx == CMD_diffget)
  3482. #endif
  3483.         ))
  3484.     return (char_u *)_(e_invrange);
  3485.     return NULL;
  3486. }
  3487.  
  3488. /*
  3489.  * Correct the range for zero line number, if required.
  3490.  */
  3491.     static void
  3492. correct_range(eap)
  3493.     exarg_T    *eap;
  3494. {
  3495.     if (!(eap->argt & ZEROR))        /* zero in range not allowed */
  3496.     {
  3497.     if (eap->line1 == 0)
  3498.         eap->line1 = 1;
  3499.     if (eap->line2 == 0)
  3500.         eap->line2 = 1;
  3501.     }
  3502. }
  3503.  
  3504. /*
  3505.  * Expand file name in Ex command argument.
  3506.  * Return FAIL for failure, OK otherwise.
  3507.  */
  3508.     int
  3509. expand_filename(eap, cmdlinep, errormsgp)
  3510.     exarg_T    *eap;
  3511.     char_u    **cmdlinep;
  3512.     char_u    **errormsgp;
  3513. {
  3514.     int        has_wildcards;    /* need to expand wildcards */
  3515.     char_u    *repl;
  3516.     int        srclen;
  3517.     char_u    *p;
  3518.     int        n;
  3519.  
  3520.     /*
  3521.      * Decide to expand wildcards *before* replacing '%', '#', etc.  If
  3522.      * the file name contains a wildcard it should not cause expanding.
  3523.      * (it will be expanded anyway if there is a wildcard before replacing).
  3524.      */
  3525.     has_wildcards = mch_has_wildcard(eap->arg);
  3526.     for (p = eap->arg; *p; )
  3527.     {
  3528.     /*
  3529.      * Quick check if this cannot be the start of a special string.
  3530.      * Also removes backslash before '%', '#' and '<'.
  3531.      */
  3532.     if (vim_strchr((char_u *)"%#<", *p) == NULL)
  3533.     {
  3534.         ++p;
  3535.         continue;
  3536.     }
  3537.  
  3538.     /*
  3539.      * Try to find a match at this position.
  3540.      */
  3541.     repl = eval_vars(p, &srclen, &(eap->do_ecmd_lnum), errormsgp, eap->arg);
  3542.     if (*errormsgp != NULL)        /* error detected */
  3543.         return FAIL;
  3544.     if (repl == NULL)        /* no match found */
  3545.     {
  3546.         p += srclen;
  3547.         continue;
  3548.     }
  3549.  
  3550.     /* Need to escape white space et al. with a backslash.  Don't do this
  3551.      * for shell commands (may have to use quotes instead).  Don't do this
  3552.      * for non-unix systems when there is a single argument (spaces don't
  3553.      * separate arguments then). */
  3554.     if (!eap->usefilter
  3555.         && eap->cmdidx != CMD_bang
  3556.         && eap->cmdidx != CMD_make
  3557.         && eap->cmdidx != CMD_grep
  3558.         && eap->cmdidx != CMD_grepadd
  3559. #ifndef UNIX
  3560.         && !(eap->argt & NOSPC)
  3561. #endif
  3562.         )
  3563.     {
  3564.         char_u    *l;
  3565. #ifdef BACKSLASH_IN_FILENAME
  3566.         /* Don't escape a backslash here, because rem_backslash() doesn't
  3567.          * remove it later. */
  3568.         static char_u *nobslash = (char_u *)" \t\"|";
  3569. # define ESCAPE_CHARS nobslash
  3570. #else
  3571. # define ESCAPE_CHARS escape_chars
  3572. #endif
  3573.  
  3574.         for (l = repl; *l; ++l)
  3575.         if (vim_strchr(ESCAPE_CHARS, *l) != NULL)
  3576.         {
  3577.             l = vim_strsave_escaped(repl, ESCAPE_CHARS);
  3578.             if (l != NULL)
  3579.             {
  3580.             vim_free(repl);
  3581.             repl = l;
  3582.             }
  3583.             break;
  3584.         }
  3585.     }
  3586.  
  3587.     /* For a shell command a '!' must be escaped. */
  3588.     if ((eap->usefilter || eap->cmdidx == CMD_bang)
  3589.         && vim_strchr(repl, '!') != NULL)
  3590.     {
  3591.         char_u    *l;
  3592.  
  3593.         l = vim_strsave_escaped(repl, (char_u *)"!");
  3594.         if (l != NULL)
  3595.         {
  3596.         vim_free(repl);
  3597.         repl = l;
  3598.         /* For a sh-like shell escape it another time. */
  3599.         if (strstr((char *)p_sh, "sh") != NULL)
  3600.         {
  3601.             l = vim_strsave_escaped(repl, (char_u *)"!");
  3602.             if (l != NULL)
  3603.             {
  3604.             vim_free(repl);
  3605.             repl = l;
  3606.             }
  3607.         }
  3608.         }
  3609.     }
  3610.  
  3611.     p = repl_cmdline(eap, p, srclen, repl, cmdlinep);
  3612.     vim_free(repl);
  3613.     if (p == NULL)
  3614.         return FAIL;
  3615.     }
  3616.  
  3617.     /*
  3618.      * One file argument: Expand wildcards.
  3619.      * Don't do this with ":r !command" or ":w !command".
  3620.      */
  3621.     if ((eap->argt & NOSPC) && !eap->usefilter)
  3622.     {
  3623.     /*
  3624.      * May do this twice:
  3625.      * 1. Replace environment variables.
  3626.      * 2. Replace any other wildcards, remove backslashes.
  3627.      */
  3628.     for (n = 1; n <= 2; ++n)
  3629.     {
  3630.         if (n == 2)
  3631.         {
  3632. #ifdef UNIX
  3633.         /*
  3634.          * Only for Unix we check for more than one file name.
  3635.          * For other systems spaces are considered to be part
  3636.          * of the file name.
  3637.          * Only check here if there is no wildcard, otherwise
  3638.          * ExpandOne() will check for errors. This allows
  3639.          * ":e `ls ve*.c`" on Unix.
  3640.          */
  3641.         if (!has_wildcards)
  3642.             for (p = eap->arg; *p; ++p)
  3643.             {
  3644.             /* skip escaped characters */
  3645.             if (p[1] && (*p == '\\' || *p == Ctrl_V))
  3646.                 ++p;
  3647.             else if (vim_iswhite(*p))
  3648.             {
  3649.                 *errormsgp = (char_u *)_("E172: Only one file name allowed");
  3650.                 return FAIL;
  3651.             }
  3652.             }
  3653. #endif
  3654.  
  3655.         /*
  3656.          * Halve the number of backslashes (this is Vi compatible).
  3657.          * For Unix and OS/2, when wildcards are expanded, this is
  3658.          * done by ExpandOne() below.
  3659.          */
  3660. #if defined(UNIX) || defined(OS2)
  3661.         if (!has_wildcards)
  3662. #endif
  3663.             backslash_halve(eap->arg);
  3664. #ifdef MACOS_CLASSIC
  3665.         /*
  3666.          * translate unix-like path components
  3667.          */
  3668.         slash_n_colon_adjust(eap->arg);
  3669. #endif
  3670.         }
  3671.  
  3672.         if (has_wildcards)
  3673.         {
  3674.         if (n == 1)
  3675.         {
  3676.             /*
  3677.              * First loop: May expand environment variables.  This
  3678.              * can be done much faster with expand_env() than with
  3679.              * something else (e.g., calling a shell).
  3680.              * After expanding environment variables, check again
  3681.              * if there are still wildcards present.
  3682.              */
  3683.             if (vim_strchr(eap->arg, '$') != NULL
  3684.                 || vim_strchr(eap->arg, '~') != NULL)
  3685.             {
  3686.             expand_env_esc(eap->arg, NameBuff, MAXPATHL, TRUE);
  3687.             has_wildcards = mch_has_wildcard(NameBuff);
  3688.             p = NameBuff;
  3689.             }
  3690.             else
  3691.             p = NULL;
  3692.         }
  3693.         else /* n == 2 */
  3694.         {
  3695.             expand_T    xpc;
  3696.  
  3697.             xpc.xp_context = EXPAND_FILES;
  3698.             xpc.xp_backslash = XP_BS_NONE;
  3699.             if ((p = ExpandOne(&xpc, eap->arg, NULL,
  3700.                         WILD_LIST_NOTFOUND|WILD_ADD_SLASH,
  3701.                            WILD_EXPAND_FREE)) == NULL)
  3702.             return FAIL;
  3703.         }
  3704.         if (p != NULL)
  3705.         {
  3706.             (void)repl_cmdline(eap, eap->arg, (int)STRLEN(eap->arg),
  3707.                                  p, cmdlinep);
  3708.             if (n == 2)    /* p came from ExpandOne() */
  3709.             vim_free(p);
  3710.         }
  3711.         }
  3712.     }
  3713.     }
  3714.     return OK;
  3715. }
  3716.  
  3717. /*
  3718.  * Replace part of the command line, keeping eap->cmd, eap->arg and
  3719.  * eap->nextcmd correct.
  3720.  * "src" points to the part that is to be replaced, of length "srclen".
  3721.  * "repl" is the replacement string.
  3722.  * Returns a pointer to the character after the replaced string.
  3723.  * Returns NULL for failure.
  3724.  */
  3725.     static char_u *
  3726. repl_cmdline(eap, src, srclen, repl, cmdlinep)
  3727.     exarg_T    *eap;
  3728.     char_u    *src;
  3729.     int        srclen;
  3730.     char_u    *repl;
  3731.     char_u    **cmdlinep;
  3732. {
  3733.     int        len;
  3734.     int        i;
  3735.     char_u    *new_cmdline;
  3736.  
  3737.     /*
  3738.      * The new command line is build in new_cmdline[].
  3739.      * First allocate it.
  3740.      * Careful: a "+cmd" argument may have been NUL terminated.
  3741.      */
  3742.     len = (int)STRLEN(repl);
  3743.     i = (int)(src - *cmdlinep) + (int)STRLEN(src + srclen) + len + 3;
  3744.     if (eap->nextcmd)
  3745.     i += (int)STRLEN(eap->nextcmd);/* add space for next command */
  3746.     if ((new_cmdline = alloc((unsigned)i)) == NULL)
  3747.     return NULL;            /* out of memory! */
  3748.  
  3749.     /*
  3750.      * Copy the stuff before the expanded part.
  3751.      * Copy the expanded stuff.
  3752.      * Copy what came after the expanded part.
  3753.      * Copy the next commands, if there are any.
  3754.      */
  3755.     i = (int)(src - *cmdlinep);    /* length of part before match */
  3756.     mch_memmove(new_cmdline, *cmdlinep, (size_t)i);
  3757.     mch_memmove(new_cmdline + i, repl, (size_t)len);
  3758.     i += len;                /* remember the end of the string */
  3759.     STRCPY(new_cmdline + i, src + srclen);
  3760.     src = new_cmdline + i;        /* remember where to continue */
  3761.  
  3762.     if (eap->nextcmd)            /* append next command */
  3763.     {
  3764.     i = (int)STRLEN(new_cmdline) + 1;
  3765.     STRCPY(new_cmdline + i, eap->nextcmd);
  3766.     eap->nextcmd = new_cmdline + i;
  3767.     }
  3768.     eap->cmd = new_cmdline + (eap->cmd - *cmdlinep);
  3769.     eap->arg = new_cmdline + (eap->arg - *cmdlinep);
  3770.     if (eap->do_ecmd_cmd != NULL && eap->do_ecmd_cmd != dollar_command)
  3771.     eap->do_ecmd_cmd = new_cmdline + (eap->do_ecmd_cmd - *cmdlinep);
  3772.     vim_free(*cmdlinep);
  3773.     *cmdlinep = new_cmdline;
  3774.  
  3775.     return src;
  3776. }
  3777.  
  3778. /*
  3779.  * Check for '|' to separate commands and '"' to start comments.
  3780.  */
  3781.     void
  3782. separate_nextcmd(eap)
  3783.     exarg_T    *eap;
  3784. {
  3785.     char_u    *p;
  3786.  
  3787.     for (p = eap->arg; *p; ++p)
  3788.     {
  3789.     if (*p == Ctrl_V)
  3790.     {
  3791.         if (eap->argt & (USECTRLV | XFILE))
  3792.         ++p;        /* skip CTRL-V and next char */
  3793.         else
  3794.         STRCPY(p, p + 1);    /* remove CTRL-V and skip next char */
  3795.         if (*p == NUL)        /* stop at NUL after CTRL-V */
  3796.         break;
  3797.     }
  3798.     /* Check for '"': start of comment or '|': next command */
  3799.     /* :@" and :*" do not start a comment!
  3800.      * :redir @" doesn't either. */
  3801.     else if ((*p == '"' && !(eap->argt & NOTRLCOM)
  3802.             && ((eap->cmdidx != CMD_at && eap->cmdidx != CMD_star)
  3803.             || p != eap->arg)
  3804.             && (eap->cmdidx != CMD_redir
  3805.             || p != eap->arg + 1 || p[-1] != '@'))
  3806.         || *p == '|' || *p == '\n')
  3807.     {
  3808.         /*
  3809.          * We remove the '\' before the '|', unless USECTRLV is used
  3810.          * AND 'b' is present in 'cpoptions'.
  3811.          */
  3812.         if ((vim_strchr(p_cpo, CPO_BAR) == NULL
  3813.                   || !(eap->argt & USECTRLV)) && *(p - 1) == '\\')
  3814.         {
  3815.         mch_memmove(p - 1, p, STRLEN(p) + 1);    /* remove the '\' */
  3816.         --p;
  3817.         }
  3818.         else
  3819.         {
  3820.         eap->nextcmd = check_nextcmd(p);
  3821.         *p = NUL;
  3822.         break;
  3823.         }
  3824.     }
  3825. #ifdef FEAT_MBYTE
  3826.     else if (has_mbyte)
  3827.         p += (*mb_ptr2len_check)(p) - 1; /* skip bytes of multi-byte char */
  3828. #endif
  3829.     }
  3830.     if (!(eap->argt & NOTRLCOM))    /* remove trailing spaces */
  3831.     del_trailing_spaces(eap->arg);
  3832. }
  3833.  
  3834. /*
  3835.  * get + command from ex argument
  3836.  */
  3837.     static char_u *
  3838. getargcmd(argp)
  3839.     char_u **argp;
  3840. {
  3841.     char_u *arg = *argp;
  3842.     char_u *command = NULL;
  3843.  
  3844.     if (*arg == '+')        /* +[command] */
  3845.     {
  3846.     ++arg;
  3847.     if (vim_isspace(*arg))
  3848.         command = dollar_command;
  3849.     else
  3850.     {
  3851.         command = arg;
  3852.         arg = skip_cmd_arg(command, TRUE);
  3853.         if (*arg != NUL)
  3854.         *arg++ = NUL;        /* terminate command with NUL */
  3855.     }
  3856.  
  3857.     arg = skipwhite(arg);    /* skip over spaces */
  3858.     *argp = arg;
  3859.     }
  3860.     return command;
  3861. }
  3862.  
  3863. /*
  3864.  * Find end of "+command" argument.  Skip over "\ " and "\\".
  3865.  */
  3866.     static char_u *
  3867. skip_cmd_arg(p, rembs)
  3868.     char_u *p;
  3869.     int       rembs;    /* TRUE to halve the number of backslashes */
  3870. {
  3871.     while (*p && !vim_isspace(*p))
  3872.     {
  3873.     if (*p == '\\' && p[1] != NUL)
  3874.     {
  3875.         if (rembs)
  3876.         mch_memmove(p, p + 1, STRLEN(p));
  3877.         else
  3878.         ++p;
  3879.     }
  3880. #ifdef FEAT_MBYTE
  3881.     if (has_mbyte)
  3882.         p += (*mb_ptr2len_check)(p);
  3883.     else
  3884. #endif
  3885.         ++p;
  3886.     }
  3887.     return p;
  3888. }
  3889.  
  3890. /*
  3891.  * Get "++opt=arg" argument.
  3892.  * Return FAIL or OK.
  3893.  */
  3894.     static int
  3895. getargopt(eap)
  3896.     exarg_T    *eap;
  3897. {
  3898.     char_u    *arg = eap->arg + 2;
  3899.     int        *pp = NULL;
  3900. #ifdef FEAT_MBYTE
  3901.     char_u    *p;
  3902. #endif
  3903.  
  3904.     if (STRNCMP(arg, "ff", 2) == 0)
  3905.     {
  3906.     arg += 2;
  3907.     pp = &eap->force_ff;
  3908.     }
  3909.     else if (STRNCMP(arg, "fileformat", 10) == 0)
  3910.     {
  3911.     arg += 10;
  3912.     pp = &eap->force_ff;
  3913.     }
  3914. #ifdef FEAT_MBYTE
  3915.     else if (STRNCMP(arg, "enc", 3) == 0)
  3916.     {
  3917.     arg += 3;
  3918.     pp = &eap->force_enc;
  3919.     }
  3920.     else if (STRNCMP(arg, "encoding", 8) == 0)
  3921.     {
  3922.     arg += 8;
  3923.     pp = &eap->force_enc;
  3924.     }
  3925. #endif
  3926.  
  3927.     if (pp == NULL || *arg != '=')
  3928.     return FAIL;
  3929.  
  3930.     ++arg;
  3931.     *pp = (int)(arg - eap->cmd);
  3932.     arg = skip_cmd_arg(arg, FALSE);
  3933.     eap->arg = skipwhite(arg);
  3934.     *arg = NUL;
  3935.  
  3936. #ifdef FEAT_MBYTE
  3937.     if (pp == &eap->force_ff)
  3938.     {
  3939. #endif
  3940.     if (check_ff_value(eap->cmd + eap->force_ff) == FAIL)
  3941.         return FAIL;
  3942. #ifdef FEAT_MBYTE
  3943.     }
  3944.     else
  3945.     {
  3946.     /* Make 'fileencoding' lower case. */
  3947.     for (p = eap->cmd + eap->force_enc; *p != NUL; ++p)
  3948.         *p = TOLOWER_ASC(*p);
  3949.     }
  3950. #endif
  3951.  
  3952.     return OK;
  3953. }
  3954.  
  3955. /*
  3956.  * ":abbreviate" and friends.
  3957.  */
  3958.     static void
  3959. ex_abbreviate(eap)
  3960.     exarg_T    *eap;
  3961. {
  3962.     do_exmap(eap, TRUE);    /* almost the same as mapping */
  3963. }
  3964.  
  3965. /*
  3966.  * ":map" and friends.
  3967.  */
  3968.     static void
  3969. ex_map(eap)
  3970.     exarg_T    *eap;
  3971. {
  3972.     /*
  3973.      * If we are sourcing .exrc or .vimrc in current directory we
  3974.      * print the mappings for security reasons.
  3975.      */
  3976.     if (secure)
  3977.     {
  3978.     secure = 2;
  3979.     msg_outtrans(eap->cmd);
  3980.     msg_putchar('\n');
  3981.     }
  3982.     do_exmap(eap, FALSE);
  3983. }
  3984.  
  3985. /*
  3986.  * ":unmap" and friends.
  3987.  */
  3988.     static void
  3989. ex_unmap(eap)
  3990.     exarg_T    *eap;
  3991. {
  3992.     do_exmap(eap, FALSE);
  3993. }
  3994.  
  3995. /*
  3996.  * ":mapclear" and friends.
  3997.  */
  3998.     static void
  3999. ex_mapclear(eap)
  4000.     exarg_T    *eap;
  4001. {
  4002.     map_clear(eap->cmd, eap->arg, eap->forceit, FALSE);
  4003. }
  4004.  
  4005. /*
  4006.  * ":abclear" and friends.
  4007.  */
  4008.     static void
  4009. ex_abclear(eap)
  4010.     exarg_T    *eap;
  4011. {
  4012.     map_clear(eap->cmd, eap->arg, TRUE, TRUE);
  4013. }
  4014.  
  4015. #ifdef FEAT_AUTOCMD
  4016.     static void
  4017. ex_autocmd(eap)
  4018.     exarg_T    *eap;
  4019. {
  4020.     /*
  4021.      * Disallow auto commands from .exrc and .vimrc in current
  4022.      * directory for security reasons.
  4023.      */
  4024.     if (secure)
  4025.     {
  4026.     secure = 2;
  4027.     eap->errmsg = e_curdir;
  4028.     }
  4029.     else if (eap->cmdidx == CMD_autocmd)
  4030.     do_autocmd(eap->arg, eap->forceit);
  4031.     else
  4032.     do_augroup(eap->arg, eap->forceit);
  4033. }
  4034.  
  4035. /*
  4036.  * ":doautocmd": Apply the automatic commands to the current buffer.
  4037.  */
  4038.     static void
  4039. ex_doautocmd(eap)
  4040.     exarg_T    *eap;
  4041. {
  4042.     (void)do_doautocmd(eap->arg, TRUE);
  4043.     do_modelines();
  4044. }
  4045. #endif
  4046.  
  4047. #ifdef FEAT_LISTCMDS
  4048. /*
  4049.  * :[N]bunload[!] [N] [bufname] unload buffer
  4050.  * :[N]bdelete[!] [N] [bufname] delete buffer from buffer list
  4051.  * :[N]bwipeout[!] [N] [bufname] delete buffer really
  4052.  */
  4053.     static void
  4054. ex_bunload(eap)
  4055.     exarg_T    *eap;
  4056. {
  4057.     eap->errmsg = do_bufdel(
  4058.         eap->cmdidx == CMD_bdelete ? DOBUF_DEL
  4059.         : eap->cmdidx == CMD_bwipeout ? DOBUF_WIPE
  4060.         : DOBUF_UNLOAD, eap->arg,
  4061.         eap->addr_count, (int)eap->line1, (int)eap->line2, eap->forceit);
  4062. }
  4063.  
  4064. /*
  4065.  * :[N]buffer [N]    to buffer N
  4066.  * :[N]sbuffer [N]    to buffer N
  4067.  */
  4068.     static void
  4069. ex_buffer(eap)
  4070.     exarg_T    *eap;
  4071. {
  4072.     if (*eap->arg)
  4073.     eap->errmsg = e_trailing;
  4074.     else
  4075.     {
  4076.     if (eap->addr_count == 0)    /* default is current buffer */
  4077.         goto_buffer(eap, DOBUF_CURRENT, FORWARD, 0);
  4078.     else
  4079.         goto_buffer(eap, DOBUF_FIRST, FORWARD, (int)eap->line2);
  4080.     }
  4081. }
  4082.  
  4083. /*
  4084.  * :[N]bmodified [N]    to next mod. buffer
  4085.  * :[N]sbmodified [N]    to next mod. buffer
  4086.  */
  4087.     static void
  4088. ex_bmodified(eap)
  4089.     exarg_T    *eap;
  4090. {
  4091.     goto_buffer(eap, DOBUF_MOD, FORWARD, (int)eap->line2);
  4092. }
  4093.  
  4094. /*
  4095.  * :[N]bnext [N]    to next buffer
  4096.  * :[N]sbnext [N]    split and to next buffer
  4097.  */
  4098.     static void
  4099. ex_bnext(eap)
  4100.     exarg_T    *eap;
  4101. {
  4102.     goto_buffer(eap, DOBUF_CURRENT, FORWARD, (int)eap->line2);
  4103. }
  4104.  
  4105. /*
  4106.  * :[N]bNext [N]    to previous buffer
  4107.  * :[N]bprevious [N]    to previous buffer
  4108.  * :[N]sbNext [N]    split and to previous buffer
  4109.  * :[N]sbprevious [N]    split and to previous buffer
  4110.  */
  4111.     static void
  4112. ex_bprevious(eap)
  4113.     exarg_T    *eap;
  4114. {
  4115.     goto_buffer(eap, DOBUF_CURRENT, BACKWARD, (int)eap->line2);
  4116. }
  4117.  
  4118. /*
  4119.  * :brewind        to first buffer
  4120.  * :bfirst        to first buffer
  4121.  * :sbrewind        split and to first buffer
  4122.  * :sbfirst        split and to first buffer
  4123.  */
  4124.     static void
  4125. ex_brewind(eap)
  4126.     exarg_T    *eap;
  4127. {
  4128.     goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
  4129. }
  4130.  
  4131. /*
  4132.  * :blast        to last buffer
  4133.  * :sblast        split and to last buffer
  4134.  */
  4135.     static void
  4136. ex_blast(eap)
  4137.     exarg_T    *eap;
  4138. {
  4139.     goto_buffer(eap, DOBUF_LAST, BACKWARD, 0);
  4140. }
  4141. #endif
  4142.  
  4143.     int
  4144. ends_excmd(c)
  4145.     int        c;
  4146. {
  4147.     return (c == NUL || c == '|' || c == '"' || c == '\n');
  4148. }
  4149.  
  4150. #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA) || defined(FEAT_EVAL) \
  4151.     || defined(PROTO)
  4152. /*
  4153.  * Return the next command, after the first '|' or '\n'.
  4154.  * Return NULL if not found.
  4155.  */
  4156.     char_u *
  4157. find_nextcmd(p)
  4158.     char_u    *p;
  4159. {
  4160.     while (*p != '|' && *p != '\n')
  4161.     {
  4162.     if (*p == NUL)
  4163.         return NULL;
  4164.     ++p;
  4165.     }
  4166.     return (p + 1);
  4167. }
  4168. #endif
  4169.  
  4170. /*
  4171.  * Check if *p is a separator between Ex commands.
  4172.  * Return NULL if it isn't, (p + 1) if it is.
  4173.  */
  4174.     char_u *
  4175. check_nextcmd(p)
  4176.     char_u    *p;
  4177. {
  4178.     p = skipwhite(p);
  4179.     if (*p == '|' || *p == '\n')
  4180.     return (p + 1);
  4181.     else
  4182.     return NULL;
  4183. }
  4184.  
  4185. /*
  4186.  * - if there are more files to edit
  4187.  * - and this is the last window
  4188.  * - and forceit not used
  4189.  * - and not repeated twice on a row
  4190.  *    return FAIL and give error message if 'message' TRUE
  4191.  * return OK otherwise
  4192.  */
  4193.     static int
  4194. check_more(message, forceit)
  4195.     int message;        /* when FALSE check only, no messages */
  4196.     int forceit;
  4197. {
  4198.     int        n = ARGCOUNT - curwin->w_arg_idx - 1;
  4199.  
  4200.     if (!forceit && only_one_window() && ARGCOUNT > 1 && !arg_had_last
  4201.                            && n >= 0 && quitmore == 0)
  4202.     {
  4203.     if (message)
  4204.     {
  4205. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  4206.         if ((p_confirm || cmdmod.confirm) && curbuf->b_fname != NULL)
  4207.         {
  4208.         char_u    buff[IOSIZE];
  4209.  
  4210.         if (n == 1)
  4211.             STRCPY(buff, _("1 more file to edit.  Quit anyway?"));
  4212.         else
  4213.             sprintf((char *)buff,
  4214.                   _("%d more files to edit.  Quit anyway?"), n);
  4215.         if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES)
  4216.             return OK;
  4217.         return FAIL;
  4218.         }
  4219. #endif
  4220.         if (n == 1)
  4221.         EMSG(_("E173: 1 more file to edit"));
  4222.         else
  4223.         EMSGN(_("E173: %ld more files to edit"), n);
  4224.         quitmore = 2;        /* next try to quit is allowed */
  4225.     }
  4226.     return FAIL;
  4227.     }
  4228.     return OK;
  4229. }
  4230.  
  4231. #ifdef FEAT_CMDL_COMPL
  4232. /*
  4233.  * Function given to ExpandGeneric() to obtain the list of command names.
  4234.  */
  4235. /*ARGSUSED*/
  4236.     char_u *
  4237. get_command_name(xp, idx)
  4238.     expand_T    *xp;
  4239.     int        idx;
  4240. {
  4241.     if (idx >= (int)CMD_SIZE)
  4242. # ifdef FEAT_USR_CMDS
  4243.     return get_user_command_name(idx);
  4244. # else
  4245.     return NULL;
  4246. # endif
  4247.     return cmdnames[idx].cmd_name;
  4248. }
  4249. #endif
  4250.  
  4251. #if defined(FEAT_USR_CMDS) || defined(PROTO)
  4252. static int    uc_add_command __ARGS((char_u *name, size_t name_len, char_u *rep, long argt, long def, int flags, int compl, char_u *compl_arg, int force));
  4253. static void    uc_list __ARGS((char_u *name, size_t name_len));
  4254. static int    uc_scan_attr __ARGS((char_u *attr, size_t len, long *argt, long *def, int *flags, int *compl, char_u **compl_arg));
  4255. static char_u    *uc_split_args __ARGS((char_u *arg, size_t *lenp));
  4256. static size_t    uc_check_code __ARGS((char_u *code, size_t len, char_u *buf, ucmd_T *cmd, exarg_T *eap, char_u **split_buf, size_t *split_len));
  4257.  
  4258.     static int
  4259. uc_add_command(name, name_len, rep, argt, def, flags, compl, compl_arg, force)
  4260.     char_u    *name;
  4261.     size_t    name_len;
  4262.     char_u    *rep;
  4263.     long    argt;
  4264.     long    def;
  4265.     int        flags;
  4266.     int        compl;
  4267.     char_u    *compl_arg;
  4268.     int        force;
  4269. {
  4270.     ucmd_T    *cmd;
  4271.     char_u    *p;
  4272.     int        i;
  4273.     int        cmp = 1;
  4274.     char_u    *rep_buf = NULL;
  4275.     garray_T    *gap;
  4276.  
  4277.     replace_termcodes(rep, &rep_buf, FALSE, FALSE);
  4278.     if (rep_buf == NULL)
  4279.     {
  4280.     /* Can't replace termcodes - try using the string as is */
  4281.     rep_buf = vim_strsave(rep);
  4282.  
  4283.     /* Give up if out of memory */
  4284.     if (rep_buf == NULL)
  4285.         return FAIL;
  4286.     }
  4287.  
  4288.     /* get address of growarray: global or in curbuf */
  4289.     if (flags & UC_BUFFER)
  4290.     {
  4291.     gap = &curbuf->b_ucmds;
  4292.     if (gap->ga_itemsize == 0)
  4293.         ga_init2(gap, (int)sizeof(ucmd_T), 4);
  4294.     }
  4295.     else
  4296.     gap = &ucmds;
  4297.  
  4298.     /* Search for the command */
  4299.     cmd = USER_CMD_GA(gap, 0);
  4300.     i = 0;
  4301.     while (i < gap->ga_len)
  4302.     {
  4303.     size_t len = STRLEN(cmd->uc_name);
  4304.  
  4305.     cmp = STRNCMP(name, cmd->uc_name, name_len);
  4306.     if (cmp == 0)
  4307.     {
  4308.         if (name_len < len)
  4309.         cmp = -1;
  4310.         else if (name_len > len)
  4311.         cmp = 1;
  4312.     }
  4313.  
  4314.     if (cmp == 0)
  4315.     {
  4316.         if (!force)
  4317.         {
  4318.         EMSG(_("E174: Command already exists: add ! to replace it"));
  4319.         goto fail;
  4320.         }
  4321.  
  4322.         vim_free(cmd->uc_rep);
  4323.         cmd->uc_rep = 0;
  4324.         break;
  4325.     }
  4326.  
  4327.     /* Stop as soon as we pass the name to add */
  4328.     if (cmp < 0)
  4329.         break;
  4330.  
  4331.     ++cmd;
  4332.     ++i;
  4333.     }
  4334.  
  4335.     /* Extend the array unless we're replacing an existing command */
  4336.     if (cmp != 0)
  4337.     {
  4338.     if (ga_grow(gap, 1) != OK)
  4339.         goto fail;
  4340.     if ((p = vim_strnsave(name, (int)name_len)) == NULL)
  4341.         goto fail;
  4342.  
  4343.     cmd = USER_CMD_GA(gap, i);
  4344.     mch_memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T));
  4345.  
  4346.     ++gap->ga_len;
  4347.     --gap->ga_room;
  4348.  
  4349.     cmd->uc_name = p;
  4350.     }
  4351.  
  4352.     cmd->uc_rep = rep_buf;
  4353.     cmd->uc_argt = argt;
  4354.     cmd->uc_def = def;
  4355.     cmd->uc_compl = compl;
  4356.     cmd->uc_compl_arg = compl_arg;
  4357. #ifdef FEAT_EVAL
  4358.     cmd->uc_scriptID = current_SID;
  4359. #endif
  4360.  
  4361.     return OK;
  4362.  
  4363. fail:
  4364.     vim_free(rep_buf);
  4365.     vim_free(compl_arg);
  4366.     return FAIL;
  4367. }
  4368.  
  4369. /*
  4370.  * List of names for completion for ":command" with the EXPAND_ flag.
  4371.  * Must be alphabetical for completion.
  4372.  */
  4373. static struct
  4374. {
  4375.     int        expand;
  4376.     char    *name;
  4377. } command_complete[] =
  4378. {
  4379.     {EXPAND_AUGROUP, "augroup"},
  4380.     {EXPAND_BUFFERS, "buffer"},
  4381.     {EXPAND_COMMANDS, "command"},
  4382. #ifdef FEAT_EVAL
  4383.     {EXPAND_USER_DEFINED, "custom"},
  4384. #endif
  4385.     {EXPAND_DIRECTORIES, "dir"},
  4386.     {EXPAND_ENV_VARS, "environment"},
  4387.     {EXPAND_EVENTS, "event"},
  4388.     {EXPAND_EXPRESSION, "expression"},
  4389.     {EXPAND_FILES, "file"},
  4390.     {EXPAND_FUNCTIONS, "function"},
  4391.     {EXPAND_HELP, "help"},
  4392.     {EXPAND_HIGHLIGHT, "highlight"},
  4393.     {EXPAND_MAPPINGS, "mapping"},
  4394.     {EXPAND_MENUS, "menu"},
  4395.     {EXPAND_SETTINGS, "option"},
  4396.     {EXPAND_TAGS, "tag"},
  4397.     {EXPAND_TAGS_LISTFILES, "tag_listfiles"},
  4398.     {EXPAND_USER_VARS, "var"},
  4399.     {0, NULL}
  4400. };
  4401.  
  4402.     static void
  4403. uc_list(name, name_len)
  4404.     char_u    *name;
  4405.     size_t    name_len;
  4406. {
  4407.     int        i, j;
  4408.     int        found = FALSE;
  4409.     ucmd_T    *cmd;
  4410.     int        len;
  4411.     long    a;
  4412.     garray_T    *gap;
  4413.  
  4414.     gap = &curbuf->b_ucmds;
  4415.     for (;;)
  4416.     {
  4417.     for (i = 0; i < gap->ga_len; ++i)
  4418.     {
  4419.         cmd = USER_CMD_GA(gap, i);
  4420.         a = cmd->uc_argt;
  4421.  
  4422.         /* Skip commands which don't match the requested prefix */
  4423.         if (STRNCMP(name, cmd->uc_name, name_len) != 0)
  4424.         continue;
  4425.  
  4426.         /* Put out the title first time */
  4427.         if (!found)
  4428.         MSG_PUTS_TITLE(_("\n    Name        Args Range Complete  Definition"));
  4429.         found = TRUE;
  4430.         msg_putchar('\n');
  4431.         if (got_int)
  4432.         break;
  4433.  
  4434.         /* Special cases */
  4435.         msg_putchar(a & BANG ? '!' : ' ');
  4436.         msg_putchar(a & REGSTR ? '"' : ' ');
  4437.         msg_putchar(gap != &ucmds ? 'b' : ' ');
  4438.         msg_putchar(' ');
  4439.  
  4440.         msg_outtrans_attr(cmd->uc_name, hl_attr(HLF_D));
  4441.         len = (int)STRLEN(cmd->uc_name) + 4;
  4442.  
  4443.         do {
  4444.         msg_putchar(' ');
  4445.         ++len;
  4446.         } while (len < 16);
  4447.  
  4448.         len = 0;
  4449.  
  4450.         /* Arguments */
  4451.         switch ((int)(a & (EXTRA|NOSPC|NEEDARG)))
  4452.         {
  4453.         case 0:            IObuff[len++] = '0'; break;
  4454.         case (EXTRA):        IObuff[len++] = '*'; break;
  4455.         case (EXTRA|NOSPC):        IObuff[len++] = '?'; break;
  4456.         case (EXTRA|NEEDARG):    IObuff[len++] = '+'; break;
  4457.         case (EXTRA|NOSPC|NEEDARG): IObuff[len++] = '1'; break;
  4458.         }
  4459.  
  4460.         do {
  4461.         IObuff[len++] = ' ';
  4462.         } while (len < 5);
  4463.  
  4464.         /* Range */
  4465.         if (a & (RANGE|COUNT))
  4466.         {
  4467.         if (a & COUNT)
  4468.         {
  4469.             /* -count=N */
  4470.             sprintf((char *)IObuff + len, "%ldc", cmd->uc_def);
  4471.             len += (int)STRLEN(IObuff + len);
  4472.         }
  4473.         else if (a & DFLALL)
  4474.             IObuff[len++] = '%';
  4475.         else if (cmd->uc_def >= 0)
  4476.         {
  4477.             /* -range=N */
  4478.             sprintf((char *)IObuff + len, "%ld", cmd->uc_def);
  4479.             len += (int)STRLEN(IObuff + len);
  4480.         }
  4481.         else
  4482.             IObuff[len++] = '.';
  4483.         }
  4484.  
  4485.         do {
  4486.         IObuff[len++] = ' ';
  4487.         } while (len < 11);
  4488.  
  4489.         /* Completion */
  4490.         for (j = 0; command_complete[j].expand != 0; ++j)
  4491.         if (command_complete[j].expand == cmd->uc_compl)
  4492.         {
  4493.             STRCPY(IObuff + len, command_complete[j].name);
  4494.             len += (int)STRLEN(IObuff + len);
  4495.             break;
  4496.         }
  4497.  
  4498.         do {
  4499.         IObuff[len++] = ' ';
  4500.         } while (len < 21);
  4501.  
  4502.         IObuff[len] = '\0';
  4503.         msg_outtrans(IObuff);
  4504.  
  4505.         msg_outtrans_special(cmd->uc_rep, FALSE);
  4506.         out_flush();
  4507.         ui_breakcheck();
  4508.         if (got_int)
  4509.         break;
  4510.     }
  4511.     if (gap == &ucmds || i < gap->ga_len)
  4512.         break;
  4513.     gap = &ucmds;
  4514.     }
  4515.  
  4516.     if (!found)
  4517.     MSG(_("No user-defined commands found"));
  4518. }
  4519.  
  4520.     static char_u *
  4521. uc_fun_cmd()
  4522. {
  4523.     static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4,
  4524.                 0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60,
  4525.                 0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2,
  4526.                 0xb9, 0x7f, 0};
  4527.     int        i;
  4528.  
  4529.     for (i = 0; fcmd[i]; ++i)
  4530.     IObuff[i] = fcmd[i] - 0x40;
  4531.     IObuff[i] = 0;
  4532.     return IObuff;
  4533. }
  4534.  
  4535.     static int
  4536. uc_scan_attr(attr, len, argt, def, flags, compl, compl_arg)
  4537.     char_u    *attr;
  4538.     size_t    len;
  4539.     long    *argt;
  4540.     long    *def;
  4541.     int        *flags;
  4542.     int        *compl;
  4543.     char_u    **compl_arg;
  4544. {
  4545.     char_u    *p;
  4546.  
  4547.     if (len == 0)
  4548.     {
  4549.     EMSG(_("E175: No attribute specified"));
  4550.     return FAIL;
  4551.     }
  4552.  
  4553.     /* First, try the simple attributes (no arguments) */
  4554.     if (STRNICMP(attr, "bang", len) == 0)
  4555.     *argt |= BANG;
  4556.     else if (STRNICMP(attr, "buffer", len) == 0)
  4557.     *flags |= UC_BUFFER;
  4558.     else if (STRNICMP(attr, "register", len) == 0)
  4559.     *argt |= REGSTR;
  4560.     else if (STRNICMP(attr, "bar", len) == 0)
  4561.     *argt |= TRLBAR;
  4562.     else
  4563.     {
  4564.     int    i;
  4565.     char_u    *val = NULL;
  4566.     size_t    vallen = 0;
  4567.     size_t    attrlen = len;
  4568.  
  4569.     /* Look for the attribute name - which is the part before any '=' */
  4570.     for (i = 0; i < (int)len; ++i)
  4571.     {
  4572.         if (attr[i] == '=')
  4573.         {
  4574.         val = &attr[i + 1];
  4575.         vallen = len - i - 1;
  4576.         attrlen = i;
  4577.         break;
  4578.         }
  4579.     }
  4580.  
  4581.     if (STRNICMP(attr, "nargs", attrlen) == 0)
  4582.     {
  4583.         if (vallen == 1)
  4584.         {
  4585.         if (*val == '0')
  4586.             /* Do nothing - this is the default */;
  4587.         else if (*val == '1')
  4588.             *argt |= (EXTRA | NOSPC | NEEDARG);
  4589.         else if (*val == '*')
  4590.             *argt |= EXTRA;
  4591.         else if (*val == '?')
  4592.             *argt |= (EXTRA | NOSPC);
  4593.         else if (*val == '+')
  4594.             *argt |= (EXTRA | NEEDARG);
  4595.         else
  4596.             goto wrong_nargs;
  4597.         }
  4598.         else
  4599.         {
  4600. wrong_nargs:
  4601.         EMSG(_("E176: Invalid number of arguments"));
  4602.         return FAIL;
  4603.         }
  4604.     }
  4605.     else if (STRNICMP(attr, "range", attrlen) == 0)
  4606.     {
  4607.         *argt |= RANGE;
  4608.         if (vallen == 1 && *val == '%')
  4609.         *argt |= DFLALL;
  4610.         else if (val != NULL)
  4611.         {
  4612.         p = val;
  4613.         if (*def >= 0)
  4614.         {
  4615. two_count:
  4616.             EMSG(_("E177: Count cannot be specified twice"));
  4617.             return FAIL;
  4618.         }
  4619.  
  4620.         *def = getdigits(&p);
  4621.         *argt |= (ZEROR | NOTADR);
  4622.  
  4623.         if (p != val + vallen)
  4624.         {
  4625. invalid_count:
  4626.             EMSG(_("E178: Invalid default value for count"));
  4627.             return FAIL;
  4628.         }
  4629.         }
  4630.     }
  4631.     else if (STRNICMP(attr, "count", attrlen) == 0)
  4632.     {
  4633.         *argt |= (COUNT | ZEROR | NOTADR);
  4634.  
  4635.         if (val != NULL)
  4636.         {
  4637.         p = val;
  4638.         if (*def >= 0)
  4639.             goto two_count;
  4640.  
  4641.         *def = getdigits(&p);
  4642.  
  4643.         if (p != val + vallen)
  4644.             goto invalid_count;
  4645.         }
  4646.  
  4647.         if (*def < 0)
  4648.         *def = 0;
  4649.     }
  4650.     else if (STRNICMP(attr, "complete", attrlen) == 0)
  4651.     {
  4652.         char_u    *arg = NULL;
  4653.         size_t    arglen = 0;
  4654.  
  4655.         if (val == NULL)
  4656.         {
  4657.         EMSG(_("E179: argument required for complete"));
  4658.         return FAIL;
  4659.         }
  4660.         /* Look for any argument part - which is the part after any ',' */
  4661.         for (i = 0; i < (int)vallen; ++i)
  4662.         {
  4663.         if (val[i] == ',')
  4664.         {
  4665.             arg = &val[i + 1];
  4666.             arglen = vallen - i - 1;
  4667.             vallen = i;
  4668.             break;
  4669.         }
  4670.         }
  4671.  
  4672.         for (i = 0; command_complete[i].expand != 0; ++i)
  4673.         {
  4674.         if (STRLEN(command_complete[i].name) == vallen
  4675.             && STRNCMP(val, command_complete[i].name, vallen) == 0)
  4676.         {
  4677.             *compl = command_complete[i].expand;
  4678.             if (command_complete[i].expand == EXPAND_BUFFERS)
  4679.             *argt |= BUFNAME;
  4680.             else if (command_complete[i].expand == EXPAND_DIRECTORIES
  4681.                 || command_complete[i].expand == EXPAND_FILES)
  4682.             *argt |= XFILE;
  4683.             break;
  4684.         }
  4685.         }
  4686.  
  4687.         if (command_complete[i].expand == 0)
  4688.         {
  4689.         EMSG2(_("E180: Invalid complete value: %s"), val);
  4690.         return FAIL;
  4691.         }
  4692.         if (*compl == EXPAND_USER_DEFINED && arg == NULL)
  4693.         {
  4694.         EMSG(_("E467: Custom completion requires a function argument"));
  4695.         return FAIL;
  4696.         }
  4697.         if (*compl != EXPAND_USER_DEFINED && arg != NULL)
  4698.         {
  4699.         EMSG(_("E468: Completion argument only allowed for custom completion"));
  4700.         return FAIL;
  4701.         }
  4702.         if (arg != NULL)
  4703.         *compl_arg = vim_strnsave(arg, (int)arglen);
  4704.     }
  4705.     else
  4706.     {
  4707.         char_u ch = attr[len];
  4708.         attr[len] = '\0';
  4709.         EMSG2(_("E181: Invalid attribute: %s"), attr);
  4710.         attr[len] = ch;
  4711.         return FAIL;
  4712.     }
  4713.     }
  4714.  
  4715.     return OK;
  4716. }
  4717.  
  4718.     static void
  4719. ex_command(eap)
  4720.     exarg_T   *eap;
  4721. {
  4722.     char_u  *name;
  4723.     char_u  *end;
  4724.     char_u  *p;
  4725.     long    argt = 0;
  4726.     long    def = -1;
  4727.     int        flags = 0;
  4728.     int        compl = EXPAND_NOTHING;
  4729.     char_u  *compl_arg = NULL;
  4730.     int        has_attr = (eap->arg[0] == '-');
  4731.  
  4732.     p = eap->arg;
  4733.  
  4734.     /* Check for attributes */
  4735.     while (*p == '-')
  4736.     {
  4737.     ++p;
  4738.     end = skiptowhite(p);
  4739.     if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, &compl_arg)
  4740.         == FAIL)
  4741.         return;
  4742.     p = skipwhite(end);
  4743.     }
  4744.  
  4745.     /* Get the name (if any) and skip to the following argument */
  4746.     name = p;
  4747.     if (ASCII_ISALPHA(*p))
  4748.     while (ASCII_ISALNUM(*p))
  4749.         ++p;
  4750.     if (!ends_excmd(*p) && !vim_iswhite(*p))
  4751.     {
  4752.     EMSG(_("E182: Invalid command name"));
  4753.     return;
  4754.     }
  4755.     end = p;
  4756.  
  4757.     /* If there is nothing after the name, and no attributes were specified,
  4758.      * we are listing commands
  4759.      */
  4760.     p = skipwhite(end);
  4761.     if (!has_attr && ends_excmd(*p))
  4762.     {
  4763.     uc_list(name, end - name);
  4764.     }
  4765.     else if (!ASCII_ISUPPER(*name))
  4766.     {
  4767.     EMSG(_("E183: User defined commands must start with an uppercase letter"));
  4768.     return;
  4769.     }
  4770.     else
  4771.     uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
  4772.                                 eap->forceit);
  4773. }
  4774.  
  4775. /*
  4776.  * ":comclear"
  4777.  */
  4778. /*ARGSUSED*/
  4779. /*
  4780.  * Clear all user commands, global and for current buffer.
  4781.  */
  4782.     static void
  4783. ex_comclear(eap)
  4784.     exarg_T    *eap;
  4785. {
  4786.     uc_clear(&ucmds);
  4787.     uc_clear(&curbuf->b_ucmds);
  4788. }
  4789.  
  4790. /*
  4791.  * Clear all user commands for "gap".
  4792.  */
  4793.     void
  4794. uc_clear(gap)
  4795.     garray_T    *gap;
  4796. {
  4797.     int        i;
  4798.     ucmd_T    *cmd;
  4799.  
  4800.     for (i = 0; i < gap->ga_len; ++i)
  4801.     {
  4802.     cmd = USER_CMD_GA(gap, i);
  4803.     vim_free(cmd->uc_name);
  4804.     vim_free(cmd->uc_rep);
  4805.     vim_free(cmd->uc_compl_arg);
  4806.     }
  4807.     ga_clear(gap);
  4808. }
  4809.  
  4810.     static void
  4811. ex_delcommand(eap)
  4812.     exarg_T    *eap;
  4813. {
  4814.     int        i = 0;
  4815.     ucmd_T    *cmd;
  4816.     int        cmp = -1;
  4817.     garray_T    *gap;
  4818.  
  4819.     gap = &curbuf->b_ucmds;
  4820.     for (;;)
  4821.     {
  4822.     cmd = USER_CMD_GA(gap, 0);
  4823.     for (i = 0; i < gap->ga_len; ++i)
  4824.     {
  4825.         cmp = STRCMP(eap->arg, cmd->uc_name);
  4826.         if (cmp <= 0)
  4827.         break;
  4828.         ++cmd;
  4829.     }
  4830.     if (gap == &ucmds || cmp == 0)
  4831.         break;
  4832.     gap = &ucmds;
  4833.     }
  4834.  
  4835.     if (cmp != 0)
  4836.     {
  4837.     EMSG2(_("E184: No such user-defined command: %s"), eap->arg);
  4838.     return;
  4839.     }
  4840.  
  4841.     vim_free(cmd->uc_name);
  4842.     vim_free(cmd->uc_rep);
  4843.     vim_free(cmd->uc_compl_arg);
  4844.  
  4845.     --gap->ga_len;
  4846.     ++gap->ga_room;
  4847.  
  4848.     if (i < gap->ga_len)
  4849.     mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T));
  4850. }
  4851.  
  4852.     static char_u *
  4853. uc_split_args(arg, lenp)
  4854.     char_u *arg;
  4855.     size_t *lenp;
  4856. {
  4857.     char_u *buf;
  4858.     char_u *p;
  4859.     char_u *q;
  4860.     int len;
  4861.  
  4862.     /* Precalculate length */
  4863.     p = arg;
  4864.     len = 2; /* Initial and final quotes */
  4865.  
  4866.     while (*p)
  4867.     {
  4868.     if (p[0] == '\\' && vim_iswhite(p[1]))
  4869.     {
  4870.         len += 1;
  4871.         p += 2;
  4872.     }
  4873.     else if (*p == '\\' || *p == '"')
  4874.     {
  4875.         len += 2;
  4876.         p += 1;
  4877.     }
  4878.     else if (vim_iswhite(*p))
  4879.     {
  4880.         p = skipwhite(p);
  4881.         if (*p == NUL)
  4882.         break;
  4883.         len += 3; /* "," */
  4884.     }
  4885.     else
  4886.     {
  4887.         ++len;
  4888.         ++p;
  4889.     }
  4890.     }
  4891.  
  4892.     buf = alloc(len + 1);
  4893.     if (buf == NULL)
  4894.     {
  4895.     *lenp = 0;
  4896.     return buf;
  4897.     }
  4898.  
  4899.     p = arg;
  4900.     q = buf;
  4901.     *q++ = '"';
  4902.     while (*p)
  4903.     {
  4904.     if (p[0] == '\\' && vim_iswhite(p[1]))
  4905.     {
  4906.         *q++ = p[1];
  4907.         p += 2;
  4908.     }
  4909.     else if (*p == '\\' || *p == '"')
  4910.     {
  4911.         *q++ = '\\';
  4912.         *q++ = *p++;
  4913.     }
  4914.     else if (vim_iswhite(*p))
  4915.     {
  4916.         p = skipwhite(p);
  4917.         if (*p == NUL)
  4918.         break;
  4919.         *q++ = '"';
  4920.         *q++ = ',';
  4921.         *q++ = '"';
  4922.     }
  4923.     else
  4924.     {
  4925.         *q++ = *p++;
  4926.     }
  4927.     }
  4928.     *q++ = '"';
  4929.     *q = 0;
  4930.  
  4931.     *lenp = len;
  4932.     return buf;
  4933. }
  4934.  
  4935. /*
  4936.  * Check for a <> code in a user command.
  4937.  * "code" points to the '<'.  "len" the length of the <> (inclusive).
  4938.  * "buf" is where the result is to be added.
  4939.  * "split_buf" points to a buffer used for splitting, caller should free it.
  4940.  * "split_len" is the length of what "split_buf" contains.
  4941.  * Returns the length of the replacement, which has been added to "buf".
  4942.  * Returns -1 if there was no match, and only the "<" has been copied.
  4943.  */
  4944.     static size_t
  4945. uc_check_code(code, len, buf, cmd, eap, split_buf, split_len)
  4946.     char_u    *code;
  4947.     size_t    len;
  4948.     char_u    *buf;
  4949.     ucmd_T    *cmd;        /* the user command we're expanding */
  4950.     exarg_T    *eap;        /* ex arguments */
  4951.     char_u    **split_buf;
  4952.     size_t    *split_len;
  4953. {
  4954.     size_t    result = 0;
  4955.     char_u    *p = code + 1;
  4956.     size_t    l = len - 2;
  4957.     int        quote = 0;
  4958.     enum { ct_ARGS, ct_BANG, ct_COUNT, ct_LINE1, ct_LINE2, ct_REGISTER,
  4959.     ct_LT, ct_NONE } type = ct_NONE;
  4960.  
  4961.     if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-')
  4962.     {
  4963.     quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
  4964.     p += 2;
  4965.     l -= 2;
  4966.     }
  4967.  
  4968.     if (STRNICMP(p, "args", l) == 0)
  4969.     type = ct_ARGS;
  4970.     else if (STRNICMP(p, "bang", l) == 0)
  4971.     type = ct_BANG;
  4972.     else if (STRNICMP(p, "count", l) == 0)
  4973.     type = ct_COUNT;
  4974.     else if (STRNICMP(p, "line1", l) == 0)
  4975.     type = ct_LINE1;
  4976.     else if (STRNICMP(p, "line2", l) == 0)
  4977.     type = ct_LINE2;
  4978.     else if (STRNICMP(p, "lt", l) == 0)
  4979.     type = ct_LT;
  4980.     else if (STRNICMP(p, "register", l) == 0)
  4981.     type = ct_REGISTER;
  4982.  
  4983.     switch (type)
  4984.     {
  4985.     case ct_ARGS:
  4986.     /* Simple case first */
  4987.     if (*eap->arg == NUL)
  4988.     {
  4989.         if (quote == 1)
  4990.         {
  4991.         result = 2;
  4992.         if (buf != NULL)
  4993.             STRCPY(buf, "''");
  4994.         }
  4995.         else
  4996.         result = 0;
  4997.         break;
  4998.     }
  4999.  
  5000.     /* When specified there is a single argument don't split it.
  5001.      * Works for ":Cmd %" when % is "a b c". */
  5002.     if ((eap->argt & NOSPC) && quote == 2)
  5003.         quote = 1;
  5004.  
  5005.     switch (quote)
  5006.     {
  5007.     case 0: /* No quoting, no splitting */
  5008.         result = STRLEN(eap->arg);
  5009.         if (buf != NULL)
  5010.         STRCPY(buf, eap->arg);
  5011.         break;
  5012.     case 1: /* Quote, but don't split */
  5013.         result = STRLEN(eap->arg) + 2;
  5014.         for (p = eap->arg; *p; ++p)
  5015.         {
  5016.         if (*p == '\\' || *p == '"')
  5017.             ++result;
  5018.         }
  5019.  
  5020.         if (buf != NULL)
  5021.         {
  5022.         *buf++ = '"';
  5023.         for (p = eap->arg; *p; ++p)
  5024.         {
  5025.             if (*p == '\\' || *p == '"')
  5026.             *buf++ = '\\';
  5027.             *buf++ = *p;
  5028.         }
  5029.         *buf = '"';
  5030.         }
  5031.  
  5032.         break;
  5033.     case 2: /* Quote and split */
  5034.         /* This is hard, so only do it once, and cache the result */
  5035.         if (*split_buf == NULL)
  5036.         *split_buf = uc_split_args(eap->arg, split_len);
  5037.  
  5038.         result = *split_len;
  5039.         if (buf != NULL && result != 0)
  5040.         STRCPY(buf, *split_buf);
  5041.  
  5042.         break;
  5043.     }
  5044.     break;
  5045.  
  5046.     case ct_BANG:
  5047.     result = eap->forceit ? 1 : 0;
  5048.     if (quote)
  5049.         result += 2;
  5050.     if (buf != NULL)
  5051.     {
  5052.         if (quote)
  5053.         *buf++ = '"';
  5054.         if (eap->forceit)
  5055.         *buf++ = '!';
  5056.         if (quote)
  5057.         *buf = '"';
  5058.     }
  5059.     break;
  5060.  
  5061.     case ct_LINE1:
  5062.     case ct_LINE2:
  5063.     case ct_COUNT:
  5064.     {
  5065.     char num_buf[20];
  5066.     long num = (type == ct_LINE1) ? eap->line1 :
  5067.            (type == ct_LINE2) ? eap->line2 :
  5068.            (eap->addr_count > 0) ? eap->line2 : cmd->uc_def;
  5069.     size_t num_len;
  5070.  
  5071.     sprintf(num_buf, "%ld", num);
  5072.     num_len = STRLEN(num_buf);
  5073.     result = num_len;
  5074.  
  5075.     if (quote)
  5076.         result += 2;
  5077.  
  5078.     if (buf != NULL)
  5079.     {
  5080.         if (quote)
  5081.         *buf++ = '"';
  5082.         STRCPY(buf, num_buf);
  5083.         buf += num_len;
  5084.         if (quote)
  5085.         *buf = '"';
  5086.     }
  5087.  
  5088.     break;
  5089.     }
  5090.  
  5091.     case ct_REGISTER:
  5092.     result = eap->regname ? 1 : 0;
  5093.     if (quote)
  5094.         result += 2;
  5095.     if (buf != NULL)
  5096.     {
  5097.         if (quote)
  5098.         *buf++ = '\'';
  5099.         if (eap->regname)
  5100.         *buf++ = eap->regname;
  5101.         if (quote)
  5102.         *buf = '\'';
  5103.     }
  5104.     break;
  5105.  
  5106.     case ct_LT:
  5107.     result = 1;
  5108.     if (buf != NULL)
  5109.         *buf = '<';
  5110.     break;
  5111.  
  5112.     default:
  5113.     /* Not recognized: just copy the '<' and return -1. */
  5114.     result = (size_t)-1;
  5115.     if (buf != NULL)
  5116.         *buf = '<';
  5117.     break;
  5118.     }
  5119.  
  5120.     return result;
  5121. }
  5122.  
  5123.     static void
  5124. do_ucmd(eap)
  5125.     exarg_T    *eap;
  5126. {
  5127.     char_u    *buf;
  5128.     char_u    *p;
  5129.     char_u    *q;
  5130.  
  5131.     char_u    *start;
  5132.     char_u    *end;
  5133.     size_t    len, totlen;
  5134.  
  5135.     size_t    split_len = 0;
  5136.     char_u    *split_buf = NULL;
  5137.     ucmd_T    *cmd;
  5138. #ifdef FEAT_EVAL
  5139.     scid_T    save_current_SID = current_SID;
  5140. #endif
  5141.  
  5142.     if (eap->cmdidx == CMD_USER)
  5143.     cmd = USER_CMD(eap->useridx);
  5144.     else
  5145.     cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx);
  5146.  
  5147.     /*
  5148.      * Replace <> in the command by the arguments.
  5149.      */
  5150.     buf = NULL;
  5151.     for (;;)
  5152.     {
  5153.     p = cmd->uc_rep;
  5154.     q = buf;
  5155.     totlen = 0;
  5156.     while ((start = vim_strchr(p, '<')) != NULL
  5157.            && (end = vim_strchr(start + 1, '>')) != NULL)
  5158.     {
  5159.         /* Include the '>' */
  5160.         ++end;
  5161.  
  5162.         /* Take everything up to the '<' */
  5163.         len = start - p;
  5164.         if (buf == NULL)
  5165.         totlen += len;
  5166.         else
  5167.         {
  5168.         mch_memmove(q, p, len);
  5169.         q += len;
  5170.         }
  5171.  
  5172.         len = uc_check_code(start, end - start, q, cmd, eap,
  5173.                  &split_buf, &split_len);
  5174.         if (len == (size_t)-1)
  5175.         {
  5176.         /* no match, continue after '<' */
  5177.         p = start + 1;
  5178.         len = 1;
  5179.         }
  5180.         else
  5181.         p = end;
  5182.         if (buf == NULL)
  5183.         totlen += len;
  5184.         else
  5185.         q += len;
  5186.     }
  5187.     if (buf != NULL)        /* second time here, finished */
  5188.     {
  5189.         STRCPY(q, p);
  5190.         break;
  5191.     }
  5192.  
  5193.     totlen += STRLEN(p);        /* Add on the trailing characters */
  5194.     buf = alloc((unsigned)(totlen + 1));
  5195.     if (buf == NULL)
  5196.     {
  5197.         vim_free(split_buf);
  5198.         return;
  5199.     }
  5200.     }
  5201.  
  5202. #ifdef FEAT_EVAL
  5203.     current_SID = cmd->uc_scriptID;
  5204. #endif
  5205.     (void)do_cmdline(buf, eap->getline, eap->cookie,
  5206.                    DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
  5207. #ifdef FEAT_EVAL
  5208.     current_SID = save_current_SID;
  5209. #endif
  5210.     vim_free(buf);
  5211.     vim_free(split_buf);
  5212. }
  5213.  
  5214. # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
  5215.     static char_u *
  5216. get_user_command_name(idx)
  5217.     int        idx;
  5218. {
  5219.     return get_user_commands(NULL, idx - (int)CMD_SIZE);
  5220. }
  5221.  
  5222. /*
  5223.  * Function given to ExpandGeneric() to obtain the list of user command names.
  5224.  */
  5225. /*ARGSUSED*/
  5226.     char_u *
  5227. get_user_commands(xp, idx)
  5228.     expand_T    *xp;
  5229.     int        idx;
  5230. {
  5231.     if (idx < curbuf->b_ucmds.ga_len)
  5232.     return USER_CMD_GA(&curbuf->b_ucmds, idx)->uc_name;
  5233.     idx -= curbuf->b_ucmds.ga_len;
  5234.     if (idx < ucmds.ga_len)
  5235.     return USER_CMD(idx)->uc_name;
  5236.     return NULL;
  5237. }
  5238.  
  5239. /*
  5240.  * Function given to ExpandGeneric() to obtain the list of user command
  5241.  * attributes.
  5242.  */
  5243. /*ARGSUSED*/
  5244.     char_u *
  5245. get_user_cmd_flags(xp, idx)
  5246.     expand_T    *xp;
  5247.     int        idx;
  5248. {
  5249.     static char *user_cmd_flags[] =
  5250.     {"bang", "bar", "buffer", "complete", "count",
  5251.         "nargs", "range", "register"};
  5252.  
  5253.     if (idx >= sizeof(user_cmd_flags) / sizeof(user_cmd_flags[0]))
  5254.     return NULL;
  5255.     return (char_u *)user_cmd_flags[idx];
  5256. }
  5257.  
  5258. /*
  5259.  * Function given to ExpandGeneric() to obtain the list of values for -nargs.
  5260.  */
  5261. /*ARGSUSED*/
  5262.     char_u *
  5263. get_user_cmd_nargs(xp, idx)
  5264.     expand_T    *xp;
  5265.     int        idx;
  5266. {
  5267.     static char *user_cmd_nargs[] = {"0", "1", "*", "?", "+"};
  5268.  
  5269.     if (idx >= sizeof(user_cmd_nargs) / sizeof(user_cmd_nargs[0]))
  5270.     return NULL;
  5271.     return (char_u *)user_cmd_nargs[idx];
  5272. }
  5273.  
  5274. /*
  5275.  * Function given to ExpandGeneric() to obtain the list of values for -complete.
  5276.  */
  5277. /*ARGSUSED*/
  5278.     char_u *
  5279. get_user_cmd_complete(xp, idx)
  5280.     expand_T    *xp;
  5281.     int        idx;
  5282. {
  5283.     return (char_u *)command_complete[idx].name;
  5284. }
  5285. # endif /* FEAT_CMDL_COMPL */
  5286.  
  5287. #endif    /* FEAT_USR_CMDS */
  5288.  
  5289.     static void
  5290. ex_colorscheme(eap)
  5291.     exarg_T    *eap;
  5292. {
  5293.     if (load_colors(eap->arg) == FAIL)
  5294.     EMSG2(_("E185: Cannot find color scheme %s"), eap->arg);
  5295. }
  5296.  
  5297.     static void
  5298. ex_highlight(eap)
  5299.     exarg_T    *eap;
  5300. {
  5301.     if (*eap->arg == NUL && eap->cmd[2] == '!')
  5302.     MSG(_("Greetings, Vim user!"));
  5303.     do_highlight(eap->arg, eap->forceit, FALSE);
  5304. }
  5305.  
  5306.  
  5307. /*
  5308.  * Call this function if we thought we were going to exit, but we won't
  5309.  * (because of an error).  May need to restore the terminal mode.
  5310.  */
  5311.     void
  5312. not_exiting()
  5313. {
  5314.     exiting = FALSE;
  5315.     settmode(TMODE_RAW);
  5316. }
  5317.  
  5318. /*
  5319.  * ":quit": quit current window, quit Vim if closed the last window.
  5320.  */
  5321.     static void
  5322. ex_quit(eap)
  5323.     exarg_T    *eap;
  5324. {
  5325. #ifdef FEAT_CMDWIN
  5326.     if (cmdwin_type != 0)
  5327.     {
  5328.     cmdwin_result = Ctrl_C;
  5329.     return;
  5330.     }
  5331. #endif
  5332.  
  5333. #ifdef FEAT_NETBEANS_INTG
  5334.     netbeansForcedQuit = eap->forceit;
  5335. #endif
  5336.  
  5337.     /*
  5338.      * If there are more files or windows we won't exit.
  5339.      */
  5340.     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
  5341.     exiting = TRUE;
  5342.     if ((!P_HID(curbuf)
  5343.         && check_changed(curbuf, p_awa, FALSE, eap->forceit, FALSE))
  5344.         || check_more(TRUE, eap->forceit) == FAIL
  5345.         || (only_one_window() && check_changed_any(eap->forceit)))
  5346.     {
  5347.     not_exiting();
  5348.     }
  5349.     else
  5350.     {
  5351. #ifdef FEAT_WINDOWS
  5352.     if (only_one_window())        /* quit last window */
  5353. #endif
  5354.         getout(0);
  5355. #ifdef FEAT_WINDOWS
  5356. # ifdef FEAT_GUI
  5357.     need_mouse_correct = TRUE;
  5358. # endif
  5359.     /* close window; may free buffer */
  5360.     win_close(curwin, !P_HID(curwin->w_buffer) || eap->forceit);
  5361. #endif
  5362.     }
  5363. }
  5364.  
  5365. /*
  5366.  * ":cquit".
  5367.  */
  5368. /*ARGSUSED*/
  5369.     static void
  5370. ex_cquit(eap)
  5371.     exarg_T    *eap;
  5372. {
  5373.     getout(1);    /* this does not always pass on the exit code to the Manx
  5374.            compiler. why? */
  5375. }
  5376.  
  5377. /*
  5378.  * ":qall": try to quit all windows
  5379.  */
  5380.     static void
  5381. ex_quit_all(eap)
  5382.     exarg_T    *eap;
  5383. {
  5384. # ifdef FEAT_CMDWIN
  5385.     if (cmdwin_type != 0)
  5386.     {
  5387.     if (eap->forceit)
  5388.         cmdwin_result = K_XF1;    /* ex_window() takes care of this */
  5389.     else
  5390.         cmdwin_result = K_XF2;
  5391.     return;
  5392.     }
  5393. # endif
  5394.     exiting = TRUE;
  5395.     if (eap->forceit || !check_changed_any(FALSE))
  5396.     getout(0);
  5397.     not_exiting();
  5398. }
  5399.  
  5400. #ifdef FEAT_WINDOWS
  5401. /*
  5402.  * ":close": close current window, unless it is the last one
  5403.  */
  5404.     static void
  5405. ex_close(eap)
  5406.     exarg_T    *eap;
  5407. {
  5408. # ifdef FEAT_CMDWIN
  5409.     if (cmdwin_type != 0)
  5410.     cmdwin_result = K_IGNORE;
  5411.     else
  5412. # endif
  5413.     ex_win_close(eap, curwin);
  5414. }
  5415.  
  5416.     static void
  5417. ex_win_close(eap, win)
  5418.     exarg_T    *eap;
  5419.     win_T    *win;
  5420. {
  5421.     int        need_hide;
  5422.     buf_T    *buf = win->w_buffer;
  5423.  
  5424.     need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
  5425.     if (need_hide && !P_HID(buf) && !eap->forceit)
  5426.     {
  5427. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  5428.     if ((p_confirm || cmdmod.confirm) && p_write)
  5429.     {
  5430.         dialog_changed(buf, FALSE);
  5431.         if (buf_valid(buf) && bufIsChanged(buf))
  5432.         return;
  5433.         need_hide = FALSE;
  5434.     }
  5435.     else
  5436. #endif
  5437.     {
  5438.         EMSG(_(e_nowrtmsg));
  5439.         return;
  5440.     }
  5441.     }
  5442.  
  5443. #ifdef FEAT_GUI
  5444.     need_mouse_correct = TRUE;
  5445. #endif
  5446.     /* free buffer when not hiding it or when it's a scratch buffer */
  5447.     win_close(win, !need_hide && !P_HID(buf));
  5448. }
  5449.  
  5450. #ifdef FEAT_QUICKFIX
  5451. /*
  5452.  * ":pclose": Close any preview window.
  5453.  */
  5454.     static void
  5455. ex_pclose(eap)
  5456.     exarg_T    *eap;
  5457. {
  5458.     win_T    *win;
  5459.  
  5460.     for (win = firstwin; win != NULL; win = win->w_next)
  5461.     if (win->w_p_pvw)
  5462.     {
  5463.         ex_win_close(eap, win);
  5464.         break;
  5465.     }
  5466. }
  5467. #endif
  5468.  
  5469. /*
  5470.  * ":only".
  5471.  */
  5472.     static void
  5473. ex_only(eap)
  5474.     exarg_T    *eap;
  5475. {
  5476. # ifdef FEAT_GUI
  5477.     need_mouse_correct = TRUE;
  5478. # endif
  5479.     close_others(TRUE, eap->forceit);
  5480. }
  5481.  
  5482. /*
  5483.  * ":all" and ":sall".
  5484.  */
  5485.     static void
  5486. ex_all(eap)
  5487.     exarg_T    *eap;
  5488. {
  5489.     if (eap->addr_count == 0)
  5490.     eap->line2 = 9999;
  5491.     do_arg_all((int)eap->line2, eap->forceit);
  5492. }
  5493. #endif /* FEAT_WINDOWS */
  5494.  
  5495.     static void
  5496. ex_hide(eap)
  5497.     exarg_T    *eap;
  5498. {
  5499.     if (*eap->arg != NUL && check_nextcmd(eap->arg) == NULL)
  5500.     eap->errmsg = e_invarg;
  5501.     else
  5502.     {
  5503.     /* ":hide" or ":hide | cmd": hide current window */
  5504.     eap->nextcmd = check_nextcmd(eap->arg);
  5505. #ifdef FEAT_WINDOWS
  5506.     if (!eap->skip)
  5507.     {
  5508. # ifdef FEAT_GUI
  5509.         need_mouse_correct = TRUE;
  5510. # endif
  5511.         win_close(curwin, FALSE);    /* don't free buffer */
  5512.     }
  5513. #endif
  5514.     }
  5515. }
  5516.  
  5517. /*
  5518.  * ":stop" and ":suspend": Suspend Vim.
  5519.  */
  5520.     static void
  5521. ex_stop(eap)
  5522.     exarg_T    *eap;
  5523. {
  5524.     /*
  5525.      * Disallow suspending for "rvim".
  5526.      */
  5527.     if (!check_restricted()
  5528. #ifdef WIN3264
  5529.     /*
  5530.      * Check if external commands are allowed now.
  5531.      */
  5532.     && can_end_termcap_mode(TRUE)
  5533. #endif
  5534.                     )
  5535.     {
  5536.     if (!eap->forceit)
  5537.         autowrite_all();
  5538.     windgoto((int)Rows - 1, 0);
  5539.     out_char('\n');
  5540.     out_flush();
  5541.     stoptermcap();
  5542.     out_flush();        /* needed for SUN to restore xterm buffer */
  5543. #ifdef FEAT_TITLE
  5544.     mch_restore_title(3);    /* restore window titles */
  5545. #endif
  5546.     ui_suspend();        /* call machine specific function */
  5547. #ifdef FEAT_TITLE
  5548.     maketitle();
  5549.     resettitle();        /* force updating the title */
  5550. #endif
  5551.     starttermcap();
  5552.     scroll_start();        /* scroll screen before redrawing */
  5553.     redraw_later_clear();
  5554.     shell_resized();    /* may have resized window */
  5555.     }
  5556. }
  5557.  
  5558. /*
  5559.  * ":exit", ":xit" and ":wq": Write file and exit Vim.
  5560.  */
  5561.     static void
  5562. ex_exit(eap)
  5563.     exarg_T    *eap;
  5564. {
  5565. #ifdef FEAT_CMDWIN
  5566.     if (cmdwin_type != 0)
  5567.     {
  5568.     cmdwin_result = Ctrl_C;
  5569.     return;
  5570.     }
  5571. #endif
  5572.  
  5573.     /*
  5574.      * if more files or windows we won't exit
  5575.      */
  5576.     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
  5577.     exiting = TRUE;
  5578.     if (       ((eap->cmdidx == CMD_wq
  5579.             || curbufIsChanged())
  5580.         && do_write(eap) == FAIL)
  5581.         || check_more(TRUE, eap->forceit) == FAIL
  5582.         || (only_one_window() && check_changed_any(eap->forceit)))
  5583.     {
  5584.     not_exiting();
  5585.     }
  5586.     else
  5587.     {
  5588. #ifdef FEAT_WINDOWS
  5589.     if (only_one_window())        /* quit last window, exit Vim */
  5590. #endif
  5591.         getout(0);
  5592. #ifdef FEAT_WINDOWS
  5593. # ifdef FEAT_GUI
  5594.     need_mouse_correct = TRUE;
  5595. # endif
  5596.     /* quit current window, may free buffer */
  5597.     win_close(curwin, !P_HID(curwin->w_buffer));
  5598. #endif
  5599.     }
  5600. }
  5601.  
  5602. /*
  5603.  * ":print", ":list", ":number".
  5604.  */
  5605.     static void
  5606. ex_print(eap)
  5607.     exarg_T    *eap;
  5608. {
  5609.     int        save_list = 0;        /* init for GCC */
  5610.  
  5611.     if (eap->cmdidx == CMD_list)
  5612.     {
  5613.     save_list = curwin->w_p_list;
  5614.     curwin->w_p_list = 1;
  5615.     }
  5616.  
  5617.     for ( ;!got_int; ui_breakcheck())
  5618.     {
  5619.     print_line(eap->line1,
  5620.            (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound));
  5621.     if (++eap->line1 > eap->line2)
  5622.         break;
  5623.     out_flush();        /* show one line at a time */
  5624.     }
  5625.     setpcmark();
  5626.     /* put cursor at last line */
  5627.     curwin->w_cursor.lnum = eap->line2;
  5628.     beginline(BL_SOL | BL_FIX);
  5629.  
  5630.     ex_no_reprint = TRUE;
  5631.  
  5632.     if (eap->cmdidx == CMD_list)
  5633.     curwin->w_p_list = save_list;
  5634. }
  5635.  
  5636. #ifdef FEAT_BYTEOFF
  5637.     static void
  5638. ex_goto(eap)
  5639.     exarg_T    *eap;
  5640. {
  5641.     goto_byte(eap->line2);
  5642. }
  5643. #endif
  5644.  
  5645. /*
  5646.  * ":shell".
  5647.  */
  5648. /*ARGSUSED*/
  5649.     static void
  5650. ex_shell(eap)
  5651.     exarg_T    *eap;
  5652. {
  5653.     do_shell(NULL, 0);
  5654. }
  5655.  
  5656. #if (defined(FEAT_WINDOWS) && defined(HAVE_DROP_FILE)) || defined(PROTO)
  5657.  
  5658. /*
  5659.  * Handle a file drop. The code is here because a drop is *nearly* like an
  5660.  * :args command, but not quite (we have a list of exact filenames, so we
  5661.  * don't want to (a) parse a command line, or (b) expand wildcards. So the
  5662.  * code is very similar to :args and hence needs access to a lot of the static
  5663.  * functions in this file.
  5664.  *
  5665.  * The list should be allocated using alloc(), as should each item in the
  5666.  * list. This function takes over responsibility for freeing the list.
  5667.  *
  5668.  * XXX The list is made into the arggument list. This is freed using
  5669.  * FreeWild(), which does a series of vim_free() calls, unless the two defines
  5670.  * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a
  5671.  * routine _fnexplodefree() is used. This may cause problems, but as the drop
  5672.  * file functionality is (currently) not in EMX this is not presently a
  5673.  * problem.
  5674.  */
  5675.     void
  5676. handle_drop(filec, filev, split)
  5677.     int        filec;        /* the number of files dropped */
  5678.     char_u    **filev;    /* the list of files dropped */
  5679.     int        split;        /* force splitting the window */
  5680. {
  5681.     exarg_T    ea;
  5682.  
  5683. #ifdef FEAT_CMDWIN
  5684.     if (cmdwin_type != 0)
  5685.     return;
  5686. #endif
  5687.  
  5688.     /* Check whether the current buffer is changed. If so, we will need
  5689.      * to split the current window or data could be lost.
  5690.      * We don't need to check if the 'hidden' option is set, as in this
  5691.      * case the buffer won't be lost.
  5692.      */
  5693.     if (!P_HID(curbuf) && !split)
  5694.     {
  5695.     ++emsg_off;
  5696.     split = check_changed(curbuf, TRUE, FALSE, FALSE, FALSE);
  5697.     --emsg_off;
  5698.     }
  5699.     if (split)
  5700.     {
  5701.     if (win_split(0, 0) == FAIL)
  5702.         return;
  5703. # ifdef FEAT_SCROLLBIND
  5704.     curwin->w_p_scb = FALSE;
  5705. # endif
  5706.  
  5707.     /* When splitting the window, create a new alist.  Otherwise the
  5708.      * existing one is overwritten. */
  5709.     alist_unlink(curwin->w_alist);
  5710.     alist_new();
  5711.     }
  5712.  
  5713.     /*
  5714.      * Set up the new argument list.
  5715.      */
  5716.     alist_set(ALIST(curwin), filec, filev, FALSE);
  5717.  
  5718.     /*
  5719.      * Move to the first file.
  5720.      */
  5721.     /* Fake up a minimal "next" command for do_argfile() */
  5722.     ea.cmd = (char_u *)"next";
  5723.     ea.forceit = FALSE;
  5724.     ea.do_ecmd_cmd = NULL;
  5725.     ea.do_ecmd_lnum = 0;
  5726.     ea.force_ff = 0;
  5727. # ifdef FEAT_MBYTE
  5728.     ea.force_enc = 0;
  5729. # endif
  5730.     do_argfile(&ea, 0);
  5731.  
  5732.     /* do_ecmd() may set need_start_insertmode, but since we never left Insert
  5733.      * mode that is not needed here. */
  5734.     need_start_insertmode = FALSE;
  5735. }
  5736. #endif
  5737.  
  5738. static void alist_clear __ARGS((alist_T *al));
  5739. /*
  5740.  * Clear an argument list: free all file names and reset it to zero entries.
  5741.  */
  5742.     static void
  5743. alist_clear(al)
  5744.     alist_T    *al;
  5745. {
  5746.     while (--al->al_ga.ga_len >= 0)
  5747.     vim_free(AARGLIST(al)[al->al_ga.ga_len].ae_fname);
  5748.     ga_clear(&al->al_ga);
  5749. }
  5750.  
  5751. /*
  5752.  * Init an argument list.
  5753.  */
  5754.     void
  5755. alist_init(al)
  5756.     alist_T    *al;
  5757. {
  5758.     ga_init2(&al->al_ga, (int)sizeof(aentry_T), 5);
  5759. }
  5760.  
  5761. #if defined(FEAT_WINDOWS) || defined(PROTO)
  5762.  
  5763. /*
  5764.  * Remove a reference from an argument list.
  5765.  * Ignored when the argument list is the global one.
  5766.  * If the argument list is no longer used by any window, free it.
  5767.  */
  5768.     void
  5769. alist_unlink(al)
  5770.     alist_T    *al;
  5771. {
  5772.     if (al != &global_alist && --al->al_refcount <= 0)
  5773.     {
  5774.     alist_clear(al);
  5775.     vim_free(al);
  5776.     }
  5777. }
  5778.  
  5779. # if defined(FEAT_LISTCMDS) || defined(HAVE_DROP_FILE) || defined(PROTO)
  5780. /*
  5781.  * Create a new argument list and use it for the current window.
  5782.  */
  5783.     void
  5784. alist_new()
  5785. {
  5786.     curwin->w_alist = (alist_T *)alloc((unsigned)sizeof(alist_T));
  5787.     if (curwin->w_alist == NULL)
  5788.     {
  5789.     curwin->w_alist = &global_alist;
  5790.     ++global_alist.al_refcount;
  5791.     }
  5792.     else
  5793.     {
  5794.     curwin->w_alist->al_refcount = 1;
  5795.     alist_init(curwin->w_alist);
  5796.     }
  5797. }
  5798. # endif
  5799. #endif
  5800.  
  5801. #if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE) || defined(PROTO)
  5802. /*
  5803.  * Expand the file names in the global argument list.
  5804.  */
  5805.     void
  5806. alist_expand()
  5807. {
  5808.     char_u    **old_arg_files;
  5809.     char_u    **new_arg_files;
  5810.     int        new_arg_file_count;
  5811.     char_u    *save_p_su = p_su;
  5812.     int        i;
  5813.  
  5814.     /* Don't use 'suffixes' here.  This should work like the shell did the
  5815.      * expansion.  Also, the vimrc file isn't read yet, thus the user
  5816.      * can't set the options. */
  5817.     p_su = empty_option;
  5818.     old_arg_files = (char_u **)alloc((unsigned)(sizeof(char_u *) * GARGCOUNT));
  5819.     if (old_arg_files != NULL)
  5820.     {
  5821.     for (i = 0; i < GARGCOUNT; ++i)
  5822.         old_arg_files[i] = GARGLIST[i].ae_fname;
  5823.     if (expand_wildcards(GARGCOUNT, old_arg_files,
  5824.             &new_arg_file_count, &new_arg_files,
  5825.             EW_FILE|EW_NOTFOUND|EW_ADDSLASH) == OK
  5826.         && new_arg_file_count > 0)
  5827.     {
  5828.         alist_set(&global_alist, new_arg_file_count, new_arg_files, TRUE);
  5829.     }
  5830.     vim_free(old_arg_files);
  5831.     }
  5832.     p_su = save_p_su;
  5833. }
  5834. #endif
  5835.  
  5836. /*
  5837.  * Set the argument list for the current window.
  5838.  * Takes over the allocated files[] and the allocated fnames in it.
  5839.  */
  5840.     void
  5841. alist_set(al, count, files, use_curbuf)
  5842.     alist_T    *al;
  5843.     int        count;
  5844.     char_u    **files;
  5845.     int        use_curbuf;
  5846. {
  5847.     int        i;
  5848.  
  5849.     alist_clear(al);
  5850.     if (ga_grow(&al->al_ga, count) == OK)
  5851.     {
  5852.     for (i = 0; i < count; ++i)
  5853.         alist_add(al, files[i], use_curbuf ? 2 : 1);
  5854.     vim_free(files);
  5855.     }
  5856.     else
  5857.     FreeWild(count, files);
  5858. #ifdef FEAT_WINDOWS
  5859.     if (al == &global_alist)
  5860. #endif
  5861.     arg_had_last = FALSE;
  5862. }
  5863.  
  5864. /*
  5865.  * Add file "fname" to argument list "al".
  5866.  * "fname" must have been allocated and "al" must have been checked for room.
  5867.  */
  5868.     void
  5869. alist_add(al, fname, set_fnum)
  5870.     alist_T    *al;
  5871.     char_u    *fname;
  5872.     int        set_fnum;    /* 1: set buffer number; 2: re-use curbuf */
  5873. {
  5874.     if (fname == NULL)        /* don't add NULL file names */
  5875.     return;
  5876. #ifdef BACKSLASH_IN_FILENAME
  5877.     slash_adjust(fname);
  5878. #endif
  5879.     AARGLIST(al)[al->al_ga.ga_len].ae_fname = fname;
  5880.     if (set_fnum > 0)
  5881.     AARGLIST(al)[al->al_ga.ga_len].ae_fnum =
  5882.         buflist_add(fname, BLN_LISTED | (set_fnum == 2 ? BLN_CURBUF : 0));
  5883.     ++al->al_ga.ga_len;
  5884.     --al->al_ga.ga_room;
  5885. }
  5886.  
  5887. #if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
  5888. /*
  5889.  * Adjust slashes in file names.  Called after 'shellslash' was set.
  5890.  */
  5891.     void
  5892. alist_slash_adjust()
  5893. {
  5894.     int        i;
  5895. # ifdef FEAT_WINDOWS
  5896.     win_T    *wp;
  5897. # endif
  5898.  
  5899.     for (i = 0; i < GARGCOUNT; ++i)
  5900.     if (GARGLIST[i].ae_fname != NULL)
  5901.         slash_adjust(GARGLIST[i].ae_fname);
  5902. # ifdef FEAT_WINDOWS
  5903.     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  5904.     if (wp->w_alist != &global_alist)
  5905.         for (i = 0; i < WARGCOUNT(wp); ++i)
  5906.         if (WARGLIST(wp)[i].ae_fname != NULL)
  5907.             slash_adjust(WARGLIST(wp)[i].ae_fname);
  5908. # endif
  5909. }
  5910. #endif
  5911.  
  5912. /*
  5913.  * ":preserve".
  5914.  */
  5915. /*ARGSUSED*/
  5916.     static void
  5917. ex_preserve(eap)
  5918.     exarg_T    *eap;
  5919. {
  5920.     ml_preserve(curbuf, TRUE);
  5921. }
  5922.  
  5923. /*
  5924.  * ":recover".
  5925.  */
  5926.     static void
  5927. ex_recover(eap)
  5928.     exarg_T    *eap;
  5929. {
  5930.     /* Set recoverymode right away to avoid the ATTENTION prompt. */
  5931.     recoverymode = TRUE;
  5932.     if (!check_changed(curbuf, p_awa, TRUE, eap->forceit, FALSE)
  5933.         && (*eap->arg == NUL || setfname(eap->arg, NULL, TRUE) == OK))
  5934.     ml_recover();
  5935.     recoverymode = FALSE;
  5936. }
  5937.  
  5938. /*
  5939.  * Command modifier used in a wrong way.
  5940.  */
  5941.     static void
  5942. ex_wrongmodifier(eap)
  5943.     exarg_T    *eap;
  5944. {
  5945.     eap->errmsg = e_invcmd;
  5946. }
  5947.  
  5948. #ifdef FEAT_WINDOWS
  5949. /*
  5950.  * :sview [+command] file    split window with new file, read-only
  5951.  * :split [[+command] file]    split window with current or new file
  5952.  * :vsplit [[+command] file]    split window vertically with current or new file
  5953.  * :new [[+command] file]    split window with no or new file
  5954.  * :vnew [[+command] file]    split vertically window with no or new file
  5955.  * :sfind [+command] file    split window with file in 'path'
  5956.  */
  5957.     void
  5958. ex_splitview(eap)
  5959.     exarg_T    *eap;
  5960. {
  5961.     win_T    *old_curwin;
  5962. #if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
  5963.     char_u    *fname = NULL;
  5964. #endif
  5965.  
  5966. #ifndef FEAT_VERTSPLIT
  5967.     if (eap->cmdidx == CMD_vsplit || eap->cmdidx == CMD_vnew)
  5968.     {
  5969.     ex_ni(eap);
  5970.     return;
  5971.     }
  5972. #endif
  5973.  
  5974.     old_curwin = curwin;
  5975. #ifdef FEAT_GUI
  5976.     need_mouse_correct = TRUE;
  5977. #endif
  5978.  
  5979. #ifdef FEAT_QUICKFIX
  5980.     /* A ":split" in the quickfix window works like ":new".  Don't want two
  5981.      * quickfix windows. */
  5982.     if (bt_quickfix(curbuf))
  5983.     {
  5984.     if (eap->cmdidx == CMD_split)
  5985.         eap->cmdidx = CMD_new;
  5986. # ifdef FEAT_VERTSPLIT
  5987.     if (eap->cmdidx == CMD_vsplit)
  5988.         eap->cmdidx = CMD_vnew;
  5989. # endif
  5990.     }
  5991. #endif
  5992.  
  5993. #ifdef FEAT_SEARCHPATH
  5994.     if (eap->cmdidx == CMD_sfind)
  5995.     {
  5996.     fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
  5997.                       FNAME_MESS, TRUE, curbuf->b_ffname);
  5998.     if (fname == NULL)
  5999.         goto theend;
  6000.     eap->arg = fname;
  6001.     }
  6002. # ifdef FEAT_BROWSE
  6003.     else
  6004. # endif
  6005. #endif
  6006. #ifdef FEAT_BROWSE
  6007.     if (cmdmod.browse
  6008. # ifdef FEAT_VERTSPLIT
  6009.         && eap->cmdidx != CMD_vnew
  6010. #endif
  6011.         && eap->cmdidx != CMD_new)
  6012.     {
  6013.     fname = do_browse(FALSE, (char_u *)_("Edit File in new window"),
  6014.                       eap->arg, NULL, NULL, NULL, curbuf);
  6015.     if (fname == NULL)
  6016.         goto theend;
  6017.     eap->arg = fname;
  6018.     }
  6019. #endif
  6020.     if (win_split(eap->addr_count > 0 ? (int)eap->line2 : 0,
  6021.                      *eap->cmd == 'v' ? WSP_VERT : 0) != FAIL)
  6022.     {
  6023. #ifdef FEAT_SCROLLBIND
  6024.     /* Reset 'scrollbind' when editing another file, but keep it when
  6025.      * doing ":split" without arguments. */
  6026.     if (*eap->arg != NUL
  6027. #ifdef FEAT_BROWSE
  6028.         || cmdmod.browse
  6029. #endif
  6030.        )
  6031.         curwin->w_p_scb = FALSE;
  6032.     else
  6033.         do_check_scrollbind(FALSE);
  6034. #endif
  6035.     do_exedit(eap, old_curwin);
  6036.     }
  6037.  
  6038. #if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
  6039. theend:
  6040.     vim_free(fname);
  6041. #endif
  6042. }
  6043. #endif
  6044.  
  6045. /*
  6046.  * ":mode": Set screen mode.
  6047.  * If no argument given, just get the screen size and redraw.
  6048.  */
  6049.     static void
  6050. ex_mode(eap)
  6051.     exarg_T    *eap;
  6052. {
  6053.     if (*eap->arg == NUL)
  6054.     shell_resized();
  6055.     else
  6056.     mch_screenmode(eap->arg);
  6057. }
  6058.  
  6059. #ifdef FEAT_WINDOWS
  6060. /*
  6061.  * ":resize".
  6062.  * set, increment or decrement current window height
  6063.  */
  6064.     static void
  6065. ex_resize(eap)
  6066.     exarg_T    *eap;
  6067. {
  6068.     int        n;
  6069.  
  6070. #ifdef FEAT_GUI
  6071.     need_mouse_correct = TRUE;
  6072. #endif
  6073.     n = atol((char *)eap->arg);
  6074. #ifdef FEAT_VERTSPLIT
  6075.     if (cmdmod.split & WSP_VERT)
  6076.     {
  6077.     if (*eap->arg == '-' || *eap->arg == '+')
  6078.         n += W_WIDTH(curwin);
  6079.     else if (n == 0)        /* default is very wide */
  6080.         n = 9999;
  6081.     win_setwidth((int)n);
  6082.     }
  6083.     else
  6084. #endif
  6085.     {
  6086.     if (*eap->arg == '-' || *eap->arg == '+')
  6087.         n += curwin->w_height;
  6088.     else if (n == 0)        /* default is very high */
  6089.         n = 9999;
  6090.     win_setheight((int)n);
  6091.     }
  6092. }
  6093. #endif
  6094.  
  6095. /*
  6096.  * ":find [+command] <file>" command.
  6097.  */
  6098.     static void
  6099. ex_find(eap)
  6100.     exarg_T    *eap;
  6101. {
  6102. #ifdef FEAT_SEARCHPATH
  6103.     char_u    *fname;
  6104.     int        count;
  6105.  
  6106.     fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
  6107.                               TRUE, curbuf->b_ffname);
  6108.     if (eap->addr_count > 0)
  6109.     {
  6110.     /* Repeat finding the file "count" times.  This matters when it
  6111.      * appears several times in the path. */
  6112.     count = eap->line2;
  6113.     while (fname != NULL && --count > 0)
  6114.     {
  6115.         vim_free(fname);
  6116.         fname = find_file_in_path(NULL, 0, FNAME_MESS,
  6117.                              FALSE, curbuf->b_ffname);
  6118.     }
  6119.     }
  6120.  
  6121.     if (fname != NULL)
  6122.     {
  6123.     eap->arg = fname;
  6124. #endif
  6125.     do_exedit(eap, NULL);
  6126. #ifdef FEAT_SEARCHPATH
  6127.     vim_free(fname);
  6128.     }
  6129. #endif
  6130. }
  6131.  
  6132. /*
  6133.  * ":edit", ":badd".
  6134.  */
  6135.     static void
  6136. ex_edit(eap)
  6137.     exarg_T    *eap;
  6138. {
  6139.     do_exedit(eap, NULL);
  6140. }
  6141.  
  6142. /*
  6143.  * ":edit <file>" command and alikes.
  6144.  */
  6145. /*ARGSUSED*/
  6146.     void
  6147. do_exedit(eap, old_curwin)
  6148.     exarg_T    *eap;
  6149.     win_T    *old_curwin;        /* curwin before doing a split or NULL */
  6150. {
  6151.     int        n;
  6152. #ifdef FEAT_WINDOWS
  6153.     int        need_hide;
  6154. #endif
  6155.  
  6156.     /*
  6157.      * ":vi" command ends Ex mode.
  6158.      */
  6159.     if (exmode_active && (eap->cmdidx == CMD_visual
  6160.                         || eap->cmdidx == CMD_view))
  6161.     {
  6162.     exmode_active = FALSE;
  6163.     if (*eap->arg == NUL)
  6164.         return;
  6165.     }
  6166.  
  6167.     if ((eap->cmdidx == CMD_new
  6168. #ifdef FEAT_VERTSPLIT
  6169.         || eap->cmdidx == CMD_vnew
  6170. #endif
  6171.         ) && *eap->arg == NUL)
  6172.     {
  6173.     /* ":new" without argument: edit an new empty buffer */
  6174.     setpcmark();
  6175.     (void)do_ecmd(0, NULL, NULL, eap, ECMD_ONE,
  6176.                    ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0));
  6177.     }
  6178.     else if ((eap->cmdidx != CMD_split
  6179. #ifdef FEAT_VERTSPLIT
  6180.         && eap->cmdidx != CMD_vsplit
  6181. #endif
  6182.         )
  6183.         || *eap->arg != NUL
  6184. #ifdef FEAT_BROWSE
  6185.         || cmdmod.browse
  6186. #endif
  6187.         )
  6188.     {
  6189.     n = readonlymode;
  6190.     if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
  6191.         readonlymode = TRUE;
  6192.     else if (eap->cmdidx == CMD_enew)
  6193.         readonlymode = FALSE;   /* 'readonly' doesn't make sense in an
  6194.                        empty buffer */
  6195.     setpcmark();
  6196.     if (do_ecmd(0, (eap->cmdidx == CMD_enew ? NULL : eap->arg),
  6197.             NULL, eap,
  6198.             /* ":edit" goes to first line if Vi compatible */
  6199.             (*eap->arg == NUL && eap->do_ecmd_lnum == 0
  6200.                       && vim_strchr(p_cpo, CPO_GOTO1) != NULL)
  6201.                            ? ECMD_ONE : eap->do_ecmd_lnum,
  6202.             (P_HID(curbuf) ? ECMD_HIDE : 0)
  6203.             + (eap->forceit ? ECMD_FORCEIT : 0)
  6204. #ifdef FEAT_LISTCMDS
  6205.             + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 )
  6206. #endif
  6207.             ) == FAIL)
  6208.     {
  6209.         /* Editing the file failed.  If the window was split, close it. */
  6210. #ifdef FEAT_WINDOWS
  6211.         if (old_curwin != NULL)
  6212.         {
  6213.         need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
  6214.         if (!need_hide || P_HID(curbuf))
  6215.         {
  6216. # ifdef FEAT_GUI
  6217.             need_mouse_correct = TRUE;
  6218. # endif
  6219.             win_close(curwin, !need_hide && !P_HID(curbuf));
  6220.         }
  6221.         }
  6222. #endif
  6223.     }
  6224.     else if (readonlymode && curbuf->b_nwindows == 1)
  6225.     {
  6226.         /* When editing an already visited buffer, 'readonly' won't be set
  6227.          * but the previous value is kept.  With ":view" and ":sview" we
  6228.          * want the  file to be readonly, except when another window is
  6229.          * editing the same buffer. */
  6230.         curbuf->b_p_ro = TRUE;
  6231.     }
  6232.     readonlymode = n;
  6233.     }
  6234.     else
  6235.     {
  6236.     if (eap->do_ecmd_cmd != NULL)
  6237.         do_cmdline_cmd(eap->do_ecmd_cmd);
  6238. #ifdef FEAT_TITLE
  6239.     n = curwin->w_arg_idx_invalid;
  6240. #endif
  6241.     check_arg_idx(curwin);
  6242. #ifdef FEAT_TITLE
  6243.     if (n != curwin->w_arg_idx_invalid)
  6244.         maketitle();
  6245. #endif
  6246.     }
  6247.  
  6248. #ifdef FEAT_WINDOWS
  6249.     /*
  6250.      * if ":split file" worked, set alternate file name in old window to new
  6251.      * file
  6252.      */
  6253.     if (old_curwin != NULL
  6254.         && *eap->arg != NUL
  6255.         && curwin != old_curwin
  6256.         && win_valid(old_curwin)
  6257.         && old_curwin->w_buffer != curbuf)
  6258.     old_curwin->w_alt_fnum = curbuf->b_fnum;
  6259. #endif
  6260.  
  6261.     ex_no_reprint = TRUE;
  6262. }
  6263.  
  6264. #ifndef FEAT_GUI
  6265. /*
  6266.  * ":gui" and ":gvim" when there is no GUI.
  6267.  */
  6268.     static void
  6269. ex_nogui(eap)
  6270.     exarg_T    *eap;
  6271. {
  6272.     eap->errmsg = e_nogvim;
  6273. }
  6274. #endif
  6275.  
  6276. #if defined(FEAT_GUI_W32) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
  6277.     static void
  6278. ex_tearoff(eap)
  6279.     exarg_T    *eap;
  6280. {
  6281.     gui_make_tearoff(eap->arg);
  6282. }
  6283. #endif
  6284.  
  6285. #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)) && defined(FEAT_MENU)
  6286.     static void
  6287. ex_popup(eap)
  6288.     exarg_T    *eap;
  6289. {
  6290.     gui_make_popup(eap->arg);
  6291. }
  6292. #endif
  6293.  
  6294. /*ARGSUSED*/
  6295.     static void
  6296. ex_swapname(eap)
  6297.     exarg_T    *eap;
  6298. {
  6299.     if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL)
  6300.     MSG(_("No swap file"));
  6301.     else
  6302.     msg(curbuf->b_ml.ml_mfp->mf_fname);
  6303. }
  6304.  
  6305. /*
  6306.  * ":syncbind" forces all 'scrollbind' windows to have the same relative
  6307.  * offset.
  6308.  * (1998-11-02 16:21:01  R. Edward Ralston <eralston@computer.org>)
  6309.  */
  6310. /*ARGSUSED*/
  6311.     static void
  6312. ex_syncbind(eap)
  6313.     exarg_T    *eap;
  6314. {
  6315. #ifdef FEAT_SCROLLBIND
  6316.     win_T    *wp;
  6317.     long    topline;
  6318.     long    y;
  6319.     linenr_T    old_linenr = curwin->w_cursor.lnum;
  6320.  
  6321.     setpcmark();
  6322.  
  6323.     /*
  6324.      * determine max topline
  6325.      */
  6326.     if (curwin->w_p_scb)
  6327.     {
  6328.     topline = curwin->w_topline;
  6329.     for (wp = firstwin; wp; wp = wp->w_next)
  6330.     {
  6331.         if (wp->w_p_scb && wp->w_buffer)
  6332.         {
  6333.         y = wp->w_buffer->b_ml.ml_line_count - p_so;
  6334.         if (topline > y)
  6335.             topline = y;
  6336.         }
  6337.     }
  6338.     if (topline < 1)
  6339.         topline = 1;
  6340.     }
  6341.     else
  6342.     {
  6343.     topline = 1;
  6344.     }
  6345.  
  6346.  
  6347.     /*
  6348.      * set all scrollbind windows to the same topline
  6349.      */
  6350.     wp = curwin;
  6351.     for (curwin = firstwin; curwin; curwin = curwin->w_next)
  6352.     {
  6353.     if (curwin->w_p_scb)
  6354.     {
  6355.         y = topline - curwin->w_topline;
  6356.         if (y > 0)
  6357.         scrollup(y, TRUE);
  6358.         else
  6359.         scrolldown(-y, TRUE);
  6360.         curwin->w_scbind_pos = topline;
  6361.         redraw_later(VALID);
  6362.         cursor_correct();
  6363. #ifdef FEAT_WINDOWS
  6364.         curwin->w_redr_status = TRUE;
  6365. #endif
  6366.     }
  6367.     }
  6368.     curwin = wp;
  6369.     if (curwin->w_p_scb)
  6370.     {
  6371.     did_syncbind = TRUE;
  6372.     checkpcmark();
  6373.     if (old_linenr != curwin->w_cursor.lnum)
  6374.     {
  6375.         char_u ctrl_o[2];
  6376.  
  6377.         ctrl_o[0] = Ctrl_O;
  6378.         ctrl_o[1] = 0;
  6379.         ins_typebuf(ctrl_o, REMAP_NONE, 0, TRUE, FALSE);
  6380.     }
  6381.     }
  6382. #endif
  6383. }
  6384.  
  6385.  
  6386.     static void
  6387. ex_read(eap)
  6388.     exarg_T    *eap;
  6389. {
  6390.     int        i;
  6391.  
  6392.     if (eap->usefilter)            /* :r!cmd */
  6393.     do_bang(1, eap, FALSE, FALSE, TRUE);
  6394.     else
  6395.     {
  6396.     if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
  6397.         return;
  6398.  
  6399. #ifdef FEAT_BROWSE
  6400.     if (cmdmod.browse)
  6401.     {
  6402.         char_u *browseFile;
  6403.  
  6404.         browseFile = do_browse(FALSE, (char_u *)_("Append File"), eap->arg,
  6405.                             NULL, NULL, NULL, curbuf);
  6406.         if (browseFile != NULL)
  6407.         {
  6408.         i = readfile(browseFile, NULL,
  6409.               eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
  6410.         vim_free(browseFile);
  6411.         }
  6412.         else
  6413.         i = OK;
  6414.     }
  6415.     else
  6416. #endif
  6417.          if (*eap->arg == NUL)
  6418.     {
  6419.         if (check_fname() == FAIL)    /* check for no file name */
  6420.         return;
  6421.         i = readfile(curbuf->b_ffname, curbuf->b_fname,
  6422.               eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
  6423.     }
  6424.     else
  6425.     {
  6426.         if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL)
  6427.         (void)setaltfname(eap->arg, eap->arg, (linenr_T)1);
  6428.         i = readfile(eap->arg, NULL,
  6429.               eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
  6430.  
  6431.     }
  6432.     if (i == FAIL)
  6433.     {
  6434. #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
  6435.         if (!aborting())
  6436. #endif
  6437.         EMSG2(_(e_notopen), eap->arg);
  6438.     }
  6439.     else
  6440.         redraw_curbuf_later(VALID);
  6441.     }
  6442. }
  6443.  
  6444. /*
  6445.  * ":cd", ":lcd", ":chdir" and ":lchdir".
  6446.  */
  6447.     static void
  6448. ex_cd(eap)
  6449.     exarg_T    *eap;
  6450. {
  6451.     static char_u    *prev_dir = NULL;
  6452.     char_u        *new_dir;
  6453.     char_u        *tofree;
  6454.  
  6455.     new_dir = eap->arg;
  6456. #if !defined(UNIX) && !defined(VMS)
  6457.     /* for non-UNIX ":cd" means: print current directory */
  6458.     if (*new_dir == NUL)
  6459.     ex_pwd(NULL);
  6460.     else
  6461. #endif
  6462.     {
  6463.     /* ":cd -": Change to previous directory */
  6464.     if (STRCMP(new_dir, "-") == 0)
  6465.     {
  6466.         if (prev_dir == NULL)
  6467.         {
  6468.         EMSG(_("E186: No previous directory"));
  6469.         return;
  6470.         }
  6471.         new_dir = prev_dir;
  6472.     }
  6473.  
  6474.     /* Save current directory for next ":cd -" */
  6475.     tofree = prev_dir;
  6476.     if (mch_dirname(NameBuff, MAXPATHL) == OK)
  6477.         prev_dir = vim_strsave(NameBuff);
  6478.     else
  6479.         prev_dir = NULL;
  6480.  
  6481. #if defined(UNIX) || defined(VMS)
  6482.     /* for UNIX ":cd" means: go to home directory */
  6483.     if (*new_dir == NUL)
  6484.     {
  6485.         /* use NameBuff for home directory name */
  6486. # ifdef VMS
  6487.         char_u    *p;
  6488.  
  6489.         p = mch_getenv((char_u *)"SYS$LOGIN");
  6490.         if (p == NULL || *p == NUL)    /* empty is the same as not set */
  6491.         NameBuff[0] = NUL;
  6492.         else
  6493.         STRNCPY(NameBuff, p, MAXPATHL);
  6494. # else
  6495.         expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
  6496. # endif
  6497.         new_dir = NameBuff;
  6498.     }
  6499. #endif
  6500.     if (new_dir == NULL || vim_chdir(new_dir))
  6501.         EMSG(_(e_failed));
  6502.     else
  6503.     {
  6504.         vim_free(curwin->w_localdir);
  6505.         if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
  6506.         {
  6507.         /* If still in global directory, need to remember current
  6508.          * directory as global directory. */
  6509.         if (globaldir == NULL && prev_dir != NULL)
  6510.             globaldir = vim_strsave(prev_dir);
  6511.         /* Remember this local directory for the window. */
  6512.         if (mch_dirname(NameBuff, MAXPATHL) == OK)
  6513.             curwin->w_localdir = vim_strsave(NameBuff);
  6514.         }
  6515.         else
  6516.         {
  6517.         /* We are now in the global directory, no need to remember its
  6518.          * name. */
  6519.         vim_free(globaldir);
  6520.         globaldir = NULL;
  6521.         curwin->w_localdir = NULL;
  6522.         }
  6523.  
  6524.         shorten_fnames(TRUE);
  6525.  
  6526.         /* Echo the new current directory if the command was typed. */
  6527.         if (KeyTyped)
  6528.         ex_pwd(eap);
  6529.     }
  6530.     vim_free(tofree);
  6531.     }
  6532. }
  6533.  
  6534. /*
  6535.  * ":pwd".
  6536.  */
  6537. /*ARGSUSED*/
  6538.     static void
  6539. ex_pwd(eap)
  6540.     exarg_T    *eap;
  6541. {
  6542.     if (mch_dirname(NameBuff, MAXPATHL) == OK)
  6543.     {
  6544. #ifdef BACKSLASH_IN_FILENAME
  6545.     slash_adjust(NameBuff);
  6546. #endif
  6547.     msg(NameBuff);
  6548.     }
  6549.     else
  6550.     EMSG(_("E187: Unknown"));
  6551. }
  6552.  
  6553. /*
  6554.  * ":=".
  6555.  */
  6556.     static void
  6557. ex_equal(eap)
  6558.     exarg_T    *eap;
  6559. {
  6560.     smsg((char_u *)_("line %ld"), (long)eap->line2);
  6561. }
  6562.  
  6563.     static void
  6564. ex_sleep(eap)
  6565.     exarg_T    *eap;
  6566. {
  6567.     int        n;
  6568.  
  6569.     if (cursor_valid())
  6570.     {
  6571.     n = W_WINROW(curwin) + curwin->w_wrow - msg_scrolled;
  6572.     if (n >= 0)
  6573.         windgoto((int)n, curwin->w_wcol);
  6574.     }
  6575.     do_sleep(eap->line2 * (*eap->arg == 'm' ? 1L : 1000L));
  6576. }
  6577.  
  6578. /*
  6579.  * Sleep for "msec" milliseconds, but keep checking for a CTRL-C every second.
  6580.  */
  6581.     void
  6582. do_sleep(msec)
  6583.     long    msec;
  6584. {
  6585.     long    done;
  6586.  
  6587.     cursor_on();
  6588.     out_flush();
  6589.     for (done = 0; !got_int && done < msec; done += 1000L)
  6590.     {
  6591.     ui_delay(msec - done > 1000L ? 1000L : msec - done, TRUE);
  6592.     ui_breakcheck();
  6593.     }
  6594. }
  6595.  
  6596.     static void
  6597. do_exmap(eap, isabbrev)
  6598.     exarg_T    *eap;
  6599.     int        isabbrev;
  6600. {
  6601.     int        mode;
  6602.     char_u  *cmdp;
  6603.  
  6604.     cmdp = eap->cmd;
  6605.     mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
  6606.  
  6607.     switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'),
  6608.                             eap->arg, mode, isabbrev))
  6609.     {
  6610.     case 1: EMSG(_(e_invarg));
  6611.         break;
  6612.     case 2: EMSG(isabbrev ? _(e_noabbr) : _(e_nomap));
  6613.         break;
  6614.     }
  6615. }
  6616.  
  6617. /*
  6618.  * ":winsize" command (obsolete).
  6619.  */
  6620.     static void
  6621. ex_winsize(eap)
  6622.     exarg_T    *eap;
  6623. {
  6624.     int        w, h;
  6625.     char_u    *arg = eap->arg;
  6626.     char_u    *p;
  6627.  
  6628.     w = getdigits(&arg);
  6629.     arg = skipwhite(arg);
  6630.     p = arg;
  6631.     h = getdigits(&arg);
  6632.     if (*p != NUL && *arg == NUL)
  6633.     set_shellsize(w, h, TRUE);
  6634.     else
  6635.     EMSG(_("E465: :winsize requires two number arguments"));
  6636. }
  6637.  
  6638. #ifdef FEAT_WINDOWS
  6639.     static void
  6640. ex_wincmd(eap)
  6641.     exarg_T    *eap;
  6642. {
  6643.     int        xchar = NUL;
  6644.     char_u    *p;
  6645.  
  6646.     if (*eap->arg == 'g' || *eap->arg == Ctrl_G)
  6647.     {
  6648.     /* CTRL-W g and CTRL-W CTRL-G  have an extra command character */
  6649.     if (eap->arg[1] == NUL)
  6650.     {
  6651.         EMSG(_(e_invarg));
  6652.         return;
  6653.     }
  6654.     xchar = eap->arg[1];
  6655.     p = eap->arg + 2;
  6656.     }
  6657.     else
  6658.     p = eap->arg + 1;
  6659.  
  6660.     eap->nextcmd = check_nextcmd(p);
  6661.     p = skipwhite(p);
  6662.     if (*p != NUL && *p != '"' && eap->nextcmd == NULL)
  6663.     EMSG(_(e_invarg));
  6664.     else
  6665.     do_window(*eap->arg, eap->addr_count > 0 ? eap->line2 : 0L, xchar);
  6666. }
  6667. #endif
  6668.  
  6669. #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS)
  6670. /*
  6671.  * ":winpos".
  6672.  */
  6673.     static void
  6674. ex_winpos(eap)
  6675.     exarg_T    *eap;
  6676. {
  6677.     int        x, y;
  6678.     char_u    *arg = eap->arg;
  6679.     char_u    *p;
  6680.  
  6681.     if (*arg == NUL)
  6682.     {
  6683. # ifdef FEAT_GUI
  6684.     if (gui.in_use && gui_mch_get_winpos(&x, &y) != FAIL)
  6685.     {
  6686.         sprintf((char *)IObuff, _("Window position: X %d, Y %d"), x, y);
  6687.         msg(IObuff);
  6688.     }
  6689.     else
  6690. # endif
  6691.         EMSG(_("E188: Obtaining window position not implemented for this platform"));
  6692.     }
  6693.     else
  6694.     {
  6695.     x = getdigits(&arg);
  6696.     arg = skipwhite(arg);
  6697.     p = arg;
  6698.     y = getdigits(&arg);
  6699.     if (*p == NUL || *arg != NUL)
  6700.     {
  6701.         EMSG(_("E466: :winpos requires two number arguments"));
  6702.         return;
  6703.     }
  6704. # ifdef FEAT_GUI
  6705.     if (gui.in_use)
  6706.         gui_mch_set_winpos(x, y);
  6707.     else if (gui.starting)
  6708.     {
  6709.         /* Remember the coordinates for when the window is opened. */
  6710.         gui_win_x = x;
  6711.         gui_win_y = y;
  6712.     }
  6713. #  ifdef HAVE_TGETENT
  6714.     else
  6715. #  endif
  6716. # endif
  6717. # ifdef HAVE_TGETENT
  6718.     if (*T_CWP)
  6719.         term_set_winpos(x, y);
  6720. # endif
  6721.     }
  6722. }
  6723. #endif
  6724.  
  6725. /*
  6726.  * Handle command that work like operators: ":delete", ":yank", ":>" and ":<".
  6727.  */
  6728.     static void
  6729. ex_operators(eap)
  6730.     exarg_T    *eap;
  6731. {
  6732.     oparg_T    oa;
  6733.  
  6734.     clear_oparg(&oa);
  6735.     oa.regname = eap->regname;
  6736.     oa.start.lnum = eap->line1;
  6737.     oa.end.lnum = eap->line2;
  6738.     oa.line_count = eap->line2 - eap->line1 + 1;
  6739.     oa.motion_type = MLINE;
  6740. #ifdef FEAT_VIRTUALEDIT
  6741.     virtual_op = FALSE;
  6742. #endif
  6743.     if (eap->cmdidx != CMD_yank)    /* position cursor for undo */
  6744.     {
  6745.     setpcmark();
  6746.     curwin->w_cursor.lnum = eap->line1;
  6747.     beginline(BL_SOL | BL_FIX);
  6748.     }
  6749.  
  6750.     switch (eap->cmdidx)
  6751.     {
  6752.     case CMD_delete:
  6753.         oa.op_type = OP_DELETE;
  6754.         op_delete(&oa);
  6755.         break;
  6756.  
  6757.     case CMD_yank:
  6758.         oa.op_type = OP_YANK;
  6759.         (void)op_yank(&oa, FALSE, TRUE);
  6760.         break;
  6761.  
  6762.     default:    /* CMD_rshift or CMD_lshift */
  6763.         if ((eap->cmdidx == CMD_rshift)
  6764. #ifdef FEAT_RIGHTLEFT
  6765.                     ^ curwin->w_p_rl
  6766. #endif
  6767.                             )
  6768.         oa.op_type = OP_RSHIFT;
  6769.         else
  6770.         oa.op_type = OP_LSHIFT;
  6771.         op_shift(&oa, FALSE, eap->amount);
  6772.         break;
  6773.     }
  6774. #ifdef FEAT_VIRTUALEDIT
  6775.     virtual_op = MAYBE;
  6776. #endif
  6777. }
  6778.  
  6779. /*
  6780.  * ":put".
  6781.  */
  6782.     static void
  6783. ex_put(eap)
  6784.     exarg_T    *eap;
  6785. {
  6786.     /* ":0put" works like ":1put!". */
  6787.     if (eap->line2 == 0)
  6788.     {
  6789.     eap->line2 = 1;
  6790.     eap->forceit = TRUE;
  6791.     }
  6792.     curwin->w_cursor.lnum = eap->line2;
  6793.     do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L, PUT_LINE);
  6794. }
  6795.  
  6796. /*
  6797.  * Handle ":copy" and ":move".
  6798.  */
  6799.     static void
  6800. ex_copymove(eap)
  6801.     exarg_T    *eap;
  6802. {
  6803.     long    n;
  6804.  
  6805.     n = get_address(&eap->arg, FALSE, FALSE);
  6806.     if (eap->arg == NULL)        /* error detected */
  6807.     {
  6808.     eap->nextcmd = NULL;
  6809.     return;
  6810.     }
  6811.  
  6812.     /*
  6813.      * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
  6814.      */
  6815.     if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
  6816.     {
  6817.     EMSG(_(e_invaddr));
  6818.     return;
  6819.     }
  6820.  
  6821.     if (eap->cmdidx == CMD_move)
  6822.     {
  6823.     if (do_move(eap->line1, eap->line2, n) == FAIL)
  6824.         return;
  6825.     }
  6826.     else
  6827.     ex_copy(eap->line1, eap->line2, n);
  6828.     u_clearline();
  6829.     beginline(BL_SOL | BL_FIX);
  6830. }
  6831.  
  6832. /*
  6833.  * ":smagic" and ":snomagic".
  6834.  */
  6835.     static void
  6836. ex_submagic(eap)
  6837.     exarg_T    *eap;
  6838. {
  6839.     int        magic_save = p_magic;
  6840.  
  6841.     p_magic = (eap->cmdidx == CMD_smagic);
  6842.     do_sub(eap);
  6843.     p_magic = magic_save;
  6844. }
  6845.  
  6846. /*
  6847.  * ":join".
  6848.  */
  6849.     static void
  6850. ex_join(eap)
  6851.     exarg_T    *eap;
  6852. {
  6853.     curwin->w_cursor.lnum = eap->line1;
  6854.     if (eap->line1 == eap->line2)
  6855.     {
  6856.     if (eap->addr_count >= 2)   /* :2,2join does nothing */
  6857.         return;
  6858.     if (eap->line2 == curbuf->b_ml.ml_line_count)
  6859.     {
  6860.         beep_flush();
  6861.         return;
  6862.     }
  6863.     ++eap->line2;
  6864.     }
  6865.     do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit);
  6866.     beginline(BL_WHITE | BL_FIX);
  6867. }
  6868.  
  6869. /*
  6870.  * ":[addr]@r" or ":[addr]*r": execute register
  6871.  */
  6872.     static void
  6873. ex_at(eap)
  6874.     exarg_T    *eap;
  6875. {
  6876.     int        c;
  6877.  
  6878.     curwin->w_cursor.lnum = eap->line2;
  6879.  
  6880. #ifdef USE_ON_FLY_SCROLL
  6881.     dont_scroll = TRUE;        /* disallow scrolling here */
  6882. #endif
  6883.  
  6884.     /* get the register name.  No name means to use the previous one */
  6885.     c = *eap->arg;
  6886.     if (c == NUL || (c == '*' && *eap->cmd == '*'))
  6887.     c = '@';
  6888.     /* put the register in mapbuf */
  6889.     if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL)
  6890.     beep_flush();
  6891.     else
  6892.     {
  6893.     int    save_efr = exec_from_reg;
  6894.  
  6895.     exec_from_reg = TRUE;
  6896.     /* execute from the mapbuf */
  6897.     while (vpeekc() == ':')
  6898.     {
  6899.         (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
  6900.         /* In Ex mode need to quit when the typeahead is exhausted,
  6901.          * otherwise input unexpectedly goes to the typeahead buffer and
  6902.          * getexmodeline() can't get it with inchar(). */
  6903.         if (exmode_active && stuff_empty() && typebuf.tb_len == 0)
  6904.         break;
  6905.     }
  6906.  
  6907.     exec_from_reg = save_efr;
  6908.     }
  6909. }
  6910.  
  6911. /*
  6912.  * ":!".
  6913.  */
  6914.     static void
  6915. ex_bang(eap)
  6916.     exarg_T    *eap;
  6917. {
  6918.     do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
  6919. }
  6920.  
  6921. /*
  6922.  * ":undo".
  6923.  */
  6924. /*ARGSUSED*/
  6925.     static void
  6926. ex_undo(eap)
  6927.     exarg_T    *eap;
  6928. {
  6929.     u_undo(1);
  6930. }
  6931.  
  6932. /*
  6933.  * ":redo".
  6934.  */
  6935. /*ARGSUSED*/
  6936.     static void
  6937. ex_redo(eap)
  6938.     exarg_T    *eap;
  6939. {
  6940.     u_redo(1);
  6941. }
  6942.  
  6943. /*
  6944.  * ":redir": start/stop redirection.
  6945.  */
  6946.     static void
  6947. ex_redir(eap)
  6948.     exarg_T    *eap;
  6949. {
  6950.     char    *mode;
  6951.     char_u    *fname;
  6952.  
  6953.     if (STRICMP(eap->arg, "END") == 0)
  6954.     close_redir();
  6955.     else
  6956.     {
  6957.     if (*eap->arg == '>')
  6958.     {
  6959.         ++eap->arg;
  6960.         if (*eap->arg == '>')
  6961.         {
  6962.         ++eap->arg;
  6963.         mode = "a";
  6964.         }
  6965.         else
  6966.         mode = "w";
  6967.         eap->arg = skipwhite(eap->arg);
  6968.  
  6969.         close_redir();
  6970.  
  6971.         /* Expand environment variables and "~/". */
  6972.         fname = expand_env_save(eap->arg);
  6973.         if (fname == NULL)
  6974.         return;
  6975. #ifdef FEAT_BROWSE
  6976.         if (cmdmod.browse)
  6977.         {
  6978.         char_u    *browseFile;
  6979.  
  6980.         browseFile = do_browse(TRUE, (char_u *)_("Save Redirection"),
  6981.                fname, NULL, NULL, BROWSE_FILTER_ALL_FILES, curbuf);
  6982.         if (browseFile == NULL)
  6983.             return;        /* operation cancelled */
  6984.         vim_free(fname);
  6985.         fname = browseFile;
  6986.         eap->forceit = TRUE;    /* since dialog already asked */
  6987.         }
  6988. #endif
  6989.  
  6990.         redir_fd = open_exfile(fname, eap->forceit, mode);
  6991.         vim_free(fname);
  6992.     }
  6993. #ifdef FEAT_EVAL
  6994.     else if (*eap->arg == '@')
  6995.     {
  6996.         /* redirect to a register a-z (resp. A-Z for appending) */
  6997.         close_redir();
  6998.         ++eap->arg;
  6999.         if (ASCII_ISALPHA(*eap->arg)
  7000. # ifdef FEAT_CLIPBOARD
  7001.             || *eap->arg == '*'
  7002. # endif
  7003.             || *eap->arg == '"')
  7004.         {
  7005.         redir_reg = *eap->arg;
  7006.         if (islower(redir_reg)
  7007. # ifdef FEAT_CLIPBOARD
  7008.             || redir_reg == '*'
  7009. # endif
  7010.             || redir_reg == '"')
  7011.         {
  7012.             /* make register empty */
  7013.             write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
  7014.         }
  7015.         }
  7016.         else
  7017.         EMSG(_(e_invarg));
  7018.     }
  7019. #endif
  7020.  
  7021.     /* TODO: redirect to a buffer */
  7022.  
  7023.     /* TODO: redirect to an internal variable */
  7024.  
  7025.     else
  7026.         EMSG(_(e_invarg));
  7027.     }
  7028. }
  7029.  
  7030. /*
  7031.  * ":redraw": force redraw
  7032.  */
  7033.     static void
  7034. ex_redraw(eap)
  7035.     exarg_T    *eap;
  7036. {
  7037.     int        r = RedrawingDisabled;
  7038.     int        p = p_lz;
  7039.  
  7040.     RedrawingDisabled = 0;
  7041.     p_lz = FALSE;
  7042.     update_screen(eap->forceit ? CLEAR :
  7043. #ifdef FEAT_VISUAL
  7044.         VIsual_active ? INVERTED :
  7045. #endif
  7046.         0);
  7047.     RedrawingDisabled = r;
  7048.     p_lz = p;
  7049.     out_flush();
  7050. }
  7051.  
  7052.     static void
  7053. close_redir()
  7054. {
  7055.     if (redir_fd != NULL)
  7056.     {
  7057.     fclose(redir_fd);
  7058.     redir_fd = NULL;
  7059.     }
  7060. #ifdef FEAT_EVAL
  7061.     redir_reg = 0;
  7062. #endif
  7063. }
  7064.  
  7065. #if defined(FEAT_SESSION) && defined(USE_CRNL)
  7066. # define MKSESSION_NL
  7067. static int mksession_nl = FALSE;    /* use NL only in put_eol() */
  7068. #endif
  7069.  
  7070. /*
  7071.  * ":mkexrc", ":mkvimrc", ":mkview" and ":mksession".
  7072.  */
  7073.     static void
  7074. ex_mkrc(eap)
  7075.     exarg_T    *eap;
  7076. {
  7077.     FILE    *fd;
  7078.     int        failed = FALSE;
  7079.     char_u    *fname;
  7080. #ifdef FEAT_BROWSE
  7081.     char_u    *browseFile = NULL;
  7082. #endif
  7083. #ifdef FEAT_SESSION
  7084.     int        view_session = FALSE;
  7085.     int        using_vdir = FALSE;    /* using 'viewdir'? */
  7086.     char_u    *viewFile = NULL;
  7087.     unsigned    *flagp;
  7088. #endif
  7089.  
  7090.     if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview)
  7091.     {
  7092. #ifdef FEAT_SESSION
  7093.     view_session = TRUE;
  7094. #else
  7095.     ex_ni(eap);
  7096.     return;
  7097. #endif
  7098.     }
  7099.  
  7100. #ifdef FEAT_SESSION
  7101.     /* ":mkview" or ":mkview 9": generate file name with 'viewdir' */
  7102.     if (eap->cmdidx == CMD_mkview
  7103.         && (*eap->arg == NUL
  7104.         || (isdigit(*eap->arg) && eap->arg[1] == NUL)))
  7105.     {
  7106.     eap->forceit = TRUE;
  7107.     fname = get_view_file(*eap->arg);
  7108.     if (fname == NULL)
  7109.         return;
  7110.     viewFile = fname;
  7111.     using_vdir = TRUE;
  7112.     }
  7113.     else
  7114. #endif
  7115.     if (*eap->arg != NUL)
  7116.     fname = eap->arg;
  7117.     else if (eap->cmdidx == CMD_mkvimrc)
  7118.     fname = (char_u *)VIMRC_FILE;
  7119. #ifdef FEAT_SESSION
  7120.     else if (eap->cmdidx == CMD_mksession)
  7121.     fname = (char_u *)SESSION_FILE;
  7122. #endif
  7123.     else
  7124.     fname = (char_u *)EXRC_FILE;
  7125.  
  7126. #ifdef FEAT_BROWSE
  7127.     if (cmdmod.browse)
  7128.     {
  7129.     browseFile = do_browse(TRUE,
  7130. # ifdef FEAT_SESSION
  7131.         eap->cmdidx == CMD_mkview ? (char_u *)_("Save View") :
  7132.         eap->cmdidx == CMD_mksession ? (char_u *)_("Save Session") :
  7133. # endif
  7134.         (char_u *)_("Save Setup"),
  7135.         fname, (char_u *)"vim", NULL, BROWSE_FILTER_MACROS, NULL);
  7136.     if (browseFile == NULL)
  7137.         goto theend;
  7138.     fname = browseFile;
  7139.     eap->forceit = TRUE;    /* since dialog already asked */
  7140.     }
  7141. #endif
  7142.  
  7143. #if defined(FEAT_SESSION) && defined(vim_mkdir)
  7144.     /* When using 'viewdir' may have to create the directory. */
  7145.     if (using_vdir && !mch_isdir(p_vdir))
  7146.     vim_mkdir(p_vdir, 0755); /* ignore errors, open_exfile() will fail */
  7147. #endif
  7148.  
  7149.     fd = open_exfile(fname, eap->forceit, WRITEBIN);
  7150.     if (fd != NULL)
  7151.     {
  7152. #ifdef FEAT_SESSION
  7153.     if (eap->cmdidx == CMD_mkview)
  7154.         flagp = &vop_flags;
  7155.     else
  7156.         flagp = &ssop_flags;
  7157. #endif
  7158.  
  7159. #ifdef MKSESSION_NL
  7160.     /* "unix" in 'sessionoptions': use NL line separator */
  7161.     if (view_session && (*flagp & SSOP_UNIX))
  7162.         mksession_nl = TRUE;
  7163. #endif
  7164.  
  7165.     /* Write the version command for :mkvimrc */
  7166.     if (eap->cmdidx == CMD_mkvimrc)
  7167.         (void)put_line(fd, "version 6.0");
  7168.  
  7169. #ifdef FEAT_SESSION
  7170.     if (eap->cmdidx != CMD_mkview)
  7171. #endif
  7172.     {
  7173.         /* Write setting 'compatible' first, because it has side effects */
  7174.         if (p_cp)
  7175.         (void)put_line(fd, "set compatible");
  7176.         else
  7177.         (void)put_line(fd, "set nocompatible");
  7178.     }
  7179.  
  7180. #ifdef FEAT_SESSION
  7181.     if (!view_session
  7182.         || (eap->cmdidx == CMD_mksession
  7183.             && (*flagp & SSOP_OPTIONS)))
  7184. #endif
  7185.         failed |= (makemap(fd, NULL) == FAIL
  7186.                    || makeset(fd, OPT_GLOBAL, FALSE) == FAIL);
  7187.  
  7188. #ifdef FEAT_SESSION
  7189.     if (!failed && view_session)
  7190.     {
  7191.         if (put_line(fd, "let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0") == FAIL)
  7192.         failed = TRUE;
  7193.         if (eap->cmdidx == CMD_mksession)
  7194.         {
  7195.         char_u dirnow[MAXPATHL];    /* current directory */
  7196.  
  7197.         /*
  7198.          * Change to session file's dir.
  7199.          */
  7200.         if (mch_dirname(dirnow, MAXPATHL) == FAIL
  7201.                         || mch_chdir((char *)dirnow) != 0)
  7202.             *dirnow = NUL;
  7203.         if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR))
  7204.         {
  7205.             if (vim_chdirfile(fname) == OK)
  7206.             shorten_fnames(TRUE);
  7207.         }
  7208.         else if (*dirnow != NUL
  7209.             && (ssop_flags & SSOP_CURDIR) && globaldir != NULL)
  7210.         {
  7211.             (void)mch_chdir((char *)globaldir);
  7212.             shorten_fnames(TRUE);
  7213.         }
  7214.  
  7215.         failed |= (makeopens(fd, dirnow) == FAIL);
  7216.  
  7217.         /* restore original dir */
  7218.         if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR)
  7219.             || ((ssop_flags & SSOP_CURDIR) && globaldir != NULL)))
  7220.         {
  7221.             if (mch_chdir((char *)dirnow) != 0)
  7222.             EMSG(_(e_prev_dir));
  7223.             shorten_fnames(TRUE);
  7224.         }
  7225.         }
  7226.         else
  7227.         {
  7228.         failed |= (put_view(fd, curwin, !using_vdir, flagp) == FAIL);
  7229.         }
  7230.         if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save")
  7231.                                       == FAIL)
  7232.         failed = TRUE;
  7233.     }
  7234. #endif
  7235.     failed |= fclose(fd);
  7236.  
  7237.     if (failed)
  7238.         EMSG(_(e_write));
  7239. #if defined(FEAT_EVAL) && defined(FEAT_SESSION)
  7240.     else if (eap->cmdidx == CMD_mksession)
  7241.     {
  7242.         /* successful session write - set this_session var */
  7243.         char_u    tbuf[MAXPATHL];
  7244.  
  7245.         if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK)
  7246.         set_vim_var_string(VV_THIS_SESSION, tbuf, -1);
  7247.     }
  7248. #endif
  7249. #ifdef MKSESSION_NL
  7250.     mksession_nl = FALSE;
  7251. #endif
  7252.     }
  7253.  
  7254. #ifdef FEAT_BROWSE
  7255. theend:
  7256.     vim_free(browseFile);
  7257. #endif
  7258. #ifdef FEAT_SESSION
  7259.     vim_free(viewFile);
  7260. #endif
  7261. }
  7262.  
  7263. /*
  7264.  * Open a file for writing for an Ex command, with some checks.
  7265.  * Return file descriptor, or NULL on failure.
  7266.  */
  7267.     FILE *
  7268. open_exfile(fname, forceit, mode)
  7269.     char_u    *fname;
  7270.     int        forceit;
  7271.     char    *mode;        /* "w" for create new file or "a" for append */
  7272. {
  7273.     FILE    *fd;
  7274.  
  7275. #ifdef UNIX
  7276.     /* with Unix it is possible to open a directory */
  7277.     if (mch_isdir(fname))
  7278.     {
  7279.     EMSG2(_(e_isadir2), fname);
  7280.     return NULL;
  7281.     }
  7282. #endif
  7283.     if (!forceit && *mode != 'a' && vim_fexists(fname))
  7284.     {
  7285.     EMSG2(_("E189: \"%s\" exists (add ! to override)"), fname);
  7286.     return NULL;
  7287.     }
  7288.  
  7289.     if ((fd = mch_fopen((char *)fname, mode)) == NULL)
  7290.     EMSG2(_("E190: Cannot open \"%s\" for writing"), fname);
  7291.  
  7292.     return fd;
  7293. }
  7294.  
  7295. /*
  7296.  * ":mark" and ":k".
  7297.  */
  7298.     static void
  7299. ex_mark(eap)
  7300.     exarg_T    *eap;
  7301. {
  7302.     pos_T    pos;
  7303.  
  7304.     if (*eap->arg == NUL)        /* No argument? */
  7305.     EMSG(_(e_argreq));
  7306.     else if (eap->arg[1] != NUL)    /* more than one character? */
  7307.     EMSG(_(e_trailing));
  7308.     else
  7309.     {
  7310.     pos = curwin->w_cursor;        /* save curwin->w_cursor */
  7311.     curwin->w_cursor.lnum = eap->line2;
  7312.     beginline(BL_WHITE | BL_FIX);
  7313.     if (setmark(*eap->arg) == FAIL)    /* set mark */
  7314.         EMSG(_("E191: Argument must be a letter or forward/backward quote"));
  7315.     curwin->w_cursor = pos;        /* restore curwin->w_cursor */
  7316.     }
  7317. }
  7318.  
  7319. /*
  7320.  * Update w_topline, w_leftcol and the cursor position.
  7321.  */
  7322.     void
  7323. update_topline_cursor()
  7324. {
  7325.     check_cursor();        /* put cursor on valid line */
  7326.     update_topline();
  7327.     if (!curwin->w_p_wrap)
  7328.     validate_cursor();
  7329.     update_curswant();
  7330. }
  7331.  
  7332. #ifdef FEAT_EX_EXTRA
  7333. /*
  7334.  * ":normal[!] {commands}": Execute normal mode commands.
  7335.  */
  7336.     static void
  7337. ex_normal(eap)
  7338.     exarg_T    *eap;
  7339. {
  7340.     oparg_T    oa;
  7341.     int        save_msg_scroll = msg_scroll;
  7342.     int        save_restart_edit = restart_edit;
  7343.     int        save_msg_didout = msg_didout;
  7344.     int        save_State = State;
  7345.     tasave_T    tabuf;
  7346.     int        save_insertmode = p_im;
  7347.     int        save_finish_op = finish_op;
  7348. #ifdef FEAT_MBYTE
  7349.     char_u    *arg = NULL;
  7350.     int        l;
  7351.     char_u    *p;
  7352. #endif
  7353.  
  7354.     if (ex_normal_busy >= p_mmd)
  7355.     {
  7356.     EMSG(_("E192: Recursive use of :normal too deep"));
  7357.     return;
  7358.     }
  7359.     ++ex_normal_busy;
  7360.  
  7361.     msg_scroll = FALSE;        /* no msg scrolling in Normal mode */
  7362.     restart_edit = 0;        /* don't go to Insert mode */
  7363.     p_im = FALSE;        /* don't use 'insertmode' */
  7364.  
  7365. #ifdef FEAT_MBYTE
  7366.     /*
  7367.      * vgetc() expects a CSI and K_SPECIAL to have been escaped.  Don't do
  7368.      * this for the K_SPECIAL leading byte, otherwise special keys will not
  7369.      * work.
  7370.      */
  7371.     if (has_mbyte)
  7372.     {
  7373.     int    len = 0;
  7374.  
  7375.     /* Count the number of characters to be escaped. */
  7376.     for (p = eap->arg; *p != NUL; ++p)
  7377.     {
  7378. # ifdef FEAT_GUI
  7379.         if (*p == CSI)  /* leadbyte CSI */
  7380.         len += 2;
  7381. # endif
  7382.         for (l = (*mb_ptr2len_check)(p) - 1; l > 0; --l)
  7383.         if (*++p == K_SPECIAL      /* trailbyte K_SPECIAL or CSI */
  7384. # ifdef FEAT_GUI
  7385.             || *p == CSI
  7386. # endif
  7387.             )
  7388.             len += 2;
  7389.     }
  7390.     if (len > 0)
  7391.     {
  7392.         arg = alloc((unsigned)(STRLEN(eap->arg) + len + 1));
  7393.         if (arg != NULL)
  7394.         {
  7395.         len = 0;
  7396.         for (p = eap->arg; *p != NUL; ++p)
  7397.         {
  7398.             arg[len++] = *p;
  7399. # ifdef FEAT_GUI
  7400.             if (*p == CSI)
  7401.             {
  7402.             arg[len++] = KS_EXTRA;
  7403.             arg[len++] = (int)KE_CSI;
  7404.             }
  7405. # endif
  7406.             for (l = (*mb_ptr2len_check)(p) - 1; l > 0; --l)
  7407.             {
  7408.             arg[len++] = *++p;
  7409.             if (*p == K_SPECIAL)
  7410.             {
  7411.                 arg[len++] = KS_SPECIAL;
  7412.                 arg[len++] = KE_FILLER;
  7413.             }
  7414. # ifdef FEAT_GUI
  7415.             else if (*p == CSI)
  7416.             {
  7417.                 arg[len++] = KS_EXTRA;
  7418.                 arg[len++] = (int)KE_CSI;
  7419.             }
  7420. # endif
  7421.             }
  7422.             arg[len] = NUL;
  7423.         }
  7424.         }
  7425.     }
  7426.     }
  7427. #endif
  7428.  
  7429.     /*
  7430.      * Save the current typeahead.  This is required to allow using ":normal"
  7431.      * from an event handler and makes sure we don't hang when the argument
  7432.      * ends with half a command.
  7433.      */
  7434.     save_typeahead(&tabuf);
  7435.     if (tabuf.typebuf_valid)
  7436.     {
  7437.     /*
  7438.      * Repeat the :normal command for each line in the range.  When no
  7439.      * range given, execute it just once, without positioning the cursor
  7440.      * first.
  7441.      */
  7442.     do
  7443.     {
  7444.         clear_oparg(&oa);
  7445.         finish_op = FALSE;
  7446.         if (eap->addr_count != 0)
  7447.         {
  7448.         curwin->w_cursor.lnum = eap->line1++;
  7449.         curwin->w_cursor.col = 0;
  7450.         }
  7451.  
  7452.         /*
  7453.          * Stuff the argument into the typeahead buffer.
  7454.          * Execute normal_cmd() until there is no typeahead left.
  7455.          */
  7456.         ins_typebuf(
  7457. #ifdef FEAT_MBYTE
  7458.             arg != NULL ? arg :
  7459. #endif
  7460.             eap->arg, eap->forceit ? REMAP_NONE : REMAP_YES, 0,
  7461.                                  TRUE, FALSE);
  7462.         while ((!stuff_empty() || (!typebuf_typed() && typebuf.tb_len > 0))
  7463.             && !got_int)
  7464.         {
  7465.         update_topline_cursor();
  7466.         normal_cmd(&oa, FALSE);    /* execute a Normal mode cmd */
  7467.         }
  7468.     }
  7469.     while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int);
  7470.     }
  7471.  
  7472.     /* Might not return to the main loop when in an event handler. */
  7473.     update_topline_cursor();
  7474.  
  7475.     /* Restore the previous typeahead. */
  7476.     restore_typeahead(&tabuf);
  7477.  
  7478.     --ex_normal_busy;
  7479.     msg_scroll = save_msg_scroll;
  7480.     restart_edit = save_restart_edit;
  7481.     p_im = save_insertmode;
  7482.     finish_op = save_finish_op;
  7483.     msg_didout |= save_msg_didout;    /* don't reset msg_didout now */
  7484.  
  7485.     /* Restore the state (needed when called from a function executed for
  7486.      * 'indentexpr'). */
  7487.     State = save_State;
  7488. #ifdef FEAT_MBYTE
  7489.     vim_free(arg);
  7490. #endif
  7491. }
  7492.  
  7493. /*
  7494.  * ":startinsert"
  7495.  */
  7496.     static void
  7497. ex_startinsert(eap)
  7498.     exarg_T    *eap;
  7499. {
  7500.     if (eap->forceit)
  7501.     {
  7502.     coladvance((colnr_T)MAXCOL);
  7503.     curwin->w_curswant = MAXCOL;
  7504.     curwin->w_set_curswant = FALSE;
  7505.     restart_edit = 'a';
  7506.     }
  7507.     else
  7508.     restart_edit = 'i';
  7509. }
  7510.  
  7511. /*
  7512.  * ":stopinsert"
  7513.  */
  7514. /*ARGSUSED*/
  7515.     static void
  7516. ex_stopinsert(eap)
  7517.     exarg_T    *eap;
  7518. {
  7519.     restart_edit = 0;
  7520.     stop_insert_mode = TRUE;
  7521. }
  7522. #endif
  7523.  
  7524. #ifdef FEAT_FIND_ID
  7525.     static void
  7526. ex_checkpath(eap)
  7527.     exarg_T    *eap;
  7528. {
  7529.     find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
  7530.                    eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
  7531.                           (linenr_T)1, (linenr_T)MAXLNUM);
  7532. }
  7533.  
  7534. #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
  7535. /*
  7536.  * ":psearch"
  7537.  */
  7538.     static void
  7539. ex_psearch(eap)
  7540.     exarg_T    *eap;
  7541. {
  7542.     g_do_tagpreview = p_pvh;
  7543.     ex_findpat(eap);
  7544.     g_do_tagpreview = 0;
  7545. }
  7546. #endif
  7547.  
  7548.     static void
  7549. ex_findpat(eap)
  7550.     exarg_T    *eap;
  7551. {
  7552.     int        whole = TRUE;
  7553.     long    n;
  7554.     char_u    *p;
  7555.     int        action;
  7556.  
  7557.     switch (cmdnames[eap->cmdidx].cmd_name[2])
  7558.     {
  7559.     case 'e':    /* ":psearch", ":isearch" and ":dsearch" */
  7560.         if (cmdnames[eap->cmdidx].cmd_name[0] == 'p')
  7561.             action = ACTION_GOTO;
  7562.         else
  7563.             action = ACTION_SHOW;
  7564.         break;
  7565.     case 'i':    /* ":ilist" and ":dlist" */
  7566.         action = ACTION_SHOW_ALL;
  7567.         break;
  7568.     case 'u':    /* ":ijump" and ":djump" */
  7569.         action = ACTION_GOTO;
  7570.         break;
  7571.     default:    /* ":isplit" and ":dsplit" */
  7572.         action = ACTION_SPLIT;
  7573.         break;
  7574.     }
  7575.  
  7576.     n = 1;
  7577.     if (isdigit(*eap->arg))    /* get count */
  7578.     {
  7579.     n = getdigits(&eap->arg);
  7580.     eap->arg = skipwhite(eap->arg);
  7581.     }
  7582.     if (*eap->arg == '/')   /* Match regexp, not just whole words */
  7583.     {
  7584.     whole = FALSE;
  7585.     ++eap->arg;
  7586.     p = skip_regexp(eap->arg, '/', p_magic, NULL);
  7587.     if (*p)
  7588.     {
  7589.         *p++ = NUL;
  7590.         p = skipwhite(p);
  7591.  
  7592.         /* Check for trailing illegal characters */
  7593.         if (!ends_excmd(*p))
  7594.         eap->errmsg = e_trailing;
  7595.         else
  7596.         eap->nextcmd = check_nextcmd(p);
  7597.     }
  7598.     }
  7599.     if (!eap->skip)
  7600.     find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
  7601.                 whole, !eap->forceit,
  7602.                 *eap->cmd == 'd' ?    FIND_DEFINE : FIND_ANY,
  7603.                 n, action, eap->line1, eap->line2);
  7604. }
  7605. #endif
  7606.  
  7607. #ifdef FEAT_WINDOWS
  7608.  
  7609. # ifdef FEAT_QUICKFIX
  7610. /*
  7611.  * ":ptag", ":ptselect", ":ptjump", ":ptnext", etc.
  7612.  */
  7613.     static void
  7614. ex_ptag(eap)
  7615.     exarg_T    *eap;
  7616. {
  7617.     g_do_tagpreview = p_pvh;
  7618.     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
  7619. }
  7620.  
  7621. /*
  7622.  * ":pedit"
  7623.  */
  7624.     static void
  7625. ex_pedit(eap)
  7626.     exarg_T    *eap;
  7627. {
  7628.     win_T    *curwin_save = curwin;
  7629.  
  7630.     g_do_tagpreview = p_pvh;
  7631.     prepare_tagpreview();
  7632.     keep_help_flag = curwin_save->w_buffer->b_help;
  7633.     do_exedit(eap, NULL);
  7634.     keep_help_flag = FALSE;
  7635.     if (curwin != curwin_save && win_valid(curwin_save))
  7636.     {
  7637.     /* Return cursor to where we were */
  7638.     validate_cursor();
  7639.     redraw_later(VALID);
  7640.     win_enter(curwin_save, TRUE);
  7641.     }
  7642.     g_do_tagpreview = 0;
  7643. }
  7644. # endif
  7645.  
  7646. /*
  7647.  * ":stag", ":stselect" and ":stjump".
  7648.  */
  7649.     static void
  7650. ex_stag(eap)
  7651.     exarg_T    *eap;
  7652. {
  7653.     postponed_split = -1;
  7654.     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
  7655. }
  7656. #endif
  7657.  
  7658. /*
  7659.  * ":tag", ":tselect", ":tjump", ":tnext", etc.
  7660.  */
  7661.     static void
  7662. ex_tag(eap)
  7663.     exarg_T    *eap;
  7664. {
  7665.     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name);
  7666. }
  7667.  
  7668.     static void
  7669. ex_tag_cmd(eap, name)
  7670.     exarg_T    *eap;
  7671.     char_u    *name;
  7672. {
  7673.     int        cmd;
  7674.  
  7675.     switch (name[1])
  7676.     {
  7677.     case 'j': cmd = DT_JUMP;    /* ":tjump" */
  7678.           break;
  7679.     case 's': cmd = DT_SELECT;    /* ":tselect" */
  7680.           break;
  7681.     case 'p': cmd = DT_PREV;    /* ":tprevious" */
  7682.           break;
  7683.     case 'N': cmd = DT_PREV;    /* ":tNext" */
  7684.           break;
  7685.     case 'n': cmd = DT_NEXT;    /* ":tnext" */
  7686.           break;
  7687.     case 'o': cmd = DT_POP;        /* ":pop" */
  7688.           break;
  7689.     case 'f':            /* ":tfirst" */
  7690.     case 'r': cmd = DT_FIRST;    /* ":trewind" */
  7691.           break;
  7692.     case 'l': cmd = DT_LAST;    /* ":tlast" */
  7693.           break;
  7694.     default:            /* ":tag" */
  7695. #ifdef FEAT_CSCOPE
  7696.           if (p_cst)
  7697.           {
  7698.               do_cstag(eap);
  7699.               return;
  7700.           }
  7701. #endif
  7702.           cmd = DT_TAG;
  7703.           break;
  7704.     }
  7705.  
  7706.     do_tag(eap->arg, cmd, eap->addr_count > 0 ? (int)eap->line2 : 1,
  7707.                               eap->forceit, TRUE);
  7708. }
  7709.  
  7710. /*
  7711.  * Evaluate cmdline variables.
  7712.  *
  7713.  * change '%'        to curbuf->b_ffname
  7714.  *      '#'        to curwin->w_altfile
  7715.  *      '<cword>' to word under the cursor
  7716.  *      '<cWORD>' to WORD under the cursor
  7717.  *      '<cfile>' to path name under the cursor
  7718.  *      '<sfile>' to sourced file name
  7719.  *      '<afile>' to file name for autocommand
  7720.  *      '<abuf>'  to buffer number for autocommand
  7721.  *      '<amatch>' to matching name for autocommand
  7722.  *
  7723.  * When an error is detected, "errormsg" is set to a non-NULL pointer (may be
  7724.  * "" for error without a message) and NULL is returned.
  7725.  * Returns an allocated string if a valid match was found.
  7726.  * Returns NULL if no match was found.    "usedlen" then still contains the
  7727.  * number of characters to skip.
  7728.  */
  7729.     char_u *
  7730. eval_vars(src, usedlen, lnump, errormsg, srcstart)
  7731.     char_u    *src;        /* pointer into commandline */
  7732.     int        *usedlen;    /* characters after src that are used */
  7733.     linenr_T    *lnump;        /* line number for :e command, or NULL */
  7734.     char_u    **errormsg;    /* pointer to error message */
  7735.     char_u    *srcstart;    /* beginning of valid memory for src */
  7736. {
  7737.     int        i;
  7738.     char_u    *s;
  7739.     char_u    *result;
  7740.     char_u    *resultbuf = NULL;
  7741.     int        resultlen;
  7742.     buf_T    *buf;
  7743.     int        valid = VALID_HEAD + VALID_PATH;    /* assume valid result */
  7744.     int        spec_idx;
  7745. #ifdef FEAT_MODIFY_FNAME
  7746.     int        skip_mod = FALSE;
  7747. #endif
  7748.     static char *(spec_str[]) =
  7749.     {
  7750.             "%",
  7751. #define SPEC_PERC   0
  7752.             "#",
  7753. #define SPEC_HASH   1
  7754.             "<cword>",        /* cursor word */
  7755. #define SPEC_CWORD  2
  7756.             "<cWORD>",        /* cursor WORD */
  7757. #define SPEC_CCWORD 3
  7758.             "<cfile>",        /* cursor path name */
  7759. #define SPEC_CFILE  4
  7760.             "<sfile>",        /* ":so" file name */
  7761. #define SPEC_SFILE  5
  7762. #ifdef FEAT_AUTOCMD
  7763.             "<afile>",        /* autocommand file name */
  7764. # define SPEC_AFILE 6
  7765.             "<abuf>",        /* autocommand buffer number */
  7766. # define SPEC_ABUF  7
  7767.             "<amatch>",        /* autocommand match name */
  7768. # define SPEC_AMATCH 8
  7769. #endif
  7770. #ifdef FEAT_CLIENTSERVER
  7771.             "<client>"
  7772. # define SPEC_CLIENT 9
  7773. #endif
  7774.         };
  7775. #define SPEC_COUNT  (sizeof(spec_str) / sizeof(char *))
  7776.  
  7777. #if defined(FEAT_AUTOCMD) || defined(FEAT_CLIENTSERVER)
  7778.     char_u    strbuf[30];
  7779. #endif
  7780.  
  7781.     *errormsg = NULL;
  7782.  
  7783.     /*
  7784.      * Check if there is something to do.
  7785.      */
  7786.     for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx)
  7787.     {
  7788.     *usedlen = (int)STRLEN(spec_str[spec_idx]);
  7789.     if (STRNCMP(src, spec_str[spec_idx], *usedlen) == 0)
  7790.         break;
  7791.     }
  7792.     if (spec_idx == SPEC_COUNT)        /* no match */
  7793.     {
  7794.     *usedlen = 1;
  7795.     return NULL;
  7796.     }
  7797.  
  7798.     /*
  7799.      * Skip when preceded with a backslash "\%" and "\#".
  7800.      * Note: In "\\%" the % is also not recognized!
  7801.      */
  7802.     if (src > srcstart && src[-1] == '\\')
  7803.     {
  7804.     *usedlen = 0;
  7805.     STRCPY(src - 1, src);        /* remove backslash */
  7806.     return NULL;
  7807.     }
  7808.  
  7809.     /*
  7810.      * word or WORD under cursor
  7811.      */
  7812.     if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD)
  7813.     {
  7814.     resultlen = find_ident_under_cursor(&result, spec_idx == SPEC_CWORD ?
  7815.                       (FIND_IDENT|FIND_STRING) : FIND_STRING);
  7816.     if (resultlen == 0)
  7817.     {
  7818.         *errormsg = (char_u *)"";
  7819.         return NULL;
  7820.     }
  7821.     }
  7822.  
  7823.     /*
  7824.      * '#': Alternate file name
  7825.      * '%': Current file name
  7826.      *        File name under the cursor
  7827.      *        File name for autocommand
  7828.      *    and following modifiers
  7829.      */
  7830.     else
  7831.     {
  7832.     switch (spec_idx)
  7833.     {
  7834.     case SPEC_PERC:        /* '%': current file */
  7835.         if (curbuf->b_fname == NULL)
  7836.         {
  7837.             result = (char_u *)"";
  7838.             valid = 0;        /* Must have ":p:h" to be valid */
  7839.         }
  7840.         else
  7841. #ifdef RISCOS
  7842.             /* Always use the full path for RISC OS if possible. */
  7843.             result = curbuf->b_ffname;
  7844.             if (result == NULL)
  7845.             result = curbuf->b_fname;
  7846. #else
  7847.             result = curbuf->b_fname;
  7848. #endif
  7849.         break;
  7850.  
  7851.     case SPEC_HASH:        /* '#' or "#99": alternate file */
  7852.         if (src[1] == '#')  /* "##": the argument list */
  7853.         {
  7854.             result = arg_all();
  7855.             resultbuf = result;
  7856.             *usedlen = 2;
  7857. #ifdef FEAT_MODIFY_FNAME
  7858.             skip_mod = TRUE;
  7859. #endif
  7860.             break;
  7861.         }
  7862.         s = src + 1;
  7863.         i = (int)getdigits(&s);
  7864.         *usedlen = (int)(s - src); /* length of what we expand */
  7865.  
  7866.         buf = buflist_findnr(i);
  7867.         if (buf == NULL)
  7868.         {
  7869.             *errormsg = (char_u *)_("E194: No alternate file name to substitute for '#'");
  7870.             return NULL;
  7871.         }
  7872.         if (lnump != NULL)
  7873.             *lnump = ECMD_LAST;
  7874.         if (buf->b_fname == NULL)
  7875.         {
  7876.             result = (char_u *)"";
  7877.             valid = 0;        /* Must have ":p:h" to be valid */
  7878.         }
  7879.         else
  7880.             result = buf->b_fname;
  7881.         break;
  7882.  
  7883. #ifdef FEAT_SEARCHPATH
  7884.     case SPEC_CFILE:    /* file name under cursor */
  7885.         result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L);
  7886.         if (result == NULL)
  7887.         {
  7888.             *errormsg = (char_u *)"";
  7889.             return NULL;
  7890.         }
  7891.         resultbuf = result;        /* remember allocated string */
  7892.         break;
  7893. #endif
  7894.  
  7895. #ifdef FEAT_AUTOCMD
  7896.     case SPEC_AFILE:    /* file name for autocommand */
  7897.         result = autocmd_fname;
  7898.         if (result == NULL)
  7899.         {
  7900.             *errormsg = (char_u *)_("E495: no autocommand file name to substitute for \"<afile>\"");
  7901.             return NULL;
  7902.         }
  7903.         break;
  7904.  
  7905.     case SPEC_ABUF:        /* buffer number for autocommand */
  7906.         if (autocmd_bufnr <= 0)
  7907.         {
  7908.             *errormsg = (char_u *)_("E496: no autocommand buffer number to substitute for \"<abuf>\"");
  7909.             return NULL;
  7910.         }
  7911.         sprintf((char *)strbuf, "%d", autocmd_bufnr);
  7912.         result = strbuf;
  7913.         break;
  7914.  
  7915.     case SPEC_AMATCH:    /* match name for autocommand */
  7916.         result = autocmd_match;
  7917.         if (result == NULL)
  7918.         {
  7919.             *errormsg = (char_u *)_("E497: no autocommand match name to substitute for \"<amatch>\"");
  7920.             return NULL;
  7921.         }
  7922.         break;
  7923.  
  7924. #endif
  7925.     case SPEC_SFILE:    /* file name for ":so" command */
  7926.         result = sourcing_name;
  7927.         if (result == NULL)
  7928.         {
  7929.             *errormsg = (char_u *)_("E498: no :source file name to substitute for \"<sfile>\"");
  7930.             return NULL;
  7931.         }
  7932.         break;
  7933. #if defined(FEAT_CLIENTSERVER)
  7934.     case SPEC_CLIENT:    /* Source of last submitted input */
  7935.         sprintf((char *)strbuf, "0x%x", (unsigned int)clientWindow);
  7936.         result = strbuf;
  7937.         break;
  7938. #endif
  7939.     }
  7940.  
  7941.     resultlen = (int)STRLEN(result);    /* length of new string */
  7942.     if (src[*usedlen] == '<')    /* remove the file name extension */
  7943.     {
  7944.         ++*usedlen;
  7945. #ifdef RISCOS
  7946.         if ((s = vim_strrchr(result, '/')) != NULL && s >= gettail(result))
  7947. #else
  7948.         if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result))
  7949. #endif
  7950.         resultlen = (int)(s - result);
  7951.     }
  7952. #ifdef FEAT_MODIFY_FNAME
  7953.     else if (!skip_mod)
  7954.     {
  7955.         valid |= modify_fname(src, usedlen, &result, &resultbuf,
  7956.                                   &resultlen);
  7957.         if (result == NULL)
  7958.         {
  7959.         *errormsg = (char_u *)"";
  7960.         return NULL;
  7961.         }
  7962.     }
  7963. #endif
  7964.     }
  7965.  
  7966.     if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH)
  7967.     {
  7968.     if (valid != VALID_HEAD + VALID_PATH)
  7969.         /* xgettext:no-c-format */
  7970.         *errormsg = (char_u *)_("E499: Empty file name for '%' or '#', only works with \":p:h\"");
  7971.     else
  7972.         *errormsg = (char_u *)_("E500: Evaluates to an empty string");
  7973.     result = NULL;
  7974.     }
  7975.     else
  7976.     result = vim_strnsave(result, resultlen);
  7977.     vim_free(resultbuf);
  7978.     return result;
  7979. }
  7980.  
  7981. /*
  7982.  * Concatenate all files in the argument list, separated by spaces, and return
  7983.  * it in one allocated string.
  7984.  * Spaces and backslashes in the file names are escaped with a backslash.
  7985.  * Returns NULL when out of memory.
  7986.  */
  7987.     static char_u *
  7988. arg_all()
  7989. {
  7990.     int        len;
  7991.     int        idx;
  7992.     char_u    *retval = NULL;
  7993.     char_u    *p;
  7994.  
  7995.     /*
  7996.      * Do this loop two times:
  7997.      * first time: compute the total length
  7998.      * second time: concatenate the names
  7999.      */
  8000.     for (;;)
  8001.     {
  8002.     len = 0;
  8003.     for (idx = 0; idx < ARGCOUNT; ++idx)
  8004.     {
  8005.         p = alist_name(&ARGLIST[idx]);
  8006.         if (p != NULL)
  8007.         {
  8008.         if (len > 0)
  8009.         {
  8010.             /* insert a space in between names */
  8011.             if (retval != NULL)
  8012.             retval[len] = ' ';
  8013.             ++len;
  8014.         }
  8015.         for ( ; *p != NUL; ++p)
  8016.         {
  8017.             if (*p == ' ' || *p == '\\')
  8018.             {
  8019.             /* insert a backslash */
  8020.             if (retval != NULL)
  8021.                 retval[len] = '\\';
  8022.             ++len;
  8023.             }
  8024.             if (retval != NULL)
  8025.             retval[len] = *p;
  8026.             ++len;
  8027.         }
  8028.         }
  8029.     }
  8030.  
  8031.     /* second time: break here */
  8032.     if (retval != NULL)
  8033.     {
  8034.         retval[len] = NUL;
  8035.         break;
  8036.     }
  8037.  
  8038.     /* allocate memory */
  8039.     retval = alloc(len + 1);
  8040.     if (retval == NULL)
  8041.         break;
  8042.     }
  8043.  
  8044.     return retval;
  8045. }
  8046.  
  8047. #if defined(FEAT_AUTOCMD) || defined(PROTO)
  8048. /*
  8049.  * Expand the <sfile> string in "arg".
  8050.  *
  8051.  * Returns an allocated string, or NULL for any error.
  8052.  */
  8053.     char_u *
  8054. expand_sfile(arg)
  8055.     char_u    *arg;
  8056. {
  8057.     char_u    *errormsg;
  8058.     int        len;
  8059.     char_u    *result;
  8060.     char_u    *newres;
  8061.     char_u    *repl;
  8062.     int        srclen;
  8063.     char_u    *p;
  8064.  
  8065.     result = vim_strsave(arg);
  8066.     if (result == NULL)
  8067.     return NULL;
  8068.  
  8069.     for (p = result; *p; )
  8070.     {
  8071.     if (STRNCMP(p, "<sfile>", 7) != 0)
  8072.         ++p;
  8073.     else
  8074.     {
  8075.         /* replace "<sfile>" with the sourced file name, and do ":" stuff */
  8076.         repl = eval_vars(p, &srclen, NULL, &errormsg, result);
  8077.         if (errormsg != NULL)
  8078.         {
  8079.         if (*errormsg)
  8080.             emsg(errormsg);
  8081.         vim_free(result);
  8082.         return NULL;
  8083.         }
  8084.         if (repl == NULL)        /* no match (cannot happen) */
  8085.         {
  8086.         p += srclen;
  8087.         continue;
  8088.         }
  8089.         len = (int)STRLEN(result) - srclen + (int)STRLEN(repl) + 1;
  8090.         newres = alloc(len);
  8091.         if (newres == NULL)
  8092.         {
  8093.         vim_free(repl);
  8094.         vim_free(result);
  8095.         return NULL;
  8096.         }
  8097.         mch_memmove(newres, result, (size_t)(p - result));
  8098.         STRCPY(newres + (p - result), repl);
  8099.         len = (int)STRLEN(newres);
  8100.         STRCAT(newres, p + srclen);
  8101.         vim_free(repl);
  8102.         vim_free(result);
  8103.         result = newres;
  8104.         p = newres + len;        /* continue after the match */
  8105.     }
  8106.     }
  8107.  
  8108.     return result;
  8109. }
  8110. #endif
  8111.  
  8112. #ifdef FEAT_SESSION
  8113. static int ses_win_rec __ARGS((FILE *fd, frame_T *fr));
  8114. static frame_T *ses_skipframe __ARGS((frame_T *fr));
  8115. static int ses_do_frame __ARGS((frame_T *fr));
  8116. static int ses_do_win __ARGS((win_T *wp));
  8117. static int ses_arglist __ARGS((FILE *fd, char *cmd, garray_T *gap, int fullname, unsigned *flagp));
  8118. static int ses_put_fname __ARGS((FILE *fd, char_u *name, unsigned *flagp));
  8119. static int ses_fname __ARGS((FILE *fd, buf_T *buf, unsigned *flagp));
  8120.  
  8121. /*
  8122.  * Write openfile commands for the current buffers to an .exrc file.
  8123.  * Return FAIL on error, OK otherwise.
  8124.  */
  8125.     static int
  8126. makeopens(fd, dirnow)
  8127.     FILE    *fd;
  8128.     char_u    *dirnow;    /* Current directory name */
  8129. {
  8130.     buf_T    *buf;
  8131.     int        only_save_windows = TRUE;
  8132.     int        nr;
  8133.     int        cnr = 1;
  8134.     int        restore_size = TRUE;
  8135.     win_T    *wp;
  8136.     char_u    *sname;
  8137.  
  8138.     if (ssop_flags & SSOP_BUFFERS)
  8139.     only_save_windows = FALSE;        /* Save ALL buffers */
  8140.  
  8141.     /*
  8142.      * Begin by setting the this_session variable, and then other
  8143.      * sessionable variables.
  8144.      */
  8145. #ifdef FEAT_EVAL
  8146.     if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL)
  8147.     return FAIL;
  8148.     if (ssop_flags & SSOP_GLOBALS)
  8149.     if (store_session_globals(fd) == FAIL)
  8150.         return FAIL;
  8151. #endif
  8152.  
  8153.     /*
  8154.      * Close all windows but one.
  8155.      */
  8156.     if (put_line(fd, "silent only") == FAIL)
  8157.     return FAIL;
  8158.  
  8159.     /*
  8160.      * Now a :cd command to the session directory or the current directory
  8161.      */
  8162.     if (ssop_flags & SSOP_SESDIR)
  8163.     {
  8164.     if (put_line(fd, "exe \"cd \" . expand(\"<sfile>:p:h\")") == FAIL)
  8165.         return FAIL;
  8166.     }
  8167.     else if (ssop_flags & SSOP_CURDIR)
  8168.     {
  8169.     sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow);
  8170.     if (sname == NULL
  8171.         || fprintf(fd, "cd %s", sname) < 0 || put_eol(fd) == FAIL)
  8172.         return FAIL;
  8173.     vim_free(sname);
  8174.     }
  8175.  
  8176.     /*
  8177.      * Now save the current files, current buffer first.
  8178.      */
  8179.     if (put_line(fd, "set shortmess=aoO") == FAIL)
  8180.     return FAIL;
  8181.  
  8182.     /* Now put the other buffers into the buffer list */
  8183.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  8184.     {
  8185.     if (!(only_save_windows && buf->b_nwindows == 0)
  8186.         && !(buf->b_help && !(ssop_flags & SSOP_HELP))
  8187.         && buf->b_fname != NULL
  8188.         && buf->b_p_bl)
  8189.     {
  8190.         if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L
  8191.                        : buf->b_wininfo->wi_fpos.lnum) < 0
  8192.             || ses_fname(fd, buf, &ssop_flags) == FAIL)
  8193.         return FAIL;
  8194.     }
  8195.     }
  8196.  
  8197.     /* the global argument list */
  8198.     if (ses_arglist(fd, "args", &global_alist.al_ga,
  8199.                 !(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL)
  8200.     return FAIL;
  8201.  
  8202.     if (ssop_flags & SSOP_RESIZE)
  8203.     {
  8204.     /* Note: after the restore we still check it worked!*/
  8205.     if (fprintf(fd, "set lines=%ld columns=%ld" , Rows, Columns) < 0
  8206.         || put_eol(fd) == FAIL)
  8207.         return FAIL;
  8208.     }
  8209.  
  8210. #ifdef FEAT_GUI
  8211.     if (gui.in_use && (ssop_flags & SSOP_WINPOS))
  8212.     {
  8213.     int    x, y;
  8214.  
  8215.     if (gui_mch_get_winpos(&x, &y) == OK)
  8216.     {
  8217.         /* Note: after the restore we still check it worked!*/
  8218.         if (fprintf(fd, "winpos %d %d", x, y) < 0 || put_eol(fd) == FAIL)
  8219.         return FAIL;
  8220.     }
  8221.     }
  8222. #endif
  8223.  
  8224.     /*
  8225.      * Save current window layout.
  8226.      */
  8227.     if (put_line(fd, "set splitbelow splitright") == FAIL)
  8228.     return FAIL;
  8229.     if (ses_win_rec(fd, topframe) == FAIL)
  8230.     return FAIL;
  8231.     if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL)
  8232.     return FAIL;
  8233.     if (!p_spr && put_line(fd, "set nosplitright") == FAIL)
  8234.     return FAIL;
  8235.  
  8236.     /*
  8237.      * Check if window sizes can be restored (no windows omitted).
  8238.      * Remember the window number of the current window after restoring.
  8239.      */
  8240.     nr = 0;
  8241.     for (wp = firstwin; wp != NULL; wp = W_NEXT(wp))
  8242.     {
  8243.     if (ses_do_win(wp))
  8244.         ++nr;
  8245.     else
  8246.         restore_size = FALSE;
  8247.     if (curwin == wp)
  8248.         cnr = nr;
  8249.     }
  8250.  
  8251.     /* Go to the first window. */
  8252.     if (put_line(fd, "wincmd t") == FAIL)
  8253.     return FAIL;
  8254.  
  8255.     /*
  8256.      * If more than one window, see if sizes can be restored.
  8257.      * First set 'winheight' and 'winwidth' to 1 to avoid the windows being
  8258.      * resized when moving between windows.
  8259.      */
  8260.     if (put_line(fd, "set winheight=1 winwidth=1") == FAIL)
  8261.     return FAIL;
  8262.     if (nr > 1)
  8263.     {
  8264.     if (restore_size && (ssop_flags & SSOP_WINSIZE))
  8265.     {
  8266.         for (wp = firstwin; wp != NULL; wp = wp->w_next)
  8267.         {
  8268.         if (!ses_do_win(wp))
  8269.             continue;
  8270.  
  8271.         /* restore height when not full height */
  8272.         if (wp->w_height + wp->w_status_height < topframe->fr_height
  8273.             && (fprintf(fd,
  8274.                 "exe 'resize ' . ((&lines * %ld + %ld) / %ld)",
  8275.                 (long)wp->w_height, Rows / 2, Rows) < 0
  8276.                               || put_eol(fd) == FAIL))
  8277.             return FAIL;
  8278.  
  8279.         /* restore width when not full width */
  8280.         if (wp->w_width < Columns && (fprintf(fd,
  8281.             "exe 'vert resize ' . ((&columns * %ld + %ld) / %ld)",
  8282.                 (long)wp->w_width, Columns / 2, Columns) < 0
  8283.                               || put_eol(fd) == FAIL))
  8284.             return FAIL;
  8285.         if (put_line(fd, "wincmd w") == FAIL)
  8286.             return FAIL;
  8287.  
  8288.         }
  8289.     }
  8290.     else
  8291.     {
  8292.         /* Just equalise window sizes */
  8293.         if (put_line(fd, "wincmd =") == FAIL)
  8294.         return FAIL;
  8295.     }
  8296.     }
  8297.  
  8298.     /*
  8299.      * Restore the view of the window (options, file, cursor, etc.).
  8300.      */
  8301.     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  8302.     {
  8303.     if (!ses_do_win(wp))
  8304.         continue;
  8305.     if (put_view(fd, wp, TRUE, &ssop_flags) == FAIL)
  8306.         return FAIL;
  8307.     if (nr > 1 && put_line(fd, "wincmd w") == FAIL)
  8308.         return FAIL;
  8309.     }
  8310.  
  8311.     /*
  8312.      * Restore cursor to the current window if it's not the first one.
  8313.      */
  8314.     if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0
  8315.                               || put_eol(fd) == FAIL))
  8316.     return FAIL;
  8317.  
  8318.     /* Re-apply 'winheight', 'winwidth' and 'shortmess'. */
  8319.     if (fprintf(fd, "set winheight=%ld winwidth=%ld shortmess=%s",
  8320.                    p_wh, p_wiw, p_shm) < 0 || put_eol(fd) == FAIL)
  8321.     return FAIL;
  8322.  
  8323.     /*
  8324.      * Lastly, execute the x.vim file if it exists.
  8325.      */
  8326.     if (put_line(fd, "let s:sx = expand(\"<sfile>:p:r\").\"x.vim\"") == FAIL
  8327.         || put_line(fd, "if file_readable(s:sx)") == FAIL
  8328.         || put_line(fd, "  exe \"source \" . s:sx") == FAIL
  8329.         || put_line(fd, "endif") == FAIL)
  8330.     return FAIL;
  8331.  
  8332.     return OK;
  8333. }
  8334.  
  8335. /*
  8336.  * Write commands to "fd" to recursively create windows for frame "fr",
  8337.  * horizontally and vertically split.
  8338.  * After the commands the last window in the frame is the current window.
  8339.  * Returns FAIL when writing the commands to "fd" fails.
  8340.  */
  8341.     static int
  8342. ses_win_rec(fd, fr)
  8343.     FILE    *fd;
  8344.     frame_T    *fr;
  8345. {
  8346.     frame_T    *frc;
  8347.     int        count = 0;
  8348.  
  8349.     if (fr->fr_layout != FR_LEAF)
  8350.     {
  8351.     /* Find first frame that's not skipped and then create a window for
  8352.      * each following one (first frame is already there). */
  8353.     frc = ses_skipframe(fr->fr_child);
  8354.     if (frc != NULL)
  8355.         while ((frc = ses_skipframe(frc->fr_next)) != NULL)
  8356.         {
  8357.         /* Make window as big as possible so that we have lots of room
  8358.          * to split. */
  8359.         if (put_line(fd, "wincmd _ | wincmd |") == FAIL
  8360.             || put_line(fd, fr->fr_layout == FR_COL
  8361.                         ? "split" : "vsplit") == FAIL)
  8362.             return FAIL;
  8363.         ++count;
  8364.         }
  8365.  
  8366.     /* Go back to the first window. */
  8367.     if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
  8368.             ? "%dwincmd k" : "%dwincmd h", count) < 0
  8369.                               || put_eol(fd) == FAIL))
  8370.         return FAIL;
  8371.  
  8372.     /* Recursively create frames/windows in each window of this column or
  8373.      * row. */
  8374.     frc = ses_skipframe(fr->fr_child);
  8375.     while (frc != NULL)
  8376.     {
  8377.         ses_win_rec(fd, frc);
  8378.         frc = ses_skipframe(frc->fr_next);
  8379.         /* Go to next window. */
  8380.         if (frc != NULL && put_line(fd, "wincmd w") == FAIL)
  8381.         return FAIL;
  8382.     }
  8383.     }
  8384.     return OK;
  8385. }
  8386.  
  8387. /*
  8388.  * Skip frames that don't contain windows we want to save in the Session.
  8389.  * Returns NULL when there none.
  8390.  */
  8391.     static frame_T *
  8392. ses_skipframe(fr)
  8393.     frame_T    *fr;
  8394. {
  8395.     frame_T    *frc;
  8396.  
  8397.     for (frc = fr; frc != NULL; frc = frc->fr_next)
  8398.     if (ses_do_frame(frc))
  8399.         break;
  8400.     return frc;
  8401. }
  8402.  
  8403. /*
  8404.  * Return TRUE if frame "fr" has a window somewhere that we want to save in
  8405.  * the Session.
  8406.  */
  8407.     static int
  8408. ses_do_frame(fr)
  8409.     frame_T    *fr;
  8410. {
  8411.     frame_T    *frc;
  8412.  
  8413.     if (fr->fr_layout == FR_LEAF)
  8414.     return ses_do_win(fr->fr_win);
  8415.     for (frc = fr->fr_child; frc != NULL; frc = frc->fr_next)
  8416.     if (ses_do_frame(frc))
  8417.         return TRUE;
  8418.     return FALSE;
  8419. }
  8420.  
  8421. /*
  8422.  * Return non-zero if window "wp" is to be stored in the Session.
  8423.  */
  8424.     static int
  8425. ses_do_win(wp)
  8426.     win_T    *wp;
  8427. {
  8428.     if (wp->w_buffer->b_fname == NULL
  8429. #ifdef FEAT_QUICKFIX
  8430.         /* When 'buftype' is "nofile" can't restore the window contents. */
  8431.         || bt_nofile(wp->w_buffer)
  8432. #endif
  8433.        )
  8434.     return (ssop_flags & SSOP_BLANK);
  8435.     if (wp->w_buffer->b_help)
  8436.     return (ssop_flags & SSOP_HELP);
  8437.     return TRUE;
  8438. }
  8439.  
  8440. /*
  8441.  * Write commands to "fd" to restore the view of a window.
  8442.  * Caller must make sure 'scrolloff' is zero.
  8443.  */
  8444.     static int
  8445. put_view(fd, wp, add_edit, flagp)
  8446.     FILE    *fd;
  8447.     win_T    *wp;
  8448.     int        add_edit;    /* add ":edit" command to view */
  8449.     unsigned    *flagp;        /* vop_flags or ssop_flags */
  8450. {
  8451.     win_T    *save_curwin;
  8452.     int        f;
  8453.     int        do_cursor;
  8454.  
  8455.     /* Always restore cursor position for ":mksession".  For ":mkview" only
  8456.      * when 'viewoptions' contains "cursor". */
  8457.     do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
  8458.  
  8459.     /*
  8460.      * Local argument list.
  8461.      */
  8462.     if (wp->w_alist == &global_alist)
  8463.     {
  8464.     if (put_line(fd, "argglobal") == FAIL)
  8465.         return FAIL;
  8466.     }
  8467.     else
  8468.     {
  8469.     if (ses_arglist(fd, "arglocal", &wp->w_alist->al_ga,
  8470.             flagp == &vop_flags
  8471.             || !(*flagp & SSOP_CURDIR)
  8472.             || wp->w_localdir != NULL, flagp) == FAIL)
  8473.         return FAIL;
  8474.     }
  8475.  
  8476.     /* Only when part of a session: restore the argument index. */
  8477.     if (wp->w_arg_idx != 0 && flagp == &ssop_flags)
  8478.     {
  8479.     if (fprintf(fd, "%ldnext", (long)wp->w_arg_idx) < 0
  8480.         || put_eol(fd) == FAIL)
  8481.         return FAIL;
  8482.     }
  8483.  
  8484.     if (add_edit)
  8485.     {
  8486.     /*
  8487.      * Load the file.
  8488.      */
  8489.     if (wp->w_buffer->b_ffname != NULL
  8490. #ifdef FEAT_QUICKFIX
  8491.         && !bt_nofile(wp->w_buffer)
  8492. #endif
  8493.         )
  8494.     {
  8495.         /*
  8496.          * Editing a file in this buffer: use ":edit file".
  8497.          * This may have side effects! (e.g., compressed or network file).
  8498.          */
  8499.         if (fputs("edit ", fd) < 0
  8500.             || ses_fname(fd, wp->w_buffer, flagp) == FAIL)
  8501.         return FAIL;
  8502.     }
  8503.     else
  8504.     {
  8505.         /* No file in this buffer, just make it empty. */
  8506.         if (put_line(fd, "enew") == FAIL)
  8507.         return FAIL;
  8508. #ifdef FEAT_QUICKFIX
  8509.         if (wp->w_buffer->b_ffname != NULL)
  8510.         {
  8511.         /* The buffer does have a name, but it's not a file name. */
  8512.         if (fputs("file ", fd) < 0
  8513.             || ses_fname(fd, wp->w_buffer, flagp) == FAIL)
  8514.             return FAIL;
  8515.         }
  8516. #endif
  8517.         do_cursor = FALSE;
  8518.     }
  8519.     }
  8520.  
  8521.     /*
  8522.      * Local mappings and abbreviations.
  8523.      */
  8524.     if ((*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
  8525.                      && makemap(fd, wp->w_buffer) == FAIL)
  8526.     return FAIL;
  8527.  
  8528.     /*
  8529.      * Local options.  Need to go to the window temporarily.
  8530.      * Store only local values when using ":mkview" and when ":mksession" is
  8531.      * used and 'sessionoptions' doesn't include "options".
  8532.      * Some folding options are always stored when "folds" is included,
  8533.      * otherwise the folds would not be restored correctly.
  8534.      */
  8535.     save_curwin = curwin;
  8536.     curwin = wp;
  8537.     curbuf = curwin->w_buffer;
  8538.     if (*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
  8539.     f = makeset(fd, OPT_LOCAL,
  8540.                  flagp == &vop_flags || !(*flagp & SSOP_OPTIONS));
  8541. #ifdef FEAT_FOLDING
  8542.     else if (*flagp & SSOP_FOLDS)
  8543.     f = makefoldset(fd);
  8544. #endif
  8545.     else
  8546.     f = OK;
  8547.     curwin = save_curwin;
  8548.     curbuf = curwin->w_buffer;
  8549.     if (f == FAIL)
  8550.     return FAIL;
  8551.  
  8552. #ifdef FEAT_FOLDING
  8553.     /*
  8554.      * Save Folds when 'buftype' is empty and for help files.
  8555.      */
  8556.     if ((*flagp & SSOP_FOLDS)
  8557.         && wp->w_buffer->b_ffname != NULL
  8558.         && (*wp->w_buffer->b_p_bt == NUL || wp->w_buffer->b_help))
  8559.     {
  8560.     if (put_folds(fd, wp) == FAIL)
  8561.         return FAIL;
  8562.     }
  8563. #endif
  8564.  
  8565.     /*
  8566.      * Set the cursor after creating folds, since that moves the cursor.
  8567.      */
  8568.     if (do_cursor)
  8569.     {
  8570.  
  8571.     /* Restore the cursor line in the file and relatively in the
  8572.      * window.  Don't use "G", it changes the jumplist. */
  8573.     if (fprintf(fd, "let s:l = %ld - ((%ld * winheight(0) + %ld) / %ld)",
  8574.             (long)wp->w_cursor.lnum,
  8575.             (long)(wp->w_cursor.lnum - wp->w_topline),
  8576.             (long)wp->w_height / 2, (long)wp->w_height) < 0
  8577.         || put_eol(fd) == FAIL
  8578.         || put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL
  8579.         || put_line(fd, "exe s:l") == FAIL
  8580.         || put_line(fd, "normal! zt") == FAIL
  8581.         || fprintf(fd, "%ld", (long)wp->w_cursor.lnum) < 0
  8582.         || put_eol(fd) == FAIL)
  8583.         return FAIL;
  8584.     /* Restore the cursor column and left offset when not wrapping. */
  8585.     if (wp->w_cursor.col == 0)
  8586.     {
  8587.         if (put_line(fd, "normal! 0") == FAIL)
  8588.         return FAIL;
  8589.     }
  8590.     else
  8591.     {
  8592.         if (!wp->w_p_wrap && wp->w_leftcol > 0 && wp->w_width > 0)
  8593.         {
  8594.         if (fprintf(fd,
  8595.               "let s:c = %ld - ((%ld * winwidth(0) + %ld) / %ld)",
  8596.                 (long)wp->w_cursor.col,
  8597.                 (long)(wp->w_cursor.col - wp->w_leftcol),
  8598.                 (long)wp->w_width / 2, (long)wp->w_width) < 0
  8599.             || put_eol(fd) == FAIL
  8600.             || put_line(fd, "if s:c > 0") == FAIL
  8601.             || fprintf(fd,
  8602.                 "  exe 'normal! 0' . s:c . 'lzs' . (%ld - s:c) . 'l'",
  8603.                 (long)wp->w_cursor.col) < 0
  8604.             || put_eol(fd) == FAIL
  8605.             || put_line(fd, "else") == FAIL
  8606.             || fprintf(fd, "  normal! 0%dl", wp->w_cursor.col) < 0
  8607.             || put_eol(fd) == FAIL
  8608.             || put_line(fd, "endif") == FAIL)
  8609.             return FAIL;
  8610.         }
  8611.         else
  8612.         {
  8613.         if (fprintf(fd, "normal! 0%dl", wp->w_cursor.col) < 0
  8614.             || put_eol(fd) == FAIL)
  8615.             return FAIL;
  8616.         }
  8617.     }
  8618.     }
  8619.  
  8620.     /*
  8621.      * Local directory.
  8622.      */
  8623.     if (wp->w_localdir != NULL)
  8624.     {
  8625.     if (fputs("lcd ", fd) < 0
  8626.         || ses_put_fname(fd, wp->w_localdir, flagp) == FAIL
  8627.         || put_eol(fd) == FAIL)
  8628.         return FAIL;
  8629.     }
  8630.  
  8631.     return OK;
  8632. }
  8633.  
  8634. /*
  8635.  * Write an argument list to the session file.
  8636.  * Returns FAIL if writing fails.
  8637.  */
  8638.     static int
  8639. ses_arglist(fd, cmd, gap, fullname, flagp)
  8640.     FILE    *fd;
  8641.     char    *cmd;
  8642.     garray_T    *gap;
  8643.     int        fullname;    /* TRUE: use full path name */
  8644.     unsigned    *flagp;
  8645. {
  8646.     int        i;
  8647.     char_u    buf[MAXPATHL];
  8648.     char_u    *s;
  8649.  
  8650.     if (gap->ga_len == 0)
  8651.     return put_line(fd, "silent! argdel *");
  8652.     if (fputs(cmd, fd) < 0)
  8653.     return FAIL;
  8654.     for (i = 0; i < gap->ga_len; ++i)
  8655.     {
  8656.     /* NULL file names are skipped (only happens when out of memory). */
  8657.     s = alist_name(&((aentry_T *)gap->ga_data)[i]);
  8658.     if (s != NULL)
  8659.     {
  8660.         if (fullname)
  8661.         {
  8662.         (void)vim_FullName(s, buf, MAXPATHL, FALSE);
  8663.         s = buf;
  8664.         }
  8665.         if (fputs(" ", fd) < 0 || ses_put_fname(fd, s, flagp) == FAIL)
  8666.         return FAIL;
  8667.     }
  8668.     }
  8669.     return put_eol(fd);
  8670. }
  8671.  
  8672. /*
  8673.  * Write a buffer name to the session file.
  8674.  * Also ends the line.
  8675.  * Returns FAIL if writing fails.
  8676.  */
  8677.     static int
  8678. ses_fname(fd, buf, flagp)
  8679.     FILE    *fd;
  8680.     buf_T    *buf;
  8681.     unsigned    *flagp;
  8682. {
  8683.     char_u    *name;
  8684.  
  8685.     /* Use the short file name if the current directory is known at the time
  8686.      * the session file will be sourced.  Don't do this for ":mkview", we
  8687.      * don't know the current directory. */
  8688.     if (buf->b_sfname != NULL
  8689.         && flagp == &ssop_flags
  8690.         && (ssop_flags & (SSOP_CURDIR | SSOP_SESDIR)))
  8691.     name = buf->b_sfname;
  8692.     else
  8693.     name = buf->b_ffname;
  8694.     if (ses_put_fname(fd, name, flagp) == FAIL || put_eol(fd) == FAIL)
  8695.     return FAIL;
  8696.     return OK;
  8697. }
  8698.  
  8699. /*
  8700.  * Write a file name to the session file.
  8701.  * Takes care of the "slash" option in 'sessionoptions' and escapes special
  8702.  * characters.
  8703.  * Returns FAIL if writing fails.
  8704.  */
  8705.     static int
  8706. ses_put_fname(fd, name, flagp)
  8707.     FILE    *fd;
  8708.     char_u    *name;
  8709.     unsigned    *flagp;
  8710. {
  8711.     char_u    *sname;
  8712.     int        retval = OK;
  8713.     int        c;
  8714.  
  8715.     sname = home_replace_save(NULL, name);
  8716.     if (sname != NULL)
  8717.     name = sname;
  8718.     while (*name != NUL)
  8719.     {
  8720. #ifdef FEAT_MBYTE
  8721.     {
  8722.         int l;
  8723.  
  8724.         if (has_mbyte && (l = (*mb_ptr2len_check)(name)) > 1)
  8725.         {
  8726.         /* copy a multibyte char */
  8727.         while (--l >= 0)
  8728.         {
  8729.             if (putc(*name, fd) != *name)
  8730.             retval = FAIL;
  8731.             ++name;
  8732.         }
  8733.         continue;
  8734.         }
  8735.     }
  8736. #endif
  8737.     c = *name++;
  8738.     if (c == '\\' && (*flagp & SSOP_SLASH))
  8739.         /* change a backslash to a forward slash */
  8740.         c = '/';
  8741.     else if ((vim_strchr(escape_chars, c) != NULL
  8742. #ifdef BACKSLASH_IN_FILENAME
  8743.             && c != '\\'
  8744. #endif
  8745.          ) || c == '#' || c == '%')
  8746.     {
  8747.         /* escape a special character with a backslash */
  8748.         if (putc('\\', fd) != '\\')
  8749.         retval = FAIL;
  8750.     }
  8751.     if (putc(c, fd) != c)
  8752.         retval = FAIL;
  8753.     }
  8754.     vim_free(sname);
  8755.     return retval;
  8756. }
  8757.  
  8758. /*
  8759.  * ":loadview [nr]"
  8760.  */
  8761.     static void
  8762. ex_loadview(eap)
  8763.     exarg_T    *eap;
  8764. {
  8765.     char_u    *fname;
  8766.  
  8767.     fname = get_view_file(*eap->arg);
  8768.     if (fname != NULL)
  8769.     {
  8770.     do_source(fname, FALSE, FALSE);
  8771.     vim_free(fname);
  8772.     }
  8773. }
  8774.  
  8775. /*
  8776.  * Get the name of the view file for the current buffer.
  8777.  */
  8778.     static char_u *
  8779. get_view_file(c)
  8780.     int        c;
  8781. {
  8782.     int        len = 0;
  8783.     char_u    *p, *s;
  8784.     char_u    *retval;
  8785.     char_u    *sname;
  8786.  
  8787.     if (curbuf->b_ffname == NULL)
  8788.     {
  8789.     EMSG(_(e_noname));
  8790.     return NULL;
  8791.     }
  8792.     sname = home_replace_save(NULL, curbuf->b_ffname);
  8793.     if (sname == NULL)
  8794.     return NULL;
  8795.  
  8796.     /*
  8797.      * We want a file name without separators, because we're not going to make
  8798.      * a directory.
  8799.      * "normal" path separator    -> "=+"
  8800.      * "="            -> "=="
  8801.      * ":" path separator    -> "=-"
  8802.      */
  8803.     for (p = sname; *p; ++p)
  8804.     if (*p == '=' || vim_ispathsep(*p))
  8805.         ++len;
  8806.     retval = alloc((unsigned)(STRLEN(sname) + len + STRLEN(p_vdir) + 9));
  8807.     if (retval != NULL)
  8808.     {
  8809.     STRCPY(retval, p_vdir);
  8810.     add_pathsep(retval);
  8811.     s = retval + STRLEN(retval);
  8812.     for (p = sname; *p; ++p)
  8813.     {
  8814.         if (*p == '=')
  8815.         {
  8816.         *s++ = '=';
  8817.         *s++ = '=';
  8818.         }
  8819.         else if (vim_ispathsep(*p))
  8820.         {
  8821.         *s++ = '=';
  8822. #ifdef MACOS_CLASSIC /* TODO: Is it also needed for MACOS_X? (Dany) */
  8823.         *s++ = '+';
  8824. #else
  8825. # if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) || defined(RISCOS) \
  8826.     || defined(VMS)
  8827.         if (*p == ':')
  8828.             *s++ = '-';
  8829.         else
  8830. # endif
  8831.             *s++ = '+';
  8832. #endif
  8833.         }
  8834.         else
  8835.         *s++ = *p;
  8836.     }
  8837.     *s++ = '=';
  8838.     *s++ = c;
  8839.     STRCPY(s, ".vim");
  8840.     }
  8841.  
  8842.     vim_free(sname);
  8843.     return retval;
  8844. }
  8845.  
  8846. #endif /* FEAT_SESSION */
  8847.  
  8848. /*
  8849.  * Write end-of-line character(s) for ":mkexrc", ":mkvimrc" and ":mksession".
  8850.  * Return FAIL for a write error.
  8851.  */
  8852.     int
  8853. put_eol(fd)
  8854.     FILE    *fd;
  8855. {
  8856.     if (
  8857. #ifdef USE_CRNL
  8858.         (
  8859. # ifdef MKSESSION_NL
  8860.          !mksession_nl &&
  8861. # endif
  8862.          (putc('\r', fd) < 0)) ||
  8863. #endif
  8864.         (putc('\n', fd) < 0))
  8865.     return FAIL;
  8866.     return OK;
  8867. }
  8868.  
  8869. /*
  8870.  * Write a line to "fd".
  8871.  * Return FAIL for a write error.
  8872.  */
  8873.     int
  8874. put_line(fd, s)
  8875.     FILE    *fd;
  8876.     char    *s;
  8877. {
  8878.     if (fputs(s, fd) < 0 || put_eol(fd) == FAIL)
  8879.     return FAIL;
  8880.     return OK;
  8881. }
  8882.  
  8883. #ifdef FEAT_VIMINFO
  8884. /*
  8885.  * ":rviminfo" and ":wviminfo".
  8886.  */
  8887.     static void
  8888. ex_viminfo(eap)
  8889.     exarg_T    *eap;
  8890. {
  8891.     char_u    *save_viminfo;
  8892.  
  8893.     save_viminfo = p_viminfo;
  8894.     if (*p_viminfo == NUL)
  8895.     p_viminfo = (char_u *)"'100";
  8896.     if (eap->cmdidx == CMD_rviminfo)
  8897.     {
  8898.     if (read_viminfo(eap->arg, TRUE, TRUE, eap->forceit) == FAIL)
  8899.         EMSG(_("E195: Cannot open viminfo file for reading"));
  8900.     }
  8901.     else
  8902.     write_viminfo(eap->arg, eap->forceit);
  8903.     p_viminfo = save_viminfo;
  8904. }
  8905. #endif
  8906.  
  8907. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
  8908.     void
  8909. dialog_msg(buff, format, fname)
  8910.     char_u    *buff;
  8911.     char    *format;
  8912.     char_u    *fname;
  8913. {
  8914.     int        len;
  8915.  
  8916.     if (fname == NULL)
  8917.     fname = (char_u *)_("Untitled");
  8918.     len = (int)STRLEN(format) + (int)STRLEN(fname);
  8919.     if (len >= IOSIZE)
  8920.     sprintf((char *)buff, format, (int)(IOSIZE - STRLEN(format)), fname);
  8921.     else
  8922.     sprintf((char *)buff, format, (int)STRLEN(fname), fname);
  8923. }
  8924. #endif
  8925.  
  8926. /*
  8927.  * ":behave {mswin,xterm}"
  8928.  */
  8929.     static void
  8930. ex_behave(eap)
  8931.     exarg_T    *eap;
  8932. {
  8933.     if (STRCMP(eap->arg, "mswin") == 0)
  8934.     {
  8935.     set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0);
  8936.     set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0);
  8937.     set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0);
  8938.     set_option_value((char_u *)"keymodel", 0L,
  8939.                          (char_u *)"startsel,stopsel", 0);
  8940.     }
  8941.     else if (STRCMP(eap->arg, "xterm") == 0)
  8942.     {
  8943.     set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0);
  8944.     set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0);
  8945.     set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0);
  8946.     set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0);
  8947.     }
  8948.     else
  8949.     EMSG2(_(e_invarg2), eap->arg);
  8950. }
  8951.  
  8952. #ifdef FEAT_AUTOCMD
  8953. static int filetype_detect = FALSE;
  8954. static int filetype_plugin = FALSE;
  8955. static int filetype_indent = FALSE;
  8956.  
  8957. /*
  8958.  * ":filetype [plugin] [indent] {on,off,detect}"
  8959.  * on: Load the filetype.vim file to install autocommands for file types.
  8960.  * off: Load the ftoff.vim file to remove all autocommands for file types.
  8961.  * plugin on: load filetype.vim and ftplugin.vim
  8962.  * plugin off: load ftplugof.vim
  8963.  * indent on: load filetype.vim and indent.vim
  8964.  * indent off: load indoff.vim
  8965.  */
  8966.     static void
  8967. ex_filetype(eap)
  8968.     exarg_T    *eap;
  8969. {
  8970.     char_u    *arg = eap->arg;
  8971.     int        plugin = FALSE;
  8972.     int        indent = FALSE;
  8973.  
  8974.     if (*eap->arg == NUL)
  8975.     {
  8976.     /* Print current status. */
  8977.     smsg((char_u *)"filetype detection:%s  plugin:%s  indent:%s",
  8978.         filetype_detect ? "ON" : "OFF",
  8979.         filetype_plugin ? (filetype_detect ? "ON" : "(on)") : "OFF",
  8980.         filetype_indent ? (filetype_detect ? "ON" : "(on)") : "OFF");
  8981.     return;
  8982.     }
  8983.  
  8984.     /* Accept "plugin" and "indent" in any order. */
  8985.     for (;;)
  8986.     {
  8987.     if (STRNCMP(arg, "plugin", 6) == 0)
  8988.     {
  8989.         plugin = TRUE;
  8990.         arg = skipwhite(arg + 6);
  8991.         continue;
  8992.     }
  8993.     if (STRNCMP(arg, "indent", 6) == 0)
  8994.     {
  8995.         indent = TRUE;
  8996.         arg = skipwhite(arg + 6);
  8997.         continue;
  8998.     }
  8999.     break;
  9000.     }
  9001.     if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0)
  9002.     {
  9003.     if (*arg == 'o' || !filetype_detect)
  9004.     {
  9005.         cmd_runtime((char_u *)FILETYPE_FILE, TRUE);
  9006.         filetype_detect = TRUE;
  9007.         if (plugin)
  9008.         {
  9009.         cmd_runtime((char_u *)FTPLUGIN_FILE, TRUE);
  9010.         filetype_plugin = TRUE;
  9011.         }
  9012.         if (indent)
  9013.         {
  9014.         cmd_runtime((char_u *)INDENT_FILE, TRUE);
  9015.         filetype_indent = TRUE;
  9016.         }
  9017.     }
  9018.     if (*arg == 'd')
  9019.     {
  9020.         (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE);
  9021.         do_modelines();
  9022.     }
  9023.     }
  9024.     else if (STRCMP(arg, "off") == 0)
  9025.     {
  9026.     if (plugin || indent)
  9027.     {
  9028.         if (plugin)
  9029.         {
  9030.         cmd_runtime((char_u *)FTPLUGOF_FILE, TRUE);
  9031.         filetype_plugin = FALSE;
  9032.         }
  9033.         if (indent)
  9034.         {
  9035.         cmd_runtime((char_u *)INDOFF_FILE, TRUE);
  9036.         filetype_indent = FALSE;
  9037.         }
  9038.     }
  9039.     else
  9040.     {
  9041.         cmd_runtime((char_u *)FTOFF_FILE, TRUE);
  9042.         filetype_detect = FALSE;
  9043.     }
  9044.     }
  9045.     else
  9046.     EMSG2(_(e_invarg2), arg);
  9047. }
  9048.  
  9049. /*
  9050.  * ":setfiletype {name}"
  9051.  */
  9052.     static void
  9053. ex_setfiletype(eap)
  9054.     exarg_T    *eap;
  9055. {
  9056.     if (!did_filetype)
  9057.     set_option_value((char_u *)"filetype", 0L, eap->arg, OPT_LOCAL);
  9058. }
  9059. #endif
  9060.  
  9061. /*ARGSUSED*/
  9062.     static void
  9063. ex_digraphs(eap)
  9064.     exarg_T    *eap;
  9065. {
  9066. #ifdef FEAT_DIGRAPHS
  9067.     if (*eap->arg != NUL)
  9068.     putdigraph(eap->arg);
  9069.     else
  9070.     listdigraphs();
  9071. #else
  9072.     EMSG(_("E196: No digraphs in this version"));
  9073. #endif
  9074. }
  9075.  
  9076.     static void
  9077. ex_set(eap)
  9078.     exarg_T    *eap;
  9079. {
  9080.     int        flags = 0;
  9081.  
  9082.     if (eap->cmdidx == CMD_setlocal)
  9083.     flags = OPT_LOCAL;
  9084.     else if (eap->cmdidx == CMD_setglobal)
  9085.     flags = OPT_GLOBAL;
  9086. #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD) && defined(FEAT_BROWSE)
  9087.     if (cmdmod.browse && flags == 0)
  9088.     ex_options(eap);
  9089.     else
  9090. #endif
  9091.     (void)do_set(eap->arg, flags);
  9092. }
  9093.  
  9094. #ifdef FEAT_SEARCH_EXTRA
  9095. /*
  9096.  * ":nohlsearch"
  9097.  */
  9098. /*ARGSUSED*/
  9099.     static void
  9100. ex_nohlsearch(eap)
  9101.     exarg_T    *eap;
  9102. {
  9103.     no_hlsearch = TRUE;
  9104.     redraw_all_later(NOT_VALID);
  9105. }
  9106.  
  9107. /*
  9108.  * ":match {group} {pattern}"
  9109.  * Sets nextcmd to the start of the next command, if any.  Also called when
  9110.  * skipping commands to find the next command.
  9111.  */
  9112.     static void
  9113. ex_match(eap)
  9114.     exarg_T    *eap;
  9115. {
  9116.     char_u    *p;
  9117.     char_u    *end;
  9118.     int        c;
  9119.  
  9120.     /* First clear any old pattern. */
  9121.     if (!eap->skip)
  9122.     {
  9123.     vim_free(curwin->w_match.regprog);
  9124.     curwin->w_match.regprog = NULL;
  9125.     redraw_later(NOT_VALID);    /* always need a redraw */
  9126.     }
  9127.  
  9128.     if (ends_excmd(*eap->arg))
  9129.     end = eap->arg;
  9130.     else if ((STRNICMP(eap->arg, "none", 4) == 0
  9131.         && (vim_iswhite(eap->arg[4]) || ends_excmd(eap->arg[4]))))
  9132.     end = eap->arg + 4;
  9133.     else
  9134.     {
  9135.     p = skiptowhite(eap->arg);
  9136.     if (!eap->skip)
  9137.     {
  9138.         curwin->w_match_id = syn_namen2id(eap->arg, (int)(p - eap->arg));
  9139.         if (curwin->w_match_id == 0)
  9140.         {
  9141.         EMSG2(_(e_nogroup), eap->arg);
  9142.         return;
  9143.         }
  9144.     }
  9145.     p = skipwhite(p);
  9146.     if (*p == NUL)
  9147.     {
  9148.         /* There must be two arguments. */
  9149.         EMSG2(_(e_invarg2), eap->arg);
  9150.         return;
  9151.     }
  9152.     end = skip_regexp(p + 1, *p, TRUE, NULL);
  9153.     if (!eap->skip)
  9154.     {
  9155.         if (*end != NUL && !ends_excmd(*skipwhite(end + 1)))
  9156.         {
  9157.         eap->errmsg = e_trailing;
  9158.         return;
  9159.         }
  9160.  
  9161.         c = *end;
  9162.         *end = NUL;
  9163.         curwin->w_match.regprog = vim_regcomp(p + 1, RE_MAGIC);
  9164.         *end = c;
  9165.         if (curwin->w_match.regprog == NULL)
  9166.         {
  9167.         EMSG2(_(e_invarg2), p);
  9168.         return;
  9169.         }
  9170.     }
  9171.     }
  9172.     eap->nextcmd = find_nextcmd(end);
  9173. }
  9174. #endif
  9175.  
  9176. #ifdef FEAT_CRYPT
  9177. /*
  9178.  * ":X": Get crypt key
  9179.  */
  9180. /*ARGSUSED*/
  9181.     static void
  9182. ex_X(eap)
  9183.     exarg_T    *eap;
  9184. {
  9185.     (void)get_crypt_key(TRUE, TRUE);
  9186. }
  9187. #endif
  9188.  
  9189. #ifdef FEAT_FOLDING
  9190.     static void
  9191. ex_fold(eap)
  9192.     exarg_T    *eap;
  9193. {
  9194.     if (foldManualAllowed(TRUE))
  9195.     foldCreate(eap->line1, eap->line2);
  9196. }
  9197.  
  9198.     static void
  9199. ex_foldopen(eap)
  9200.     exarg_T    *eap;
  9201. {
  9202.     opFoldRange(eap->line1, eap->line2, eap->cmdidx == CMD_foldopen,
  9203.                              eap->forceit, FALSE);
  9204. }
  9205.  
  9206.     static void
  9207. ex_folddo(eap)
  9208.     exarg_T    *eap;
  9209. {
  9210.     linenr_T    lnum;
  9211.  
  9212.     /* First set the marks for all lines closed/open. */
  9213.     for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
  9214.     if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed))
  9215.         ml_setmarked(lnum);
  9216.  
  9217.     /* Execute the command on the marked lines. */
  9218.     global_exe(eap->arg);
  9219.     ml_clearmarked();       /* clear rest of the marks */
  9220. }
  9221. #endif
  9222.