xref: /vim-8.2.3635/src/message.c (revision 3577c6fa)
1 /* vi:set ts=8 sts=4 sw=4:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * message.c: functions for displaying messages on the command line
12  */
13 
14 #define MESSAGE_FILE		/* don't include prototype for smsg() */
15 
16 #include "vim.h"
17 
18 #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
19 # include <math.h>
20 #endif
21 
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));
28 #ifdef FEAT_MBYTE
29 static char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr));
30 #endif
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 */
48 #endif
49 
50 struct msg_hist
51 {
52     struct msg_hist	*next;
53     char_u		*msg;
54     int			attr;
55 };
56 
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;
60 
61 /*
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
93  *		    main_loop().
94  *		    This is an allocated string or NULL when not used.
95  */
96 
97 /*
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
101  */
102     int
103 msg(s)
104     char_u	*s;
105 {
106     return msg_attr_keep(s, 0, FALSE);
107 }
108 
109 #if defined(FEAT_EVAL) || defined(FEAT_X11) || defined(USE_XSMP) \
110     || defined(PROTO)
111 /*
112  * Like msg() but keep it silent when 'verbosefile' is set.
113  */
114     int
115 verb_msg(s)
116     char_u	*s;
117 {
118     int		n;
119 
120     verbose_enter();
121     n = msg_attr_keep(s, 0, FALSE);
122     verbose_leave();
123 
124     return n;
125 }
126 #endif
127 
128     int
129 msg_attr(s, attr)
130     char_u	*s;
131     int		attr;
132 {
133     return msg_attr_keep(s, attr, FALSE);
134 }
135 
136     int
137 msg_attr_keep(s, attr, keep)
138     char_u	*s;
139     int		attr;
140     int		keep;	    /* TRUE: set keep_msg if it doesn't scroll */
141 {
142     static int	entered = 0;
143     int		retval;
144     char_u	*buf = NULL;
145 
146 #ifdef FEAT_EVAL
147     if (attr == 0)
148 	set_vim_var_string(VV_STATUSMSG, s, -1);
149 #endif
150 
151     /*
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.
155      */
156     if (entered >= 3)
157 	return TRUE;
158     ++entered;
159 
160     /* Add message to history (unless it's a repeated kept message or a
161      * truncated message) */
162     if (s != keep_msg
163 	    || (*s != '<'
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);
168 
169     /* When displaying keep_msg, don't let msg_start() free it, caller must do
170      * that. */
171     if (s == keep_msg)
172 	keep_msg = NULL;
173 
174     /* Truncate the message if needed. */
175     msg_start();
176     buf = msg_strtrunc(s, FALSE);
177     if (buf != NULL)
178 	s = buf;
179 
180     msg_outtrans_attr(s, attr);
181     msg_clr_eos();
182     retval = msg_end();
183 
184     if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1)
185 							   * Columns + sc_col)
186 	set_keep_msg(s, 0);
187 
188     vim_free(buf);
189     --entered;
190     return retval;
191 }
192 
193 /*
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.
196  */
197     char_u *
198 msg_strtrunc(s, force)
199     char_u	*s;
200     int		force;	    /* always truncate */
201 {
202     char_u	*buf = NULL;
203     int		len;
204     int		room;
205 
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)
209     {
210 	len = vim_strsize(s);
211 	if (msg_scrolled != 0)
212 	    /* Use all the columns. */
213 	    room = (int)(Rows - msg_row) * Columns - 1;
214 	else
215 	    /* Use up to 'showcmd' column. */
216 	    room = (int)(Rows - msg_row - 1) * Columns + sc_col - 1;
217 	if (len > room && room > 0)
218 	{
219 #ifdef FEAT_MBYTE
220 	    if (enc_utf8)
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);
227 	    else
228 #endif
229 		buf = alloc(room + 2);
230 	    if (buf != NULL)
231 		trunc_string(s, buf, room);
232 	}
233     }
234     return buf;
235 }
236 
237 /*
238  * Truncate a string "s" to "buf" with cell width "room".
239  * "s" and "buf" may be equal.
240  */
241     void
242 trunc_string(s, buf, room)
243     char_u	*s;
244     char_u	*buf;
245     int		room;
246 {
247     int		half;
248     int		len;
249     int		e;
250     int		i;
251     int		n;
252 
253     room -= 3;
254     half = room / 2;
255     len = 0;
256 
257     /* First part: Start of the string. */
258     for (e = 0; len < half; ++e)
259     {
260 	if (s[e] == NUL)
261 	{
262 	    /* text fits without truncating! */
263 	    buf[e] = NUL;
264 	    return;
265 	}
266 	n = ptr2cells(s + e);
267 	if (len + n >= half)
268 	    break;
269 	len += n;
270 	buf[e] = s[e];
271 #ifdef FEAT_MBYTE
272 	if (has_mbyte)
273 	    for (n = (*mb_ptr2len)(s + e); --n > 0; )
274 	    {
275 		++e;
276 		buf[e] = s[e];
277 	    }
278 #endif
279     }
280 
281     /* Last part: End of the string. */
282     i = e;
283 #ifdef FEAT_MBYTE
284     if (enc_dbcs != 0)
285     {
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)
291 	{
292 	    n -= ptr2cells(s + i);
293 	    i += (*mb_ptr2len)(s + i);
294 	}
295     }
296     else if (enc_utf8)
297     {
298 	/* For UTF-8 we can go backwards easily. */
299 	half = i = (int)STRLEN(s);
300 	for (;;)
301 	{
302 	    do
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);
306 	    if (len + n > room)
307 		break;
308 	    len += n;
309 	    i = half;
310 	}
311     }
312     else
313 #endif
314     {
315 	for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i)
316 	    len += n;
317     }
318 
319     /* Set the middle and copy the last part. */
320     mch_memmove(buf + e, "...", (size_t)3);
321     STRMOVE(buf + e + 3, s + i);
322 }
323 
324 /*
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!!!
328  */
329 #ifndef PROTO
330 # ifndef HAVE_STDARG_H
331 
332 int
333 #ifdef __BORLANDC__
334 _RTLENTRYF
335 #endif
336 smsg __ARGS((char_u *, long, long, long,
337 			long, long, long, long, long, long, long));
338 int
339 #ifdef __BORLANDC__
340 _RTLENTRYF
341 #endif
342 smsg_attr __ARGS((int, char_u *, long, long, long,
343 			long, long, long, long, long, long, long));
344 
345 int vim_snprintf __ARGS((char *, size_t, char *, long, long, long,
346 				   long, long, long, long, long, long, long));
347 
348 /*
349  * smsg(str, arg, ...) is like using sprintf(buf, str, arg, ...) and then
350  * calling msg(buf).
351  * The buffer used is IObuff, the message is truncated at IOSIZE.
352  */
353 
354 /* VARARGS */
355     int
356 #ifdef __BORLANDC__
357 _RTLENTRYF
358 #endif
359 smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
360     char_u	*s;
361     long	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
362 {
363     return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
364 }
365 
366 /* VARARGS */
367     int
368 #ifdef __BORLANDC__
369 _RTLENTRYF
370 #endif
371 smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
372     int		attr;
373     char_u	*s;
374     long	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
375 {
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);
379 }
380 
381 # else /* HAVE_STDARG_H */
382 
383 int vim_snprintf(char *str, size_t str_m, char *fmt, ...);
384 
385     int
386 #ifdef __BORLANDC__
387 _RTLENTRYF
388 #endif
389 smsg(char_u *s, ...)
390 {
391     va_list arglist;
392 
393     va_start(arglist, s);
394     vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL);
395     va_end(arglist);
396     return msg(IObuff);
397 }
398 
399     int
400 #ifdef __BORLANDC__
401 _RTLENTRYF
402 #endif
403 smsg_attr(int attr, char_u *s, ...)
404 {
405     va_list arglist;
406 
407     va_start(arglist, s);
408     vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist, NULL);
409     va_end(arglist);
410     return msg_attr(IObuff, attr);
411 }
412 
413 # endif /* HAVE_STDARG_H */
414 #endif
415 
416 /*
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.
419  */
420 static int	last_sourcing_lnum = 0;
421 static char_u   *last_sourcing_name = NULL;
422 
423 /*
424  * Reset the last used sourcing name/lnum.  Makes sure it is displayed again
425  * for the next error message;
426  */
427     void
428 reset_last_sourcing()
429 {
430     vim_free(last_sourcing_name);
431     last_sourcing_name = NULL;
432     last_sourcing_lnum = 0;
433 }
434 
435 /*
436  * Return TRUE if "sourcing_name" differs from "last_sourcing_name".
437  */
438     static int
439 other_sourcing_name()
440 {
441     if (sourcing_name != NULL)
442     {
443 	if (last_sourcing_name != NULL)
444 	    return STRCMP(sourcing_name, last_sourcing_name) != 0;
445 	return TRUE;
446     }
447     return FALSE;
448 }
449 
450 /*
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.
454  */
455     static char_u *
456 get_emsg_source()
457 {
458     char_u	*Buf, *p;
459 
460     if (sourcing_name != NULL && other_sourcing_name())
461     {
462 	p = (char_u *)_("Error detected while processing %s:");
463 	Buf = alloc((unsigned)(STRLEN(sourcing_name) + STRLEN(p)));
464 	if (Buf != NULL)
465 	    sprintf((char *)Buf, (char *)p, sourcing_name);
466 	return Buf;
467     }
468     return NULL;
469 }
470 
471 /*
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.
475  */
476     static char_u *
477 get_emsg_lnum()
478 {
479     char_u	*Buf, *p;
480 
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)
486     {
487 	p = (char_u *)_("line %4ld:");
488 	Buf = alloc((unsigned)(STRLEN(p) + 20));
489 	if (Buf != NULL)
490 	    sprintf((char *)Buf, (char *)p, (long)sourcing_lnum);
491 	return Buf;
492     }
493     return NULL;
494 }
495 
496 /*
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.
500  */
501     void
502 msg_source(attr)
503     int		attr;
504 {
505     char_u	*p;
506 
507     ++no_wait_return;
508     p = get_emsg_source();
509     if (p != NULL)
510     {
511 	msg_attr(p, attr);
512 	vim_free(p);
513     }
514     p = get_emsg_lnum();
515     if (p != NULL)
516     {
517 	msg_attr(p, hl_attr(HLF_N));
518 	vim_free(p);
519 	last_sourcing_lnum = sourcing_lnum;  /* only once for each line */
520     }
521 
522     /* remember the last sourcing name printed, also when it's empty */
523     if (sourcing_name == NULL || other_sourcing_name())
524     {
525 	vim_free(last_sourcing_name);
526 	if (sourcing_name == NULL)
527 	    last_sourcing_name = NULL;
528 	else
529 	    last_sourcing_name = vim_strsave(sourcing_name);
530     }
531     --no_wait_return;
532 }
533 
534 /*
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.
539  */
540     int
541 emsg_not_now()
542 {
543     if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL
544 					  && vim_strchr(p_debug, 't') == NULL)
545 #ifdef FEAT_EVAL
546 	    || emsg_skip > 0
547 #endif
548 	    )
549 	return TRUE;
550     return FALSE;
551 }
552 
553 /*
554  * emsg() - display an error message
555  *
556  * Rings the bell, if appropriate, and calls message() to do the real work
557  * When terminal not initialized (yet) mch_errmsg(..) is used.
558  *
559  * return TRUE if wait_return not called
560  */
561     int
562 emsg(s)
563     char_u	*s;
564 {
565     int		attr;
566     char_u	*p;
567 #ifdef FEAT_EVAL
568     int		ignore = FALSE;
569     int		severe;
570 #endif
571 
572     called_emsg = TRUE;
573     ex_exitval = 1;
574 
575     /*
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.
578      */
579 #ifdef FEAT_EVAL
580     severe = emsg_severe;
581     emsg_severe = FALSE;
582 #endif
583 
584     /* Skip this if not giving error messages at the moment. */
585     if (emsg_not_now())
586 	return TRUE;
587 
588     if (!emsg_off || vim_strchr(p_debug, 't') != NULL)
589     {
590 #ifdef FEAT_EVAL
591 	/*
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).
597 	 */
598 	if (cause_errthrow(s, severe, &ignore) == TRUE)
599 	{
600 	    if (!ignore)
601 		did_emsg = TRUE;
602 	    return TRUE;
603 	}
604 
605 	/* set "v:errmsg", also when using ":silent! cmd" */
606 	set_vim_var_string(VV_ERRMSG, s, -1);
607 #endif
608 
609 	/*
610 	 * When using ":silent! cmd" ignore error messages.
611 	 * But do write it to the redirection file.
612 	 */
613 	if (emsg_silent != 0)
614 	{
615 	    msg_start();
616 	    p = get_emsg_source();
617 	    if (p != NULL)
618 	    {
619 		STRCAT(p, "\n");
620 		redir_write(p, -1);
621 		vim_free(p);
622 	    }
623 	    p = get_emsg_lnum();
624 	    if (p != NULL)
625 	    {
626 		STRCAT(p, "\n");
627 		redir_write(p, -1);
628 		vim_free(p);
629 	    }
630 	    redir_write(s, -1);
631 	    return TRUE;
632 	}
633 
634 	/* Reset msg_silent, an error causes messages to be switched back on. */
635 	msg_silent = 0;
636 	cmd_silent = FALSE;
637 
638 	if (global_busy)		/* break :global command */
639 	    ++global_busy;
640 
641 	if (p_eb)
642 	    beep_flush();		/* also includes flush_buffers() */
643 	else
644 	    flush_buffers(FALSE);	/* flush internal buffers */
645 	did_emsg = TRUE;		/* flag for DoOneCmd() */
646     }
647 
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 */
656 
657     /*
658      * Display name and line number for the source of the error.
659      */
660     msg_source(attr);
661 
662     /*
663      * Display the error message itself.
664      */
665     msg_nowait = FALSE;			/* wait for this msg */
666     return msg_attr(s, attr);
667 }
668 
669 /*
670  * Print an error message with one "%s" and one string argument.
671  */
672     int
673 emsg2(s, a1)
674     char_u *s, *a1;
675 {
676     return emsg3(s, a1, NULL);
677 }
678 
679 /* emsg3() and emsgn() are in misc2.c to avoid warnings for the prototypes. */
680 
681     void
682 emsg_invreg(name)
683     int	    name;
684 {
685     EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
686 }
687 
688 /*
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.
693  */
694     char_u *
695 msg_trunc_attr(s, force, attr)
696     char_u	*s;
697     int		force;
698     int		attr;
699 {
700     int		n;
701 
702     /* Add message to history before truncating */
703     add_msg_hist(s, -1, attr);
704 
705     s = msg_may_trunc(force, s);
706 
707     msg_hist_off = TRUE;
708     n = msg_attr(s, attr);
709     msg_hist_off = FALSE;
710 
711     if (n)
712 	return s;
713     return NULL;
714 }
715 
716 /*
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 '<'.
720  */
721     char_u *
722 msg_may_trunc(force, s)
723     int		force;
724     char_u	*s;
725 {
726     int		n;
727     int		room;
728 
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)
732     {
733 #ifdef FEAT_MBYTE
734 	if (has_mbyte)
735 	{
736 	    int	size = vim_strsize(s);
737 
738 	    /* There may be room anyway when there are multibyte chars. */
739 	    if (size <= room)
740 		return s;
741 
742 	    for (n = 0; size >= room; )
743 	    {
744 		size -= (*mb_ptr2cells)(s + n);
745 		n += (*mb_ptr2len)(s + n);
746 	    }
747 	    --n;
748 	}
749 #endif
750 	s += n;
751 	*s = '<';
752     }
753     return s;
754 }
755 
756     static void
757 add_msg_hist(s, len, attr)
758     char_u	*s;
759     int		len;		/* -1 for undetermined length */
760     int		attr;
761 {
762     struct msg_hist *p;
763 
764     if (msg_hist_off || msg_silent != 0)
765 	return;
766 
767     /* Don't let the message history get too big */
768     while (msg_hist_len > MAX_MSG_HIST_LEN)
769 	(void)delete_first_msg();
770 
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));
773     if (p != NULL)
774     {
775 	if (len < 0)
776 	    len = (int)STRLEN(s);
777 	/* remove leading and trailing newlines */
778 	while (len > 0 && *s == '\n')
779 	{
780 	    ++s;
781 	    --len;
782 	}
783 	while (len > 0 && s[len - 1] == '\n')
784 	    --len;
785 	p->msg = vim_strnsave(s, len);
786 	p->next = NULL;
787 	p->attr = attr;
788 	if (last_msg_hist != NULL)
789 	    last_msg_hist->next = p;
790 	last_msg_hist = p;
791 	if (first_msg_hist == NULL)
792 	    first_msg_hist = last_msg_hist;
793 	++msg_hist_len;
794     }
795 }
796 
797 /*
798  * Delete the first (oldest) message from the history.
799  * Returns FAIL if there are no messages.
800  */
801     int
802 delete_first_msg()
803 {
804     struct msg_hist *p;
805 
806     if (msg_hist_len <= 0)
807 	return FAIL;
808     p = first_msg_hist;
809     first_msg_hist = p->next;
810     if (first_msg_hist == NULL)
811         last_msg_hist = NULL;  /* history is empty */
812     vim_free(p->msg);
813     vim_free(p);
814     --msg_hist_len;
815     return OK;
816 }
817 
818 /*
819  * ":messages" command.
820  */
821 /*ARGSUSED*/
822     void
823 ex_messages(eap)
824     exarg_T	*eap;
825 {
826     struct msg_hist *p;
827     char_u	    *s;
828 
829     msg_hist_off = TRUE;
830 
831     s = mch_getenv((char_u *)"LANG");
832     if (s != NULL && *s != NUL)
833 	msg_attr((char_u *)
834 		_("Messages maintainer: Bram Moolenaar <[email protected]>"),
835 		hl_attr(HLF_T));
836 
837     for (p = first_msg_hist; p != NULL && !got_int; p = p->next)
838 	if (p->msg != NULL)
839 	    msg_attr(p->msg, p->attr);
840 
841     msg_hist_off = FALSE;
842 }
843 
844 #if defined(FEAT_CON_DIALOG) || defined(FIND_REPLACE_DIALOG) || defined(PROTO)
845 /*
846  * Call this after prompting the user.  This will avoid a hit-return message
847  * and a delay.
848  */
849     void
850 msg_end_prompt()
851 {
852     need_wait_return = FALSE;
853     emsg_on_display = FALSE;
854     cmdline_row = msg_row;
855     msg_col = 0;
856     msg_clr_eos();
857 }
858 #endif
859 
860 /*
861  * wait for the user to hit a key (normally a return)
862  * if 'redraw' is TRUE, clear and redraw the screen
863  * if 'redraw' is FALSE, just redraw the screen
864  * if 'redraw' is -1, don't redraw at all
865  */
866     void
867 wait_return(redraw)
868     int		redraw;
869 {
870     int		c;
871     int		oldState;
872     int		tmpState;
873     int		had_got_int;
874 
875     if (redraw == TRUE)
876 	must_redraw = CLEAR;
877 
878     /* If using ":silent cmd", don't wait for a return.  Also don't set
879      * need_wait_return to do it later. */
880     if (msg_silent != 0)
881 	return;
882 
883 /*
884  * With the global command (and some others) we only need one return at the
885  * end. Adjust cmdline_row to avoid the next message overwriting the last one.
886  * When inside vgetc(), we can't wait for a typed character at all.
887  */
888     if (vgetc_busy > 0)
889 	return;
890     if (no_wait_return)
891     {
892 	need_wait_return = TRUE;
893 	if (!exmode_active)
894 	    cmdline_row = msg_row;
895 	return;
896     }
897 
898     redir_off = TRUE;		/* don't redirect this message */
899     oldState = State;
900     if (quit_more)
901     {
902 	c = CAR;		/* just pretend CR was hit */
903 	quit_more = FALSE;
904 	got_int = FALSE;
905     }
906     else if (exmode_active)
907     {
908 	MSG_PUTS(" ");		/* make sure the cursor is on the right line */
909 	c = CAR;		/* no need for a return in ex mode */
910 	got_int = FALSE;
911     }
912     else
913     {
914 	/* Make sure the hit-return prompt is on screen when 'guioptions' was
915 	 * just changed. */
916 	screenalloc(FALSE);
917 
918 	State = HITRETURN;
919 #ifdef FEAT_MOUSE
920 	setmouse();
921 #endif
922 #ifdef USE_ON_FLY_SCROLL
923 	dont_scroll = TRUE;		/* disallow scrolling here */
924 #endif
925 	hit_return_msg();
926 
927 	do
928 	{
929 	    /* Remember "got_int", if it is set vgetc() probably returns a
930 	     * CTRL-C, but we need to loop then. */
931 	    had_got_int = got_int;
932 
933 	    /* Don't do mappings here, we put the character back in the
934 	     * typeahead buffer. */
935 	    ++no_mapping;
936 	    ++allow_keys;
937 	    c = safe_vgetc();
938 	    if (had_got_int && !global_busy)
939 		got_int = FALSE;
940 	    --no_mapping;
941 	    --allow_keys;
942 
943 #ifdef FEAT_CLIPBOARD
944 	    /* Strange way to allow copying (yanking) a modeless selection at
945 	     * the hit-enter prompt.  Use CTRL-Y, because the same is used in
946 	     * Cmdline-mode and it's harmless when there is no selection. */
947 	    if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
948 	    {
949 		clip_copy_modeless_selection(TRUE);
950 		c = K_IGNORE;
951 	    }
952 #endif
953 
954 	    /*
955 	     * Allow scrolling back in the messages.
956 	     * Also accept scroll-down commands when messages fill the screen,
957 	     * to avoid that typing one 'j' too many makes the messages
958 	     * disappear.
959 	     */
960 	    if (p_more && !p_cp)
961 	    {
962 		if (c == 'b' || c == 'k' || c == 'u' || c == 'g' || c == K_UP)
963 		{
964 		    /* scroll back to show older messages */
965 		    do_more_prompt(c);
966 		    if (quit_more)
967 		    {
968 			c = CAR;		/* just pretend CR was hit */
969 			quit_more = FALSE;
970 			got_int = FALSE;
971 		    }
972 		    else
973 		    {
974 			c = K_IGNORE;
975 			hit_return_msg();
976 		    }
977 		}
978 		else if (msg_scrolled > Rows - 2
979 				     && (c == 'j' || c == K_DOWN || c == 'd'))
980 		    c = K_IGNORE;
981 	    }
982 	} while ((had_got_int && c == Ctrl_C)
983 				|| c == K_IGNORE
984 #ifdef FEAT_GUI
985 				|| c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
986 #endif
987 #ifdef FEAT_MOUSE
988 				|| c == K_LEFTDRAG   || c == K_LEFTRELEASE
989 				|| c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
990 				|| c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
991 				|| c == K_MOUSEDOWN  || c == K_MOUSEUP
992 				|| (!mouse_has(MOUSE_RETURN)
993 				    && mouse_row < msg_row
994 				    && (c == K_LEFTMOUSE
995 					|| c == K_MIDDLEMOUSE
996 					|| c == K_RIGHTMOUSE
997 					|| c == K_X1MOUSE
998 					|| c == K_X2MOUSE))
999 #endif
1000 				);
1001 	ui_breakcheck();
1002 #ifdef FEAT_MOUSE
1003 	/*
1004 	 * Avoid that the mouse-up event causes visual mode to start.
1005 	 */
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);
1009 	else
1010 #endif
1011 	    if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C)
1012 	{
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
1017 				       typeahead */
1018 	}
1019     }
1020     redir_off = FALSE;
1021 
1022     /*
1023      * If the user hits ':', '?' or '/' we get a command line from the next
1024      * line.
1025      */
1026     if (c == ':' || c == '?' || c == '/')
1027     {
1028 	if (!exmode_active)
1029 	    cmdline_row = msg_row;
1030 	skip_redraw = TRUE;	    /* skip redraw once */
1031 	do_redraw = FALSE;
1032     }
1033 
1034     /*
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 ':'
1037      * typed.
1038      */
1039     tmpState = State;
1040     State = oldState;		    /* restore State before set_shellsize */
1041 #ifdef FEAT_MOUSE
1042     setmouse();
1043 #endif
1044     msg_check();
1045 
1046 #if defined(UNIX) || defined(VMS)
1047     /*
1048      * When switching screens, we need to output an extra newline on exit.
1049      */
1050     if (swapping_screen() && !termcap_active)
1051 	newline_on_exit = TRUE;
1052 #endif
1053 
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)
1061     {
1062 	vim_free(keep_msg);
1063 	keep_msg = NULL;	    /* don't redisplay message, it's too long */
1064     }
1065 
1066     if (tmpState == SETWSIZE)	    /* got resize event while in vgetc() */
1067     {
1068 	starttermcap();		    /* start termcap before redrawing */
1069 	shell_resized();
1070     }
1071     else if (!skip_redraw
1072 	    && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1)))
1073     {
1074 	starttermcap();		    /* start termcap before redrawing */
1075 	redraw_later(VALID);
1076     }
1077 }
1078 
1079 /*
1080  * Write the hit-return prompt.
1081  */
1082     static void
1083 hit_return_msg()
1084 {
1085     int		save_p_more = p_more;
1086 
1087     p_more = FALSE;	/* don't want see this message when scrolling back */
1088     if (msg_didout)	/* start on a new line */
1089 	msg_putchar('\n');
1090     if (got_int)
1091 	MSG_PUTS(_("Interrupt: "));
1092 
1093     MSG_PUTS_ATTR(_("Press ENTER or type command to continue"), hl_attr(HLF_R));
1094     if (!msg_use_printf())
1095 	msg_clr_eos();
1096     p_more = save_p_more;
1097 }
1098 
1099 /*
1100  * Set "keep_msg" to "s".  Free the old value and check for NULL pointer.
1101  */
1102     void
1103 set_keep_msg(s, attr)
1104     char_u	*s;
1105     int		attr;
1106 {
1107     vim_free(keep_msg);
1108     if (s != NULL && msg_silent == 0)
1109 	keep_msg = vim_strsave(s);
1110     else
1111 	keep_msg = NULL;
1112     keep_msg_more = FALSE;
1113     keep_msg_attr = attr;
1114 }
1115 
1116 #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
1117 /*
1118  * If there currently is a message being displayed, set "keep_msg" to it, so
1119  * that it will be displayed again after redraw.
1120  */
1121     void
1122 set_keep_msg_from_hist()
1123 {
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);
1127 }
1128 #endif
1129 
1130 /*
1131  * Prepare for outputting characters in the command line.
1132  */
1133     void
1134 msg_start()
1135 {
1136     int		did_return = FALSE;
1137 
1138     vim_free(keep_msg);
1139     keep_msg = NULL;			/* don't display old message now */
1140 
1141 #ifdef FEAT_EVAL
1142     if (need_clr_eos)
1143     {
1144 	/* Halfway an ":echo" command and getting an (error) message: clear
1145 	 * any text from the command. */
1146 	need_clr_eos = FALSE;
1147 	msg_clr_eos();
1148     }
1149 #endif
1150 
1151     if (!msg_scroll && full_screen)	/* overwrite last message */
1152     {
1153 	msg_row = cmdline_row;
1154 	msg_col =
1155 #ifdef FEAT_RIGHTLEFT
1156 	    cmdmsg_rl ? Columns - 1 :
1157 #endif
1158 	    0;
1159     }
1160     else if (msg_didout)		    /* start message on next line */
1161     {
1162 	msg_putchar('\n');
1163 	did_return = TRUE;
1164 	if (exmode_active != EXMODE_NORMAL)
1165 	    cmdline_row = msg_row;
1166     }
1167     if (!msg_didany || lines_left < 0)
1168 	msg_starthere();
1169     if (msg_silent == 0)
1170     {
1171 	msg_didout = FALSE;		    /* no output on current line yet */
1172 	cursor_off();
1173     }
1174 
1175     /* when redirecting, may need to start a new line. */
1176     if (!did_return)
1177 	redir_write((char_u *)"\n", -1);
1178 }
1179 
1180 /*
1181  * Note that the current msg position is where messages start.
1182  */
1183     void
1184 msg_starthere()
1185 {
1186     lines_left = cmdline_row;
1187     msg_didany = FALSE;
1188 }
1189 
1190     void
1191 msg_putchar(c)
1192     int		c;
1193 {
1194     msg_putchar_attr(c, 0);
1195 }
1196 
1197     void
1198 msg_putchar_attr(c, attr)
1199     int		c;
1200     int		attr;
1201 {
1202 #ifdef FEAT_MBYTE
1203     char_u	buf[MB_MAXBYTES + 1];
1204 #else
1205     char_u	buf[4];
1206 #endif
1207 
1208     if (IS_SPECIAL(c))
1209     {
1210 	buf[0] = K_SPECIAL;
1211 	buf[1] = K_SECOND(c);
1212 	buf[2] = K_THIRD(c);
1213 	buf[3] = NUL;
1214     }
1215     else
1216     {
1217 #ifdef FEAT_MBYTE
1218 	buf[(*mb_char2bytes)(c, buf)] = NUL;
1219 #else
1220 	buf[0] = c;
1221 	buf[1] = NUL;
1222 #endif
1223     }
1224     msg_puts_attr(buf, attr);
1225 }
1226 
1227     void
1228 msg_outnum(n)
1229     long	n;
1230 {
1231     char_u	buf[20];
1232 
1233     sprintf((char *)buf, "%ld", n);
1234     msg_puts(buf);
1235 }
1236 
1237     void
1238 msg_home_replace(fname)
1239     char_u	*fname;
1240 {
1241     msg_home_replace_attr(fname, 0);
1242 }
1243 
1244 #if defined(FEAT_FIND_ID) || defined(PROTO)
1245     void
1246 msg_home_replace_hl(fname)
1247     char_u	*fname;
1248 {
1249     msg_home_replace_attr(fname, hl_attr(HLF_D));
1250 }
1251 #endif
1252 
1253     static void
1254 msg_home_replace_attr(fname, attr)
1255     char_u  *fname;
1256     int	    attr;
1257 {
1258     char_u	*name;
1259 
1260     name = home_replace_save(NULL, fname);
1261     if (name != NULL)
1262 	msg_outtrans_attr(name, attr);
1263     vim_free(name);
1264 }
1265 
1266 /*
1267  * Output 'len' characters in 'str' (including NULs) with translation
1268  * if 'len' is -1, output upto a NUL character.
1269  * Use attributes 'attr'.
1270  * Return the number of characters it takes on the screen.
1271  */
1272     int
1273 msg_outtrans(str)
1274     char_u	    *str;
1275 {
1276     return msg_outtrans_attr(str, 0);
1277 }
1278 
1279     int
1280 msg_outtrans_attr(str, attr)
1281     char_u	*str;
1282     int		attr;
1283 {
1284     return msg_outtrans_len_attr(str, (int)STRLEN(str), attr);
1285 }
1286 
1287     int
1288 msg_outtrans_len(str, len)
1289     char_u	*str;
1290     int		len;
1291 {
1292     return msg_outtrans_len_attr(str, len, 0);
1293 }
1294 
1295 /*
1296  * Output one character at "p".  Return pointer to the next character.
1297  * Handles multi-byte characters.
1298  */
1299     char_u *
1300 msg_outtrans_one(p, attr)
1301     char_u	*p;
1302     int		attr;
1303 {
1304 #ifdef FEAT_MBYTE
1305     int		l;
1306 
1307     if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
1308     {
1309 	msg_outtrans_len_attr(p, l, attr);
1310 	return p + l;
1311     }
1312 #endif
1313     msg_puts_attr(transchar_byte(*p), attr);
1314     return p + 1;
1315 }
1316 
1317     int
1318 msg_outtrans_len_attr(msgstr, len, attr)
1319     char_u	*msgstr;
1320     int		len;
1321     int		attr;
1322 {
1323     int		retval = 0;
1324     char_u	*str = msgstr;
1325     char_u	*plain_start = msgstr;
1326     char_u	*s;
1327 #ifdef FEAT_MBYTE
1328     int		mb_l;
1329     int		c;
1330 #endif
1331 
1332     /* if MSG_HIST flag set, add message to history */
1333     if (attr & MSG_HIST)
1334     {
1335 	add_msg_hist(str, len, attr);
1336 	attr &= ~MSG_HIST;
1337     }
1338 
1339 #ifdef FEAT_MBYTE
1340     /* If the string starts with a composing character first draw a space on
1341      * which the composing char can be drawn. */
1342     if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr)))
1343 	msg_puts_attr((char_u *)" ", attr);
1344 #endif
1345 
1346     /*
1347      * Go over the string.  Special characters are translated and printed.
1348      * Normal characters are printed several at a time.
1349      */
1350     while (--len >= 0)
1351     {
1352 #ifdef FEAT_MBYTE
1353 	if (enc_utf8)
1354 	    /* Don't include composing chars after the end. */
1355 	    mb_l = utfc_ptr2len_len(str, len + 1);
1356 	else if (has_mbyte)
1357 	    mb_l = (*mb_ptr2len)(str);
1358 	else
1359 	    mb_l = 1;
1360 	if (has_mbyte && mb_l > 1)
1361 	{
1362 	    c = (*mb_ptr2char)(str);
1363 	    if (vim_isprintc(c))
1364 		/* printable multi-byte char: count the cells. */
1365 		retval += (*mb_ptr2cells)(str);
1366 	    else
1367 	    {
1368 		/* unprintable multi-byte char: print the printable chars so
1369 		 * far and the translation of the unprintable char. */
1370 		if (str > plain_start)
1371 		    msg_puts_attr_len(plain_start, (int)(str - plain_start),
1372 									attr);
1373 		plain_start = str + mb_l;
1374 		msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr);
1375 		retval += char2cells(c);
1376 	    }
1377 	    len -= mb_l - 1;
1378 	    str += mb_l;
1379 	}
1380 	else
1381 #endif
1382 	{
1383 	    s = transchar_byte(*str);
1384 	    if (s[1] != NUL)
1385 	    {
1386 		/* unprintable char: print the printable chars so far and the
1387 		 * translation of the unprintable char. */
1388 		if (str > plain_start)
1389 		    msg_puts_attr_len(plain_start, (int)(str - plain_start),
1390 									attr);
1391 		plain_start = str + 1;
1392 		msg_puts_attr(s, attr == 0 ? hl_attr(HLF_8) : attr);
1393 	    }
1394 	    retval += ptr2cells(str);
1395 	    ++str;
1396 	}
1397     }
1398 
1399     if (str > plain_start)
1400 	/* print the printable chars at the end */
1401 	msg_puts_attr_len(plain_start, (int)(str - plain_start), attr);
1402 
1403     return retval;
1404 }
1405 
1406 #if defined(FEAT_QUICKFIX) || defined(PROTO)
1407     void
1408 msg_make(arg)
1409     char_u  *arg;
1410 {
1411     int	    i;
1412     static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB";
1413 
1414     arg = skipwhite(arg);
1415     for (i = 5; *arg && i >= 0; --i)
1416 	if (*arg++ != str[i])
1417 	    break;
1418     if (i < 0)
1419     {
1420 	msg_putchar('\n');
1421 	for (i = 0; rs[i]; ++i)
1422 	    msg_putchar(rs[i] - 3);
1423     }
1424 }
1425 #endif
1426 
1427 /*
1428  * Output the string 'str' upto a NUL character.
1429  * Return the number of characters it takes on the screen.
1430  *
1431  * If K_SPECIAL is encountered, then it is taken in conjunction with the
1432  * following character and shown as <F1>, <S-Up> etc.  Any other character
1433  * which is not printable shown in <> form.
1434  * If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>.
1435  * If a character is displayed in one of these special ways, is also
1436  * highlighted (its highlight name is '8' in the p_hl variable).
1437  * Otherwise characters are not highlighted.
1438  * This function is used to show mappings, where we want to see how to type
1439  * the character/string -- webb
1440  */
1441     int
1442 msg_outtrans_special(strstart, from)
1443     char_u	*strstart;
1444     int		from;	/* TRUE for lhs of a mapping */
1445 {
1446     char_u	*str = strstart;
1447     int		retval = 0;
1448     char_u	*string;
1449     int		attr;
1450     int		len;
1451 
1452     attr = hl_attr(HLF_8);
1453     while (*str != NUL)
1454     {
1455 	/* Leading and trailing spaces need to be displayed in <> form. */
1456 	if ((str == strstart || str[1] == NUL) && *str == ' ')
1457 	{
1458 	    string = (char_u *)"<Space>";
1459 	    ++str;
1460 	}
1461 	else
1462 	    string = str2special(&str, from);
1463 	len = vim_strsize(string);
1464 	/* Highlight special keys */
1465 	msg_puts_attr(string, len > 1
1466 #ifdef FEAT_MBYTE
1467 		&& (*mb_ptr2len)(string) <= 1
1468 #endif
1469 		? attr : 0);
1470 	retval += len;
1471     }
1472     return retval;
1473 }
1474 
1475 /*
1476  * Return the printable string for the key codes at "*sp".
1477  * Used for translating the lhs or rhs of a mapping to printable chars.
1478  * Advances "sp" to the next code.
1479  */
1480     char_u *
1481 str2special(sp, from)
1482     char_u	**sp;
1483     int		from;	/* TRUE for lhs of mapping */
1484 {
1485     int			c;
1486     static char_u	buf[7];
1487     char_u		*str = *sp;
1488     int			modifiers = 0;
1489     int			special = FALSE;
1490 
1491 #ifdef FEAT_MBYTE
1492     if (has_mbyte)
1493     {
1494 	char_u	*p;
1495 
1496 	/* Try to un-escape a multi-byte character.  Return the un-escaped
1497 	 * string if it is a multi-byte character. */
1498 	p = mb_unescape(sp);
1499 	if (p != NULL)
1500 	    return p;
1501     }
1502 #endif
1503 
1504     c = *str;
1505     if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
1506     {
1507 	if (str[1] == KS_MODIFIER)
1508 	{
1509 	    modifiers = str[2];
1510 	    str += 3;
1511 	    c = *str;
1512 	}
1513 	if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
1514 	{
1515 	    c = TO_SPECIAL(str[1], str[2]);
1516 	    str += 2;
1517 	    if (c == K_ZERO)	/* display <Nul> as ^@ */
1518 		c = NUL;
1519 	}
1520 	if (IS_SPECIAL(c) || modifiers)	/* special key */
1521 	    special = TRUE;
1522     }
1523     *sp = str + 1;
1524 
1525 #ifdef FEAT_MBYTE
1526     /* For multi-byte characters check for an illegal byte. */
1527     if (has_mbyte && MB_BYTE2LEN(*str) > (*mb_ptr2len)(str))
1528     {
1529 	transchar_nonprint(buf, c);
1530 	return buf;
1531     }
1532 #endif
1533 
1534     /* Make unprintable characters in <> form, also <M-Space> and <Tab>.
1535      * Use <Space> only for lhs of a mapping. */
1536     if (special || char2cells(c) > 1 || (from && c == ' '))
1537 	return get_special_key_name(c, modifiers);
1538     buf[0] = c;
1539     buf[1] = NUL;
1540     return buf;
1541 }
1542 
1543 /*
1544  * Translate a key sequence into special key names.
1545  */
1546     void
1547 str2specialbuf(sp, buf, len)
1548     char_u	*sp;
1549     char_u	*buf;
1550     int		len;
1551 {
1552     char_u	*s;
1553 
1554     *buf = NUL;
1555     while (*sp)
1556     {
1557 	s = str2special(&sp, FALSE);
1558 	if ((int)(STRLEN(s) + STRLEN(buf)) < len)
1559 	    STRCAT(buf, s);
1560     }
1561 }
1562 
1563 /*
1564  * print line for :print or :list command
1565  */
1566     void
1567 msg_prt_line(s, list)
1568     char_u	*s;
1569     int		list;
1570 {
1571     int		c;
1572     int		col = 0;
1573     int		n_extra = 0;
1574     int		c_extra = 0;
1575     char_u	*p_extra = NULL;	    /* init to make SASC shut up */
1576     int		n;
1577     int		attr = 0;
1578     char_u	*trail = NULL;
1579 #ifdef FEAT_MBYTE
1580     int		l;
1581     char_u	buf[MB_MAXBYTES + 1];
1582 #endif
1583 
1584     if (curwin->w_p_list)
1585 	list = TRUE;
1586 
1587     /* find start of trailing whitespace */
1588     if (list && lcs_trail)
1589     {
1590 	trail = s + STRLEN(s);
1591 	while (trail > s && vim_iswhite(trail[-1]))
1592 	    --trail;
1593     }
1594 
1595     /* output a space for an empty line, otherwise the line will be
1596      * overwritten */
1597     if (*s == NUL && !(list && lcs_eol != NUL))
1598 	msg_putchar(' ');
1599 
1600     while (!got_int)
1601     {
1602 	if (n_extra > 0)
1603 	{
1604 	    --n_extra;
1605 	    if (c_extra)
1606 		c = c_extra;
1607 	    else
1608 		c = *p_extra++;
1609 	}
1610 #ifdef FEAT_MBYTE
1611 	else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1)
1612 	{
1613 	    col += (*mb_ptr2cells)(s);
1614 	    mch_memmove(buf, s, (size_t)l);
1615 	    buf[l] = NUL;
1616 	    msg_puts(buf);
1617 	    s += l;
1618 	    continue;
1619 	}
1620 #endif
1621 	else
1622 	{
1623 	    attr = 0;
1624 	    c = *s++;
1625 	    if (c == TAB && (!list || lcs_tab1))
1626 	    {
1627 		/* tab amount depends on current column */
1628 		n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
1629 		if (!list)
1630 		{
1631 		    c = ' ';
1632 		    c_extra = ' ';
1633 		}
1634 		else
1635 		{
1636 		    c = lcs_tab1;
1637 		    c_extra = lcs_tab2;
1638 		    attr = hl_attr(HLF_8);
1639 		}
1640 	    }
1641 	    else if (c == NUL && list && lcs_eol != NUL)
1642 	    {
1643 		p_extra = (char_u *)"";
1644 		c_extra = NUL;
1645 		n_extra = 1;
1646 		c = lcs_eol;
1647 		attr = hl_attr(HLF_AT);
1648 		--s;
1649 	    }
1650 	    else if (c != NUL && (n = byte2cells(c)) > 1)
1651 	    {
1652 		n_extra = n - 1;
1653 		p_extra = transchar_byte(c);
1654 		c_extra = NUL;
1655 		c = *p_extra++;
1656 		/* Use special coloring to be able to distinguish <hex> from
1657 		 * the same in plain text. */
1658 		attr = hl_attr(HLF_8);
1659 	    }
1660 	    else if (c == ' ' && trail != NULL && s > trail)
1661 	    {
1662 		c = lcs_trail;
1663 		attr = hl_attr(HLF_8);
1664 	    }
1665 	}
1666 
1667 	if (c == NUL)
1668 	    break;
1669 
1670 	msg_putchar_attr(c, attr);
1671 	col++;
1672     }
1673     msg_clr_eos();
1674 }
1675 
1676 #ifdef FEAT_MBYTE
1677 /*
1678  * Use screen_puts() to output one multi-byte character.
1679  * Return the pointer "s" advanced to the next character.
1680  */
1681     static char_u *
1682 screen_puts_mbyte(s, l, attr)
1683     char_u	*s;
1684     int		l;
1685     int		attr;
1686 {
1687     int		cw;
1688 
1689     msg_didout = TRUE;		/* remember that line is not empty */
1690     cw = (*mb_ptr2cells)(s);
1691     if (cw > 1 && (
1692 #ifdef FEAT_RIGHTLEFT
1693 		cmdmsg_rl ? msg_col <= 1 :
1694 #endif
1695 		msg_col == Columns - 1))
1696     {
1697 	/* Doesn't fit, print a highlighted '>' to fill it up. */
1698 	msg_screen_putchar('>', hl_attr(HLF_AT));
1699 	return s;
1700     }
1701 
1702     screen_puts_len(s, l, msg_row, msg_col, attr);
1703 #ifdef FEAT_RIGHTLEFT
1704     if (cmdmsg_rl)
1705     {
1706 	msg_col -= cw;
1707 	if (msg_col == 0)
1708 	{
1709 	    msg_col = Columns;
1710 	    ++msg_row;
1711 	}
1712     }
1713     else
1714 #endif
1715     {
1716 	msg_col += cw;
1717 	if (msg_col >= Columns)
1718 	{
1719 	    msg_col = 0;
1720 	    ++msg_row;
1721 	}
1722     }
1723     return s + l;
1724 }
1725 #endif
1726 
1727 /*
1728  * Output a string to the screen at position msg_row, msg_col.
1729  * Update msg_row and msg_col for the next message.
1730  */
1731     void
1732 msg_puts(s)
1733     char_u	*s;
1734 {
1735     msg_puts_attr(s, 0);
1736 }
1737 
1738     void
1739 msg_puts_title(s)
1740     char_u	*s;
1741 {
1742     msg_puts_attr(s, hl_attr(HLF_T));
1743 }
1744 
1745 /*
1746  * Show a message in such a way that it always fits in the line.  Cut out a
1747  * part in the middle and replace it with "..." when necessary.
1748  * Does not handle multi-byte characters!
1749  */
1750     void
1751 msg_puts_long_attr(longstr, attr)
1752     char_u	*longstr;
1753     int		attr;
1754 {
1755     msg_puts_long_len_attr(longstr, (int)STRLEN(longstr), attr);
1756 }
1757 
1758     void
1759 msg_puts_long_len_attr(longstr, len, attr)
1760     char_u	*longstr;
1761     int		len;
1762     int		attr;
1763 {
1764     int		slen = len;
1765     int		room;
1766 
1767     room = Columns - msg_col;
1768     if (len > room && room >= 20)
1769     {
1770 	slen = (room - 3) / 2;
1771 	msg_outtrans_len_attr(longstr, slen, attr);
1772 	msg_puts_attr((char_u *)"...", hl_attr(HLF_8));
1773     }
1774     msg_outtrans_len_attr(longstr + len - slen, slen, attr);
1775 }
1776 
1777 /*
1778  * Basic function for writing a message with highlight attributes.
1779  */
1780     void
1781 msg_puts_attr(s, attr)
1782     char_u	*s;
1783     int		attr;
1784 {
1785     msg_puts_attr_len(s, -1, attr);
1786 }
1787 
1788 /*
1789  * Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
1790  * When "maxlen" is -1 there is no maximum length.
1791  * When "maxlen" is >= 0 the message is not put in the history.
1792  */
1793     static void
1794 msg_puts_attr_len(str, maxlen, attr)
1795     char_u	*str;
1796     int		maxlen;
1797     int		attr;
1798 {
1799     /*
1800      * If redirection is on, also write to the redirection file.
1801      */
1802     redir_write(str, maxlen);
1803 
1804     /*
1805      * Don't print anything when using ":silent cmd".
1806      */
1807     if (msg_silent != 0)
1808 	return;
1809 
1810     /* if MSG_HIST flag set, add message to history */
1811     if ((attr & MSG_HIST) && maxlen < 0)
1812     {
1813 	add_msg_hist(str, -1, attr);
1814 	attr &= ~MSG_HIST;
1815     }
1816 
1817     /*
1818      * When writing something to the screen after it has scrolled, requires a
1819      * wait-return prompt later.  Needed when scrolling, resetting
1820      * need_wait_return after some prompt, and then outputting something
1821      * without scrolling
1822      */
1823     if (msg_scrolled != 0 && !msg_scrolled_ign)
1824 	need_wait_return = TRUE;
1825     msg_didany = TRUE;		/* remember that something was outputted */
1826 
1827     /*
1828      * If there is no valid screen, use fprintf so we can see error messages.
1829      * If termcap is not active, we may be writing in an alternate console
1830      * window, cursor positioning may not work correctly (window size may be
1831      * different, e.g. for Win32 console) or we just don't know where the
1832      * cursor is.
1833      */
1834     if (msg_use_printf())
1835 	msg_puts_printf(str, maxlen);
1836     else
1837 	msg_puts_display(str, maxlen, attr, FALSE);
1838 }
1839 
1840 /*
1841  * The display part of msg_puts_attr_len().
1842  * May be called recursively to display scroll-back text.
1843  */
1844     static void
1845 msg_puts_display(str, maxlen, attr, recurse)
1846     char_u	*str;
1847     int		maxlen;
1848     int		attr;
1849     int		recurse;
1850 {
1851     char_u	*s = str;
1852     char_u	*t_s = str;	/* string from "t_s" to "s" is still todo */
1853     int		t_col = 0;	/* screen cells todo, 0 when "t_s" not used */
1854 #ifdef FEAT_MBYTE
1855     int		l;
1856     int		cw;
1857 #endif
1858     char_u	*sb_str = str;
1859     int		sb_col = msg_col;
1860     int		wrap;
1861     int		did_last_char;
1862 
1863     did_wait_return = FALSE;
1864     while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL)
1865     {
1866 	/*
1867 	 * We are at the end of the screen line when:
1868 	 * - When outputting a newline.
1869 	 * - When outputting a character in the last column.
1870 	 */
1871 	if (!recurse && msg_row >= Rows - 1 && (*s == '\n' || (
1872 #ifdef FEAT_RIGHTLEFT
1873 		    cmdmsg_rl
1874 		    ? (
1875 			msg_col <= 1
1876 			|| (*s == TAB && msg_col <= 7)
1877 # ifdef FEAT_MBYTE
1878 			|| (has_mbyte && (*mb_ptr2cells)(s) > 1 && msg_col <= 2)
1879 # endif
1880 		      )
1881 		    :
1882 #endif
1883 		      (msg_col + t_col >= Columns - 1
1884 		       || (*s == TAB && msg_col + t_col >= ((Columns - 1) & ~7))
1885 # ifdef FEAT_MBYTE
1886 		       || (has_mbyte && (*mb_ptr2cells)(s) > 1
1887 					    && msg_col + t_col >= Columns - 2)
1888 # endif
1889 		      ))))
1890 	{
1891 	    /*
1892 	     * The screen is scrolled up when at the last row (some terminals
1893 	     * scroll automatically, some don't.  To avoid problems we scroll
1894 	     * ourselves).
1895 	     */
1896 	    if (t_col > 0)
1897 		/* output postponed text */
1898 		t_puts(&t_col, t_s, s, attr);
1899 
1900 	    /* When no more prompt and no more room, truncate here */
1901 	    if (msg_no_more && lines_left == 0)
1902 		break;
1903 
1904 	    /* Scroll the screen up one line. */
1905 	    msg_scroll_up();
1906 
1907 	    msg_row = Rows - 2;
1908 	    if (msg_col >= Columns)	/* can happen after screen resize */
1909 		msg_col = Columns - 1;
1910 
1911 	    /* Display char in last column before showing more-prompt. */
1912 	    if (*s >= ' '
1913 #ifdef FEAT_RIGHTLEFT
1914 		    && !cmdmsg_rl
1915 #endif
1916 	       )
1917 	    {
1918 #ifdef FEAT_MBYTE
1919 		if (has_mbyte)
1920 		{
1921 		    if (enc_utf8 && maxlen >= 0)
1922 			/* avoid including composing chars after the end */
1923 			l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
1924 		    else
1925 			l = (*mb_ptr2len)(s);
1926 		    s = screen_puts_mbyte(s, l, attr);
1927 		}
1928 		else
1929 #endif
1930 		    msg_screen_putchar(*s++, attr);
1931 		did_last_char = TRUE;
1932 	    }
1933 	    else
1934 		did_last_char = FALSE;
1935 
1936 	    if (p_more)
1937 		/* store text for scrolling back */
1938 		store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
1939 
1940 	    inc_msg_scrolled();
1941 	    need_wait_return = TRUE; /* may need wait_return in main() */
1942 	    if (must_redraw < VALID)
1943 		must_redraw = VALID;
1944 	    redraw_cmdline = TRUE;
1945 	    if (cmdline_row > 0 && !exmode_active)
1946 		--cmdline_row;
1947 
1948 	    /*
1949 	     * If screen is completely filled and 'more' is set then wait
1950 	     * for a character.
1951 	     */
1952 	    if (lines_left > 0)
1953 		--lines_left;
1954 	    if (p_more && lines_left == 0 && State != HITRETURN
1955 					    && !msg_no_more && !exmode_active)
1956 	    {
1957 #ifdef FEAT_CON_DIALOG
1958 		if (do_more_prompt(NUL))
1959 		    s = confirm_msg_tail;
1960 #else
1961 		(void)do_more_prompt(NUL);
1962 #endif
1963 		if (quit_more)
1964 		    return;
1965 	    }
1966 
1967 	    /* When we displayed a char in last column need to check if there
1968 	     * is still more. */
1969 	    if (did_last_char)
1970 		continue;
1971 	}
1972 
1973 	wrap = *s == '\n'
1974 		    || msg_col + t_col >= Columns
1975 #ifdef FEAT_MBYTE
1976 		    || (has_mbyte && (*mb_ptr2cells)(s) > 1
1977 					    && msg_col + t_col >= Columns - 1)
1978 #endif
1979 		    ;
1980 	if (t_col > 0 && (wrap || *s == '\r' || *s == '\b'
1981 						 || *s == '\t' || *s == BELL))
1982 	    /* output any postponed text */
1983 	    t_puts(&t_col, t_s, s, attr);
1984 
1985 	if (wrap && p_more && !recurse)
1986 	    /* store text for scrolling back */
1987 	    store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
1988 
1989 	if (*s == '\n')		    /* go to next line */
1990 	{
1991 	    msg_didout = FALSE;	    /* remember that line is empty */
1992 #ifdef FEAT_RIGHTLEFT
1993 	    if (cmdmsg_rl)
1994 		msg_col = Columns - 1;
1995 	    else
1996 #endif
1997 		msg_col = 0;
1998 	    if (++msg_row >= Rows)  /* safety check */
1999 		msg_row = Rows - 1;
2000 	}
2001 	else if (*s == '\r')	    /* go to column 0 */
2002 	{
2003 	    msg_col = 0;
2004 	}
2005 	else if (*s == '\b')	    /* go to previous char */
2006 	{
2007 	    if (msg_col)
2008 		--msg_col;
2009 	}
2010 	else if (*s == TAB)	    /* translate Tab into spaces */
2011 	{
2012 	    do
2013 		msg_screen_putchar(' ', attr);
2014 	    while (msg_col & 7);
2015 	}
2016 	else if (*s == BELL)	    /* beep (from ":sh") */
2017 	    vim_beep();
2018 	else
2019 	{
2020 #ifdef FEAT_MBYTE
2021 	    if (has_mbyte)
2022 	    {
2023 		cw = (*mb_ptr2cells)(s);
2024 		if (enc_utf8 && maxlen >= 0)
2025 		    /* avoid including composing chars after the end */
2026 		    l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
2027 		else
2028 		    l = (*mb_ptr2len)(s);
2029 	    }
2030 	    else
2031 	    {
2032 		cw = 1;
2033 		l = 1;
2034 	    }
2035 #endif
2036 	    /* When drawing from right to left or when a double-wide character
2037 	     * doesn't fit, draw a single character here.  Otherwise collect
2038 	     * characters and draw them all at once later. */
2039 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
2040 	    if (
2041 # ifdef FEAT_RIGHTLEFT
2042 		    cmdmsg_rl
2043 #  ifdef FEAT_MBYTE
2044 		    ||
2045 #  endif
2046 # endif
2047 # ifdef FEAT_MBYTE
2048 		    (cw > 1 && msg_col + t_col >= Columns - 1)
2049 # endif
2050 		    )
2051 	    {
2052 # ifdef FEAT_MBYTE
2053 		if (l > 1)
2054 		    s = screen_puts_mbyte(s, l, attr) - 1;
2055 		else
2056 # endif
2057 		    msg_screen_putchar(*s, attr);
2058 	    }
2059 	    else
2060 #endif
2061 	    {
2062 		/* postpone this character until later */
2063 		if (t_col == 0)
2064 		    t_s = s;
2065 #ifdef FEAT_MBYTE
2066 		t_col += cw;
2067 		s += l - 1;
2068 #else
2069 		++t_col;
2070 #endif
2071 	    }
2072 	}
2073 	++s;
2074     }
2075 
2076     /* output any postponed text */
2077     if (t_col > 0)
2078 	t_puts(&t_col, t_s, s, attr);
2079     if (p_more && !recurse)
2080 	store_sb_text(&sb_str, s, attr, &sb_col, FALSE);
2081 
2082     msg_check();
2083 }
2084 
2085 /*
2086  * Scroll the screen up one line for displaying the next message line.
2087  */
2088     static void
2089 msg_scroll_up()
2090 {
2091 #ifdef FEAT_GUI
2092     /* Remove the cursor before scrolling, ScreenLines[] is going
2093      * to become invalid. */
2094     if (gui.in_use)
2095 	gui_undraw_cursor();
2096 #endif
2097     /* scrolling up always works */
2098     screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL);
2099 
2100     if (!can_clear((char_u *)" "))
2101     {
2102 	/* Scrolling up doesn't result in the right background.  Set the
2103 	 * background here.  It's not efficient, but avoids that we have to do
2104 	 * it all over the code. */
2105 	screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2106 
2107 	/* Also clear the last char of the last but one line if it was not
2108 	 * cleared before to avoid a scroll-up. */
2109 	if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1] == (sattr_T)-1)
2110 	    screen_fill((int)Rows - 2, (int)Rows - 1,
2111 				 (int)Columns - 1, (int)Columns, ' ', ' ', 0);
2112     }
2113 }
2114 
2115 /*
2116  * Increment "msg_scrolled".
2117  */
2118     static void
2119 inc_msg_scrolled()
2120 {
2121 #ifdef FEAT_EVAL
2122     if (*get_vim_var_str(VV_SCROLLSTART) == NUL)
2123     {
2124 	char_u	    *p = sourcing_name;
2125 	char_u	    *tofree = NULL;
2126 	int	    len;
2127 
2128 	/* v:scrollstart is empty, set it to the script/function name and line
2129 	 * number */
2130 	if (p == NULL)
2131 	    p = (char_u *)_("Unknown");
2132 	else
2133 	{
2134 	    len = (int)STRLEN(p) + 40;
2135 	    tofree = alloc(len);
2136 	    if (tofree != NULL)
2137 	    {
2138 		vim_snprintf((char *)tofree, len, _("%s line %ld"),
2139 						      p, (long)sourcing_lnum);
2140 		p = tofree;
2141 	    }
2142 	}
2143 	set_vim_var_string(VV_SCROLLSTART, p, -1);
2144 	vim_free(tofree);
2145     }
2146 #endif
2147     ++msg_scrolled;
2148 }
2149 
2150 /*
2151  * To be able to scroll back at the "more" and "hit-enter" prompts we need to
2152  * store the displayed text and remember where screen lines start.
2153  */
2154 typedef struct msgchunk_S msgchunk_T;
2155 struct msgchunk_S
2156 {
2157     msgchunk_T	*sb_next;
2158     msgchunk_T	*sb_prev;
2159     char	sb_eol;		/* TRUE when line ends after this text */
2160     int		sb_msg_col;	/* column in which text starts */
2161     int		sb_attr;	/* text attributes */
2162     char_u	sb_text[1];	/* text to be displayed, actually longer */
2163 };
2164 
2165 static msgchunk_T *last_msgchunk = NULL; /* last displayed text */
2166 
2167 static msgchunk_T *msg_sb_start __ARGS((msgchunk_T *mps));
2168 static msgchunk_T *disp_sb_line __ARGS((int row, msgchunk_T *smp));
2169 
2170 static int do_clear_sb_text = FALSE;	/* clear text on next msg */
2171 
2172 /*
2173  * Store part of a printed message for displaying when scrolling back.
2174  */
2175     static void
2176 store_sb_text(sb_str, s, attr, sb_col, finish)
2177     char_u	**sb_str;	/* start of string */
2178     char_u	*s;		/* just after string */
2179     int		attr;
2180     int		*sb_col;
2181     int		finish;		/* line ends */
2182 {
2183     msgchunk_T	*mp;
2184 
2185     if (do_clear_sb_text)
2186     {
2187 	clear_sb_text();
2188 	do_clear_sb_text = FALSE;
2189     }
2190 
2191     if (s > *sb_str)
2192     {
2193 	mp = (msgchunk_T *)alloc((int)(sizeof(msgchunk_T) + (s - *sb_str)));
2194 	if (mp != NULL)
2195 	{
2196 	    mp->sb_eol = finish;
2197 	    mp->sb_msg_col = *sb_col;
2198 	    mp->sb_attr = attr;
2199 	    vim_strncpy(mp->sb_text, *sb_str, s - *sb_str);
2200 
2201 	    if (last_msgchunk == NULL)
2202 	    {
2203 		last_msgchunk = mp;
2204 		mp->sb_prev = NULL;
2205 	    }
2206 	    else
2207 	    {
2208 		mp->sb_prev = last_msgchunk;
2209 		last_msgchunk->sb_next = mp;
2210 		last_msgchunk = mp;
2211 	    }
2212 	    mp->sb_next = NULL;
2213 	}
2214     }
2215     else if (finish && last_msgchunk != NULL)
2216 	last_msgchunk->sb_eol = TRUE;
2217 
2218     *sb_str = s;
2219     *sb_col = 0;
2220 }
2221 
2222 /*
2223  * Finished showing messages, clear the scroll-back text on the next message.
2224  */
2225     void
2226 may_clear_sb_text()
2227 {
2228     do_clear_sb_text = TRUE;
2229 }
2230 
2231 /*
2232  * Clear any text remembered for scrolling back.
2233  * Called when redrawing the screen.
2234  */
2235     void
2236 clear_sb_text()
2237 {
2238     msgchunk_T	*mp;
2239 
2240     while (last_msgchunk != NULL)
2241     {
2242 	mp = last_msgchunk->sb_prev;
2243 	vim_free(last_msgchunk);
2244 	last_msgchunk = mp;
2245     }
2246 }
2247 
2248 /*
2249  * "g<" command.
2250  */
2251     void
2252 show_sb_text()
2253 {
2254     msgchunk_T	*mp;
2255 
2256     /* Only show something if there is more than one line, otherwise it looks
2257      * weird, typing a command without output results in one line. */
2258     mp = msg_sb_start(last_msgchunk);
2259     if (mp == NULL || mp->sb_prev == NULL)
2260 	vim_beep();
2261     else
2262     {
2263 	do_more_prompt('G');
2264 	wait_return(FALSE);
2265     }
2266 }
2267 
2268 /*
2269  * Move to the start of screen line in already displayed text.
2270  */
2271     static msgchunk_T *
2272 msg_sb_start(mps)
2273     msgchunk_T *mps;
2274 {
2275     msgchunk_T *mp = mps;
2276 
2277     while (mp != NULL && mp->sb_prev != NULL && !mp->sb_prev->sb_eol)
2278 	mp = mp->sb_prev;
2279     return mp;
2280 }
2281 
2282 /*
2283  * Display a screen line from previously displayed text at row "row".
2284  * Returns a pointer to the text for the next line (can be NULL).
2285  */
2286     static msgchunk_T *
2287 disp_sb_line(row, smp)
2288     int		row;
2289     msgchunk_T	*smp;
2290 {
2291     msgchunk_T	*mp = smp;
2292     char_u	*p;
2293 
2294     for (;;)
2295     {
2296 	msg_row = row;
2297 	msg_col = mp->sb_msg_col;
2298 	p = mp->sb_text;
2299 	if (*p == '\n')	    /* don't display the line break */
2300 	    ++p;
2301 	msg_puts_display(p, -1, mp->sb_attr, TRUE);
2302 	if (mp->sb_eol || mp->sb_next == NULL)
2303 	    break;
2304 	mp = mp->sb_next;
2305     }
2306     return mp->sb_next;
2307 }
2308 
2309 /*
2310  * Output any postponed text for msg_puts_attr_len().
2311  */
2312     static void
2313 t_puts(t_col, t_s, s, attr)
2314     int		*t_col;
2315     char_u	*t_s;
2316     char_u	*s;
2317     int		attr;
2318 {
2319     /* output postponed text */
2320     msg_didout = TRUE;		/* remember that line is not empty */
2321     screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr);
2322     msg_col += *t_col;
2323     *t_col = 0;
2324 #ifdef FEAT_MBYTE
2325     /* If the string starts with a composing character don't increment the
2326      * column position for it. */
2327     if (enc_utf8 && utf_iscomposing(utf_ptr2char(t_s)))
2328 	--msg_col;
2329 #endif
2330     if (msg_col >= Columns)
2331     {
2332 	msg_col = 0;
2333 	++msg_row;
2334     }
2335 }
2336 
2337 /*
2338  * Returns TRUE when messages should be printed with mch_errmsg().
2339  * This is used when there is no valid screen, so we can see error messages.
2340  * If termcap is not active, we may be writing in an alternate console
2341  * window, cursor positioning may not work correctly (window size may be
2342  * different, e.g. for Win32 console) or we just don't know where the
2343  * cursor is.
2344  */
2345     int
2346 msg_use_printf()
2347 {
2348     return (!msg_check_screen()
2349 #if defined(WIN3264) && !defined(FEAT_GUI_MSWIN)
2350 	    || !termcap_active
2351 #endif
2352 	    || (swapping_screen() && !termcap_active)
2353 	       );
2354 }
2355 
2356 /*
2357  * Print a message when there is no valid screen.
2358  */
2359     static void
2360 msg_puts_printf(str, maxlen)
2361     char_u	*str;
2362     int		maxlen;
2363 {
2364     char_u	*s = str;
2365     char_u	buf[4];
2366     char_u	*p;
2367 
2368 #ifdef WIN3264
2369     if (!(silent_mode && p_verbose == 0))
2370 	mch_settmode(TMODE_COOK);	/* handle '\r' and '\n' correctly */
2371 #endif
2372     while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
2373     {
2374 	if (!(silent_mode && p_verbose == 0))
2375 	{
2376 	    /* NL --> CR NL translation (for Unix, not for "--version") */
2377 	    /* NL --> CR translation (for Mac) */
2378 	    p = &buf[0];
2379 	    if (*s == '\n' && !info_message)
2380 		*p++ = '\r';
2381 #if defined(USE_CR) && !defined(MACOS_X_UNIX)
2382 	    else
2383 #endif
2384 		*p++ = *s;
2385 	    *p = '\0';
2386 	    if (info_message)	/* informative message, not an error */
2387 		mch_msg((char *)buf);
2388 	    else
2389 		mch_errmsg((char *)buf);
2390 	}
2391 
2392 	/* primitive way to compute the current column */
2393 #ifdef FEAT_RIGHTLEFT
2394 	if (cmdmsg_rl)
2395 	{
2396 	    if (*s == '\r' || *s == '\n')
2397 		msg_col = Columns - 1;
2398 	    else
2399 		--msg_col;
2400 	}
2401 	else
2402 #endif
2403 	{
2404 	    if (*s == '\r' || *s == '\n')
2405 		msg_col = 0;
2406 	    else
2407 		++msg_col;
2408 	}
2409 	++s;
2410     }
2411     msg_didout = TRUE;	    /* assume that line is not empty */
2412 
2413 #ifdef WIN3264
2414     if (!(silent_mode && p_verbose == 0))
2415 	mch_settmode(TMODE_RAW);
2416 #endif
2417 }
2418 
2419 /*
2420  * Show the more-prompt and handle the user response.
2421  * This takes care of scrolling back and displaying previously displayed text.
2422  * When at hit-enter prompt "typed_char" is the already typed character,
2423  * otherwise it's NUL.
2424  * Returns TRUE when jumping ahead to "confirm_msg_tail".
2425  */
2426     static int
2427 do_more_prompt(typed_char)
2428     int		typed_char;
2429 {
2430     int		used_typed_char = typed_char;
2431     int		oldState = State;
2432     int		c;
2433 #ifdef FEAT_CON_DIALOG
2434     int		retval = FALSE;
2435 #endif
2436     int		scroll;
2437     msgchunk_T	*mp_last = NULL;
2438     msgchunk_T	*mp;
2439     int		i;
2440 
2441     if (typed_char == 'G')
2442     {
2443 	/* "g<": Find first line on the last page. */
2444 	mp_last = msg_sb_start(last_msgchunk);
2445 	for (i = 0; i < Rows - 2 && mp_last != NULL
2446 					     && mp_last->sb_prev != NULL; ++i)
2447 	    mp_last = msg_sb_start(mp_last->sb_prev);
2448     }
2449 
2450     State = ASKMORE;
2451 #ifdef FEAT_MOUSE
2452     setmouse();
2453 #endif
2454     if (typed_char == NUL)
2455 	msg_moremsg(FALSE);
2456     for (;;)
2457     {
2458 	/*
2459 	 * Get a typed character directly from the user.
2460 	 */
2461 	if (used_typed_char != NUL)
2462 	{
2463 	    c = used_typed_char;	/* was typed at hit-enter prompt */
2464 	    used_typed_char = NUL;
2465 	}
2466 	else
2467 	    c = get_keystroke();
2468 
2469 #if defined(FEAT_MENU) && defined(FEAT_GUI)
2470 	if (c == K_MENU)
2471 	{
2472 	    int idx = get_menu_index(current_menu, ASKMORE);
2473 
2474 	    /* Used a menu.  If it starts with CTRL-Y, it must
2475 	     * be a "Copy" for the clipboard.  Otherwise
2476 	     * assume that we end */
2477 	    if (idx == MENU_INDEX_INVALID)
2478 		continue;
2479 	    c = *current_menu->strings[idx];
2480 	    if (c != NUL && current_menu->strings[idx][1] != NUL)
2481 		ins_typebuf(current_menu->strings[idx] + 1,
2482 				current_menu->noremap[idx], 0, TRUE,
2483 						   current_menu->silent[idx]);
2484 	}
2485 #endif
2486 
2487 	scroll = 0;
2488 	switch (c)
2489 	{
2490 	case BS:		/* scroll one line back */
2491 	case K_BS:
2492 	case 'k':
2493 	case K_UP:
2494 	    scroll = -1;
2495 	    break;
2496 
2497 	case CAR:		/* one extra line */
2498 	case NL:
2499 	case 'j':
2500 	case K_DOWN:
2501 	    scroll = 1;
2502 	    break;
2503 
2504 	case 'u':		/* Up half a page */
2505 	case K_PAGEUP:
2506 	    scroll = -(Rows / 2);
2507 	    break;
2508 
2509 	case 'd':		/* Down half a page */
2510 	    scroll = Rows / 2;
2511 	    break;
2512 
2513 	case 'b':		/* one page back */
2514 	    scroll = -(Rows - 1);
2515 	    break;
2516 
2517 	case ' ':		/* one extra page */
2518 	case K_PAGEDOWN:
2519 	case K_LEFTMOUSE:
2520 	    scroll = Rows - 1;
2521 	    break;
2522 
2523 	case 'g':		/* all the way back to the start */
2524 	    scroll = -999999;
2525 	    break;
2526 
2527 	case 'G':		/* all the way to the end */
2528 	    scroll = 999999;
2529 	    lines_left = 999999;
2530 	    break;
2531 
2532 	case ':':		/* start new command line */
2533 #ifdef FEAT_CON_DIALOG
2534 	    if (!confirm_msg_used)
2535 #endif
2536 	    {
2537 		/* Since got_int is set all typeahead will be flushed, but we
2538 		 * want to keep this ':', remember that in a special way. */
2539 		typeahead_noflush(':');
2540 		cmdline_row = Rows - 1;		/* put ':' on this line */
2541 		skip_redraw = TRUE;		/* skip redraw once */
2542 		need_wait_return = FALSE;	/* don't wait in main() */
2543 	    }
2544 	    /*FALLTHROUGH*/
2545 	case 'q':		/* quit */
2546 	case Ctrl_C:
2547 	case ESC:
2548 #ifdef FEAT_CON_DIALOG
2549 	    if (confirm_msg_used)
2550 	    {
2551 		/* Jump to the choices of the dialog. */
2552 		retval = TRUE;
2553 		lines_left = Rows - 1;
2554 	    }
2555 	    else
2556 #endif
2557 	    {
2558 		got_int = TRUE;
2559 		quit_more = TRUE;
2560 	    }
2561 	    break;
2562 
2563 #ifdef FEAT_CLIPBOARD
2564 	case Ctrl_Y:
2565 	    /* Strange way to allow copying (yanking) a modeless
2566 	     * selection at the more prompt.  Use CTRL-Y,
2567 	     * because the same is used in Cmdline-mode and at the
2568 	     * hit-enter prompt.  However, scrolling one line up
2569 	     * might be expected... */
2570 	    if (clip_star.state == SELECT_DONE)
2571 		clip_copy_modeless_selection(TRUE);
2572 	    continue;
2573 #endif
2574 	default:		/* no valid response */
2575 	    msg_moremsg(TRUE);
2576 	    continue;
2577 	}
2578 
2579 	if (scroll != 0)
2580 	{
2581 	    if (scroll < 0)
2582 	    {
2583 		/* go to start of last line */
2584 		if (mp_last == NULL)
2585 		    mp = msg_sb_start(last_msgchunk);
2586 		else if (mp_last->sb_prev != NULL)
2587 		    mp = msg_sb_start(mp_last->sb_prev);
2588 		else
2589 		    mp = NULL;
2590 
2591 		/* go to start of line at top of the screen */
2592 		for (i = 0; i < Rows - 2 && mp != NULL && mp->sb_prev != NULL;
2593 									  ++i)
2594 		    mp = msg_sb_start(mp->sb_prev);
2595 
2596 		if (mp != NULL && mp->sb_prev != NULL)
2597 		{
2598 		    /* Find line to be displayed at top. */
2599 		    for (i = 0; i > scroll; --i)
2600 		    {
2601 			if (mp == NULL || mp->sb_prev == NULL)
2602 			    break;
2603 			mp = msg_sb_start(mp->sb_prev);
2604 			if (mp_last == NULL)
2605 			    mp_last = msg_sb_start(last_msgchunk);
2606 			else
2607 			    mp_last = msg_sb_start(mp_last->sb_prev);
2608 		    }
2609 
2610 		    if (scroll == -1 && screen_ins_lines(0, 0, 1,
2611 						       (int)Rows, NULL) == OK)
2612 		    {
2613 			/* display line at top */
2614 			(void)disp_sb_line(0, mp);
2615 		    }
2616 		    else
2617 		    {
2618 			/* redisplay all lines */
2619 			screenclear();
2620 			for (i = 0; mp != NULL && i < Rows - 1; ++i)
2621 			{
2622 			    mp = disp_sb_line(i, mp);
2623 			    ++msg_scrolled;
2624 			}
2625 		    }
2626 		    scroll = 0;
2627 		}
2628 	    }
2629 	    else
2630 	    {
2631 		/* First display any text that we scrolled back. */
2632 		while (scroll > 0 && mp_last != NULL)
2633 		{
2634 		    /* scroll up, display line at bottom */
2635 		    msg_scroll_up();
2636 		    inc_msg_scrolled();
2637 		    screen_fill((int)Rows - 2, (int)Rows - 1, 0,
2638 						   (int)Columns, ' ', ' ', 0);
2639 		    mp_last = disp_sb_line((int)Rows - 2, mp_last);
2640 		    --scroll;
2641 		}
2642 	    }
2643 
2644 	    if (scroll <= 0)
2645 	    {
2646 		/* displayed the requested text, more prompt again */
2647 		screen_fill((int)Rows - 1, (int)Rows, 0,
2648 						   (int)Columns, ' ', ' ', 0);
2649 		msg_moremsg(FALSE);
2650 		continue;
2651 	    }
2652 
2653 	    /* display more text, return to caller */
2654 	    lines_left = scroll;
2655 	}
2656 
2657 	break;
2658     }
2659 
2660     /* clear the --more-- message */
2661     screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2662     State = oldState;
2663 #ifdef FEAT_MOUSE
2664     setmouse();
2665 #endif
2666     if (quit_more)
2667     {
2668 	msg_row = Rows - 1;
2669 	msg_col = 0;
2670     }
2671 #ifdef FEAT_RIGHTLEFT
2672     else if (cmdmsg_rl)
2673 	msg_col = Columns - 1;
2674 #endif
2675 
2676 #ifdef FEAT_CON_DIALOG
2677     return retval;
2678 #else
2679     return FALSE;
2680 #endif
2681 }
2682 
2683 #if defined(USE_MCH_ERRMSG) || defined(PROTO)
2684 
2685 #ifdef mch_errmsg
2686 # undef mch_errmsg
2687 #endif
2688 #ifdef mch_msg
2689 # undef mch_msg
2690 #endif
2691 
2692 /*
2693  * Give an error message.  To be used when the screen hasn't been initialized
2694  * yet.  When stderr can't be used, collect error messages until the GUI has
2695  * started and they can be displayed in a message box.
2696  */
2697     void
2698 mch_errmsg(str)
2699     char	*str;
2700 {
2701     int		len;
2702 
2703 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
2704     /* On Unix use stderr if it's a tty.
2705      * When not going to start the GUI also use stderr.
2706      * On Mac, when started from Finder, stderr is the console. */
2707     if (
2708 # ifdef UNIX
2709 #  ifdef MACOS_X_UNIX
2710 	    (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
2711 #  else
2712 	    isatty(2)
2713 #  endif
2714 #  ifdef FEAT_GUI
2715 	    ||
2716 #  endif
2717 # endif
2718 # ifdef FEAT_GUI
2719 	    !(gui.in_use || gui.starting)
2720 # endif
2721 	    )
2722     {
2723 	fprintf(stderr, "%s", str);
2724 	return;
2725     }
2726 #endif
2727 
2728     /* avoid a delay for a message that isn't there */
2729     emsg_on_display = FALSE;
2730 
2731     len = (int)STRLEN(str) + 1;
2732     if (error_ga.ga_growsize == 0)
2733     {
2734 	error_ga.ga_growsize = 80;
2735 	error_ga.ga_itemsize = 1;
2736     }
2737     if (ga_grow(&error_ga, len) == OK)
2738     {
2739 	mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len,
2740 							  (char_u *)str, len);
2741 #ifdef UNIX
2742 	/* remove CR characters, they are displayed */
2743 	{
2744 	    char_u	*p;
2745 
2746 	    p = (char_u *)error_ga.ga_data + error_ga.ga_len;
2747 	    for (;;)
2748 	    {
2749 		p = vim_strchr(p, '\r');
2750 		if (p == NULL)
2751 		    break;
2752 		*p = ' ';
2753 	    }
2754 	}
2755 #endif
2756 	--len;		/* don't count the NUL at the end */
2757 	error_ga.ga_len += len;
2758     }
2759 }
2760 
2761 /*
2762  * Give a message.  To be used when the screen hasn't been initialized yet.
2763  * When there is no tty, collect messages until the GUI has started and they
2764  * can be displayed in a message box.
2765  */
2766     void
2767 mch_msg(str)
2768     char	*str;
2769 {
2770 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
2771     /* On Unix use stdout if we have a tty.  This allows "vim -h | more" and
2772      * uses mch_errmsg() when started from the desktop.
2773      * When not going to start the GUI also use stdout.
2774      * On Mac, when started from Finder, stderr is the console. */
2775     if (
2776 #  ifdef UNIX
2777 #   ifdef MACOS_X_UNIX
2778 	    (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
2779 #   else
2780 	    isatty(2)
2781 #    endif
2782 #   ifdef FEAT_GUI
2783 	    ||
2784 #   endif
2785 #  endif
2786 #  ifdef FEAT_GUI
2787 	    !(gui.in_use || gui.starting)
2788 #  endif
2789 	    )
2790     {
2791 	printf("%s", str);
2792 	return;
2793     }
2794 # endif
2795     mch_errmsg(str);
2796 }
2797 #endif /* USE_MCH_ERRMSG */
2798 
2799 /*
2800  * Put a character on the screen at the current message position and advance
2801  * to the next position.  Only for printable ASCII!
2802  */
2803     static void
2804 msg_screen_putchar(c, attr)
2805     int		c;
2806     int		attr;
2807 {
2808     msg_didout = TRUE;		/* remember that line is not empty */
2809     screen_putchar(c, msg_row, msg_col, attr);
2810 #ifdef FEAT_RIGHTLEFT
2811     if (cmdmsg_rl)
2812     {
2813 	if (--msg_col == 0)
2814 	{
2815 	    msg_col = Columns;
2816 	    ++msg_row;
2817 	}
2818     }
2819     else
2820 #endif
2821     {
2822 	if (++msg_col >= Columns)
2823 	{
2824 	    msg_col = 0;
2825 	    ++msg_row;
2826 	}
2827     }
2828 }
2829 
2830     void
2831 msg_moremsg(full)
2832     int	    full;
2833 {
2834     int		attr;
2835     char_u	*s = (char_u *)_("-- More --");
2836 
2837     attr = hl_attr(HLF_M);
2838     screen_puts(s, (int)Rows - 1, 0, attr);
2839     if (full)
2840 	screen_puts((char_u *)
2841 		_(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
2842 		(int)Rows - 1, vim_strsize(s), attr);
2843 }
2844 
2845 /*
2846  * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
2847  * exmode_active.
2848  */
2849     void
2850 repeat_message()
2851 {
2852     if (State == ASKMORE)
2853     {
2854 	msg_moremsg(TRUE);	/* display --more-- message again */
2855 	msg_row = Rows - 1;
2856     }
2857 #ifdef FEAT_CON_DIALOG
2858     else if (State == CONFIRM)
2859     {
2860 	display_confirm_msg();	/* display ":confirm" message again */
2861 	msg_row = Rows - 1;
2862     }
2863 #endif
2864     else if (State == EXTERNCMD)
2865     {
2866 	windgoto(msg_row, msg_col); /* put cursor back */
2867     }
2868     else if (State == HITRETURN || State == SETWSIZE)
2869     {
2870 	if (msg_row == Rows - 1)
2871 	{
2872 	    /* Avoid drawing the "hit-enter" prompt below the previous one,
2873 	     * overwrite it.  Esp. useful when regaining focus and a
2874 	     * FocusGained autocmd exists but didn't draw anything. */
2875 	    msg_didout = FALSE;
2876 	    msg_col = 0;
2877 	    msg_clr_eos();
2878 	}
2879 	hit_return_msg();
2880 	msg_row = Rows - 1;
2881     }
2882 }
2883 
2884 /*
2885  * msg_check_screen - check if the screen is initialized.
2886  * Also check msg_row and msg_col, if they are too big it may cause a crash.
2887  * While starting the GUI the terminal codes will be set for the GUI, but the
2888  * output goes to the terminal.  Don't use the terminal codes then.
2889  */
2890     static int
2891 msg_check_screen()
2892 {
2893     if (!full_screen || !screen_valid(FALSE))
2894 	return FALSE;
2895 
2896     if (msg_row >= Rows)
2897 	msg_row = Rows - 1;
2898     if (msg_col >= Columns)
2899 	msg_col = Columns - 1;
2900     return TRUE;
2901 }
2902 
2903 /*
2904  * Clear from current message position to end of screen.
2905  * Skip this when ":silent" was used, no need to clear for redirection.
2906  */
2907     void
2908 msg_clr_eos()
2909 {
2910     if (msg_silent == 0)
2911 	msg_clr_eos_force();
2912 }
2913 
2914 /*
2915  * Clear from current message position to end of screen.
2916  * Note: msg_col is not updated, so we remember the end of the message
2917  * for msg_check().
2918  */
2919     void
2920 msg_clr_eos_force()
2921 {
2922     if (msg_use_printf())
2923     {
2924 	if (full_screen)	/* only when termcap codes are valid */
2925 	{
2926 	    if (*T_CD)
2927 		out_str(T_CD);	/* clear to end of display */
2928 	    else if (*T_CE)
2929 		out_str(T_CE);	/* clear to end of line */
2930 	}
2931     }
2932     else
2933     {
2934 #ifdef FEAT_RIGHTLEFT
2935 	if (cmdmsg_rl)
2936 	{
2937 	    screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0);
2938 	    screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2939 	}
2940 	else
2941 #endif
2942 	{
2943 	    screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns,
2944 								 ' ', ' ', 0);
2945 	    screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2946 	}
2947     }
2948 }
2949 
2950 /*
2951  * Clear the command line.
2952  */
2953     void
2954 msg_clr_cmdline()
2955 {
2956     msg_row = cmdline_row;
2957     msg_col = 0;
2958     msg_clr_eos_force();
2959 }
2960 
2961 /*
2962  * end putting a message on the screen
2963  * call wait_return if the message does not fit in the available space
2964  * return TRUE if wait_return not called.
2965  */
2966     int
2967 msg_end()
2968 {
2969     /*
2970      * if the string is larger than the window,
2971      * or the ruler option is set and we run into it,
2972      * we have to redraw the window.
2973      * Do not do this if we are abandoning the file or editing the command line.
2974      */
2975     if (!exiting && need_wait_return && !(State & CMDLINE))
2976     {
2977 	wait_return(FALSE);
2978 	return FALSE;
2979     }
2980     out_flush();
2981     return TRUE;
2982 }
2983 
2984 /*
2985  * If the written message runs into the shown command or ruler, we have to
2986  * wait for hit-return and redraw the window later.
2987  */
2988     void
2989 msg_check()
2990 {
2991     if (msg_row == Rows - 1 && msg_col >= sc_col)
2992     {
2993 	need_wait_return = TRUE;
2994 	redraw_cmdline = TRUE;
2995     }
2996 }
2997 
2998 /*
2999  * May write a string to the redirection file.
3000  * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
3001  */
3002     static void
3003 redir_write(str, maxlen)
3004     char_u	*str;
3005     int		maxlen;
3006 {
3007     char_u	*s = str;
3008     static int	cur_col = 0;
3009 
3010     /* Don't do anything for displaying prompts and the like. */
3011     if (redir_off)
3012 	return;
3013 
3014     /*
3015      * If 'verbosefile' is set write message in that file.
3016      * Must come before the rest because of updating "msg_col".
3017      */
3018     if (*p_vfile != NUL)
3019 	verbose_write(s, maxlen);
3020 
3021     if (redir_fd != NULL
3022 #ifdef FEAT_EVAL
3023 			  || redir_reg || redir_vname
3024 #endif
3025 				       )
3026     {
3027 	/* If the string doesn't start with CR or NL, go to msg_col */
3028 	if (*s != '\n' && *s != '\r')
3029 	{
3030 	    while (cur_col < msg_col)
3031 	    {
3032 #ifdef FEAT_EVAL
3033 		if (redir_reg)
3034 		    write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
3035 		else if (redir_vname)
3036 		    var_redir_str((char_u *)" ", -1);
3037 		else if (redir_fd)
3038 #endif
3039 		    fputs(" ", redir_fd);
3040 		++cur_col;
3041 	    }
3042 	}
3043 
3044 #ifdef FEAT_EVAL
3045 	if (redir_reg)
3046 	    write_reg_contents(redir_reg, s, maxlen, TRUE);
3047 	if (redir_vname)
3048 	    var_redir_str(s, maxlen);
3049 #endif
3050 
3051 	/* Adjust the current column */
3052 	while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
3053 	{
3054 #ifdef FEAT_EVAL
3055 	    if (!redir_reg && !redir_vname && redir_fd != NULL)
3056 #endif
3057 		putc(*s, redir_fd);
3058 	    if (*s == '\r' || *s == '\n')
3059 		cur_col = 0;
3060 	    else if (*s == '\t')
3061 		cur_col += (8 - cur_col % 8);
3062 	    else
3063 		++cur_col;
3064 	    ++s;
3065 	}
3066 
3067 	if (msg_silent != 0)	/* should update msg_col */
3068 	    msg_col = cur_col;
3069     }
3070 }
3071 
3072 /*
3073  * Before giving verbose message.
3074  * Must always be called paired with verbose_leave()!
3075  */
3076     void
3077 verbose_enter()
3078 {
3079     if (*p_vfile != NUL)
3080 	++msg_silent;
3081 }
3082 
3083 /*
3084  * After giving verbose message.
3085  * Must always be called paired with verbose_enter()!
3086  */
3087     void
3088 verbose_leave()
3089 {
3090     if (*p_vfile != NUL)
3091 	if (--msg_silent < 0)
3092 	    msg_silent = 0;
3093 }
3094 
3095 /*
3096  * Like verbose_enter() and set msg_scroll when displaying the message.
3097  */
3098     void
3099 verbose_enter_scroll()
3100 {
3101     if (*p_vfile != NUL)
3102 	++msg_silent;
3103     else
3104 	/* always scroll up, don't overwrite */
3105 	msg_scroll = TRUE;
3106 }
3107 
3108 /*
3109  * Like verbose_leave() and set cmdline_row when displaying the message.
3110  */
3111     void
3112 verbose_leave_scroll()
3113 {
3114     if (*p_vfile != NUL)
3115     {
3116 	if (--msg_silent < 0)
3117 	    msg_silent = 0;
3118     }
3119     else
3120 	cmdline_row = msg_row;
3121 }
3122 
3123 static FILE *verbose_fd = NULL;
3124 static int  verbose_did_open = FALSE;
3125 
3126 /*
3127  * Called when 'verbosefile' is set: stop writing to the file.
3128  */
3129     void
3130 verbose_stop()
3131 {
3132     if (verbose_fd != NULL)
3133     {
3134 	fclose(verbose_fd);
3135 	verbose_fd = NULL;
3136     }
3137     verbose_did_open = FALSE;
3138 }
3139 
3140 /*
3141  * Open the file 'verbosefile'.
3142  * Return FAIL or OK.
3143  */
3144     int
3145 verbose_open()
3146 {
3147     if (verbose_fd == NULL && !verbose_did_open)
3148     {
3149 	/* Only give the error message once. */
3150 	verbose_did_open = TRUE;
3151 
3152 	verbose_fd = mch_fopen((char *)p_vfile, "a");
3153 	if (verbose_fd == NULL)
3154 	{
3155 	    EMSG2(_(e_notopen), p_vfile);
3156 	    return FAIL;
3157 	}
3158     }
3159     return OK;
3160 }
3161 
3162 /*
3163  * Write a string to 'verbosefile'.
3164  * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
3165  */
3166     static void
3167 verbose_write(str, maxlen)
3168     char_u	*str;
3169     int		maxlen;
3170 {
3171     char_u	*s = str;
3172     static int	cur_col = 0;
3173 
3174     /* Open the file when called the first time. */
3175     if (verbose_fd == NULL)
3176 	verbose_open();
3177 
3178     if (verbose_fd != NULL)
3179     {
3180 	/* If the string doesn't start with CR or NL, go to msg_col */
3181 	if (*s != '\n' && *s != '\r')
3182 	{
3183 	    while (cur_col < msg_col)
3184 	    {
3185 		fputs(" ", verbose_fd);
3186 		++cur_col;
3187 	    }
3188 	}
3189 
3190 	/* Adjust the current column */
3191 	while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
3192 	{
3193 	    putc(*s, verbose_fd);
3194 	    if (*s == '\r' || *s == '\n')
3195 		cur_col = 0;
3196 	    else if (*s == '\t')
3197 		cur_col += (8 - cur_col % 8);
3198 	    else
3199 		++cur_col;
3200 	    ++s;
3201 	}
3202     }
3203 }
3204 
3205 /*
3206  * Give a warning message (for searching).
3207  * Use 'w' highlighting and may repeat the message after redrawing
3208  */
3209     void
3210 give_warning(message, hl)
3211     char_u  *message;
3212     int	    hl;
3213 {
3214     /* Don't do this for ":silent". */
3215     if (msg_silent != 0)
3216 	return;
3217 
3218     /* Don't want a hit-enter prompt here. */
3219     ++no_wait_return;
3220 
3221 #ifdef FEAT_EVAL
3222     set_vim_var_string(VV_WARNINGMSG, message, -1);
3223 #endif
3224     vim_free(keep_msg);
3225     keep_msg = NULL;
3226     if (hl)
3227 	keep_msg_attr = hl_attr(HLF_W);
3228     else
3229 	keep_msg_attr = 0;
3230     if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0)
3231 	set_keep_msg(message, keep_msg_attr);
3232     msg_didout = FALSE;	    /* overwrite this message */
3233     msg_nowait = TRUE;	    /* don't wait for this message */
3234     msg_col = 0;
3235 
3236     --no_wait_return;
3237 }
3238 
3239 /*
3240  * Advance msg cursor to column "col".
3241  */
3242     void
3243 msg_advance(col)
3244     int	    col;
3245 {
3246     if (msg_silent != 0)	/* nothing to advance to */
3247     {
3248 	msg_col = col;		/* for redirection, may fill it up later */
3249 	return;
3250     }
3251     if (col >= Columns)		/* not enough room */
3252 	col = Columns - 1;
3253 #ifdef FEAT_RIGHTLEFT
3254     if (cmdmsg_rl)
3255 	while (msg_col > Columns - col)
3256 	    msg_putchar(' ');
3257     else
3258 #endif
3259 	while (msg_col < col)
3260 	    msg_putchar(' ');
3261 }
3262 
3263 #if defined(FEAT_CON_DIALOG) || defined(PROTO)
3264 /*
3265  * Used for "confirm()" function, and the :confirm command prefix.
3266  * Versions which haven't got flexible dialogs yet, and console
3267  * versions, get this generic handler which uses the command line.
3268  *
3269  * type  = one of:
3270  *	   VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC
3271  * title = title string (can be NULL for default)
3272  * (neither used in console dialogs at the moment)
3273  *
3274  * Format of the "buttons" string:
3275  * "Button1Name\nButton2Name\nButton3Name"
3276  * The first button should normally be the default/accept
3277  * The second button should be the 'Cancel' button
3278  * Other buttons- use your imagination!
3279  * A '&' in a button name becomes a shortcut, so each '&' should be before a
3280  * different letter.
3281  */
3282 /* ARGSUSED */
3283     int
3284 do_dialog(type, title, message, buttons, dfltbutton, textfield)
3285     int		type;
3286     char_u	*title;
3287     char_u	*message;
3288     char_u	*buttons;
3289     int		dfltbutton;
3290     char_u	*textfield;	/* IObuff for inputdialog(), NULL otherwise */
3291 {
3292     int		oldState;
3293     int		retval = 0;
3294     char_u	*hotkeys;
3295     int		c;
3296     int		i;
3297 
3298 #ifndef NO_CONSOLE
3299     /* Don't output anything in silent mode ("ex -s") */
3300     if (silent_mode)
3301 	return dfltbutton;   /* return default option */
3302 #endif
3303 
3304 #ifdef FEAT_GUI_DIALOG
3305     /* When GUI is running and 'c' not in 'guioptions', use the GUI dialog */
3306     if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
3307     {
3308 	c = gui_mch_dialog(type, title, message, buttons, dfltbutton,
3309 								   textfield);
3310 	msg_end_prompt();
3311 
3312 	/* Flush output to avoid that further messages and redrawing is done
3313 	 * in the wrong order. */
3314 	out_flush();
3315 	gui_mch_update();
3316 
3317 	return c;
3318     }
3319 #endif
3320 
3321     oldState = State;
3322     State = CONFIRM;
3323 #ifdef FEAT_MOUSE
3324     setmouse();
3325 #endif
3326 
3327     /*
3328      * Since we wait for a keypress, don't make the
3329      * user press RETURN as well afterwards.
3330      */
3331     ++no_wait_return;
3332     hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
3333 
3334     if (hotkeys != NULL)
3335     {
3336 	for (;;)
3337 	{
3338 	    /* Get a typed character directly from the user. */
3339 	    c = get_keystroke();
3340 	    switch (c)
3341 	    {
3342 	    case CAR:		/* User accepts default option */
3343 	    case NL:
3344 		retval = dfltbutton;
3345 		break;
3346 	    case Ctrl_C:	/* User aborts/cancels */
3347 	    case ESC:
3348 		retval = 0;
3349 		break;
3350 	    default:		/* Could be a hotkey? */
3351 		if (c < 0)	/* special keys are ignored here */
3352 		    continue;
3353 		/* Make the character lowercase, as chars in "hotkeys" are. */
3354 		c = MB_TOLOWER(c);
3355 		retval = 1;
3356 		for (i = 0; hotkeys[i]; ++i)
3357 		{
3358 #ifdef FEAT_MBYTE
3359 		    if (has_mbyte)
3360 		    {
3361 			if ((*mb_ptr2char)(hotkeys + i) == c)
3362 			    break;
3363 			i += (*mb_ptr2len)(hotkeys + i) - 1;
3364 		    }
3365 		    else
3366 #endif
3367 			if (hotkeys[i] == c)
3368 			    break;
3369 		    ++retval;
3370 		}
3371 		if (hotkeys[i])
3372 		    break;
3373 		/* No hotkey match, so keep waiting */
3374 		continue;
3375 	    }
3376 	    break;
3377 	}
3378 
3379 	vim_free(hotkeys);
3380     }
3381 
3382     State = oldState;
3383 #ifdef FEAT_MOUSE
3384     setmouse();
3385 #endif
3386     --no_wait_return;
3387     msg_end_prompt();
3388 
3389     return retval;
3390 }
3391 
3392 static int copy_char __ARGS((char_u *from, char_u *to, int lowercase));
3393 
3394 /*
3395  * Copy one character from "*from" to "*to", taking care of multi-byte
3396  * characters.  Return the length of the character in bytes.
3397  */
3398     static int
3399 copy_char(from, to, lowercase)
3400     char_u	*from;
3401     char_u	*to;
3402     int		lowercase;	/* make character lower case */
3403 {
3404 #ifdef FEAT_MBYTE
3405     int		len;
3406     int		c;
3407 
3408     if (has_mbyte)
3409     {
3410 	if (lowercase)
3411 	{
3412 	    c = MB_TOLOWER((*mb_ptr2char)(from));
3413 	    return (*mb_char2bytes)(c, to);
3414 	}
3415 	else
3416 	{
3417 	    len = (*mb_ptr2len)(from);
3418 	    mch_memmove(to, from, (size_t)len);
3419 	    return len;
3420 	}
3421     }
3422     else
3423 #endif
3424     {
3425 	if (lowercase)
3426 	    *to = (char_u)TOLOWER_LOC(*from);
3427 	else
3428 	    *to = *from;
3429 	return 1;
3430     }
3431 }
3432 
3433 /*
3434  * Format the dialog string, and display it at the bottom of
3435  * the screen. Return a string of hotkey chars (if defined) for
3436  * each 'button'. If a button has no hotkey defined, the first character of
3437  * the button is used.
3438  * The hotkeys can be multi-byte characters, but without combining chars.
3439  *
3440  * Returns an allocated string with hotkeys, or NULL for error.
3441  */
3442     static char_u *
3443 msg_show_console_dialog(message, buttons, dfltbutton)
3444     char_u	*message;
3445     char_u	*buttons;
3446     int		dfltbutton;
3447 {
3448     int		len = 0;
3449 #ifdef FEAT_MBYTE
3450 # define HOTK_LEN (has_mbyte ? MB_MAXBYTES : 1)
3451 #else
3452 # define HOTK_LEN 1
3453 #endif
3454     int		lenhotkey = HOTK_LEN;	/* count first button */
3455     char_u	*hotk = NULL;
3456     char_u	*msgp = NULL;
3457     char_u	*hotkp = NULL;
3458     char_u	*r;
3459     int		copy;
3460 #define HAS_HOTKEY_LEN 30
3461     char_u	has_hotkey[HAS_HOTKEY_LEN];
3462     int		first_hotkey = FALSE;	/* first char of button is hotkey */
3463     int		idx;
3464 
3465     has_hotkey[0] = FALSE;
3466 
3467     /*
3468      * First loop: compute the size of memory to allocate.
3469      * Second loop: copy to the allocated memory.
3470      */
3471     for (copy = 0; copy <= 1; ++copy)
3472     {
3473 	r = buttons;
3474 	idx = 0;
3475 	while (*r)
3476 	{
3477 	    if (*r == DLG_BUTTON_SEP)
3478 	    {
3479 		if (copy)
3480 		{
3481 		    *msgp++ = ',';
3482 		    *msgp++ = ' ';	    /* '\n' -> ', ' */
3483 
3484 		    /* advance to next hotkey and set default hotkey */
3485 #ifdef FEAT_MBYTE
3486 		    if (has_mbyte)
3487 			hotkp += STRLEN(hotkp);
3488 		    else
3489 #endif
3490 			++hotkp;
3491 		    hotkp[copy_char(r + 1, hotkp, TRUE)] = NUL;
3492 		    if (dfltbutton)
3493 			--dfltbutton;
3494 
3495 		    /* If no hotkey is specified first char is used. */
3496 		    if (idx < HAS_HOTKEY_LEN - 1 && !has_hotkey[++idx])
3497 			first_hotkey = TRUE;
3498 		}
3499 		else
3500 		{
3501 		    len += 3;		    /* '\n' -> ', '; 'x' -> '(x)' */
3502 		    lenhotkey += HOTK_LEN;  /* each button needs a hotkey */
3503 		    if (idx < HAS_HOTKEY_LEN - 1)
3504 			has_hotkey[++idx] = FALSE;
3505 		}
3506 	    }
3507 	    else if (*r == DLG_HOTKEY_CHAR || first_hotkey)
3508 	    {
3509 		if (*r == DLG_HOTKEY_CHAR)
3510 		    ++r;
3511 		first_hotkey = FALSE;
3512 		if (copy)
3513 		{
3514 		    if (*r == DLG_HOTKEY_CHAR)		/* '&&a' -> '&a' */
3515 			*msgp++ = *r;
3516 		    else
3517 		    {
3518 			/* '&a' -> '[a]' */
3519 			*msgp++ = (dfltbutton == 1) ? '[' : '(';
3520 			msgp += copy_char(r, msgp, FALSE);
3521 			*msgp++ = (dfltbutton == 1) ? ']' : ')';
3522 
3523 			/* redefine hotkey */
3524 			hotkp[copy_char(r, hotkp, TRUE)] = NUL;
3525 		    }
3526 		}
3527 		else
3528 		{
3529 		    ++len;	    /* '&a' -> '[a]' */
3530 		    if (idx < HAS_HOTKEY_LEN - 1)
3531 			has_hotkey[idx] = TRUE;
3532 		}
3533 	    }
3534 	    else
3535 	    {
3536 		/* everything else copy literally */
3537 		if (copy)
3538 		    msgp += copy_char(r, msgp, FALSE);
3539 	    }
3540 
3541 	    /* advance to the next character */
3542 	    mb_ptr_adv(r);
3543 	}
3544 
3545 	if (copy)
3546 	{
3547 	    *msgp++ = ':';
3548 	    *msgp++ = ' ';
3549 	    *msgp = NUL;
3550 	}
3551 	else
3552 	{
3553 	    len += (int)(STRLEN(message)
3554 			+ 2			/* for the NL's */
3555 			+ STRLEN(buttons)
3556 			+ 3);			/* for the ": " and NUL */
3557 	    lenhotkey++;			/* for the NUL */
3558 
3559 	    /* If no hotkey is specified first char is used. */
3560 	    if (!has_hotkey[0])
3561 	    {
3562 		first_hotkey = TRUE;
3563 		len += 2;		/* "x" -> "[x]" */
3564 	    }
3565 
3566 	    /*
3567 	     * Now allocate and load the strings
3568 	     */
3569 	    vim_free(confirm_msg);
3570 	    confirm_msg = alloc(len);
3571 	    if (confirm_msg == NULL)
3572 		return NULL;
3573 	    *confirm_msg = NUL;
3574 	    hotk = alloc(lenhotkey);
3575 	    if (hotk == NULL)
3576 		return NULL;
3577 
3578 	    *confirm_msg = '\n';
3579 	    STRCPY(confirm_msg + 1, message);
3580 
3581 	    msgp = confirm_msg + 1 + STRLEN(message);
3582 	    hotkp = hotk;
3583 
3584 	    /* Define first default hotkey.  Keep the hotkey string NUL
3585 	     * terminated to avoid reading past the end. */
3586 	    hotkp[copy_char(buttons, hotkp, TRUE)] = NUL;
3587 
3588 	    /* Remember where the choices start, displaying starts here when
3589 	     * "hotkp" typed at the more prompt. */
3590 	    confirm_msg_tail = msgp;
3591 	    *msgp++ = '\n';
3592 	}
3593     }
3594 
3595     display_confirm_msg();
3596     return hotk;
3597 }
3598 
3599 /*
3600  * Display the ":confirm" message.  Also called when screen resized.
3601  */
3602     void
3603 display_confirm_msg()
3604 {
3605     /* avoid that 'q' at the more prompt truncates the message here */
3606     ++confirm_msg_used;
3607     if (confirm_msg != NULL)
3608 	msg_puts_attr(confirm_msg, hl_attr(HLF_M));
3609     --confirm_msg_used;
3610 }
3611 
3612 #endif /* FEAT_CON_DIALOG */
3613 
3614 #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
3615 
3616     int
3617 vim_dialog_yesno(type, title, message, dflt)
3618     int		type;
3619     char_u	*title;
3620     char_u	*message;
3621     int		dflt;
3622 {
3623     if (do_dialog(type,
3624 		title == NULL ? (char_u *)_("Question") : title,
3625 		message,
3626 		(char_u *)_("&Yes\n&No"), dflt, NULL) == 1)
3627 	return VIM_YES;
3628     return VIM_NO;
3629 }
3630 
3631     int
3632 vim_dialog_yesnocancel(type, title, message, dflt)
3633     int		type;
3634     char_u	*title;
3635     char_u	*message;
3636     int		dflt;
3637 {
3638     switch (do_dialog(type,
3639 		title == NULL ? (char_u *)_("Question") : title,
3640 		message,
3641 		(char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL))
3642     {
3643 	case 1: return VIM_YES;
3644 	case 2: return VIM_NO;
3645     }
3646     return VIM_CANCEL;
3647 }
3648 
3649     int
3650 vim_dialog_yesnoallcancel(type, title, message, dflt)
3651     int		type;
3652     char_u	*title;
3653     char_u	*message;
3654     int		dflt;
3655 {
3656     switch (do_dialog(type,
3657 		title == NULL ? (char_u *)"Question" : title,
3658 		message,
3659 		(char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
3660 								  dflt, NULL))
3661     {
3662 	case 1: return VIM_YES;
3663 	case 2: return VIM_NO;
3664 	case 3: return VIM_ALL;
3665 	case 4: return VIM_DISCARDALL;
3666     }
3667     return VIM_CANCEL;
3668 }
3669 
3670 #endif /* FEAT_GUI_DIALOG || FEAT_CON_DIALOG */
3671 
3672 #if defined(FEAT_BROWSE) || defined(PROTO)
3673 /*
3674  * Generic browse function.  Calls gui_mch_browse() when possible.
3675  * Later this may pop-up a non-GUI file selector (external command?).
3676  */
3677     char_u *
3678 do_browse(flags, title, dflt, ext, initdir, filter, buf)
3679     int		flags;		/* BROWSE_SAVE and BROWSE_DIR */
3680     char_u	*title;		/* title for the window */
3681     char_u	*dflt;		/* default file name (may include directory) */
3682     char_u	*ext;		/* extension added */
3683     char_u	*initdir;	/* initial directory, NULL for current dir or
3684 				   when using path from "dflt" */
3685     char_u	*filter;	/* file name filter */
3686     buf_T	*buf;		/* buffer to read/write for */
3687 {
3688     char_u		*fname;
3689     static char_u	*last_dir = NULL;    /* last used directory */
3690     char_u		*tofree = NULL;
3691     int			save_browse = cmdmod.browse;
3692 
3693     /* Must turn off browse to avoid that autocommands will get the
3694      * flag too!  */
3695     cmdmod.browse = FALSE;
3696 
3697     if (title == NULL || *title == NUL)
3698     {
3699 	if (flags & BROWSE_DIR)
3700 	    title = (char_u *)_("Select Directory dialog");
3701 	else if (flags & BROWSE_SAVE)
3702 	    title = (char_u *)_("Save File dialog");
3703 	else
3704 	    title = (char_u *)_("Open File dialog");
3705     }
3706 
3707     /* When no directory specified, use default file name, default dir, buffer
3708      * dir, last dir or current dir */
3709     if ((initdir == NULL || *initdir == NUL) && dflt != NULL && *dflt != NUL)
3710     {
3711 	if (mch_isdir(dflt))		/* default file name is a directory */
3712 	{
3713 	    initdir = dflt;
3714 	    dflt = NULL;
3715 	}
3716 	else if (gettail(dflt) != dflt)	/* default file name includes a path */
3717 	{
3718 	    tofree = vim_strsave(dflt);
3719 	    if (tofree != NULL)
3720 	    {
3721 		initdir = tofree;
3722 		*gettail(initdir) = NUL;
3723 		dflt = gettail(dflt);
3724 	    }
3725 	}
3726     }
3727 
3728     if (initdir == NULL || *initdir == NUL)
3729     {
3730 	/* When 'browsedir' is a directory, use it */
3731 	if (STRCMP(p_bsdir, "last") != 0
3732 		&& STRCMP(p_bsdir, "buffer") != 0
3733 		&& STRCMP(p_bsdir, "current") != 0
3734 		&& mch_isdir(p_bsdir))
3735 	    initdir = p_bsdir;
3736 	/* When saving or 'browsedir' is "buffer", use buffer fname */
3737 	else if (((flags & BROWSE_SAVE) || *p_bsdir == 'b')
3738 		&& buf != NULL && buf->b_ffname != NULL)
3739 	{
3740 	    if (dflt == NULL || *dflt == NUL)
3741 		dflt = gettail(curbuf->b_ffname);
3742 	    tofree = vim_strsave(curbuf->b_ffname);
3743 	    if (tofree != NULL)
3744 	    {
3745 		initdir = tofree;
3746 		*gettail(initdir) = NUL;
3747 	    }
3748 	}
3749 	/* When 'browsedir' is "last", use dir from last browse */
3750 	else if (*p_bsdir == 'l')
3751 	    initdir = last_dir;
3752 	/* When 'browsedir is "current", use current directory.  This is the
3753 	 * default already, leave initdir empty. */
3754     }
3755 
3756 # ifdef FEAT_GUI
3757     if (gui.in_use)		/* when this changes, also adjust f_has()! */
3758     {
3759 	if (filter == NULL
3760 #  ifdef FEAT_EVAL
3761 		&& (filter = get_var_value((char_u *)"b:browsefilter")) == NULL
3762 		&& (filter = get_var_value((char_u *)"g:browsefilter")) == NULL
3763 #  endif
3764 	)
3765 	    filter = BROWSE_FILTER_DEFAULT;
3766 	if (flags & BROWSE_DIR)
3767 	{
3768 #  if defined(HAVE_GTK2) || defined(WIN3264)
3769 	    /* For systems that have a directory dialog. */
3770 	    fname = gui_mch_browsedir(title, initdir);
3771 #  else
3772 	    /* Generic solution for selecting a directory: select a file and
3773 	     * remove the file name. */
3774 	    fname = gui_mch_browse(0, title, dflt, ext, initdir, (char_u *)"");
3775 #  endif
3776 #  if !defined(HAVE_GTK2)
3777 	    /* Win32 adds a dummy file name, others return an arbitrary file
3778 	     * name.  GTK+ 2 returns only the directory, */
3779 	    if (fname != NULL && *fname != NUL && !mch_isdir(fname))
3780 	    {
3781 		/* Remove the file name. */
3782 		char_u	    *tail = gettail_sep(fname);
3783 
3784 		if (tail == fname)
3785 		    *tail++ = '.';	/* use current dir */
3786 		*tail = NUL;
3787 	    }
3788 #  endif
3789 	}
3790 	else
3791 	    fname = gui_mch_browse(flags & BROWSE_SAVE,
3792 					   title, dflt, ext, initdir, filter);
3793 
3794 	/* We hang around in the dialog for a while, the user might do some
3795 	 * things to our files.  The Win32 dialog allows deleting or renaming
3796 	 * a file, check timestamps. */
3797 	need_check_timestamps = TRUE;
3798 	did_check_timestamps = FALSE;
3799     }
3800     else
3801 # endif
3802     {
3803 	/* TODO: non-GUI file selector here */
3804 	EMSG(_("E338: Sorry, no file browser in console mode"));
3805 	fname = NULL;
3806     }
3807 
3808     /* keep the directory for next time */
3809     if (fname != NULL)
3810     {
3811 	vim_free(last_dir);
3812 	last_dir = vim_strsave(fname);
3813 	if (last_dir != NULL && !(flags & BROWSE_DIR))
3814 	{
3815 	    *gettail(last_dir) = NUL;
3816 	    if (*last_dir == NUL)
3817 	    {
3818 		/* filename only returned, must be in current dir */
3819 		vim_free(last_dir);
3820 		last_dir = alloc(MAXPATHL);
3821 		if (last_dir != NULL)
3822 		    mch_dirname(last_dir, MAXPATHL);
3823 	    }
3824 	}
3825     }
3826 
3827     vim_free(tofree);
3828     cmdmod.browse = save_browse;
3829 
3830     return fname;
3831 }
3832 #endif
3833 
3834 #if defined(HAVE_STDARG_H) && defined(FEAT_EVAL)
3835 static char *e_printf = N_("E766: Insufficient arguments for printf()");
3836 
3837 static long tv_nr __ARGS((typval_T *tvs, int *idxp));
3838 static char *tv_str __ARGS((typval_T *tvs, int *idxp));
3839 # ifdef FEAT_FLOAT
3840 static double tv_float __ARGS((typval_T *tvs, int *idxp));
3841 # endif
3842 
3843 /*
3844  * Get number argument from "idxp" entry in "tvs".  First entry is 1.
3845  */
3846     static long
3847 tv_nr(tvs, idxp)
3848     typval_T	*tvs;
3849     int		*idxp;
3850 {
3851     int		idx = *idxp - 1;
3852     long	n = 0;
3853     int		err = FALSE;
3854 
3855     if (tvs[idx].v_type == VAR_UNKNOWN)
3856 	EMSG(_(e_printf));
3857     else
3858     {
3859 	++*idxp;
3860 	n = get_tv_number_chk(&tvs[idx], &err);
3861 	if (err)
3862 	    n = 0;
3863     }
3864     return n;
3865 }
3866 
3867 /*
3868  * Get string argument from "idxp" entry in "tvs".  First entry is 1.
3869  * Returns NULL for an error.
3870  */
3871     static char *
3872 tv_str(tvs, idxp)
3873     typval_T	*tvs;
3874     int		*idxp;
3875 {
3876     int		idx = *idxp - 1;
3877     char	*s = NULL;
3878 
3879     if (tvs[idx].v_type == VAR_UNKNOWN)
3880 	EMSG(_(e_printf));
3881     else
3882     {
3883 	++*idxp;
3884 	s = (char *)get_tv_string_chk(&tvs[idx]);
3885     }
3886     return s;
3887 }
3888 
3889 # ifdef FEAT_FLOAT
3890 /*
3891  * Get float argument from "idxp" entry in "tvs".  First entry is 1.
3892  */
3893     static double
3894 tv_float(tvs, idxp)
3895     typval_T	*tvs;
3896     int		*idxp;
3897 {
3898     int		idx = *idxp - 1;
3899     double	f = 0;
3900 
3901     if (tvs[idx].v_type == VAR_UNKNOWN)
3902 	EMSG(_(e_printf));
3903     else
3904     {
3905 	++*idxp;
3906 	if (tvs[idx].v_type == VAR_FLOAT)
3907 	    f = tvs[idx].vval.v_float;
3908 	else
3909 	    EMSG(_("E807: Expected Float argument for printf()"));
3910     }
3911     return f;
3912 }
3913 # endif
3914 #endif
3915 
3916 /*
3917  * This code was included to provide a portable vsnprintf() and snprintf().
3918  * Some systems may provide their own, but we always use this one for
3919  * consistency.
3920  *
3921  * This code is based on snprintf.c - a portable implementation of snprintf
3922  * by Mark Martinec <[email protected]>, Version 2.2, 2000-10-06.
3923  * Included with permission.  It was heavily modified to fit in Vim.
3924  * The original code, including useful comments, can be found here:
3925  *	http://www.ijs.si/software/snprintf/
3926  *
3927  * This snprintf() only supports the following conversion specifiers:
3928  * s, c, d, u, o, x, X, p  (and synonyms: i, D, U, O - see below)
3929  * with flags: '-', '+', ' ', '0' and '#'.
3930  * An asterisk is supported for field width as well as precision.
3931  *
3932  * Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'.
3933  *
3934  * Length modifiers 'h' (short int) and 'l' (long int) are supported.
3935  * 'll' (long long int) is not supported.
3936  *
3937  * The locale is not used, the string is used as a byte string.  This is only
3938  * relevant for double-byte encodings where the second byte may be '%'.
3939  *
3940  * It is permitted for "str_m" to be zero, and it is permitted to specify NULL
3941  * pointer for resulting string argument if "str_m" is zero (as per ISO C99).
3942  *
3943  * The return value is the number of characters which would be generated
3944  * for the given input, excluding the trailing null. If this value
3945  * is greater or equal to "str_m", not all characters from the result
3946  * have been stored in str, output bytes beyond the ("str_m"-1) -th character
3947  * are discarded. If "str_m" is greater than zero it is guaranteed
3948  * the resulting string will be null-terminated.
3949  */
3950 
3951 /*
3952  * When va_list is not supported we only define vim_snprintf().
3953  *
3954  * vim_vsnprintf() can be invoked with either "va_list" or a list of
3955  * "typval_T".  When the latter is not used it must be NULL.
3956  */
3957 
3958 /* When generating prototypes all of this is skipped, cproto doesn't
3959  * understand this. */
3960 #ifndef PROTO
3961 # ifdef HAVE_STDARG_H
3962     int
3963 vim_snprintf(char *str, size_t str_m, char *fmt, ...)
3964 {
3965     va_list	ap;
3966     int		str_l;
3967 
3968     va_start(ap, fmt);
3969     str_l = vim_vsnprintf(str, str_m, fmt, ap, NULL);
3970     va_end(ap);
3971     return str_l;
3972 }
3973 
3974     int
3975 vim_vsnprintf(str, str_m, fmt, ap, tvs)
3976 # else
3977     /* clumsy way to work around missing va_list */
3978 #  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)
3979 
3980 /* VARARGS */
3981     int
3982 #ifdef __BORLANDC__
3983 _RTLENTRYF
3984 #endif
3985 vim_snprintf(str, str_m, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
3986 # endif
3987     char	*str;
3988     size_t	str_m;
3989     char	*fmt;
3990 # ifdef HAVE_STDARG_H
3991     va_list	ap;
3992     typval_T	*tvs;
3993 # else
3994     long	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
3995 # endif
3996 {
3997     size_t	str_l = 0;
3998     char	*p = fmt;
3999     int		arg_idx = 1;
4000 
4001     if (p == NULL)
4002 	p = "";
4003     while (*p != NUL)
4004     {
4005 	if (*p != '%')
4006 	{
4007 	    char    *q = strchr(p + 1, '%');
4008 	    size_t  n = (q == NULL) ? STRLEN(p) : (q - p);
4009 
4010 	    /* Copy up to the next '%' or NUL without any changes. */
4011 	    if (str_l < str_m)
4012 	    {
4013 		size_t avail = str_m - str_l;
4014 
4015 		mch_memmove(str + str_l, p, n > avail ? avail : n);
4016 	    }
4017 	    p += n;
4018 	    str_l += n;
4019 	}
4020 	else
4021 	{
4022 	    size_t  min_field_width = 0, precision = 0;
4023 	    int	    zero_padding = 0, precision_specified = 0, justify_left = 0;
4024 	    int	    alternate_form = 0, force_sign = 0;
4025 
4026 	    /* If both the ' ' and '+' flags appear, the ' ' flag should be
4027 	     * ignored. */
4028 	    int	    space_for_positive = 1;
4029 
4030 	    /* allowed values: \0, h, l, L */
4031 	    char    length_modifier = '\0';
4032 
4033 	    /* temporary buffer for simple numeric->string conversion */
4034 #ifdef FEAT_FLOAT
4035 # define TMP_LEN 350	/* On my system 1e308 is the biggest number possible.
4036 			 * That sounds reasonable to use as the maximum
4037 			 * printable. */
4038 #else
4039 # define TMP_LEN 32
4040 #endif
4041 	    char    tmp[TMP_LEN];
4042 
4043 	    /* string address in case of string argument */
4044 	    char    *str_arg;
4045 
4046 	    /* natural field width of arg without padding and sign */
4047 	    size_t  str_arg_l;
4048 
4049 	    /* unsigned char argument value - only defined for c conversion.
4050 	     * N.B. standard explicitly states the char argument for the c
4051 	     * conversion is unsigned */
4052 	    unsigned char uchar_arg;
4053 
4054 	    /* number of zeros to be inserted for numeric conversions as
4055 	     * required by the precision or minimal field width */
4056 	    size_t  number_of_zeros_to_pad = 0;
4057 
4058 	    /* index into tmp where zero padding is to be inserted */
4059 	    size_t  zero_padding_insertion_ind = 0;
4060 
4061 	    /* current conversion specifier character */
4062 	    char    fmt_spec = '\0';
4063 
4064 	    str_arg = NULL;
4065 	    p++;  /* skip '%' */
4066 
4067 	    /* parse flags */
4068 	    while (*p == '0' || *p == '-' || *p == '+' || *p == ' '
4069 						   || *p == '#' || *p == '\'')
4070 	    {
4071 		switch (*p)
4072 		{
4073 		    case '0': zero_padding = 1; break;
4074 		    case '-': justify_left = 1; break;
4075 		    case '+': force_sign = 1; space_for_positive = 0; break;
4076 		    case ' ': force_sign = 1;
4077 			      /* If both the ' ' and '+' flags appear, the ' '
4078 			       * flag should be ignored */
4079 			      break;
4080 		    case '#': alternate_form = 1; break;
4081 		    case '\'': break;
4082 		}
4083 		p++;
4084 	    }
4085 	    /* If the '0' and '-' flags both appear, the '0' flag should be
4086 	     * ignored. */
4087 
4088 	    /* parse field width */
4089 	    if (*p == '*')
4090 	    {
4091 		int j;
4092 
4093 		p++;
4094 		j =
4095 #ifndef HAVE_STDARG_H
4096 		    get_a_arg(arg_idx);
4097 #else
4098 # if defined(FEAT_EVAL)
4099 		    tvs != NULL ? tv_nr(tvs, &arg_idx) :
4100 # endif
4101 			va_arg(ap, int);
4102 #endif
4103 		if (j >= 0)
4104 		    min_field_width = j;
4105 		else
4106 		{
4107 		    min_field_width = -j;
4108 		    justify_left = 1;
4109 		}
4110 	    }
4111 	    else if (VIM_ISDIGIT((int)(*p)))
4112 	    {
4113 		/* size_t could be wider than unsigned int; make sure we treat
4114 		 * argument like common implementations do */
4115 		unsigned int uj = *p++ - '0';
4116 
4117 		while (VIM_ISDIGIT((int)(*p)))
4118 		    uj = 10 * uj + (unsigned int)(*p++ - '0');
4119 		min_field_width = uj;
4120 	    }
4121 
4122 	    /* parse precision */
4123 	    if (*p == '.')
4124 	    {
4125 		p++;
4126 		precision_specified = 1;
4127 		if (*p == '*')
4128 		{
4129 		    int j;
4130 
4131 		    j =
4132 #ifndef HAVE_STDARG_H
4133 			get_a_arg(arg_idx);
4134 #else
4135 # if defined(FEAT_EVAL)
4136 			tvs != NULL ? tv_nr(tvs, &arg_idx) :
4137 # endif
4138 			    va_arg(ap, int);
4139 #endif
4140 		    p++;
4141 		    if (j >= 0)
4142 			precision = j;
4143 		    else
4144 		    {
4145 			precision_specified = 0;
4146 			precision = 0;
4147 		    }
4148 		}
4149 		else if (VIM_ISDIGIT((int)(*p)))
4150 		{
4151 		    /* size_t could be wider than unsigned int; make sure we
4152 		     * treat argument like common implementations do */
4153 		    unsigned int uj = *p++ - '0';
4154 
4155 		    while (VIM_ISDIGIT((int)(*p)))
4156 			uj = 10 * uj + (unsigned int)(*p++ - '0');
4157 		    precision = uj;
4158 		}
4159 	    }
4160 
4161 	    /* parse 'h', 'l' and 'll' length modifiers */
4162 	    if (*p == 'h' || *p == 'l')
4163 	    {
4164 		length_modifier = *p;
4165 		p++;
4166 		if (length_modifier == 'l' && *p == 'l')
4167 		{
4168 		    /* double l = long long */
4169 		    length_modifier = 'l';	/* treat it as a single 'l' */
4170 		    p++;
4171 		}
4172 	    }
4173 	    fmt_spec = *p;
4174 
4175 	    /* common synonyms: */
4176 	    switch (fmt_spec)
4177 	    {
4178 		case 'i': fmt_spec = 'd'; break;
4179 		case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
4180 		case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
4181 		case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
4182 		case 'F': fmt_spec = 'f'; break;
4183 		default: break;
4184 	    }
4185 
4186 	    /* get parameter value, do initial processing */
4187 	    switch (fmt_spec)
4188 	    {
4189 		/* '%' and 'c' behave similar to 's' regarding flags and field
4190 		 * widths */
4191 	    case '%':
4192 	    case 'c':
4193 	    case 's':
4194 		length_modifier = '\0';
4195 		str_arg_l = 1;
4196 		switch (fmt_spec)
4197 		{
4198 		case '%':
4199 		    str_arg = p;
4200 		    break;
4201 
4202 		case 'c':
4203 		    {
4204 			int j;
4205 
4206 			j =
4207 #ifndef HAVE_STDARG_H
4208 			    get_a_arg(arg_idx);
4209 #else
4210 # if defined(FEAT_EVAL)
4211 			    tvs != NULL ? tv_nr(tvs, &arg_idx) :
4212 # endif
4213 				va_arg(ap, int);
4214 #endif
4215 			/* standard demands unsigned char */
4216 			uchar_arg = (unsigned char)j;
4217 			str_arg = (char *)&uchar_arg;
4218 			break;
4219 		    }
4220 
4221 		case 's':
4222 		    str_arg =
4223 #ifndef HAVE_STDARG_H
4224 				(char *)get_a_arg(arg_idx);
4225 #else
4226 # if defined(FEAT_EVAL)
4227 				tvs != NULL ? tv_str(tvs, &arg_idx) :
4228 # endif
4229 				    va_arg(ap, char *);
4230 #endif
4231 		    if (str_arg == NULL)
4232 		    {
4233 			str_arg = "[NULL]";
4234 			str_arg_l = 6;
4235 		    }
4236 		    /* make sure not to address string beyond the specified
4237 		     * precision !!! */
4238 		    else if (!precision_specified)
4239 			str_arg_l = strlen(str_arg);
4240 		    /* truncate string if necessary as requested by precision */
4241 		    else if (precision == 0)
4242 			str_arg_l = 0;
4243 		    else
4244 		    {
4245 			/* Don't put the #if inside memchr(), it can be a
4246 			 * macro. */
4247 #if SIZEOF_INT <= 2
4248 			char *q = memchr(str_arg, '\0', precision);
4249 #else
4250 			/* memchr on HP does not like n > 2^31  !!! */
4251 			char *q = memchr(str_arg, '\0',
4252 				  precision <= (size_t)0x7fffffffL ? precision
4253 						       : (size_t)0x7fffffffL);
4254 #endif
4255 			str_arg_l = (q == NULL) ? precision : q - str_arg;
4256 		    }
4257 		    break;
4258 
4259 		default:
4260 		    break;
4261 		}
4262 		break;
4263 
4264 	    case 'd': case 'u': case 'o': case 'x': case 'X': case 'p':
4265 		{
4266 		    /* NOTE: the u, o, x, X and p conversion specifiers
4267 		     * imply the value is unsigned;  d implies a signed
4268 		     * value */
4269 
4270 		    /* 0 if numeric argument is zero (or if pointer is
4271 		     * NULL for 'p'), +1 if greater than zero (or nonzero
4272 		     * for unsigned arguments), -1 if negative (unsigned
4273 		     * argument is never negative) */
4274 		    int arg_sign = 0;
4275 
4276 		    /* only defined for length modifier h, or for no
4277 		     * length modifiers */
4278 		    int int_arg = 0;
4279 		    unsigned int uint_arg = 0;
4280 
4281 		    /* only defined for length modifier l */
4282 		    long int long_arg = 0;
4283 		    unsigned long int ulong_arg = 0;
4284 
4285 		    /* pointer argument value -only defined for p
4286 		     * conversion */
4287 		    void *ptr_arg = NULL;
4288 
4289 		    if (fmt_spec == 'p')
4290 		    {
4291 			length_modifier = '\0';
4292 			ptr_arg =
4293 #ifndef HAVE_STDARG_H
4294 				 (void *)get_a_arg(arg_idx);
4295 #else
4296 # if defined(FEAT_EVAL)
4297 				 tvs != NULL ? (void *)tv_str(tvs, &arg_idx) :
4298 # endif
4299 					va_arg(ap, void *);
4300 #endif
4301 			if (ptr_arg != NULL)
4302 			    arg_sign = 1;
4303 		    }
4304 		    else if (fmt_spec == 'd')
4305 		    {
4306 			/* signed */
4307 			switch (length_modifier)
4308 			{
4309 			case '\0':
4310 			case 'h':
4311 			    /* char and short arguments are passed as int. */
4312 			    int_arg =
4313 #ifndef HAVE_STDARG_H
4314 					get_a_arg(arg_idx);
4315 #else
4316 # if defined(FEAT_EVAL)
4317 					tvs != NULL ? tv_nr(tvs, &arg_idx) :
4318 # endif
4319 					    va_arg(ap, int);
4320 #endif
4321 			    if (int_arg > 0)
4322 				arg_sign =  1;
4323 			    else if (int_arg < 0)
4324 				arg_sign = -1;
4325 			    break;
4326 			case 'l':
4327 			    long_arg =
4328 #ifndef HAVE_STDARG_H
4329 					get_a_arg(arg_idx);
4330 #else
4331 # if defined(FEAT_EVAL)
4332 					tvs != NULL ? tv_nr(tvs, &arg_idx) :
4333 # endif
4334 					    va_arg(ap, long int);
4335 #endif
4336 			    if (long_arg > 0)
4337 				arg_sign =  1;
4338 			    else if (long_arg < 0)
4339 				arg_sign = -1;
4340 			    break;
4341 			}
4342 		    }
4343 		    else
4344 		    {
4345 			/* unsigned */
4346 			switch (length_modifier)
4347 			{
4348 			    case '\0':
4349 			    case 'h':
4350 				uint_arg =
4351 #ifndef HAVE_STDARG_H
4352 					    get_a_arg(arg_idx);
4353 #else
4354 # if defined(FEAT_EVAL)
4355 					    tvs != NULL ? tv_nr(tvs, &arg_idx) :
4356 # endif
4357 						va_arg(ap, unsigned int);
4358 #endif
4359 				if (uint_arg != 0)
4360 				    arg_sign = 1;
4361 				break;
4362 			    case 'l':
4363 				ulong_arg =
4364 #ifndef HAVE_STDARG_H
4365 					    get_a_arg(arg_idx);
4366 #else
4367 # if defined(FEAT_EVAL)
4368 					    tvs != NULL ? tv_nr(tvs, &arg_idx) :
4369 # endif
4370 						va_arg(ap, unsigned long int);
4371 #endif
4372 				if (ulong_arg != 0)
4373 				    arg_sign = 1;
4374 				break;
4375 			}
4376 		    }
4377 
4378 		    str_arg = tmp;
4379 		    str_arg_l = 0;
4380 
4381 		    /* NOTE:
4382 		     *   For d, i, u, o, x, and X conversions, if precision is
4383 		     *   specified, the '0' flag should be ignored. This is so
4384 		     *   with Solaris 2.6, Digital UNIX 4.0, HPUX 10, Linux,
4385 		     *   FreeBSD, NetBSD; but not with Perl.
4386 		     */
4387 		    if (precision_specified)
4388 			zero_padding = 0;
4389 		    if (fmt_spec == 'd')
4390 		    {
4391 			if (force_sign && arg_sign >= 0)
4392 			    tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
4393 			/* leave negative numbers for sprintf to handle, to
4394 			 * avoid handling tricky cases like (short int)-32768 */
4395 		    }
4396 		    else if (alternate_form)
4397 		    {
4398 			if (arg_sign != 0
4399 				     && (fmt_spec == 'x' || fmt_spec == 'X') )
4400 			{
4401 			    tmp[str_arg_l++] = '0';
4402 			    tmp[str_arg_l++] = fmt_spec;
4403 			}
4404 			/* alternate form should have no effect for p
4405 			 * conversion, but ... */
4406 		    }
4407 
4408 		    zero_padding_insertion_ind = str_arg_l;
4409 		    if (!precision_specified)
4410 			precision = 1;   /* default precision is 1 */
4411 		    if (precision == 0 && arg_sign == 0)
4412 		    {
4413 			/* When zero value is formatted with an explicit
4414 			 * precision 0, the resulting formatted string is
4415 			 * empty (d, i, u, o, x, X, p).   */
4416 		    }
4417 		    else
4418 		    {
4419 			char	f[5];
4420 			int	f_l = 0;
4421 
4422 			/* construct a simple format string for sprintf */
4423 			f[f_l++] = '%';
4424 			if (!length_modifier)
4425 			    ;
4426 			else if (length_modifier == '2')
4427 			{
4428 			    f[f_l++] = 'l';
4429 			    f[f_l++] = 'l';
4430 			}
4431 			else
4432 			    f[f_l++] = length_modifier;
4433 			f[f_l++] = fmt_spec;
4434 			f[f_l++] = '\0';
4435 
4436 			if (fmt_spec == 'p')
4437 			    str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg);
4438 			else if (fmt_spec == 'd')
4439 			{
4440 			    /* signed */
4441 			    switch (length_modifier)
4442 			    {
4443 			    case '\0':
4444 			    case 'h': str_arg_l += sprintf(
4445 						 tmp + str_arg_l, f, int_arg);
4446 				      break;
4447 			    case 'l': str_arg_l += sprintf(
4448 						tmp + str_arg_l, f, long_arg);
4449 				      break;
4450 			    }
4451 			}
4452 			else
4453 			{
4454 			    /* unsigned */
4455 			    switch (length_modifier)
4456 			    {
4457 			    case '\0':
4458 			    case 'h': str_arg_l += sprintf(
4459 						tmp + str_arg_l, f, uint_arg);
4460 				      break;
4461 			    case 'l': str_arg_l += sprintf(
4462 					       tmp + str_arg_l, f, ulong_arg);
4463 				      break;
4464 			    }
4465 			}
4466 
4467 			/* include the optional minus sign and possible
4468 			 * "0x" in the region before the zero padding
4469 			 * insertion point */
4470 			if (zero_padding_insertion_ind < str_arg_l
4471 				&& tmp[zero_padding_insertion_ind] == '-')
4472 			    zero_padding_insertion_ind++;
4473 			if (zero_padding_insertion_ind + 1 < str_arg_l
4474 				&& tmp[zero_padding_insertion_ind]   == '0'
4475 				&& (tmp[zero_padding_insertion_ind + 1] == 'x'
4476 				 || tmp[zero_padding_insertion_ind + 1] == 'X'))
4477 			    zero_padding_insertion_ind += 2;
4478 		    }
4479 
4480 		    {
4481 			size_t num_of_digits = str_arg_l
4482 						 - zero_padding_insertion_ind;
4483 
4484 			if (alternate_form && fmt_spec == 'o'
4485 				/* unless zero is already the first
4486 				 * character */
4487 				&& !(zero_padding_insertion_ind < str_arg_l
4488 				    && tmp[zero_padding_insertion_ind] == '0'))
4489 			{
4490 			    /* assure leading zero for alternate-form
4491 			     * octal numbers */
4492 			    if (!precision_specified
4493 					     || precision < num_of_digits + 1)
4494 			    {
4495 				/* precision is increased to force the
4496 				 * first character to be zero, except if a
4497 				 * zero value is formatted with an
4498 				 * explicit precision of zero */
4499 				precision = num_of_digits + 1;
4500 				precision_specified = 1;
4501 			    }
4502 			}
4503 			/* zero padding to specified precision? */
4504 			if (num_of_digits < precision)
4505 			    number_of_zeros_to_pad = precision - num_of_digits;
4506 		    }
4507 		    /* zero padding to specified minimal field width? */
4508 		    if (!justify_left && zero_padding)
4509 		    {
4510 			int n = (int)(min_field_width - (str_arg_l
4511 						    + number_of_zeros_to_pad));
4512 			if (n > 0)
4513 			    number_of_zeros_to_pad += n;
4514 		    }
4515 		    break;
4516 		}
4517 
4518 #ifdef FEAT_FLOAT
4519 	    case 'f':
4520 	    case 'e':
4521 	    case 'E':
4522 	    case 'g':
4523 	    case 'G':
4524 		{
4525 		    /* Floating point. */
4526 		    double	f;
4527 		    double	abs_f;
4528 		    char	format[40];
4529 		    int		l;
4530 		    int		remove_trailing_zeroes = FALSE;
4531 
4532 		    f =
4533 # ifndef HAVE_STDARG_H
4534 			get_a_arg(arg_idx);
4535 # else
4536 #  if defined(FEAT_EVAL)
4537 			tvs != NULL ? tv_float(tvs, &arg_idx) :
4538 #  endif
4539 			    va_arg(ap, double);
4540 # endif
4541 		    abs_f = f < 0 ? -f : f;
4542 
4543 		    if (fmt_spec == 'g' || fmt_spec == 'G')
4544 		    {
4545 			/* Would be nice to use %g directly, but it prints
4546 			 * "1.0" as "1", we don't want that. */
4547 			if ((abs_f >= 0.001 && abs_f < 10000000.0)
4548 							      || abs_f == 0.0)
4549 			    fmt_spec = 'f';
4550 			else
4551 			    fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
4552 			remove_trailing_zeroes = TRUE;
4553 		    }
4554 
4555 		    if (fmt_spec == 'f' && abs_f > 1.0e307)
4556 		    {
4557 			/* Avoid a buffer overflow */
4558 			strcpy(tmp, "inf");
4559 			str_arg_l = 3;
4560 		    }
4561 		    else
4562 		    {
4563 			format[0] = '%';
4564 			l = 1;
4565 			if (precision_specified)
4566 			{
4567 			    size_t max_prec = TMP_LEN - 10;
4568 
4569 			    /* Make sure we don't get more digits than we
4570 			     * have room for. */
4571 			    if (fmt_spec == 'f' && abs_f > 1.0)
4572 				max_prec -= (size_t)log10(abs_f);
4573 			    if (precision > max_prec)
4574 				precision = max_prec;
4575 			    l += sprintf(format + 1, ".%d", (int)precision);
4576 			}
4577 			format[l] = fmt_spec;
4578 			format[l + 1] = NUL;
4579 			str_arg_l = sprintf(tmp, format, f);
4580 
4581 			if (remove_trailing_zeroes)
4582 			{
4583 			    int i;
4584 			    char *p;
4585 
4586 			    /* Using %g or %G: remove superfluous zeroes. */
4587 			    if (fmt_spec == 'f')
4588 				p = tmp + str_arg_l - 1;
4589 			    else
4590 			    {
4591 				p = (char *)vim_strchr((char_u *)tmp,
4592 						 fmt_spec == 'e' ? 'e' : 'E');
4593 				if (p != NULL)
4594 				{
4595 				    /* Remove superfluous '+' and leading
4596 				     * zeroes from the exponent. */
4597 				    if (p[1] == '+')
4598 				    {
4599 					/* Change "1.0e+07" to "1.0e07" */
4600 					STRMOVE(p + 1, p + 2);
4601 					--str_arg_l;
4602 				    }
4603 				    i = (p[1] == '-') ? 2 : 1;
4604 				    while (p[i] == '0')
4605 				    {
4606 					/* Change "1.0e07" to "1.0e7" */
4607 					STRMOVE(p + i, p + i + 1);
4608 					--str_arg_l;
4609 				    }
4610 				    --p;
4611 				}
4612 			    }
4613 
4614 			    if (p != NULL && !precision_specified)
4615 				/* Remove trailing zeroes, but keep the one
4616 				 * just after a dot. */
4617 				while (p > tmp + 2 && *p == '0' && p[-1] != '.')
4618 				{
4619 				    STRMOVE(p, p + 1);
4620 				    --p;
4621 				    --str_arg_l;
4622 				}
4623 			}
4624 			else
4625 			{
4626 			    char *p;
4627 
4628 			    /* Be consistent: some printf("%e") use 1.0e+12
4629 			     * and some 1.0e+012.  Remove one zero in the last
4630 			     * case. */
4631 			    p = (char *)vim_strchr((char_u *)tmp,
4632 						 fmt_spec == 'e' ? 'e' : 'E');
4633 			    if (p != NULL && (p[1] == '+' || p[1] == '-')
4634 					  && p[2] == '0'
4635 					  && vim_isdigit(p[3])
4636 					  && vim_isdigit(p[4]))
4637 			    {
4638 				STRMOVE(p + 2, p + 3);
4639 				--str_arg_l;
4640 			    }
4641 			}
4642 		    }
4643 		    str_arg = tmp;
4644 		    break;
4645 		}
4646 #endif
4647 
4648 	    default:
4649 		/* unrecognized conversion specifier, keep format string
4650 		 * as-is */
4651 		zero_padding = 0;  /* turn zero padding off for non-numeric
4652 				      conversion */
4653 		justify_left = 1;
4654 		min_field_width = 0;		    /* reset flags */
4655 
4656 		/* discard the unrecognized conversion, just keep *
4657 		 * the unrecognized conversion character	  */
4658 		str_arg = p;
4659 		str_arg_l = 0;
4660 		if (*p != NUL)
4661 		    str_arg_l++;  /* include invalid conversion specifier
4662 				     unchanged if not at end-of-string */
4663 		break;
4664 	    }
4665 
4666 	    if (*p != NUL)
4667 		p++;     /* step over the just processed conversion specifier */
4668 
4669 	    /* insert padding to the left as requested by min_field_width;
4670 	     * this does not include the zero padding in case of numerical
4671 	     * conversions*/
4672 	    if (!justify_left)
4673 	    {
4674 		/* left padding with blank or zero */
4675 		int pn = (int)(min_field_width - (str_arg_l + number_of_zeros_to_pad));
4676 
4677 		if (pn > 0)
4678 		{
4679 		    if (str_l < str_m)
4680 		    {
4681 			size_t avail = str_m - str_l;
4682 
4683 			vim_memset(str + str_l, zero_padding ? '0' : ' ',
4684 					     (size_t)pn > avail ? avail : pn);
4685 		    }
4686 		    str_l += pn;
4687 		}
4688 	    }
4689 
4690 	    /* zero padding as requested by the precision or by the minimal
4691 	     * field width for numeric conversions required? */
4692 	    if (number_of_zeros_to_pad == 0)
4693 	    {
4694 		/* will not copy first part of numeric right now, *
4695 		 * force it to be copied later in its entirety    */
4696 		zero_padding_insertion_ind = 0;
4697 	    }
4698 	    else
4699 	    {
4700 		/* insert first part of numerics (sign or '0x') before zero
4701 		 * padding */
4702 		int zn = (int)zero_padding_insertion_ind;
4703 
4704 		if (zn > 0)
4705 		{
4706 		    if (str_l < str_m)
4707 		    {
4708 			size_t avail = str_m - str_l;
4709 
4710 			mch_memmove(str + str_l, str_arg,
4711 					     (size_t)zn > avail ? avail : zn);
4712 		    }
4713 		    str_l += zn;
4714 		}
4715 
4716 		/* insert zero padding as requested by the precision or min
4717 		 * field width */
4718 		zn = (int)number_of_zeros_to_pad;
4719 		if (zn > 0)
4720 		{
4721 		    if (str_l < str_m)
4722 		    {
4723 			size_t avail = str_m-str_l;
4724 
4725 			vim_memset(str + str_l, '0',
4726 					     (size_t)zn > avail ? avail : zn);
4727 		    }
4728 		    str_l += zn;
4729 		}
4730 	    }
4731 
4732 	    /* insert formatted string
4733 	     * (or as-is conversion specifier for unknown conversions) */
4734 	    {
4735 		int sn = (int)(str_arg_l - zero_padding_insertion_ind);
4736 
4737 		if (sn > 0)
4738 		{
4739 		    if (str_l < str_m)
4740 		    {
4741 			size_t avail = str_m - str_l;
4742 
4743 			mch_memmove(str + str_l,
4744 				str_arg + zero_padding_insertion_ind,
4745 				(size_t)sn > avail ? avail : sn);
4746 		    }
4747 		    str_l += sn;
4748 		}
4749 	    }
4750 
4751 	    /* insert right padding */
4752 	    if (justify_left)
4753 	    {
4754 		/* right blank padding to the field width */
4755 		int pn = (int)(min_field_width
4756 				      - (str_arg_l + number_of_zeros_to_pad));
4757 
4758 		if (pn > 0)
4759 		{
4760 		    if (str_l < str_m)
4761 		    {
4762 			size_t avail = str_m - str_l;
4763 
4764 			vim_memset(str + str_l, ' ',
4765 					     (size_t)pn > avail ? avail : pn);
4766 		    }
4767 		    str_l += pn;
4768 		}
4769 	    }
4770 	}
4771     }
4772 
4773     if (str_m > 0)
4774     {
4775 	/* make sure the string is nul-terminated even at the expense of
4776 	 * overwriting the last character (shouldn't happen, but just in case)
4777 	 * */
4778 	str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0';
4779     }
4780 
4781 #ifdef HAVE_STDARG_H
4782     if (tvs != NULL && tvs[arg_idx - 1].v_type != VAR_UNKNOWN)
4783 	EMSG(_("E767: Too many arguments to printf()"));
4784 #endif
4785 
4786     /* Return the number of characters formatted (excluding trailing nul
4787      * character), that is, the number of characters that would have been
4788      * written to the buffer if it were large enough. */
4789     return (int)str_l;
4790 }
4791 
4792 #endif /* PROTO */
4793