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.
11 * message.c: functions for displaying messages on the command line
14 #define MESSAGE_FILE /* don't include prototype for smsg() */
18 #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
22 static int other_sourcing_name __ARGS((void));
23 static char_u *get_emsg_source __ARGS((void));
24 static char_u *get_emsg_lnum __ARGS((void));
25 static void add_msg_hist __ARGS((char_u *s, int len, int attr));
26 static void hit_return_msg __ARGS((void));
27 static void msg_home_replace_attr __ARGS((char_u *fname, int attr));
29 static char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr));
31 static void msg_puts_attr_len __ARGS((char_u *str, int maxlen, int attr));
32 static void msg_puts_display __ARGS((char_u *str, int maxlen, int attr, int recurse));
33 static void msg_scroll_up __ARGS((void));
34 static void inc_msg_scrolled __ARGS((void));
35 static void store_sb_text __ARGS((char_u **sb_str, char_u *s, int attr, int *sb_col, int finish));
36 static void t_puts __ARGS((int *t_col, char_u *t_s, char_u *s, int attr));
37 static void msg_puts_printf __ARGS((char_u *str, int maxlen));
38 static int do_more_prompt __ARGS((int typed_char));
39 static void msg_screen_putchar __ARGS((int c, int attr));
40 static int msg_check_screen __ARGS((void));
41 static void redir_write __ARGS((char_u *s, int maxlen));
42 static void verbose_write __ARGS((char_u *s, int maxlen));
43 #ifdef FEAT_CON_DIALOG
44 static char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton));
45 static int confirm_msg_used = FALSE; /* displaying confirm_msg */
46 static char_u *confirm_msg = NULL; /* ":confirm" message */
47 static char_u *confirm_msg_tail; /* tail of confirm_msg */
52 struct msg_hist *next;
57 static struct msg_hist *first_msg_hist = NULL;
58 static struct msg_hist *last_msg_hist = NULL;
59 static int msg_hist_len = 0;
62 * When writing messages to the screen, there are many different situations.
63 * A number of variables is used to remember the current state:
64 * msg_didany TRUE when messages were written since the last time the
65 * user reacted to a prompt.
66 * Reset: After hitting a key for the hit-return prompt,
67 * hitting <CR> for the command line or input().
68 * Set: When any message is written to the screen.
69 * msg_didout TRUE when something was written to the current line.
70 * Reset: When advancing to the next line, when the current
71 * text can be overwritten.
72 * Set: When any message is written to the screen.
73 * msg_nowait No extra delay for the last drawn message.
74 * Used in normal_cmd() before the mode message is drawn.
75 * emsg_on_display There was an error message recently. Indicates that there
76 * should be a delay before redrawing.
77 * msg_scroll The next message should not overwrite the current one.
78 * msg_scrolled How many lines the screen has been scrolled (because of
79 * messages). Used in update_screen() to scroll the screen
80 * back. Incremented each time the screen scrolls a line.
81 * msg_scrolled_ign TRUE when msg_scrolled is non-zero and msg_puts_attr()
82 * writes something without scrolling should not make
83 * need_wait_return to be set. This is a hack to make ":ts"
84 * work without an extra prompt.
85 * lines_left Number of lines available for messages before the
86 * more-prompt is to be given.
87 * need_wait_return TRUE when the hit-return prompt is needed.
88 * Reset: After giving the hit-return prompt, when the user
89 * has answered some other prompt.
90 * Set: When the ruler or typeahead display is overwritten,
91 * scrolling the screen for some message.
92 * keep_msg Message to be displayed after redrawing the screen, in
94 * This is an allocated string or NULL when not used.
98 * msg(s) - displays the string 's' on the status line
99 * When terminal not initialized (yet) mch_errmsg(..) is used.
100 * return TRUE if wait_return not called
106 return msg_attr_keep(s, 0, FALSE);
109 #if defined(FEAT_EVAL) || defined(FEAT_X11) || defined(USE_XSMP) \
110 || defined(FEAT_GUI_GTK) || defined(PROTO)
112 * Like msg() but keep it silent when 'verbosefile' is set.
121 n = msg_attr_keep(s, 0, FALSE);
133 return msg_attr_keep(s, attr, FALSE);
137 msg_attr_keep(s, attr, keep)
140 int keep; /* TRUE: set keep_msg if it doesn't scroll */
142 static int entered = 0;
148 set_vim_var_string(VV_STATUSMSG, s, -1);
152 * It is possible that displaying a messages causes a problem (e.g.,
153 * when redrawing the window), which causes another message, etc.. To
154 * break this loop, limit the recursiveness to 3 levels.
160 /* Add message to history (unless it's a repeated kept message or a
161 * truncated message) */
164 && last_msg_hist != NULL
165 && last_msg_hist->msg != NULL
166 && STRCMP(s, last_msg_hist->msg)))
167 add_msg_hist(s, -1, attr);
169 /* When displaying keep_msg, don't let msg_start() free it, caller must do
174 /* Truncate the message if needed. */
176 buf = msg_strtrunc(s, FALSE);
180 msg_outtrans_attr(s, attr);
184 if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1)
194 * Truncate a string such that it can be printed without causing a scroll.
195 * Returns an allocated string or NULL when no truncating is done.
198 msg_strtrunc(s, force)
200 int force; /* always truncate */
206 /* May truncate message to avoid a hit-return prompt */
207 if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL)
208 && !exmode_active && msg_silent == 0) || force)
210 len = vim_strsize(s);
211 if (msg_scrolled != 0)
212 /* Use all the columns. */
213 room = (int)(Rows - msg_row) * Columns - 1;
215 /* Use up to 'showcmd' column. */
216 room = (int)(Rows - msg_row - 1) * Columns + sc_col - 1;
217 if (len > room && room > 0)
221 /* may have up to 18 bytes per cell (6 per char, up to two
222 * composing chars) */
223 buf = alloc((room + 2) * 18);
224 else if (enc_dbcs == DBCS_JPNU)
225 /* may have up to 2 bytes per cell for euc-jp */
226 buf = alloc((room + 2) * 2);
229 buf = alloc(room + 2);
231 trunc_string(s, buf, room);
238 * Truncate a string "s" to "buf" with cell width "room".
239 * "s" and "buf" may be equal.
242 trunc_string(s, buf, room)
257 /* First part: Start of the string. */
258 for (e = 0; len < half; ++e)
262 /* text fits without truncating! */
266 n = ptr2cells(s + e);
273 for (n = (*mb_ptr2len)(s + e); --n > 0; )
281 /* Last part: End of the string. */
286 /* For DBCS going backwards in a string is slow, but
287 * computing the cell width isn't too slow: go forward
288 * until the rest fits. */
289 n = vim_strsize(s + i);
290 while (len + n > room)
292 n -= ptr2cells(s + i);
293 i += (*mb_ptr2len)(s + i);
298 /* For UTF-8 we can go backwards easily. */
299 half = i = (int)STRLEN(s);
303 half = half - (*mb_head_off)(s, s + half - 1) - 1;
304 while (utf_iscomposing(utf_ptr2char(s + half)) && half > 0);
305 n = ptr2cells(s + half);
315 for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i)
319 /* Set the middle and copy the last part. */
320 mch_memmove(buf + e, "...", (size_t)3);
321 STRMOVE(buf + e + 3, s + i);
325 * Automatic prototype generation does not understand this function.
326 * Note: Caller of smgs() and smsg_attr() must check the resulting string is
327 * shorter than IOSIZE!!!
330 # ifndef HAVE_STDARG_H
336 smsg __ARGS((char_u *, long, long, long,
337 long, long, long, long, long, long, long));
342 smsg_attr __ARGS((int, char_u *, long, long, long,
343 long, long, long, long, long, long, long));
345 int vim_snprintf __ARGS((char *, size_t, char *, long, long, long,
346 long, long, long, long, long, long, long));
349 * smsg(str, arg, ...) is like using sprintf(buf, str, arg, ...) and then
351 * The buffer used is IObuff, the message is truncated at IOSIZE.
359 smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
361 long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
363 return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
371 smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
374 long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
376 vim_snprintf((char *)IObuff, IOSIZE, (char *)s,
377 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
378 return msg_attr(IObuff, attr);
381 # else /* HAVE_STDARG_H */
383 int vim_snprintf(char *str, size_t str_m, char *fmt, ...);
393 va_start(arglist, s);
394 vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL);
403 smsg_attr(int attr, char_u *s, ...)
407 va_start(arglist, s);
408 vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL);
410 return msg_attr(IObuff, attr);
413 # endif /* HAVE_STDARG_H */
417 * Remember the last sourcing name/lnum used in an error message, so that it
418 * isn't printed each time when it didn't change.
420 static int last_sourcing_lnum = 0;
421 static char_u *last_sourcing_name = NULL;
424 * Reset the last used sourcing name/lnum. Makes sure it is displayed again
425 * for the next error message;
428 reset_last_sourcing()
430 vim_free(last_sourcing_name);
431 last_sourcing_name = NULL;
432 last_sourcing_lnum = 0;
436 * Return TRUE if "sourcing_name" differs from "last_sourcing_name".
439 other_sourcing_name()
441 if (sourcing_name != NULL)
443 if (last_sourcing_name != NULL)
444 return STRCMP(sourcing_name, last_sourcing_name) != 0;
451 * Get the message about the source, as used for an error message.
452 * Returns an allocated string with room for one more character.
453 * Returns NULL when no message is to be given.
460 if (sourcing_name != NULL && other_sourcing_name())
462 p = (char_u *)_("Error detected while processing %s:");
463 Buf = alloc((unsigned)(STRLEN(sourcing_name) + STRLEN(p)));
465 sprintf((char *)Buf, (char *)p, sourcing_name);
472 * Get the message about the source lnum, as used for an error message.
473 * Returns an allocated string with room for one more character.
474 * Returns NULL when no message is to be given.
481 /* lnum is 0 when executing a command from the command line
482 * argument, we don't want a line number then */
483 if (sourcing_name != NULL
484 && (other_sourcing_name() || sourcing_lnum != last_sourcing_lnum)
485 && sourcing_lnum != 0)
487 p = (char_u *)_("line %4ld:");
488 Buf = alloc((unsigned)(STRLEN(p) + 20));
490 sprintf((char *)Buf, (char *)p, (long)sourcing_lnum);
497 * Display name and line number for the source of an error.
498 * Remember the file name and line number, so that for the next error the info
499 * is only displayed if it changed.
508 p = get_emsg_source();
517 msg_attr(p, hl_attr(HLF_N));
519 last_sourcing_lnum = sourcing_lnum; /* only once for each line */
522 /* remember the last sourcing name printed, also when it's empty */
523 if (sourcing_name == NULL || other_sourcing_name())
525 vim_free(last_sourcing_name);
526 if (sourcing_name == NULL)
527 last_sourcing_name = NULL;
529 last_sourcing_name = vim_strsave(sourcing_name);
535 * Return TRUE if not giving error messages right now:
536 * If "emsg_off" is set: no error messages at the moment.
537 * If "msg" is in 'debug': do error message but without side effects.
538 * If "emsg_skip" is set: never do error messages.
543 if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL
544 && vim_strchr(p_debug, 't') == NULL)
554 * emsg() - display an error message
556 * Rings the bell, if appropriate, and calls message() to do the real work
557 * When terminal not initialized (yet) mch_errmsg(..) is used.
559 * return TRUE if wait_return not called
576 * If "emsg_severe" is TRUE: When an error exception is to be thrown,
577 * prefer this message over previous messages for the same command.
580 severe = emsg_severe;
584 /* Skip this if not giving error messages at the moment. */
588 if (!emsg_off || vim_strchr(p_debug, 't') != NULL)
592 * Cause a throw of an error exception if appropriate. Don't display
593 * the error message in this case. (If no matching catch clause will
594 * be found, the message will be displayed later on.) "ignore" is set
595 * when the message should be ignored completely (used for the
596 * interrupt message).
598 if (cause_errthrow(s, severe, &ignore) == TRUE)
605 /* set "v:errmsg", also when using ":silent! cmd" */
606 set_vim_var_string(VV_ERRMSG, s, -1);
610 * When using ":silent! cmd" ignore error messages.
611 * But do write it to the redirection file.
613 if (emsg_silent != 0)
616 p = get_emsg_source();
634 /* Reset msg_silent, an error causes messages to be switched back on. */
638 if (global_busy) /* break :global command */
642 beep_flush(); /* also includes flush_buffers() */
644 flush_buffers(FALSE); /* flush internal buffers */
645 did_emsg = TRUE; /* flag for DoOneCmd() */
648 emsg_on_display = TRUE; /* remember there is an error message */
649 ++msg_scroll; /* don't overwrite a previous message */
650 attr = hl_attr(HLF_E); /* set highlight mode for error messages */
651 if (msg_scrolled != 0)
652 need_wait_return = TRUE; /* needed in case emsg() is called after
653 * wait_return has reset need_wait_return
654 * and a redraw is expected because
655 * msg_scrolled is non-zero */
658 * Display name and line number for the source of the error.
663 * Display the error message itself.
665 msg_nowait = FALSE; /* wait for this msg */
666 return msg_attr(s, attr);
670 * Print an error message with one "%s" and one string argument.
676 return emsg3(s, a1, NULL);
679 /* emsg3() and emsgn() are in misc2.c to avoid warnings for the prototypes. */
685 EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
689 * Like msg(), but truncate to a single line if p_shm contains 't', or when
690 * "force" is TRUE. This truncates in another way as for normal messages.
691 * Careful: The string may be changed by msg_may_trunc()!
692 * Returns a pointer to the printed message, if wait_return() not called.
695 msg_trunc_attr(s, force, attr)
702 /* Add message to history before truncating */
703 add_msg_hist(s, -1, attr);
705 s = msg_may_trunc(force, s);
708 n = msg_attr(s, attr);
709 msg_hist_off = FALSE;
717 * Check if message "s" should be truncated at the start (for filenames).
718 * Return a pointer to where the truncated message starts.
719 * Note: May change the message by replacing a character with '<'.
722 msg_may_trunc(force, s)
729 room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
730 if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
731 && (n = (int)STRLEN(s) - room) > 0)
736 int size = vim_strsize(s);
738 /* There may be room anyway when there are multibyte chars. */
742 for (n = 0; size >= room; )
744 size -= (*mb_ptr2cells)(s + n);
745 n += (*mb_ptr2len)(s + n);
757 add_msg_hist(s, len, attr)
759 int len; /* -1 for undetermined length */
764 if (msg_hist_off || msg_silent != 0)
767 /* Don't let the message history get too big */
768 while (msg_hist_len > MAX_MSG_HIST_LEN)
769 (void)delete_first_msg();
771 /* allocate an entry and add the message at the end of the history */
772 p = (struct msg_hist *)alloc((int)sizeof(struct msg_hist));
776 len = (int)STRLEN(s);
777 /* remove leading and trailing newlines */
778 while (len > 0 && *s == '\n')
783 while (len > 0 && s[len - 1] == '\n')
785 p->msg = vim_strnsave(s, len);
788 if (last_msg_hist != NULL)
789 last_msg_hist->next = p;
791 if (first_msg_hist == NULL)
792 first_msg_hist = last_msg_hist;
798 * Delete the first (oldest) message from the history.
799 * Returns FAIL if there are no messages.
806 if (msg_hist_len <= 0)
809 first_msg_hist = p->next;
810 if (first_msg_hist == NULL)
811 last_msg_hist = NULL; /* history is empty */
819 * ":messages" command.
830 s = mch_getenv((char_u *)"LANG");
831 if (s != NULL && *s != NUL)
833 _("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
836 for (p = first_msg_hist; p != NULL && !got_int; p = p->next)
838 msg_attr(p->msg, p->attr);
840 msg_hist_off = FALSE;
843 #if defined(FEAT_CON_DIALOG) || defined(FIND_REPLACE_DIALOG) || defined(PROTO)
845 * Call this after prompting the user. This will avoid a hit-return message
851 need_wait_return = FALSE;
852 emsg_on_display = FALSE;
853 cmdline_row = msg_row;
860 * wait for the user to hit a key (normally a return)
861 * if 'redraw' is TRUE, clear and redraw the screen
862 * if 'redraw' is FALSE, just redraw the screen
863 * if 'redraw' is -1, don't redraw at all
877 /* If using ":silent cmd", don't wait for a return. Also don't set
878 * need_wait_return to do it later. */
883 * With the global command (and some others) we only need one return at the
884 * end. Adjust cmdline_row to avoid the next message overwriting the last one.
885 * When inside vgetc(), we can't wait for a typed character at all.
891 need_wait_return = TRUE;
893 cmdline_row = msg_row;
897 redir_off = TRUE; /* don't redirect this message */
901 c = CAR; /* just pretend CR was hit */
905 else if (exmode_active)
907 MSG_PUTS(" "); /* make sure the cursor is on the right line */
908 c = CAR; /* no need for a return in ex mode */
913 /* Make sure the hit-return prompt is on screen when 'guioptions' was
921 #ifdef USE_ON_FLY_SCROLL
922 dont_scroll = TRUE; /* disallow scrolling here */
928 /* Remember "got_int", if it is set vgetc() probably returns a
929 * CTRL-C, but we need to loop then. */
930 had_got_int = got_int;
932 /* Don't do mappings here, we put the character back in the
933 * typeahead buffer. */
937 if (had_got_int && !global_busy)
942 #ifdef FEAT_CLIPBOARD
943 /* Strange way to allow copying (yanking) a modeless selection at
944 * the hit-enter prompt. Use CTRL-Y, because the same is used in
945 * Cmdline-mode and it's harmless when there is no selection. */
946 if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
948 clip_copy_modeless_selection(TRUE);
954 * Allow scrolling back in the messages.
955 * Also accept scroll-down commands when messages fill the screen,
956 * to avoid that typing one 'j' too many makes the messages
961 if (c == 'b' || c == 'k' || c == 'u' || c == 'g' || c == K_UP)
963 /* scroll back to show older messages */
967 c = CAR; /* just pretend CR was hit */
977 else if (msg_scrolled > Rows - 2
978 && (c == 'j' || c == K_DOWN || c == 'd' || c == 'f'))
981 } while ((had_got_int && c == Ctrl_C)
984 || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
987 || c == K_LEFTDRAG || c == K_LEFTRELEASE
988 || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
989 || c == K_RIGHTDRAG || c == K_RIGHTRELEASE
990 || c == K_MOUSELEFT || c == K_MOUSERIGHT
991 || c == K_MOUSEDOWN || c == K_MOUSEUP
992 || (!mouse_has(MOUSE_RETURN)
993 && mouse_row < msg_row
995 || c == K_MIDDLEMOUSE
1004 * Avoid that the mouse-up event causes visual mode to start.
1006 if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
1007 || c == K_X1MOUSE || c == K_X2MOUSE)
1008 (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
1011 if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C)
1013 /* Put the character back in the typeahead buffer. Don't use the
1014 * stuff buffer, because lmaps wouldn't work. */
1015 ins_char_typebuf(c);
1016 do_redraw = TRUE; /* need a redraw even though there is
1023 * If the user hits ':', '?' or '/' we get a command line from the next
1026 if (c == ':' || c == '?' || c == '/')
1029 cmdline_row = msg_row;
1030 skip_redraw = TRUE; /* skip redraw once */
1035 * If the window size changed set_shellsize() will redraw the screen.
1036 * Otherwise the screen is only redrawn if 'redraw' is set and no ':'
1040 State = oldState; /* restore State before set_shellsize */
1046 #if defined(UNIX) || defined(VMS)
1048 * When switching screens, we need to output an extra newline on exit.
1050 if (swapping_screen() && !termcap_active)
1051 newline_on_exit = TRUE;
1054 need_wait_return = FALSE;
1055 did_wait_return = TRUE;
1056 emsg_on_display = FALSE; /* can delete error message now */
1057 lines_left = -1; /* reset lines_left at next msg_start() */
1058 reset_last_sourcing();
1059 if (keep_msg != NULL && vim_strsize(keep_msg) >=
1060 (Rows - cmdline_row - 1) * Columns + sc_col)
1063 keep_msg = NULL; /* don't redisplay message, it's too long */
1066 if (tmpState == SETWSIZE) /* got resize event while in vgetc() */
1068 starttermcap(); /* start termcap before redrawing */
1071 else if (!skip_redraw
1072 && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1)))
1074 starttermcap(); /* start termcap before redrawing */
1075 redraw_later(VALID);
1080 * Write the hit-return prompt.
1085 int save_p_more = p_more;
1087 p_more = FALSE; /* don't want see this message when scrolling back */
1088 if (msg_didout) /* start on a new line */
1091 MSG_PUTS(_("Interrupt: "));
1093 MSG_PUTS_ATTR(_("Press ENTER or type command to continue"), hl_attr(HLF_R));
1094 if (!msg_use_printf())
1096 p_more = save_p_more;
1100 * Set "keep_msg" to "s". Free the old value and check for NULL pointer.
1103 set_keep_msg(s, attr)
1108 if (s != NULL && msg_silent == 0)
1109 keep_msg = vim_strsave(s);
1112 keep_msg_more = FALSE;
1113 keep_msg_attr = attr;
1116 #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
1118 * If there currently is a message being displayed, set "keep_msg" to it, so
1119 * that it will be displayed again after redraw.
1122 set_keep_msg_from_hist()
1124 if (keep_msg == NULL && last_msg_hist != NULL && msg_scrolled == 0
1125 && (State & NORMAL))
1126 set_keep_msg(last_msg_hist->msg, last_msg_hist->attr);
1131 * Prepare for outputting characters in the command line.
1136 int did_return = FALSE;
1141 keep_msg = NULL; /* don't display old message now */
1147 /* Halfway an ":echo" command and getting an (error) message: clear
1148 * any text from the command. */
1149 need_clr_eos = FALSE;
1154 if (!msg_scroll && full_screen) /* overwrite last message */
1156 msg_row = cmdline_row;
1158 #ifdef FEAT_RIGHTLEFT
1159 cmdmsg_rl ? Columns - 1 :
1163 else if (msg_didout) /* start message on next line */
1167 if (exmode_active != EXMODE_NORMAL)
1168 cmdline_row = msg_row;
1170 if (!msg_didany || lines_left < 0)
1172 if (msg_silent == 0)
1174 msg_didout = FALSE; /* no output on current line yet */
1178 /* when redirecting, may need to start a new line. */
1180 redir_write((char_u *)"\n", -1);
1184 * Note that the current msg position is where messages start.
1189 lines_left = cmdline_row;
1197 msg_putchar_attr(c, 0);
1201 msg_putchar_attr(c, attr)
1206 char_u buf[MB_MAXBYTES + 1];
1214 buf[1] = K_SECOND(c);
1215 buf[2] = K_THIRD(c);
1221 buf[(*mb_char2bytes)(c, buf)] = NUL;
1227 msg_puts_attr(buf, attr);
1236 sprintf((char *)buf, "%ld", n);
1241 msg_home_replace(fname)
1244 msg_home_replace_attr(fname, 0);
1247 #if defined(FEAT_FIND_ID) || defined(PROTO)
1249 msg_home_replace_hl(fname)
1252 msg_home_replace_attr(fname, hl_attr(HLF_D));
1257 msg_home_replace_attr(fname, attr)
1263 name = home_replace_save(NULL, fname);
1265 msg_outtrans_attr(name, attr);
1270 * Output 'len' characters in 'str' (including NULs) with translation
1271 * if 'len' is -1, output upto a NUL character.
1272 * Use attributes 'attr'.
1273 * Return the number of characters it takes on the screen.
1279 return msg_outtrans_attr(str, 0);
1283 msg_outtrans_attr(str, attr)
1287 return msg_outtrans_len_attr(str, (int)STRLEN(str), attr);
1291 msg_outtrans_len(str, len)
1295 return msg_outtrans_len_attr(str, len, 0);
1299 * Output one character at "p". Return pointer to the next character.
1300 * Handles multi-byte characters.
1303 msg_outtrans_one(p, attr)
1310 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
1312 msg_outtrans_len_attr(p, l, attr);
1316 msg_puts_attr(transchar_byte(*p), attr);
1321 msg_outtrans_len_attr(msgstr, len, attr)
1327 char_u *str = msgstr;
1328 char_u *plain_start = msgstr;
1335 /* if MSG_HIST flag set, add message to history */
1336 if (attr & MSG_HIST)
1338 add_msg_hist(str, len, attr);
1343 /* If the string starts with a composing character first draw a space on
1344 * which the composing char can be drawn. */
1345 if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr)))
1346 msg_puts_attr((char_u *)" ", attr);
1350 * Go over the string. Special characters are translated and printed.
1351 * Normal characters are printed several at a time.
1357 /* Don't include composing chars after the end. */
1358 mb_l = utfc_ptr2len_len(str, len + 1);
1360 mb_l = (*mb_ptr2len)(str);
1363 if (has_mbyte && mb_l > 1)
1365 c = (*mb_ptr2char)(str);
1366 if (vim_isprintc(c))
1367 /* printable multi-byte char: count the cells. */
1368 retval += (*mb_ptr2cells)(str);
1371 /* unprintable multi-byte char: print the printable chars so
1372 * far and the translation of the unprintable char. */
1373 if (str > plain_start)
1374 msg_puts_attr_len(plain_start, (int)(str - plain_start),
1376 plain_start = str + mb_l;
1377 msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr);
1378 retval += char2cells(c);
1386 s = transchar_byte(*str);
1389 /* unprintable char: print the printable chars so far and the
1390 * translation of the unprintable char. */
1391 if (str > plain_start)
1392 msg_puts_attr_len(plain_start, (int)(str - plain_start),
1394 plain_start = str + 1;
1395 msg_puts_attr(s, attr == 0 ? hl_attr(HLF_8) : attr);
1396 retval += (int)STRLEN(s);
1404 if (str > plain_start)
1405 /* print the printable chars at the end */
1406 msg_puts_attr_len(plain_start, (int)(str - plain_start), attr);
1411 #if defined(FEAT_QUICKFIX) || defined(PROTO)
1417 static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB";
1419 arg = skipwhite(arg);
1420 for (i = 5; *arg && i >= 0; --i)
1421 if (*arg++ != str[i])
1426 for (i = 0; rs[i]; ++i)
1427 msg_putchar(rs[i] - 3);
1433 * Output the string 'str' upto a NUL character.
1434 * Return the number of characters it takes on the screen.
1436 * If K_SPECIAL is encountered, then it is taken in conjunction with the
1437 * following character and shown as <F1>, <S-Up> etc. Any other character
1438 * which is not printable shown in <> form.
1439 * If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>.
1440 * If a character is displayed in one of these special ways, is also
1441 * highlighted (its highlight name is '8' in the p_hl variable).
1442 * Otherwise characters are not highlighted.
1443 * This function is used to show mappings, where we want to see how to type
1444 * the character/string -- webb
1447 msg_outtrans_special(strstart, from)
1449 int from; /* TRUE for lhs of a mapping */
1451 char_u *str = strstart;
1457 attr = hl_attr(HLF_8);
1460 /* Leading and trailing spaces need to be displayed in <> form. */
1461 if ((str == strstart || str[1] == NUL) && *str == ' ')
1463 string = (char_u *)"<Space>";
1467 string = str2special(&str, from);
1468 len = vim_strsize(string);
1469 /* Highlight special keys */
1470 msg_puts_attr(string, len > 1
1472 && (*mb_ptr2len)(string) <= 1
1481 * Return the printable string for the key codes at "*sp".
1482 * Used for translating the lhs or rhs of a mapping to printable chars.
1483 * Advances "sp" to the next code.
1486 str2special(sp, from)
1488 int from; /* TRUE for lhs of mapping */
1491 static char_u buf[7];
1494 int special = FALSE;
1501 /* Try to un-escape a multi-byte character. Return the un-escaped
1502 * string if it is a multi-byte character. */
1503 p = mb_unescape(sp);
1510 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
1512 if (str[1] == KS_MODIFIER)
1518 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
1520 c = TO_SPECIAL(str[1], str[2]);
1522 if (c == K_ZERO) /* display <Nul> as ^@ */
1525 if (IS_SPECIAL(c) || modifiers) /* special key */
1531 /* For multi-byte characters check for an illegal byte. */
1532 if (has_mbyte && MB_BYTE2LEN(*str) > (*mb_ptr2len)(str))
1534 transchar_nonprint(buf, c);
1539 /* Make unprintable characters in <> form, also <M-Space> and <Tab>.
1540 * Use <Space> only for lhs of a mapping. */
1541 if (special || char2cells(c) > 1 || (from && c == ' '))
1542 return get_special_key_name(c, modifiers);
1549 * Translate a key sequence into special key names.
1552 str2specialbuf(sp, buf, len)
1562 s = str2special(&sp, FALSE);
1563 if ((int)(STRLEN(s) + STRLEN(buf)) < len)
1569 * print line for :print or :list command
1572 msg_prt_line(s, list)
1580 char_u *p_extra = NULL; /* init to make SASC shut up */
1583 char_u *trail = NULL;
1586 char_u buf[MB_MAXBYTES + 1];
1589 if (curwin->w_p_list)
1592 /* find start of trailing whitespace */
1593 if (list && lcs_trail)
1595 trail = s + STRLEN(s);
1596 while (trail > s && vim_iswhite(trail[-1]))
1600 /* output a space for an empty line, otherwise the line will be
1602 if (*s == NUL && !(list && lcs_eol != NUL))
1616 else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1)
1618 col += (*mb_ptr2cells)(s);
1619 mch_memmove(buf, s, (size_t)l);
1630 if (c == TAB && (!list || lcs_tab1))
1632 /* tab amount depends on current column */
1633 n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
1643 attr = hl_attr(HLF_8);
1646 else if (c == NUL && list && lcs_eol != NUL)
1648 p_extra = (char_u *)"";
1652 attr = hl_attr(HLF_AT);
1655 else if (c != NUL && (n = byte2cells(c)) > 1)
1658 p_extra = transchar_byte(c);
1661 /* Use special coloring to be able to distinguish <hex> from
1662 * the same in plain text. */
1663 attr = hl_attr(HLF_8);
1665 else if (c == ' ' && trail != NULL && s > trail)
1668 attr = hl_attr(HLF_8);
1675 msg_putchar_attr(c, attr);
1683 * Use screen_puts() to output one multi-byte character.
1684 * Return the pointer "s" advanced to the next character.
1687 screen_puts_mbyte(s, l, attr)
1694 msg_didout = TRUE; /* remember that line is not empty */
1695 cw = (*mb_ptr2cells)(s);
1697 #ifdef FEAT_RIGHTLEFT
1698 cmdmsg_rl ? msg_col <= 1 :
1700 msg_col == Columns - 1))
1702 /* Doesn't fit, print a highlighted '>' to fill it up. */
1703 msg_screen_putchar('>', hl_attr(HLF_AT));
1707 screen_puts_len(s, l, msg_row, msg_col, attr);
1708 #ifdef FEAT_RIGHTLEFT
1722 if (msg_col >= Columns)
1733 * Output a string to the screen at position msg_row, msg_col.
1734 * Update msg_row and msg_col for the next message.
1740 msg_puts_attr(s, 0);
1747 msg_puts_attr(s, hl_attr(HLF_T));
1751 * Show a message in such a way that it always fits in the line. Cut out a
1752 * part in the middle and replace it with "..." when necessary.
1753 * Does not handle multi-byte characters!
1756 msg_puts_long_attr(longstr, attr)
1760 msg_puts_long_len_attr(longstr, (int)STRLEN(longstr), attr);
1764 msg_puts_long_len_attr(longstr, len, attr)
1772 room = Columns - msg_col;
1773 if (len > room && room >= 20)
1775 slen = (room - 3) / 2;
1776 msg_outtrans_len_attr(longstr, slen, attr);
1777 msg_puts_attr((char_u *)"...", hl_attr(HLF_8));
1779 msg_outtrans_len_attr(longstr + len - slen, slen, attr);
1783 * Basic function for writing a message with highlight attributes.
1786 msg_puts_attr(s, attr)
1790 msg_puts_attr_len(s, -1, attr);
1794 * Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
1795 * When "maxlen" is -1 there is no maximum length.
1796 * When "maxlen" is >= 0 the message is not put in the history.
1799 msg_puts_attr_len(str, maxlen, attr)
1805 * If redirection is on, also write to the redirection file.
1807 redir_write(str, maxlen);
1810 * Don't print anything when using ":silent cmd".
1812 if (msg_silent != 0)
1815 /* if MSG_HIST flag set, add message to history */
1816 if ((attr & MSG_HIST) && maxlen < 0)
1818 add_msg_hist(str, -1, attr);
1823 * When writing something to the screen after it has scrolled, requires a
1824 * wait-return prompt later. Needed when scrolling, resetting
1825 * need_wait_return after some prompt, and then outputting something
1828 if (msg_scrolled != 0 && !msg_scrolled_ign)
1829 need_wait_return = TRUE;
1830 msg_didany = TRUE; /* remember that something was outputted */
1833 * If there is no valid screen, use fprintf so we can see error messages.
1834 * If termcap is not active, we may be writing in an alternate console
1835 * window, cursor positioning may not work correctly (window size may be
1836 * different, e.g. for Win32 console) or we just don't know where the
1839 if (msg_use_printf())
1840 msg_puts_printf(str, maxlen);
1842 msg_puts_display(str, maxlen, attr, FALSE);
1846 * The display part of msg_puts_attr_len().
1847 * May be called recursively to display scroll-back text.
1850 msg_puts_display(str, maxlen, attr, recurse)
1857 char_u *t_s = str; /* string from "t_s" to "s" is still todo */
1858 int t_col = 0; /* screen cells todo, 0 when "t_s" not used */
1863 char_u *sb_str = str;
1864 int sb_col = msg_col;
1868 did_wait_return = FALSE;
1869 while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL)
1872 * We are at the end of the screen line when:
1873 * - When outputting a newline.
1874 * - When outputting a character in the last column.
1876 if (!recurse && msg_row >= Rows - 1 && (*s == '\n' || (
1877 #ifdef FEAT_RIGHTLEFT
1881 || (*s == TAB && msg_col <= 7)
1883 || (has_mbyte && (*mb_ptr2cells)(s) > 1 && msg_col <= 2)
1888 (msg_col + t_col >= Columns - 1
1889 || (*s == TAB && msg_col + t_col >= ((Columns - 1) & ~7))
1891 || (has_mbyte && (*mb_ptr2cells)(s) > 1
1892 && msg_col + t_col >= Columns - 2)
1897 * The screen is scrolled up when at the last row (some terminals
1898 * scroll automatically, some don't. To avoid problems we scroll
1902 /* output postponed text */
1903 t_puts(&t_col, t_s, s, attr);
1905 /* When no more prompt and no more room, truncate here */
1906 if (msg_no_more && lines_left == 0)
1909 /* Scroll the screen up one line. */
1913 if (msg_col >= Columns) /* can happen after screen resize */
1914 msg_col = Columns - 1;
1916 /* Display char in last column before showing more-prompt. */
1918 #ifdef FEAT_RIGHTLEFT
1926 if (enc_utf8 && maxlen >= 0)
1927 /* avoid including composing chars after the end */
1928 l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
1930 l = (*mb_ptr2len)(s);
1931 s = screen_puts_mbyte(s, l, attr);
1935 msg_screen_putchar(*s++, attr);
1936 did_last_char = TRUE;
1939 did_last_char = FALSE;
1942 /* store text for scrolling back */
1943 store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
1946 need_wait_return = TRUE; /* may need wait_return in main() */
1947 if (must_redraw < VALID)
1948 must_redraw = VALID;
1949 redraw_cmdline = TRUE;
1950 if (cmdline_row > 0 && !exmode_active)
1954 * If screen is completely filled and 'more' is set then wait
1959 if (p_more && lines_left == 0 && State != HITRETURN
1960 && !msg_no_more && !exmode_active)
1962 #ifdef FEAT_CON_DIALOG
1963 if (do_more_prompt(NUL))
1964 s = confirm_msg_tail;
1966 (void)do_more_prompt(NUL);
1972 /* When we displayed a char in last column need to check if there
1979 || msg_col + t_col >= Columns
1981 || (has_mbyte && (*mb_ptr2cells)(s) > 1
1982 && msg_col + t_col >= Columns - 1)
1985 if (t_col > 0 && (wrap || *s == '\r' || *s == '\b'
1986 || *s == '\t' || *s == BELL))
1987 /* output any postponed text */
1988 t_puts(&t_col, t_s, s, attr);
1990 if (wrap && p_more && !recurse)
1991 /* store text for scrolling back */
1992 store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
1994 if (*s == '\n') /* go to next line */
1996 msg_didout = FALSE; /* remember that line is empty */
1997 #ifdef FEAT_RIGHTLEFT
1999 msg_col = Columns - 1;
2003 if (++msg_row >= Rows) /* safety check */
2006 else if (*s == '\r') /* go to column 0 */
2010 else if (*s == '\b') /* go to previous char */
2015 else if (*s == TAB) /* translate Tab into spaces */
2018 msg_screen_putchar(' ', attr);
2019 while (msg_col & 7);
2021 else if (*s == BELL) /* beep (from ":sh") */
2028 cw = (*mb_ptr2cells)(s);
2029 if (enc_utf8 && maxlen >= 0)
2030 /* avoid including composing chars after the end */
2031 l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
2033 l = (*mb_ptr2len)(s);
2041 /* When drawing from right to left or when a double-wide character
2042 * doesn't fit, draw a single character here. Otherwise collect
2043 * characters and draw them all at once later. */
2044 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
2046 # ifdef FEAT_RIGHTLEFT
2053 (cw > 1 && msg_col + t_col >= Columns - 1)
2059 s = screen_puts_mbyte(s, l, attr) - 1;
2062 msg_screen_putchar(*s, attr);
2067 /* postpone this character until later */
2081 /* output any postponed text */
2083 t_puts(&t_col, t_s, s, attr);
2084 if (p_more && !recurse)
2085 store_sb_text(&sb_str, s, attr, &sb_col, FALSE);
2091 * Scroll the screen up one line for displaying the next message line.
2097 /* Remove the cursor before scrolling, ScreenLines[] is going
2098 * to become invalid. */
2100 gui_undraw_cursor();
2102 /* scrolling up always works */
2103 screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL);
2105 if (!can_clear((char_u *)" "))
2107 /* Scrolling up doesn't result in the right background. Set the
2108 * background here. It's not efficient, but avoids that we have to do
2109 * it all over the code. */
2110 screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2112 /* Also clear the last char of the last but one line if it was not
2113 * cleared before to avoid a scroll-up. */
2114 if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1] == (sattr_T)-1)
2115 screen_fill((int)Rows - 2, (int)Rows - 1,
2116 (int)Columns - 1, (int)Columns, ' ', ' ', 0);
2121 * Increment "msg_scrolled".
2127 if (*get_vim_var_str(VV_SCROLLSTART) == NUL)
2129 char_u *p = sourcing_name;
2130 char_u *tofree = NULL;
2133 /* v:scrollstart is empty, set it to the script/function name and line
2136 p = (char_u *)_("Unknown");
2139 len = (int)STRLEN(p) + 40;
2140 tofree = alloc(len);
2143 vim_snprintf((char *)tofree, len, _("%s line %ld"),
2144 p, (long)sourcing_lnum);
2148 set_vim_var_string(VV_SCROLLSTART, p, -1);
2156 * To be able to scroll back at the "more" and "hit-enter" prompts we need to
2157 * store the displayed text and remember where screen lines start.
2159 typedef struct msgchunk_S msgchunk_T;
2162 msgchunk_T *sb_next;
2163 msgchunk_T *sb_prev;
2164 char sb_eol; /* TRUE when line ends after this text */
2165 int sb_msg_col; /* column in which text starts */
2166 int sb_attr; /* text attributes */
2167 char_u sb_text[1]; /* text to be displayed, actually longer */
2170 static msgchunk_T *last_msgchunk = NULL; /* last displayed text */
2172 static msgchunk_T *msg_sb_start __ARGS((msgchunk_T *mps));
2173 static msgchunk_T *disp_sb_line __ARGS((int row, msgchunk_T *smp));
2175 static int do_clear_sb_text = FALSE; /* clear text on next msg */
2178 * Store part of a printed message for displaying when scrolling back.
2181 store_sb_text(sb_str, s, attr, sb_col, finish)
2182 char_u **sb_str; /* start of string */
2183 char_u *s; /* just after string */
2186 int finish; /* line ends */
2190 if (do_clear_sb_text)
2193 do_clear_sb_text = FALSE;
2198 mp = (msgchunk_T *)alloc((int)(sizeof(msgchunk_T) + (s - *sb_str)));
2201 mp->sb_eol = finish;
2202 mp->sb_msg_col = *sb_col;
2204 vim_strncpy(mp->sb_text, *sb_str, s - *sb_str);
2206 if (last_msgchunk == NULL)
2213 mp->sb_prev = last_msgchunk;
2214 last_msgchunk->sb_next = mp;
2220 else if (finish && last_msgchunk != NULL)
2221 last_msgchunk->sb_eol = TRUE;
2228 * Finished showing messages, clear the scroll-back text on the next message.
2233 do_clear_sb_text = TRUE;
2237 * Clear any text remembered for scrolling back.
2238 * Called when redrawing the screen.
2245 while (last_msgchunk != NULL)
2247 mp = last_msgchunk->sb_prev;
2248 vim_free(last_msgchunk);
2261 /* Only show something if there is more than one line, otherwise it looks
2262 * weird, typing a command without output results in one line. */
2263 mp = msg_sb_start(last_msgchunk);
2264 if (mp == NULL || mp->sb_prev == NULL)
2268 do_more_prompt('G');
2274 * Move to the start of screen line in already displayed text.
2280 msgchunk_T *mp = mps;
2282 while (mp != NULL && mp->sb_prev != NULL && !mp->sb_prev->sb_eol)
2288 * Display a screen line from previously displayed text at row "row".
2289 * Returns a pointer to the text for the next line (can be NULL).
2292 disp_sb_line(row, smp)
2296 msgchunk_T *mp = smp;
2302 msg_col = mp->sb_msg_col;
2304 if (*p == '\n') /* don't display the line break */
2306 msg_puts_display(p, -1, mp->sb_attr, TRUE);
2307 if (mp->sb_eol || mp->sb_next == NULL)
2315 * Output any postponed text for msg_puts_attr_len().
2318 t_puts(t_col, t_s, s, attr)
2324 /* output postponed text */
2325 msg_didout = TRUE; /* remember that line is not empty */
2326 screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr);
2330 /* If the string starts with a composing character don't increment the
2331 * column position for it. */
2332 if (enc_utf8 && utf_iscomposing(utf_ptr2char(t_s)))
2335 if (msg_col >= Columns)
2343 * Returns TRUE when messages should be printed with mch_errmsg().
2344 * This is used when there is no valid screen, so we can see error messages.
2345 * If termcap is not active, we may be writing in an alternate console
2346 * window, cursor positioning may not work correctly (window size may be
2347 * different, e.g. for Win32 console) or we just don't know where the
2353 return (!msg_check_screen()
2354 #if defined(WIN3264) && !defined(FEAT_GUI_MSWIN)
2357 || (swapping_screen() && !termcap_active)
2362 * Print a message when there is no valid screen.
2365 msg_puts_printf(str, maxlen)
2374 if (!(silent_mode && p_verbose == 0))
2375 mch_settmode(TMODE_COOK); /* handle '\r' and '\n' correctly */
2377 while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
2379 if (!(silent_mode && p_verbose == 0))
2381 /* NL --> CR NL translation (for Unix, not for "--version") */
2382 /* NL --> CR translation (for Mac) */
2384 if (*s == '\n' && !info_message)
2386 #if defined(USE_CR) && !defined(MACOS_X_UNIX)
2391 if (info_message) /* informative message, not an error */
2392 mch_msg((char *)buf);
2394 mch_errmsg((char *)buf);
2397 /* primitive way to compute the current column */
2398 #ifdef FEAT_RIGHTLEFT
2401 if (*s == '\r' || *s == '\n')
2402 msg_col = Columns - 1;
2409 if (*s == '\r' || *s == '\n')
2416 msg_didout = TRUE; /* assume that line is not empty */
2419 if (!(silent_mode && p_verbose == 0))
2420 mch_settmode(TMODE_RAW);
2425 * Show the more-prompt and handle the user response.
2426 * This takes care of scrolling back and displaying previously displayed text.
2427 * When at hit-enter prompt "typed_char" is the already typed character,
2428 * otherwise it's NUL.
2429 * Returns TRUE when jumping ahead to "confirm_msg_tail".
2432 do_more_prompt(typed_char)
2435 int used_typed_char = typed_char;
2436 int oldState = State;
2438 #ifdef FEAT_CON_DIALOG
2442 msgchunk_T *mp_last = NULL;
2446 if (typed_char == 'G')
2448 /* "g<": Find first line on the last page. */
2449 mp_last = msg_sb_start(last_msgchunk);
2450 for (i = 0; i < Rows - 2 && mp_last != NULL
2451 && mp_last->sb_prev != NULL; ++i)
2452 mp_last = msg_sb_start(mp_last->sb_prev);
2459 if (typed_char == NUL)
2464 * Get a typed character directly from the user.
2466 if (used_typed_char != NUL)
2468 c = used_typed_char; /* was typed at hit-enter prompt */
2469 used_typed_char = NUL;
2472 c = get_keystroke();
2474 #if defined(FEAT_MENU) && defined(FEAT_GUI)
2477 int idx = get_menu_index(current_menu, ASKMORE);
2479 /* Used a menu. If it starts with CTRL-Y, it must
2480 * be a "Copy" for the clipboard. Otherwise
2481 * assume that we end */
2482 if (idx == MENU_INDEX_INVALID)
2484 c = *current_menu->strings[idx];
2485 if (c != NUL && current_menu->strings[idx][1] != NUL)
2486 ins_typebuf(current_menu->strings[idx] + 1,
2487 current_menu->noremap[idx], 0, TRUE,
2488 current_menu->silent[idx]);
2495 case BS: /* scroll one line back */
2502 case CAR: /* one extra line */
2509 case 'u': /* Up half a page */
2510 scroll = -(Rows / 2);
2513 case 'd': /* Down half a page */
2517 case 'b': /* one page back */
2519 scroll = -(Rows - 1);
2522 case ' ': /* one extra page */
2529 case 'g': /* all the way back to the start */
2533 case 'G': /* all the way to the end */
2535 lines_left = 999999;
2538 case ':': /* start new command line */
2539 #ifdef FEAT_CON_DIALOG
2540 if (!confirm_msg_used)
2543 /* Since got_int is set all typeahead will be flushed, but we
2544 * want to keep this ':', remember that in a special way. */
2545 typeahead_noflush(':');
2546 cmdline_row = Rows - 1; /* put ':' on this line */
2547 skip_redraw = TRUE; /* skip redraw once */
2548 need_wait_return = FALSE; /* don't wait in main() */
2551 case 'q': /* quit */
2554 #ifdef FEAT_CON_DIALOG
2555 if (confirm_msg_used)
2557 /* Jump to the choices of the dialog. */
2566 /* When there is some more output (wrapping line) display that
2567 * without another prompt. */
2568 lines_left = Rows - 1;
2571 #ifdef FEAT_CLIPBOARD
2573 /* Strange way to allow copying (yanking) a modeless
2574 * selection at the more prompt. Use CTRL-Y,
2575 * because the same is used in Cmdline-mode and at the
2576 * hit-enter prompt. However, scrolling one line up
2577 * might be expected... */
2578 if (clip_star.state == SELECT_DONE)
2579 clip_copy_modeless_selection(TRUE);
2582 default: /* no valid response */
2591 /* go to start of last line */
2592 if (mp_last == NULL)
2593 mp = msg_sb_start(last_msgchunk);
2594 else if (mp_last->sb_prev != NULL)
2595 mp = msg_sb_start(mp_last->sb_prev);
2599 /* go to start of line at top of the screen */
2600 for (i = 0; i < Rows - 2 && mp != NULL && mp->sb_prev != NULL;
2602 mp = msg_sb_start(mp->sb_prev);
2604 if (mp != NULL && mp->sb_prev != NULL)
2606 /* Find line to be displayed at top. */
2607 for (i = 0; i > scroll; --i)
2609 if (mp == NULL || mp->sb_prev == NULL)
2611 mp = msg_sb_start(mp->sb_prev);
2612 if (mp_last == NULL)
2613 mp_last = msg_sb_start(last_msgchunk);
2615 mp_last = msg_sb_start(mp_last->sb_prev);
2618 if (scroll == -1 && screen_ins_lines(0, 0, 1,
2619 (int)Rows, NULL) == OK)
2621 /* display line at top */
2622 (void)disp_sb_line(0, mp);
2626 /* redisplay all lines */
2628 for (i = 0; mp != NULL && i < Rows - 1; ++i)
2630 mp = disp_sb_line(i, mp);
2639 /* First display any text that we scrolled back. */
2640 while (scroll > 0 && mp_last != NULL)
2642 /* scroll up, display line at bottom */
2645 screen_fill((int)Rows - 2, (int)Rows - 1, 0,
2646 (int)Columns, ' ', ' ', 0);
2647 mp_last = disp_sb_line((int)Rows - 2, mp_last);
2654 /* displayed the requested text, more prompt again */
2655 screen_fill((int)Rows - 1, (int)Rows, 0,
2656 (int)Columns, ' ', ' ', 0);
2661 /* display more text, return to caller */
2662 lines_left = scroll;
2668 /* clear the --more-- message */
2669 screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2679 #ifdef FEAT_RIGHTLEFT
2681 msg_col = Columns - 1;
2684 #ifdef FEAT_CON_DIALOG
2691 #if defined(USE_MCH_ERRMSG) || defined(PROTO)
2701 * Give an error message. To be used when the screen hasn't been initialized
2702 * yet. When stderr can't be used, collect error messages until the GUI has
2703 * started and they can be displayed in a message box.
2711 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
2712 /* On Unix use stderr if it's a tty.
2713 * When not going to start the GUI also use stderr.
2714 * On Mac, when started from Finder, stderr is the console. */
2717 # ifdef MACOS_X_UNIX
2718 (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
2727 !(gui.in_use || gui.starting)
2731 fprintf(stderr, "%s", str);
2736 /* avoid a delay for a message that isn't there */
2737 emsg_on_display = FALSE;
2739 len = (int)STRLEN(str) + 1;
2740 if (error_ga.ga_growsize == 0)
2742 error_ga.ga_growsize = 80;
2743 error_ga.ga_itemsize = 1;
2745 if (ga_grow(&error_ga, len) == OK)
2747 mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len,
2748 (char_u *)str, len);
2750 /* remove CR characters, they are displayed */
2754 p = (char_u *)error_ga.ga_data + error_ga.ga_len;
2757 p = vim_strchr(p, '\r');
2764 --len; /* don't count the NUL at the end */
2765 error_ga.ga_len += len;
2770 * Give a message. To be used when the screen hasn't been initialized yet.
2771 * When there is no tty, collect messages until the GUI has started and they
2772 * can be displayed in a message box.
2778 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
2779 /* On Unix use stdout if we have a tty. This allows "vim -h | more" and
2780 * uses mch_errmsg() when started from the desktop.
2781 * When not going to start the GUI also use stdout.
2782 * On Mac, when started from Finder, stderr is the console. */
2785 # ifdef MACOS_X_UNIX
2786 (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
2795 !(gui.in_use || gui.starting)
2805 #endif /* USE_MCH_ERRMSG */
2808 * Put a character on the screen at the current message position and advance
2809 * to the next position. Only for printable ASCII!
2812 msg_screen_putchar(c, attr)
2816 msg_didout = TRUE; /* remember that line is not empty */
2817 screen_putchar(c, msg_row, msg_col, attr);
2818 #ifdef FEAT_RIGHTLEFT
2830 if (++msg_col >= Columns)
2843 char_u *s = (char_u *)_("-- More --");
2845 attr = hl_attr(HLF_M);
2846 screen_puts(s, (int)Rows - 1, 0, attr);
2848 screen_puts((char_u *)
2849 _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
2850 (int)Rows - 1, vim_strsize(s), attr);
2854 * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
2860 if (State == ASKMORE)
2862 msg_moremsg(TRUE); /* display --more-- message again */
2865 #ifdef FEAT_CON_DIALOG
2866 else if (State == CONFIRM)
2868 display_confirm_msg(); /* display ":confirm" message again */
2872 else if (State == EXTERNCMD)
2874 windgoto(msg_row, msg_col); /* put cursor back */
2876 else if (State == HITRETURN || State == SETWSIZE)
2878 if (msg_row == Rows - 1)
2880 /* Avoid drawing the "hit-enter" prompt below the previous one,
2881 * overwrite it. Esp. useful when regaining focus and a
2882 * FocusGained autocmd exists but didn't draw anything. */
2893 * msg_check_screen - check if the screen is initialized.
2894 * Also check msg_row and msg_col, if they are too big it may cause a crash.
2895 * While starting the GUI the terminal codes will be set for the GUI, but the
2896 * output goes to the terminal. Don't use the terminal codes then.
2901 if (!full_screen || !screen_valid(FALSE))
2904 if (msg_row >= Rows)
2906 if (msg_col >= Columns)
2907 msg_col = Columns - 1;
2912 * Clear from current message position to end of screen.
2913 * Skip this when ":silent" was used, no need to clear for redirection.
2918 if (msg_silent == 0)
2919 msg_clr_eos_force();
2923 * Clear from current message position to end of screen.
2924 * Note: msg_col is not updated, so we remember the end of the message
2930 if (msg_use_printf())
2932 if (full_screen) /* only when termcap codes are valid */
2935 out_str(T_CD); /* clear to end of display */
2937 out_str(T_CE); /* clear to end of line */
2942 #ifdef FEAT_RIGHTLEFT
2945 screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0);
2946 screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2951 screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns,
2953 screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2959 * Clear the command line.
2964 msg_row = cmdline_row;
2966 msg_clr_eos_force();
2970 * end putting a message on the screen
2971 * call wait_return if the message does not fit in the available space
2972 * return TRUE if wait_return not called.
2978 * if the string is larger than the window,
2979 * or the ruler option is set and we run into it,
2980 * we have to redraw the window.
2981 * Do not do this if we are abandoning the file or editing the command line.
2983 if (!exiting && need_wait_return && !(State & CMDLINE))
2993 * If the written message runs into the shown command or ruler, we have to
2994 * wait for hit-return and redraw the window later.
2999 if (msg_row == Rows - 1 && msg_col >= sc_col)
3001 need_wait_return = TRUE;
3002 redraw_cmdline = TRUE;
3007 * May write a string to the redirection file.
3008 * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
3011 redir_write(str, maxlen)
3016 static int cur_col = 0;
3018 /* Don't do anything for displaying prompts and the like. */
3023 * If 'verbosefile' is set write message in that file.
3024 * Must come before the rest because of updating "msg_col".
3026 if (*p_vfile != NUL)
3027 verbose_write(s, maxlen);
3031 /* If the string doesn't start with CR or NL, go to msg_col */
3032 if (*s != '\n' && *s != '\r')
3034 while (cur_col < msg_col)
3038 write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
3039 else if (redir_vname)
3040 var_redir_str((char_u *)" ", -1);
3043 fputs(" ", redir_fd);
3050 write_reg_contents(redir_reg, s, maxlen, TRUE);
3052 var_redir_str(s, maxlen);
3055 /* Adjust the current column */
3056 while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
3059 if (!redir_reg && !redir_vname && redir_fd != NULL)
3062 if (*s == '\r' || *s == '\n')
3064 else if (*s == '\t')
3065 cur_col += (8 - cur_col % 8);
3071 if (msg_silent != 0) /* should update msg_col */
3079 return redir_fd != NULL
3081 || redir_reg || redir_vname
3087 * Before giving verbose message.
3088 * Must always be called paired with verbose_leave()!
3093 if (*p_vfile != NUL)
3098 * After giving verbose message.
3099 * Must always be called paired with verbose_enter()!
3104 if (*p_vfile != NUL)
3105 if (--msg_silent < 0)
3110 * Like verbose_enter() and set msg_scroll when displaying the message.
3113 verbose_enter_scroll()
3115 if (*p_vfile != NUL)
3118 /* always scroll up, don't overwrite */
3123 * Like verbose_leave() and set cmdline_row when displaying the message.
3126 verbose_leave_scroll()
3128 if (*p_vfile != NUL)
3130 if (--msg_silent < 0)
3134 cmdline_row = msg_row;
3137 static FILE *verbose_fd = NULL;
3138 static int verbose_did_open = FALSE;
3141 * Called when 'verbosefile' is set: stop writing to the file.
3146 if (verbose_fd != NULL)
3151 verbose_did_open = FALSE;
3155 * Open the file 'verbosefile'.
3156 * Return FAIL or OK.
3161 if (verbose_fd == NULL && !verbose_did_open)
3163 /* Only give the error message once. */
3164 verbose_did_open = TRUE;
3166 verbose_fd = mch_fopen((char *)p_vfile, "a");
3167 if (verbose_fd == NULL)
3169 EMSG2(_(e_notopen), p_vfile);
3177 * Write a string to 'verbosefile'.
3178 * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
3181 verbose_write(str, maxlen)
3186 static int cur_col = 0;
3188 /* Open the file when called the first time. */
3189 if (verbose_fd == NULL)
3192 if (verbose_fd != NULL)
3194 /* If the string doesn't start with CR or NL, go to msg_col */
3195 if (*s != '\n' && *s != '\r')
3197 while (cur_col < msg_col)
3199 fputs(" ", verbose_fd);
3204 /* Adjust the current column */
3205 while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
3207 putc(*s, verbose_fd);
3208 if (*s == '\r' || *s == '\n')
3210 else if (*s == '\t')
3211 cur_col += (8 - cur_col % 8);
3220 * Give a warning message (for searching).
3221 * Use 'w' highlighting and may repeat the message after redrawing
3224 give_warning(message, hl)
3228 /* Don't do this for ":silent". */
3229 if (msg_silent != 0)
3232 /* Don't want a hit-enter prompt here. */
3236 set_vim_var_string(VV_WARNINGMSG, message, -1);
3241 keep_msg_attr = hl_attr(HLF_W);
3244 if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0)
3245 set_keep_msg(message, keep_msg_attr);
3246 msg_didout = FALSE; /* overwrite this message */
3247 msg_nowait = TRUE; /* don't wait for this message */
3254 * Advance msg cursor to column "col".
3260 if (msg_silent != 0) /* nothing to advance to */
3262 msg_col = col; /* for redirection, may fill it up later */
3265 if (col >= Columns) /* not enough room */
3267 #ifdef FEAT_RIGHTLEFT
3269 while (msg_col > Columns - col)
3273 while (msg_col < col)
3277 #if defined(FEAT_CON_DIALOG) || defined(PROTO)
3279 * Used for "confirm()" function, and the :confirm command prefix.
3280 * Versions which haven't got flexible dialogs yet, and console
3281 * versions, get this generic handler which uses the command line.
3284 * VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC
3285 * title = title string (can be NULL for default)
3286 * (neither used in console dialogs at the moment)
3288 * Format of the "buttons" string:
3289 * "Button1Name\nButton2Name\nButton3Name"
3290 * The first button should normally be the default/accept
3291 * The second button should be the 'Cancel' button
3292 * Other buttons- use your imagination!
3293 * A '&' in a button name becomes a shortcut, so each '&' should be before a
3297 do_dialog(type, title, message, buttons, dfltbutton, textfield)
3299 char_u *title UNUSED;
3303 char_u *textfield UNUSED; /* IObuff for inputdialog(), NULL
3313 /* Don't output anything in silent mode ("ex -s") */
3315 return dfltbutton; /* return default option */
3318 #ifdef FEAT_GUI_DIALOG
3319 /* When GUI is running and 'c' not in 'guioptions', use the GUI dialog */
3320 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
3322 c = gui_mch_dialog(type, title, message, buttons, dfltbutton,
3324 /* avoid a hit-enter prompt without clearing the cmdline */
3325 need_wait_return = FALSE;
3326 emsg_on_display = FALSE;
3327 cmdline_row = msg_row;
3329 /* Flush output to avoid that further messages and redrawing is done
3330 * in the wrong order. */
3345 * Since we wait for a keypress, don't make the
3346 * user press RETURN as well afterwards.
3349 hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
3351 if (hotkeys != NULL)
3355 /* Get a typed character directly from the user. */
3356 c = get_keystroke();
3359 case CAR: /* User accepts default option */
3361 retval = dfltbutton;
3363 case Ctrl_C: /* User aborts/cancels */
3367 default: /* Could be a hotkey? */
3368 if (c < 0) /* special keys are ignored here */
3370 /* Make the character lowercase, as chars in "hotkeys" are. */
3373 for (i = 0; hotkeys[i]; ++i)
3378 if ((*mb_ptr2char)(hotkeys + i) == c)
3380 i += (*mb_ptr2len)(hotkeys + i) - 1;
3384 if (hotkeys[i] == c)
3390 /* No hotkey match, so keep waiting */
3409 static int copy_char __ARGS((char_u *from, char_u *to, int lowercase));
3412 * Copy one character from "*from" to "*to", taking care of multi-byte
3413 * characters. Return the length of the character in bytes.
3416 copy_char(from, to, lowercase)
3419 int lowercase; /* make character lower case */
3429 c = MB_TOLOWER((*mb_ptr2char)(from));
3430 return (*mb_char2bytes)(c, to);
3434 len = (*mb_ptr2len)(from);
3435 mch_memmove(to, from, (size_t)len);
3443 *to = (char_u)TOLOWER_LOC(*from);
3451 * Format the dialog string, and display it at the bottom of
3452 * the screen. Return a string of hotkey chars (if defined) for
3453 * each 'button'. If a button has no hotkey defined, the first character of
3454 * the button is used.
3455 * The hotkeys can be multi-byte characters, but without combining chars.
3457 * Returns an allocated string with hotkeys, or NULL for error.
3460 msg_show_console_dialog(message, buttons, dfltbutton)
3467 # define HOTK_LEN (has_mbyte ? MB_MAXBYTES : 1)
3471 int lenhotkey = HOTK_LEN; /* count first button */
3472 char_u *hotk = NULL;
3473 char_u *msgp = NULL;
3474 char_u *hotkp = NULL;
3477 #define HAS_HOTKEY_LEN 30
3478 char_u has_hotkey[HAS_HOTKEY_LEN];
3479 int first_hotkey = FALSE; /* first char of button is hotkey */
3482 has_hotkey[0] = FALSE;
3485 * First loop: compute the size of memory to allocate.
3486 * Second loop: copy to the allocated memory.
3488 for (copy = 0; copy <= 1; ++copy)
3494 if (*r == DLG_BUTTON_SEP)
3499 *msgp++ = ' '; /* '\n' -> ', ' */
3501 /* advance to next hotkey and set default hotkey */
3504 hotkp += STRLEN(hotkp);
3508 hotkp[copy_char(r + 1, hotkp, TRUE)] = NUL;
3512 /* If no hotkey is specified first char is used. */
3513 if (idx < HAS_HOTKEY_LEN - 1 && !has_hotkey[++idx])
3514 first_hotkey = TRUE;
3518 len += 3; /* '\n' -> ', '; 'x' -> '(x)' */
3519 lenhotkey += HOTK_LEN; /* each button needs a hotkey */
3520 if (idx < HAS_HOTKEY_LEN - 1)
3521 has_hotkey[++idx] = FALSE;
3524 else if (*r == DLG_HOTKEY_CHAR || first_hotkey)
3526 if (*r == DLG_HOTKEY_CHAR)
3528 first_hotkey = FALSE;
3531 if (*r == DLG_HOTKEY_CHAR) /* '&&a' -> '&a' */
3536 *msgp++ = (dfltbutton == 1) ? '[' : '(';
3537 msgp += copy_char(r, msgp, FALSE);
3538 *msgp++ = (dfltbutton == 1) ? ']' : ')';
3540 /* redefine hotkey */
3541 hotkp[copy_char(r, hotkp, TRUE)] = NUL;
3546 ++len; /* '&a' -> '[a]' */
3547 if (idx < HAS_HOTKEY_LEN - 1)
3548 has_hotkey[idx] = TRUE;
3553 /* everything else copy literally */
3555 msgp += copy_char(r, msgp, FALSE);
3558 /* advance to the next character */
3570 len += (int)(STRLEN(message)
3571 + 2 /* for the NL's */
3573 + 3); /* for the ": " and NUL */
3574 lenhotkey++; /* for the NUL */
3576 /* If no hotkey is specified first char is used. */
3579 first_hotkey = TRUE;
3580 len += 2; /* "x" -> "[x]" */
3584 * Now allocate and load the strings
3586 vim_free(confirm_msg);
3587 confirm_msg = alloc(len);
3588 if (confirm_msg == NULL)
3591 hotk = alloc(lenhotkey);
3595 *confirm_msg = '\n';
3596 STRCPY(confirm_msg + 1, message);
3598 msgp = confirm_msg + 1 + STRLEN(message);
3601 /* Define first default hotkey. Keep the hotkey string NUL
3602 * terminated to avoid reading past the end. */
3603 hotkp[copy_char(buttons, hotkp, TRUE)] = NUL;
3605 /* Remember where the choices start, displaying starts here when
3606 * "hotkp" typed at the more prompt. */
3607 confirm_msg_tail = msgp;
3612 display_confirm_msg();
3617 * Display the ":confirm" message. Also called when screen resized.
3620 display_confirm_msg()
3622 /* avoid that 'q' at the more prompt truncates the message here */
3624 if (confirm_msg != NULL)
3625 msg_puts_attr(confirm_msg, hl_attr(HLF_M));
3629 #endif /* FEAT_CON_DIALOG */
3631 #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
3634 vim_dialog_yesno(type, title, message, dflt)
3641 title == NULL ? (char_u *)_("Question") : title,
3643 (char_u *)_("&Yes\n&No"), dflt, NULL) == 1)
3649 vim_dialog_yesnocancel(type, title, message, dflt)
3655 switch (do_dialog(type,
3656 title == NULL ? (char_u *)_("Question") : title,
3658 (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL))
3660 case 1: return VIM_YES;
3661 case 2: return VIM_NO;
3667 vim_dialog_yesnoallcancel(type, title, message, dflt)
3673 switch (do_dialog(type,
3674 title == NULL ? (char_u *)"Question" : title,
3676 (char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
3679 case 1: return VIM_YES;
3680 case 2: return VIM_NO;
3681 case 3: return VIM_ALL;
3682 case 4: return VIM_DISCARDALL;
3687 #endif /* FEAT_GUI_DIALOG || FEAT_CON_DIALOG */
3689 #if defined(FEAT_BROWSE) || defined(PROTO)
3691 * Generic browse function. Calls gui_mch_browse() when possible.
3692 * Later this may pop-up a non-GUI file selector (external command?).
3695 do_browse(flags, title, dflt, ext, initdir, filter, buf)
3696 int flags; /* BROWSE_SAVE and BROWSE_DIR */
3697 char_u *title; /* title for the window */
3698 char_u *dflt; /* default file name (may include directory) */
3699 char_u *ext; /* extension added */
3700 char_u *initdir; /* initial directory, NULL for current dir or
3701 when using path from "dflt" */
3702 char_u *filter; /* file name filter */
3703 buf_T *buf; /* buffer to read/write for */
3706 static char_u *last_dir = NULL; /* last used directory */
3707 char_u *tofree = NULL;
3708 int save_browse = cmdmod.browse;
3710 /* Must turn off browse to avoid that autocommands will get the
3712 cmdmod.browse = FALSE;
3714 if (title == NULL || *title == NUL)
3716 if (flags & BROWSE_DIR)
3717 title = (char_u *)_("Select Directory dialog");
3718 else if (flags & BROWSE_SAVE)
3719 title = (char_u *)_("Save File dialog");
3721 title = (char_u *)_("Open File dialog");
3724 /* When no directory specified, use default file name, default dir, buffer
3725 * dir, last dir or current dir */
3726 if ((initdir == NULL || *initdir == NUL) && dflt != NULL && *dflt != NUL)
3728 if (mch_isdir(dflt)) /* default file name is a directory */
3733 else if (gettail(dflt) != dflt) /* default file name includes a path */
3735 tofree = vim_strsave(dflt);
3739 *gettail(initdir) = NUL;
3740 dflt = gettail(dflt);
3745 if (initdir == NULL || *initdir == NUL)
3747 /* When 'browsedir' is a directory, use it */
3748 if (STRCMP(p_bsdir, "last") != 0
3749 && STRCMP(p_bsdir, "buffer") != 0
3750 && STRCMP(p_bsdir, "current") != 0
3751 && mch_isdir(p_bsdir))
3753 /* When saving or 'browsedir' is "buffer", use buffer fname */
3754 else if (((flags & BROWSE_SAVE) || *p_bsdir == 'b')
3755 && buf != NULL && buf->b_ffname != NULL)
3757 if (dflt == NULL || *dflt == NUL)
3758 dflt = gettail(curbuf->b_ffname);
3759 tofree = vim_strsave(curbuf->b_ffname);
3763 *gettail(initdir) = NUL;
3766 /* When 'browsedir' is "last", use dir from last browse */
3767 else if (*p_bsdir == 'l')
3769 /* When 'browsedir is "current", use current directory. This is the
3770 * default already, leave initdir empty. */
3774 if (gui.in_use) /* when this changes, also adjust f_has()! */
3778 && (filter = get_var_value((char_u *)"b:browsefilter")) == NULL
3779 && (filter = get_var_value((char_u *)"g:browsefilter")) == NULL
3782 filter = BROWSE_FILTER_DEFAULT;
3783 if (flags & BROWSE_DIR)
3785 # if defined(FEAT_GUI_GTK) || defined(WIN3264)
3786 /* For systems that have a directory dialog. */
3787 fname = gui_mch_browsedir(title, initdir);
3789 /* Generic solution for selecting a directory: select a file and
3790 * remove the file name. */
3791 fname = gui_mch_browse(0, title, dflt, ext, initdir, (char_u *)"");
3793 # if !defined(FEAT_GUI_GTK)
3794 /* Win32 adds a dummy file name, others return an arbitrary file
3795 * name. GTK+ 2 returns only the directory, */
3796 if (fname != NULL && *fname != NUL && !mch_isdir(fname))
3798 /* Remove the file name. */
3799 char_u *tail = gettail_sep(fname);
3802 *tail++ = '.'; /* use current dir */
3808 fname = gui_mch_browse(flags & BROWSE_SAVE,
3809 title, dflt, ext, initdir, filter);
3811 /* We hang around in the dialog for a while, the user might do some
3812 * things to our files. The Win32 dialog allows deleting or renaming
3813 * a file, check timestamps. */
3814 need_check_timestamps = TRUE;
3815 did_check_timestamps = FALSE;
3820 /* TODO: non-GUI file selector here */
3821 EMSG(_("E338: Sorry, no file browser in console mode"));
3825 /* keep the directory for next time */
3829 last_dir = vim_strsave(fname);
3830 if (last_dir != NULL && !(flags & BROWSE_DIR))
3832 *gettail(last_dir) = NUL;
3833 if (*last_dir == NUL)
3835 /* filename only returned, must be in current dir */
3837 last_dir = alloc(MAXPATHL);
3838 if (last_dir != NULL)
3839 mch_dirname(last_dir, MAXPATHL);
3845 cmdmod.browse = save_browse;
3851 #if defined(HAVE_STDARG_H) && defined(FEAT_EVAL)
3852 static char *e_printf = N_("E766: Insufficient arguments for printf()");
3854 static long tv_nr __ARGS((typval_T *tvs, int *idxp));
3855 static char *tv_str __ARGS((typval_T *tvs, int *idxp));
3857 static double tv_float __ARGS((typval_T *tvs, int *idxp));
3861 * Get number argument from "idxp" entry in "tvs". First entry is 1.
3868 int idx = *idxp - 1;
3872 if (tvs[idx].v_type == VAR_UNKNOWN)
3877 n = get_tv_number_chk(&tvs[idx], &err);
3885 * Get string argument from "idxp" entry in "tvs". First entry is 1.
3886 * Returns NULL for an error.
3893 int idx = *idxp - 1;
3896 if (tvs[idx].v_type == VAR_UNKNOWN)
3901 s = (char *)get_tv_string_chk(&tvs[idx]);
3908 * Get float argument from "idxp" entry in "tvs". First entry is 1.
3915 int idx = *idxp - 1;
3918 if (tvs[idx].v_type == VAR_UNKNOWN)
3923 if (tvs[idx].v_type == VAR_FLOAT)
3924 f = tvs[idx].vval.v_float;
3925 else if (tvs[idx].v_type == VAR_NUMBER)
3926 f = tvs[idx].vval.v_number;
3928 EMSG(_("E807: Expected Float argument for printf()"));
3936 * This code was included to provide a portable vsnprintf() and snprintf().
3937 * Some systems may provide their own, but we always use this one for
3940 * This code is based on snprintf.c - a portable implementation of snprintf
3941 * by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06.
3942 * Included with permission. It was heavily modified to fit in Vim.
3943 * The original code, including useful comments, can be found here:
3944 * http://www.ijs.si/software/snprintf/
3946 * This snprintf() only supports the following conversion specifiers:
3947 * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
3948 * with flags: '-', '+', ' ', '0' and '#'.
3949 * An asterisk is supported for field width as well as precision.
3951 * Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'.
3953 * Length modifiers 'h' (short int) and 'l' (long int) are supported.
3954 * 'll' (long long int) is not supported.
3956 * The locale is not used, the string is used as a byte string. This is only
3957 * relevant for double-byte encodings where the second byte may be '%'.
3959 * It is permitted for "str_m" to be zero, and it is permitted to specify NULL
3960 * pointer for resulting string argument if "str_m" is zero (as per ISO C99).
3962 * The return value is the number of characters which would be generated
3963 * for the given input, excluding the trailing null. If this value
3964 * is greater or equal to "str_m", not all characters from the result
3965 * have been stored in str, output bytes beyond the ("str_m"-1) -th character
3966 * are discarded. If "str_m" is greater than zero it is guaranteed
3967 * the resulting string will be null-terminated.
3971 * When va_list is not supported we only define vim_snprintf().
3973 * vim_vsnprintf() can be invoked with either "va_list" or a list of
3974 * "typval_T". When the latter is not used it must be NULL.
3977 /* When generating prototypes all of this is skipped, cproto doesn't
3978 * understand this. */
3981 # ifdef HAVE_STDARG_H
3982 /* Like vim_vsnprintf() but append to the string. */
3984 vim_snprintf_add(char *str, size_t str_m, char *fmt, ...)
3988 size_t len = STRLEN(str);
3994 space = str_m - len;
3996 str_l = vim_vsnprintf(str + len, space, fmt, ap, NULL);
4001 /* Like vim_vsnprintf() but append to the string. */
4003 vim_snprintf_add(str, str_m, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
4007 long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
4009 size_t len = STRLEN(str);
4015 space = str_m - len;
4016 return vim_vsnprintf(str + len, space, fmt,
4017 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
4021 # ifdef HAVE_STDARG_H
4023 vim_snprintf(char *str, size_t str_m, char *fmt, ...)
4029 str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL);
4035 vim_vsnprintf(str, str_m, fmt, ap, tvs)
4037 /* clumsy way to work around missing va_list */
4038 # define get_a_arg(i) (++i, i == 2 ? a1 : i == 3 ? a2 : i == 4 ? a3 : i == 5 ? a4 : i == 6 ? a5 : i == 7 ? a6 : i == 8 ? a7 : i == 9 ? a8 : i == 10 ? a9 : a10)
4045 vim_snprintf(str, str_m, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
4050 # ifdef HAVE_STDARG_H
4054 long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
4067 char *q = strchr(p + 1, '%');
4068 size_t n = (q == NULL) ? STRLEN(p) : (size_t)(q - p);
4070 /* Copy up to the next '%' or NUL without any changes. */
4073 size_t avail = str_m - str_l;
4075 mch_memmove(str + str_l, p, n > avail ? avail : n);
4082 size_t min_field_width = 0, precision = 0;
4083 int zero_padding = 0, precision_specified = 0, justify_left = 0;
4084 int alternate_form = 0, force_sign = 0;
4086 /* If both the ' ' and '+' flags appear, the ' ' flag should be
4088 int space_for_positive = 1;
4090 /* allowed values: \0, h, l, L */
4091 char length_modifier = '\0';
4093 /* temporary buffer for simple numeric->string conversion */
4095 # define TMP_LEN 350 /* On my system 1e308 is the biggest number possible.
4096 * That sounds reasonable to use as the maximum
4103 /* string address in case of string argument */
4106 /* natural field width of arg without padding and sign */
4109 /* unsigned char argument value - only defined for c conversion.
4110 * N.B. standard explicitly states the char argument for the c
4111 * conversion is unsigned */
4112 unsigned char uchar_arg;
4114 /* number of zeros to be inserted for numeric conversions as
4115 * required by the precision or minimal field width */
4116 size_t number_of_zeros_to_pad = 0;
4118 /* index into tmp where zero padding is to be inserted */
4119 size_t zero_padding_insertion_ind = 0;
4121 /* current conversion specifier character */
4122 char fmt_spec = '\0';
4128 while (*p == '0' || *p == '-' || *p == '+' || *p == ' '
4129 || *p == '#' || *p == '\'')
4133 case '0': zero_padding = 1; break;
4134 case '-': justify_left = 1; break;
4135 case '+': force_sign = 1; space_for_positive = 0; break;
4136 case ' ': force_sign = 1;
4137 /* If both the ' ' and '+' flags appear, the ' '
4138 * flag should be ignored */
4140 case '#': alternate_form = 1; break;
4145 /* If the '0' and '-' flags both appear, the '0' flag should be
4148 /* parse field width */
4155 #ifndef HAVE_STDARG_H
4158 # if defined(FEAT_EVAL)
4159 tvs != NULL ? tv_nr(tvs, &arg_idx) :
4164 min_field_width = j;
4167 min_field_width = -j;
4171 else if (VIM_ISDIGIT((int)(*p)))
4173 /* size_t could be wider than unsigned int; make sure we treat
4174 * argument like common implementations do */
4175 unsigned int uj = *p++ - '0';
4177 while (VIM_ISDIGIT((int)(*p)))
4178 uj = 10 * uj + (unsigned int)(*p++ - '0');
4179 min_field_width = uj;
4182 /* parse precision */
4186 precision_specified = 1;
4192 #ifndef HAVE_STDARG_H
4195 # if defined(FEAT_EVAL)
4196 tvs != NULL ? tv_nr(tvs, &arg_idx) :
4205 precision_specified = 0;
4209 else if (VIM_ISDIGIT((int)(*p)))
4211 /* size_t could be wider than unsigned int; make sure we
4212 * treat argument like common implementations do */
4213 unsigned int uj = *p++ - '0';
4215 while (VIM_ISDIGIT((int)(*p)))
4216 uj = 10 * uj + (unsigned int)(*p++ - '0');
4221 /* parse 'h', 'l' and 'll' length modifiers */
4222 if (*p == 'h' || *p == 'l')
4224 length_modifier = *p;
4226 if (length_modifier == 'l' && *p == 'l')
4228 /* double l = long long */
4229 length_modifier = 'l'; /* treat it as a single 'l' */
4235 /* common synonyms: */
4238 case 'i': fmt_spec = 'd'; break;
4239 case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
4240 case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
4241 case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
4242 case 'F': fmt_spec = 'f'; break;
4246 /* get parameter value, do initial processing */
4249 /* '%' and 'c' behave similar to 's' regarding flags and field
4254 length_modifier = '\0';
4267 #ifndef HAVE_STDARG_H
4270 # if defined(FEAT_EVAL)
4271 tvs != NULL ? tv_nr(tvs, &arg_idx) :
4275 /* standard demands unsigned char */
4276 uchar_arg = (unsigned char)j;
4277 str_arg = (char *)&uchar_arg;
4283 #ifndef HAVE_STDARG_H
4284 (char *)get_a_arg(arg_idx);
4286 # if defined(FEAT_EVAL)
4287 tvs != NULL ? tv_str(tvs, &arg_idx) :
4291 if (str_arg == NULL)
4296 /* make sure not to address string beyond the specified
4298 else if (!precision_specified)
4299 str_arg_l = strlen(str_arg);
4300 /* truncate string if necessary as requested by precision */
4301 else if (precision == 0)
4305 /* Don't put the #if inside memchr(), it can be a
4308 char *q = memchr(str_arg, '\0', precision);
4310 /* memchr on HP does not like n > 2^31 !!! */
4311 char *q = memchr(str_arg, '\0',
4312 precision <= (size_t)0x7fffffffL ? precision
4313 : (size_t)0x7fffffffL);
4315 str_arg_l = (q == NULL) ? precision
4316 : (size_t)(q - str_arg);
4325 case 'd': case 'u': case 'o': case 'x': case 'X': case 'p':
4327 /* NOTE: the u, o, x, X and p conversion specifiers
4328 * imply the value is unsigned; d implies a signed
4331 /* 0 if numeric argument is zero (or if pointer is
4332 * NULL for 'p'), +1 if greater than zero (or nonzero
4333 * for unsigned arguments), -1 if negative (unsigned
4334 * argument is never negative) */
4337 /* only defined for length modifier h, or for no
4338 * length modifiers */
4340 unsigned int uint_arg = 0;
4342 /* only defined for length modifier l */
4343 long int long_arg = 0;
4344 unsigned long int ulong_arg = 0;
4346 /* pointer argument value -only defined for p
4348 void *ptr_arg = NULL;
4350 if (fmt_spec == 'p')
4352 length_modifier = '\0';
4354 #ifndef HAVE_STDARG_H
4355 (void *)get_a_arg(arg_idx);
4357 # if defined(FEAT_EVAL)
4358 tvs != NULL ? (void *)tv_str(tvs, &arg_idx) :
4362 if (ptr_arg != NULL)
4365 else if (fmt_spec == 'd')
4368 switch (length_modifier)
4372 /* char and short arguments are passed as int. */
4374 #ifndef HAVE_STDARG_H
4377 # if defined(FEAT_EVAL)
4378 tvs != NULL ? tv_nr(tvs, &arg_idx) :
4384 else if (int_arg < 0)
4389 #ifndef HAVE_STDARG_H
4392 # if defined(FEAT_EVAL)
4393 tvs != NULL ? tv_nr(tvs, &arg_idx) :
4395 va_arg(ap, long int);
4399 else if (long_arg < 0)
4407 switch (length_modifier)
4412 #ifndef HAVE_STDARG_H
4415 # if defined(FEAT_EVAL)
4416 tvs != NULL ? (unsigned)
4417 tv_nr(tvs, &arg_idx) :
4419 va_arg(ap, unsigned int);
4426 #ifndef HAVE_STDARG_H
4429 # if defined(FEAT_EVAL)
4430 tvs != NULL ? (unsigned long)
4431 tv_nr(tvs, &arg_idx) :
4433 va_arg(ap, unsigned long int);
4445 * For d, i, u, o, x, and X conversions, if precision is
4446 * specified, the '0' flag should be ignored. This is so
4447 * with Solaris 2.6, Digital UNIX 4.0, HPUX 10, Linux,
4448 * FreeBSD, NetBSD; but not with Perl.
4450 if (precision_specified)
4452 if (fmt_spec == 'd')
4454 if (force_sign && arg_sign >= 0)
4455 tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
4456 /* leave negative numbers for sprintf to handle, to
4457 * avoid handling tricky cases like (short int)-32768 */
4459 else if (alternate_form)
4462 && (fmt_spec == 'x' || fmt_spec == 'X') )
4464 tmp[str_arg_l++] = '0';
4465 tmp[str_arg_l++] = fmt_spec;
4467 /* alternate form should have no effect for p
4468 * conversion, but ... */
4471 zero_padding_insertion_ind = str_arg_l;
4472 if (!precision_specified)
4473 precision = 1; /* default precision is 1 */
4474 if (precision == 0 && arg_sign == 0)
4476 /* When zero value is formatted with an explicit
4477 * precision 0, the resulting formatted string is
4478 * empty (d, i, u, o, x, X, p). */
4485 /* construct a simple format string for sprintf */
4487 if (!length_modifier)
4489 else if (length_modifier == '2')
4495 f[f_l++] = length_modifier;
4496 f[f_l++] = fmt_spec;
4499 if (fmt_spec == 'p')
4500 str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg);
4501 else if (fmt_spec == 'd')
4504 switch (length_modifier)
4507 case 'h': str_arg_l += sprintf(
4508 tmp + str_arg_l, f, int_arg);
4510 case 'l': str_arg_l += sprintf(
4511 tmp + str_arg_l, f, long_arg);
4518 switch (length_modifier)
4521 case 'h': str_arg_l += sprintf(
4522 tmp + str_arg_l, f, uint_arg);
4524 case 'l': str_arg_l += sprintf(
4525 tmp + str_arg_l, f, ulong_arg);
4530 /* include the optional minus sign and possible
4531 * "0x" in the region before the zero padding
4532 * insertion point */
4533 if (zero_padding_insertion_ind < str_arg_l
4534 && tmp[zero_padding_insertion_ind] == '-')
4535 zero_padding_insertion_ind++;
4536 if (zero_padding_insertion_ind + 1 < str_arg_l
4537 && tmp[zero_padding_insertion_ind] == '0'
4538 && (tmp[zero_padding_insertion_ind + 1] == 'x'
4539 || tmp[zero_padding_insertion_ind + 1] == 'X'))
4540 zero_padding_insertion_ind += 2;
4544 size_t num_of_digits = str_arg_l
4545 - zero_padding_insertion_ind;
4547 if (alternate_form && fmt_spec == 'o'
4548 /* unless zero is already the first
4550 && !(zero_padding_insertion_ind < str_arg_l
4551 && tmp[zero_padding_insertion_ind] == '0'))
4553 /* assure leading zero for alternate-form
4555 if (!precision_specified
4556 || precision < num_of_digits + 1)
4558 /* precision is increased to force the
4559 * first character to be zero, except if a
4560 * zero value is formatted with an
4561 * explicit precision of zero */
4562 precision = num_of_digits + 1;
4563 precision_specified = 1;
4566 /* zero padding to specified precision? */
4567 if (num_of_digits < precision)
4568 number_of_zeros_to_pad = precision - num_of_digits;
4570 /* zero padding to specified minimal field width? */
4571 if (!justify_left && zero_padding)
4573 int n = (int)(min_field_width - (str_arg_l
4574 + number_of_zeros_to_pad));
4576 number_of_zeros_to_pad += n;
4588 /* Floating point. */
4593 int remove_trailing_zeroes = FALSE;
4596 # ifndef HAVE_STDARG_H
4599 # if defined(FEAT_EVAL)
4600 tvs != NULL ? tv_float(tvs, &arg_idx) :
4604 abs_f = f < 0 ? -f : f;
4606 if (fmt_spec == 'g' || fmt_spec == 'G')
4608 /* Would be nice to use %g directly, but it prints
4609 * "1.0" as "1", we don't want that. */
4610 if ((abs_f >= 0.001 && abs_f < 10000000.0)
4614 fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
4615 remove_trailing_zeroes = TRUE;
4618 if (fmt_spec == 'f' &&
4626 /* Avoid a buffer overflow */
4634 if (precision_specified)
4636 size_t max_prec = TMP_LEN - 10;
4638 /* Make sure we don't get more digits than we
4640 if (fmt_spec == 'f' && abs_f > 1.0)
4641 max_prec -= (size_t)log10(abs_f);
4642 if (precision > max_prec)
4643 precision = max_prec;
4644 l += sprintf(format + 1, ".%d", (int)precision);
4646 format[l] = fmt_spec;
4647 format[l + 1] = NUL;
4648 str_arg_l = sprintf(tmp, format, f);
4650 if (remove_trailing_zeroes)
4655 /* Using %g or %G: remove superfluous zeroes. */
4656 if (fmt_spec == 'f')
4657 tp = tmp + str_arg_l - 1;
4660 tp = (char *)vim_strchr((char_u *)tmp,
4661 fmt_spec == 'e' ? 'e' : 'E');
4664 /* Remove superfluous '+' and leading
4665 * zeroes from the exponent. */
4668 /* Change "1.0e+07" to "1.0e07" */
4669 STRMOVE(tp + 1, tp + 2);
4672 i = (tp[1] == '-') ? 2 : 1;
4673 while (tp[i] == '0')
4675 /* Change "1.0e07" to "1.0e7" */
4676 STRMOVE(tp + i, tp + i + 1);
4683 if (tp != NULL && !precision_specified)
4684 /* Remove trailing zeroes, but keep the one
4685 * just after a dot. */
4686 while (tp > tmp + 2 && *tp == '0'
4689 STRMOVE(tp, tp + 1);
4698 /* Be consistent: some printf("%e") use 1.0e+12
4699 * and some 1.0e+012. Remove one zero in the last
4701 tp = (char *)vim_strchr((char_u *)tmp,
4702 fmt_spec == 'e' ? 'e' : 'E');
4703 if (tp != NULL && (tp[1] == '+' || tp[1] == '-')
4705 && vim_isdigit(tp[3])
4706 && vim_isdigit(tp[4]))
4708 STRMOVE(tp + 2, tp + 3);
4719 /* unrecognized conversion specifier, keep format string
4721 zero_padding = 0; /* turn zero padding off for non-numeric
4724 min_field_width = 0; /* reset flags */
4726 /* discard the unrecognized conversion, just keep *
4727 * the unrecognized conversion character */
4731 str_arg_l++; /* include invalid conversion specifier
4732 unchanged if not at end-of-string */
4737 p++; /* step over the just processed conversion specifier */
4739 /* insert padding to the left as requested by min_field_width;
4740 * this does not include the zero padding in case of numerical
4744 /* left padding with blank or zero */
4745 int pn = (int)(min_field_width - (str_arg_l + number_of_zeros_to_pad));
4751 size_t avail = str_m - str_l;
4753 vim_memset(str + str_l, zero_padding ? '0' : ' ',
4754 (size_t)pn > avail ? avail
4761 /* zero padding as requested by the precision or by the minimal
4762 * field width for numeric conversions required? */
4763 if (number_of_zeros_to_pad == 0)
4765 /* will not copy first part of numeric right now, *
4766 * force it to be copied later in its entirety */
4767 zero_padding_insertion_ind = 0;
4771 /* insert first part of numerics (sign or '0x') before zero
4773 int zn = (int)zero_padding_insertion_ind;
4779 size_t avail = str_m - str_l;
4781 mch_memmove(str + str_l, str_arg,
4782 (size_t)zn > avail ? avail
4788 /* insert zero padding as requested by the precision or min
4790 zn = (int)number_of_zeros_to_pad;
4795 size_t avail = str_m-str_l;
4797 vim_memset(str + str_l, '0',
4798 (size_t)zn > avail ? avail
4805 /* insert formatted string
4806 * (or as-is conversion specifier for unknown conversions) */
4808 int sn = (int)(str_arg_l - zero_padding_insertion_ind);
4814 size_t avail = str_m - str_l;
4816 mch_memmove(str + str_l,
4817 str_arg + zero_padding_insertion_ind,
4818 (size_t)sn > avail ? avail : (size_t)sn);
4824 /* insert right padding */
4827 /* right blank padding to the field width */
4828 int pn = (int)(min_field_width
4829 - (str_arg_l + number_of_zeros_to_pad));
4835 size_t avail = str_m - str_l;
4837 vim_memset(str + str_l, ' ',
4838 (size_t)pn > avail ? avail
4849 /* make sure the string is nul-terminated even at the expense of
4850 * overwriting the last character (shouldn't happen, but just in case)
4852 str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0';
4855 #ifdef HAVE_STDARG_H
4856 if (tvs != NULL && tvs[arg_idx - 1].v_type != VAR_UNKNOWN)
4857 EMSG(_("E767: Too many arguments to printf()"));
4860 /* Return the number of characters formatted (excluding trailing nul
4861 * character), that is, the number of characters that would have been
4862 * written to the buffer if it were large enough. */