xref: /vim-8.2.3635/src/message.c (revision ba02e472)
1 /* vi:set ts=8 sts=4 sw=4 noet:
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 static void add_msg_hist(char_u *s, int len, int attr);
19 static void hit_return_msg(void);
20 static void msg_home_replace_attr(char_u *fname, int attr);
21 static void msg_puts_attr_len(char *str, int maxlen, int attr);
22 static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse);
23 static void msg_scroll_up(void);
24 static void inc_msg_scrolled(void);
25 static void store_sb_text(char_u **sb_str, char_u *s, int attr, int *sb_col, int finish);
26 static void t_puts(int *t_col, char_u *t_s, char_u *s, int attr);
27 static void msg_puts_printf(char_u *str, int maxlen);
28 static int do_more_prompt(int typed_char);
29 static void msg_screen_putchar(int c, int attr);
30 static void msg_moremsg(int full);
31 static int  msg_check_screen(void);
32 static void redir_write(char_u *s, int maxlen);
33 #ifdef FEAT_CON_DIALOG
34 static char_u *msg_show_console_dialog(char_u *message, char_u *buttons, int dfltbutton);
35 static int	confirm_msg_used = FALSE;	// displaying confirm_msg
36 static char_u	*confirm_msg = NULL;		// ":confirm" message
37 static char_u	*confirm_msg_tail;		// tail of confirm_msg
38 static void display_confirm_msg(void);
39 #endif
40 #ifdef FEAT_JOB_CHANNEL
41 static int emsg_to_channel_log = FALSE;
42 #endif
43 
44 struct msg_hist
45 {
46     struct msg_hist	*next;
47     char_u		*msg;
48     int			attr;
49 };
50 
51 static struct msg_hist *first_msg_hist = NULL;
52 static struct msg_hist *last_msg_hist = NULL;
53 static int msg_hist_len = 0;
54 
55 static FILE *verbose_fd = NULL;
56 static int  verbose_did_open = FALSE;
57 
58 /*
59  * When writing messages to the screen, there are many different situations.
60  * A number of variables is used to remember the current state:
61  * msg_didany	    TRUE when messages were written since the last time the
62  *		    user reacted to a prompt.
63  *		    Reset: After hitting a key for the hit-return prompt,
64  *		    hitting <CR> for the command line or input().
65  *		    Set: When any message is written to the screen.
66  * msg_didout	    TRUE when something was written to the current line.
67  *		    Reset: When advancing to the next line, when the current
68  *		    text can be overwritten.
69  *		    Set: When any message is written to the screen.
70  * msg_nowait	    No extra delay for the last drawn message.
71  *		    Used in normal_cmd() before the mode message is drawn.
72  * emsg_on_display  There was an error message recently.  Indicates that there
73  *		    should be a delay before redrawing.
74  * msg_scroll	    The next message should not overwrite the current one.
75  * msg_scrolled	    How many lines the screen has been scrolled (because of
76  *		    messages).  Used in update_screen() to scroll the screen
77  *		    back.  Incremented each time the screen scrolls a line.
78  * msg_scrolled_ign  TRUE when msg_scrolled is non-zero and msg_puts_attr()
79  *		    writes something without scrolling should not make
80  *		    need_wait_return to be set.  This is a hack to make ":ts"
81  *		    work without an extra prompt.
82  * lines_left	    Number of lines available for messages before the
83  *		    more-prompt is to be given.  -1 when not set.
84  * need_wait_return TRUE when the hit-return prompt is needed.
85  *		    Reset: After giving the hit-return prompt, when the user
86  *		    has answered some other prompt.
87  *		    Set: When the ruler or typeahead display is overwritten,
88  *		    scrolling the screen for some message.
89  * keep_msg	    Message to be displayed after redrawing the screen, in
90  *		    main_loop().
91  *		    This is an allocated string or NULL when not used.
92  */
93 
94 /*
95  * msg(s) - displays the string 's' on the status line
96  * When terminal not initialized (yet) mch_errmsg(..) is used.
97  * return TRUE if wait_return not called
98  */
99     int
100 msg(char *s)
101 {
102     return msg_attr_keep(s, 0, FALSE);
103 }
104 
105 /*
106  * Like msg() but keep it silent when 'verbosefile' is set.
107  */
108     int
109 verb_msg(char *s)
110 {
111     int		n;
112 
113     verbose_enter();
114     n = msg_attr_keep(s, 0, FALSE);
115     verbose_leave();
116 
117     return n;
118 }
119 
120     int
121 msg_attr(char *s, int attr)
122 {
123     return msg_attr_keep(s, attr, FALSE);
124 }
125 
126     int
127 msg_attr_keep(
128     char	*s,
129     int		attr,
130     int		keep)	    // TRUE: set keep_msg if it doesn't scroll
131 {
132     static int	entered = 0;
133     int		retval;
134     char_u	*buf = NULL;
135 
136     // Skip messages not matching ":filter pattern".
137     // Don't filter when there is an error.
138     if (!emsg_on_display && message_filtered((char_u *)s))
139 	return TRUE;
140 
141 #ifdef FEAT_EVAL
142     if (attr == 0)
143 	set_vim_var_string(VV_STATUSMSG, (char_u *)s, -1);
144 #endif
145 
146     /*
147      * It is possible that displaying a messages causes a problem (e.g.,
148      * when redrawing the window), which causes another message, etc..	To
149      * break this loop, limit the recursiveness to 3 levels.
150      */
151     if (entered >= 3)
152 	return TRUE;
153     ++entered;
154 
155     // Add message to history (unless it's a repeated kept message or a
156     // truncated message)
157     if ((char_u *)s != keep_msg
158 	    || (*s != '<'
159 		&& last_msg_hist != NULL
160 		&& last_msg_hist->msg != NULL
161 		&& STRCMP(s, last_msg_hist->msg)))
162 	add_msg_hist((char_u *)s, -1, attr);
163 
164 #ifdef FEAT_JOB_CHANNEL
165     if (emsg_to_channel_log)
166 	// Write message in the channel log.
167 	ch_log(NULL, "ERROR: %s", (char *)s);
168 #endif
169 
170     // Truncate the message if needed.
171     msg_start();
172     buf = msg_strtrunc((char_u *)s, FALSE);
173     if (buf != NULL)
174 	s = (char *)buf;
175 
176     msg_outtrans_attr((char_u *)s, attr);
177     msg_clr_eos();
178     retval = msg_end();
179 
180     if (keep && retval && vim_strsize((char_u *)s)
181 			    < (int)(Rows - cmdline_row - 1) * Columns + sc_col)
182 	set_keep_msg((char_u *)s, 0);
183 
184     vim_free(buf);
185     --entered;
186     return retval;
187 }
188 
189 /*
190  * Truncate a string such that it can be printed without causing a scroll.
191  * Returns an allocated string or NULL when no truncating is done.
192  */
193     char_u *
194 msg_strtrunc(
195     char_u	*s,
196     int		force)	    // always truncate
197 {
198     char_u	*buf = NULL;
199     int		len;
200     int		room;
201 
202     // May truncate message to avoid a hit-return prompt
203     if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL)
204 			       && !exmode_active && msg_silent == 0) || force)
205     {
206 	len = vim_strsize(s);
207 	if (msg_scrolled != 0)
208 	    // Use all the columns.
209 	    room = (int)(Rows - msg_row) * Columns - 1;
210 	else
211 	    // Use up to 'showcmd' column.
212 	    room = (int)(Rows - msg_row - 1) * Columns + sc_col - 1;
213 	if (len > room && room > 0)
214 	{
215 	    if (enc_utf8)
216 		// may have up to 18 bytes per cell (6 per char, up to two
217 		// composing chars)
218 		len = (room + 2) * 18;
219 	    else if (enc_dbcs == DBCS_JPNU)
220 		// may have up to 2 bytes per cell for euc-jp
221 		len = (room + 2) * 2;
222 	    else
223 		len = room + 2;
224 	    buf = alloc(len);
225 	    if (buf != NULL)
226 		trunc_string(s, buf, room, len);
227 	}
228     }
229     return buf;
230 }
231 
232 /*
233  * Truncate a string "s" to "buf" with cell width "room".
234  * "s" and "buf" may be equal.
235  */
236     void
237 trunc_string(
238     char_u	*s,
239     char_u	*buf,
240     int		room_in,
241     int		buflen)
242 {
243     size_t	room = room_in - 3; // "..." takes 3 chars
244     size_t	half;
245     size_t	len = 0;
246     int		e;
247     int		i;
248     int		n;
249 
250     if (*s == NUL)
251     {
252 	if (buflen > 0)
253 	    *buf = NUL;
254 	return;
255     }
256 
257     if (room_in < 3)
258 	room = 0;
259     half = room / 2;
260 
261     // First part: Start of the string.
262     for (e = 0; len < half && e < buflen; ++e)
263     {
264 	if (s[e] == NUL)
265 	{
266 	    // text fits without truncating!
267 	    buf[e] = NUL;
268 	    return;
269 	}
270 	n = ptr2cells(s + e);
271 	if (len + n > half)
272 	    break;
273 	len += n;
274 	buf[e] = s[e];
275 	if (has_mbyte)
276 	    for (n = (*mb_ptr2len)(s + e); --n > 0; )
277 	    {
278 		if (++e == buflen)
279 		    break;
280 		buf[e] = s[e];
281 	    }
282     }
283 
284     // Last part: End of the string.
285     i = e;
286     if (enc_dbcs != 0)
287     {
288 	// For DBCS going backwards in a string is slow, but
289 	// computing the cell width isn't too slow: go forward
290 	// until the rest fits.
291 	n = vim_strsize(s + i);
292 	while (len + n > room)
293 	{
294 	    n -= ptr2cells(s + i);
295 	    i += (*mb_ptr2len)(s + i);
296 	}
297     }
298     else if (enc_utf8)
299     {
300 	// For UTF-8 we can go backwards easily.
301 	half = i = (int)STRLEN(s);
302 	for (;;)
303 	{
304 	    do
305 		half = half - utf_head_off(s, s + half - 1) - 1;
306 	    while (half > 0 && utf_iscomposing(utf_ptr2char(s + half)));
307 	    n = ptr2cells(s + half);
308 	    if (len + n > room || half == 0)
309 		break;
310 	    len += n;
311 	    i = (int)half;
312 	}
313     }
314     else
315     {
316 	for (i = (int)STRLEN(s);
317 		   i - 1 >= 0 && len + (n = ptr2cells(s + i - 1)) <= room; --i)
318 	    len += n;
319     }
320 
321 
322     if (i <= e + 3)
323     {
324 	// text fits without truncating
325 	if (s != buf)
326 	{
327 	    len = STRLEN(s);
328 	    if (len >= (size_t)buflen)
329 		len = buflen - 1;
330 	    len = len - e + 1;
331 	    if (len < 1)
332 		buf[e - 1] = NUL;
333 	    else
334 		mch_memmove(buf + e, s + e, len);
335 	}
336     }
337     else if (e + 3 < buflen)
338     {
339 	// set the middle and copy the last part
340 	mch_memmove(buf + e, "...", (size_t)3);
341 	len = STRLEN(s + i) + 1;
342 	if (len >= (size_t)buflen - e - 3)
343 	    len = buflen - e - 3 - 1;
344 	mch_memmove(buf + e + 3, s + i, len);
345 	buf[e + 3 + len - 1] = NUL;
346     }
347     else
348     {
349 	// can't fit in the "...", just truncate it
350 	buf[e - 1] = NUL;
351     }
352 }
353 
354 /*
355  * Automatic prototype generation does not understand this function.
356  * Note: Caller of smsg() and smsg_attr() must check the resulting string is
357  * shorter than IOSIZE!!!
358  */
359 #ifndef PROTO
360 
361 int vim_snprintf(char *str, size_t str_m, const char *fmt, ...);
362 
363     int
364 smsg(const char *s, ...)
365 {
366     if (IObuff == NULL)
367     {
368 	// Very early in initialisation and already something wrong, just
369 	// give the raw message so the user at least gets a hint.
370 	return msg((char *)s);
371     }
372     else
373     {
374 	va_list arglist;
375 
376 	va_start(arglist, s);
377 	vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist);
378 	va_end(arglist);
379 	return msg((char *)IObuff);
380     }
381 }
382 
383     int
384 smsg_attr(int attr, const char *s, ...)
385 {
386     if (IObuff == NULL)
387     {
388 	// Very early in initialisation and already something wrong, just
389 	// give the raw message so the user at least gets a hint.
390 	return msg_attr((char *)s, attr);
391     }
392     else
393     {
394 	va_list arglist;
395 
396 	va_start(arglist, s);
397 	vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist);
398 	va_end(arglist);
399 	return msg_attr((char *)IObuff, attr);
400     }
401 }
402 
403     int
404 smsg_attr_keep(int attr, const char *s, ...)
405 {
406     if (IObuff == NULL)
407     {
408 	// Very early in initialisation and already something wrong, just
409 	// give the raw message so the user at least gets a hint.
410 	return msg_attr_keep((char *)s, attr, TRUE);
411     }
412     else
413     {
414 	va_list arglist;
415 
416 	va_start(arglist, s);
417 	vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist);
418 	va_end(arglist);
419 	return msg_attr_keep((char *)IObuff, attr, TRUE);
420     }
421 }
422 
423 #endif
424 
425 /*
426  * Remember the last sourcing name/lnum used in an error message, so that it
427  * isn't printed each time when it didn't change.
428  */
429 static int	last_sourcing_lnum = 0;
430 static char_u   *last_sourcing_name = NULL;
431 
432 /*
433  * Reset the last used sourcing name/lnum.  Makes sure it is displayed again
434  * for the next error message;
435  */
436     void
437 reset_last_sourcing(void)
438 {
439     VIM_CLEAR(last_sourcing_name);
440     last_sourcing_lnum = 0;
441 }
442 
443 /*
444  * Return TRUE if "SOURCING_NAME" differs from "last_sourcing_name".
445  */
446     static int
447 other_sourcing_name(void)
448 {
449     if (SOURCING_NAME != NULL)
450     {
451 	if (last_sourcing_name != NULL)
452 	    return STRCMP(SOURCING_NAME, last_sourcing_name) != 0;
453 	return TRUE;
454     }
455     return FALSE;
456 }
457 
458 /*
459  * Get the message about the source, as used for an error message.
460  * Returns an allocated string with room for one more character.
461  * Returns NULL when no message is to be given.
462  */
463     static char_u *
464 get_emsg_source(void)
465 {
466     char_u	*Buf, *p;
467 
468     if (SOURCING_NAME != NULL && other_sourcing_name())
469     {
470 	char_u	    *sname = estack_sfile(ESTACK_NONE);
471 	char_u	    *tofree = sname;
472 
473 	if (sname == NULL)
474 	    sname = SOURCING_NAME;
475 
476 #ifdef FEAT_EVAL
477 	if (estack_compiling)
478 	    p = (char_u *)_("Error detected while compiling %s:");
479 	else
480 #endif
481 	    p = (char_u *)_("Error detected while processing %s:");
482 	Buf = alloc(STRLEN(sname) + STRLEN(p));
483 	if (Buf != NULL)
484 	    sprintf((char *)Buf, (char *)p, sname);
485 	vim_free(tofree);
486 	return Buf;
487     }
488     return NULL;
489 }
490 
491 /*
492  * Get the message about the source lnum, as used for an error message.
493  * Returns an allocated string with room for one more character.
494  * Returns NULL when no message is to be given.
495  */
496     static char_u *
497 get_emsg_lnum(void)
498 {
499     char_u	*Buf, *p;
500 
501     // lnum is 0 when executing a command from the command line
502     // argument, we don't want a line number then
503     if (SOURCING_NAME != NULL
504 	    && (other_sourcing_name() || SOURCING_LNUM != last_sourcing_lnum)
505 	    && SOURCING_LNUM != 0)
506     {
507 	p = (char_u *)_("line %4ld:");
508 	Buf = alloc(STRLEN(p) + 20);
509 	if (Buf != NULL)
510 	    sprintf((char *)Buf, (char *)p, (long)SOURCING_LNUM);
511 	return Buf;
512     }
513     return NULL;
514 }
515 
516 /*
517  * Display name and line number for the source of an error.
518  * Remember the file name and line number, so that for the next error the info
519  * is only displayed if it changed.
520  */
521     void
522 msg_source(int attr)
523 {
524     char_u	*p;
525 
526     ++no_wait_return;
527     p = get_emsg_source();
528     if (p != NULL)
529     {
530 	msg_attr((char *)p, attr);
531 	vim_free(p);
532     }
533     p = get_emsg_lnum();
534     if (p != NULL)
535     {
536 	msg_attr((char *)p, HL_ATTR(HLF_N));
537 	vim_free(p);
538 	last_sourcing_lnum = SOURCING_LNUM;  // only once for each line
539     }
540 
541     // remember the last sourcing name printed, also when it's empty
542     if (SOURCING_NAME == NULL || other_sourcing_name())
543     {
544 	vim_free(last_sourcing_name);
545 	if (SOURCING_NAME == NULL)
546 	    last_sourcing_name = NULL;
547 	else
548 	    last_sourcing_name = vim_strsave(SOURCING_NAME);
549     }
550     --no_wait_return;
551 }
552 
553 /*
554  * Return TRUE if not giving error messages right now:
555  * If "emsg_off" is set: no error messages at the moment.
556  * If "msg" is in 'debug': do error message but without side effects.
557  * If "emsg_skip" is set: never do error messages.
558  */
559     static int
560 emsg_not_now(void)
561 {
562     if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL
563 					  && vim_strchr(p_debug, 't') == NULL)
564 #ifdef FEAT_EVAL
565 	    || emsg_skip > 0
566 #endif
567 	    )
568 	return TRUE;
569     return FALSE;
570 }
571 
572 #if defined(FEAT_EVAL) || defined(PROTO)
573 static garray_T ignore_error_list = GA_EMPTY;
574 
575     void
576 ignore_error_for_testing(char_u *error)
577 {
578     if (ignore_error_list.ga_itemsize == 0)
579 	ga_init2(&ignore_error_list, sizeof(char_u *), 1);
580 
581     if (STRCMP("RESET", error) == 0)
582 	ga_clear_strings(&ignore_error_list);
583     else
584 	ga_add_string(&ignore_error_list, error);
585 }
586 
587     static int
588 ignore_error(char_u *msg)
589 {
590     int i;
591 
592     for (i = 0; i < ignore_error_list.ga_len; ++i)
593 	if (strstr((char *)msg,
594 		  (char *)((char_u **)(ignore_error_list.ga_data))[i]) != NULL)
595 	    return TRUE;
596     return FALSE;
597 }
598 #endif
599 
600 #if !defined(HAVE_STRERROR) || defined(PROTO)
601 /*
602  * Replacement for perror() that behaves more or less like emsg() was called.
603  * v:errmsg will be set and called_emsg will be incremented.
604  */
605     void
606 do_perror(char *msg)
607 {
608     perror(msg);
609     ++emsg_silent;
610     emsg(msg);
611     --emsg_silent;
612 }
613 #endif
614 
615 /*
616  * emsg_core() - display an error message
617  *
618  * Rings the bell, if appropriate, and calls message() to do the real work
619  * When terminal not initialized (yet) mch_errmsg(..) is used.
620  *
621  * Return TRUE if wait_return not called.
622  * Note: caller must check 'emsg_not_now()' before calling this.
623  */
624     static int
625 emsg_core(char_u *s)
626 {
627     int		attr;
628     char_u	*p;
629     int		r;
630 #ifdef FEAT_EVAL
631     int		ignore = FALSE;
632     int		severe;
633 #endif
634 
635 #ifdef FEAT_EVAL
636     // When testing some errors are turned into a normal message.
637     if (ignore_error(s))
638 	// don't call msg() if it results in a dialog
639 	return msg_use_printf() ? FALSE : msg((char *)s);
640 #endif
641 
642     ++called_emsg;
643 
644 #ifdef FEAT_EVAL
645     // If "emsg_severe" is TRUE: When an error exception is to be thrown,
646     // prefer this message over previous messages for the same command.
647     severe = emsg_severe;
648     emsg_severe = FALSE;
649 #endif
650 
651     if (!emsg_off || vim_strchr(p_debug, 't') != NULL)
652     {
653 #ifdef FEAT_EVAL
654 	/*
655 	 * Cause a throw of an error exception if appropriate.  Don't display
656 	 * the error message in this case.  (If no matching catch clause will
657 	 * be found, the message will be displayed later on.)  "ignore" is set
658 	 * when the message should be ignored completely (used for the
659 	 * interrupt message).
660 	 */
661 	if (cause_errthrow(s, severe, &ignore) == TRUE)
662 	{
663 	    if (!ignore)
664 		++did_emsg;
665 	    return TRUE;
666 	}
667 
668 	if (in_assert_fails && emsg_assert_fails_msg == NULL)
669 	{
670 	    emsg_assert_fails_msg = vim_strsave(s);
671 	    emsg_assert_fails_lnum = SOURCING_LNUM;
672 	    vim_free(emsg_assert_fails_context);
673 	    emsg_assert_fails_context = vim_strsave(
674 			 SOURCING_NAME == NULL ? (char_u *)"" : SOURCING_NAME);
675 	}
676 
677 	// set "v:errmsg", also when using ":silent! cmd"
678 	set_vim_var_string(VV_ERRMSG, s, -1);
679 #endif
680 
681 	/*
682 	 * When using ":silent! cmd" ignore error messages.
683 	 * But do write it to the redirection file.
684 	 */
685 	if (emsg_silent != 0)
686 	{
687 #ifdef FEAT_EVAL
688 	    ++did_emsg_silent;
689 #endif
690 	    if (emsg_noredir == 0)
691 	    {
692 		msg_start();
693 		p = get_emsg_source();
694 		if (p != NULL)
695 		{
696 		    STRCAT(p, "\n");
697 		    redir_write(p, -1);
698 		    vim_free(p);
699 		}
700 		p = get_emsg_lnum();
701 		if (p != NULL)
702 		{
703 		    STRCAT(p, "\n");
704 		    redir_write(p, -1);
705 		    vim_free(p);
706 		}
707 		redir_write(s, -1);
708 	    }
709 #ifdef FEAT_EVAL
710 	    // Only increment did_emsg_def when :silent! wasn't used inside the
711 	    // :def function.
712 	    if (emsg_silent == emsg_silent_def)
713 		++did_emsg_def;
714 #endif
715 #ifdef FEAT_JOB_CHANNEL
716 	    ch_log(NULL, "ERROR silent: %s", (char *)s);
717 #endif
718 	    return TRUE;
719 	}
720 
721 	ex_exitval = 1;
722 
723 	// Reset msg_silent, an error causes messages to be switched back on.
724 	msg_silent = 0;
725 	cmd_silent = FALSE;
726 
727 	if (global_busy)		// break :global command
728 	    ++global_busy;
729 
730 	if (p_eb)
731 	    beep_flush();		// also includes flush_buffers()
732 	else
733 	    flush_buffers(FLUSH_MINIMAL);  // flush internal buffers
734 	++did_emsg;			   // flag for DoOneCmd()
735 #ifdef FEAT_EVAL
736 	++uncaught_emsg;
737 #endif
738     }
739 
740     emsg_on_display = TRUE;	// remember there is an error message
741     ++msg_scroll;		// don't overwrite a previous message
742     attr = HL_ATTR(HLF_E);	// set highlight mode for error messages
743     if (msg_scrolled != 0)
744 	need_wait_return = TRUE;    // needed in case emsg() is called after
745 				    // wait_return has reset need_wait_return
746 				    // and a redraw is expected because
747 				    // msg_scrolled is non-zero
748 
749 #ifdef FEAT_JOB_CHANNEL
750     emsg_to_channel_log = TRUE;
751 #endif
752     /*
753      * Display name and line number for the source of the error.
754      */
755     msg_source(attr);
756 
757     /*
758      * Display the error message itself.
759      */
760     msg_nowait = FALSE;			// wait for this msg
761     r = msg_attr((char *)s, attr);
762 
763 #ifdef FEAT_JOB_CHANNEL
764     emsg_to_channel_log = FALSE;
765 #endif
766     return r;
767 }
768 
769 /*
770  * Print an error message.
771  */
772     int
773 emsg(char *s)
774 {
775     // Skip this if not giving error messages at the moment.
776     if (!emsg_not_now())
777 	return emsg_core((char_u *)s);
778     return TRUE;		// no error messages at the moment
779 }
780 
781 #ifndef PROTO  // manual proto with __attribute__
782 /*
783  * Print an error message with format string and variable arguments.
784  * Note: caller must not pass 'IObuff' as 1st argument.
785  */
786     int
787 semsg(const char *s, ...)
788 {
789     // Skip this if not giving error messages at the moment.
790     if (!emsg_not_now())
791     {
792 	if (IObuff == NULL)
793 	{
794 	    // Very early in initialisation and already something wrong, just
795 	    // give the raw message so the user at least gets a hint.
796 	    return emsg_core((char_u *)s);
797 	}
798 	else
799 	{
800 	    va_list ap;
801 
802 	    va_start(ap, s);
803 	    vim_vsnprintf((char *)IObuff, IOSIZE, s, ap);
804 	    va_end(ap);
805 	    return emsg_core(IObuff);
806 	}
807     }
808     return TRUE;		// no error messages at the moment
809 }
810 #endif
811 
812 /*
813  * Same as emsg(...), but abort on error when ABORT_ON_INTERNAL_ERROR is
814  * defined. It is used for internal errors only, so that they can be
815  * detected when fuzzing vim.
816  */
817     void
818 iemsg(char *s)
819 {
820     if (!emsg_not_now())
821 	emsg_core((char_u *)s);
822 #ifdef ABORT_ON_INTERNAL_ERROR
823     abort();
824 #endif
825 }
826 
827 #ifndef PROTO  // manual proto with __attribute__
828 /*
829  * Same as semsg(...) but abort on error when ABORT_ON_INTERNAL_ERROR is
830  * defined. It is used for internal errors only, so that they can be
831  * detected when fuzzing vim.
832  * Note: caller must not pass 'IObuff' as 1st argument.
833  */
834     void
835 siemsg(const char *s, ...)
836 {
837     if (!emsg_not_now())
838     {
839 	if (IObuff == NULL)
840 	{
841 	    // Very early in initialisation and already something wrong, just
842 	    // give the raw message so the user at least gets a hint.
843 	    emsg_core((char_u *)s);
844 	}
845 	else
846 	{
847 	    va_list ap;
848 
849 	    va_start(ap, s);
850 	    vim_vsnprintf((char *)IObuff, IOSIZE, s, ap);
851 	    va_end(ap);
852 	    emsg_core(IObuff);
853 	}
854     }
855 # ifdef ABORT_ON_INTERNAL_ERROR
856     abort();
857 # endif
858 }
859 #endif
860 
861 /*
862  * Give an "Internal error" message.
863  */
864     void
865 internal_error(char *where)
866 {
867     siemsg(_(e_intern2), where);
868 }
869 
870 /*
871  * Like internal_error() but do not call abort(), to avoid tests using
872  * test_unknown() and test_void() causing Vim to exit.
873  */
874     void
875 internal_error_no_abort(char *where)
876 {
877      semsg(_(e_intern2), where);
878 }
879 
880 // emsg3() and emsgn() are in misc2.c to avoid warnings for the prototypes.
881 
882     void
883 emsg_invreg(int name)
884 {
885     semsg(_("E354: Invalid register name: '%s'"), transchar(name));
886 }
887 
888 /*
889  * Give an error message which contains %s for "name[len]".
890  */
891     void
892 emsg_namelen(char *msg, char_u *name, int len)
893 {
894     char_u *copy = vim_strnsave((char_u *)name, len);
895 
896     semsg(msg, copy == NULL ? "NULL" : (char *)copy);
897     vim_free(copy);
898 }
899 
900 /*
901  * Like msg(), but truncate to a single line if p_shm contains 't', or when
902  * "force" is TRUE.  This truncates in another way as for normal messages.
903  * Careful: The string may be changed by msg_may_trunc()!
904  * Returns a pointer to the printed message, if wait_return() not called.
905  */
906     char *
907 msg_trunc_attr(char *s, int force, int attr)
908 {
909     int		n;
910     char	*ts;
911 
912     // Add message to history before truncating
913     add_msg_hist((char_u *)s, -1, attr);
914 
915     ts = (char *)msg_may_trunc(force, (char_u *)s);
916 
917     msg_hist_off = TRUE;
918     n = msg_attr(ts, attr);
919     msg_hist_off = FALSE;
920 
921     if (n)
922 	return ts;
923     return NULL;
924 }
925 
926 /*
927  * Check if message "s" should be truncated at the start (for filenames).
928  * Return a pointer to where the truncated message starts.
929  * Note: May change the message by replacing a character with '<'.
930  */
931     char_u *
932 msg_may_trunc(int force, char_u *s)
933 {
934     int		n;
935     int		room;
936 
937     room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
938     if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
939 	    && (n = (int)STRLEN(s) - room) > 0)
940     {
941 	if (has_mbyte)
942 	{
943 	    int	size = vim_strsize(s);
944 
945 	    // There may be room anyway when there are multibyte chars.
946 	    if (size <= room)
947 		return s;
948 
949 	    for (n = 0; size >= room; )
950 	    {
951 		size -= (*mb_ptr2cells)(s + n);
952 		n += (*mb_ptr2len)(s + n);
953 	    }
954 	    --n;
955 	}
956 	s += n;
957 	*s = '<';
958     }
959     return s;
960 }
961 
962     static void
963 add_msg_hist(
964     char_u	*s,
965     int		len,		// -1 for undetermined length
966     int		attr)
967 {
968     struct msg_hist *p;
969 
970     if (msg_hist_off || msg_silent != 0)
971 	return;
972 
973     // Don't let the message history get too big
974     while (msg_hist_len > MAX_MSG_HIST_LEN)
975 	(void)delete_first_msg();
976 
977     // allocate an entry and add the message at the end of the history
978     p = ALLOC_ONE(struct msg_hist);
979     if (p != NULL)
980     {
981 	if (len < 0)
982 	    len = (int)STRLEN(s);
983 	// remove leading and trailing newlines
984 	while (len > 0 && *s == '\n')
985 	{
986 	    ++s;
987 	    --len;
988 	}
989 	while (len > 0 && s[len - 1] == '\n')
990 	    --len;
991 	p->msg = vim_strnsave(s, len);
992 	p->next = NULL;
993 	p->attr = attr;
994 	if (last_msg_hist != NULL)
995 	    last_msg_hist->next = p;
996 	last_msg_hist = p;
997 	if (first_msg_hist == NULL)
998 	    first_msg_hist = last_msg_hist;
999 	++msg_hist_len;
1000     }
1001 }
1002 
1003 /*
1004  * Delete the first (oldest) message from the history.
1005  * Returns FAIL if there are no messages.
1006  */
1007     int
1008 delete_first_msg(void)
1009 {
1010     struct msg_hist *p;
1011 
1012     if (msg_hist_len <= 0)
1013 	return FAIL;
1014     p = first_msg_hist;
1015     first_msg_hist = p->next;
1016     if (first_msg_hist == NULL)
1017 	last_msg_hist = NULL;  // history is empty
1018     vim_free(p->msg);
1019     vim_free(p);
1020     --msg_hist_len;
1021     return OK;
1022 }
1023 
1024 /*
1025  * ":messages" command.
1026  */
1027     void
1028 ex_messages(exarg_T *eap)
1029 {
1030     struct msg_hist *p;
1031     char_u	    *s;
1032     int		    c = 0;
1033 
1034     if (STRCMP(eap->arg, "clear") == 0)
1035     {
1036 	int keep = eap->addr_count == 0 ? 0 : eap->line2;
1037 
1038 	while (msg_hist_len > keep)
1039 	    (void)delete_first_msg();
1040 	return;
1041     }
1042 
1043     if (*eap->arg != NUL)
1044     {
1045 	emsg(_(e_invarg));
1046 	return;
1047     }
1048 
1049     msg_hist_off = TRUE;
1050 
1051     p = first_msg_hist;
1052     if (eap->addr_count != 0)
1053     {
1054 	// Count total messages
1055 	for (; p != NULL && !got_int; p = p->next)
1056 	    c++;
1057 
1058 	c -= eap->line2;
1059 
1060 	// Skip without number of messages specified
1061 	for (p = first_msg_hist; p != NULL && !got_int && c > 0;
1062 						    p = p->next, c--);
1063     }
1064 
1065     if (p == first_msg_hist)
1066     {
1067 #ifdef FEAT_MULTI_LANG
1068 	s = get_mess_lang();
1069 #else
1070 	s = mch_getenv((char_u *)"LANG");
1071 #endif
1072 	if (s != NULL && *s != NUL)
1073 	    // The next comment is extracted by xgettext and put in po file for
1074 	    // translators to read.
1075 	    msg_attr(
1076 		    // Translator: Please replace the name and email address
1077 		    // with the appropriate text for your translation.
1078 		    _("Messages maintainer: Bram Moolenaar <[email protected]>"),
1079 		    HL_ATTR(HLF_T));
1080     }
1081 
1082     // Display what was not skipped.
1083     for (; p != NULL && !got_int; p = p->next)
1084 	if (p->msg != NULL)
1085 	    msg_attr((char *)p->msg, p->attr);
1086 
1087     msg_hist_off = FALSE;
1088 }
1089 
1090 #if defined(FEAT_CON_DIALOG) || defined(FIND_REPLACE_DIALOG) || defined(PROTO)
1091 /*
1092  * Call this after prompting the user.  This will avoid a hit-return message
1093  * and a delay.
1094  */
1095     void
1096 msg_end_prompt(void)
1097 {
1098     need_wait_return = FALSE;
1099     emsg_on_display = FALSE;
1100     cmdline_row = msg_row;
1101     msg_col = 0;
1102     msg_clr_eos();
1103     lines_left = -1;
1104 }
1105 #endif
1106 
1107 /*
1108  * Wait for the user to hit a key (normally Enter).
1109  * If "redraw" is TRUE, clear and redraw the screen.
1110  * If "redraw" is FALSE, just redraw the screen.
1111  * If "redraw" is -1, don't redraw at all.
1112  */
1113     void
1114 wait_return(int redraw)
1115 {
1116     int		c;
1117     int		oldState;
1118     int		tmpState;
1119     int		had_got_int;
1120     int		save_reg_recording;
1121     FILE	*save_scriptout;
1122 
1123     if (redraw == TRUE)
1124 	must_redraw = CLEAR;
1125 
1126     // If using ":silent cmd", don't wait for a return.  Also don't set
1127     // need_wait_return to do it later.
1128     if (msg_silent != 0)
1129 	return;
1130 
1131     /*
1132      * When inside vgetc(), we can't wait for a typed character at all.
1133      * With the global command (and some others) we only need one return at
1134      * the end. Adjust cmdline_row to avoid the next message overwriting the
1135      * last one.
1136      */
1137     if (vgetc_busy > 0)
1138 	return;
1139     need_wait_return = TRUE;
1140     if (no_wait_return)
1141     {
1142 	if (!exmode_active)
1143 	    cmdline_row = msg_row;
1144 	return;
1145     }
1146 
1147     redir_off = TRUE;		// don't redirect this message
1148     oldState = State;
1149     if (quit_more)
1150     {
1151 	c = CAR;		// just pretend CR was hit
1152 	quit_more = FALSE;
1153 	got_int = FALSE;
1154     }
1155     else if (exmode_active)
1156     {
1157 	msg_puts(" ");		// make sure the cursor is on the right line
1158 	c = CAR;		// no need for a return in ex mode
1159 	got_int = FALSE;
1160     }
1161     else
1162     {
1163 	// Make sure the hit-return prompt is on screen when 'guioptions' was
1164 	// just changed.
1165 	screenalloc(FALSE);
1166 
1167 	State = HITRETURN;
1168 	setmouse();
1169 #ifdef USE_ON_FLY_SCROLL
1170 	dont_scroll = TRUE;		// disallow scrolling here
1171 #endif
1172 	cmdline_row = msg_row;
1173 
1174 	// Avoid the sequence that the user types ":" at the hit-return prompt
1175 	// to start an Ex command, but the file-changed dialog gets in the
1176 	// way.
1177 	if (need_check_timestamps)
1178 	    check_timestamps(FALSE);
1179 
1180 	hit_return_msg();
1181 
1182 	do
1183 	{
1184 	    // Remember "got_int", if it is set vgetc() probably returns a
1185 	    // CTRL-C, but we need to loop then.
1186 	    had_got_int = got_int;
1187 
1188 	    // Don't do mappings here, we put the character back in the
1189 	    // typeahead buffer.
1190 	    ++no_mapping;
1191 	    ++allow_keys;
1192 
1193 	    // Temporarily disable Recording. If Recording is active, the
1194 	    // character will be recorded later, since it will be added to the
1195 	    // typebuf after the loop
1196 	    save_reg_recording = reg_recording;
1197 	    save_scriptout = scriptout;
1198 	    reg_recording = 0;
1199 	    scriptout = NULL;
1200 	    c = safe_vgetc();
1201 	    if (had_got_int && !global_busy)
1202 		got_int = FALSE;
1203 	    --no_mapping;
1204 	    --allow_keys;
1205 	    reg_recording = save_reg_recording;
1206 	    scriptout = save_scriptout;
1207 
1208 #ifdef FEAT_CLIPBOARD
1209 	    // Strange way to allow copying (yanking) a modeless selection at
1210 	    // the hit-enter prompt.  Use CTRL-Y, because the same is used in
1211 	    // Cmdline-mode and it's harmless when there is no selection.
1212 	    if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
1213 	    {
1214 		clip_copy_modeless_selection(TRUE);
1215 		c = K_IGNORE;
1216 	    }
1217 #endif
1218 
1219 	    /*
1220 	     * Allow scrolling back in the messages.
1221 	     * Also accept scroll-down commands when messages fill the screen,
1222 	     * to avoid that typing one 'j' too many makes the messages
1223 	     * disappear.
1224 	     */
1225 	    if (p_more && !p_cp)
1226 	    {
1227 		if (c == 'b' || c == 'k' || c == 'u' || c == 'g'
1228 						|| c == K_UP || c == K_PAGEUP)
1229 		{
1230 		    if (msg_scrolled > Rows)
1231 			// scroll back to show older messages
1232 			do_more_prompt(c);
1233 		    else
1234 		    {
1235 			msg_didout = FALSE;
1236 			c = K_IGNORE;
1237 			msg_col =
1238 #ifdef FEAT_RIGHTLEFT
1239 			    cmdmsg_rl ? Columns - 1 :
1240 #endif
1241 			    0;
1242 		    }
1243 		    if (quit_more)
1244 		    {
1245 			c = CAR;		// just pretend CR was hit
1246 			quit_more = FALSE;
1247 			got_int = FALSE;
1248 		    }
1249 		    else if (c != K_IGNORE)
1250 		    {
1251 			c = K_IGNORE;
1252 			hit_return_msg();
1253 		    }
1254 		}
1255 		else if (msg_scrolled > Rows - 2
1256 			 && (c == 'j' || c == 'd' || c == 'f'
1257 					   || c == K_DOWN || c == K_PAGEDOWN))
1258 		    c = K_IGNORE;
1259 	    }
1260 	} while ((had_got_int && c == Ctrl_C)
1261 				|| c == K_IGNORE
1262 #ifdef FEAT_GUI
1263 				|| c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
1264 #endif
1265 				|| c == K_LEFTDRAG   || c == K_LEFTRELEASE
1266 				|| c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
1267 				|| c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
1268 				|| c == K_MOUSELEFT  || c == K_MOUSERIGHT
1269 				|| c == K_MOUSEDOWN  || c == K_MOUSEUP
1270 				|| c == K_MOUSEMOVE
1271 				|| (!mouse_has(MOUSE_RETURN)
1272 				    && mouse_row < msg_row
1273 				    && (c == K_LEFTMOUSE
1274 					|| c == K_MIDDLEMOUSE
1275 					|| c == K_RIGHTMOUSE
1276 					|| c == K_X1MOUSE
1277 					|| c == K_X2MOUSE))
1278 				);
1279 	ui_breakcheck();
1280 	/*
1281 	 * Avoid that the mouse-up event causes visual mode to start.
1282 	 */
1283 	if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
1284 					  || c == K_X1MOUSE || c == K_X2MOUSE)
1285 	    (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
1286 	else if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C)
1287 	{
1288 	    // Put the character back in the typeahead buffer.  Don't use the
1289 	    // stuff buffer, because lmaps wouldn't work.
1290 	    ins_char_typebuf(vgetc_char, vgetc_mod_mask);
1291 	    do_redraw = TRUE;	    // need a redraw even though there is
1292 				    // typeahead
1293 	}
1294     }
1295     redir_off = FALSE;
1296 
1297     /*
1298      * If the user hits ':', '?' or '/' we get a command line from the next
1299      * line.
1300      */
1301     if (c == ':' || c == '?' || c == '/')
1302     {
1303 	if (!exmode_active)
1304 	    cmdline_row = msg_row;
1305 	skip_redraw = TRUE;	    // skip redraw once
1306 	do_redraw = FALSE;
1307 #ifdef FEAT_TERMINAL
1308 	skip_term_loop = TRUE;
1309 #endif
1310     }
1311 
1312     /*
1313      * If the window size changed set_shellsize() will redraw the screen.
1314      * Otherwise the screen is only redrawn if 'redraw' is set and no ':'
1315      * typed.
1316      */
1317     tmpState = State;
1318     State = oldState;		    // restore State before set_shellsize
1319     setmouse();
1320     msg_check();
1321 
1322 #if defined(UNIX) || defined(VMS)
1323     /*
1324      * When switching screens, we need to output an extra newline on exit.
1325      */
1326     if (swapping_screen() && !termcap_active)
1327 	newline_on_exit = TRUE;
1328 #endif
1329 
1330     need_wait_return = FALSE;
1331     did_wait_return = TRUE;
1332     emsg_on_display = FALSE;	// can delete error message now
1333     lines_left = -1;		// reset lines_left at next msg_start()
1334     reset_last_sourcing();
1335     if (keep_msg != NULL && vim_strsize(keep_msg) >=
1336 				  (Rows - cmdline_row - 1) * Columns + sc_col)
1337 	VIM_CLEAR(keep_msg);	    // don't redisplay message, it's too long
1338 
1339     if (tmpState == SETWSIZE)	    // got resize event while in vgetc()
1340     {
1341 	starttermcap();		    // start termcap before redrawing
1342 	shell_resized();
1343     }
1344     else if (!skip_redraw
1345 	    && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1)))
1346     {
1347 	starttermcap();		    // start termcap before redrawing
1348 	redraw_later(VALID);
1349     }
1350 }
1351 
1352 /*
1353  * Write the hit-return prompt.
1354  */
1355     static void
1356 hit_return_msg(void)
1357 {
1358     int		save_p_more = p_more;
1359 
1360     p_more = FALSE;	// don't want see this message when scrolling back
1361     if (msg_didout)	// start on a new line
1362 	msg_putchar('\n');
1363     if (got_int)
1364 	msg_puts(_("Interrupt: "));
1365 
1366     msg_puts_attr(_("Press ENTER or type command to continue"), HL_ATTR(HLF_R));
1367     if (!msg_use_printf())
1368 	msg_clr_eos();
1369     p_more = save_p_more;
1370 }
1371 
1372 /*
1373  * Set "keep_msg" to "s".  Free the old value and check for NULL pointer.
1374  */
1375     void
1376 set_keep_msg(char_u *s, int attr)
1377 {
1378     vim_free(keep_msg);
1379     if (s != NULL && msg_silent == 0)
1380 	keep_msg = vim_strsave(s);
1381     else
1382 	keep_msg = NULL;
1383     keep_msg_more = FALSE;
1384     keep_msg_attr = attr;
1385 }
1386 
1387 #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
1388 /*
1389  * If there currently is a message being displayed, set "keep_msg" to it, so
1390  * that it will be displayed again after redraw.
1391  */
1392     void
1393 set_keep_msg_from_hist(void)
1394 {
1395     if (keep_msg == NULL && last_msg_hist != NULL && msg_scrolled == 0
1396 							  && (State & NORMAL))
1397 	set_keep_msg(last_msg_hist->msg, last_msg_hist->attr);
1398 }
1399 #endif
1400 
1401 /*
1402  * Prepare for outputting characters in the command line.
1403  */
1404     void
1405 msg_start(void)
1406 {
1407     int		did_return = FALSE;
1408 
1409     if (!msg_silent)
1410 	VIM_CLEAR(keep_msg);
1411 
1412 #ifdef FEAT_EVAL
1413     if (need_clr_eos)
1414     {
1415 	// Halfway an ":echo" command and getting an (error) message: clear
1416 	// any text from the command.
1417 	need_clr_eos = FALSE;
1418 	msg_clr_eos();
1419     }
1420 #endif
1421 
1422     if (!msg_scroll && full_screen)	// overwrite last message
1423     {
1424 	msg_row = cmdline_row;
1425 	msg_col =
1426 #ifdef FEAT_RIGHTLEFT
1427 	    cmdmsg_rl ? Columns - 1 :
1428 #endif
1429 	    0;
1430     }
1431     else if (msg_didout)		    // start message on next line
1432     {
1433 	msg_putchar('\n');
1434 	did_return = TRUE;
1435 	if (exmode_active != EXMODE_NORMAL)
1436 	    cmdline_row = msg_row;
1437     }
1438     if (!msg_didany || lines_left < 0)
1439 	msg_starthere();
1440     if (msg_silent == 0)
1441     {
1442 	msg_didout = FALSE;		    // no output on current line yet
1443 	cursor_off();
1444     }
1445 
1446     // when redirecting, may need to start a new line.
1447     if (!did_return)
1448 	redir_write((char_u *)"\n", -1);
1449 }
1450 
1451 /*
1452  * Note that the current msg position is where messages start.
1453  */
1454     void
1455 msg_starthere(void)
1456 {
1457     lines_left = cmdline_row;
1458     msg_didany = FALSE;
1459 }
1460 
1461     void
1462 msg_putchar(int c)
1463 {
1464     msg_putchar_attr(c, 0);
1465 }
1466 
1467     void
1468 msg_putchar_attr(int c, int attr)
1469 {
1470     char_u	buf[MB_MAXBYTES + 1];
1471 
1472     if (IS_SPECIAL(c))
1473     {
1474 	buf[0] = K_SPECIAL;
1475 	buf[1] = K_SECOND(c);
1476 	buf[2] = K_THIRD(c);
1477 	buf[3] = NUL;
1478     }
1479     else
1480 	buf[(*mb_char2bytes)(c, buf)] = NUL;
1481     msg_puts_attr((char *)buf, attr);
1482 }
1483 
1484     void
1485 msg_outnum(long n)
1486 {
1487     char	buf[20];
1488 
1489     sprintf(buf, "%ld", n);
1490     msg_puts(buf);
1491 }
1492 
1493     void
1494 msg_home_replace(char_u *fname)
1495 {
1496     msg_home_replace_attr(fname, 0);
1497 }
1498 
1499 #if defined(FEAT_FIND_ID) || defined(PROTO)
1500     void
1501 msg_home_replace_hl(char_u *fname)
1502 {
1503     msg_home_replace_attr(fname, HL_ATTR(HLF_D));
1504 }
1505 #endif
1506 
1507     static void
1508 msg_home_replace_attr(char_u *fname, int attr)
1509 {
1510     char_u	*name;
1511 
1512     name = home_replace_save(NULL, fname);
1513     if (name != NULL)
1514 	msg_outtrans_attr(name, attr);
1515     vim_free(name);
1516 }
1517 
1518 /*
1519  * Output 'len' characters in 'str' (including NULs) with translation
1520  * if 'len' is -1, output up to a NUL character.
1521  * Use attributes 'attr'.
1522  * Return the number of characters it takes on the screen.
1523  */
1524     int
1525 msg_outtrans(char_u *str)
1526 {
1527     return msg_outtrans_attr(str, 0);
1528 }
1529 
1530     int
1531 msg_outtrans_attr(char_u *str, int attr)
1532 {
1533     return msg_outtrans_len_attr(str, (int)STRLEN(str), attr);
1534 }
1535 
1536     int
1537 msg_outtrans_len(char_u *str, int len)
1538 {
1539     return msg_outtrans_len_attr(str, len, 0);
1540 }
1541 
1542 /*
1543  * Output one character at "p".  Return pointer to the next character.
1544  * Handles multi-byte characters.
1545  */
1546     char_u *
1547 msg_outtrans_one(char_u *p, int attr)
1548 {
1549     int		l;
1550 
1551     if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
1552     {
1553 	msg_outtrans_len_attr(p, l, attr);
1554 	return p + l;
1555     }
1556     msg_puts_attr((char *)transchar_byte(*p), attr);
1557     return p + 1;
1558 }
1559 
1560     int
1561 msg_outtrans_len_attr(char_u *msgstr, int len, int attr)
1562 {
1563     int		retval = 0;
1564     char_u	*str = msgstr;
1565     char_u	*plain_start = msgstr;
1566     char_u	*s;
1567     int		mb_l;
1568     int		c;
1569     int		save_got_int = got_int;
1570 
1571     // Only quit when got_int was set in here.
1572     got_int = FALSE;
1573 
1574     // if MSG_HIST flag set, add message to history
1575     if (attr & MSG_HIST)
1576     {
1577 	add_msg_hist(str, len, attr);
1578 	attr &= ~MSG_HIST;
1579     }
1580 
1581     // If the string starts with a composing character first draw a space on
1582     // which the composing char can be drawn.
1583     if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr)))
1584 	msg_puts_attr(" ", attr);
1585 
1586     /*
1587      * Go over the string.  Special characters are translated and printed.
1588      * Normal characters are printed several at a time.
1589      */
1590     while (--len >= 0 && !got_int)
1591     {
1592 	if (enc_utf8)
1593 	    // Don't include composing chars after the end.
1594 	    mb_l = utfc_ptr2len_len(str, len + 1);
1595 	else if (has_mbyte)
1596 	    mb_l = (*mb_ptr2len)(str);
1597 	else
1598 	    mb_l = 1;
1599 	if (has_mbyte && mb_l > 1)
1600 	{
1601 	    c = (*mb_ptr2char)(str);
1602 	    if (vim_isprintc(c))
1603 		// printable multi-byte char: count the cells.
1604 		retval += (*mb_ptr2cells)(str);
1605 	    else
1606 	    {
1607 		// unprintable multi-byte char: print the printable chars so
1608 		// far and the translation of the unprintable char.
1609 		if (str > plain_start)
1610 		    msg_puts_attr_len((char *)plain_start,
1611 					       (int)(str - plain_start), attr);
1612 		plain_start = str + mb_l;
1613 		msg_puts_attr((char *)transchar(c),
1614 					    attr == 0 ? HL_ATTR(HLF_8) : attr);
1615 		retval += char2cells(c);
1616 	    }
1617 	    len -= mb_l - 1;
1618 	    str += mb_l;
1619 	}
1620 	else
1621 	{
1622 	    s = transchar_byte(*str);
1623 	    if (s[1] != NUL)
1624 	    {
1625 		// unprintable char: print the printable chars so far and the
1626 		// translation of the unprintable char.
1627 		if (str > plain_start)
1628 		    msg_puts_attr_len((char *)plain_start,
1629 					       (int)(str - plain_start), attr);
1630 		plain_start = str + 1;
1631 		msg_puts_attr((char *)s, attr == 0 ? HL_ATTR(HLF_8) : attr);
1632 		retval += (int)STRLEN(s);
1633 	    }
1634 	    else
1635 		++retval;
1636 	    ++str;
1637 	}
1638     }
1639 
1640     if (str > plain_start && !got_int)
1641 	// print the printable chars at the end
1642 	msg_puts_attr_len((char *)plain_start, (int)(str - plain_start), attr);
1643 
1644     got_int |= save_got_int;
1645 
1646     return retval;
1647 }
1648 
1649 #if defined(FEAT_QUICKFIX) || defined(PROTO)
1650     void
1651 msg_make(char_u *arg)
1652 {
1653     int	    i;
1654     static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB";
1655 
1656     arg = skipwhite(arg);
1657     for (i = 5; *arg && i >= 0; --i)
1658 	if (*arg++ != str[i])
1659 	    break;
1660     if (i < 0)
1661     {
1662 	msg_putchar('\n');
1663 	for (i = 0; rs[i]; ++i)
1664 	    msg_putchar(rs[i] - 3);
1665     }
1666 }
1667 #endif
1668 
1669 /*
1670  * Output the string 'str' up to a NUL character.
1671  * Return the number of characters it takes on the screen.
1672  *
1673  * If K_SPECIAL is encountered, then it is taken in conjunction with the
1674  * following character and shown as <F1>, <S-Up> etc.  Any other character
1675  * which is not printable shown in <> form.
1676  * If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>.
1677  * If a character is displayed in one of these special ways, is also
1678  * highlighted (its highlight name is '8' in the p_hl variable).
1679  * Otherwise characters are not highlighted.
1680  * This function is used to show mappings, where we want to see how to type
1681  * the character/string -- webb
1682  */
1683     int
1684 msg_outtrans_special(
1685     char_u	*strstart,
1686     int		from,	// TRUE for lhs of a mapping
1687     int		maxlen) // screen columns, 0 for unlimited
1688 {
1689     char_u	*str = strstart;
1690     int		retval = 0;
1691     char	*text;
1692     int		attr;
1693     int		len;
1694 
1695     attr = HL_ATTR(HLF_8);
1696     while (*str != NUL)
1697     {
1698 	// Leading and trailing spaces need to be displayed in <> form.
1699 	if ((str == strstart || str[1] == NUL) && *str == ' ')
1700 	{
1701 	    text = "<Space>";
1702 	    ++str;
1703 	}
1704 	else
1705 	    text = (char *)str2special(&str, from);
1706 	len = vim_strsize((char_u *)text);
1707 	if (maxlen > 0 && retval + len >= maxlen)
1708 	    break;
1709 	// Highlight special keys
1710 	msg_puts_attr(text, len > 1
1711 		&& (*mb_ptr2len)((char_u *)text) <= 1 ? attr : 0);
1712 	retval += len;
1713     }
1714     return retval;
1715 }
1716 
1717 #if defined(FEAT_EVAL) || defined(PROTO)
1718 /*
1719  * Return the lhs or rhs of a mapping, with the key codes turned into printable
1720  * strings, in an allocated string.
1721  */
1722     char_u *
1723 str2special_save(
1724     char_u  *str,
1725     int	    is_lhs)  // TRUE for lhs, FALSE for rhs
1726 {
1727     garray_T	ga;
1728     char_u	*p = str;
1729 
1730     ga_init2(&ga, 1, 40);
1731     while (*p != NUL)
1732 	ga_concat(&ga, str2special(&p, is_lhs));
1733     ga_append(&ga, NUL);
1734     return (char_u *)ga.ga_data;
1735 }
1736 #endif
1737 
1738 /*
1739  * Return the printable string for the key codes at "*sp".
1740  * Used for translating the lhs or rhs of a mapping to printable chars.
1741  * Advances "sp" to the next code.
1742  */
1743     char_u *
1744 str2special(
1745     char_u	**sp,
1746     int		from)	// TRUE for lhs of mapping
1747 {
1748     int			c;
1749     static char_u	buf[7];
1750     char_u		*str = *sp;
1751     int			modifiers = 0;
1752     int			special = FALSE;
1753 
1754     if (has_mbyte)
1755     {
1756 	char_u	*p;
1757 
1758 	// Try to un-escape a multi-byte character.  Return the un-escaped
1759 	// string if it is a multi-byte character.
1760 	p = mb_unescape(sp);
1761 	if (p != NULL)
1762 	    return p;
1763     }
1764 
1765     c = *str;
1766     if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
1767     {
1768 	if (str[1] == KS_MODIFIER)
1769 	{
1770 	    modifiers = str[2];
1771 	    str += 3;
1772 	    c = *str;
1773 	}
1774 	if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
1775 	{
1776 	    c = TO_SPECIAL(str[1], str[2]);
1777 	    str += 2;
1778 	}
1779 	if (IS_SPECIAL(c) || modifiers)	// special key
1780 	    special = TRUE;
1781     }
1782 
1783     if (has_mbyte && !IS_SPECIAL(c))
1784     {
1785 	int len = (*mb_ptr2len)(str);
1786 
1787 	// For multi-byte characters check for an illegal byte.
1788 	if (has_mbyte && MB_BYTE2LEN(*str) > len)
1789 	{
1790 	    transchar_nonprint(curbuf, buf, c);
1791 	    *sp = str + 1;
1792 	    return buf;
1793 	}
1794 	// Since 'special' is TRUE the multi-byte character 'c' will be
1795 	// processed by get_special_key_name()
1796 	c = (*mb_ptr2char)(str);
1797 	*sp = str + len;
1798     }
1799     else
1800 	*sp = str + 1;
1801 
1802     // Make unprintable characters in <> form, also <M-Space> and <Tab>.
1803     // Use <Space> only for lhs of a mapping.
1804     if (special || char2cells(c) > 1 || (from && c == ' '))
1805 	return get_special_key_name(c, modifiers);
1806     buf[0] = c;
1807     buf[1] = NUL;
1808     return buf;
1809 }
1810 
1811 /*
1812  * Translate a key sequence into special key names.
1813  */
1814     void
1815 str2specialbuf(char_u *sp, char_u *buf, int len)
1816 {
1817     char_u	*s;
1818 
1819     *buf = NUL;
1820     while (*sp)
1821     {
1822 	s = str2special(&sp, FALSE);
1823 	if ((int)(STRLEN(s) + STRLEN(buf)) < len)
1824 	    STRCAT(buf, s);
1825     }
1826 }
1827 
1828 /*
1829  * print line for :print or :list command
1830  */
1831     void
1832 msg_prt_line(char_u *s, int list)
1833 {
1834     int		c;
1835     int		col = 0;
1836     int		n_extra = 0;
1837     int		c_extra = 0;
1838     int		c_final = 0;
1839     char_u	*p_extra = NULL;	    // init to make SASC shut up
1840     int		n;
1841     int		attr = 0;
1842     char_u	*trail = NULL;
1843     char_u	*lead = NULL;
1844     int		l;
1845     char_u	buf[MB_MAXBYTES + 1];
1846 
1847     if (curwin->w_p_list)
1848 	list = TRUE;
1849 
1850     if (list)
1851     {
1852 	// find start of trailing whitespace
1853 	if (curwin->w_lcs_chars.trail)
1854 	{
1855 	    trail = s + STRLEN(s);
1856 	    while (trail > s && VIM_ISWHITE(trail[-1]))
1857 		--trail;
1858 	}
1859 	// find end of leading whitespace
1860 	if (curwin->w_lcs_chars.lead)
1861 	{
1862 	    lead = s;
1863 	    while (VIM_ISWHITE(lead[0]))
1864 		lead++;
1865 	    // in a line full of spaces all of them are treated as trailing
1866 	    if (*lead == NUL)
1867 		lead = NULL;
1868 	}
1869     }
1870 
1871     // output a space for an empty line, otherwise the line will be
1872     // overwritten
1873     if (*s == NUL && !(list && curwin->w_lcs_chars.eol != NUL))
1874 	msg_putchar(' ');
1875 
1876     while (!got_int)
1877     {
1878 	if (n_extra > 0)
1879 	{
1880 	    --n_extra;
1881 	    if (n_extra == 0 && c_final)
1882 		c = c_final;
1883 	    else if (c_extra)
1884 		c = c_extra;
1885 	    else
1886 		c = *p_extra++;
1887 	}
1888 	else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1)
1889 	{
1890 	    col += (*mb_ptr2cells)(s);
1891 	    if (l >= MB_MAXBYTES)
1892 	    {
1893 		STRCPY(buf, "?");
1894 	    }
1895 	    else if (curwin->w_lcs_chars.nbsp != NUL && list
1896 		    && (mb_ptr2char(s) == 160
1897 			|| mb_ptr2char(s) == 0x202f))
1898 	    {
1899 		mb_char2bytes(curwin->w_lcs_chars.nbsp, buf);
1900 		buf[(*mb_ptr2len)(buf)] = NUL;
1901 	    }
1902 	    else
1903 	    {
1904 		mch_memmove(buf, s, (size_t)l);
1905 		buf[l] = NUL;
1906 	    }
1907 	    msg_puts((char *)buf);
1908 	    s += l;
1909 	    continue;
1910 	}
1911 	else
1912 	{
1913 	    attr = 0;
1914 	    c = *s++;
1915 	    if (c == TAB && (!list || curwin->w_lcs_chars.tab1))
1916 	    {
1917 		// tab amount depends on current column
1918 #ifdef FEAT_VARTABS
1919 		n_extra = tabstop_padding(col, curbuf->b_p_ts,
1920 						    curbuf->b_p_vts_array) - 1;
1921 #else
1922 		n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
1923 #endif
1924 		if (!list)
1925 		{
1926 		    c = ' ';
1927 		    c_extra = ' ';
1928 		    c_final = NUL;
1929 		}
1930 		else
1931 		{
1932 		    c = (n_extra == 0 && curwin->w_lcs_chars.tab3)
1933 						? curwin->w_lcs_chars.tab3
1934 						: curwin->w_lcs_chars.tab1;
1935 		    c_extra = curwin->w_lcs_chars.tab2;
1936 		    c_final = curwin->w_lcs_chars.tab3;
1937 		    attr = HL_ATTR(HLF_8);
1938 		}
1939 	    }
1940 	    else if (c == 160 && list && curwin->w_lcs_chars.nbsp != NUL)
1941 	    {
1942 		c = curwin->w_lcs_chars.nbsp;
1943 		attr = HL_ATTR(HLF_8);
1944 	    }
1945 	    else if (c == NUL && list && curwin->w_lcs_chars.eol != NUL)
1946 	    {
1947 		p_extra = (char_u *)"";
1948 		c_extra = NUL;
1949 		c_final = NUL;
1950 		n_extra = 1;
1951 		c = curwin->w_lcs_chars.eol;
1952 		attr = HL_ATTR(HLF_AT);
1953 		--s;
1954 	    }
1955 	    else if (c != NUL && (n = byte2cells(c)) > 1)
1956 	    {
1957 		n_extra = n - 1;
1958 		p_extra = transchar_byte(c);
1959 		c_extra = NUL;
1960 		c_final = NUL;
1961 		c = *p_extra++;
1962 		// Use special coloring to be able to distinguish <hex> from
1963 		// the same in plain text.
1964 		attr = HL_ATTR(HLF_8);
1965 	    }
1966 	    else if (c == ' ' && lead != NULL && s <= lead)
1967 	    {
1968 		c = curwin->w_lcs_chars.lead;
1969 		attr = HL_ATTR(HLF_8);
1970 	    }
1971 	    else if (c == ' ' && trail != NULL && s > trail)
1972 	    {
1973 		c = curwin->w_lcs_chars.trail;
1974 		attr = HL_ATTR(HLF_8);
1975 	    }
1976 	    else if (c == ' ' && list && curwin->w_lcs_chars.space != NUL)
1977 	    {
1978 		c = curwin->w_lcs_chars.space;
1979 		attr = HL_ATTR(HLF_8);
1980 	    }
1981 	}
1982 
1983 	if (c == NUL)
1984 	    break;
1985 
1986 	msg_putchar_attr(c, attr);
1987 	col++;
1988     }
1989     msg_clr_eos();
1990 }
1991 
1992 /*
1993  * Use screen_puts() to output one multi-byte character.
1994  * Return the pointer "s" advanced to the next character.
1995  */
1996     static char_u *
1997 screen_puts_mbyte(char_u *s, int l, int attr)
1998 {
1999     int		cw;
2000 
2001     msg_didout = TRUE;		// remember that line is not empty
2002     cw = (*mb_ptr2cells)(s);
2003     if (cw > 1 && (
2004 #ifdef FEAT_RIGHTLEFT
2005 		cmdmsg_rl ? msg_col <= 1 :
2006 #endif
2007 		msg_col == Columns - 1))
2008     {
2009 	// Doesn't fit, print a highlighted '>' to fill it up.
2010 	msg_screen_putchar('>', HL_ATTR(HLF_AT));
2011 	return s;
2012     }
2013 
2014     screen_puts_len(s, l, msg_row, msg_col, attr);
2015 #ifdef FEAT_RIGHTLEFT
2016     if (cmdmsg_rl)
2017     {
2018 	msg_col -= cw;
2019 	if (msg_col == 0)
2020 	{
2021 	    msg_col = Columns;
2022 	    ++msg_row;
2023 	}
2024     }
2025     else
2026 #endif
2027     {
2028 	msg_col += cw;
2029 	if (msg_col >= Columns)
2030 	{
2031 	    msg_col = 0;
2032 	    ++msg_row;
2033 	}
2034     }
2035     return s + l;
2036 }
2037 
2038 /*
2039  * Output a string to the screen at position msg_row, msg_col.
2040  * Update msg_row and msg_col for the next message.
2041  */
2042     void
2043 msg_puts(char *s)
2044 {
2045     msg_puts_attr(s, 0);
2046 }
2047 
2048     void
2049 msg_puts_title(char *s)
2050 {
2051     msg_puts_attr(s, HL_ATTR(HLF_T));
2052 }
2053 
2054 /*
2055  * Show a message in such a way that it always fits in the line.  Cut out a
2056  * part in the middle and replace it with "..." when necessary.
2057  * Does not handle multi-byte characters!
2058  */
2059     static void
2060 msg_outtrans_long_len_attr(char_u *longstr, int len, int attr)
2061 {
2062     int		slen = len;
2063     int		room;
2064 
2065     room = Columns - msg_col;
2066     if (len > room && room >= 20)
2067     {
2068 	slen = (room - 3) / 2;
2069 	msg_outtrans_len_attr(longstr, slen, attr);
2070 	msg_puts_attr("...", HL_ATTR(HLF_8));
2071     }
2072     msg_outtrans_len_attr(longstr + len - slen, slen, attr);
2073 }
2074 
2075     void
2076 msg_outtrans_long_attr(char_u *longstr, int attr)
2077 {
2078     msg_outtrans_long_len_attr(longstr, (int)STRLEN(longstr), attr);
2079 }
2080 
2081 /*
2082  * Basic function for writing a message with highlight attributes.
2083  */
2084     void
2085 msg_puts_attr(char *s, int attr)
2086 {
2087     msg_puts_attr_len(s, -1, attr);
2088 }
2089 
2090 /*
2091  * Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
2092  * When "maxlen" is -1 there is no maximum length.
2093  * When "maxlen" is >= 0 the message is not put in the history.
2094  */
2095     static void
2096 msg_puts_attr_len(char *str, int maxlen, int attr)
2097 {
2098     /*
2099      * If redirection is on, also write to the redirection file.
2100      */
2101     redir_write((char_u *)str, maxlen);
2102 
2103     /*
2104      * Don't print anything when using ":silent cmd".
2105      */
2106     if (msg_silent != 0)
2107 	return;
2108 
2109     // if MSG_HIST flag set, add message to history
2110     if ((attr & MSG_HIST) && maxlen < 0)
2111     {
2112 	add_msg_hist((char_u *)str, -1, attr);
2113 	attr &= ~MSG_HIST;
2114     }
2115 
2116     // When writing something to the screen after it has scrolled, requires a
2117     // wait-return prompt later.  Needed when scrolling, resetting
2118     // need_wait_return after some prompt, and then outputting something
2119     // without scrolling
2120     // Not needed when only using CR to move the cursor.
2121     if (msg_scrolled != 0 && !msg_scrolled_ign && STRCMP(str, "\r") != 0)
2122 	need_wait_return = TRUE;
2123     msg_didany = TRUE;		// remember that something was outputted
2124 
2125     /*
2126      * If there is no valid screen, use fprintf so we can see error messages.
2127      * If termcap is not active, we may be writing in an alternate console
2128      * window, cursor positioning may not work correctly (window size may be
2129      * different, e.g. for Win32 console) or we just don't know where the
2130      * cursor is.
2131      */
2132     if (msg_use_printf())
2133 	msg_puts_printf((char_u *)str, maxlen);
2134     else
2135 	msg_puts_display((char_u *)str, maxlen, attr, FALSE);
2136 }
2137 
2138 /*
2139  * The display part of msg_puts_attr_len().
2140  * May be called recursively to display scroll-back text.
2141  */
2142     static void
2143 msg_puts_display(
2144     char_u	*str,
2145     int		maxlen,
2146     int		attr,
2147     int		recurse)
2148 {
2149     char_u	*s = str;
2150     char_u	*t_s = str;	// string from "t_s" to "s" is still todo
2151     int		t_col = 0;	// screen cells todo, 0 when "t_s" not used
2152     int		l;
2153     int		cw;
2154     char_u	*sb_str = str;
2155     int		sb_col = msg_col;
2156     int		wrap;
2157     int		did_last_char;
2158 
2159     did_wait_return = FALSE;
2160     while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL)
2161     {
2162 	/*
2163 	 * We are at the end of the screen line when:
2164 	 * - When outputting a newline.
2165 	 * - When outputting a character in the last column.
2166 	 */
2167 	if (!recurse && msg_row >= Rows - 1 && (*s == '\n' || (
2168 #ifdef FEAT_RIGHTLEFT
2169 		    cmdmsg_rl
2170 		    ? (
2171 			msg_col <= 1
2172 		      || (*s == TAB && msg_col <= 7)
2173 		      || (has_mbyte && (*mb_ptr2cells)(s) > 1 && msg_col <= 2))
2174 		    :
2175 #endif
2176 		      ((*s != '\r' && msg_col + t_col >= Columns - 1)
2177 		       || (*s == TAB && msg_col + t_col >= ((Columns - 1) & ~7))
2178 		       || (has_mbyte && (*mb_ptr2cells)(s) > 1
2179 					 && msg_col + t_col >= Columns - 2)))))
2180 	{
2181 	    /*
2182 	     * The screen is scrolled up when at the last row (some terminals
2183 	     * scroll automatically, some don't.  To avoid problems we scroll
2184 	     * ourselves).
2185 	     */
2186 	    if (t_col > 0)
2187 		// output postponed text
2188 		t_puts(&t_col, t_s, s, attr);
2189 
2190 	    // When no more prompt and no more room, truncate here
2191 	    if (msg_no_more && lines_left == 0)
2192 		break;
2193 
2194 	    // Scroll the screen up one line.
2195 	    msg_scroll_up();
2196 
2197 	    msg_row = Rows - 2;
2198 	    if (msg_col >= Columns)	// can happen after screen resize
2199 		msg_col = Columns - 1;
2200 
2201 	    // Display char in last column before showing more-prompt.
2202 	    if (*s >= ' '
2203 #ifdef FEAT_RIGHTLEFT
2204 		    && !cmdmsg_rl
2205 #endif
2206 	       )
2207 	    {
2208 		if (has_mbyte)
2209 		{
2210 		    if (enc_utf8 && maxlen >= 0)
2211 			// avoid including composing chars after the end
2212 			l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
2213 		    else
2214 			l = (*mb_ptr2len)(s);
2215 		    s = screen_puts_mbyte(s, l, attr);
2216 		}
2217 		else
2218 		    msg_screen_putchar(*s++, attr);
2219 		did_last_char = TRUE;
2220 	    }
2221 	    else
2222 		did_last_char = FALSE;
2223 
2224 	    if (p_more)
2225 		// store text for scrolling back
2226 		store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
2227 
2228 	    inc_msg_scrolled();
2229 	    need_wait_return = TRUE; // may need wait_return in main()
2230 	    redraw_cmdline = TRUE;
2231 	    if (cmdline_row > 0 && !exmode_active)
2232 		--cmdline_row;
2233 
2234 	    /*
2235 	     * If screen is completely filled and 'more' is set then wait
2236 	     * for a character.
2237 	     */
2238 	    if (lines_left > 0)
2239 		--lines_left;
2240 	    if (p_more && lines_left == 0 && State != HITRETURN
2241 					    && !msg_no_more && !exmode_active)
2242 	    {
2243 #ifdef FEAT_CON_DIALOG
2244 		if (do_more_prompt(NUL))
2245 		    s = confirm_msg_tail;
2246 #else
2247 		(void)do_more_prompt(NUL);
2248 #endif
2249 		if (quit_more)
2250 		    return;
2251 	    }
2252 
2253 	    // When we displayed a char in last column need to check if there
2254 	    // is still more.
2255 	    if (did_last_char)
2256 		continue;
2257 	}
2258 
2259 	wrap = *s == '\n'
2260 		    || msg_col + t_col >= Columns
2261 		    || (has_mbyte && (*mb_ptr2cells)(s) > 1
2262 					    && msg_col + t_col >= Columns - 1);
2263 	if (t_col > 0 && (wrap || *s == '\r' || *s == '\b'
2264 						 || *s == '\t' || *s == BELL))
2265 	    // output any postponed text
2266 	    t_puts(&t_col, t_s, s, attr);
2267 
2268 	if (wrap && p_more && !recurse)
2269 	    // store text for scrolling back
2270 	    store_sb_text(&sb_str, s, attr, &sb_col, TRUE);
2271 
2272 	if (*s == '\n')		    // go to next line
2273 	{
2274 	    msg_didout = FALSE;	    // remember that line is empty
2275 #ifdef FEAT_RIGHTLEFT
2276 	    if (cmdmsg_rl)
2277 		msg_col = Columns - 1;
2278 	    else
2279 #endif
2280 		msg_col = 0;
2281 	    if (++msg_row >= Rows)  // safety check
2282 		msg_row = Rows - 1;
2283 	}
2284 	else if (*s == '\r')	    // go to column 0
2285 	{
2286 	    msg_col = 0;
2287 	}
2288 	else if (*s == '\b')	    // go to previous char
2289 	{
2290 	    if (msg_col)
2291 		--msg_col;
2292 	}
2293 	else if (*s == TAB)	    // translate Tab into spaces
2294 	{
2295 	    do
2296 		msg_screen_putchar(' ', attr);
2297 	    while (msg_col & 7);
2298 	}
2299 	else if (*s == BELL)		// beep (from ":sh")
2300 	    vim_beep(BO_SH);
2301 	else
2302 	{
2303 	    if (has_mbyte)
2304 	    {
2305 		cw = (*mb_ptr2cells)(s);
2306 		if (enc_utf8 && maxlen >= 0)
2307 		    // avoid including composing chars after the end
2308 		    l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
2309 		else
2310 		    l = (*mb_ptr2len)(s);
2311 	    }
2312 	    else
2313 	    {
2314 		cw = 1;
2315 		l = 1;
2316 	    }
2317 
2318 	    // When drawing from right to left or when a double-wide character
2319 	    // doesn't fit, draw a single character here.  Otherwise collect
2320 	    // characters and draw them all at once later.
2321 	    if (
2322 # ifdef FEAT_RIGHTLEFT
2323 		    cmdmsg_rl ||
2324 # endif
2325 		    (cw > 1 && msg_col + t_col >= Columns - 1))
2326 	    {
2327 		if (l > 1)
2328 		    s = screen_puts_mbyte(s, l, attr) - 1;
2329 		else
2330 		    msg_screen_putchar(*s, attr);
2331 	    }
2332 	    else
2333 	    {
2334 		// postpone this character until later
2335 		if (t_col == 0)
2336 		    t_s = s;
2337 		t_col += cw;
2338 		s += l - 1;
2339 	    }
2340 	}
2341 	++s;
2342     }
2343 
2344     // output any postponed text
2345     if (t_col > 0)
2346 	t_puts(&t_col, t_s, s, attr);
2347     if (p_more && !recurse)
2348 	store_sb_text(&sb_str, s, attr, &sb_col, FALSE);
2349 
2350     msg_check();
2351 }
2352 
2353 /*
2354  * Return TRUE when ":filter pattern" was used and "msg" does not match
2355  * "pattern".
2356  */
2357     int
2358 message_filtered(char_u *msg)
2359 {
2360     int match;
2361 
2362     if (cmdmod.cmod_filter_regmatch.regprog == NULL)
2363 	return FALSE;
2364     match = vim_regexec(&cmdmod.cmod_filter_regmatch, msg, (colnr_T)0);
2365     return cmdmod.cmod_filter_force ? match : !match;
2366 }
2367 
2368 /*
2369  * Scroll the screen up one line for displaying the next message line.
2370  */
2371     static void
2372 msg_scroll_up(void)
2373 {
2374 #ifdef FEAT_GUI
2375     // Remove the cursor before scrolling, ScreenLines[] is going
2376     // to become invalid.
2377     if (gui.in_use)
2378 	gui_undraw_cursor();
2379 #endif
2380     // scrolling up always works
2381     mch_disable_flush();
2382     screen_del_lines(0, 0, 1, (int)Rows, TRUE, 0, NULL);
2383     mch_enable_flush();
2384 
2385     if (!can_clear((char_u *)" "))
2386     {
2387 	// Scrolling up doesn't result in the right background.  Set the
2388 	// background here.  It's not efficient, but avoids that we have to do
2389 	// it all over the code.
2390 	screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
2391 
2392 	// Also clear the last char of the last but one line if it was not
2393 	// cleared before to avoid a scroll-up.
2394 	if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1] == (sattr_T)-1)
2395 	    screen_fill((int)Rows - 2, (int)Rows - 1,
2396 				 (int)Columns - 1, (int)Columns, ' ', ' ', 0);
2397     }
2398 }
2399 
2400 /*
2401  * Increment "msg_scrolled".
2402  */
2403     static void
2404 inc_msg_scrolled(void)
2405 {
2406 #ifdef FEAT_EVAL
2407     if (*get_vim_var_str(VV_SCROLLSTART) == NUL)
2408     {
2409 	char_u	    *p = SOURCING_NAME;
2410 	char_u	    *tofree = NULL;
2411 	int	    len;
2412 
2413 	// v:scrollstart is empty, set it to the script/function name and line
2414 	// number
2415 	if (p == NULL)
2416 	    p = (char_u *)_("Unknown");
2417 	else
2418 	{
2419 	    len = (int)STRLEN(p) + 40;
2420 	    tofree = alloc(len);
2421 	    if (tofree != NULL)
2422 	    {
2423 		vim_snprintf((char *)tofree, len, _("%s line %ld"),
2424 						      p, (long)SOURCING_LNUM);
2425 		p = tofree;
2426 	    }
2427 	}
2428 	set_vim_var_string(VV_SCROLLSTART, p, -1);
2429 	vim_free(tofree);
2430     }
2431 #endif
2432     ++msg_scrolled;
2433     if (must_redraw < VALID)
2434 	must_redraw = VALID;
2435 }
2436 
2437 /*
2438  * To be able to scroll back at the "more" and "hit-enter" prompts we need to
2439  * store the displayed text and remember where screen lines start.
2440  */
2441 typedef struct msgchunk_S msgchunk_T;
2442 struct msgchunk_S
2443 {
2444     msgchunk_T	*sb_next;
2445     msgchunk_T	*sb_prev;
2446     char	sb_eol;		// TRUE when line ends after this text
2447     int		sb_msg_col;	// column in which text starts
2448     int		sb_attr;	// text attributes
2449     char_u	sb_text[1];	// text to be displayed, actually longer
2450 };
2451 
2452 static msgchunk_T *last_msgchunk = NULL; // last displayed text
2453 
2454 static msgchunk_T *msg_sb_start(msgchunk_T *mps);
2455 
2456 typedef enum {
2457     SB_CLEAR_NONE = 0,
2458     SB_CLEAR_ALL,
2459     SB_CLEAR_CMDLINE_BUSY,
2460     SB_CLEAR_CMDLINE_DONE
2461 } sb_clear_T;
2462 
2463 // When to clear text on next msg.
2464 static sb_clear_T do_clear_sb_text = SB_CLEAR_NONE;
2465 
2466 /*
2467  * Store part of a printed message for displaying when scrolling back.
2468  */
2469     static void
2470 store_sb_text(
2471     char_u	**sb_str,	// start of string
2472     char_u	*s,		// just after string
2473     int		attr,
2474     int		*sb_col,
2475     int		finish)		// line ends
2476 {
2477     msgchunk_T	*mp;
2478 
2479     if (do_clear_sb_text == SB_CLEAR_ALL
2480 	    || do_clear_sb_text == SB_CLEAR_CMDLINE_DONE)
2481     {
2482 	clear_sb_text(do_clear_sb_text == SB_CLEAR_ALL);
2483 	do_clear_sb_text = SB_CLEAR_NONE;
2484     }
2485 
2486     if (s > *sb_str)
2487     {
2488 	mp = alloc(sizeof(msgchunk_T) + (s - *sb_str));
2489 	if (mp != NULL)
2490 	{
2491 	    mp->sb_eol = finish;
2492 	    mp->sb_msg_col = *sb_col;
2493 	    mp->sb_attr = attr;
2494 	    vim_strncpy(mp->sb_text, *sb_str, s - *sb_str);
2495 
2496 	    if (last_msgchunk == NULL)
2497 	    {
2498 		last_msgchunk = mp;
2499 		mp->sb_prev = NULL;
2500 	    }
2501 	    else
2502 	    {
2503 		mp->sb_prev = last_msgchunk;
2504 		last_msgchunk->sb_next = mp;
2505 		last_msgchunk = mp;
2506 	    }
2507 	    mp->sb_next = NULL;
2508 	}
2509     }
2510     else if (finish && last_msgchunk != NULL)
2511 	last_msgchunk->sb_eol = TRUE;
2512 
2513     *sb_str = s;
2514     *sb_col = 0;
2515 }
2516 
2517 /*
2518  * Finished showing messages, clear the scroll-back text on the next message.
2519  */
2520     void
2521 may_clear_sb_text(void)
2522 {
2523     do_clear_sb_text = SB_CLEAR_ALL;
2524 }
2525 
2526 /*
2527  * Starting to edit the command line, do not clear messages now.
2528  */
2529     void
2530 sb_text_start_cmdline(void)
2531 {
2532     do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY;
2533     msg_sb_eol();
2534 }
2535 
2536 /*
2537  * Ending to edit the command line.  Clear old lines but the last one later.
2538  */
2539     void
2540 sb_text_end_cmdline(void)
2541 {
2542     do_clear_sb_text = SB_CLEAR_CMDLINE_DONE;
2543 }
2544 
2545 /*
2546  * Clear any text remembered for scrolling back.
2547  * When "all" is FALSE keep the last line.
2548  * Called when redrawing the screen.
2549  */
2550     void
2551 clear_sb_text(int all)
2552 {
2553     msgchunk_T	*mp;
2554     msgchunk_T	**lastp;
2555 
2556     if (all)
2557 	lastp = &last_msgchunk;
2558     else
2559     {
2560 	if (last_msgchunk == NULL)
2561 	    return;
2562 	lastp = &last_msgchunk->sb_prev;
2563     }
2564 
2565     while (*lastp != NULL)
2566     {
2567 	mp = (*lastp)->sb_prev;
2568 	vim_free(*lastp);
2569 	*lastp = mp;
2570     }
2571 }
2572 
2573 /*
2574  * "g<" command.
2575  */
2576     void
2577 show_sb_text(void)
2578 {
2579     msgchunk_T	*mp;
2580 
2581     // Only show something if there is more than one line, otherwise it looks
2582     // weird, typing a command without output results in one line.
2583     mp = msg_sb_start(last_msgchunk);
2584     if (mp == NULL || mp->sb_prev == NULL)
2585 	vim_beep(BO_MESS);
2586     else
2587     {
2588 	do_more_prompt('G');
2589 	wait_return(FALSE);
2590     }
2591 }
2592 
2593 /*
2594  * Move to the start of screen line in already displayed text.
2595  */
2596     static msgchunk_T *
2597 msg_sb_start(msgchunk_T *mps)
2598 {
2599     msgchunk_T *mp = mps;
2600 
2601     while (mp != NULL && mp->sb_prev != NULL && !mp->sb_prev->sb_eol)
2602 	mp = mp->sb_prev;
2603     return mp;
2604 }
2605 
2606 /*
2607  * Mark the last message chunk as finishing the line.
2608  */
2609     void
2610 msg_sb_eol(void)
2611 {
2612     if (last_msgchunk != NULL)
2613 	last_msgchunk->sb_eol = TRUE;
2614 }
2615 
2616 /*
2617  * Display a screen line from previously displayed text at row "row".
2618  * Returns a pointer to the text for the next line (can be NULL).
2619  */
2620     static msgchunk_T *
2621 disp_sb_line(int row, msgchunk_T *smp)
2622 {
2623     msgchunk_T	*mp = smp;
2624     char_u	*p;
2625 
2626     for (;;)
2627     {
2628 	msg_row = row;
2629 	msg_col = mp->sb_msg_col;
2630 	p = mp->sb_text;
2631 	if (*p == '\n')	    // don't display the line break
2632 	    ++p;
2633 	msg_puts_display(p, -1, mp->sb_attr, TRUE);
2634 	if (mp->sb_eol || mp->sb_next == NULL)
2635 	    break;
2636 	mp = mp->sb_next;
2637     }
2638     return mp->sb_next;
2639 }
2640 
2641 /*
2642  * Output any postponed text for msg_puts_attr_len().
2643  */
2644     static void
2645 t_puts(
2646     int		*t_col,
2647     char_u	*t_s,
2648     char_u	*s,
2649     int		attr)
2650 {
2651     // output postponed text
2652     msg_didout = TRUE;		// remember that line is not empty
2653     screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr);
2654     msg_col += *t_col;
2655     *t_col = 0;
2656     // If the string starts with a composing character don't increment the
2657     // column position for it.
2658     if (enc_utf8 && utf_iscomposing(utf_ptr2char(t_s)))
2659 	--msg_col;
2660     if (msg_col >= Columns)
2661     {
2662 	msg_col = 0;
2663 	++msg_row;
2664     }
2665 }
2666 
2667 /*
2668  * Returns TRUE when messages should be printed with mch_errmsg().
2669  * This is used when there is no valid screen, so we can see error messages.
2670  * If termcap is not active, we may be writing in an alternate console
2671  * window, cursor positioning may not work correctly (window size may be
2672  * different, e.g. for Win32 console) or we just don't know where the
2673  * cursor is.
2674  */
2675     int
2676 msg_use_printf(void)
2677 {
2678     return (!msg_check_screen()
2679 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
2680 # ifdef VIMDLL
2681 	    || (!gui.in_use && !termcap_active)
2682 # else
2683 	    || !termcap_active
2684 # endif
2685 #endif
2686 	    || (swapping_screen() && !termcap_active)
2687 	       );
2688 }
2689 
2690 /*
2691  * Print a message when there is no valid screen.
2692  */
2693     static void
2694 msg_puts_printf(char_u *str, int maxlen)
2695 {
2696     char_u	*s = str;
2697     char_u	*buf = NULL;
2698     char_u	*p = s;
2699 
2700 #ifdef MSWIN
2701     if (!(silent_mode && p_verbose == 0))
2702 	mch_settmode(TMODE_COOK);	// handle CR and NL correctly
2703 #endif
2704     while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL)
2705     {
2706 	if (!(silent_mode && p_verbose == 0))
2707 	{
2708 	    // NL --> CR NL translation (for Unix, not for "--version")
2709 	    if (*s == NL)
2710 	    {
2711 		int n = (int)(s - p);
2712 
2713 		buf = alloc(n + 3);
2714 		if (buf != NULL)
2715 		{
2716 		    memcpy(buf, p, n);
2717 		    if (!info_message)
2718 			buf[n++] = CAR;
2719 		    buf[n++] = NL;
2720 		    buf[n++] = NUL;
2721 		    if (info_message)   // informative message, not an error
2722 			mch_msg((char *)buf);
2723 		    else
2724 			mch_errmsg((char *)buf);
2725 		    vim_free(buf);
2726 		}
2727 		p = s + 1;
2728 	    }
2729 	}
2730 
2731 	// primitive way to compute the current column
2732 #ifdef FEAT_RIGHTLEFT
2733 	if (cmdmsg_rl)
2734 	{
2735 	    if (*s == CAR || *s == NL)
2736 		msg_col = Columns - 1;
2737 	    else
2738 		--msg_col;
2739 	}
2740 	else
2741 #endif
2742 	{
2743 	    if (*s == CAR || *s == NL)
2744 		msg_col = 0;
2745 	    else
2746 		++msg_col;
2747 	}
2748 	++s;
2749     }
2750 
2751     if (*p != NUL && !(silent_mode && p_verbose == 0))
2752     {
2753 	char_u *tofree = NULL;
2754 
2755 	if (maxlen > 0 && STRLEN(p) > (size_t)maxlen)
2756 	{
2757 	    tofree = vim_strnsave(p, (size_t)maxlen);
2758 	    p = tofree;
2759 	}
2760 	if (p != NULL)
2761 	{
2762 	    if (info_message)
2763 		mch_msg((char *)p);
2764 	    else
2765 		mch_errmsg((char *)p);
2766 	    vim_free(tofree);
2767 	}
2768     }
2769 
2770     msg_didout = TRUE;	    // assume that line is not empty
2771 
2772 #ifdef MSWIN
2773     if (!(silent_mode && p_verbose == 0))
2774 	mch_settmode(TMODE_RAW);
2775 #endif
2776 }
2777 
2778 /*
2779  * Show the more-prompt and handle the user response.
2780  * This takes care of scrolling back and displaying previously displayed text.
2781  * When at hit-enter prompt "typed_char" is the already typed character,
2782  * otherwise it's NUL.
2783  * Returns TRUE when jumping ahead to "confirm_msg_tail".
2784  */
2785     static int
2786 do_more_prompt(int typed_char)
2787 {
2788     static int	entered = FALSE;
2789     int		used_typed_char = typed_char;
2790     int		oldState = State;
2791     int		c;
2792 #ifdef FEAT_CON_DIALOG
2793     int		retval = FALSE;
2794 #endif
2795     int		toscroll;
2796     msgchunk_T	*mp_last = NULL;
2797     msgchunk_T	*mp;
2798     int		i;
2799 
2800     // We get called recursively when a timer callback outputs a message. In
2801     // that case don't show another prompt. Also when at the hit-Enter prompt
2802     // and nothing was typed.
2803     if (entered || (State == HITRETURN && typed_char == 0))
2804 	return FALSE;
2805     entered = TRUE;
2806 
2807     if (typed_char == 'G')
2808     {
2809 	// "g<": Find first line on the last page.
2810 	mp_last = msg_sb_start(last_msgchunk);
2811 	for (i = 0; i < Rows - 2 && mp_last != NULL
2812 					     && mp_last->sb_prev != NULL; ++i)
2813 	    mp_last = msg_sb_start(mp_last->sb_prev);
2814     }
2815 
2816     State = ASKMORE;
2817     setmouse();
2818     if (typed_char == NUL)
2819 	msg_moremsg(FALSE);
2820     for (;;)
2821     {
2822 	/*
2823 	 * Get a typed character directly from the user.
2824 	 */
2825 	if (used_typed_char != NUL)
2826 	{
2827 	    c = used_typed_char;	// was typed at hit-enter prompt
2828 	    used_typed_char = NUL;
2829 	}
2830 	else
2831 	    c = get_keystroke();
2832 
2833 #if defined(FEAT_MENU) && defined(FEAT_GUI)
2834 	if (c == K_MENU)
2835 	{
2836 	    int idx = get_menu_index(current_menu, ASKMORE);
2837 
2838 	    // Used a menu.  If it starts with CTRL-Y, it must
2839 	    // be a "Copy" for the clipboard.  Otherwise
2840 	    // assume that we end
2841 	    if (idx == MENU_INDEX_INVALID)
2842 		continue;
2843 	    c = *current_menu->strings[idx];
2844 	    if (c != NUL && current_menu->strings[idx][1] != NUL)
2845 		ins_typebuf(current_menu->strings[idx] + 1,
2846 				current_menu->noremap[idx], 0, TRUE,
2847 						   current_menu->silent[idx]);
2848 	}
2849 #endif
2850 
2851 	toscroll = 0;
2852 	switch (c)
2853 	{
2854 	case BS:		// scroll one line back
2855 	case K_BS:
2856 	case 'k':
2857 	case K_UP:
2858 	    toscroll = -1;
2859 	    break;
2860 
2861 	case CAR:		// one extra line
2862 	case NL:
2863 	case 'j':
2864 	case K_DOWN:
2865 	    toscroll = 1;
2866 	    break;
2867 
2868 	case 'u':		// Up half a page
2869 	    toscroll = -(Rows / 2);
2870 	    break;
2871 
2872 	case 'd':		// Down half a page
2873 	    toscroll = Rows / 2;
2874 	    break;
2875 
2876 	case 'b':		// one page back
2877 	case K_PAGEUP:
2878 	    toscroll = -(Rows - 1);
2879 	    break;
2880 
2881 	case ' ':		// one extra page
2882 	case 'f':
2883 	case K_PAGEDOWN:
2884 	case K_LEFTMOUSE:
2885 	    toscroll = Rows - 1;
2886 	    break;
2887 
2888 	case 'g':		// all the way back to the start
2889 	    toscroll = -999999;
2890 	    break;
2891 
2892 	case 'G':		// all the way to the end
2893 	    toscroll = 999999;
2894 	    lines_left = 999999;
2895 	    break;
2896 
2897 	case ':':		// start new command line
2898 #ifdef FEAT_CON_DIALOG
2899 	    if (!confirm_msg_used)
2900 #endif
2901 	    {
2902 		// Since got_int is set all typeahead will be flushed, but we
2903 		// want to keep this ':', remember that in a special way.
2904 		typeahead_noflush(':');
2905 #ifdef FEAT_TERMINAL
2906 		skip_term_loop = TRUE;
2907 #endif
2908 		cmdline_row = Rows - 1;		// put ':' on this line
2909 		skip_redraw = TRUE;		// skip redraw once
2910 		need_wait_return = FALSE;	// don't wait in main()
2911 	    }
2912 	    // FALLTHROUGH
2913 	case 'q':		// quit
2914 	case Ctrl_C:
2915 	case ESC:
2916 #ifdef FEAT_CON_DIALOG
2917 	    if (confirm_msg_used)
2918 	    {
2919 		// Jump to the choices of the dialog.
2920 		retval = TRUE;
2921 	    }
2922 	    else
2923 #endif
2924 	    {
2925 		got_int = TRUE;
2926 		quit_more = TRUE;
2927 	    }
2928 	    // When there is some more output (wrapping line) display that
2929 	    // without another prompt.
2930 	    lines_left = Rows - 1;
2931 	    break;
2932 
2933 #ifdef FEAT_CLIPBOARD
2934 	case Ctrl_Y:
2935 	    // Strange way to allow copying (yanking) a modeless
2936 	    // selection at the more prompt.  Use CTRL-Y,
2937 	    // because the same is used in Cmdline-mode and at the
2938 	    // hit-enter prompt.  However, scrolling one line up
2939 	    // might be expected...
2940 	    if (clip_star.state == SELECT_DONE)
2941 		clip_copy_modeless_selection(TRUE);
2942 	    continue;
2943 #endif
2944 	default:		// no valid response
2945 	    msg_moremsg(TRUE);
2946 	    continue;
2947 	}
2948 
2949 	if (toscroll != 0)
2950 	{
2951 	    if (toscroll < 0)
2952 	    {
2953 		// go to start of last line
2954 		if (mp_last == NULL)
2955 		    mp = msg_sb_start(last_msgchunk);
2956 		else if (mp_last->sb_prev != NULL)
2957 		    mp = msg_sb_start(mp_last->sb_prev);
2958 		else
2959 		    mp = NULL;
2960 
2961 		// go to start of line at top of the screen
2962 		for (i = 0; i < Rows - 2 && mp != NULL && mp->sb_prev != NULL;
2963 									  ++i)
2964 		    mp = msg_sb_start(mp->sb_prev);
2965 
2966 		if (mp != NULL && mp->sb_prev != NULL)
2967 		{
2968 		    // Find line to be displayed at top.
2969 		    for (i = 0; i > toscroll; --i)
2970 		    {
2971 			if (mp == NULL || mp->sb_prev == NULL)
2972 			    break;
2973 			mp = msg_sb_start(mp->sb_prev);
2974 			if (mp_last == NULL)
2975 			    mp_last = msg_sb_start(last_msgchunk);
2976 			else
2977 			    mp_last = msg_sb_start(mp_last->sb_prev);
2978 		    }
2979 
2980 		    if (toscroll == -1 && screen_ins_lines(0, 0, 1,
2981 						     (int)Rows, 0, NULL) == OK)
2982 		    {
2983 			// display line at top
2984 			(void)disp_sb_line(0, mp);
2985 		    }
2986 		    else
2987 		    {
2988 			// redisplay all lines
2989 			screenclear();
2990 			for (i = 0; mp != NULL && i < Rows - 1; ++i)
2991 			{
2992 			    mp = disp_sb_line(i, mp);
2993 			    ++msg_scrolled;
2994 			}
2995 		    }
2996 		    toscroll = 0;
2997 		}
2998 	    }
2999 	    else
3000 	    {
3001 		// First display any text that we scrolled back.
3002 		while (toscroll > 0 && mp_last != NULL)
3003 		{
3004 		    // scroll up, display line at bottom
3005 		    msg_scroll_up();
3006 		    inc_msg_scrolled();
3007 		    screen_fill((int)Rows - 2, (int)Rows - 1, 0,
3008 						   (int)Columns, ' ', ' ', 0);
3009 		    mp_last = disp_sb_line((int)Rows - 2, mp_last);
3010 		    --toscroll;
3011 		}
3012 	    }
3013 
3014 	    if (toscroll <= 0)
3015 	    {
3016 		// displayed the requested text, more prompt again
3017 		screen_fill((int)Rows - 1, (int)Rows, 0,
3018 						   (int)Columns, ' ', ' ', 0);
3019 		msg_moremsg(FALSE);
3020 		continue;
3021 	    }
3022 
3023 	    // display more text, return to caller
3024 	    lines_left = toscroll;
3025 	}
3026 
3027 	break;
3028     }
3029 
3030     // clear the --more-- message
3031     screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
3032     State = oldState;
3033     setmouse();
3034     if (quit_more)
3035     {
3036 	msg_row = Rows - 1;
3037 	msg_col = 0;
3038     }
3039 #ifdef FEAT_RIGHTLEFT
3040     else if (cmdmsg_rl)
3041 	msg_col = Columns - 1;
3042 #endif
3043 
3044     entered = FALSE;
3045 #ifdef FEAT_CON_DIALOG
3046     return retval;
3047 #else
3048     return FALSE;
3049 #endif
3050 }
3051 
3052 #if defined(USE_MCH_ERRMSG) || defined(PROTO)
3053 
3054 #ifdef mch_errmsg
3055 # undef mch_errmsg
3056 #endif
3057 #ifdef mch_msg
3058 # undef mch_msg
3059 #endif
3060 
3061 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
3062     static void
3063 mch_errmsg_c(char *str)
3064 {
3065     int	    len = (int)STRLEN(str);
3066     DWORD   nwrite = 0;
3067     DWORD   mode = 0;
3068     HANDLE  h = GetStdHandle(STD_ERROR_HANDLE);
3069 
3070     if (GetConsoleMode(h, &mode) && enc_codepage >= 0
3071 	    && (int)GetConsoleCP() != enc_codepage)
3072     {
3073 	WCHAR	*w = enc_to_utf16((char_u *)str, &len);
3074 
3075 	WriteConsoleW(h, w, len, &nwrite, NULL);
3076 	vim_free(w);
3077     }
3078     else
3079     {
3080 	fprintf(stderr, "%s", str);
3081     }
3082 }
3083 #endif
3084 
3085 /*
3086  * Give an error message.  To be used when the screen hasn't been initialized
3087  * yet.  When stderr can't be used, collect error messages until the GUI has
3088  * started and they can be displayed in a message box.
3089  */
3090     void
3091 mch_errmsg(char *str)
3092 {
3093 #if !defined(MSWIN) || defined(FEAT_GUI_MSWIN)
3094     int		len;
3095 #endif
3096 
3097 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI) && !defined(VIMDLL)
3098     // On Unix use stderr if it's a tty.
3099     // When not going to start the GUI also use stderr.
3100     // On Mac, when started from Finder, stderr is the console.
3101     if (
3102 # ifdef UNIX
3103 #  ifdef MACOS_X
3104 	    (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
3105 #  else
3106 	    isatty(2)
3107 #  endif
3108 #  ifdef FEAT_GUI
3109 	    ||
3110 #  endif
3111 # endif
3112 # ifdef FEAT_GUI
3113 	    !(gui.in_use || gui.starting)
3114 # endif
3115 	    )
3116     {
3117 	fprintf(stderr, "%s", str);
3118 	return;
3119     }
3120 #endif
3121 
3122 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
3123 # ifdef VIMDLL
3124     if (!(gui.in_use || gui.starting))
3125 # endif
3126     {
3127 	mch_errmsg_c(str);
3128 	return;
3129     }
3130 #endif
3131 
3132 #if !defined(MSWIN) || defined(FEAT_GUI_MSWIN)
3133     // avoid a delay for a message that isn't there
3134     emsg_on_display = FALSE;
3135 
3136     len = (int)STRLEN(str) + 1;
3137     if (error_ga.ga_growsize == 0)
3138     {
3139 	error_ga.ga_growsize = 80;
3140 	error_ga.ga_itemsize = 1;
3141     }
3142     if (ga_grow(&error_ga, len) == OK)
3143     {
3144 	mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len,
3145 							  (char_u *)str, len);
3146 # ifdef UNIX
3147 	// remove CR characters, they are displayed
3148 	{
3149 	    char_u	*p;
3150 
3151 	    p = (char_u *)error_ga.ga_data + error_ga.ga_len;
3152 	    for (;;)
3153 	    {
3154 		p = vim_strchr(p, '\r');
3155 		if (p == NULL)
3156 		    break;
3157 		*p = ' ';
3158 	    }
3159 	}
3160 # endif
3161 	--len;		// don't count the NUL at the end
3162 	error_ga.ga_len += len;
3163     }
3164 #endif
3165 }
3166 
3167 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
3168     static void
3169 mch_msg_c(char *str)
3170 {
3171     int	    len = (int)STRLEN(str);
3172     DWORD   nwrite = 0;
3173     DWORD   mode;
3174     HANDLE  h = GetStdHandle(STD_OUTPUT_HANDLE);
3175 
3176 
3177     if (GetConsoleMode(h, &mode) && enc_codepage >= 0
3178 	    && (int)GetConsoleCP() != enc_codepage)
3179     {
3180 	WCHAR	*w = enc_to_utf16((char_u *)str, &len);
3181 
3182 	WriteConsoleW(h, w, len, &nwrite, NULL);
3183 	vim_free(w);
3184     }
3185     else
3186     {
3187 	printf("%s", str);
3188     }
3189 }
3190 #endif
3191 
3192 /*
3193  * Give a message.  To be used when the screen hasn't been initialized yet.
3194  * When there is no tty, collect messages until the GUI has started and they
3195  * can be displayed in a message box.
3196  */
3197     void
3198 mch_msg(char *str)
3199 {
3200 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI) && !defined(VIMDLL)
3201     // On Unix use stdout if we have a tty.  This allows "vim -h | more" and
3202     // uses mch_errmsg() when started from the desktop.
3203     // When not going to start the GUI also use stdout.
3204     // On Mac, when started from Finder, stderr is the console.
3205     if (
3206 # ifdef UNIX
3207 #  ifdef MACOS_X
3208 	    (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
3209 #  else
3210 	    isatty(2)
3211 #  endif
3212 #  ifdef FEAT_GUI
3213 	    ||
3214 #  endif
3215 # endif
3216 # ifdef FEAT_GUI
3217 	    !(gui.in_use || gui.starting)
3218 # endif
3219 	    )
3220     {
3221 	printf("%s", str);
3222 	return;
3223     }
3224 #endif
3225 
3226 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
3227 # ifdef VIMDLL
3228     if (!(gui.in_use || gui.starting))
3229 # endif
3230     {
3231 	mch_msg_c(str);
3232 	return;
3233     }
3234 #endif
3235 #if !defined(MSWIN) || defined(FEAT_GUI_MSWIN)
3236     mch_errmsg(str);
3237 #endif
3238 }
3239 #endif // USE_MCH_ERRMSG
3240 
3241 /*
3242  * Put a character on the screen at the current message position and advance
3243  * to the next position.  Only for printable ASCII!
3244  */
3245     static void
3246 msg_screen_putchar(int c, int attr)
3247 {
3248     msg_didout = TRUE;		// remember that line is not empty
3249     screen_putchar(c, msg_row, msg_col, attr);
3250 #ifdef FEAT_RIGHTLEFT
3251     if (cmdmsg_rl)
3252     {
3253 	if (--msg_col == 0)
3254 	{
3255 	    msg_col = Columns;
3256 	    ++msg_row;
3257 	}
3258     }
3259     else
3260 #endif
3261     {
3262 	if (++msg_col >= Columns)
3263 	{
3264 	    msg_col = 0;
3265 	    ++msg_row;
3266 	}
3267     }
3268 }
3269 
3270     static void
3271 msg_moremsg(int full)
3272 {
3273     int		attr;
3274     char_u	*s = (char_u *)_("-- More --");
3275 
3276     attr = HL_ATTR(HLF_M);
3277     screen_puts(s, (int)Rows - 1, 0, attr);
3278     if (full)
3279 	screen_puts((char_u *)
3280 		_(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
3281 		(int)Rows - 1, vim_strsize(s), attr);
3282 }
3283 
3284 /*
3285  * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
3286  * exmode_active.
3287  */
3288     void
3289 repeat_message(void)
3290 {
3291     if (State == ASKMORE)
3292     {
3293 	msg_moremsg(TRUE);	// display --more-- message again
3294 	msg_row = Rows - 1;
3295     }
3296 #ifdef FEAT_CON_DIALOG
3297     else if (State == CONFIRM)
3298     {
3299 	display_confirm_msg();	// display ":confirm" message again
3300 	msg_row = Rows - 1;
3301     }
3302 #endif
3303     else if (State == EXTERNCMD)
3304     {
3305 	windgoto(msg_row, msg_col); // put cursor back
3306     }
3307     else if (State == HITRETURN || State == SETWSIZE)
3308     {
3309 	if (msg_row == Rows - 1)
3310 	{
3311 	    // Avoid drawing the "hit-enter" prompt below the previous one,
3312 	    // overwrite it.  Esp. useful when regaining focus and a
3313 	    // FocusGained autocmd exists but didn't draw anything.
3314 	    msg_didout = FALSE;
3315 	    msg_col = 0;
3316 	    msg_clr_eos();
3317 	}
3318 	hit_return_msg();
3319 	msg_row = Rows - 1;
3320     }
3321 }
3322 
3323 /*
3324  * msg_check_screen - check if the screen is initialized.
3325  * Also check msg_row and msg_col, if they are too big it may cause a crash.
3326  * While starting the GUI the terminal codes will be set for the GUI, but the
3327  * output goes to the terminal.  Don't use the terminal codes then.
3328  */
3329     static int
3330 msg_check_screen(void)
3331 {
3332     if (!full_screen || !screen_valid(FALSE))
3333 	return FALSE;
3334 
3335     if (msg_row >= Rows)
3336 	msg_row = Rows - 1;
3337     if (msg_col >= Columns)
3338 	msg_col = Columns - 1;
3339     return TRUE;
3340 }
3341 
3342 /*
3343  * Clear from current message position to end of screen.
3344  * Skip this when ":silent" was used, no need to clear for redirection.
3345  */
3346     void
3347 msg_clr_eos(void)
3348 {
3349     if (msg_silent == 0)
3350 	msg_clr_eos_force();
3351 }
3352 
3353 /*
3354  * Clear from current message position to end of screen.
3355  * Note: msg_col is not updated, so we remember the end of the message
3356  * for msg_check().
3357  */
3358     void
3359 msg_clr_eos_force(void)
3360 {
3361     if (msg_use_printf())
3362     {
3363 	if (full_screen)	// only when termcap codes are valid
3364 	{
3365 	    if (*T_CD)
3366 		out_str(T_CD);	// clear to end of display
3367 	    else if (*T_CE)
3368 		out_str(T_CE);	// clear to end of line
3369 	}
3370     }
3371     else
3372     {
3373 #ifdef FEAT_RIGHTLEFT
3374 	if (cmdmsg_rl)
3375 	{
3376 	    screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0);
3377 	    screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
3378 	}
3379 	else
3380 #endif
3381 	{
3382 	    screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns,
3383 								 ' ', ' ', 0);
3384 	    screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
3385 	}
3386     }
3387 }
3388 
3389 /*
3390  * Clear the command line.
3391  */
3392     void
3393 msg_clr_cmdline(void)
3394 {
3395     msg_row = cmdline_row;
3396     msg_col = 0;
3397     msg_clr_eos_force();
3398 }
3399 
3400 /*
3401  * end putting a message on the screen
3402  * call wait_return if the message does not fit in the available space
3403  * return TRUE if wait_return not called.
3404  */
3405     int
3406 msg_end(void)
3407 {
3408     /*
3409      * If the string is larger than the window,
3410      * or the ruler option is set and we run into it,
3411      * we have to redraw the window.
3412      * Do not do this if we are abandoning the file or editing the command line.
3413      */
3414     if (!exiting && need_wait_return && !(State & CMDLINE))
3415     {
3416 	wait_return(FALSE);
3417 	return FALSE;
3418     }
3419     out_flush();
3420     return TRUE;
3421 }
3422 
3423 /*
3424  * If the written message runs into the shown command or ruler, we have to
3425  * wait for hit-return and redraw the window later.
3426  */
3427     void
3428 msg_check(void)
3429 {
3430     if (msg_row == Rows - 1 && msg_col >= sc_col)
3431     {
3432 	need_wait_return = TRUE;
3433 	redraw_cmdline = TRUE;
3434     }
3435 }
3436 
3437 /*
3438  * May write a string to the redirection file.
3439  * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
3440  */
3441     static void
3442 redir_write(char_u *str, int maxlen)
3443 {
3444     char_u	*s = str;
3445     static int	cur_col = 0;
3446 
3447     // Don't do anything for displaying prompts and the like.
3448     if (redir_off)
3449 	return;
3450 
3451     // If 'verbosefile' is set prepare for writing in that file.
3452     if (*p_vfile != NUL && verbose_fd == NULL)
3453 	verbose_open();
3454 
3455     if (redirecting())
3456     {
3457 	// If the string doesn't start with CR or NL, go to msg_col
3458 	if (*s != '\n' && *s != '\r')
3459 	{
3460 	    while (cur_col < msg_col)
3461 	    {
3462 #ifdef FEAT_EVAL
3463 		if (redir_execute)
3464 		    execute_redir_str((char_u *)" ", -1);
3465 		else if (redir_reg)
3466 		    write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
3467 		else if (redir_vname)
3468 		    var_redir_str((char_u *)" ", -1);
3469 		else
3470 #endif
3471 		    if (redir_fd != NULL)
3472 		    fputs(" ", redir_fd);
3473 		if (verbose_fd != NULL)
3474 		    fputs(" ", verbose_fd);
3475 		++cur_col;
3476 	    }
3477 	}
3478 
3479 #ifdef FEAT_EVAL
3480 	if (redir_execute)
3481 	    execute_redir_str(s, maxlen);
3482 	else if (redir_reg)
3483 	    write_reg_contents(redir_reg, s, maxlen, TRUE);
3484 	else if (redir_vname)
3485 	    var_redir_str(s, maxlen);
3486 #endif
3487 
3488 	// Write and adjust the current column.
3489 	while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
3490 	{
3491 #ifdef FEAT_EVAL
3492 	    if (!redir_reg && !redir_vname && !redir_execute)
3493 #endif
3494 		if (redir_fd != NULL)
3495 		    putc(*s, redir_fd);
3496 	    if (verbose_fd != NULL)
3497 		putc(*s, verbose_fd);
3498 	    if (*s == '\r' || *s == '\n')
3499 		cur_col = 0;
3500 	    else if (*s == '\t')
3501 		cur_col += (8 - cur_col % 8);
3502 	    else
3503 		++cur_col;
3504 	    ++s;
3505 	}
3506 
3507 	if (msg_silent != 0)	// should update msg_col
3508 	    msg_col = cur_col;
3509     }
3510 }
3511 
3512     int
3513 redirecting(void)
3514 {
3515     return redir_fd != NULL || *p_vfile != NUL
3516 #ifdef FEAT_EVAL
3517 			  || redir_reg || redir_vname || redir_execute
3518 #endif
3519 				       ;
3520 }
3521 
3522 /*
3523  * Before giving verbose message.
3524  * Must always be called paired with verbose_leave()!
3525  */
3526     void
3527 verbose_enter(void)
3528 {
3529     if (*p_vfile != NUL)
3530 	++msg_silent;
3531 }
3532 
3533 /*
3534  * After giving verbose message.
3535  * Must always be called paired with verbose_enter()!
3536  */
3537     void
3538 verbose_leave(void)
3539 {
3540     if (*p_vfile != NUL)
3541 	if (--msg_silent < 0)
3542 	    msg_silent = 0;
3543 }
3544 
3545 /*
3546  * Like verbose_enter() and set msg_scroll when displaying the message.
3547  */
3548     void
3549 verbose_enter_scroll(void)
3550 {
3551     if (*p_vfile != NUL)
3552 	++msg_silent;
3553     else
3554 	// always scroll up, don't overwrite
3555 	msg_scroll = TRUE;
3556 }
3557 
3558 /*
3559  * Like verbose_leave() and set cmdline_row when displaying the message.
3560  */
3561     void
3562 verbose_leave_scroll(void)
3563 {
3564     if (*p_vfile != NUL)
3565     {
3566 	if (--msg_silent < 0)
3567 	    msg_silent = 0;
3568     }
3569     else
3570 	cmdline_row = msg_row;
3571 }
3572 
3573 /*
3574  * Called when 'verbosefile' is set: stop writing to the file.
3575  */
3576     void
3577 verbose_stop(void)
3578 {
3579     if (verbose_fd != NULL)
3580     {
3581 	fclose(verbose_fd);
3582 	verbose_fd = NULL;
3583     }
3584     verbose_did_open = FALSE;
3585 }
3586 
3587 /*
3588  * Open the file 'verbosefile'.
3589  * Return FAIL or OK.
3590  */
3591     int
3592 verbose_open(void)
3593 {
3594     if (verbose_fd == NULL && !verbose_did_open)
3595     {
3596 	// Only give the error message once.
3597 	verbose_did_open = TRUE;
3598 
3599 	verbose_fd = mch_fopen((char *)p_vfile, "a");
3600 	if (verbose_fd == NULL)
3601 	{
3602 	    semsg(_(e_notopen), p_vfile);
3603 	    return FAIL;
3604 	}
3605     }
3606     return OK;
3607 }
3608 
3609 /*
3610  * Give a warning message (for searching).
3611  * Use 'w' highlighting and may repeat the message after redrawing
3612  */
3613     void
3614 give_warning(char_u *message, int hl)
3615 {
3616     give_warning_with_source(message, hl, FALSE);
3617 }
3618 
3619     void
3620 give_warning_with_source(char_u *message, int hl, int with_source)
3621 {
3622     // Don't do this for ":silent".
3623     if (msg_silent != 0)
3624 	return;
3625 
3626     // Don't want a hit-enter prompt here.
3627     ++no_wait_return;
3628 
3629 #ifdef FEAT_EVAL
3630     set_vim_var_string(VV_WARNINGMSG, message, -1);
3631 #endif
3632     VIM_CLEAR(keep_msg);
3633     if (hl)
3634 	keep_msg_attr = HL_ATTR(HLF_W);
3635     else
3636 	keep_msg_attr = 0;
3637 
3638     if (with_source)
3639     {
3640 	// Do what msg() does, but with a column offset if the warning should
3641 	// be after the mode message.
3642 	msg_start();
3643 	msg_source(HL_ATTR(HLF_W));
3644 	msg_puts(" ");
3645 	msg_puts_attr((char *)message, HL_ATTR(HLF_W) | MSG_HIST);
3646 	msg_clr_eos();
3647 	(void)msg_end();
3648     }
3649     else if (msg_attr((char *)message, keep_msg_attr) && msg_scrolled == 0)
3650 	set_keep_msg(message, keep_msg_attr);
3651 
3652     msg_didout = FALSE;	    // overwrite this message
3653     msg_nowait = TRUE;	    // don't wait for this message
3654     msg_col = 0;
3655 
3656     --no_wait_return;
3657 }
3658 
3659 #if defined(FEAT_EVAL) || defined(PROTO)
3660     void
3661 give_warning2(char_u *message, char_u *a1, int hl)
3662 {
3663     if (IObuff == NULL)
3664     {
3665 	// Very early in initialisation and already something wrong, just give
3666 	// the raw message so the user at least gets a hint.
3667 	give_warning((char_u *)message, hl);
3668     }
3669     else
3670     {
3671 	vim_snprintf((char *)IObuff, IOSIZE, (char *)message, a1);
3672 	give_warning(IObuff, hl);
3673     }
3674 }
3675 #endif
3676 
3677 /*
3678  * Advance msg cursor to column "col".
3679  */
3680     void
3681 msg_advance(int col)
3682 {
3683     if (msg_silent != 0)	// nothing to advance to
3684     {
3685 	msg_col = col;		// for redirection, may fill it up later
3686 	return;
3687     }
3688     if (col >= Columns)		// not enough room
3689 	col = Columns - 1;
3690 #ifdef FEAT_RIGHTLEFT
3691     if (cmdmsg_rl)
3692 	while (msg_col > Columns - col)
3693 	    msg_putchar(' ');
3694     else
3695 #endif
3696 	while (msg_col < col)
3697 	    msg_putchar(' ');
3698 }
3699 
3700 #if defined(FEAT_CON_DIALOG) || defined(PROTO)
3701 /*
3702  * Used for "confirm()" function, and the :confirm command prefix.
3703  * Versions which haven't got flexible dialogs yet, and console
3704  * versions, get this generic handler which uses the command line.
3705  *
3706  * type  = one of:
3707  *	   VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC
3708  * title = title string (can be NULL for default)
3709  * (neither used in console dialogs at the moment)
3710  *
3711  * Format of the "buttons" string:
3712  * "Button1Name\nButton2Name\nButton3Name"
3713  * The first button should normally be the default/accept
3714  * The second button should be the 'Cancel' button
3715  * Other buttons- use your imagination!
3716  * A '&' in a button name becomes a shortcut, so each '&' should be before a
3717  * different letter.
3718  */
3719     int
3720 do_dialog(
3721     int		type UNUSED,
3722     char_u	*title UNUSED,
3723     char_u	*message,
3724     char_u	*buttons,
3725     int		dfltbutton,
3726     char_u	*textfield UNUSED,	// IObuff for inputdialog(), NULL
3727 					// otherwise
3728     int		ex_cmd)	    // when TRUE pressing : accepts default and starts
3729 			    // Ex command
3730 {
3731     int		oldState;
3732     int		retval = 0;
3733     char_u	*hotkeys;
3734     int		c;
3735     int		i;
3736     tmode_T	save_tmode;
3737 
3738 #ifndef NO_CONSOLE
3739     // Don't output anything in silent mode ("ex -s")
3740     if (silent_mode)
3741 	return dfltbutton;   // return default option
3742 #endif
3743 
3744 #ifdef FEAT_GUI_DIALOG
3745     // When GUI is running and 'c' not in 'guioptions', use the GUI dialog
3746     if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
3747     {
3748 	c = gui_mch_dialog(type, title, message, buttons, dfltbutton,
3749 							   textfield, ex_cmd);
3750 	// avoid a hit-enter prompt without clearing the cmdline
3751 	need_wait_return = FALSE;
3752 	emsg_on_display = FALSE;
3753 	cmdline_row = msg_row;
3754 
3755 	// Flush output to avoid that further messages and redrawing is done
3756 	// in the wrong order.
3757 	out_flush();
3758 	gui_mch_update();
3759 
3760 	return c;
3761     }
3762 #endif
3763 
3764     oldState = State;
3765     State = CONFIRM;
3766     setmouse();
3767 
3768     // Ensure raw mode here.
3769     save_tmode = cur_tmode;
3770     settmode(TMODE_RAW);
3771 
3772     /*
3773      * Since we wait for a keypress, don't make the
3774      * user press RETURN as well afterwards.
3775      */
3776     ++no_wait_return;
3777     hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
3778 
3779     if (hotkeys != NULL)
3780     {
3781 	for (;;)
3782 	{
3783 	    // Get a typed character directly from the user.
3784 	    c = get_keystroke();
3785 	    switch (c)
3786 	    {
3787 	    case CAR:		// User accepts default option
3788 	    case NL:
3789 		retval = dfltbutton;
3790 		break;
3791 	    case Ctrl_C:	// User aborts/cancels
3792 	    case ESC:
3793 		retval = 0;
3794 		break;
3795 	    default:		// Could be a hotkey?
3796 		if (c < 0)	// special keys are ignored here
3797 		    continue;
3798 		if (c == ':' && ex_cmd)
3799 		{
3800 		    retval = dfltbutton;
3801 		    ins_char_typebuf(':', 0);
3802 		    break;
3803 		}
3804 
3805 		// Make the character lowercase, as chars in "hotkeys" are.
3806 		c = MB_TOLOWER(c);
3807 		retval = 1;
3808 		for (i = 0; hotkeys[i]; ++i)
3809 		{
3810 		    if (has_mbyte)
3811 		    {
3812 			if ((*mb_ptr2char)(hotkeys + i) == c)
3813 			    break;
3814 			i += (*mb_ptr2len)(hotkeys + i) - 1;
3815 		    }
3816 		    else
3817 			if (hotkeys[i] == c)
3818 			    break;
3819 		    ++retval;
3820 		}
3821 		if (hotkeys[i])
3822 		    break;
3823 		// No hotkey match, so keep waiting
3824 		continue;
3825 	    }
3826 	    break;
3827 	}
3828 
3829 	vim_free(hotkeys);
3830     }
3831 
3832     settmode(save_tmode);
3833     State = oldState;
3834     setmouse();
3835     --no_wait_return;
3836     msg_end_prompt();
3837 
3838     return retval;
3839 }
3840 
3841 /*
3842  * Copy one character from "*from" to "*to", taking care of multi-byte
3843  * characters.  Return the length of the character in bytes.
3844  */
3845     static int
3846 copy_char(
3847     char_u	*from,
3848     char_u	*to,
3849     int		lowercase)	// make character lower case
3850 {
3851     int		len;
3852     int		c;
3853 
3854     if (has_mbyte)
3855     {
3856 	if (lowercase)
3857 	{
3858 	    c = MB_TOLOWER((*mb_ptr2char)(from));
3859 	    return (*mb_char2bytes)(c, to);
3860 	}
3861 	else
3862 	{
3863 	    len = (*mb_ptr2len)(from);
3864 	    mch_memmove(to, from, (size_t)len);
3865 	    return len;
3866 	}
3867     }
3868     else
3869     {
3870 	if (lowercase)
3871 	    *to = (char_u)TOLOWER_LOC(*from);
3872 	else
3873 	    *to = *from;
3874 	return 1;
3875     }
3876 }
3877 
3878 /*
3879  * Format the dialog string, and display it at the bottom of
3880  * the screen. Return a string of hotkey chars (if defined) for
3881  * each 'button'. If a button has no hotkey defined, the first character of
3882  * the button is used.
3883  * The hotkeys can be multi-byte characters, but without combining chars.
3884  *
3885  * Returns an allocated string with hotkeys, or NULL for error.
3886  */
3887     static char_u *
3888 msg_show_console_dialog(
3889     char_u	*message,
3890     char_u	*buttons,
3891     int		dfltbutton)
3892 {
3893     int		len = 0;
3894 #define HOTK_LEN (has_mbyte ? MB_MAXBYTES : 1)
3895     int		lenhotkey = HOTK_LEN;	// count first button
3896     char_u	*hotk = NULL;
3897     char_u	*msgp = NULL;
3898     char_u	*hotkp = NULL;
3899     char_u	*r;
3900     int		copy;
3901 #define HAS_HOTKEY_LEN 30
3902     char_u	has_hotkey[HAS_HOTKEY_LEN];
3903     int		first_hotkey = FALSE;	// first char of button is hotkey
3904     int		idx;
3905 
3906     has_hotkey[0] = FALSE;
3907 
3908     /*
3909      * First loop: compute the size of memory to allocate.
3910      * Second loop: copy to the allocated memory.
3911      */
3912     for (copy = 0; copy <= 1; ++copy)
3913     {
3914 	r = buttons;
3915 	idx = 0;
3916 	while (*r)
3917 	{
3918 	    if (*r == DLG_BUTTON_SEP)
3919 	    {
3920 		if (copy)
3921 		{
3922 		    *msgp++ = ',';
3923 		    *msgp++ = ' ';	    // '\n' -> ', '
3924 
3925 		    // advance to next hotkey and set default hotkey
3926 		    if (has_mbyte)
3927 			hotkp += STRLEN(hotkp);
3928 		    else
3929 			++hotkp;
3930 		    hotkp[copy_char(r + 1, hotkp, TRUE)] = NUL;
3931 		    if (dfltbutton)
3932 			--dfltbutton;
3933 
3934 		    // If no hotkey is specified first char is used.
3935 		    if (idx < HAS_HOTKEY_LEN - 1 && !has_hotkey[++idx])
3936 			first_hotkey = TRUE;
3937 		}
3938 		else
3939 		{
3940 		    len += 3;		    // '\n' -> ', '; 'x' -> '(x)'
3941 		    lenhotkey += HOTK_LEN;  // each button needs a hotkey
3942 		    if (idx < HAS_HOTKEY_LEN - 1)
3943 			has_hotkey[++idx] = FALSE;
3944 		}
3945 	    }
3946 	    else if (*r == DLG_HOTKEY_CHAR || first_hotkey)
3947 	    {
3948 		if (*r == DLG_HOTKEY_CHAR)
3949 		    ++r;
3950 		first_hotkey = FALSE;
3951 		if (copy)
3952 		{
3953 		    if (*r == DLG_HOTKEY_CHAR)		// '&&a' -> '&a'
3954 			*msgp++ = *r;
3955 		    else
3956 		    {
3957 			// '&a' -> '[a]'
3958 			*msgp++ = (dfltbutton == 1) ? '[' : '(';
3959 			msgp += copy_char(r, msgp, FALSE);
3960 			*msgp++ = (dfltbutton == 1) ? ']' : ')';
3961 
3962 			// redefine hotkey
3963 			hotkp[copy_char(r, hotkp, TRUE)] = NUL;
3964 		    }
3965 		}
3966 		else
3967 		{
3968 		    ++len;	    // '&a' -> '[a]'
3969 		    if (idx < HAS_HOTKEY_LEN - 1)
3970 			has_hotkey[idx] = TRUE;
3971 		}
3972 	    }
3973 	    else
3974 	    {
3975 		// everything else copy literally
3976 		if (copy)
3977 		    msgp += copy_char(r, msgp, FALSE);
3978 	    }
3979 
3980 	    // advance to the next character
3981 	    MB_PTR_ADV(r);
3982 	}
3983 
3984 	if (copy)
3985 	{
3986 	    *msgp++ = ':';
3987 	    *msgp++ = ' ';
3988 	    *msgp = NUL;
3989 	}
3990 	else
3991 	{
3992 	    len += (int)(STRLEN(message)
3993 			+ 2			// for the NL's
3994 			+ STRLEN(buttons)
3995 			+ 3);			// for the ": " and NUL
3996 	    lenhotkey++;			// for the NUL
3997 
3998 	    // If no hotkey is specified first char is used.
3999 	    if (!has_hotkey[0])
4000 	    {
4001 		first_hotkey = TRUE;
4002 		len += 2;		// "x" -> "[x]"
4003 	    }
4004 
4005 	    /*
4006 	     * Now allocate and load the strings
4007 	     */
4008 	    vim_free(confirm_msg);
4009 	    confirm_msg = alloc(len);
4010 	    if (confirm_msg == NULL)
4011 		return NULL;
4012 	    *confirm_msg = NUL;
4013 	    hotk = alloc(lenhotkey);
4014 	    if (hotk == NULL)
4015 		return NULL;
4016 
4017 	    *confirm_msg = '\n';
4018 	    STRCPY(confirm_msg + 1, message);
4019 
4020 	    msgp = confirm_msg + 1 + STRLEN(message);
4021 	    hotkp = hotk;
4022 
4023 	    // Define first default hotkey.  Keep the hotkey string NUL
4024 	    // terminated to avoid reading past the end.
4025 	    hotkp[copy_char(buttons, hotkp, TRUE)] = NUL;
4026 
4027 	    // Remember where the choices start, displaying starts here when
4028 	    // "hotkp" typed at the more prompt.
4029 	    confirm_msg_tail = msgp;
4030 	    *msgp++ = '\n';
4031 	}
4032     }
4033 
4034     display_confirm_msg();
4035     return hotk;
4036 }
4037 
4038 /*
4039  * Display the ":confirm" message.  Also called when screen resized.
4040  */
4041     static void
4042 display_confirm_msg(void)
4043 {
4044     // avoid that 'q' at the more prompt truncates the message here
4045     ++confirm_msg_used;
4046     if (confirm_msg != NULL)
4047 	msg_puts_attr((char *)confirm_msg, HL_ATTR(HLF_M));
4048     --confirm_msg_used;
4049 }
4050 
4051 #endif // FEAT_CON_DIALOG
4052 
4053 #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
4054 
4055     int
4056 vim_dialog_yesno(
4057     int		type,
4058     char_u	*title,
4059     char_u	*message,
4060     int		dflt)
4061 {
4062     if (do_dialog(type,
4063 		title == NULL ? (char_u *)_("Question") : title,
4064 		message,
4065 		(char_u *)_("&Yes\n&No"), dflt, NULL, FALSE) == 1)
4066 	return VIM_YES;
4067     return VIM_NO;
4068 }
4069 
4070     int
4071 vim_dialog_yesnocancel(
4072     int		type,
4073     char_u	*title,
4074     char_u	*message,
4075     int		dflt)
4076 {
4077     switch (do_dialog(type,
4078 		title == NULL ? (char_u *)_("Question") : title,
4079 		message,
4080 		(char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL, FALSE))
4081     {
4082 	case 1: return VIM_YES;
4083 	case 2: return VIM_NO;
4084     }
4085     return VIM_CANCEL;
4086 }
4087 
4088     int
4089 vim_dialog_yesnoallcancel(
4090     int		type,
4091     char_u	*title,
4092     char_u	*message,
4093     int		dflt)
4094 {
4095     switch (do_dialog(type,
4096 		title == NULL ? (char_u *)"Question" : title,
4097 		message,
4098 		(char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
4099 							   dflt, NULL, FALSE))
4100     {
4101 	case 1: return VIM_YES;
4102 	case 2: return VIM_NO;
4103 	case 3: return VIM_ALL;
4104 	case 4: return VIM_DISCARDALL;
4105     }
4106     return VIM_CANCEL;
4107 }
4108 
4109 #endif // FEAT_GUI_DIALOG || FEAT_CON_DIALOG
4110