Merge branch 'vim'
[MacVim.git] / src / ex_cmds2.c
blobcfb3d1c9e860921623082fb34acf9967b8a85838
1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
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 */
11 * ex_cmds2.c: some more functions for command line commands
14 #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
15 # include "vimio.h" /* for mch_open(), must be before vim.h */
16 #endif
18 #include "vim.h"
19 #include "version.h"
21 static void cmd_source __ARGS((char_u *fname, exarg_T *eap));
23 #ifdef FEAT_EVAL
24 /* Growarray to store info about already sourced scripts.
25 * For Unix also store the dev/ino, so that we don't have to stat() each
26 * script when going through the list. */
27 typedef struct scriptitem_S
29 char_u *sn_name;
30 # ifdef UNIX
31 int sn_dev;
32 ino_t sn_ino;
33 # endif
34 # ifdef FEAT_PROFILE
35 int sn_prof_on; /* TRUE when script is/was profiled */
36 int sn_pr_force; /* forceit: profile functions in this script */
37 proftime_T sn_pr_child; /* time set when going into first child */
38 int sn_pr_nest; /* nesting for sn_pr_child */
39 /* profiling the script as a whole */
40 int sn_pr_count; /* nr of times sourced */
41 proftime_T sn_pr_total; /* time spent in script + children */
42 proftime_T sn_pr_self; /* time spent in script itself */
43 proftime_T sn_pr_start; /* time at script start */
44 proftime_T sn_pr_children; /* time in children after script start */
45 /* profiling the script per line */
46 garray_T sn_prl_ga; /* things stored for every line */
47 proftime_T sn_prl_start; /* start time for current line */
48 proftime_T sn_prl_children; /* time spent in children for this line */
49 proftime_T sn_prl_wait; /* wait start time for current line */
50 int sn_prl_idx; /* index of line being timed; -1 if none */
51 int sn_prl_execed; /* line being timed was executed */
52 # endif
53 } scriptitem_T;
55 static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL};
56 #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1])
58 # ifdef FEAT_PROFILE
59 /* Struct used in sn_prl_ga for every line of a script. */
60 typedef struct sn_prl_S
62 int snp_count; /* nr of times line was executed */
63 proftime_T sn_prl_total; /* time spent in a line + children */
64 proftime_T sn_prl_self; /* time spent in a line itself */
65 } sn_prl_T;
67 # define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
68 # endif
69 #endif
71 #if defined(FEAT_EVAL) || defined(PROTO)
72 static int debug_greedy = FALSE; /* batch mode debugging: don't save
73 and restore typeahead. */
76 * do_debug(): Debug mode.
77 * Repeatedly get Ex commands, until told to continue normal execution.
79 void
80 do_debug(cmd)
81 char_u *cmd;
83 int save_msg_scroll = msg_scroll;
84 int save_State = State;
85 int save_did_emsg = did_emsg;
86 int save_cmd_silent = cmd_silent;
87 int save_msg_silent = msg_silent;
88 int save_emsg_silent = emsg_silent;
89 int save_redir_off = redir_off;
90 tasave_T typeaheadbuf;
91 int typeahead_saved = FALSE;
92 int save_ignore_script = 0;
93 # ifdef FEAT_EX_EXTRA
94 int save_ex_normal_busy;
95 # endif
96 int n;
97 char_u *cmdline = NULL;
98 char_u *p;
99 char *tail = NULL;
100 static int last_cmd = 0;
101 #define CMD_CONT 1
102 #define CMD_NEXT 2
103 #define CMD_STEP 3
104 #define CMD_FINISH 4
105 #define CMD_QUIT 5
106 #define CMD_INTERRUPT 6
108 #ifdef ALWAYS_USE_GUI
109 /* Can't do this when there is no terminal for input/output. */
110 if (!gui.in_use)
112 /* Break as soon as possible. */
113 debug_break_level = 9999;
114 return;
116 #endif
118 /* Make sure we are in raw mode and start termcap mode. Might have side
119 * effects... */
120 settmode(TMODE_RAW);
121 starttermcap();
123 ++RedrawingDisabled; /* don't redisplay the window */
124 ++no_wait_return; /* don't wait for return */
125 did_emsg = FALSE; /* don't use error from debugged stuff */
126 cmd_silent = FALSE; /* display commands */
127 msg_silent = FALSE; /* display messages */
128 emsg_silent = FALSE; /* display error messages */
129 redir_off = TRUE; /* don't redirect debug commands */
131 State = NORMAL;
132 #ifdef FEAT_SNIFF
133 want_sniff_request = 0; /* No K_SNIFF wanted */
134 #endif
136 if (!debug_did_msg)
137 MSG(_("Entering Debug mode. Type \"cont\" to continue."));
138 if (sourcing_name != NULL)
139 msg(sourcing_name);
140 if (sourcing_lnum != 0)
141 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd);
142 else
143 smsg((char_u *)_("cmd: %s"), cmd);
146 * Repeat getting a command and executing it.
148 for (;;)
150 msg_scroll = TRUE;
151 need_wait_return = FALSE;
152 #ifdef FEAT_SNIFF
153 ProcessSniffRequests();
154 #endif
155 /* Save the current typeahead buffer and replace it with an empty one.
156 * This makes sure we get input from the user here and don't interfere
157 * with the commands being executed. Reset "ex_normal_busy" to avoid
158 * the side effects of using ":normal". Save the stuff buffer and make
159 * it empty. Set ignore_script to avoid reading from script input. */
160 # ifdef FEAT_EX_EXTRA
161 save_ex_normal_busy = ex_normal_busy;
162 ex_normal_busy = 0;
163 # endif
164 if (!debug_greedy)
166 save_typeahead(&typeaheadbuf);
167 typeahead_saved = TRUE;
168 save_ignore_script = ignore_script;
169 ignore_script = TRUE;
172 cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
174 if (typeahead_saved)
176 restore_typeahead(&typeaheadbuf);
177 ignore_script = save_ignore_script;
179 # ifdef FEAT_EX_EXTRA
180 ex_normal_busy = save_ex_normal_busy;
181 # endif
183 cmdline_row = msg_row;
184 if (cmdline != NULL)
186 /* If this is a debug command, set "last_cmd".
187 * If not, reset "last_cmd".
188 * For a blank line use previous command. */
189 p = skipwhite(cmdline);
190 if (*p != NUL)
192 switch (*p)
194 case 'c': last_cmd = CMD_CONT;
195 tail = "ont";
196 break;
197 case 'n': last_cmd = CMD_NEXT;
198 tail = "ext";
199 break;
200 case 's': last_cmd = CMD_STEP;
201 tail = "tep";
202 break;
203 case 'f': last_cmd = CMD_FINISH;
204 tail = "inish";
205 break;
206 case 'q': last_cmd = CMD_QUIT;
207 tail = "uit";
208 break;
209 case 'i': last_cmd = CMD_INTERRUPT;
210 tail = "nterrupt";
211 break;
212 default: last_cmd = 0;
214 if (last_cmd != 0)
216 /* Check that the tail matches. */
217 ++p;
218 while (*p != NUL && *p == *tail)
220 ++p;
221 ++tail;
223 if (ASCII_ISALPHA(*p))
224 last_cmd = 0;
228 if (last_cmd != 0)
230 /* Execute debug command: decided where to break next and
231 * return. */
232 switch (last_cmd)
234 case CMD_CONT:
235 debug_break_level = -1;
236 break;
237 case CMD_NEXT:
238 debug_break_level = ex_nesting_level;
239 break;
240 case CMD_STEP:
241 debug_break_level = 9999;
242 break;
243 case CMD_FINISH:
244 debug_break_level = ex_nesting_level - 1;
245 break;
246 case CMD_QUIT:
247 got_int = TRUE;
248 debug_break_level = -1;
249 break;
250 case CMD_INTERRUPT:
251 got_int = TRUE;
252 debug_break_level = 9999;
253 /* Do not repeat ">interrupt" cmd, continue stepping. */
254 last_cmd = CMD_STEP;
255 break;
257 break;
260 /* don't debug this command */
261 n = debug_break_level;
262 debug_break_level = -1;
263 (void)do_cmdline(cmdline, getexline, NULL,
264 DOCMD_VERBOSE|DOCMD_EXCRESET);
265 debug_break_level = n;
267 vim_free(cmdline);
269 lines_left = Rows - 1;
271 vim_free(cmdline);
273 --RedrawingDisabled;
274 --no_wait_return;
275 redraw_all_later(NOT_VALID);
276 need_wait_return = FALSE;
277 msg_scroll = save_msg_scroll;
278 lines_left = Rows - 1;
279 State = save_State;
280 did_emsg = save_did_emsg;
281 cmd_silent = save_cmd_silent;
282 msg_silent = save_msg_silent;
283 emsg_silent = save_emsg_silent;
284 redir_off = save_redir_off;
286 /* Only print the message again when typing a command before coming back
287 * here. */
288 debug_did_msg = TRUE;
292 * ":debug".
294 void
295 ex_debug(eap)
296 exarg_T *eap;
298 int debug_break_level_save = debug_break_level;
300 debug_break_level = 9999;
301 do_cmdline_cmd(eap->arg);
302 debug_break_level = debug_break_level_save;
305 static char_u *debug_breakpoint_name = NULL;
306 static linenr_T debug_breakpoint_lnum;
309 * When debugging or a breakpoint is set on a skipped command, no debug prompt
310 * is shown by do_one_cmd(). This situation is indicated by debug_skipped, and
311 * debug_skipped_name is then set to the source name in the breakpoint case. If
312 * a skipped command decides itself that a debug prompt should be displayed, it
313 * can do so by calling dbg_check_skipped().
315 static int debug_skipped;
316 static char_u *debug_skipped_name;
319 * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
320 * at or below the break level. But only when the line is actually
321 * executed. Return TRUE and set breakpoint_name for skipped commands that
322 * decide to execute something themselves.
323 * Called from do_one_cmd() before executing a command.
325 void
326 dbg_check_breakpoint(eap)
327 exarg_T *eap;
329 char_u *p;
331 debug_skipped = FALSE;
332 if (debug_breakpoint_name != NULL)
334 if (!eap->skip)
336 /* replace K_SNR with "<SNR>" */
337 if (debug_breakpoint_name[0] == K_SPECIAL
338 && debug_breakpoint_name[1] == KS_EXTRA
339 && debug_breakpoint_name[2] == (int)KE_SNR)
340 p = (char_u *)"<SNR>";
341 else
342 p = (char_u *)"";
343 smsg((char_u *)_("Breakpoint in \"%s%s\" line %ld"),
345 debug_breakpoint_name + (*p == NUL ? 0 : 3),
346 (long)debug_breakpoint_lnum);
347 debug_breakpoint_name = NULL;
348 do_debug(eap->cmd);
350 else
352 debug_skipped = TRUE;
353 debug_skipped_name = debug_breakpoint_name;
354 debug_breakpoint_name = NULL;
357 else if (ex_nesting_level <= debug_break_level)
359 if (!eap->skip)
360 do_debug(eap->cmd);
361 else
363 debug_skipped = TRUE;
364 debug_skipped_name = NULL;
370 * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was
371 * set. Return TRUE when the debug mode is entered this time.
374 dbg_check_skipped(eap)
375 exarg_T *eap;
377 int prev_got_int;
379 if (debug_skipped)
382 * Save the value of got_int and reset it. We don't want a previous
383 * interruption cause flushing the input buffer.
385 prev_got_int = got_int;
386 got_int = FALSE;
387 debug_breakpoint_name = debug_skipped_name;
388 /* eap->skip is TRUE */
389 eap->skip = FALSE;
390 (void)dbg_check_breakpoint(eap);
391 eap->skip = TRUE;
392 got_int |= prev_got_int;
393 return TRUE;
395 return FALSE;
399 * The list of breakpoints: dbg_breakp.
400 * This is a grow-array of structs.
402 struct debuggy
404 int dbg_nr; /* breakpoint number */
405 int dbg_type; /* DBG_FUNC or DBG_FILE */
406 char_u *dbg_name; /* function or file name */
407 regprog_T *dbg_prog; /* regexp program */
408 linenr_T dbg_lnum; /* line number in function or file */
409 int dbg_forceit; /* ! used */
412 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
413 #define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx])
414 #define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx])
415 static int last_breakp = 0; /* nr of last defined breakpoint */
417 #ifdef FEAT_PROFILE
418 /* Profiling uses file and func names similar to breakpoints. */
419 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL};
420 #endif
421 #define DBG_FUNC 1
422 #define DBG_FILE 2
424 static int dbg_parsearg __ARGS((char_u *arg, garray_T *gap));
425 static linenr_T debuggy_find __ARGS((int file,char_u *fname, linenr_T after, garray_T *gap, int *fp));
428 * Parse the arguments of ":profile", ":breakadd" or ":breakdel" and put them
429 * in the entry just after the last one in dbg_breakp. Note that "dbg_name"
430 * is allocated.
431 * Returns FAIL for failure.
433 static int
434 dbg_parsearg(arg, gap)
435 char_u *arg;
436 garray_T *gap; /* either &dbg_breakp or &prof_ga */
438 char_u *p = arg;
439 char_u *q;
440 struct debuggy *bp;
441 int here = FALSE;
443 if (ga_grow(gap, 1) == FAIL)
444 return FAIL;
445 bp = &DEBUGGY(gap, gap->ga_len);
447 /* Find "func" or "file". */
448 if (STRNCMP(p, "func", 4) == 0)
449 bp->dbg_type = DBG_FUNC;
450 else if (STRNCMP(p, "file", 4) == 0)
451 bp->dbg_type = DBG_FILE;
452 else if (
453 #ifdef FEAT_PROFILE
454 gap != &prof_ga &&
455 #endif
456 STRNCMP(p, "here", 4) == 0)
458 if (curbuf->b_ffname == NULL)
460 EMSG(_(e_noname));
461 return FAIL;
463 bp->dbg_type = DBG_FILE;
464 here = TRUE;
466 else
468 EMSG2(_(e_invarg2), p);
469 return FAIL;
471 p = skipwhite(p + 4);
473 /* Find optional line number. */
474 if (here)
475 bp->dbg_lnum = curwin->w_cursor.lnum;
476 else if (
477 #ifdef FEAT_PROFILE
478 gap != &prof_ga &&
479 #endif
480 VIM_ISDIGIT(*p))
482 bp->dbg_lnum = getdigits(&p);
483 p = skipwhite(p);
485 else
486 bp->dbg_lnum = 0;
488 /* Find the function or file name. Don't accept a function name with (). */
489 if ((!here && *p == NUL)
490 || (here && *p != NUL)
491 || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL))
493 EMSG2(_(e_invarg2), arg);
494 return FAIL;
497 if (bp->dbg_type == DBG_FUNC)
498 bp->dbg_name = vim_strsave(p);
499 else if (here)
500 bp->dbg_name = vim_strsave(curbuf->b_ffname);
501 else
503 /* Expand the file name in the same way as do_source(). This means
504 * doing it twice, so that $DIR/file gets expanded when $DIR is
505 * "~/dir". */
506 #ifdef RISCOS
507 q = mch_munge_fname(p);
508 #else
509 q = expand_env_save(p);
510 #endif
511 if (q == NULL)
512 return FAIL;
513 #ifdef RISCOS
514 p = mch_munge_fname(q);
515 #else
516 p = expand_env_save(q);
517 #endif
518 vim_free(q);
519 if (p == NULL)
520 return FAIL;
521 if (*p != '*')
523 bp->dbg_name = fix_fname(p);
524 vim_free(p);
526 else
527 bp->dbg_name = p;
530 if (bp->dbg_name == NULL)
531 return FAIL;
532 return OK;
536 * ":breakadd".
538 void
539 ex_breakadd(eap)
540 exarg_T *eap;
542 struct debuggy *bp;
543 char_u *pat;
544 garray_T *gap;
546 gap = &dbg_breakp;
547 #ifdef FEAT_PROFILE
548 if (eap->cmdidx == CMD_profile)
549 gap = &prof_ga;
550 #endif
552 if (dbg_parsearg(eap->arg, gap) == OK)
554 bp = &DEBUGGY(gap, gap->ga_len);
555 bp->dbg_forceit = eap->forceit;
557 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE);
558 if (pat != NULL)
560 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
561 vim_free(pat);
563 if (pat == NULL || bp->dbg_prog == NULL)
564 vim_free(bp->dbg_name);
565 else
567 if (bp->dbg_lnum == 0) /* default line number is 1 */
568 bp->dbg_lnum = 1;
569 #ifdef FEAT_PROFILE
570 if (eap->cmdidx != CMD_profile)
571 #endif
573 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp;
574 ++debug_tick;
576 ++gap->ga_len;
582 * ":debuggreedy".
584 void
585 ex_debuggreedy(eap)
586 exarg_T *eap;
588 if (eap->addr_count == 0 || eap->line2 != 0)
589 debug_greedy = TRUE;
590 else
591 debug_greedy = FALSE;
595 * ":breakdel" and ":profdel".
597 void
598 ex_breakdel(eap)
599 exarg_T *eap;
601 struct debuggy *bp, *bpi;
602 int nr;
603 int todel = -1;
604 int del_all = FALSE;
605 int i;
606 linenr_T best_lnum = 0;
607 garray_T *gap;
609 gap = &dbg_breakp;
610 #ifdef FEAT_PROFILE
611 if (eap->cmdidx == CMD_profdel)
612 gap = &prof_ga;
613 #endif
615 if (vim_isdigit(*eap->arg))
617 /* ":breakdel {nr}" */
618 nr = atol((char *)eap->arg);
619 for (i = 0; i < gap->ga_len; ++i)
620 if (DEBUGGY(gap, i).dbg_nr == nr)
622 todel = i;
623 break;
626 else if (*eap->arg == '*')
628 todel = 0;
629 del_all = TRUE;
631 else
633 /* ":breakdel {func|file} [lnum] {name}" */
634 if (dbg_parsearg(eap->arg, gap) == FAIL)
635 return;
636 bp = &DEBUGGY(gap, gap->ga_len);
637 for (i = 0; i < gap->ga_len; ++i)
639 bpi = &DEBUGGY(gap, i);
640 if (bp->dbg_type == bpi->dbg_type
641 && STRCMP(bp->dbg_name, bpi->dbg_name) == 0
642 && (bp->dbg_lnum == bpi->dbg_lnum
643 || (bp->dbg_lnum == 0
644 && (best_lnum == 0
645 || bpi->dbg_lnum < best_lnum))))
647 todel = i;
648 best_lnum = bpi->dbg_lnum;
651 vim_free(bp->dbg_name);
654 if (todel < 0)
655 EMSG2(_("E161: Breakpoint not found: %s"), eap->arg);
656 else
658 while (gap->ga_len > 0)
660 vim_free(DEBUGGY(gap, todel).dbg_name);
661 vim_free(DEBUGGY(gap, todel).dbg_prog);
662 --gap->ga_len;
663 if (todel < gap->ga_len)
664 mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1),
665 (gap->ga_len - todel) * sizeof(struct debuggy));
666 #ifdef FEAT_PROFILE
667 if (eap->cmdidx == CMD_breakdel)
668 #endif
669 ++debug_tick;
670 if (!del_all)
671 break;
674 /* If all breakpoints were removed clear the array. */
675 if (gap->ga_len == 0)
676 ga_clear(gap);
681 * ":breaklist".
683 /*ARGSUSED*/
684 void
685 ex_breaklist(eap)
686 exarg_T *eap;
688 struct debuggy *bp;
689 int i;
691 if (dbg_breakp.ga_len == 0)
692 MSG(_("No breakpoints defined"));
693 else
694 for (i = 0; i < dbg_breakp.ga_len; ++i)
696 bp = &BREAKP(i);
697 smsg((char_u *)_("%3d %s %s line %ld"),
698 bp->dbg_nr,
699 bp->dbg_type == DBG_FUNC ? "func" : "file",
700 bp->dbg_name,
701 (long)bp->dbg_lnum);
706 * Find a breakpoint for a function or sourced file.
707 * Returns line number at which to break; zero when no matching breakpoint.
709 linenr_T
710 dbg_find_breakpoint(file, fname, after)
711 int file; /* TRUE for a file, FALSE for a function */
712 char_u *fname; /* file or function name */
713 linenr_T after; /* after this line number */
715 return debuggy_find(file, fname, after, &dbg_breakp, NULL);
718 #if defined(FEAT_PROFILE) || defined(PROTO)
720 * Return TRUE if profiling is on for a function or sourced file.
723 has_profiling(file, fname, fp)
724 int file; /* TRUE for a file, FALSE for a function */
725 char_u *fname; /* file or function name */
726 int *fp; /* return: forceit */
728 return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
729 != (linenr_T)0);
731 #endif
734 * Common code for dbg_find_breakpoint() and has_profiling().
736 static linenr_T
737 debuggy_find(file, fname, after, gap, fp)
738 int file; /* TRUE for a file, FALSE for a function */
739 char_u *fname; /* file or function name */
740 linenr_T after; /* after this line number */
741 garray_T *gap; /* either &dbg_breakp or &prof_ga */
742 int *fp; /* if not NULL: return forceit */
744 struct debuggy *bp;
745 int i;
746 linenr_T lnum = 0;
747 regmatch_T regmatch;
748 char_u *name = fname;
749 int prev_got_int;
751 /* Return quickly when there are no breakpoints. */
752 if (gap->ga_len == 0)
753 return (linenr_T)0;
755 /* Replace K_SNR in function name with "<SNR>". */
756 if (!file && fname[0] == K_SPECIAL)
758 name = alloc((unsigned)STRLEN(fname) + 3);
759 if (name == NULL)
760 name = fname;
761 else
763 STRCPY(name, "<SNR>");
764 STRCPY(name + 5, fname + 3);
768 for (i = 0; i < gap->ga_len; ++i)
770 /* Skip entries that are not useful or are for a line that is beyond
771 * an already found breakpoint. */
772 bp = &DEBUGGY(gap, i);
773 if (((bp->dbg_type == DBG_FILE) == file && (
774 #ifdef FEAT_PROFILE
775 gap == &prof_ga ||
776 #endif
777 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum)))))
779 regmatch.regprog = bp->dbg_prog;
780 regmatch.rm_ic = FALSE;
782 * Save the value of got_int and reset it. We don't want a
783 * previous interruption cancel matching, only hitting CTRL-C
784 * while matching should abort it.
786 prev_got_int = got_int;
787 got_int = FALSE;
788 if (vim_regexec(&regmatch, name, (colnr_T)0))
790 lnum = bp->dbg_lnum;
791 if (fp != NULL)
792 *fp = bp->dbg_forceit;
794 got_int |= prev_got_int;
797 if (name != fname)
798 vim_free(name);
800 return lnum;
804 * Called when a breakpoint was encountered.
806 void
807 dbg_breakpoint(name, lnum)
808 char_u *name;
809 linenr_T lnum;
811 /* We need to check if this line is actually executed in do_one_cmd() */
812 debug_breakpoint_name = name;
813 debug_breakpoint_lnum = lnum;
817 # if defined(FEAT_PROFILE) || defined(FEAT_RELTIME) || defined(PROTO)
819 * Store the current time in "tm".
821 void
822 profile_start(tm)
823 proftime_T *tm;
825 # ifdef WIN3264
826 QueryPerformanceCounter(tm);
827 # else
828 gettimeofday(tm, NULL);
829 # endif
833 * Compute the elapsed time from "tm" till now and store in "tm".
835 void
836 profile_end(tm)
837 proftime_T *tm;
839 proftime_T now;
841 # ifdef WIN3264
842 QueryPerformanceCounter(&now);
843 tm->QuadPart = now.QuadPart - tm->QuadPart;
844 # else
845 gettimeofday(&now, NULL);
846 tm->tv_usec = now.tv_usec - tm->tv_usec;
847 tm->tv_sec = now.tv_sec - tm->tv_sec;
848 if (tm->tv_usec < 0)
850 tm->tv_usec += 1000000;
851 --tm->tv_sec;
853 # endif
857 * Subtract the time "tm2" from "tm".
859 void
860 profile_sub(tm, tm2)
861 proftime_T *tm, *tm2;
863 # ifdef WIN3264
864 tm->QuadPart -= tm2->QuadPart;
865 # else
866 tm->tv_usec -= tm2->tv_usec;
867 tm->tv_sec -= tm2->tv_sec;
868 if (tm->tv_usec < 0)
870 tm->tv_usec += 1000000;
871 --tm->tv_sec;
873 # endif
877 * Return a string that represents the time in "tm".
878 * Uses a static buffer!
880 char *
881 profile_msg(tm)
882 proftime_T *tm;
884 static char buf[50];
886 # ifdef WIN3264
887 LARGE_INTEGER fr;
889 QueryPerformanceFrequency(&fr);
890 sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart);
891 # else
892 sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec);
893 # endif
894 return buf;
898 * Put the time "msec" past now in "tm".
900 void
901 profile_setlimit(msec, tm)
902 long msec;
903 proftime_T *tm;
905 if (msec <= 0) /* no limit */
906 profile_zero(tm);
907 else
909 # ifdef WIN3264
910 LARGE_INTEGER fr;
912 QueryPerformanceCounter(tm);
913 QueryPerformanceFrequency(&fr);
914 tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
915 # else
916 long usec;
918 gettimeofday(tm, NULL);
919 usec = (long)tm->tv_usec + (long)msec * 1000;
920 tm->tv_usec = usec % 1000000L;
921 tm->tv_sec += usec / 1000000L;
922 # endif
927 * Return TRUE if the current time is past "tm".
930 profile_passed_limit(tm)
931 proftime_T *tm;
933 proftime_T now;
935 # ifdef WIN3264
936 if (tm->QuadPart == 0) /* timer was not set */
937 return FALSE;
938 QueryPerformanceCounter(&now);
939 return (now.QuadPart > tm->QuadPart);
940 # else
941 if (tm->tv_sec == 0) /* timer was not set */
942 return FALSE;
943 gettimeofday(&now, NULL);
944 return (now.tv_sec > tm->tv_sec
945 || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec));
946 # endif
950 * Set the time in "tm" to zero.
952 void
953 profile_zero(tm)
954 proftime_T *tm;
956 # ifdef WIN3264
957 tm->QuadPart = 0;
958 # else
959 tm->tv_usec = 0;
960 tm->tv_sec = 0;
961 # endif
964 # endif /* FEAT_PROFILE || FEAT_RELTIME */
966 # if defined(FEAT_PROFILE) || defined(PROTO)
968 * Functions for profiling.
970 static void script_do_profile __ARGS((scriptitem_T *si));
971 static void script_dump_profile __ARGS((FILE *fd));
972 static proftime_T prof_wait_time;
975 * Add the time "tm2" to "tm".
977 void
978 profile_add(tm, tm2)
979 proftime_T *tm, *tm2;
981 # ifdef WIN3264
982 tm->QuadPart += tm2->QuadPart;
983 # else
984 tm->tv_usec += tm2->tv_usec;
985 tm->tv_sec += tm2->tv_sec;
986 if (tm->tv_usec >= 1000000)
988 tm->tv_usec -= 1000000;
989 ++tm->tv_sec;
991 # endif
995 * Add the "self" time from the total time and the children's time.
997 void
998 profile_self(self, total, children)
999 proftime_T *self, *total, *children;
1001 /* Check that the result won't be negative. Can happen with recursive
1002 * calls. */
1003 #ifdef WIN3264
1004 if (total->QuadPart <= children->QuadPart)
1005 return;
1006 #else
1007 if (total->tv_sec < children->tv_sec
1008 || (total->tv_sec == children->tv_sec
1009 && total->tv_usec <= children->tv_usec))
1010 return;
1011 #endif
1012 profile_add(self, total);
1013 profile_sub(self, children);
1017 * Get the current waittime.
1019 void
1020 profile_get_wait(tm)
1021 proftime_T *tm;
1023 *tm = prof_wait_time;
1027 * Subtract the passed waittime since "tm" from "tma".
1029 void
1030 profile_sub_wait(tm, tma)
1031 proftime_T *tm, *tma;
1033 proftime_T tm3 = prof_wait_time;
1035 profile_sub(&tm3, tm);
1036 profile_sub(tma, &tm3);
1040 * Return TRUE if "tm1" and "tm2" are equal.
1043 profile_equal(tm1, tm2)
1044 proftime_T *tm1, *tm2;
1046 # ifdef WIN3264
1047 return (tm1->QuadPart == tm2->QuadPart);
1048 # else
1049 return (tm1->tv_usec == tm2->tv_usec && tm1->tv_sec == tm2->tv_sec);
1050 # endif
1054 * Return <0, 0 or >0 if "tm1" < "tm2", "tm1" == "tm2" or "tm1" > "tm2"
1057 profile_cmp(tm1, tm2)
1058 proftime_T *tm1, *tm2;
1060 # ifdef WIN3264
1061 return (int)(tm2->QuadPart - tm1->QuadPart);
1062 # else
1063 if (tm1->tv_sec == tm2->tv_sec)
1064 return tm2->tv_usec - tm1->tv_usec;
1065 return tm2->tv_sec - tm1->tv_sec;
1066 # endif
1069 static char_u *profile_fname = NULL;
1070 static proftime_T pause_time;
1073 * ":profile cmd args"
1075 void
1076 ex_profile(eap)
1077 exarg_T *eap;
1079 char_u *e;
1080 int len;
1082 e = skiptowhite(eap->arg);
1083 len = (int)(e - eap->arg);
1084 e = skipwhite(e);
1086 if (len == 5 && STRNCMP(eap->arg, "start", 5) == 0 && *e != NUL)
1088 vim_free(profile_fname);
1089 profile_fname = vim_strsave(e);
1090 do_profiling = PROF_YES;
1091 profile_zero(&prof_wait_time);
1092 set_vim_var_nr(VV_PROFILING, 1L);
1094 else if (do_profiling == PROF_NONE)
1095 EMSG(_("E750: First use :profile start <fname>"));
1096 else if (STRCMP(eap->arg, "pause") == 0)
1098 if (do_profiling == PROF_YES)
1099 profile_start(&pause_time);
1100 do_profiling = PROF_PAUSED;
1102 else if (STRCMP(eap->arg, "continue") == 0)
1104 if (do_profiling == PROF_PAUSED)
1106 profile_end(&pause_time);
1107 profile_add(&prof_wait_time, &pause_time);
1109 do_profiling = PROF_YES;
1111 else
1113 /* The rest is similar to ":breakadd". */
1114 ex_breakadd(eap);
1119 * Dump the profiling info.
1121 void
1122 profile_dump()
1124 FILE *fd;
1126 if (profile_fname != NULL)
1128 fd = mch_fopen((char *)profile_fname, "w");
1129 if (fd == NULL)
1130 EMSG2(_(e_notopen), profile_fname);
1131 else
1133 script_dump_profile(fd);
1134 func_dump_profile(fd);
1135 fclose(fd);
1141 * Start profiling script "fp".
1143 static void
1144 script_do_profile(si)
1145 scriptitem_T *si;
1147 si->sn_pr_count = 0;
1148 profile_zero(&si->sn_pr_total);
1149 profile_zero(&si->sn_pr_self);
1151 ga_init2(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
1152 si->sn_prl_idx = -1;
1153 si->sn_prof_on = TRUE;
1154 si->sn_pr_nest = 0;
1158 * save time when starting to invoke another script or function.
1160 void
1161 script_prof_save(tm)
1162 proftime_T *tm; /* place to store wait time */
1164 scriptitem_T *si;
1166 if (current_SID > 0 && current_SID <= script_items.ga_len)
1168 si = &SCRIPT_ITEM(current_SID);
1169 if (si->sn_prof_on && si->sn_pr_nest++ == 0)
1170 profile_start(&si->sn_pr_child);
1172 profile_get_wait(tm);
1176 * Count time spent in children after invoking another script or function.
1178 void
1179 script_prof_restore(tm)
1180 proftime_T *tm;
1182 scriptitem_T *si;
1184 if (current_SID > 0 && current_SID <= script_items.ga_len)
1186 si = &SCRIPT_ITEM(current_SID);
1187 if (si->sn_prof_on && --si->sn_pr_nest == 0)
1189 profile_end(&si->sn_pr_child);
1190 profile_sub_wait(tm, &si->sn_pr_child); /* don't count wait time */
1191 profile_add(&si->sn_pr_children, &si->sn_pr_child);
1192 profile_add(&si->sn_prl_children, &si->sn_pr_child);
1197 static proftime_T inchar_time;
1200 * Called when starting to wait for the user to type a character.
1202 void
1203 prof_inchar_enter()
1205 profile_start(&inchar_time);
1209 * Called when finished waiting for the user to type a character.
1211 void
1212 prof_inchar_exit()
1214 profile_end(&inchar_time);
1215 profile_add(&prof_wait_time, &inchar_time);
1219 * Dump the profiling results for all scripts in file "fd".
1221 static void
1222 script_dump_profile(fd)
1223 FILE *fd;
1225 int id;
1226 scriptitem_T *si;
1227 int i;
1228 FILE *sfd;
1229 sn_prl_T *pp;
1231 for (id = 1; id <= script_items.ga_len; ++id)
1233 si = &SCRIPT_ITEM(id);
1234 if (si->sn_prof_on)
1236 fprintf(fd, "SCRIPT %s\n", si->sn_name);
1237 if (si->sn_pr_count == 1)
1238 fprintf(fd, "Sourced 1 time\n");
1239 else
1240 fprintf(fd, "Sourced %d times\n", si->sn_pr_count);
1241 fprintf(fd, "Total time: %s\n", profile_msg(&si->sn_pr_total));
1242 fprintf(fd, " Self time: %s\n", profile_msg(&si->sn_pr_self));
1243 fprintf(fd, "\n");
1244 fprintf(fd, "count total (s) self (s)\n");
1246 sfd = mch_fopen((char *)si->sn_name, "r");
1247 if (sfd == NULL)
1248 fprintf(fd, "Cannot open file!\n");
1249 else
1251 for (i = 0; i < si->sn_prl_ga.ga_len; ++i)
1253 if (vim_fgets(IObuff, IOSIZE, sfd))
1254 break;
1255 pp = &PRL_ITEM(si, i);
1256 if (pp->snp_count > 0)
1258 fprintf(fd, "%5d ", pp->snp_count);
1259 if (profile_equal(&pp->sn_prl_total, &pp->sn_prl_self))
1260 fprintf(fd, " ");
1261 else
1262 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_total));
1263 fprintf(fd, "%s ", profile_msg(&pp->sn_prl_self));
1265 else
1266 fprintf(fd, " ");
1267 fprintf(fd, "%s", IObuff);
1269 fclose(sfd);
1271 fprintf(fd, "\n");
1277 * Return TRUE when a function defined in the current script should be
1278 * profiled.
1281 prof_def_func()
1283 if (current_SID > 0)
1284 return SCRIPT_ITEM(current_SID).sn_pr_force;
1285 return FALSE;
1288 # endif
1289 #endif
1292 * If 'autowrite' option set, try to write the file.
1293 * Careful: autocommands may make "buf" invalid!
1295 * return FAIL for failure, OK otherwise
1298 autowrite(buf, forceit)
1299 buf_T *buf;
1300 int forceit;
1302 int r;
1304 if (!(p_aw || p_awa) || !p_write
1305 #ifdef FEAT_QUICKFIX
1306 /* never autowrite a "nofile" or "nowrite" buffer */
1307 || bt_dontwrite(buf)
1308 #endif
1309 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
1310 return FAIL;
1311 r = buf_write_all(buf, forceit);
1313 /* Writing may succeed but the buffer still changed, e.g., when there is a
1314 * conversion error. We do want to return FAIL then. */
1315 if (buf_valid(buf) && bufIsChanged(buf))
1316 r = FAIL;
1317 return r;
1321 * flush all buffers, except the ones that are readonly
1323 void
1324 autowrite_all()
1326 buf_T *buf;
1328 if (!(p_aw || p_awa) || !p_write)
1329 return;
1330 for (buf = firstbuf; buf; buf = buf->b_next)
1331 if (bufIsChanged(buf) && !buf->b_p_ro)
1333 (void)buf_write_all(buf, FALSE);
1334 #ifdef FEAT_AUTOCMD
1335 /* an autocommand may have deleted the buffer */
1336 if (!buf_valid(buf))
1337 buf = firstbuf;
1338 #endif
1343 * return TRUE if buffer was changed and cannot be abandoned.
1345 /*ARGSUSED*/
1347 check_changed(buf, checkaw, mult_win, forceit, allbuf)
1348 buf_T *buf;
1349 int checkaw; /* do autowrite if buffer was changed */
1350 int mult_win; /* check also when several wins for the buf */
1351 int forceit;
1352 int allbuf; /* may write all buffers */
1354 if ( !forceit
1355 && bufIsChanged(buf)
1356 && (mult_win || buf->b_nwindows <= 1)
1357 && (!checkaw || autowrite(buf, forceit) == FAIL))
1359 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1360 if ((p_confirm || cmdmod.confirm) && p_write)
1362 buf_T *buf2;
1363 int count = 0;
1365 if (allbuf)
1366 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1367 if (bufIsChanged(buf2)
1368 && (buf2->b_ffname != NULL
1369 # ifdef FEAT_BROWSE
1370 || cmdmod.browse
1371 # endif
1373 ++count;
1374 # ifdef FEAT_AUTOCMD
1375 if (!buf_valid(buf))
1376 /* Autocommand deleted buffer, oops! It's not changed now. */
1377 return FALSE;
1378 # endif
1379 dialog_changed(buf, count > 1);
1380 # ifdef FEAT_AUTOCMD
1381 if (!buf_valid(buf))
1382 /* Autocommand deleted buffer, oops! It's not changed now. */
1383 return FALSE;
1384 # endif
1385 return bufIsChanged(buf);
1387 #endif
1388 EMSG(_(e_nowrtmsg));
1389 return TRUE;
1391 return FALSE;
1394 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
1396 #if defined(FEAT_BROWSE) || defined(PROTO)
1398 * When wanting to write a file without a file name, ask the user for a name.
1400 void
1401 browse_save_fname(buf)
1402 buf_T *buf;
1404 if (buf->b_fname == NULL)
1406 char_u *fname;
1408 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"),
1409 NULL, NULL, NULL, NULL, buf);
1410 if (fname != NULL)
1412 if (setfname(buf, fname, NULL, TRUE) == OK)
1413 buf->b_flags |= BF_NOTEDITED;
1414 vim_free(fname);
1418 #endif
1420 #ifdef FEAT_GUI_MACVIM
1422 * "Save changes" dialog that conforms to the Apple HIG.
1425 vim_dialog_save_changes(buf)
1426 buf_T *buf;
1428 char_u buff[IOSIZE];
1430 dialog_msg(buff, _("Do you want to save the changes you made in the "
1431 "document \"%s\"?"), buf->b_fname);
1432 switch (do_dialog(VIM_QUESTION, buff,
1433 (char_u*) _("Your changes will be lost if you don't save "
1434 "them."),
1435 (buf->b_fname != NULL)
1436 ? (char_u *)_("&Save\n&Cancel\n&Don't Save")
1437 : (char_u *)_("&Save...\n&Cancel\n&Don't Save"),
1438 1, NULL))
1440 case 1: return VIM_YES;
1441 case 3: return VIM_NO;
1444 return VIM_CANCEL;
1448 * "Save all changes" dialog that tries to emulate the above "Save changes"
1449 * dialog for the case of several modified buffers.
1452 vim_dialog_save_all_changes(buf)
1453 buf_T *buf;
1455 char_u buff[IOSIZE];
1457 dialog_msg(buff, _("There are several documents with unsaved changes. "
1458 "Do you want to save the changes you made in the "
1459 "document \"%s\"?"), buf->b_fname);
1460 switch (do_dialog(VIM_QUESTION, buff,
1461 (char_u*) _("Your changes will be lost if you don't save "
1462 "them."),
1463 (char_u *)_("&Save\n&Don't Save\nS&ave All\nD&iscard All\n"
1464 "&Cancel"),
1465 1, NULL))
1467 case 1: return VIM_YES;
1468 case 2: return VIM_NO;
1469 case 3: return VIM_ALL;
1470 case 4: return VIM_DISCARDALL;
1473 return VIM_CANCEL;
1475 #endif
1478 * Ask the user what to do when abondoning a changed buffer.
1479 * Must check 'write' option first!
1481 void
1482 dialog_changed(buf, checkall)
1483 buf_T *buf;
1484 int checkall; /* may abandon all changed buffers */
1486 char_u buff[IOSIZE];
1487 int ret;
1488 buf_T *buf2;
1490 #ifdef FEAT_GUI_MACVIM
1491 /* Save dialogs on Mac OS X are standardized so in case the GUI is enabled
1492 * and "c" isn't in 'guioptions' we use a OS X specific dialog. */
1493 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
1495 if (checkall)
1496 ret = vim_dialog_save_all_changes(buf);
1497 else
1498 ret = vim_dialog_save_changes(buf);
1500 else
1502 #endif
1503 dialog_msg(buff, _("Save changes to \"%s\"?"),
1504 (buf->b_fname != NULL) ?
1505 buf->b_fname : (char_u *)_("Untitled"));
1506 if (checkall)
1507 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
1508 else
1509 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
1510 #ifdef FEAT_GUI_MACVIM
1512 #endif
1514 if (ret == VIM_YES)
1516 #ifdef FEAT_BROWSE
1517 /* May get file name, when there is none */
1518 browse_save_fname(buf);
1519 #endif
1520 if (buf->b_fname != NULL) /* didn't hit Cancel */
1521 (void)buf_write_all(buf, FALSE);
1523 else if (ret == VIM_NO)
1525 unchanged(buf, TRUE);
1527 else if (ret == VIM_ALL)
1530 * Write all modified files that can be written.
1531 * Skip readonly buffers, these need to be confirmed
1532 * individually.
1534 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1536 if (bufIsChanged(buf2)
1537 && (buf2->b_ffname != NULL
1538 #ifdef FEAT_BROWSE
1539 || cmdmod.browse
1540 #endif
1542 && !buf2->b_p_ro)
1544 #ifdef FEAT_BROWSE
1545 /* May get file name, when there is none */
1546 browse_save_fname(buf2);
1547 #endif
1548 if (buf2->b_fname != NULL) /* didn't hit Cancel */
1549 (void)buf_write_all(buf2, FALSE);
1550 #ifdef FEAT_AUTOCMD
1551 /* an autocommand may have deleted the buffer */
1552 if (!buf_valid(buf2))
1553 buf2 = firstbuf;
1554 #endif
1558 else if (ret == VIM_DISCARDALL)
1561 * mark all buffers as unchanged
1563 for (buf2 = firstbuf; buf2 != NULL; buf2 = buf2->b_next)
1564 unchanged(buf2, TRUE);
1567 #endif
1570 * Return TRUE if the buffer "buf" can be abandoned, either by making it
1571 * hidden, autowriting it or unloading it.
1574 can_abandon(buf, forceit)
1575 buf_T *buf;
1576 int forceit;
1578 return ( P_HID(buf)
1579 || !bufIsChanged(buf)
1580 || buf->b_nwindows > 1
1581 || autowrite(buf, forceit) == OK
1582 || forceit);
1586 * Return TRUE if any buffer was changed and cannot be abandoned.
1587 * That changed buffer becomes the current buffer.
1590 check_changed_any(hidden)
1591 int hidden; /* Only check hidden buffers */
1593 buf_T *buf;
1594 int save;
1595 #ifdef FEAT_WINDOWS
1596 win_T *wp;
1597 #endif
1599 for (;;)
1601 /* check curbuf first: if it was changed we can't abandon it */
1602 if (!hidden && curbufIsChanged())
1603 buf = curbuf;
1604 else
1606 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1607 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf))
1608 break;
1610 if (buf == NULL) /* No buffers changed */
1611 return FALSE;
1613 /* Try auto-writing the buffer. If this fails but the buffer no
1614 * longer exists it's not changed, that's OK. */
1615 if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf))
1616 break; /* didn't save - still changes */
1619 exiting = FALSE;
1620 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1622 * When ":confirm" used, don't give an error message.
1624 if (!(p_confirm || cmdmod.confirm))
1625 #endif
1627 /* There must be a wait_return for this message, do_buffer()
1628 * may cause a redraw. But wait_return() is a no-op when vgetc()
1629 * is busy (Quit used from window menu), then make sure we don't
1630 * cause a scroll up. */
1631 if (vgetc_busy > 0)
1633 msg_row = cmdline_row;
1634 msg_col = 0;
1635 msg_didout = FALSE;
1637 if (EMSG2(_("E162: No write since last change for buffer \"%s\""),
1638 buf_spname(buf) != NULL ? (char_u *)buf_spname(buf) :
1639 buf->b_fname))
1641 save = no_wait_return;
1642 no_wait_return = FALSE;
1643 wait_return(FALSE);
1644 no_wait_return = save;
1648 #ifdef FEAT_WINDOWS
1649 /* Try to find a window that contains the buffer. */
1650 if (buf != curbuf)
1651 for (wp = firstwin; wp != NULL; wp = wp->w_next)
1652 if (wp->w_buffer == buf)
1654 win_goto(wp);
1655 # ifdef FEAT_AUTOCMD
1656 /* Paranoia: did autocms wipe out the buffer with changes? */
1657 if (!buf_valid(buf))
1658 return TRUE;
1659 # endif
1660 break;
1662 #endif
1664 /* Open the changed buffer in the current window. */
1665 if (buf != curbuf)
1666 set_curbuf(buf, DOBUF_GOTO);
1668 return TRUE;
1672 * return FAIL if there is no file name, OK if there is one
1673 * give error message for FAIL
1676 check_fname()
1678 if (curbuf->b_ffname == NULL)
1680 EMSG(_(e_noname));
1681 return FAIL;
1683 return OK;
1687 * flush the contents of a buffer, unless it has no file name
1689 * return FAIL for failure, OK otherwise
1692 buf_write_all(buf, forceit)
1693 buf_T *buf;
1694 int forceit;
1696 int retval;
1697 #ifdef FEAT_AUTOCMD
1698 buf_T *old_curbuf = curbuf;
1699 #endif
1701 retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
1702 (linenr_T)1, buf->b_ml.ml_line_count, NULL,
1703 FALSE, forceit, TRUE, FALSE));
1704 #ifdef FEAT_AUTOCMD
1705 if (curbuf != old_curbuf)
1707 msg_source(hl_attr(HLF_W));
1708 MSG(_("Warning: Entered other buffer unexpectedly (check autocommands)"));
1710 #endif
1711 return retval;
1715 * Code to handle the argument list.
1718 static char_u *do_one_arg __ARGS((char_u *str));
1719 static int do_arglist __ARGS((char_u *str, int what, int after));
1720 static void alist_check_arg_idx __ARGS((void));
1721 static int editing_arg_idx __ARGS((win_T *win));
1722 #ifdef FEAT_LISTCMDS
1723 static int alist_add_list __ARGS((int count, char_u **files, int after));
1724 #endif
1725 #define AL_SET 1
1726 #define AL_ADD 2
1727 #define AL_DEL 3
1730 * Isolate one argument, taking backticks.
1731 * Changes the argument in-place, puts a NUL after it. Backticks remain.
1732 * Return a pointer to the start of the next argument.
1734 static char_u *
1735 do_one_arg(str)
1736 char_u *str;
1738 char_u *p;
1739 int inbacktick;
1741 inbacktick = FALSE;
1742 for (p = str; *str; ++str)
1744 /* When the backslash is used for escaping the special meaning of a
1745 * character we need to keep it until wildcard expansion. */
1746 if (rem_backslash(str))
1748 *p++ = *str++;
1749 *p++ = *str;
1751 else
1753 /* An item ends at a space not in backticks */
1754 if (!inbacktick && vim_isspace(*str))
1755 break;
1756 if (*str == '`')
1757 inbacktick ^= TRUE;
1758 *p++ = *str;
1761 str = skipwhite(str);
1762 *p = NUL;
1764 return str;
1768 * Separate the arguments in "str" and return a list of pointers in the
1769 * growarray "gap".
1772 get_arglist(gap, str)
1773 garray_T *gap;
1774 char_u *str;
1776 ga_init2(gap, (int)sizeof(char_u *), 20);
1777 while (*str != NUL)
1779 if (ga_grow(gap, 1) == FAIL)
1781 ga_clear(gap);
1782 return FAIL;
1784 ((char_u **)gap->ga_data)[gap->ga_len++] = str;
1786 /* Isolate one argument, change it in-place, put a NUL after it. */
1787 str = do_one_arg(str);
1789 return OK;
1792 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO)
1794 * Parse a list of arguments (file names), expand them and return in
1795 * "fnames[fcountp]".
1796 * Return FAIL or OK.
1799 get_arglist_exp(str, fcountp, fnamesp)
1800 char_u *str;
1801 int *fcountp;
1802 char_u ***fnamesp;
1804 garray_T ga;
1805 int i;
1807 if (get_arglist(&ga, str) == FAIL)
1808 return FAIL;
1809 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
1810 fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
1811 ga_clear(&ga);
1812 return i;
1814 #endif
1816 #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
1818 * Redefine the argument list.
1820 void
1821 set_arglist(str)
1822 char_u *str;
1824 do_arglist(str, AL_SET, 0);
1826 #endif
1829 * "what" == AL_SET: Redefine the argument list to 'str'.
1830 * "what" == AL_ADD: add files in 'str' to the argument list after "after".
1831 * "what" == AL_DEL: remove files in 'str' from the argument list.
1833 * Return FAIL for failure, OK otherwise.
1835 /*ARGSUSED*/
1836 static int
1837 do_arglist(str, what, after)
1838 char_u *str;
1839 int what;
1840 int after; /* 0 means before first one */
1842 garray_T new_ga;
1843 int exp_count;
1844 char_u **exp_files;
1845 int i;
1846 #ifdef FEAT_LISTCMDS
1847 char_u *p;
1848 int match;
1849 #endif
1852 * Collect all file name arguments in "new_ga".
1854 if (get_arglist(&new_ga, str) == FAIL)
1855 return FAIL;
1857 #ifdef FEAT_LISTCMDS
1858 if (what == AL_DEL)
1860 regmatch_T regmatch;
1861 int didone;
1864 * Delete the items: use each item as a regexp and find a match in the
1865 * argument list.
1867 #ifdef CASE_INSENSITIVE_FILENAME
1868 regmatch.rm_ic = TRUE; /* Always ignore case */
1869 #else
1870 regmatch.rm_ic = FALSE; /* Never ignore case */
1871 #endif
1872 for (i = 0; i < new_ga.ga_len && !got_int; ++i)
1874 p = ((char_u **)new_ga.ga_data)[i];
1875 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE);
1876 if (p == NULL)
1877 break;
1878 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
1879 if (regmatch.regprog == NULL)
1881 vim_free(p);
1882 break;
1885 didone = FALSE;
1886 for (match = 0; match < ARGCOUNT; ++match)
1887 if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]),
1888 (colnr_T)0))
1890 didone = TRUE;
1891 vim_free(ARGLIST[match].ae_fname);
1892 mch_memmove(ARGLIST + match, ARGLIST + match + 1,
1893 (ARGCOUNT - match - 1) * sizeof(aentry_T));
1894 --ALIST(curwin)->al_ga.ga_len;
1895 if (curwin->w_arg_idx > match)
1896 --curwin->w_arg_idx;
1897 --match;
1900 vim_free(regmatch.regprog);
1901 vim_free(p);
1902 if (!didone)
1903 EMSG2(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
1905 ga_clear(&new_ga);
1907 else
1908 #endif
1910 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
1911 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
1912 ga_clear(&new_ga);
1913 if (i == FAIL)
1914 return FAIL;
1915 if (exp_count == 0)
1917 EMSG(_(e_nomatch));
1918 return FAIL;
1921 #ifdef FEAT_LISTCMDS
1922 if (what == AL_ADD)
1924 (void)alist_add_list(exp_count, exp_files, after);
1925 vim_free(exp_files);
1927 else /* what == AL_SET */
1928 #endif
1929 alist_set(ALIST(curwin), exp_count, exp_files, FALSE, NULL, 0);
1932 alist_check_arg_idx();
1934 return OK;
1938 * Check the validity of the arg_idx for each other window.
1940 static void
1941 alist_check_arg_idx()
1943 #ifdef FEAT_WINDOWS
1944 win_T *win;
1945 tabpage_T *tp;
1947 FOR_ALL_TAB_WINDOWS(tp, win)
1948 if (win->w_alist == curwin->w_alist)
1949 check_arg_idx(win);
1950 #else
1951 check_arg_idx(curwin);
1952 #endif
1956 * Return TRUE if window "win" is editing then file at the current argument
1957 * index.
1959 static int
1960 editing_arg_idx(win)
1961 win_T *win;
1963 return !(win->w_arg_idx >= WARGCOUNT(win)
1964 || (win->w_buffer->b_fnum
1965 != WARGLIST(win)[win->w_arg_idx].ae_fnum
1966 && (win->w_buffer->b_ffname == NULL
1967 || !(fullpathcmp(
1968 alist_name(&WARGLIST(win)[win->w_arg_idx]),
1969 win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
1973 * Check if window "win" is editing the w_arg_idx file in its argument list.
1975 void
1976 check_arg_idx(win)
1977 win_T *win;
1979 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win))
1981 /* We are not editing the current entry in the argument list.
1982 * Set "arg_had_last" if we are editing the last one. */
1983 win->w_arg_idx_invalid = TRUE;
1984 if (win->w_arg_idx != WARGCOUNT(win) - 1
1985 && arg_had_last == FALSE
1986 #ifdef FEAT_WINDOWS
1987 && ALIST(win) == &global_alist
1988 #endif
1989 && GARGCOUNT > 0
1990 && win->w_arg_idx < GARGCOUNT
1991 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
1992 || (win->w_buffer->b_ffname != NULL
1993 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
1994 win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
1995 arg_had_last = TRUE;
1997 else
1999 /* We are editing the current entry in the argument list.
2000 * Set "arg_had_last" if it's also the last one */
2001 win->w_arg_idx_invalid = FALSE;
2002 if (win->w_arg_idx == WARGCOUNT(win) - 1
2003 #ifdef FEAT_WINDOWS
2004 && win->w_alist == &global_alist
2005 #endif
2007 arg_had_last = TRUE;
2012 * ":args", ":argslocal" and ":argsglobal".
2014 void
2015 ex_args(eap)
2016 exarg_T *eap;
2018 int i;
2020 if (eap->cmdidx != CMD_args)
2022 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2023 alist_unlink(ALIST(curwin));
2024 if (eap->cmdidx == CMD_argglobal)
2025 ALIST(curwin) = &global_alist;
2026 else /* eap->cmdidx == CMD_arglocal */
2027 alist_new();
2028 #else
2029 ex_ni(eap);
2030 return;
2031 #endif
2034 if (!ends_excmd(*eap->arg))
2037 * ":args file ..": define new argument list, handle like ":next"
2038 * Also for ":argslocal file .." and ":argsglobal file ..".
2040 ex_next(eap);
2042 else
2043 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2044 if (eap->cmdidx == CMD_args)
2045 #endif
2048 * ":args": list arguments.
2050 if (ARGCOUNT > 0)
2052 /* Overwrite the command, for a short list there is no scrolling
2053 * required and no wait_return(). */
2054 gotocmdline(TRUE);
2055 for (i = 0; i < ARGCOUNT; ++i)
2057 if (i == curwin->w_arg_idx)
2058 msg_putchar('[');
2059 msg_outtrans(alist_name(&ARGLIST[i]));
2060 if (i == curwin->w_arg_idx)
2061 msg_putchar(']');
2062 msg_putchar(' ');
2066 #if defined(FEAT_WINDOWS) && defined(FEAT_LISTCMDS)
2067 else if (eap->cmdidx == CMD_arglocal)
2069 garray_T *gap = &curwin->w_alist->al_ga;
2072 * ":argslocal": make a local copy of the global argument list.
2074 if (ga_grow(gap, GARGCOUNT) == OK)
2075 for (i = 0; i < GARGCOUNT; ++i)
2076 if (GARGLIST[i].ae_fname != NULL)
2078 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname =
2079 vim_strsave(GARGLIST[i].ae_fname);
2080 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum =
2081 GARGLIST[i].ae_fnum;
2082 ++gap->ga_len;
2085 #endif
2089 * ":previous", ":sprevious", ":Next" and ":sNext".
2091 void
2092 ex_previous(eap)
2093 exarg_T *eap;
2095 /* If past the last one already, go to the last one. */
2096 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT)
2097 do_argfile(eap, ARGCOUNT - 1);
2098 else
2099 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2);
2103 * ":rewind", ":first", ":sfirst" and ":srewind".
2105 void
2106 ex_rewind(eap)
2107 exarg_T *eap;
2109 do_argfile(eap, 0);
2113 * ":last" and ":slast".
2115 void
2116 ex_last(eap)
2117 exarg_T *eap;
2119 do_argfile(eap, ARGCOUNT - 1);
2123 * ":argument" and ":sargument".
2125 void
2126 ex_argument(eap)
2127 exarg_T *eap;
2129 int i;
2131 if (eap->addr_count > 0)
2132 i = eap->line2 - 1;
2133 else
2134 i = curwin->w_arg_idx;
2135 do_argfile(eap, i);
2139 * Edit file "argn" of the argument lists.
2141 void
2142 do_argfile(eap, argn)
2143 exarg_T *eap;
2144 int argn;
2146 int other;
2147 char_u *p;
2148 int old_arg_idx = curwin->w_arg_idx;
2150 if (argn < 0 || argn >= ARGCOUNT)
2152 if (ARGCOUNT <= 1)
2153 EMSG(_("E163: There is only one file to edit"));
2154 else if (argn < 0)
2155 EMSG(_("E164: Cannot go before first file"));
2156 else
2157 EMSG(_("E165: Cannot go beyond last file"));
2159 else
2161 setpcmark();
2162 #ifdef FEAT_GUI
2163 need_mouse_correct = TRUE;
2164 #endif
2166 #ifdef FEAT_WINDOWS
2167 /* split window or create new tab page first */
2168 if (*eap->cmd == 's' || cmdmod.tab != 0)
2170 if (win_split(0, 0) == FAIL)
2171 return;
2172 # ifdef FEAT_SCROLLBIND
2173 curwin->w_p_scb = FALSE;
2174 # endif
2176 else
2177 #endif
2180 * if 'hidden' set, only check for changed file when re-editing
2181 * the same buffer
2183 other = TRUE;
2184 if (P_HID(curbuf))
2186 p = fix_fname(alist_name(&ARGLIST[argn]));
2187 other = otherfile(p);
2188 vim_free(p);
2190 if ((!P_HID(curbuf) || !other)
2191 && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
2192 return;
2195 curwin->w_arg_idx = argn;
2196 if (argn == ARGCOUNT - 1
2197 #ifdef FEAT_WINDOWS
2198 && curwin->w_alist == &global_alist
2199 #endif
2201 arg_had_last = TRUE;
2203 /* Edit the file; always use the last known line number.
2204 * When it fails (e.g. Abort for already edited file) restore the
2205 * argument index. */
2206 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL,
2207 eap, ECMD_LAST,
2208 (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0)
2209 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
2210 curwin->w_arg_idx = old_arg_idx;
2211 /* like Vi: set the mark where the cursor is in the file. */
2212 else if (eap->cmdidx != CMD_argdo)
2213 setmark('\'');
2218 * ":next", and commands that behave like it.
2220 void
2221 ex_next(eap)
2222 exarg_T *eap;
2224 int i;
2227 * check for changed buffer now, if this fails the argument list is not
2228 * redefined.
2230 if ( P_HID(curbuf)
2231 || eap->cmdidx == CMD_snext
2232 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2234 if (*eap->arg != NUL) /* redefine file list */
2236 if (do_arglist(eap->arg, AL_SET, 0) == FAIL)
2237 return;
2238 i = 0;
2240 else
2241 i = curwin->w_arg_idx + (int)eap->line2;
2242 do_argfile(eap, i);
2246 #ifdef FEAT_LISTCMDS
2248 * ":argedit"
2250 void
2251 ex_argedit(eap)
2252 exarg_T *eap;
2254 int fnum;
2255 int i;
2256 char_u *s;
2258 /* Add the argument to the buffer list and get the buffer number. */
2259 fnum = buflist_add(eap->arg, BLN_LISTED);
2261 /* Check if this argument is already in the argument list. */
2262 for (i = 0; i < ARGCOUNT; ++i)
2263 if (ARGLIST[i].ae_fnum == fnum)
2264 break;
2265 if (i == ARGCOUNT)
2267 /* Can't find it, add it to the argument list. */
2268 s = vim_strsave(eap->arg);
2269 if (s == NULL)
2270 return;
2271 i = alist_add_list(1, &s,
2272 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2273 if (i < 0)
2274 return;
2275 curwin->w_arg_idx = i;
2278 alist_check_arg_idx();
2280 /* Edit the argument. */
2281 do_argfile(eap, i);
2285 * ":argadd"
2287 void
2288 ex_argadd(eap)
2289 exarg_T *eap;
2291 do_arglist(eap->arg, AL_ADD,
2292 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1);
2293 #ifdef FEAT_TITLE
2294 maketitle();
2295 #endif
2299 * ":argdelete"
2301 void
2302 ex_argdelete(eap)
2303 exarg_T *eap;
2305 int i;
2306 int n;
2308 if (eap->addr_count > 0)
2310 /* ":1,4argdel": Delete all arguments in the range. */
2311 if (eap->line2 > ARGCOUNT)
2312 eap->line2 = ARGCOUNT;
2313 n = eap->line2 - eap->line1 + 1;
2314 if (*eap->arg != NUL || n <= 0)
2315 EMSG(_(e_invarg));
2316 else
2318 for (i = eap->line1; i <= eap->line2; ++i)
2319 vim_free(ARGLIST[i - 1].ae_fname);
2320 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
2321 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
2322 ALIST(curwin)->al_ga.ga_len -= n;
2323 if (curwin->w_arg_idx >= eap->line2)
2324 curwin->w_arg_idx -= n;
2325 else if (curwin->w_arg_idx > eap->line1)
2326 curwin->w_arg_idx = eap->line1;
2329 else if (*eap->arg == NUL)
2330 EMSG(_(e_argreq));
2331 else
2332 do_arglist(eap->arg, AL_DEL, 0);
2333 #ifdef FEAT_TITLE
2334 maketitle();
2335 #endif
2339 * ":argdo", ":windo", ":bufdo", ":tabdo"
2341 void
2342 ex_listdo(eap)
2343 exarg_T *eap;
2345 int i;
2346 #ifdef FEAT_WINDOWS
2347 win_T *wp;
2348 tabpage_T *tp;
2349 #endif
2350 buf_T *buf;
2351 int next_fnum = 0;
2352 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2353 char_u *save_ei = NULL;
2354 #endif
2355 char_u *p_shm_save;
2357 #ifndef FEAT_WINDOWS
2358 if (eap->cmdidx == CMD_windo)
2360 ex_ni(eap);
2361 return;
2363 #endif
2365 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2366 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo)
2367 /* Don't do syntax HL autocommands. Skipping the syntax file is a
2368 * great speed improvement. */
2369 save_ei = au_event_disable(",Syntax");
2370 #endif
2372 if (eap->cmdidx == CMD_windo
2373 || eap->cmdidx == CMD_tabdo
2374 || P_HID(curbuf)
2375 || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
2377 /* start at the first argument/window/buffer */
2378 i = 0;
2379 #ifdef FEAT_WINDOWS
2380 wp = firstwin;
2381 tp = first_tabpage;
2382 #endif
2383 /* set pcmark now */
2384 if (eap->cmdidx == CMD_bufdo)
2385 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
2386 else
2387 setpcmark();
2388 listcmd_busy = TRUE; /* avoids setting pcmark below */
2390 while (!got_int)
2392 if (eap->cmdidx == CMD_argdo)
2394 /* go to argument "i" */
2395 if (i == ARGCOUNT)
2396 break;
2397 /* Don't call do_argfile() when already there, it will try
2398 * reloading the file. */
2399 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin))
2401 /* Clear 'shm' to avoid that the file message overwrites
2402 * any output from the command. */
2403 p_shm_save = vim_strsave(p_shm);
2404 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2405 do_argfile(eap, i);
2406 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2407 vim_free(p_shm_save);
2409 if (curwin->w_arg_idx != i)
2410 break;
2411 ++i;
2413 #ifdef FEAT_WINDOWS
2414 else if (eap->cmdidx == CMD_windo)
2416 /* go to window "wp" */
2417 if (!win_valid(wp))
2418 break;
2419 win_goto(wp);
2420 if (curwin != wp)
2421 break; /* something must be wrong */
2422 wp = curwin->w_next;
2424 else if (eap->cmdidx == CMD_tabdo)
2426 /* go to window "tp" */
2427 if (!valid_tabpage(tp))
2428 break;
2429 goto_tabpage_tp(tp);
2430 tp = tp->tp_next;
2432 #endif
2433 else if (eap->cmdidx == CMD_bufdo)
2435 /* Remember the number of the next listed buffer, in case
2436 * ":bwipe" is used or autocommands do something strange. */
2437 next_fnum = -1;
2438 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next)
2439 if (buf->b_p_bl)
2441 next_fnum = buf->b_fnum;
2442 break;
2446 /* execute the command */
2447 do_cmdline(eap->arg, eap->getline, eap->cookie,
2448 DOCMD_VERBOSE + DOCMD_NOWAIT);
2450 if (eap->cmdidx == CMD_bufdo)
2452 /* Done? */
2453 if (next_fnum < 0)
2454 break;
2455 /* Check if the buffer still exists. */
2456 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
2457 if (buf->b_fnum == next_fnum)
2458 break;
2459 if (buf == NULL)
2460 break;
2462 /* Go to the next buffer. Clear 'shm' to avoid that the file
2463 * message overwrites any output from the command. */
2464 p_shm_save = vim_strsave(p_shm);
2465 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
2466 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
2467 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2468 vim_free(p_shm_save);
2470 /* If autocommands took us elsewhere, quit here */
2471 if (curbuf->b_fnum != next_fnum)
2472 break;
2475 if (eap->cmdidx == CMD_windo)
2477 validate_cursor(); /* cursor may have moved */
2478 #ifdef FEAT_SCROLLBIND
2479 /* required when 'scrollbind' has been set */
2480 if (curwin->w_p_scb)
2481 do_check_scrollbind(TRUE);
2482 #endif
2485 listcmd_busy = FALSE;
2488 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
2489 if (save_ei != NULL)
2491 au_event_restore(save_ei);
2492 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
2493 curbuf->b_fname, TRUE, curbuf);
2495 #endif
2499 * Add files[count] to the arglist of the current window after arg "after".
2500 * The file names in files[count] must have been allocated and are taken over.
2501 * Files[] itself is not taken over.
2502 * Returns index of first added argument. Returns -1 when failed (out of mem).
2504 static int
2505 alist_add_list(count, files, after)
2506 int count;
2507 char_u **files;
2508 int after; /* where to add: 0 = before first one */
2510 int i;
2512 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK)
2514 if (after < 0)
2515 after = 0;
2516 if (after > ARGCOUNT)
2517 after = ARGCOUNT;
2518 if (after < ARGCOUNT)
2519 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
2520 (ARGCOUNT - after) * sizeof(aentry_T));
2521 for (i = 0; i < count; ++i)
2523 ARGLIST[after + i].ae_fname = files[i];
2524 ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
2526 ALIST(curwin)->al_ga.ga_len += count;
2527 if (curwin->w_arg_idx >= after)
2528 ++curwin->w_arg_idx;
2529 return after;
2532 for (i = 0; i < count; ++i)
2533 vim_free(files[i]);
2534 return -1;
2537 #endif /* FEAT_LISTCMDS */
2539 #ifdef FEAT_EVAL
2541 * ":compiler[!] {name}"
2543 void
2544 ex_compiler(eap)
2545 exarg_T *eap;
2547 char_u *buf;
2548 char_u *old_cur_comp = NULL;
2549 char_u *p;
2551 if (*eap->arg == NUL)
2553 /* List all compiler scripts. */
2554 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')");
2555 /* ) keep the indenter happy... */
2557 else
2559 buf = alloc((unsigned)(STRLEN(eap->arg) + 14));
2560 if (buf != NULL)
2562 if (eap->forceit)
2564 /* ":compiler! {name}" sets global options */
2565 do_cmdline_cmd((char_u *)
2566 "command -nargs=* CompilerSet set <args>");
2568 else
2570 /* ":compiler! {name}" sets local options.
2571 * To remain backwards compatible "current_compiler" is always
2572 * used. A user's compiler plugin may set it, the distributed
2573 * plugin will then skip the settings. Afterwards set
2574 * "b:current_compiler" and restore "current_compiler". */
2575 old_cur_comp = get_var_value((char_u *)"current_compiler");
2576 if (old_cur_comp != NULL)
2577 old_cur_comp = vim_strsave(old_cur_comp);
2578 do_cmdline_cmd((char_u *)
2579 "command -nargs=* CompilerSet setlocal <args>");
2581 do_unlet((char_u *)"current_compiler", TRUE);
2582 do_unlet((char_u *)"b:current_compiler", TRUE);
2584 sprintf((char *)buf, "compiler/%s.vim", eap->arg);
2585 if (source_runtime(buf, TRUE) == FAIL)
2586 EMSG2(_("E666: compiler not supported: %s"), eap->arg);
2587 vim_free(buf);
2589 do_cmdline_cmd((char_u *)":delcommand CompilerSet");
2591 /* Set "b:current_compiler" from "current_compiler". */
2592 p = get_var_value((char_u *)"current_compiler");
2593 if (p != NULL)
2594 set_internal_string_var((char_u *)"b:current_compiler", p);
2596 /* Restore "current_compiler" for ":compiler {name}". */
2597 if (!eap->forceit)
2599 if (old_cur_comp != NULL)
2601 set_internal_string_var((char_u *)"current_compiler",
2602 old_cur_comp);
2603 vim_free(old_cur_comp);
2605 else
2606 do_unlet((char_u *)"current_compiler", TRUE);
2611 #endif
2614 * ":runtime {name}"
2616 void
2617 ex_runtime(eap)
2618 exarg_T *eap;
2620 source_runtime(eap->arg, eap->forceit);
2623 static void source_callback __ARGS((char_u *fname, void *cookie));
2625 /*ARGSUSED*/
2626 static void
2627 source_callback(fname, cookie)
2628 char_u *fname;
2629 void *cookie;
2631 (void)do_source(fname, FALSE, DOSO_NONE);
2635 * Source the file "name" from all directories in 'runtimepath'.
2636 * "name" can contain wildcards.
2637 * When "all" is TRUE, source all files, otherwise only the first one.
2638 * return FAIL when no file could be sourced, OK otherwise.
2641 source_runtime(name, all)
2642 char_u *name;
2643 int all;
2645 return do_in_runtimepath(name, all, source_callback, NULL);
2649 * Find "name" in 'runtimepath'. When found, invoke the callback function for
2650 * it: callback(fname, "cookie")
2651 * When "all" is TRUE repeat for all matches, otherwise only the first one is
2652 * used.
2653 * Returns OK when at least one match found, FAIL otherwise.
2656 do_in_runtimepath(name, all, callback, cookie)
2657 char_u *name;
2658 int all;
2659 void (*callback)__ARGS((char_u *fname, void *ck));
2660 void *cookie;
2662 char_u *rtp;
2663 char_u *np;
2664 char_u *buf;
2665 char_u *rtp_copy;
2666 char_u *tail;
2667 int num_files;
2668 char_u **files;
2669 int i;
2670 int did_one = FALSE;
2671 #ifdef AMIGA
2672 struct Process *proc = (struct Process *)FindTask(0L);
2673 APTR save_winptr = proc->pr_WindowPtr;
2675 /* Avoid a requester here for a volume that doesn't exist. */
2676 proc->pr_WindowPtr = (APTR)-1L;
2677 #endif
2679 /* Make a copy of 'runtimepath'. Invoking the callback may change the
2680 * value. */
2681 rtp_copy = vim_strsave(p_rtp);
2682 buf = alloc(MAXPATHL);
2683 if (buf != NULL && rtp_copy != NULL)
2685 if (p_verbose > 1)
2687 verbose_enter();
2688 smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
2689 (char *)name, (char *)p_rtp);
2690 verbose_leave();
2693 /* Loop over all entries in 'runtimepath'. */
2694 rtp = rtp_copy;
2695 while (*rtp != NUL && (all || !did_one))
2697 /* Copy the path from 'runtimepath' to buf[]. */
2698 copy_option_part(&rtp, buf, MAXPATHL, ",");
2699 if (STRLEN(buf) + STRLEN(name) + 2 < MAXPATHL)
2701 add_pathsep(buf);
2702 tail = buf + STRLEN(buf);
2704 /* Loop over all patterns in "name" */
2705 np = name;
2706 while (*np != NUL && (all || !did_one))
2708 /* Append the pattern from "name" to buf[]. */
2709 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
2710 "\t ");
2712 if (p_verbose > 2)
2714 verbose_enter();
2715 smsg((char_u *)_("Searching for \"%s\""), buf);
2716 verbose_leave();
2719 /* Expand wildcards, invoke the callback for each match. */
2720 if (gen_expand_wildcards(1, &buf, &num_files, &files,
2721 EW_FILE) == OK)
2723 for (i = 0; i < num_files; ++i)
2725 (*callback)(files[i], cookie);
2726 did_one = TRUE;
2727 if (!all)
2728 break;
2730 FreeWild(num_files, files);
2736 vim_free(buf);
2737 vim_free(rtp_copy);
2738 if (p_verbose > 0 && !did_one)
2740 verbose_enter();
2741 smsg((char_u *)_("not found in 'runtimepath': \"%s\""), name);
2742 verbose_leave();
2745 #ifdef AMIGA
2746 proc->pr_WindowPtr = save_winptr;
2747 #endif
2749 return did_one ? OK : FAIL;
2752 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
2754 * ":options"
2756 /*ARGSUSED*/
2757 void
2758 ex_options(eap)
2759 exarg_T *eap;
2761 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
2763 #endif
2766 * ":source {fname}"
2768 void
2769 ex_source(eap)
2770 exarg_T *eap;
2772 #ifdef FEAT_BROWSE
2773 if (cmdmod.browse)
2775 char_u *fname = NULL;
2777 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg,
2778 NULL, NULL, BROWSE_FILTER_MACROS, NULL);
2779 if (fname != NULL)
2781 cmd_source(fname, eap);
2782 vim_free(fname);
2785 else
2786 #endif
2787 cmd_source(eap->arg, eap);
2790 static void
2791 cmd_source(fname, eap)
2792 char_u *fname;
2793 exarg_T *eap;
2795 if (*fname == NUL)
2796 EMSG(_(e_argreq));
2798 else if (eap != NULL && eap->forceit)
2799 /* ":source!": read Normal mdoe commands
2800 * Need to execute the commands directly. This is required at least
2801 * for:
2802 * - ":g" command busy
2803 * - after ":argdo", ":windo" or ":bufdo"
2804 * - another command follows
2805 * - inside a loop
2807 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL
2808 #ifdef FEAT_EVAL
2809 || eap->cstack->cs_idx >= 0
2810 #endif
2813 /* ":source" read ex commands */
2814 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL)
2815 EMSG2(_(e_notopen), fname);
2819 * ":source" and associated commands.
2822 * Structure used to store info for each sourced file.
2823 * It is shared between do_source() and getsourceline().
2824 * This is required, because it needs to be handed to do_cmdline() and
2825 * sourcing can be done recursively.
2827 struct source_cookie
2829 FILE *fp; /* opened file for sourcing */
2830 char_u *nextline; /* if not NULL: line that was read ahead */
2831 int finished; /* ":finish" used */
2832 #if defined (USE_CRNL) || defined (USE_CR)
2833 int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
2834 int error; /* TRUE if LF found after CR-LF */
2835 #endif
2836 #ifdef FEAT_EVAL
2837 linenr_T breakpoint; /* next line with breakpoint or zero */
2838 char_u *fname; /* name of sourced file */
2839 int dbg_tick; /* debug_tick when breakpoint was set */
2840 int level; /* top nesting level of sourced file */
2841 #endif
2842 #ifdef FEAT_MBYTE
2843 vimconv_T conv; /* type of conversion */
2844 #endif
2847 #ifdef FEAT_EVAL
2849 * Return the address holding the next breakpoint line for a source cookie.
2851 linenr_T *
2852 source_breakpoint(cookie)
2853 void *cookie;
2855 return &((struct source_cookie *)cookie)->breakpoint;
2859 * Return the address holding the debug tick for a source cookie.
2861 int *
2862 source_dbg_tick(cookie)
2863 void *cookie;
2865 return &((struct source_cookie *)cookie)->dbg_tick;
2869 * Return the nesting level for a source cookie.
2872 source_level(cookie)
2873 void *cookie;
2875 return ((struct source_cookie *)cookie)->level;
2877 #endif
2879 static char_u *get_one_sourceline __ARGS((struct source_cookie *sp));
2881 #if defined(WIN32) && defined(FEAT_CSCOPE)
2882 static FILE *fopen_noinh_readbin __ARGS((char *filename));
2885 * Special function to open a file without handle inheritance.
2887 static FILE *
2888 fopen_noinh_readbin(filename)
2889 char *filename;
2891 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0);
2893 if (fd_tmp == -1)
2894 return NULL;
2895 return fdopen(fd_tmp, READBIN);
2897 #endif
2901 * do_source: Read the file "fname" and execute its lines as EX commands.
2903 * This function may be called recursively!
2905 * return FAIL if file could not be opened, OK otherwise
2908 do_source(fname, check_other, is_vimrc)
2909 char_u *fname;
2910 int check_other; /* check for .vimrc and _vimrc */
2911 int is_vimrc; /* DOSO_ value */
2913 struct source_cookie cookie;
2914 char_u *save_sourcing_name;
2915 linenr_T save_sourcing_lnum;
2916 char_u *p;
2917 char_u *fname_exp;
2918 char_u *firstline = NULL;
2919 int retval = FAIL;
2920 #ifdef FEAT_EVAL
2921 scid_T save_current_SID;
2922 static scid_T last_current_SID = 0;
2923 void *save_funccalp;
2924 int save_debug_break_level = debug_break_level;
2925 scriptitem_T *si = NULL;
2926 # ifdef UNIX
2927 struct stat st;
2928 int stat_ok;
2929 # endif
2930 #endif
2931 #ifdef STARTUPTIME
2932 struct timeval tv_rel;
2933 struct timeval tv_start;
2934 #endif
2935 #ifdef FEAT_PROFILE
2936 proftime_T wait_start;
2937 #endif
2939 #ifdef RISCOS
2940 p = mch_munge_fname(fname);
2941 #else
2942 p = expand_env_save(fname);
2943 #endif
2944 if (p == NULL)
2945 return retval;
2946 fname_exp = fix_fname(p);
2947 vim_free(p);
2948 if (fname_exp == NULL)
2949 return retval;
2950 if (mch_isdir(fname_exp))
2952 smsg((char_u *)_("Cannot source a directory: \"%s\""), fname);
2953 goto theend;
2956 #ifdef FEAT_AUTOCMD
2957 /* Apply SourceCmd autocommands, they should get the file and source it. */
2958 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
2959 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
2960 FALSE, curbuf))
2962 # ifdef FEAT_EVAL
2963 retval = aborting() ? FAIL : OK;
2964 # else
2965 retval = OK;
2966 # endif
2967 goto theend;
2970 /* Apply SourcePre autocommands, they may get the file. */
2971 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
2972 #endif
2974 #if defined(WIN32) && defined(FEAT_CSCOPE)
2975 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2976 #else
2977 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2978 #endif
2979 if (cookie.fp == NULL && check_other)
2982 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
2983 * and ".exrc" by "_exrc" or vice versa.
2985 p = gettail(fname_exp);
2986 if ((*p == '.' || *p == '_')
2987 && (STRICMP(p + 1, "vimrc") == 0
2988 || STRICMP(p + 1, "gvimrc") == 0
2989 || STRICMP(p + 1, "exrc") == 0))
2991 if (*p == '_')
2992 *p = '.';
2993 else
2994 *p = '_';
2995 #if defined(WIN32) && defined(FEAT_CSCOPE)
2996 cookie.fp = fopen_noinh_readbin((char *)fname_exp);
2997 #else
2998 cookie.fp = mch_fopen((char *)fname_exp, READBIN);
2999 #endif
3003 if (cookie.fp == NULL)
3005 if (p_verbose > 0)
3007 verbose_enter();
3008 if (sourcing_name == NULL)
3009 smsg((char_u *)_("could not source \"%s\""), fname);
3010 else
3011 smsg((char_u *)_("line %ld: could not source \"%s\""),
3012 sourcing_lnum, fname);
3013 verbose_leave();
3015 goto theend;
3019 * The file exists.
3020 * - In verbose mode, give a message.
3021 * - For a vimrc file, may want to set 'compatible', call vimrc_found().
3023 if (p_verbose > 1)
3025 verbose_enter();
3026 if (sourcing_name == NULL)
3027 smsg((char_u *)_("sourcing \"%s\""), fname);
3028 else
3029 smsg((char_u *)_("line %ld: sourcing \"%s\""),
3030 sourcing_lnum, fname);
3031 verbose_leave();
3033 if (is_vimrc == DOSO_VIMRC)
3034 vimrc_found(fname_exp, (char_u *)"MYVIMRC");
3035 else if (is_vimrc == DOSO_GVIMRC)
3036 vimrc_found(fname_exp, (char_u *)"MYGVIMRC");
3038 #ifdef USE_CRNL
3039 /* If no automatic file format: Set default to CR-NL. */
3040 if (*p_ffs == NUL)
3041 cookie.fileformat = EOL_DOS;
3042 else
3043 cookie.fileformat = EOL_UNKNOWN;
3044 cookie.error = FALSE;
3045 #endif
3047 #ifdef USE_CR
3048 /* If no automatic file format: Set default to CR. */
3049 if (*p_ffs == NUL)
3050 cookie.fileformat = EOL_MAC;
3051 else
3052 cookie.fileformat = EOL_UNKNOWN;
3053 cookie.error = FALSE;
3054 #endif
3056 cookie.nextline = NULL;
3057 cookie.finished = FALSE;
3059 #ifdef FEAT_EVAL
3061 * Check if this script has a breakpoint.
3063 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0);
3064 cookie.fname = fname_exp;
3065 cookie.dbg_tick = debug_tick;
3067 cookie.level = ex_nesting_level;
3068 #endif
3071 * Keep the sourcing name/lnum, for recursive calls.
3073 save_sourcing_name = sourcing_name;
3074 sourcing_name = fname_exp;
3075 save_sourcing_lnum = sourcing_lnum;
3076 sourcing_lnum = 0;
3078 #ifdef FEAT_MBYTE
3079 cookie.conv.vc_type = CONV_NONE; /* no conversion */
3081 /* Read the first line so we can check for a UTF-8 BOM. */
3082 firstline = getsourceline(0, (void *)&cookie, 0);
3083 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef
3084 && firstline[1] == 0xbb && firstline[2] == 0xbf)
3086 /* Found BOM; setup conversion, skip over BOM and recode the line. */
3087 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc);
3088 p = string_convert(&cookie.conv, firstline + 3, NULL);
3089 if (p == NULL)
3090 p = vim_strsave(firstline + 3);
3091 if (p != NULL)
3093 vim_free(firstline);
3094 firstline = p;
3097 #endif
3099 #ifdef STARTUPTIME
3100 time_push(&tv_rel, &tv_start);
3101 #endif
3103 #ifdef FEAT_EVAL
3104 # ifdef FEAT_PROFILE
3105 if (do_profiling == PROF_YES)
3106 prof_child_enter(&wait_start); /* entering a child now */
3107 # endif
3109 /* Don't use local function variables, if called from a function.
3110 * Also starts profiling timer for nested script. */
3111 save_funccalp = save_funccal();
3114 * Check if this script was sourced before to finds its SID.
3115 * If it's new, generate a new SID.
3117 save_current_SID = current_SID;
3118 # ifdef UNIX
3119 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0);
3120 # endif
3121 for (current_SID = script_items.ga_len; current_SID > 0; --current_SID)
3123 si = &SCRIPT_ITEM(current_SID);
3124 if (si->sn_name != NULL
3125 && (
3126 # ifdef UNIX
3127 /* Compare dev/ino when possible, it catches symbolic
3128 * links. Also compare file names, the inode may change
3129 * when the file was edited. */
3130 ((stat_ok && si->sn_dev != -1)
3131 && (si->sn_dev == st.st_dev
3132 && si->sn_ino == st.st_ino)) ||
3133 # endif
3134 fnamecmp(si->sn_name, fname_exp) == 0))
3135 break;
3137 if (current_SID == 0)
3139 current_SID = ++last_current_SID;
3140 if (ga_grow(&script_items, (int)(current_SID - script_items.ga_len))
3141 == FAIL)
3142 goto almosttheend;
3143 while (script_items.ga_len < current_SID)
3145 ++script_items.ga_len;
3146 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
3147 # ifdef FEAT_PROFILE
3148 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
3149 # endif
3151 si = &SCRIPT_ITEM(current_SID);
3152 si->sn_name = fname_exp;
3153 fname_exp = NULL;
3154 # ifdef UNIX
3155 if (stat_ok)
3157 si->sn_dev = st.st_dev;
3158 si->sn_ino = st.st_ino;
3160 else
3161 si->sn_dev = -1;
3162 # endif
3164 /* Allocate the local script variables to use for this script. */
3165 new_script_vars(current_SID);
3168 # ifdef FEAT_PROFILE
3169 if (do_profiling == PROF_YES)
3171 int forceit;
3173 /* Check if we do profiling for this script. */
3174 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit))
3176 script_do_profile(si);
3177 si->sn_pr_force = forceit;
3179 if (si->sn_prof_on)
3181 ++si->sn_pr_count;
3182 profile_start(&si->sn_pr_start);
3183 profile_zero(&si->sn_pr_children);
3186 # endif
3187 #endif
3190 * Call do_cmdline, which will call getsourceline() to get the lines.
3192 do_cmdline(firstline, getsourceline, (void *)&cookie,
3193 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
3194 retval = OK;
3196 #ifdef FEAT_PROFILE
3197 if (do_profiling == PROF_YES)
3199 /* Get "si" again, "script_items" may have been reallocated. */
3200 si = &SCRIPT_ITEM(current_SID);
3201 if (si->sn_prof_on)
3203 profile_end(&si->sn_pr_start);
3204 profile_sub_wait(&wait_start, &si->sn_pr_start);
3205 profile_add(&si->sn_pr_total, &si->sn_pr_start);
3206 profile_self(&si->sn_pr_self, &si->sn_pr_start,
3207 &si->sn_pr_children);
3210 #endif
3212 if (got_int)
3213 EMSG(_(e_interr));
3214 sourcing_name = save_sourcing_name;
3215 sourcing_lnum = save_sourcing_lnum;
3216 if (p_verbose > 1)
3218 verbose_enter();
3219 smsg((char_u *)_("finished sourcing %s"), fname);
3220 if (sourcing_name != NULL)
3221 smsg((char_u *)_("continuing in %s"), sourcing_name);
3222 verbose_leave();
3224 #ifdef STARTUPTIME
3225 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname);
3226 time_msg((char *)IObuff, &tv_start);
3227 time_pop(&tv_rel);
3228 #endif
3230 #ifdef FEAT_EVAL
3232 * After a "finish" in debug mode, need to break at first command of next
3233 * sourced file.
3235 if (save_debug_break_level > ex_nesting_level
3236 && debug_break_level == ex_nesting_level)
3237 ++debug_break_level;
3238 #endif
3240 #ifdef FEAT_EVAL
3241 almosttheend:
3242 current_SID = save_current_SID;
3243 restore_funccal(save_funccalp);
3244 # ifdef FEAT_PROFILE
3245 if (do_profiling == PROF_YES)
3246 prof_child_exit(&wait_start); /* leaving a child now */
3247 # endif
3248 #endif
3249 fclose(cookie.fp);
3250 vim_free(cookie.nextline);
3251 vim_free(firstline);
3252 #ifdef FEAT_MBYTE
3253 convert_setup(&cookie.conv, NULL, NULL);
3254 #endif
3256 theend:
3257 vim_free(fname_exp);
3258 return retval;
3261 #if defined(FEAT_EVAL) || defined(PROTO)
3264 * ":scriptnames"
3266 /*ARGSUSED*/
3267 void
3268 ex_scriptnames(eap)
3269 exarg_T *eap;
3271 int i;
3273 for (i = 1; i <= script_items.ga_len && !got_int; ++i)
3274 if (SCRIPT_ITEM(i).sn_name != NULL)
3275 smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name);
3278 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
3280 * Fix slashes in the list of script names for 'shellslash'.
3282 void
3283 scriptnames_slash_adjust()
3285 int i;
3287 for (i = 1; i <= script_items.ga_len; ++i)
3288 if (SCRIPT_ITEM(i).sn_name != NULL)
3289 slash_adjust(SCRIPT_ITEM(i).sn_name);
3291 # endif
3294 * Get a pointer to a script name. Used for ":verbose set".
3296 char_u *
3297 get_scriptname(id)
3298 scid_T id;
3300 if (id == SID_MODELINE)
3301 return (char_u *)_("modeline");
3302 if (id == SID_CMDARG)
3303 return (char_u *)_("--cmd argument");
3304 if (id == SID_CARG)
3305 return (char_u *)_("-c argument");
3306 if (id == SID_ENV)
3307 return (char_u *)_("environment variable");
3308 if (id == SID_ERROR)
3309 return (char_u *)_("error handler");
3310 return SCRIPT_ITEM(id).sn_name;
3313 # if defined(EXITFREE) || defined(PROTO)
3314 void
3315 free_scriptnames()
3317 int i;
3319 for (i = script_items.ga_len; i > 0; --i)
3320 vim_free(SCRIPT_ITEM(i).sn_name);
3321 ga_clear(&script_items);
3323 # endif
3325 #endif
3327 #if defined(USE_CR) || defined(PROTO)
3329 # if defined(__MSL__) && (__MSL__ >= 22)
3331 * Newer version of the Metrowerks library handle DOS and UNIX files
3332 * without help.
3333 * Test with earlier versions, MSL 2.2 is the library supplied with
3334 * Codewarrior Pro 2.
3336 char *
3337 fgets_cr(s, n, stream)
3338 char *s;
3339 int n;
3340 FILE *stream;
3342 return fgets(s, n, stream);
3344 # else
3346 * Version of fgets() which also works for lines ending in a <CR> only
3347 * (Macintosh format).
3348 * For older versions of the Metrowerks library.
3349 * At least CodeWarrior 9 needed this code.
3351 char *
3352 fgets_cr(s, n, stream)
3353 char *s;
3354 int n;
3355 FILE *stream;
3357 int c = 0;
3358 int char_read = 0;
3360 while (!feof(stream) && c != '\r' && c != '\n' && char_read < n - 1)
3362 c = fgetc(stream);
3363 s[char_read++] = c;
3364 /* If the file is in DOS format, we need to skip a NL after a CR. I
3365 * thought it was the other way around, but this appears to work... */
3366 if (c == '\n')
3368 c = fgetc(stream);
3369 if (c != '\r')
3370 ungetc(c, stream);
3374 s[char_read] = 0;
3375 if (char_read == 0)
3376 return NULL;
3378 if (feof(stream) && char_read == 1)
3379 return NULL;
3381 return s;
3383 # endif
3384 #endif
3387 * Get one full line from a sourced file.
3388 * Called by do_cmdline() when it's called from do_source().
3390 * Return a pointer to the line in allocated memory.
3391 * Return NULL for end-of-file or some error.
3393 /* ARGSUSED */
3394 char_u *
3395 getsourceline(c, cookie, indent)
3396 int c; /* not used */
3397 void *cookie;
3398 int indent; /* not used */
3400 struct source_cookie *sp = (struct source_cookie *)cookie;
3401 char_u *line;
3402 char_u *p, *s;
3404 #ifdef FEAT_EVAL
3405 /* If breakpoints have been added/deleted need to check for it. */
3406 if (sp->dbg_tick < debug_tick)
3408 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3409 sp->dbg_tick = debug_tick;
3411 # ifdef FEAT_PROFILE
3412 if (do_profiling == PROF_YES)
3413 script_line_end();
3414 # endif
3415 #endif
3417 * Get current line. If there is a read-ahead line, use it, otherwise get
3418 * one now.
3420 if (sp->finished)
3421 line = NULL;
3422 else if (sp->nextline == NULL)
3423 line = get_one_sourceline(sp);
3424 else
3426 line = sp->nextline;
3427 sp->nextline = NULL;
3428 ++sourcing_lnum;
3430 #ifdef FEAT_PROFILE
3431 if (line != NULL && do_profiling == PROF_YES)
3432 script_line_start();
3433 #endif
3435 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't
3436 * contain the 'C' flag. */
3437 if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL))
3439 /* compensate for the one line read-ahead */
3440 --sourcing_lnum;
3441 for (;;)
3443 sp->nextline = get_one_sourceline(sp);
3444 if (sp->nextline == NULL)
3445 break;
3446 p = skipwhite(sp->nextline);
3447 if (*p != '\\')
3448 break;
3449 s = alloc((int)(STRLEN(line) + STRLEN(p)));
3450 if (s == NULL) /* out of memory */
3451 break;
3452 STRCPY(s, line);
3453 STRCAT(s, p + 1);
3454 vim_free(line);
3455 line = s;
3456 vim_free(sp->nextline);
3460 #ifdef FEAT_MBYTE
3461 if (line != NULL && sp->conv.vc_type != CONV_NONE)
3463 /* Convert the encoding of the script line. */
3464 s = string_convert(&sp->conv, line, NULL);
3465 if (s != NULL)
3467 vim_free(line);
3468 line = s;
3471 #endif
3473 #ifdef FEAT_EVAL
3474 /* Did we encounter a breakpoint? */
3475 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum)
3477 dbg_breakpoint(sp->fname, sourcing_lnum);
3478 /* Find next breakpoint. */
3479 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum);
3480 sp->dbg_tick = debug_tick;
3482 #endif
3484 return line;
3487 static char_u *
3488 get_one_sourceline(sp)
3489 struct source_cookie *sp;
3491 garray_T ga;
3492 int len;
3493 int c;
3494 char_u *buf;
3495 #ifdef USE_CRNL
3496 int has_cr; /* CR-LF found */
3497 #endif
3498 #ifdef USE_CR
3499 char_u *scan;
3500 #endif
3501 int have_read = FALSE;
3503 /* use a growarray to store the sourced line */
3504 ga_init2(&ga, 1, 250);
3507 * Loop until there is a finished line (or end-of-file).
3509 sourcing_lnum++;
3510 for (;;)
3512 /* make room to read at least 120 (more) characters */
3513 if (ga_grow(&ga, 120) == FAIL)
3514 break;
3515 buf = (char_u *)ga.ga_data;
3517 #ifdef USE_CR
3518 if (sp->fileformat == EOL_MAC)
3520 if (fgets_cr((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3521 sp->fp) == NULL)
3522 break;
3524 else
3525 #endif
3526 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
3527 sp->fp) == NULL)
3528 break;
3529 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);
3530 #ifdef USE_CRNL
3531 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
3532 * CTRL-Z by its own, or after a NL. */
3533 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
3534 && sp->fileformat == EOL_DOS
3535 && buf[len - 1] == Ctrl_Z)
3537 buf[len - 1] = NUL;
3538 break;
3540 #endif
3542 #ifdef USE_CR
3543 /* If the read doesn't stop on a new line, and there's
3544 * some CR then we assume a Mac format */
3545 if (sp->fileformat == EOL_UNKNOWN)
3547 if (buf[len - 1] != '\n' && vim_strchr(buf, '\r') != NULL)
3548 sp->fileformat = EOL_MAC;
3549 else
3550 sp->fileformat = EOL_UNIX;
3553 if (sp->fileformat == EOL_MAC)
3555 scan = vim_strchr(buf, '\r');
3557 if (scan != NULL)
3559 *scan = '\n';
3560 if (*(scan + 1) != 0)
3562 *(scan + 1) = 0;
3563 fseek(sp->fp, (long)(scan - buf - len + 1), SEEK_CUR);
3566 len = STRLEN(buf);
3568 #endif
3570 have_read = TRUE;
3571 ga.ga_len = len;
3573 /* If the line was longer than the buffer, read more. */
3574 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n')
3575 continue;
3577 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */
3579 #ifdef USE_CRNL
3580 has_cr = (len >= 2 && buf[len - 2] == '\r');
3581 if (sp->fileformat == EOL_UNKNOWN)
3583 if (has_cr)
3584 sp->fileformat = EOL_DOS;
3585 else
3586 sp->fileformat = EOL_UNIX;
3589 if (sp->fileformat == EOL_DOS)
3591 if (has_cr) /* replace trailing CR */
3593 buf[len - 2] = '\n';
3594 --len;
3595 --ga.ga_len;
3597 else /* lines like ":map xx yy^M" will have failed */
3599 if (!sp->error)
3601 msg_source(hl_attr(HLF_W));
3602 EMSG(_("W15: Warning: Wrong line separator, ^M may be missing"));
3604 sp->error = TRUE;
3605 sp->fileformat = EOL_UNIX;
3608 #endif
3609 /* The '\n' is escaped if there is an odd number of ^V's just
3610 * before it, first set "c" just before the 'V's and then check
3611 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
3612 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--)
3614 if ((len & 1) != (c & 1)) /* escaped NL, read more */
3616 sourcing_lnum++;
3617 continue;
3620 buf[len - 1] = NUL; /* remove the NL */
3624 * Check for ^C here now and then, so recursive :so can be broken.
3626 line_breakcheck();
3627 break;
3630 if (have_read)
3631 return (char_u *)ga.ga_data;
3633 vim_free(ga.ga_data);
3634 return NULL;
3637 #if defined(FEAT_PROFILE) || defined(PROTO)
3639 * Called when starting to read a script line.
3640 * "sourcing_lnum" must be correct!
3641 * When skipping lines it may not actually be executed, but we won't find out
3642 * until later and we need to store the time now.
3644 void
3645 script_line_start()
3647 scriptitem_T *si;
3648 sn_prl_T *pp;
3650 if (current_SID <= 0 || current_SID > script_items.ga_len)
3651 return;
3652 si = &SCRIPT_ITEM(current_SID);
3653 if (si->sn_prof_on && sourcing_lnum >= 1)
3655 /* Grow the array before starting the timer, so that the time spent
3656 * here isn't counted. */
3657 ga_grow(&si->sn_prl_ga, (int)(sourcing_lnum - si->sn_prl_ga.ga_len));
3658 si->sn_prl_idx = sourcing_lnum - 1;
3659 while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
3660 && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen)
3662 /* Zero counters for a line that was not used before. */
3663 pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len);
3664 pp->snp_count = 0;
3665 profile_zero(&pp->sn_prl_total);
3666 profile_zero(&pp->sn_prl_self);
3667 ++si->sn_prl_ga.ga_len;
3669 si->sn_prl_execed = FALSE;
3670 profile_start(&si->sn_prl_start);
3671 profile_zero(&si->sn_prl_children);
3672 profile_get_wait(&si->sn_prl_wait);
3677 * Called when actually executing a function line.
3679 void
3680 script_line_exec()
3682 scriptitem_T *si;
3684 if (current_SID <= 0 || current_SID > script_items.ga_len)
3685 return;
3686 si = &SCRIPT_ITEM(current_SID);
3687 if (si->sn_prof_on && si->sn_prl_idx >= 0)
3688 si->sn_prl_execed = TRUE;
3692 * Called when done with a function line.
3694 void
3695 script_line_end()
3697 scriptitem_T *si;
3698 sn_prl_T *pp;
3700 if (current_SID <= 0 || current_SID > script_items.ga_len)
3701 return;
3702 si = &SCRIPT_ITEM(current_SID);
3703 if (si->sn_prof_on && si->sn_prl_idx >= 0
3704 && si->sn_prl_idx < si->sn_prl_ga.ga_len)
3706 if (si->sn_prl_execed)
3708 pp = &PRL_ITEM(si, si->sn_prl_idx);
3709 ++pp->snp_count;
3710 profile_end(&si->sn_prl_start);
3711 profile_sub_wait(&si->sn_prl_wait, &si->sn_prl_start);
3712 profile_add(&pp->sn_prl_total, &si->sn_prl_start);
3713 profile_self(&pp->sn_prl_self, &si->sn_prl_start,
3714 &si->sn_prl_children);
3716 si->sn_prl_idx = -1;
3719 #endif
3722 * ":scriptencoding": Set encoding conversion for a sourced script.
3723 * Without the multi-byte feature it's simply ignored.
3725 /*ARGSUSED*/
3726 void
3727 ex_scriptencoding(eap)
3728 exarg_T *eap;
3730 #ifdef FEAT_MBYTE
3731 struct source_cookie *sp;
3732 char_u *name;
3734 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
3736 EMSG(_("E167: :scriptencoding used outside of a sourced file"));
3737 return;
3740 if (*eap->arg != NUL)
3742 name = enc_canonize(eap->arg);
3743 if (name == NULL) /* out of memory */
3744 return;
3746 else
3747 name = eap->arg;
3749 /* Setup for conversion from the specified encoding to 'encoding'. */
3750 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
3751 convert_setup(&sp->conv, name, p_enc);
3753 if (name != eap->arg)
3754 vim_free(name);
3755 #endif
3758 #if defined(FEAT_EVAL) || defined(PROTO)
3760 * ":finish": Mark a sourced file as finished.
3762 void
3763 ex_finish(eap)
3764 exarg_T *eap;
3766 if (getline_equal(eap->getline, eap->cookie, getsourceline))
3767 do_finish(eap, FALSE);
3768 else
3769 EMSG(_("E168: :finish used outside of a sourced file"));
3773 * Mark a sourced file as finished. Possibly makes the ":finish" pending.
3774 * Also called for a pending finish at the ":endtry" or after returning from
3775 * an extra do_cmdline(). "reanimate" is used in the latter case.
3777 void
3778 do_finish(eap, reanimate)
3779 exarg_T *eap;
3780 int reanimate;
3782 int idx;
3784 if (reanimate)
3785 ((struct source_cookie *)getline_cookie(eap->getline,
3786 eap->cookie))->finished = FALSE;
3789 * Cleanup (and inactivate) conditionals, but stop when a try conditional
3790 * not in its finally clause (which then is to be executed next) is found.
3791 * In this case, make the ":finish" pending for execution at the ":endtry".
3792 * Otherwise, finish normally.
3794 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
3795 if (idx >= 0)
3797 eap->cstack->cs_pending[idx] = CSTP_FINISH;
3798 report_make_pending(CSTP_FINISH, NULL);
3800 else
3801 ((struct source_cookie *)getline_cookie(eap->getline,
3802 eap->cookie))->finished = TRUE;
3807 * Return TRUE when a sourced file had the ":finish" command: Don't give error
3808 * message for missing ":endif".
3809 * Return FALSE when not sourcing a file.
3812 source_finished(fgetline, cookie)
3813 char_u *(*fgetline) __ARGS((int, void *, int));
3814 void *cookie;
3816 return (getline_equal(fgetline, cookie, getsourceline)
3817 && ((struct source_cookie *)getline_cookie(
3818 fgetline, cookie))->finished);
3820 #endif
3822 #if defined(FEAT_LISTCMDS) || defined(PROTO)
3824 * ":checktime [buffer]"
3826 void
3827 ex_checktime(eap)
3828 exarg_T *eap;
3830 buf_T *buf;
3831 int save_no_check_timestamps = no_check_timestamps;
3833 no_check_timestamps = 0;
3834 if (eap->addr_count == 0) /* default is all buffers */
3835 check_timestamps(FALSE);
3836 else
3838 buf = buflist_findnr((int)eap->line2);
3839 if (buf != NULL) /* cannot happen? */
3840 (void)buf_check_timestamp(buf, FALSE);
3842 no_check_timestamps = save_no_check_timestamps;
3844 #endif
3846 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3847 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG))
3848 static char *get_locale_val __ARGS((int what));
3850 static char *
3851 get_locale_val(what)
3852 int what;
3854 char *loc;
3856 /* Obtain the locale value from the libraries. For DJGPP this is
3857 * redefined and it doesn't use the arguments. */
3858 loc = setlocale(what, NULL);
3860 # ifdef WIN32
3861 if (loc != NULL)
3863 char_u *p;
3865 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when
3866 * one of the values (e.g., LC_CTYPE) differs. */
3867 p = vim_strchr(loc, '=');
3868 if (p != NULL)
3870 loc = ++p;
3871 while (*p != NUL) /* remove trailing newline */
3873 if (*p < ' ' || *p == ';')
3875 *p = NUL;
3876 break;
3878 ++p;
3882 # endif
3884 return loc;
3886 #endif
3889 #ifdef WIN32
3891 * On MS-Windows locale names are strings like "German_Germany.1252", but
3892 * gettext expects "de". Try to translate one into another here for a few
3893 * supported languages.
3895 static char_u *
3896 gettext_lang(char_u *name)
3898 int i;
3899 static char *(mtable[]) = {
3900 "afrikaans", "af",
3901 "czech", "cs",
3902 "dutch", "nl",
3903 "german", "de",
3904 "english_united kingdom", "en_GB",
3905 "spanish", "es",
3906 "french", "fr",
3907 "italian", "it",
3908 "japanese", "ja",
3909 "korean", "ko",
3910 "norwegian", "no",
3911 "polish", "pl",
3912 "russian", "ru",
3913 "slovak", "sk",
3914 "swedish", "sv",
3915 "ukrainian", "uk",
3916 "chinese_china", "zh_CN",
3917 "chinese_taiwan", "zh_TW",
3918 NULL};
3920 for (i = 0; mtable[i] != NULL; i += 2)
3921 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0)
3922 return mtable[i + 1];
3923 return name;
3925 #endif
3927 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
3929 * Obtain the current messages language. Used to set the default for
3930 * 'helplang'. May return NULL or an empty string.
3932 char_u *
3933 get_mess_lang()
3935 char_u *p;
3937 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE))
3938 # if defined(LC_MESSAGES)
3939 p = (char_u *)get_locale_val(LC_MESSAGES);
3940 # else
3941 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG
3942 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME
3943 * and LC_MONETARY may be set differently for a Japanese working in the
3944 * US. */
3945 p = (char_u *)get_locale_val(LC_COLLATE);
3946 # endif
3947 # else
3948 p = mch_getenv((char_u *)"LC_ALL");
3949 if (p == NULL || *p == NUL)
3951 p = mch_getenv((char_u *)"LC_MESSAGES");
3952 if (p == NULL || *p == NUL)
3953 p = mch_getenv((char_u *)"LANG");
3955 # endif
3956 # ifdef WIN32
3957 p = gettext_lang(p);
3958 # endif
3959 return p;
3961 #endif
3963 /* Complicated #if; matches with where get_mess_env() is used below. */
3964 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3965 && defined(LC_MESSAGES))) \
3966 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
3967 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) \
3968 && !defined(LC_MESSAGES))
3969 static char_u *get_mess_env __ARGS((void));
3972 * Get the language used for messages from the environment.
3974 static char_u *
3975 get_mess_env()
3977 char_u *p;
3979 p = mch_getenv((char_u *)"LC_ALL");
3980 if (p == NULL || *p == NUL)
3982 p = mch_getenv((char_u *)"LC_MESSAGES");
3983 if (p == NULL || *p == NUL)
3985 p = mch_getenv((char_u *)"LANG");
3986 if (p != NULL && VIM_ISDIGIT(*p))
3987 p = NULL; /* ignore something like "1043" */
3988 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
3989 if (p == NULL || *p == NUL)
3990 p = (char_u *)get_locale_val(LC_CTYPE);
3991 # endif
3994 return p;
3996 #endif
3998 #if defined(FEAT_EVAL) || defined(PROTO)
4001 * Set the "v:lang" variable according to the current locale setting.
4002 * Also do "v:lc_time"and "v:ctype".
4004 void
4005 set_lang_var()
4007 char_u *loc;
4009 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4010 loc = (char_u *)get_locale_val(LC_CTYPE);
4011 # else
4012 /* setlocale() not supported: use the default value */
4013 loc = (char_u *)"C";
4014 # endif
4015 set_vim_var_string(VV_CTYPE, loc, -1);
4017 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
4018 * back to LC_CTYPE if it's empty. */
4019 # if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) && defined(LC_MESSAGES)
4020 loc = (char_u *)get_locale_val(LC_MESSAGES);
4021 # else
4022 loc = get_mess_env();
4023 # endif
4024 set_vim_var_string(VV_LANG, loc, -1);
4026 # if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4027 loc = (char_u *)get_locale_val(LC_TIME);
4028 # endif
4029 set_vim_var_string(VV_LC_TIME, loc, -1);
4031 #endif
4033 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \
4034 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))
4036 * ":language": Set the language (locale).
4038 void
4039 ex_language(eap)
4040 exarg_T *eap;
4042 char *loc;
4043 char_u *p;
4044 char_u *name;
4045 int what = LC_ALL;
4046 char *whatstr = "";
4047 #ifdef LC_MESSAGES
4048 # define VIM_LC_MESSAGES LC_MESSAGES
4049 #else
4050 # define VIM_LC_MESSAGES 6789
4051 #endif
4053 name = eap->arg;
4055 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument.
4056 * Allow abbreviation, but require at least 3 characters to avoid
4057 * confusion with a two letter language name "me" or "ct". */
4058 p = skiptowhite(eap->arg);
4059 if ((*p == NUL || vim_iswhite(*p)) && p - eap->arg >= 3)
4061 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0)
4063 what = VIM_LC_MESSAGES;
4064 name = skipwhite(p);
4065 whatstr = "messages ";
4067 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0)
4069 what = LC_CTYPE;
4070 name = skipwhite(p);
4071 whatstr = "ctype ";
4073 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0)
4075 what = LC_TIME;
4076 name = skipwhite(p);
4077 whatstr = "time ";
4081 if (*name == NUL)
4083 #ifndef LC_MESSAGES
4084 if (what == VIM_LC_MESSAGES)
4085 p = get_mess_env();
4086 else
4087 #endif
4088 p = (char_u *)setlocale(what, NULL);
4089 if (p == NULL || *p == NUL)
4090 p = (char_u *)"Unknown";
4091 smsg((char_u *)_("Current %slanguage: \"%s\""), whatstr, p);
4093 else
4095 #ifndef LC_MESSAGES
4096 if (what == VIM_LC_MESSAGES)
4097 loc = "";
4098 else
4099 #endif
4101 loc = setlocale(what, (char *)name);
4102 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
4103 /* Make sure strtod() uses a decimal point, not a comma. */
4104 setlocale(LC_NUMERIC, "C");
4105 #endif
4107 if (loc == NULL)
4108 EMSG2(_("E197: Cannot set language to \"%s\""), name);
4109 else
4111 #ifdef HAVE_NL_MSG_CAT_CNTR
4112 /* Need to do this for GNU gettext, otherwise cached translations
4113 * will be used again. */
4114 extern int _nl_msg_cat_cntr;
4116 ++_nl_msg_cat_cntr;
4117 #endif
4118 /* Reset $LC_ALL, otherwise it would overrule everything. */
4119 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
4121 if (what != LC_TIME)
4123 /* Tell gettext() what to translate to. It apparently doesn't
4124 * use the currently effective locale. Also do this when
4125 * FEAT_GETTEXT isn't defined, so that shell commands use this
4126 * value. */
4127 if (what == LC_ALL)
4129 vim_setenv((char_u *)"LANG", name);
4130 # ifdef WIN32
4131 /* Apparently MS-Windows printf() may cause a crash when
4132 * we give it 8-bit text while it's expecting text in the
4133 * current locale. This call avoids that. */
4134 setlocale(LC_CTYPE, "C");
4135 # endif
4137 if (what != LC_CTYPE)
4139 char_u *mname;
4140 #ifdef WIN32
4141 mname = gettext_lang(name);
4142 #else
4143 mname = name;
4144 #endif
4145 vim_setenv((char_u *)"LC_MESSAGES", mname);
4146 #ifdef FEAT_MULTI_LANG
4147 set_helplang_default(mname);
4148 #endif
4151 /* Set $LC_CTYPE, because it overrules $LANG, and
4152 * gtk_set_locale() calls setlocale() again. gnome_init()
4153 * sets $LC_CTYPE to "en_US" (that's a bug!). */
4154 if (what != VIM_LC_MESSAGES)
4155 vim_setenv((char_u *)"LC_CTYPE", name);
4156 # ifdef FEAT_GUI_GTK
4157 /* Let GTK know what locale we're using. Not sure this is
4158 * really needed... */
4159 if (gui.in_use)
4160 (void)gtk_set_locale();
4161 # endif
4164 # ifdef FEAT_EVAL
4165 /* Set v:lang, v:lc_time and v:ctype to the final result. */
4166 set_lang_var();
4167 # endif
4172 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4174 * Function given to ExpandGeneric() to obtain the possible arguments of the
4175 * ":language" command.
4177 /*ARGSUSED*/
4178 char_u *
4179 get_lang_arg(xp, idx)
4180 expand_T *xp;
4181 int idx;
4183 if (idx == 0)
4184 return (char_u *)"messages";
4185 if (idx == 1)
4186 return (char_u *)"ctype";
4187 if (idx == 2)
4188 return (char_u *)"time";
4189 return NULL;
4191 # endif
4193 #endif