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

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * 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. #ifdef HAVE_STDARG_H
  19. # include <stdarg.h>
  20. #endif
  21.  
  22. static void reset_last_sourcing __ARGS((void));
  23. static void add_msg_hist __ARGS((char_u *s, int len, int attr));
  24. static void hit_return_msg __ARGS((void));
  25. static void msg_home_replace_attr __ARGS((char_u *fname, int attr));
  26. #ifdef FEAT_MBYTE
  27. static char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr));
  28. #endif
  29. static void msg_puts_attr_len __ARGS((char_u *str, int maxlen, int attr));
  30. static void t_puts __ARGS((int t_col, char_u *t_s, char_u *s, int attr));
  31. static void msg_screen_putchar __ARGS((int c, int attr));
  32. static int  msg_check_screen __ARGS((void));
  33. static void redir_write __ARGS((char_u *s, int maxlen));
  34. #ifdef FEAT_CON_DIALOG
  35. static char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton));
  36. static int    confirm_msg_used = FALSE;    /* displaying confirm_msg */
  37. static char_u    *confirm_msg = NULL;        /* ":confirm" message */
  38. static char_u    *confirm_msg_tail;        /* tail of confirm_msg */
  39. #endif
  40.  
  41. struct msg_hist
  42. {
  43.     struct msg_hist    *next;
  44.     char_u        *msg;
  45.     int            attr;
  46. };
  47.  
  48. static struct msg_hist *first_msg_hist = NULL;
  49. static struct msg_hist *last_msg_hist = NULL;
  50. static int msg_hist_len = 0;
  51. static int msg_hist_off = FALSE;    /* don't add messages to history */
  52.  
  53. /*
  54.  * When writing messages to the screen, there are many different situations.
  55.  * A number of variables is used to remember the current state:
  56.  * msg_didany        TRUE when messages were written since the last time the
  57.  *            user reacted to a prompt.
  58.  *            Reset: After hitting a key for the hit-return prompt,
  59.  *            hitting <CR> for the command line or input().
  60.  *            Set: When any message is written to the screen.
  61.  * msg_didout        TRUE when something was written to the current line.
  62.  *            Reset: When advancing to the next line, when the current
  63.  *            text can be overwritten.
  64.  *            Set: When any message is written to the screen.
  65.  * msg_nowait        No extra delay for the last drawn message.
  66.  *            Used in normal_cmd() before the mode message is drawn.
  67.  * emsg_on_display  There was an error message recently.  Indicates that there
  68.  *            should be a delay before redrawing.
  69.  * msg_scroll        The next message should not overwrite the current one.
  70.  * msg_scrolled        How many lines the screen has been scrolled (because of
  71.  *            messages).  Used in update_screen() to scroll the screen
  72.  *            back.  Incremented each time the screen scrolls a line.
  73.  * msg_scrolled_ign  TRUE when msg_scrolled is non-zero and msg_puts_attr()
  74.  *            writes something without scrolling should not make
  75.  *            need_wait_return to be set.  This is a hack to make ":ts"
  76.  *            work without an extra prompt.
  77.  * lines_left        Number of lines available for messages before the
  78.  *            more-prompt is to be given.
  79.  * need_wait_return TRUE when the hit-return prompt is needed.
  80.  *            Reset: After giving the hit-return prompt, when the user
  81.  *            has answered some other prompt.
  82.  *            Set: When the ruler or typeahead display is overwritten,
  83.  *            scrolling the screen for some message.
  84.  * keep_msg        Message to be displayed after redrawing the screen, in
  85.  *            main_loop().
  86.  *            This is an allocated string or NULL when not used.
  87.  */
  88.  
  89. /*
  90.  * msg(s) - displays the string 's' on the status line
  91.  * When terminal not initialized (yet) mch_errmsg(..) is used.
  92.  * return TRUE if wait_return not called
  93.  */
  94.     int
  95. msg(s)
  96.     char_u    *s;
  97. {
  98.     return msg_attr_keep(s, 0, FALSE);
  99. }
  100.  
  101.     int
  102. msg_attr(s, attr)
  103.     char_u    *s;
  104.     int        attr;
  105. {
  106.     return msg_attr_keep(s, attr, FALSE);
  107. }
  108.  
  109.     int
  110. msg_attr_keep(s, attr, keep)
  111.     char_u    *s;
  112.     int        attr;
  113.     int        keep;        /* TRUE: set keep_msg if it doesn't scroll */
  114. {
  115.     static int    entered = 0;
  116.     int        retval;
  117.     char_u    *buf = NULL;
  118.  
  119. #ifdef FEAT_EVAL
  120.     if (attr == 0)
  121.     set_vim_var_string(VV_STATUSMSG, s, -1);
  122. #endif
  123.  
  124.     /*
  125.      * It is possible that displaying a messages causes a problem (e.g.,
  126.      * when redrawing the window), which causes another message, etc..    To
  127.      * break this loop, limit the recursiveness to 3 levels.
  128.      */
  129.     if (entered >= 3)
  130.     return TRUE;
  131.     ++entered;
  132.  
  133.     /* Add message to history (unless it's a repeated kept message or a
  134.      * truncated message) */
  135.     if (s != keep_msg
  136.         || (*s != '<'
  137.         && last_msg_hist != NULL
  138.         && last_msg_hist->msg != NULL
  139.         && STRCMP(s, last_msg_hist->msg)))
  140.     add_msg_hist(s, -1, attr);
  141.  
  142.     /* When displaying keep_msg, don't let msg_start() free it, caller must do
  143.      * that. */
  144.     if (s == keep_msg)
  145.     keep_msg = NULL;
  146.  
  147.     /* Truncate the message if needed. */
  148.     buf = msg_strtrunc(s);
  149.     if (buf != NULL)
  150.     s = buf;
  151.  
  152.     msg_start();
  153.     msg_outtrans_attr(s, attr);
  154.     if (msg_silent == 0)
  155.     msg_clr_eos();
  156.     retval = msg_end();
  157.  
  158.     if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1)
  159.                                * Columns + sc_col)
  160.     {
  161.     set_keep_msg(s);
  162.     keep_msg_attr = 0;
  163.     }
  164.  
  165.     vim_free(buf);
  166.     --entered;
  167.     return retval;
  168. }
  169.  
  170. /*
  171.  * Truncate a string such that it can be printed without causing a scroll.
  172.  * Returns an allocated string or NULL when no truncating is done.
  173.  */
  174.     char_u *
  175. msg_strtrunc(s)
  176.     char_u    *s;
  177. {
  178.     char_u    *buf = NULL;
  179.     int        len;
  180.     int        room;
  181.  
  182.     /* May truncate message to avoid a hit-return prompt */
  183.     if (!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL)
  184.                                 && !exmode_active)
  185.     {
  186.     len = vim_strsize(s);
  187.     room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
  188.     if (len > room && room > 0)
  189.     {
  190. #ifdef FEAT_MBYTE
  191.         if (enc_utf8)
  192.         /* may have up to 18 bytes per cell (6 per char, up to two
  193.          * composing chars) */
  194.         buf = alloc((room + 2) * 18);
  195.         else if (enc_dbcs == DBCS_JPNU)
  196.         /* may have up to 2 bytes per cell for euc-jp */
  197.         buf = alloc((room + 2) * 2);
  198.         else
  199. #endif
  200.         buf = alloc(room + 2);
  201.         if (buf != NULL)
  202.         trunc_string(s, buf, room);
  203.     }
  204.     }
  205.     return buf;
  206. }
  207.  
  208. /*
  209.  * Truncate a string "s" to "buf" with cell width "room".
  210.  * "s" and "buf" may be equal.
  211.  */
  212.     void
  213. trunc_string(s, buf, room)
  214.     char_u    *s;
  215.     char_u    *buf;
  216.     int        room;
  217. {
  218.     int        half;
  219.     int        len;
  220.     int        e;
  221.     int        i;
  222.     int        n;
  223.  
  224.     room -= 3;
  225.     half = room / 2;
  226.     len = 0;
  227.  
  228.     /* First part: Start of the string. */
  229.     for (e = 0; len < half; ++e)
  230.     {
  231.     if (s[e] == NUL)
  232.     {
  233.         /* text fits without truncating! */
  234.         buf[e] = NUL;
  235.         return;
  236.     }
  237.     n = ptr2cells(s + e);
  238.     if (len + n >= half)
  239.         break;
  240.     len += n;
  241.     buf[e] = s[e];
  242. #ifdef FEAT_MBYTE
  243.     if (has_mbyte)
  244.         for (n = (*mb_ptr2len_check)(s + e); --n > 0; )
  245.         {
  246.         ++e;
  247.         buf[e] = s[e];
  248.         }
  249. #endif
  250.     }
  251.  
  252.     /* Last part: End of the string. */
  253.     i = e;
  254. #ifdef FEAT_MBYTE
  255.     if (enc_dbcs != 0)
  256.     {
  257.     /* For DBCS going backwards in a string is slow, but
  258.      * computing the cell width isn't too slow: go forward
  259.      * until the rest fits. */
  260.     n = vim_strsize(s + i);
  261.     while (len + n > room)
  262.     {
  263.         n -= ptr2cells(s + i);
  264.         i += (*mb_ptr2len_check)(s + i);
  265.     }
  266.     }
  267.     else if (enc_utf8)
  268.     {
  269.     /* For UTF-8 we can go backwards easily. */
  270.     i = (int)STRLEN(s);
  271.     for (;;)
  272.     {
  273.         half = i - (*mb_head_off)(s, s + i - 1) - 1;
  274.         n = ptr2cells(s + half);
  275.         if (len + n > room)
  276.         break;
  277.         len += n;
  278.         i = half;
  279.     }
  280.     }
  281.     else
  282. #endif
  283.     {
  284.     for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i)
  285.         len += n;
  286.     }
  287.  
  288.     /* Set the middle and copy the last part. */
  289.     mch_memmove(buf + e, "...", (size_t)3);
  290.     mch_memmove(buf + e + 3, s + i, STRLEN(s + i) + 1);
  291. }
  292.  
  293. /*
  294.  * Automatic prototype generation does not understand this function.
  295.  * Note: Caller of smgs() and smsg_attr() must check the resulting string is
  296.  * shorter than IOSIZE!!!
  297.  */
  298. #ifndef PROTO
  299. # ifndef HAVE_STDARG_H
  300.  
  301. int
  302. #ifdef __BORLANDC__
  303. _RTLENTRYF
  304. #endif
  305. smsg __ARGS((char_u *, long, long, long,
  306.             long, long, long, long, long, long, long));
  307. int
  308. #ifdef __BORLANDC__
  309. _RTLENTRYF
  310. #endif
  311. smsg_attr __ARGS((int, char_u *, long, long, long,
  312.             long, long, long, long, long, long, long));
  313.  
  314. /* VARARGS */
  315.     int
  316. #ifdef __BORLANDC__
  317. _RTLENTRYF
  318. #endif
  319. smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  320.     char_u    *s;
  321.     long    a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  322. {
  323.     return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  324. }
  325.  
  326. /* VARARGS */
  327.     int
  328. #ifdef __BORLANDC__
  329. _RTLENTRYF
  330. #endif
  331. smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  332.     int        attr;
  333.     char_u    *s;
  334.     long    a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  335. {
  336.     sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  337.     return msg_attr(IObuff, attr);
  338. }
  339.  
  340. # else /* HAVE_STDARG_H */
  341.  
  342.     int
  343. #ifdef __BORLANDC__
  344. _RTLENTRYF
  345. #endif
  346. smsg(char_u *s, ...)
  347. {
  348.     va_list arglist;
  349.  
  350.     va_start(arglist, s);
  351. # ifdef HAVE_VSNPRINTF
  352.     vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
  353. # else
  354.     vsprintf((char *)IObuff, (char *)s, arglist);
  355. # endif
  356.     va_end(arglist);
  357.     return msg(IObuff);
  358. }
  359.  
  360.     int
  361. #ifdef __BORLANDC__
  362. _RTLENTRYF
  363. #endif
  364. smsg_attr(int attr, char_u *s, ...)
  365. {
  366.     va_list arglist;
  367.  
  368.     va_start(arglist, s);
  369. # ifdef HAVE_VSNPRINTF
  370.     vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
  371. # else
  372.     vsprintf((char *)IObuff, (char *)s, arglist);
  373. # endif
  374.     va_end(arglist);
  375.     return msg_attr(IObuff, attr);
  376. }
  377.  
  378. # endif /* HAVE_STDARG_H */
  379. #endif
  380.  
  381. /*
  382.  * Remember the last sourcing name/lnum used in an error message, so that it
  383.  * isn't printed each time when it didn't change.
  384.  */
  385. static int    last_sourcing_lnum = 0;
  386. static char_u   *last_sourcing_name = NULL;
  387.  
  388. /*
  389.  * Reset the last used sourcing name/lnum.  Makes sure it is displayed again
  390.  * for the next error message;
  391.  */
  392.     static void
  393. reset_last_sourcing()
  394. {
  395.     vim_free(last_sourcing_name);
  396.     last_sourcing_name = NULL;
  397.     last_sourcing_lnum = 0;
  398. }
  399.  
  400. /*
  401.  * emsg() - display an error message
  402.  *
  403.  * Rings the bell, if appropriate, and calls message() to do the real work
  404.  * When terminal not initialized (yet) mch_errmsg(..) is used.
  405.  *
  406.  * return TRUE if wait_return not called
  407.  */
  408.     int
  409. emsg(s)
  410.     char_u    *s;
  411. {
  412.     char_u    *Buf;
  413.     int        attr;
  414.     int        other_sourcing_name;
  415.     char    *p;
  416. #ifdef FEAT_EVAL
  417.     int        ignore = FALSE;
  418.     int        severe;
  419. #endif
  420.  
  421.     called_emsg = TRUE;
  422.  
  423.     /*
  424.      * If "emsg_severe" is TRUE: When an error exception is to be thrown, prefer
  425.      * this message over previous messages for the same command.
  426.      */
  427. #ifdef FEAT_EVAL
  428.     severe = emsg_severe;
  429.     emsg_severe = FALSE;
  430. #endif
  431.  
  432.     /*
  433.      * If "emsg_off" is set: no error messages at the moment.
  434.      * If 'debug' is set: do error message anyway, but without side effects.
  435.      * If "emsg_skip" is set: never do error messages.
  436.      */
  437.     if ((emsg_off > 0 && *p_debug == NUL)
  438. #ifdef FEAT_EVAL
  439.         || emsg_skip > 0
  440. #endif
  441.         )
  442.     return TRUE;
  443.  
  444.     if (!emsg_off)
  445.     {
  446. #ifdef FEAT_EVAL
  447.     /*
  448.      * Cause a throw of an error exception if appropriate.  Don't display
  449.      * the error message in this case.  (If no matching catch clause will
  450.      * be found, the message will be displayed later on.)  "ignore" is set
  451.      * when the message should be ignored completely (used for the
  452.      * interrupt message).
  453.      */
  454.     if (cause_errthrow(s, severe, &ignore) == TRUE)
  455.     {
  456.         if (!ignore)
  457.         did_emsg = TRUE;
  458.         return TRUE;
  459.     }
  460.  
  461.     /* set "v:errmsg", also when using ":silent! cmd" */
  462.     set_vim_var_string(VV_ERRMSG, s, -1);
  463. #endif
  464.  
  465.     /*
  466.      * When using ":silent! cmd" ignore error messsages.
  467.      * But do write it to the redirection file.
  468.      */
  469.     if (emsg_silent != 0)
  470.     {
  471.         redir_write(s, -1);
  472.         return TRUE;
  473.     }
  474.  
  475.     /* Reset msg_silent, an error causes messages to be switched back on. */
  476.     msg_silent = 0;
  477.     cmd_silent = FALSE;
  478.  
  479.     if (global_busy)        /* break :global command */
  480.         ++global_busy;
  481.  
  482.     if (p_eb)
  483.         beep_flush();        /* also includes flush_buffers() */
  484.     else
  485.         flush_buffers(FALSE);    /* flush internal buffers */
  486.     did_emsg = TRUE;        /* flag for DoOneCmd() */
  487.  
  488. #ifdef VIMBUDDY
  489.     if (sourcing_name == NULL)
  490.     {
  491.         VimBuddyText(s, 2);
  492.         return TRUE;
  493.     }
  494. #endif
  495.     }
  496.  
  497.     emsg_on_display = TRUE;    /* remember there is an error message */
  498.     ++msg_scroll;        /* don't overwrite a previous message */
  499.     attr = hl_attr(HLF_E);    /* set highlight mode for error messages */
  500.     if (msg_scrolled)
  501.     need_wait_return = TRUE;    /* needed in case emsg() is called after
  502.                      * wait_return has reset need_wait_return
  503.                      * and a redraw is expected because
  504.                      * msg_scrolled is non-zero */
  505.  
  506. /*
  507.  * First output name and line number of source of error message
  508.  */
  509.     if (sourcing_name != NULL)
  510.     {
  511.     if (last_sourcing_name != NULL)
  512.         other_sourcing_name = STRCMP(sourcing_name, last_sourcing_name);
  513.     else
  514.         other_sourcing_name = TRUE;
  515.     }
  516.     else
  517.     other_sourcing_name = FALSE;
  518.  
  519.     p = _("Error detected while processing %s:");
  520.     if (sourcing_name != NULL
  521.         && (other_sourcing_name || sourcing_lnum != last_sourcing_lnum)
  522.         && (Buf = alloc((unsigned)(STRLEN(sourcing_name)
  523.                                + STRLEN(p)))) != NULL)
  524.     {
  525.     ++no_wait_return;
  526.     if (other_sourcing_name)
  527.     {
  528.         sprintf((char *)Buf, p, sourcing_name);
  529.         msg_attr(Buf, attr);
  530.     }
  531.         /* lnum is 0 when executing a command from the command line
  532.          * argument, we don't want a line number then */
  533.     if (sourcing_lnum != 0)
  534.     {
  535.         sprintf((char *)Buf, _("line %4ld:"), (long)sourcing_lnum);
  536.         msg_attr(Buf, hl_attr(HLF_N));
  537.     }
  538.     --no_wait_return;
  539.     last_sourcing_lnum = sourcing_lnum;  /* only once for each line */
  540.     vim_free(Buf);
  541.     }
  542.  
  543.     /* remember the last sourcing name printed, also when it's empty */
  544.     if (sourcing_name == NULL || other_sourcing_name)
  545.     {
  546.     vim_free(last_sourcing_name);
  547.     if (sourcing_name == NULL)
  548.         last_sourcing_name = NULL;
  549.     else
  550.         last_sourcing_name = vim_strsave(sourcing_name);
  551.     }
  552.     msg_nowait = FALSE;            /* wait for this msg */
  553.  
  554.     return msg_attr(s, attr);
  555. }
  556.  
  557.     int
  558. emsg2(s, a1)
  559.     char_u *s, *a1;
  560. {
  561.     if ((emsg_off > 0 && *p_debug == NUL)
  562. #ifdef FEAT_EVAL
  563.         || emsg_skip > 0
  564. #endif
  565.         )
  566.     return TRUE;        /* no error messages at the moment */
  567.  
  568.     /* Check for NULL strings (just in case) */
  569.     if (a1 == NULL)
  570.     a1 = (char_u *)"[NULL]";
  571.     /* Check for very long strings (can happen with ":help ^A<CR>").
  572.      * Careful, the argument could actually be a long. */
  573.     if (STRLEN(s) + (strstr((char *)s, "%s") != NULL ? STRLEN(a1) : 20)
  574.                                 >= (size_t)IOSIZE)
  575.     a1 = (char_u *)_("[string too long]");
  576.     sprintf((char *)IObuff, (char *)s, (char *)a1);
  577.     return emsg(IObuff);
  578. }
  579.  
  580.     int
  581. emsgn(s, n)
  582.     char_u    *s;
  583.     long    n;
  584. {
  585.     if ((emsg_off > 0 && *p_debug == NUL)
  586. #ifdef FEAT_EVAL
  587.         || emsg_skip > 0
  588. #endif
  589.         )
  590.     return TRUE;        /* no error messages at the moment */
  591.     sprintf((char *)IObuff, (char *)s, n);
  592.     return emsg(IObuff);
  593. }
  594.  
  595. /*
  596.  * Like msg(), but truncate to a single line if p_shm contains 't', or when
  597.  * "force" is TRUE.  This truncates in another way as for normal messages.
  598.  * Careful: The string may be changed by msg_may_trunc()!
  599.  * Returns a pointer to the printed message, if wait_return() not called.
  600.  */
  601.     char_u *
  602. msg_trunc_attr(s, force, attr)
  603.     char_u    *s;
  604.     int        force;
  605.     int        attr;
  606. {
  607.     int        n;
  608.  
  609.     /* Add message to history before truncating */
  610.     add_msg_hist(s, -1, attr);
  611.  
  612.     s = msg_may_trunc(force, s);
  613.  
  614.     msg_hist_off = TRUE;
  615.     n = msg_attr(s, attr);
  616.     msg_hist_off = FALSE;
  617.  
  618.     if (n)
  619.     return s;
  620.     return NULL;
  621. }
  622.  
  623. /*
  624.  * Check if message "s" should be truncated at the start (for filenames).
  625.  * Return a pointer to where the truncated message starts.
  626.  * Note: May change the message by replacing a character with '<'.
  627.  */
  628.     char_u *
  629. msg_may_trunc(force, s)
  630.     int        force;
  631.     char_u    *s;
  632. {
  633.     int        n;
  634.     int        room;
  635.  
  636.     room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
  637.     if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
  638.         && (n = (int)STRLEN(s) - room) > 0)
  639.     {
  640. #ifdef FEAT_MBYTE
  641.     if (has_mbyte)
  642.     {
  643.         int    size = vim_strsize(s);
  644.  
  645.         for (n = 0; size >= room; )
  646.         {
  647.         size -= (*mb_ptr2cells)(s + n);
  648.         n += (*mb_ptr2len_check)(s + n);
  649.         }
  650.         --n;
  651.     }
  652. #endif
  653.     s += n;
  654.     *s = '<';
  655.     }
  656.     return s;
  657. }
  658.  
  659.     static void
  660. add_msg_hist(s, len, attr)
  661.     char_u    *s;
  662.     int        len;        /* -1 for undetermined length */
  663.     int        attr;
  664. {
  665.     struct msg_hist *p;
  666.  
  667.     if (msg_hist_off || msg_silent != 0)
  668.     return;
  669.  
  670.     /* Don't let the message history get too big */
  671.     while (msg_hist_len > 20)
  672.     {
  673.     p = first_msg_hist;
  674.     first_msg_hist = p->next;
  675.     vim_free(p->msg);
  676.     vim_free(p);
  677.     --msg_hist_len;
  678.     }
  679.     /* allocate an entry and add the message at the end of the history */
  680.     p = (struct msg_hist *)alloc((int)sizeof(struct msg_hist));
  681.     if (p != NULL)
  682.     {
  683.     if (len < 0)
  684.         len = (int)STRLEN(s);
  685.     /* remove leading and trailing newlines */
  686.     while (len > 0 && *s == '\n')
  687.     {
  688.         ++s;
  689.         --len;
  690.     }
  691.     while (len > 0 && s[len - 1] == '\n')
  692.         --len;
  693.     p->msg = vim_strnsave(s, len);
  694.     p->next = NULL;
  695.     p->attr = attr;
  696.     if (last_msg_hist != NULL)
  697.         last_msg_hist->next = p;
  698.     last_msg_hist = p;
  699.     if (first_msg_hist == NULL)
  700.         first_msg_hist = last_msg_hist;
  701.     ++msg_hist_len;
  702.     }
  703. }
  704.  
  705. /*
  706.  * ":messages" command.
  707.  */
  708. /*ARGSUSED*/
  709.     void
  710. ex_messages(eap)
  711.     exarg_T    *eap;
  712. {
  713.     struct msg_hist *p;
  714.     char_u        *s;
  715.  
  716.     msg_hist_off = TRUE;
  717.  
  718.     s = mch_getenv((char_u *)"LANG");
  719.     if (s != NULL && *s != NUL)
  720.     msg_attr((char_u *)
  721.         _("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
  722.         hl_attr(HLF_T));
  723.  
  724.     for (p = first_msg_hist; p != NULL; p = p->next)
  725.     if (p->msg != NULL)
  726.         msg_attr(p->msg, p->attr);
  727.  
  728.     msg_hist_off = FALSE;
  729. }
  730.  
  731. #if defined(FEAT_CON_DIALOG) || defined(PROTO)
  732. static void msg_end_prompt __ARGS((void));
  733.  
  734. /*
  735.  * Call this after prompting the user.  This will avoid a hit-return message
  736.  * and a delay.
  737.  */
  738.     static void
  739. msg_end_prompt()
  740. {
  741.     need_wait_return = FALSE;
  742.     emsg_on_display = FALSE;
  743.     cmdline_row = msg_row;
  744.     msg_col = 0;
  745.     msg_clr_eos();
  746. }
  747. #endif
  748.  
  749. /*
  750.  * wait for the user to hit a key (normally a return)
  751.  * if 'redraw' is TRUE, clear and redraw the screen
  752.  * if 'redraw' is FALSE, just redraw the screen
  753.  * if 'redraw' is -1, don't redraw at all
  754.  */
  755.     void
  756. wait_return(redraw)
  757.     int        redraw;
  758. {
  759.     int        c;
  760.     int        oldState;
  761.     int        tmpState;
  762. #ifndef ORG_HITRETURN
  763.     int        had_got_int;
  764. #endif
  765.  
  766.     if (redraw == TRUE)
  767.     must_redraw = CLEAR;
  768.  
  769.     /* If using ":silent cmd", don't wait for a return.  Also don't set
  770.      * need_wait_return to do it later. */
  771.     if (msg_silent != 0)
  772.     return;
  773.  
  774. /*
  775.  * With the global command (and some others) we only need one return at the
  776.  * end. Adjust cmdline_row to avoid the next message overwriting the last one.
  777.  * When inside vgetc(), we can't wait for a typed character at all.
  778.  */
  779.     if (vgetc_busy)
  780.     return;
  781.     if (no_wait_return)
  782.     {
  783.     need_wait_return = TRUE;
  784.     if (!exmode_active)
  785.         cmdline_row = msg_row;
  786.     return;
  787.     }
  788.  
  789.     redir_off = TRUE;            /* don't redirect this message */
  790.     oldState = State;
  791.     if (quit_more)
  792.     {
  793.     c = CR;                /* just pretend CR was hit */
  794.     quit_more = FALSE;
  795.     got_int = FALSE;
  796.     }
  797.     else if (exmode_active)
  798.     {
  799.     MSG_PUTS(" ");      /* make sure the cursor is on the right line */
  800.     c = CR;                /* no need for a return in ex mode */
  801.     got_int = FALSE;
  802.     }
  803.     else
  804.     {
  805.     State = HITRETURN;
  806. #ifdef FEAT_MOUSE
  807.     setmouse();
  808. #endif
  809. #ifdef USE_ON_FLY_SCROLL
  810.     dont_scroll = TRUE;        /* disallow scrolling here */
  811. #endif
  812.     hit_return_msg();
  813.  
  814. #ifdef ORG_HITRETURN
  815.     do
  816.     {
  817.         c = safe_vgetc();
  818.     } while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
  819.     if (c == ':')            /* this can vi too (but not always!) */
  820.         stuffcharReadbuff(c);
  821. #else
  822.     do
  823.     {
  824.         /* Remember "got_int", if it is set vgetc() probably returns a
  825.          * CTRL-C, but we need to loop then. */
  826.         had_got_int = got_int;
  827.         c = safe_vgetc();
  828.         if (!global_busy)
  829.         got_int = FALSE;
  830. #ifdef FEAT_CLIPBOARD
  831.         /* Strange way to allow copying (yanking) a modeless selection at
  832.          * the hit-enter prompt.  Use CTRL-Y, because the same is used in
  833.          * Cmdline-mode and it's harmless when there is no selection. */
  834.         if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
  835.         {
  836.         clip_copy_modeless_selection(TRUE);
  837.         c = K_IGNORE;
  838.         }
  839. #endif
  840.     } while ((had_got_int && c == Ctrl_C)
  841.                 || c == K_IGNORE
  842. #ifdef FEAT_GUI
  843.                 || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
  844. #endif
  845. #ifdef FEAT_MOUSE
  846.                 || c == K_LEFTDRAG   || c == K_LEFTRELEASE
  847.                 || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
  848.                 || c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
  849.                 || c == K_MOUSEDOWN  || c == K_MOUSEUP
  850.                 || (!mouse_has(MOUSE_RETURN)
  851.                     && mouse_row != Rows - 1
  852.                     && (c == K_LEFTMOUSE
  853.                     || c == K_MIDDLEMOUSE
  854.                     || c == K_RIGHTMOUSE
  855.                     || c == K_X1MOUSE
  856.                     || c == K_X2MOUSE))
  857. #endif
  858.                 );
  859.     ui_breakcheck();
  860. #ifdef FEAT_MOUSE
  861.     /*
  862.      * Avoid that the mouse-up event causes visual mode to start.
  863.      */
  864.     if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
  865.                       || c == K_X1MOUSE || c == K_X2MOUSE)
  866.         (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
  867.     else
  868. #endif
  869.         if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C)
  870.     {
  871.         stuffcharReadbuff(c);
  872.         do_redraw = TRUE;        /* need a redraw even though there is
  873.                        something in the stuff buffer */
  874.     }
  875. #endif
  876.     }
  877.     redir_off = FALSE;
  878.  
  879.     /*
  880.      * If the user hits ':', '?' or '/' we get a command line from the next
  881.      * line.
  882.      */
  883.     if (c == ':' || c == '?' || c == '/')
  884.     {
  885.     if (!exmode_active)
  886.         cmdline_row = msg_row;
  887.     skip_redraw = TRUE;        /* skip redraw once */
  888.     do_redraw = FALSE;
  889.     }
  890.  
  891.     /*
  892.      * If the window size changed set_shellsize() will redraw the screen.
  893.      * Otherwise the screen is only redrawn if 'redraw' is set and no ':'
  894.      * typed.
  895.      */
  896.     tmpState = State;
  897.     State = oldState;            /* restore State before set_shellsize */
  898. #ifdef FEAT_MOUSE
  899.     setmouse();
  900. #endif
  901.     msg_check();
  902.  
  903. #if defined(UNIX) || defined(VMS)
  904.     /*
  905.      * When switching screens, we need to output an extra newline on exit.
  906.      */
  907.     if (swapping_screen() && !termcap_active)
  908.     newline_on_exit = TRUE;
  909. #endif
  910.  
  911.     need_wait_return = FALSE;
  912.     did_wait_return = TRUE;
  913.     emsg_on_display = FALSE;    /* can delete error message now */
  914.     lines_left = -1;        /* reset lines_left at next msg_start() */
  915.     reset_last_sourcing();
  916.     if (keep_msg != NULL && vim_strsize(keep_msg) >=
  917.                   (Rows - cmdline_row - 1) * Columns + sc_col)
  918.     {
  919.     vim_free(keep_msg);
  920.     keep_msg = NULL;        /* don't redisplay message, it's too long */
  921.     }
  922.  
  923.     if (tmpState == SETWSIZE)        /* got resize event while in vgetc() */
  924.     {
  925.     starttermcap();            /* start termcap before redrawing */
  926.     shell_resized();
  927.     }
  928.     else if (!skip_redraw
  929.         && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1)))
  930.     {
  931.     starttermcap();            /* start termcap before redrawing */
  932.     redraw_later(VALID);
  933.     }
  934. }
  935.  
  936. /*
  937.  * Write the hit-return prompt.
  938.  */
  939.     static void
  940. hit_return_msg()
  941. {
  942.     if (msg_didout)            /* start on a new line */
  943.     msg_putchar('\n');
  944.     if (got_int)
  945.     MSG_PUTS(_("Interrupt: "));
  946.  
  947. #ifdef ORG_HITRETURN
  948.     MSG_PUTS_ATTR(_("Hit ENTER to continue"), hl_attr(HLF_R));
  949. #else
  950.     MSG_PUTS_ATTR(_("Hit ENTER or type command to continue"), hl_attr(HLF_R));
  951. #endif
  952.     if (!msg_use_printf())
  953.     msg_clr_eos();
  954. }
  955.  
  956. /*
  957.  * Set "keep_msg" to "s".  Free the old value and check for NULL pointer.
  958.  */
  959.     void
  960. set_keep_msg(s)
  961.     char_u    *s;
  962. {
  963.     vim_free(keep_msg);
  964.     if (s != NULL && msg_silent == 0)
  965.     keep_msg = vim_strsave(s);
  966.     else
  967.     keep_msg = NULL;
  968. }
  969.  
  970. /*
  971.  * Prepare for outputting characters in the command line.
  972.  */
  973.     void
  974. msg_start()
  975. {
  976.     int        did_return = FALSE;
  977.  
  978.     vim_free(keep_msg);
  979.     keep_msg = NULL;            /* don't display old message now */
  980.     if (!msg_scroll && full_screen)    /* overwrite last message */
  981.     {
  982.     msg_row = cmdline_row;
  983.     msg_col =
  984. #ifdef FEAT_RIGHTLEFT
  985.         cmdmsg_rl ? Columns - 1 :
  986. #endif
  987.         0;
  988.     }
  989.     else if (msg_didout)            /* start message on next line */
  990.     {
  991.     msg_putchar('\n');
  992.     did_return = TRUE;
  993.     if (exmode_active != EXMODE_NORMAL)
  994.         cmdline_row = msg_row;
  995.     }
  996.     if (!msg_didany || lines_left < 0)
  997.     msg_starthere();
  998.     msg_didout = FALSE;                /* no output on current line yet */
  999.     cursor_off();
  1000.  
  1001.     /* when redirecting, may need to start a new line. */
  1002.     if (!did_return)
  1003.     redir_write((char_u *)"\n", -1);
  1004. }
  1005.  
  1006. /*
  1007.  * Note that the current msg position is where messages start.
  1008.  */
  1009.     void
  1010. msg_starthere()
  1011. {
  1012.     lines_left = cmdline_row;
  1013.     msg_didany = FALSE;
  1014. }
  1015.  
  1016.     void
  1017. msg_putchar(c)
  1018.     int        c;
  1019. {
  1020.     msg_putchar_attr(c, 0);
  1021. }
  1022.  
  1023.     void
  1024. msg_putchar_attr(c, attr)
  1025.     int        c;
  1026.     int        attr;
  1027. {
  1028. #ifdef FEAT_MBYTE
  1029.     char_u    buf[MB_MAXBYTES + 1];
  1030. #else
  1031.     char_u    buf[4];
  1032. #endif
  1033.  
  1034.     if (IS_SPECIAL(c))
  1035.     {
  1036.     buf[0] = K_SPECIAL;
  1037.     buf[1] = K_SECOND(c);
  1038.     buf[2] = K_THIRD(c);
  1039.     buf[3] = NUL;
  1040.     }
  1041.     else
  1042.     {
  1043. #ifdef FEAT_MBYTE
  1044.     buf[(*mb_char2bytes)(c, buf)] = NUL;
  1045. #else
  1046.     buf[0] = c;
  1047.     buf[1] = NUL;
  1048. #endif
  1049.     }
  1050.     msg_puts_attr(buf, attr);
  1051. }
  1052.  
  1053.     void
  1054. msg_outnum(n)
  1055.     long    n;
  1056. {
  1057.     char_u    buf[20];
  1058.  
  1059.     sprintf((char *)buf, "%ld", n);
  1060.     msg_puts(buf);
  1061. }
  1062.  
  1063.     void
  1064. msg_home_replace(fname)
  1065.     char_u    *fname;
  1066. {
  1067.     msg_home_replace_attr(fname, 0);
  1068. }
  1069.  
  1070. #if defined(FEAT_FIND_ID) || defined(PROTO)
  1071.     void
  1072. msg_home_replace_hl(fname)
  1073.     char_u    *fname;
  1074. {
  1075.     msg_home_replace_attr(fname, hl_attr(HLF_D));
  1076. }
  1077. #endif
  1078.  
  1079.     static void
  1080. msg_home_replace_attr(fname, attr)
  1081.     char_u  *fname;
  1082.     int        attr;
  1083. {
  1084.     char_u    *name;
  1085.  
  1086.     name = home_replace_save(NULL, fname);
  1087.     if (name != NULL)
  1088.     msg_outtrans_attr(name, attr);
  1089.     vim_free(name);
  1090. }
  1091.  
  1092. /*
  1093.  * Output 'len' characters in 'str' (including NULs) with translation
  1094.  * if 'len' is -1, output upto a NUL character.
  1095.  * Use attributes 'attr'.
  1096.  * Return the number of characters it takes on the screen.
  1097.  */
  1098.     int
  1099. msg_outtrans(str)
  1100.     char_u        *str;
  1101. {
  1102.     return msg_outtrans_attr(str, 0);
  1103. }
  1104.  
  1105.     int
  1106. msg_outtrans_attr(str, attr)
  1107.     char_u    *str;
  1108.     int        attr;
  1109. {
  1110.     return msg_outtrans_len_attr(str, (int)STRLEN(str), attr);
  1111. }
  1112.  
  1113.     int
  1114. msg_outtrans_len(str, len)
  1115.     char_u    *str;
  1116.     int        len;
  1117. {
  1118.     return msg_outtrans_len_attr(str, len, 0);
  1119. }
  1120.  
  1121. /*
  1122.  * Output one character at "p".  Return pointer to the next character.
  1123.  * Handles multi-byte characters.
  1124.  */
  1125.     char_u *
  1126. msg_outtrans_one(p, attr)
  1127.     char_u    *p;
  1128.     int        attr;
  1129. {
  1130. #ifdef FEAT_MBYTE
  1131.     int        l;
  1132.  
  1133.     if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
  1134.     {
  1135.     msg_outtrans_len_attr(p, l, attr);
  1136.     return p + l;
  1137.     }
  1138. #endif
  1139.     msg_puts_attr(transchar_byte(*p), attr);
  1140.     return p + 1;
  1141. }
  1142.  
  1143.     int
  1144. msg_outtrans_len_attr(msgstr, len, attr)
  1145.     char_u    *msgstr;
  1146.     int        len;
  1147.     int        attr;
  1148. {
  1149.     int        retval = 0;
  1150.     char_u    *str = msgstr;
  1151.     char_u    *plain_start = msgstr;
  1152.     char_u    *s;
  1153. #ifdef FEAT_MBYTE
  1154.     int        mb_l;
  1155.     int        c;
  1156. #endif
  1157.  
  1158.     /* if MSG_HIST flag set, add message to history */
  1159.     if (attr & MSG_HIST)
  1160.     {
  1161.     add_msg_hist(str, len, attr);
  1162.     attr &= ~MSG_HIST;
  1163.     }
  1164.  
  1165. #ifdef FEAT_MBYTE
  1166.     /* If the string starts with a composing character first draw a space on
  1167.      * which the composing char can be drawn. */
  1168.     if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr)))
  1169.     {
  1170.     msg_puts_attr((char_u *)" ", attr);
  1171.     retval += 1;
  1172.     }
  1173. #endif
  1174.  
  1175.     /*
  1176.      * Go over the string.  Special characters are translated and printed.
  1177.      * Normal characters are printed several at a time.
  1178.      */
  1179.     while (--len >= 0)
  1180.     {
  1181. #ifdef FEAT_MBYTE
  1182.     if (enc_utf8)
  1183.         /* Don't include composing chars after the end. */
  1184.         mb_l = utfc_ptr2len_check_len(str, len + 1);
  1185.     else if (has_mbyte)
  1186.         mb_l = (*mb_ptr2len_check)(str);
  1187.     if (has_mbyte && mb_l > 1)
  1188.     {
  1189.         c = (*mb_ptr2char)(str);
  1190.         if (vim_isprintc(c))
  1191.         /* printable multi-byte char: count the cells. */
  1192.         retval += (*mb_ptr2cells)(str);
  1193.         else
  1194.         {
  1195.         /* unprintable multi-byte char: print the printable chars so
  1196.          * far and the translation of the unprintable char. */
  1197.         if (str > plain_start)
  1198.             msg_puts_attr_len(plain_start, (int)(str - plain_start),
  1199.                                     attr);
  1200.         plain_start = str + mb_l;
  1201.         msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr);
  1202.         retval += char2cells(c);
  1203.         }
  1204.         len -= mb_l - 1;
  1205.         str += mb_l;
  1206.     }
  1207.     else
  1208. #endif
  1209.     {
  1210.         s = transchar_byte(*str);
  1211.         if (s[1] != NUL)
  1212.         {
  1213.         /* unprintable char: print the printable chars so far and the
  1214.          * translation of the unprintable char. */
  1215.         if (str > plain_start)
  1216.             msg_puts_attr_len(plain_start, (int)(str - plain_start),
  1217.                                     attr);
  1218.         plain_start = str + 1;
  1219.         msg_puts_attr(s, attr == 0 ? hl_attr(HLF_8) : attr);
  1220.         }
  1221.         retval += ptr2cells(str);
  1222.         ++str;
  1223.     }
  1224.     }
  1225.  
  1226.     if (str > plain_start)
  1227.     /* print the printable chars at the end */
  1228.     msg_puts_attr_len(plain_start, (int)(str - plain_start), attr);
  1229.  
  1230.     return retval;
  1231. }
  1232.  
  1233. #if defined(FEAT_QUICKFIX) || defined(PROTO)
  1234.     void
  1235. msg_make(arg)
  1236.     char_u  *arg;
  1237. {
  1238.     int        i;
  1239.     static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB";
  1240.  
  1241.     arg = skipwhite(arg);
  1242.     for (i = 5; *arg && i >= 0; --i)
  1243.     if (*arg++ != str[i])
  1244.         break;
  1245.     if (i < 0)
  1246.     {
  1247.     msg_putchar('\n');
  1248.     for (i = 0; rs[i]; ++i)
  1249.         msg_putchar(rs[i] - 3);
  1250.     }
  1251. }
  1252. #endif
  1253.  
  1254. /*
  1255.  * Output the string 'str' upto a NUL character.
  1256.  * Return the number of characters it takes on the screen.
  1257.  *
  1258.  * If K_SPECIAL is encountered, then it is taken in conjunction with the
  1259.  * following character and shown as <F1>, <S-Up> etc.  Any other character
  1260.  * which is not printable shown in <> form.
  1261.  * If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>.
  1262.  * If a character is displayed in one of these special ways, is also
  1263.  * highlighted (its highlight name is '8' in the p_hl variable).
  1264.  * Otherwise characters are not highlighted.
  1265.  * This function is used to show mappings, where we want to see how to type
  1266.  * the character/string -- webb
  1267.  */
  1268.     int
  1269. msg_outtrans_special(strstart, from)
  1270.     char_u    *strstart;
  1271.     int        from;    /* TRUE for lhs of a mapping */
  1272. {
  1273.     char_u    *str = strstart;
  1274.     int        retval = 0;
  1275.     char_u    *string;
  1276.     int        attr;
  1277.     int        len;
  1278.  
  1279.     attr = hl_attr(HLF_8);
  1280.     while (*str != NUL)
  1281.     {
  1282.     /* Leading and trailing spaces need to be displayed in <> form. */
  1283.     if ((str == strstart || str[1] == NUL) && *str == ' ')
  1284.     {
  1285.         string = (char_u *)"<Space>";
  1286.         ++str;
  1287.     }
  1288.     else
  1289.         string = str2special(&str, from);
  1290.     len = vim_strsize(string);
  1291.     /* Highlight special keys */
  1292.     msg_puts_attr(string, len > 1
  1293. #ifdef FEAT_MBYTE
  1294.         && (*mb_ptr2len_check)(string) <= 1
  1295. #endif
  1296.         ? attr : 0);
  1297.     retval += len;
  1298.     }
  1299.     return retval;
  1300. }
  1301.  
  1302. /*
  1303.  * Return the printable string for the key codes at "*sp".
  1304.  * Used for translating the lhs or rhs of a mapping to printable chars.
  1305.  * Advances "sp" to the next code.
  1306.  */
  1307.     char_u *
  1308. str2special(sp, from)
  1309.     char_u    **sp;
  1310.     int        from;    /* TRUE for lhs of mapping */
  1311. {
  1312.     int            c;
  1313.     static char_u    buf[7];
  1314.     char_u        *str = *sp;
  1315.     int            modifiers = 0;
  1316.     int            special = FALSE;
  1317.  
  1318. #ifdef FEAT_MBYTE
  1319.     if (has_mbyte)
  1320.     {
  1321.     char_u    *p;
  1322.  
  1323.     /* Try to un-escape a multi-byte character.  Return the un-escaped
  1324.      * string if it is a multi-byte character. */
  1325.     p = mb_unescape(sp);
  1326.     if (p != NULL)
  1327.         return p;
  1328.     }
  1329. #endif
  1330.  
  1331.     c = *str;
  1332.     if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
  1333.     {
  1334.     if (str[1] == KS_MODIFIER)
  1335.     {
  1336.         modifiers = str[2];
  1337.         str += 3;
  1338.         c = *str;
  1339.     }
  1340.     if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
  1341.     {
  1342.         c = TO_SPECIAL(str[1], str[2]);
  1343.         str += 2;
  1344.         if (c == K_ZERO)    /* display <Nul> as ^@ */
  1345.         c = NUL;
  1346.     }
  1347.     if (IS_SPECIAL(c) || modifiers)    /* special key */
  1348.         special = TRUE;
  1349.     }
  1350.     *sp = str + 1;
  1351.  
  1352. #ifdef FEAT_MBYTE
  1353.     /* For multi-byte characters check for an illegal byte. */
  1354.     if (has_mbyte && MB_BYTE2LEN(*str) > (*mb_ptr2len_check)(str))
  1355.     {
  1356.     transchar_nonprint(buf, c);
  1357.     return buf;
  1358.     }
  1359. #endif
  1360.  
  1361.     /* Make unprintable characters in <> form, also <M-Space> and <Tab>.
  1362.      * Use <Space> only for lhs of a mapping. */
  1363.     if (special || char2cells(c) > 1 || (from && c == ' '))
  1364.     return get_special_key_name(c, modifiers);
  1365.     buf[0] = c;
  1366.     buf[1] = NUL;
  1367.     return buf;
  1368. }
  1369.  
  1370. /*
  1371.  * Translate a key sequence into special key names.
  1372.  */
  1373.     void
  1374. str2specialbuf(sp, buf, len)
  1375.     char_u    *sp;
  1376.     char_u    *buf;
  1377.     int        len;
  1378. {
  1379.     char_u    *s;
  1380.  
  1381.     *buf = NUL;
  1382.     while (*sp)
  1383.     {
  1384.     s = str2special(&sp, FALSE);
  1385.     if ((int)(STRLEN(s) + STRLEN(buf)) < len)
  1386.         STRCAT(buf, s);
  1387.     }
  1388. }
  1389.  
  1390. /*
  1391.  * print line for :print or :list command
  1392.  */
  1393.     void
  1394. msg_prt_line(s)
  1395.     char_u    *s;
  1396. {
  1397.     int        c;
  1398.     int        col = 0;
  1399.     int        n_extra = 0;
  1400.     int        c_extra = 0;
  1401.     char_u    *p_extra = NULL;        /* init to make SASC shut up */
  1402.     int        n;
  1403.     int        attr= 0;
  1404.     char_u    *trail = NULL;
  1405. #ifdef FEAT_MBYTE
  1406.     int        l;
  1407.     char_u    buf[MB_MAXBYTES + 1];
  1408. #endif
  1409.  
  1410.     /* find start of trailing whitespace */
  1411.     if (curwin->w_p_list && lcs_trail)
  1412.     {
  1413.     trail = s + STRLEN(s);
  1414.     while (trail > s && vim_iswhite(trail[-1]))
  1415.         --trail;
  1416.     }
  1417.  
  1418.     /* output a space for an empty line, otherwise the line will be
  1419.      * overwritten */
  1420.     if (*s == NUL && !curwin->w_p_list)
  1421.     msg_putchar(' ');
  1422.  
  1423.     for (;;)
  1424.     {
  1425.     if (n_extra)
  1426.     {
  1427.         --n_extra;
  1428.         if (c_extra)
  1429.         c = c_extra;
  1430.         else
  1431.         c = *p_extra++;
  1432.     }
  1433. #ifdef FEAT_MBYTE
  1434.     else if (has_mbyte && (l = (*mb_ptr2len_check)(s)) > 1)
  1435.     {
  1436.         col += (*mb_ptr2cells)(s);
  1437.         mch_memmove(buf, s, (size_t)l);
  1438.         buf[l] = NUL;
  1439.         msg_puts_attr(buf, attr);
  1440.         s += l;
  1441.         continue;
  1442.     }
  1443. #endif
  1444.     else
  1445.     {
  1446.         attr = 0;
  1447.         c = *s++;
  1448.         if (c == TAB && (!curwin->w_p_list || lcs_tab1))
  1449.         {
  1450.         /* tab amount depends on current column */
  1451.         n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
  1452.         if (!curwin->w_p_list)
  1453.         {
  1454.             c = ' ';
  1455.             c_extra = ' ';
  1456.         }
  1457.         else
  1458.         {
  1459.             c = lcs_tab1;
  1460.             c_extra = lcs_tab2;
  1461.             attr = hl_attr(HLF_8);
  1462.         }
  1463.         }
  1464.         else if (c == NUL && curwin->w_p_list && lcs_eol)
  1465.         {
  1466.         p_extra = (char_u *)"";
  1467.         c_extra = NUL;
  1468.         n_extra = 1;
  1469.         c = lcs_eol;
  1470.         attr = hl_attr(HLF_AT);
  1471.         --s;
  1472.         }
  1473.         else if (c != NUL && (n = byte2cells(c)) > 1)
  1474.         {
  1475.         n_extra = n - 1;
  1476.         p_extra = transchar_byte(c);
  1477.         c_extra = NUL;
  1478.         c = *p_extra++;
  1479.         }
  1480.         else if (c == ' ' && trail != NULL && s > trail)
  1481.         {
  1482.         c = lcs_trail;
  1483.         attr = hl_attr(HLF_8);
  1484.         }
  1485.     }
  1486.  
  1487.     if (c == NUL)
  1488.         break;
  1489.  
  1490.     msg_putchar_attr(c, attr);
  1491.     col++;
  1492.     }
  1493.     msg_clr_eos();
  1494. }
  1495.  
  1496. #ifdef FEAT_MBYTE
  1497. /*
  1498.  * Use screen_puts() to output one multi-byte character.
  1499.  * Return the pointer "s" advanced to the next character.
  1500.  */
  1501.     static char_u *
  1502. screen_puts_mbyte(s, l, attr)
  1503.     char_u    *s;
  1504.     int        l;
  1505.     int        attr;
  1506. {
  1507.     int        cw;
  1508.  
  1509.     msg_didout = TRUE;        /* remember that line is not empty */
  1510.     cw = (*mb_ptr2cells)(s);
  1511.     if (cw > 1 && (
  1512. #ifdef FEAT_RIGHTLEFT
  1513.         cmdmsg_rl ? msg_col <= 1 :
  1514. #endif
  1515.         msg_col == Columns - 1))
  1516.     {
  1517.     /* Doesn't fit, print a highlighted '>' to fill it up. */
  1518.     msg_screen_putchar('>', hl_attr(HLF_AT));
  1519.     return s;
  1520.     }
  1521.  
  1522.     screen_puts_len(s, l, msg_row, msg_col, attr);
  1523. #ifdef FEAT_RIGHTLEFT
  1524.     if (cmdmsg_rl)
  1525.     {
  1526.     msg_col -= cw;
  1527.     if (msg_col == 0)
  1528.     {
  1529.         msg_col = Columns;
  1530.         ++msg_row;
  1531.     }
  1532.     }
  1533.     else
  1534. #endif
  1535.     {
  1536.     msg_col += cw;
  1537.     if (msg_col >= Columns)
  1538.     {
  1539.         msg_col = 0;
  1540.         ++msg_row;
  1541.     }
  1542.     }
  1543.     return s + l;
  1544. }
  1545. #endif
  1546.  
  1547. /*
  1548.  * Output a string to the screen at position msg_row, msg_col.
  1549.  * Update msg_row and msg_col for the next message.
  1550.  */
  1551.     void
  1552. msg_puts(s)
  1553.     char_u    *s;
  1554. {
  1555.     msg_puts_attr(s, 0);
  1556. }
  1557.  
  1558.     void
  1559. msg_puts_title(s)
  1560.     char_u    *s;
  1561. {
  1562.     msg_puts_attr(s, hl_attr(HLF_T));
  1563. }
  1564.  
  1565. #if defined(FEAT_CSCOPE) || defined(PROTO)
  1566. /*
  1567.  * if printing a string will exceed the screen width, print "..." in the
  1568.  * middle.
  1569.  */
  1570.     void
  1571. msg_puts_long(longstr)
  1572.     char_u    *longstr;
  1573. {
  1574.     msg_puts_long_len_attr(longstr, (int)strlen((char *)longstr), 0);
  1575. }
  1576. #endif
  1577.  
  1578. /*
  1579.  * Show a message in such a way that it always fits in the line.  Cut out a
  1580.  * part in the middle and replace it with "..." when necessary.
  1581.  * Does not handle multi-byte characters!
  1582.  */
  1583.     void
  1584. msg_puts_long_attr(longstr, attr)
  1585.     char_u    *longstr;
  1586.     int        attr;
  1587. {
  1588.     msg_puts_long_len_attr(longstr, (int)strlen((char *)longstr), attr);
  1589. }
  1590.  
  1591.     void
  1592. msg_puts_long_len_attr(longstr, len, attr)
  1593.     char_u    *longstr;
  1594.     int        len;
  1595.     int        attr;
  1596. {
  1597.     int        slen = len;
  1598.     int        room;
  1599.  
  1600.     room = Columns - msg_col;
  1601.     if (len > room && room >= 20)
  1602.     {
  1603.     slen = (room - 3) / 2;
  1604.     msg_outtrans_len_attr(longstr, slen, attr);
  1605.     msg_puts_attr((char_u *)"...", hl_attr(HLF_8));
  1606.     }
  1607.     msg_outtrans_len_attr(longstr + len - slen, slen, attr);
  1608. }
  1609.  
  1610. /*
  1611.  * Basic function for writing a message with highlight attributes.
  1612.  */
  1613.     void
  1614. msg_puts_attr(s, attr)
  1615.     char_u    *s;
  1616.     int        attr;
  1617. {
  1618.     msg_puts_attr_len(s, -1, attr);
  1619. }
  1620.  
  1621. /*
  1622.  * Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
  1623.  * When "maxlen" is -1 there is no maximum length.
  1624.  * When "maxlen" is >= 0 the message is not put in the history.
  1625.  */
  1626.     static void
  1627. msg_puts_attr_len(str, maxlen, attr)
  1628.     char_u    *str;
  1629.     int        maxlen;
  1630.     int        attr;
  1631. {
  1632.     int        oldState;
  1633.     char_u    *s = str;
  1634.     char_u    *p;
  1635.     char_u    buf[4];
  1636.     char_u    *t_s = str;    /* string from "t_s" to "s" is still todo */
  1637.     int        t_col = 0;    /* screen cells todo, 0 when "t_s" not used */
  1638. #ifdef FEAT_MBYTE
  1639.     int        l;
  1640.     int        cw;
  1641. #endif
  1642.     int        c;
  1643.  
  1644.     /*
  1645.      * If redirection is on, also write to the redirection file.
  1646.      */
  1647.     redir_write(s, maxlen);
  1648.  
  1649.     /*
  1650.      * Don't print anything when using ":silent cmd".
  1651.      */
  1652.     if (msg_silent != 0)
  1653.     return;
  1654.  
  1655.     /* if MSG_HIST flag set, add message to history */
  1656.     if ((attr & MSG_HIST) && maxlen < 0)
  1657.     {
  1658.     add_msg_hist(s, -1, attr);
  1659.     attr &= ~MSG_HIST;
  1660.     }
  1661.  
  1662.     /*
  1663.      * When writing something to the screen after it has scrolled, requires a
  1664.      * wait-return prompt later.  Needed when scrolling, resetting
  1665.      * need_wait_return after some prompt, and then outputting something
  1666.      * without scrolling
  1667.      */
  1668.     if (msg_scrolled && !msg_scrolled_ign)
  1669.     need_wait_return = TRUE;
  1670.     msg_didany = TRUE;        /* remember that something was outputted */
  1671.  
  1672.     /*
  1673.      * If there is no valid screen, use fprintf so we can see error messages.
  1674.      * If termcap is not active, we may be writing in an alternate console
  1675.      * window, cursor positioning may not work correctly (window size may be
  1676.      * different, e.g. for Win32 console) or we just don't know where the
  1677.      * cursor is.
  1678.      */
  1679.     if (msg_use_printf())
  1680.     {
  1681. #ifdef WIN3264
  1682.     if (!silent_mode)
  1683.         mch_settmode(TMODE_COOK);    /* handle '\r' and '\n' correctly */
  1684. #endif
  1685.     while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
  1686.     {
  1687.         if (!silent_mode)
  1688.         {
  1689.         p = &buf[0];
  1690.         /* NL --> CR NL translation (for Unix, not for "--version") */
  1691.         /* NL --> CR translation (for Mac) */
  1692.         if (*s == '\n' && !info_message)
  1693.             *p++ = '\r';
  1694. #if defined(USE_CR) && !defined(MACOS_X_UNIX)
  1695.         else
  1696. #endif
  1697.             *p++ = *s;
  1698.         *p = '\0';
  1699.         if (info_message)    /* informative message, not an error */
  1700.             mch_msg((char *)buf);
  1701.         else
  1702.             mch_errmsg((char *)buf);
  1703.         }
  1704.  
  1705.         /* primitive way to compute the current column */
  1706. #ifdef FEAT_RIGHTLEFT
  1707.         if (cmdmsg_rl)
  1708.         {
  1709.         if (*s == '\r' || *s == '\n')
  1710.             msg_col = Columns - 1;
  1711.         else
  1712.             --msg_col;
  1713.         }
  1714.         else
  1715. #endif
  1716.         {
  1717.         if (*s == '\r' || *s == '\n')
  1718.             msg_col = 0;
  1719.         else
  1720.             ++msg_col;
  1721.         }
  1722.         ++s;
  1723.     }
  1724.     msg_didout = TRUE;        /* assume that line is not empty */
  1725.  
  1726. #ifdef WIN3264
  1727.     if (!silent_mode)
  1728.         mch_settmode(TMODE_RAW);
  1729. #endif
  1730.     return;
  1731.     }
  1732.  
  1733.     did_wait_return = FALSE;
  1734.     while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
  1735.     {
  1736.     /*
  1737.      * The screen is scrolled up when:
  1738.      * - When outputting a newline in the last row
  1739.      * - when outputting a character in the last column of the last row
  1740.      *   (some terminals scroll automatically, some don't. To avoid
  1741.      *   problems we scroll ourselves)
  1742.      */
  1743.     if (msg_row >= Rows - 1
  1744.         && (*s == '\n'
  1745.             || (
  1746. #ifdef FEAT_RIGHTLEFT
  1747.             cmdmsg_rl
  1748.             ? (
  1749.             msg_col <= 1
  1750.             || (*s == TAB && msg_col <= 7)
  1751. # ifdef FEAT_MBYTE
  1752.             || (has_mbyte && (*mb_ptr2cells)(s) > 1 && msg_col <= 2)
  1753. # endif
  1754.               )
  1755.             :
  1756. #endif
  1757.               (msg_col + t_col >= Columns - 1
  1758.                || (*s == TAB && msg_col + t_col >= ((Columns - 1) & ~7))
  1759. # ifdef FEAT_MBYTE
  1760.                || (has_mbyte && (*mb_ptr2cells)(s) > 1
  1761.                         && msg_col + t_col >= Columns - 2)
  1762. # endif
  1763.               ))))
  1764.     {
  1765.         if (t_col > 0)
  1766.         {
  1767.         /* output postponed text */
  1768.         t_puts(t_col, t_s, s, attr);
  1769.         t_col = 0;
  1770.         }
  1771.  
  1772.         /* When no more prompt an no more room, truncate here */
  1773.         if (msg_no_more && lines_left == 0)
  1774.         break;
  1775. #ifdef FEAT_GUI
  1776.         /* Remove the cursor before scrolling, ScreenLines[] is going to
  1777.          * become invalid. */
  1778.         if (gui.in_use)
  1779.         gui_undraw_cursor();
  1780. #endif
  1781.         /* scrolling up always works */
  1782.         screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL);
  1783.  
  1784.         if (!can_clear((char_u *)" "))
  1785.         {
  1786.         /* Scrolling up doesn't result in the right background.  Set
  1787.          * the background here.  It's not efficient, but avoids that
  1788.          * we have to do it all over the code. */
  1789.         screen_fill((int)Rows - 1, (int)Rows, 0,
  1790.                            (int)Columns, ' ', ' ', 0);
  1791.  
  1792.         /* Also clear the last char of the last but one line if it was
  1793.          * not cleared before to avoid a scroll-up. */
  1794.         if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1]
  1795.                                    == (sattr_T)-1)
  1796.             screen_fill((int)Rows - 2, (int)Rows - 1,
  1797.                  (int)Columns - 1, (int)Columns, ' ', ' ', 0);
  1798.         }
  1799.  
  1800.         msg_row = Rows - 2;
  1801.         if (msg_col >= Columns)    /* can happen after screen resize */
  1802.         msg_col = Columns - 1;
  1803.  
  1804.         ++msg_scrolled;
  1805.         need_wait_return = TRUE;    /* may need wait_return in main() */
  1806.         if (must_redraw < VALID)
  1807.         must_redraw = VALID;
  1808.         redraw_cmdline = TRUE;
  1809.         if (cmdline_row > 0 && !exmode_active)
  1810.         --cmdline_row;
  1811.  
  1812.         /*
  1813.          * if screen is completely filled wait for a character
  1814.          */
  1815.         if (p_more && --lines_left == 0 && State != HITRETURN
  1816.                         && !msg_no_more && !exmode_active)
  1817.         {
  1818.         oldState = State;
  1819.         State = ASKMORE;
  1820. #ifdef FEAT_MOUSE
  1821.         setmouse();
  1822. #endif
  1823.         msg_moremsg(FALSE);
  1824.         for (;;)
  1825.         {
  1826.             /*
  1827.              * Get a typed character directly from the user.
  1828.              */
  1829.             c = get_keystroke();
  1830.  
  1831. #if defined(FEAT_MENU) && defined(FEAT_GUI)
  1832.             if (c == K_MENU)
  1833.             {
  1834.             int idx = get_menu_index(current_menu, ASKMORE);
  1835.  
  1836.             /* Used a menu.  If it starts with CTRL-Y, it must
  1837.              * be a "Copy" for the clipboard.  Otherwise
  1838.              * assume that we end */
  1839.             if (idx == MENU_INDEX_INVALID)
  1840.                 continue;
  1841.             c = *current_menu->strings[idx];
  1842.             if (c != NUL && current_menu->strings[idx][1] != NUL)
  1843.                 ins_typebuf(current_menu->strings[idx] + 1,
  1844.                     current_menu->noremap[idx], 0, TRUE,
  1845.                     current_menu->silent[idx]);
  1846.             }
  1847. #endif
  1848.  
  1849.             switch (c)
  1850.             {
  1851.             case BS:
  1852.             case 'k':
  1853.             case K_UP:
  1854.             if (!more_back_used)
  1855.             {
  1856.                 msg_moremsg(TRUE);
  1857.                 continue;
  1858.             }
  1859.             more_back = 1;
  1860.             lines_left = 1;
  1861.             break;
  1862.             case CR:        /* one extra line */
  1863.             case NL:
  1864.             case 'j':
  1865.             case K_DOWN:
  1866.             lines_left = 1;
  1867.             break;
  1868.             case ':':        /* start new command line */
  1869. #ifdef FEAT_CON_DIALOG
  1870.             if (!confirm_msg_used)
  1871. #endif
  1872.             {
  1873.                 /* Since got_int is set all typeahead will be
  1874.                  * flushed, but we want to keep this ':', remember
  1875.                  * that in a special way. */
  1876.                 typeahead_noflush(':');
  1877.                 cmdline_row = Rows - 1;   /* put ':' on this line */
  1878.                 skip_redraw = TRUE;          /* skip redraw once */
  1879.                 need_wait_return = FALSE; /* don't wait in main() */
  1880.             }
  1881.             /*FALLTHROUGH*/
  1882.             case 'q':        /* quit */
  1883.             case Ctrl_C:
  1884.             case ESC:
  1885. #ifdef FEAT_CON_DIALOG
  1886.             if (confirm_msg_used)
  1887.             {
  1888.                 /* Jump to the choices of the dialog. */
  1889.                 s = confirm_msg_tail;
  1890.                 lines_left = Rows - 1;
  1891.             }
  1892.             else
  1893. #endif
  1894.             {
  1895.                 got_int = TRUE;
  1896.                 quit_more = TRUE;
  1897.             }
  1898.             break;
  1899.             case 'u':        /* Up half a page */
  1900.             case K_PAGEUP:
  1901.             if (!more_back_used)
  1902.             {
  1903.                 msg_moremsg(TRUE);
  1904.                 continue;
  1905.             }
  1906.             more_back = Rows / 2;
  1907.             /*FALLTHROUGH*/
  1908.             case 'd':        /* Down half a page */
  1909.             lines_left = Rows / 2;
  1910.             break;
  1911.             case 'b':        /* one page back */
  1912.             if (!more_back_used)
  1913.             {
  1914.                 msg_moremsg(TRUE);
  1915.                 continue;
  1916.             }
  1917.             more_back = Rows - 1;
  1918.             /*FALLTHROUGH*/
  1919.             case ' ':        /* one extra page */
  1920.             case K_PAGEDOWN:
  1921.             case K_LEFTMOUSE:
  1922.             lines_left = Rows - 1;
  1923.             break;
  1924.  
  1925. #ifdef FEAT_CLIPBOARD
  1926.             case Ctrl_Y:
  1927.             /* Strange way to allow copying (yanking) a modeless
  1928.              * selection at the more prompt.  Use CTRL-Y,
  1929.              * because the same is used in Cmdline-mode and at the
  1930.              * hit-enter prompt.  However, scrolling one line up
  1931.              * might be expected... */
  1932.             if (clip_star.state == SELECT_DONE)
  1933.                 clip_copy_modeless_selection(TRUE);
  1934.             continue;
  1935. #endif
  1936.             default:        /* no valid response */
  1937.             msg_moremsg(TRUE);
  1938.             continue;
  1939.             }
  1940.             break;
  1941.         }
  1942.  
  1943.         /* clear the --more-- message */
  1944.         screen_fill((int)Rows - 1, (int)Rows,
  1945.                         0, (int)Columns, ' ', ' ', 0);
  1946.         State = oldState;
  1947. #ifdef FEAT_MOUSE
  1948.         setmouse();
  1949. #endif
  1950.         if (quit_more)
  1951.         {
  1952.             msg_row = Rows - 1;
  1953.             msg_col = 0;
  1954.             return;        /* the string is not displayed! */
  1955.         }
  1956. #ifdef FEAT_RIGHTLEFT
  1957.         if (cmdmsg_rl)
  1958.             msg_col = Columns - 1;
  1959. #endif
  1960.         }
  1961.     }
  1962.  
  1963.     if (t_col > 0
  1964.         && (vim_strchr((char_u *)"\n\r\b\t", *s) != NULL
  1965.             || *s == BELL
  1966.             || msg_col + t_col >= Columns
  1967. #ifdef FEAT_MBYTE
  1968.             || (has_mbyte && (*mb_ptr2cells)(s) > 1
  1969.                         && msg_col + t_col >= Columns - 1)
  1970. #endif
  1971.             ))
  1972.     {
  1973.         /* output any postponed text */
  1974.         t_puts(t_col, t_s, s, attr);
  1975.         t_col = 0;
  1976.     }
  1977.  
  1978.     if (*s == '\n')            /* go to next line */
  1979.     {
  1980.         msg_didout = FALSE;        /* remember that line is empty */
  1981.         msg_col = 0;
  1982.         if (++msg_row >= Rows)  /* safety check */
  1983.         msg_row = Rows - 1;
  1984.     }
  1985.     else if (*s == '\r')        /* go to column 0 */
  1986.     {
  1987.         msg_col = 0;
  1988.     }
  1989.     else if (*s == '\b')        /* go to previous char */
  1990.     {
  1991.         if (msg_col)
  1992.         --msg_col;
  1993.     }
  1994.     else if (*s == TAB)        /* translate into spaces */
  1995.     {
  1996.         do
  1997.         msg_screen_putchar(' ', attr);
  1998.         while (msg_col & 7);
  1999.     }
  2000.     else if (*s == BELL)        /* beep (from ":sh") */
  2001.         vim_beep();
  2002.     else
  2003.     {
  2004. #ifdef FEAT_MBYTE
  2005.         if (has_mbyte)
  2006.         {
  2007.         cw = (*mb_ptr2cells)(s);
  2008.         if (enc_utf8 && maxlen >= 0)
  2009.             /* avoid including composing chars after the end */
  2010.             l = utfc_ptr2len_check_len(s, (int)((str + maxlen) - s));
  2011.         else
  2012.             l = (*mb_ptr2len_check)(s);
  2013.         }
  2014.         else
  2015.         {
  2016.         cw = 1;
  2017.         l = 1;
  2018.         }
  2019. #endif
  2020.         /* When drawing from right to left or when a double-wide character
  2021.          * doesn't fit, draw a single character here.  Otherwise collect
  2022.          * characters and draw them all at once later. */
  2023. #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE)
  2024.         if (
  2025. # ifdef FEAT_RIGHTLEFT
  2026.             cmdmsg_rl
  2027. #  ifdef FEAT_MBYTE
  2028.             ||
  2029. #  endif
  2030. # endif
  2031. # ifdef FEAT_MBYTE
  2032.             (cw > 1 && msg_col + t_col >= Columns - 1)
  2033. # endif
  2034.             )
  2035.         {
  2036. # ifdef FEAT_MBYTE
  2037.         if (l > 1)
  2038.             s = screen_puts_mbyte(s, l, attr) - 1;
  2039.         else
  2040. # endif
  2041.             msg_screen_putchar(*s, attr);
  2042.         }
  2043.         else
  2044. #endif
  2045.         {
  2046.         /* postpone this character until later */
  2047.         if (t_col == 0)
  2048.             t_s = s;
  2049. #ifdef FEAT_MBYTE
  2050.         t_col += cw;
  2051.         s += l - 1;
  2052. #else
  2053.         ++t_col;
  2054. #endif
  2055.         }
  2056.     }
  2057.     ++s;
  2058.     }
  2059.  
  2060.     /* output any postponed text */
  2061.     if (t_col > 0)
  2062.     t_puts(t_col, t_s, s, attr);
  2063.  
  2064.     msg_check();
  2065. }
  2066.  
  2067. /*
  2068.  * Output any postponed text for msg_puts_attr_len().
  2069.  */
  2070.     static void
  2071. t_puts(t_col, t_s, s, attr)
  2072.     int        t_col;
  2073.     char_u    *t_s;
  2074.     char_u    *s;
  2075.     int        attr;
  2076. {
  2077.     /* output postponed text */
  2078.     msg_didout = TRUE;        /* remember that line is not empty */
  2079.     screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr);
  2080.     msg_col += t_col;
  2081.     if (msg_col >= Columns)
  2082.     {
  2083.     msg_col = 0;
  2084.     ++msg_row;
  2085.     }
  2086. }
  2087.  
  2088.  
  2089. /*
  2090.  * Returns TRUE when messages should be printed with mch_errmsg().
  2091.  * This is used when there is no valid screen, so we can see error messages.
  2092.  * If termcap is not active, we may be writing in an alternate console
  2093.  * window, cursor positioning may not work correctly (window size may be
  2094.  * different, e.g. for Win32 console) or we just don't know where the
  2095.  * cursor is.
  2096.  */
  2097.     int
  2098. msg_use_printf()
  2099. {
  2100.     return (!msg_check_screen()
  2101. #if defined(WIN3264) && !defined(FEAT_GUI_MSWIN)
  2102.         || !termcap_active
  2103. #endif
  2104.         || (swapping_screen() && !termcap_active)
  2105.            );
  2106. }
  2107.  
  2108. #if defined(USE_MCH_ERRMSG) || defined(PROTO)
  2109.  
  2110. #ifdef mch_errmsg
  2111. # undef mch_errmsg
  2112. #endif
  2113. #ifdef mch_msg
  2114. # undef mch_msg
  2115. #endif
  2116.  
  2117. /*
  2118.  * Give an error message.  To be used when the screen hasn't been initialized
  2119.  * yet.  When stderr can't be used, collect error messages until the GUI has
  2120.  * started and they can be displayed in a message box.
  2121.  */
  2122.     void
  2123. mch_errmsg(str)
  2124.     char    *str;
  2125. {
  2126.     int        len;
  2127.  
  2128. #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
  2129.     /* On Unix use stderr if it's a tty.
  2130.      * When not going to start the GUI also use stderr. */
  2131.     if (
  2132. # ifdef UNIX
  2133.         isatty(2)
  2134. #  ifdef FEAT_GUI
  2135.         ||
  2136. #  endif
  2137. # endif
  2138. # ifdef FEAT_GUI
  2139.         !(gui.in_use || gui.starting)
  2140. # endif
  2141.         )
  2142.     {
  2143.     fprintf(stderr, "%s", str);
  2144.     return;
  2145.     }
  2146. #endif
  2147.  
  2148.     /* avoid a delay for a message that isn't there */
  2149.     emsg_on_display = FALSE;
  2150.  
  2151.     len = (int)STRLEN(str) + 1;
  2152.     if (error_ga.ga_growsize == 0)
  2153.     {
  2154.     error_ga.ga_growsize = 80;
  2155.     error_ga.ga_itemsize = 1;
  2156.     }
  2157.     if (ga_grow(&error_ga, len) == OK)
  2158.     {
  2159.     mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len,
  2160.                               (char_u *)str, len);
  2161. #ifdef UNIX
  2162.     /* remove CR characters, they are displayed */
  2163.     {
  2164.         char_u    *p;
  2165.  
  2166.         p = (char_u *)error_ga.ga_data + error_ga.ga_len;
  2167.         for (;;)
  2168.         {
  2169.         p = vim_strchr(p, '\r');
  2170.         if (p == NULL)
  2171.             break;
  2172.         *p = ' ';
  2173.         }
  2174.     }
  2175. #endif
  2176.     --len;        /* don't count the NUL at the end */
  2177.     error_ga.ga_len += len;
  2178.     error_ga.ga_room -= len;
  2179.     }
  2180. }
  2181.  
  2182. /*
  2183.  * Give a message.  To be used when the screen hasn't been initialized yet.
  2184.  * When there is no tty, collect messages until the GUI has started and they
  2185.  * can be displayed in a message box.
  2186.  */
  2187.     void
  2188. mch_msg(str)
  2189.     char    *str;
  2190. {
  2191. #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
  2192.     /* On Unix use stdout if we have a tty.  This allows "vim -h | more" and
  2193.      * uses mch_errmsg() when started from the desktop.
  2194.      * When not going to start the GUI also use stdout. */
  2195.     if (
  2196. #  ifdef UNIX
  2197.         isatty(2)
  2198. #   ifdef FEAT_GUI
  2199.         ||
  2200. #   endif
  2201. #  endif
  2202. #  ifdef FEAT_GUI
  2203.         !(gui.in_use || gui.starting)
  2204. #  endif
  2205.         )
  2206.     {
  2207.     printf("%s", str);
  2208.     return;
  2209.     }
  2210. # endif
  2211.     mch_errmsg(str);
  2212. }
  2213. #endif /* USE_MCH_ERRMSG */
  2214.  
  2215. /*
  2216.  * Put a character on the screen at the current message position and advance
  2217.  * to the next position.  Only for printable ASCII!
  2218.  */
  2219.     static void
  2220. msg_screen_putchar(c, attr)
  2221.     int        c;
  2222.     int        attr;
  2223. {
  2224.     msg_didout = TRUE;        /* remember that line is not empty */
  2225.     screen_putchar(c, msg_row, msg_col, attr);
  2226. #ifdef FEAT_RIGHTLEFT
  2227.     if (cmdmsg_rl)
  2228.     {
  2229.     if (--msg_col == 0)
  2230.     {
  2231.         msg_col = Columns;
  2232.         ++msg_row;
  2233.     }
  2234.     }
  2235.     else
  2236. #endif
  2237.     {
  2238.     if (++msg_col >= Columns)
  2239.     {
  2240.         msg_col = 0;
  2241.         ++msg_row;
  2242.     }
  2243.     }
  2244. }
  2245.  
  2246.     void
  2247. msg_moremsg(full)
  2248.     int        full;
  2249. {
  2250.     int        attr;
  2251.  
  2252.     attr = hl_attr(HLF_M);
  2253.     screen_puts((char_u *)_("-- More --"), (int)Rows - 1, 0, attr);
  2254.     if (full)
  2255.     screen_puts(more_back_used
  2256.         ? (char_u *)_(" (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)")
  2257.         : (char_u *)_(" (RET: line, SPACE: page, d: half page, q: quit)"),
  2258.         (int)Rows - 1, 10, attr);
  2259. }
  2260.  
  2261. /*
  2262.  * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
  2263.  * exmode_active.
  2264.  */
  2265.     void
  2266. repeat_message()
  2267. {
  2268.     if (State == ASKMORE)
  2269.     {
  2270.     msg_moremsg(TRUE);    /* display --more-- message again */
  2271.     msg_row = Rows - 1;
  2272.     }
  2273. #ifdef FEAT_CON_DIALOG
  2274.     else if (State == CONFIRM)
  2275.     {
  2276.     display_confirm_msg();    /* display ":confirm" message again */
  2277.     msg_row = Rows - 1;
  2278.     }
  2279. #endif
  2280.     else if (State == EXTERNCMD)
  2281.     {
  2282.     windgoto(msg_row, msg_col); /* put cursor back */
  2283.     }
  2284.     else if (State == HITRETURN || State == SETWSIZE)
  2285.     {
  2286.     hit_return_msg();
  2287.     msg_row = Rows - 1;
  2288.     }
  2289. }
  2290.  
  2291. /*
  2292.  * msg_check_screen - check if the screen is initialized.
  2293.  * Also check msg_row and msg_col, if they are too big it may cause a crash.
  2294.  * While starting the GUI the terminal codes will be set for the GUI, but the
  2295.  * output goes to the terminal.  Don't use the terminal codes then.
  2296.  */
  2297.     static int
  2298. msg_check_screen()
  2299. {
  2300.     if (!full_screen || !screen_valid(FALSE))
  2301.     return FALSE;
  2302.  
  2303.     if (msg_row >= Rows)
  2304.     msg_row = Rows - 1;
  2305.     if (msg_col >= Columns)
  2306.     msg_col = Columns - 1;
  2307.     return TRUE;
  2308. }
  2309.  
  2310. /*
  2311.  * Clear from current message position to end of screen.
  2312.  * Note: msg_col is not updated, so we remember the end of the message
  2313.  * for msg_check().
  2314.  */
  2315.     void
  2316. msg_clr_eos()
  2317. {
  2318.     if (msg_use_printf())
  2319.     {
  2320.     if (full_screen)    /* only when termcap codes are valid */
  2321.     {
  2322.         if (*T_CD)
  2323.         out_str(T_CD);    /* clear to end of display */
  2324.         else if (*T_CE)
  2325.         out_str(T_CE);    /* clear to end of line */
  2326.     }
  2327.     }
  2328.     else
  2329.     {
  2330. #ifdef FEAT_RIGHTLEFT
  2331.     if (cmdmsg_rl)
  2332.     {
  2333.         screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0);
  2334.         screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
  2335.     }
  2336.     else
  2337. #endif
  2338.     {
  2339.         screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns,
  2340.                                  ' ', ' ', 0);
  2341.         screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
  2342.     }
  2343.     }
  2344. }
  2345.  
  2346. /*
  2347.  * Clear the command line.
  2348.  */
  2349.     void
  2350. msg_clr_cmdline()
  2351. {
  2352.     msg_row = cmdline_row;
  2353.     msg_col = 0;
  2354.     msg_clr_eos();
  2355. }
  2356.  
  2357. /*
  2358.  * end putting a message on the screen
  2359.  * call wait_return if the message does not fit in the available space
  2360.  * return TRUE if wait_return not called.
  2361.  */
  2362.     int
  2363. msg_end()
  2364. {
  2365.     /*
  2366.      * if the string is larger than the window,
  2367.      * or the ruler option is set and we run into it,
  2368.      * we have to redraw the window.
  2369.      * Do not do this if we are abandoning the file or editing the command line.
  2370.      */
  2371.     if (!exiting && need_wait_return && !(State & CMDLINE))
  2372.     {
  2373.     wait_return(FALSE);
  2374.     return FALSE;
  2375.     }
  2376.     out_flush();
  2377.     return TRUE;
  2378. }
  2379.  
  2380. /*
  2381.  * If the written message runs into the shown command or ruler, we have to
  2382.  * wait for hit-return and redraw the window later.
  2383.  */
  2384.     void
  2385. msg_check()
  2386. {
  2387.     if (msg_row == Rows - 1 && msg_col >= sc_col)
  2388.     {
  2389.     need_wait_return = TRUE;
  2390.     redraw_cmdline = TRUE;
  2391.     }
  2392. }
  2393.  
  2394. /*
  2395.  * May write a string to the redirection file.
  2396.  * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
  2397.  */
  2398.     static void
  2399. redir_write(str, maxlen)
  2400.     char_u    *str;
  2401.     int        maxlen;
  2402. {
  2403.     char_u    *s = str;
  2404.     static int    cur_col = 0;
  2405.  
  2406.     if ((redir_fd != NULL
  2407. #ifdef FEAT_EVAL
  2408.               || redir_reg
  2409. #endif
  2410.                        ) && !redir_off)
  2411.     {
  2412.     /* If the string doesn't start with CR or NL, go to msg_col */
  2413.     if (*s != '\n' && *s != '\r')
  2414.     {
  2415.         while (cur_col < msg_col)
  2416.         {
  2417. #ifdef FEAT_EVAL
  2418.         if (redir_reg)
  2419.             write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
  2420.         else if (redir_fd)
  2421. #endif
  2422.             fputs(" ", redir_fd);
  2423.         ++cur_col;
  2424.         }
  2425.     }
  2426.  
  2427. #ifdef FEAT_EVAL
  2428.     if (redir_reg)
  2429.         write_reg_contents(redir_reg, s, maxlen, TRUE);
  2430. #endif
  2431.  
  2432.     /* Adjust the current column */
  2433.     while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
  2434.     {
  2435. #ifdef FEAT_EVAL
  2436.         if (!redir_reg && redir_fd != NULL)
  2437. #endif
  2438.         putc(*s, redir_fd);
  2439.         if (*s == '\r' || *s == '\n')
  2440.         cur_col = 0;
  2441.         else if (*s == '\t')
  2442.         cur_col += (8 - cur_col % 8);
  2443.         else
  2444.         ++cur_col;
  2445.         ++s;
  2446.     }
  2447.     }
  2448. }
  2449.  
  2450. /*
  2451.  * Give a warning message (for searching).
  2452.  * Use 'w' highlighting and may repeat the message after redrawing
  2453.  */
  2454.     void
  2455. give_warning(message, hl)
  2456.     char_u  *message;
  2457.     int        hl;
  2458. {
  2459.     /* Don't do this for ":silent". */
  2460.     if (msg_silent != 0)
  2461.     return;
  2462.  
  2463. #ifdef FEAT_EVAL
  2464.     set_vim_var_string(VV_WARNINGMSG, message, -1);
  2465. #endif
  2466. #ifdef VIMBUDDY
  2467.     VimBuddyText(message, 1);
  2468. #else
  2469.     vim_free(keep_msg);
  2470.     keep_msg = NULL;
  2471.     if (hl)
  2472.     keep_msg_attr = hl_attr(HLF_W);
  2473.     else
  2474.     keep_msg_attr = 0;
  2475.     if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0)
  2476.     set_keep_msg(message);
  2477.     msg_didout = FALSE;        /* overwrite this message */
  2478.     msg_nowait = TRUE;        /* don't wait for this message */
  2479.     msg_col = 0;
  2480. #endif
  2481. }
  2482.  
  2483. /*
  2484.  * Advance msg cursor to column "col".
  2485.  */
  2486.     void
  2487. msg_advance(col)
  2488.     int        col;
  2489. {
  2490.     if (msg_silent != 0)    /* nothing to advance to */
  2491.     {
  2492.     msg_putchar(' ');    /* insert something for redirection */
  2493.     return;
  2494.     }
  2495.     if (col >= Columns)        /* not enough room */
  2496.     col = Columns - 1;
  2497.     while (msg_col < col)
  2498.     msg_putchar(' ');
  2499. }
  2500.  
  2501. #if defined(FEAT_CON_DIALOG) || defined(PROTO)
  2502. /*
  2503.  * Used for "confirm()" function, and the :confirm command prefix.
  2504.  * Versions which haven't got flexible dialogs yet, and console
  2505.  * versions, get this generic handler which uses the command line.
  2506.  *
  2507.  * type  = one of:
  2508.  *       VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC
  2509.  * title = title string (can be NULL for default)
  2510.  * (neither used in console dialogs at the moment)
  2511.  *
  2512.  * Format of the "buttons" string:
  2513.  * "Button1Name\nButton2Name\nButton3Name"
  2514.  * The first button should normally be the default/accept
  2515.  * The second button should be the 'Cancel' button
  2516.  * Other buttons- use your imagination!
  2517.  * A '&' in a button name becomes a shortcut, so each '&' should be before a
  2518.  * different letter.
  2519.  */
  2520. /* ARGSUSED */
  2521.     int
  2522. do_dialog(type, title, message, buttons, dfltbutton, textfield)
  2523.     int        type;
  2524.     char_u    *title;
  2525.     char_u    *message;
  2526.     char_u    *buttons;
  2527.     int        dfltbutton;
  2528.     char_u    *textfield;    /* IObuff for inputdialog(), NULL otherwise */
  2529. {
  2530.     int        oldState;
  2531.     int        retval = 0;
  2532.     char_u    *hotkeys;
  2533.     int        c;
  2534.  
  2535. #ifndef NO_CONSOLE
  2536.     /* Don't output anything in silent mode ("ex -s") */
  2537.     if (silent_mode)
  2538.     return dfltbutton;   /* return default option */
  2539. #endif
  2540.  
  2541. #ifdef FEAT_GUI_DIALOG
  2542.     /* When GUI is running and 'c' not in 'guioptions', use the GUI dialog */
  2543.     if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
  2544.     {
  2545.     c = gui_mch_dialog(type, title, message, buttons, dfltbutton,
  2546.                                    textfield);
  2547.     msg_end_prompt();
  2548.     return c;
  2549.     }
  2550. #endif
  2551.  
  2552.     oldState = State;
  2553.     State = CONFIRM;
  2554. #ifdef FEAT_MOUSE
  2555.     setmouse();
  2556. #endif
  2557.  
  2558.     /*
  2559.      * Since we wait for a keypress, don't make the
  2560.      * user press RETURN as well afterwards.
  2561.      */
  2562.     ++no_wait_return;
  2563.     hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
  2564.  
  2565.     if (hotkeys != NULL)
  2566.     {
  2567.     for (;;)
  2568.     {
  2569.         /* Get a typed character directly from the user. */
  2570.         c = get_keystroke();
  2571.         switch (c)
  2572.         {
  2573.         case CR:        /* User accepts default option */
  2574.         case NL:
  2575.         retval = dfltbutton;
  2576.         break;
  2577.         case Ctrl_C:        /* User aborts/cancels */
  2578.         case ESC:
  2579.         retval = 0;
  2580.         break;
  2581.         default:        /* Could be a hotkey? */
  2582.         if (c > 255)    /* special keys are ignored here */
  2583.             continue;
  2584.         for (retval = 0; hotkeys[retval]; retval++)
  2585.         {
  2586.             if (hotkeys[retval] == TOLOWER_LOC(c))
  2587.             break;
  2588.         }
  2589.         if (hotkeys[retval])
  2590.         {
  2591.             retval++;
  2592.             break;
  2593.         }
  2594.         /* No hotkey match, so keep waiting */
  2595.         continue;
  2596.         }
  2597.         break;
  2598.     }
  2599.  
  2600.     vim_free(hotkeys);
  2601.     }
  2602.  
  2603.     State = oldState;
  2604. #ifdef FEAT_MOUSE
  2605.     setmouse();
  2606. #endif
  2607.     --no_wait_return;
  2608.     msg_end_prompt();
  2609.  
  2610.     return retval;
  2611. }
  2612.  
  2613. /*
  2614.  * Format the dialog string, and display it at the bottom of
  2615.  * the screen. Return a string of hotkey chars (if defined) for
  2616.  * each 'button'. If a button has no hotkey defined, the string
  2617.  * has the buttons first letter.
  2618.  *
  2619.  * Returns allocated array, or NULL for error.
  2620.  *
  2621.  */
  2622.     static char_u *
  2623. msg_show_console_dialog(message, buttons, dfltbutton)
  2624.     char_u    *message;
  2625.     char_u    *buttons;
  2626.     int        dfltbutton;
  2627. {
  2628.     int        len = 0;
  2629.     int        lenhotkey = 1;    /*first button*/
  2630.     char_u    *hotk;
  2631.     char_u    *p;
  2632.     char_u    *q;
  2633.     char_u    *r;
  2634.  
  2635.     /*
  2636.      * First compute how long a string we need to allocate for the message.
  2637.      */
  2638.     r = buttons;
  2639.     while (*r)
  2640.     {
  2641.     if (*r == DLG_BUTTON_SEP)
  2642.     {
  2643.         len++;        /* '\n' -> ', ' */
  2644.         lenhotkey++;    /* each button needs a hotkey */
  2645.     }
  2646.     else if (*r == DLG_HOTKEY_CHAR)
  2647.     {
  2648.         len++;        /* '&a' -> '[a]' */
  2649.     }
  2650.     r++;
  2651.     }
  2652.  
  2653.     len += STRLEN(message)
  2654.         + 2            /* for the NL's */
  2655.         + STRLEN(buttons)
  2656.         + 3;        /* for the ": " and NUL */
  2657.  
  2658.     lenhotkey++;        /* for the NUL */
  2659.  
  2660.     /*
  2661.      * Now allocate and load the strings
  2662.      */
  2663.     vim_free(confirm_msg);
  2664.     confirm_msg = alloc(len);
  2665.     if (confirm_msg == NULL)
  2666.     return NULL;
  2667.     *confirm_msg = NUL;
  2668.     hotk = alloc(lenhotkey);
  2669.     if (hotk == NULL)
  2670.     return NULL;
  2671.  
  2672.     *confirm_msg = '\n';
  2673.     STRCPY(confirm_msg + 1, message);
  2674.  
  2675.     p = confirm_msg + 1 + STRLEN(message);
  2676.     q = hotk;
  2677.     r = buttons;
  2678.     *q = (char_u)TOLOWER_LOC(*r);    /* define lowercase hotkey */
  2679.  
  2680.     /* Remember where the choices start, displaying starts here when "q" typed
  2681.      * at the more prompt. */
  2682.     confirm_msg_tail = p;
  2683.     *p++ = '\n';
  2684.  
  2685.     while (*r)
  2686.     {
  2687.     if (*r == DLG_BUTTON_SEP)
  2688.     {
  2689.         *p++ = ',';
  2690.         *p++ = ' ';        /* '\n' -> ', ' */
  2691.         *(++q) = (char_u)TOLOWER_LOC(*(r + 1)); /* next hotkey */
  2692.         if (dfltbutton)
  2693.         --dfltbutton;
  2694.     }
  2695.     else if (*r == DLG_HOTKEY_CHAR)
  2696.     {
  2697.         r++;
  2698.         if (*r == DLG_HOTKEY_CHAR)        /* '&&a' -> '&a' */
  2699.         *p++ = *r;
  2700.         else
  2701.         {
  2702.         /* '&a' -> '[a]' */
  2703.         *p++ = (dfltbutton == 1) ? '[' : '(';
  2704.         *p++ = *r;
  2705.         *p++ = (dfltbutton == 1) ? ']' : ')';
  2706.         *q = (char_u)TOLOWER_LOC(*r);    /* define lowercase hotkey */
  2707.         }
  2708.     }
  2709.     else
  2710.     {
  2711.         *p++ = *r;        /* everything else copy literally */
  2712.     }
  2713.     r++;
  2714.     }
  2715.     *p++ = ':';
  2716.     *p++ = ' ';
  2717.     *p = NUL;
  2718.     *(++q) = NUL;
  2719.  
  2720.     display_confirm_msg();
  2721.     return hotk;
  2722. }
  2723.  
  2724. /*
  2725.  * Display the ":confirm" message.  Also called when screen resized.
  2726.  */
  2727.     void
  2728. display_confirm_msg()
  2729. {
  2730.     /* avoid that 'q' at the more prompt truncates the message here */
  2731.     ++confirm_msg_used;
  2732.     if (confirm_msg != NULL)
  2733.     msg_puts_attr(confirm_msg, hl_attr(HLF_M));
  2734.     --confirm_msg_used;
  2735. }
  2736.  
  2737. #endif /* FEAT_CON_DIALOG */
  2738.  
  2739. #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
  2740.  
  2741.     int
  2742. vim_dialog_yesno(type, title, message, dflt)
  2743.     int        type;
  2744.     char_u    *title;
  2745.     char_u    *message;
  2746.     int        dflt;
  2747. {
  2748.     if (do_dialog(type,
  2749.         title == NULL ? (char_u *)_("Question") : title,
  2750.         message,
  2751.         (char_u *)_("&Yes\n&No"), dflt, NULL) == 1)
  2752.     return VIM_YES;
  2753.     return VIM_NO;
  2754. }
  2755.  
  2756.     int
  2757. vim_dialog_yesnocancel(type, title, message, dflt)
  2758.     int        type;
  2759.     char_u    *title;
  2760.     char_u    *message;
  2761.     int        dflt;
  2762. {
  2763.     switch (do_dialog(type,
  2764.         title == NULL ? (char_u *)_("Question") : title,
  2765.         message,
  2766.         (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL))
  2767.     {
  2768.     case 1: return VIM_YES;
  2769.     case 2: return VIM_NO;
  2770.     }
  2771.     return VIM_CANCEL;
  2772. }
  2773.  
  2774.     int
  2775. vim_dialog_yesnoallcancel(type, title, message, dflt)
  2776.     int        type;
  2777.     char_u    *title;
  2778.     char_u    *message;
  2779.     int        dflt;
  2780. {
  2781.     switch (do_dialog(type,
  2782.         title == NULL ? (char_u *)"Question" : title,
  2783.         message,
  2784.         (char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
  2785.                                   dflt, NULL))
  2786.     {
  2787.     case 1: return VIM_YES;
  2788.     case 2: return VIM_NO;
  2789.     case 3: return VIM_ALL;
  2790.     case 4: return VIM_DISCARDALL;
  2791.     }
  2792.     return VIM_CANCEL;
  2793. }
  2794.  
  2795. #endif /* FEAT_GUI_DIALOG || FEAT_CON_DIALOG */
  2796.  
  2797. #if defined(FEAT_BROWSE) || defined(PROTO)
  2798. /*
  2799.  * Generic browse function.  Calls gui_mch_browse() when possible.
  2800.  * Later this may pop-up a non-GUI file selector (external command?).
  2801.  */
  2802.     char_u *
  2803. do_browse(saving, title, dflt, ext, initdir, filter, buf)
  2804.     int        saving;        /* write action */
  2805.     char_u    *title;        /* title for the window */
  2806.     char_u    *dflt;        /* default file name (may include directory) */
  2807.     char_u    *ext;        /* extension added */
  2808.     char_u    *initdir;    /* initial directory, NULL for current dir or
  2809.                    when using path from "dflt" */
  2810.     char_u    *filter;    /* file name filter */
  2811.     buf_T    *buf;        /* buffer to read/write for */
  2812. {
  2813.     char_u        *fname;
  2814.     static char_u    *last_dir = NULL;    /* last used directory */
  2815.     char_u        *tofree = NULL;
  2816.  
  2817.  
  2818.     /* Must turn off browse straight away, or :so autocommands will get the
  2819.      * flag too!  */
  2820.     cmdmod.browse = FALSE;
  2821.  
  2822.     if (title == NULL)
  2823.     {
  2824.     if (saving)
  2825.         title = (char_u *)_("Save File dialog");
  2826.     else
  2827.         title = (char_u *)_("Open File dialog");
  2828.     }
  2829.  
  2830.     /* When no directory specified, use default file name, default dir, buffer
  2831.      * dir, last dir or current dir */
  2832.     if ((initdir == NULL || *initdir == NUL) && dflt != NULL && *dflt != NUL)
  2833.     {
  2834.     if (mch_isdir(dflt))        /* default file name is a directory */
  2835.     {
  2836.         initdir = dflt;
  2837.         dflt = NULL;
  2838.     }
  2839.     else if (gettail(dflt) != dflt)    /* default file name includes a path */
  2840.     {
  2841.         tofree = vim_strsave(dflt);
  2842.         if (tofree != NULL)
  2843.         {
  2844.         initdir = tofree;
  2845.         *gettail(initdir) = NUL;
  2846.         dflt = gettail(dflt);
  2847.         }
  2848.     }
  2849.     }
  2850.  
  2851.     if (initdir == NULL || *initdir == NUL)
  2852.     {
  2853.     /* When 'browsedir' is a directory, use it */
  2854.     if (mch_isdir(p_bsdir))
  2855.         initdir = p_bsdir;
  2856.     /* When saving or 'browsedir' is "buffer", use buffer fname */
  2857.     else if ((saving || *p_bsdir == 'b')
  2858.         && buf != NULL && buf->b_ffname != NULL)
  2859.     {
  2860.         if (dflt == NULL || *dflt == NUL)
  2861.         dflt = gettail(curbuf->b_ffname);
  2862.         tofree = vim_strsave(curbuf->b_ffname);
  2863.         if (tofree != NULL)
  2864.         {
  2865.         initdir = tofree;
  2866.         *gettail(initdir) = NUL;
  2867.         }
  2868.     }
  2869.     /* When 'browsedir' is "last", use dir from last browse */
  2870.     else if (*p_bsdir == 'l')
  2871.         initdir = last_dir;
  2872.     /* When 'browsedir is "current", use current directory.  This is the
  2873.      * default already, leave initdir empty. */
  2874.     }
  2875.  
  2876. # ifdef FEAT_GUI
  2877.     if (gui.in_use)        /* when this changes, also adjust f_has()! */
  2878.     {
  2879.     if (filter == NULL
  2880. #  ifdef FEAT_EVAL
  2881.         && (filter = get_var_value((char_u *)"b:browsefilter")) == NULL
  2882.         && (filter = get_var_value((char_u *)"g:browsefilter")) == NULL
  2883. #  endif
  2884.     )
  2885.         filter = BROWSE_FILTER_DEFAULT;
  2886.     fname = gui_mch_browse(saving, title, dflt, ext, initdir, filter);
  2887.  
  2888.     /* We hang around in the dialog for a while, the user might do some
  2889.      * things to our files.  The Win32 dialog allows deleting or renaming
  2890.      * a file, check timestamps. */
  2891.     need_check_timestamps = TRUE;
  2892.     did_check_timestamps = FALSE;
  2893.     }
  2894.     else
  2895. # endif
  2896.     {
  2897.     /* TODO: non-GUI file selector here */
  2898.     EMSG(_("E338: Sorry, no file browser in console mode"));
  2899.     fname = NULL;
  2900.     }
  2901.  
  2902.     /* keep the directory for next time */
  2903.     if (fname != NULL)
  2904.     {
  2905.     vim_free(last_dir);
  2906.     last_dir = vim_strsave(fname);
  2907.     if (last_dir != NULL)
  2908.     {
  2909.         *gettail(last_dir) = NUL;
  2910.         if (*last_dir == NUL)
  2911.         {
  2912.         /* filename only returned, must be in current dir */
  2913.         vim_free(last_dir);
  2914.         last_dir = alloc(MAXPATHL);
  2915.         if (last_dir != NULL)
  2916.             mch_dirname(last_dir, MAXPATHL);
  2917.         }
  2918.     }
  2919.     }
  2920.  
  2921.     vim_free(tofree);
  2922.  
  2923.     return fname;
  2924. }
  2925. #endif
  2926.