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 / amiga / vim46src.lha / vim-4.6 / src / message.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-03  |  18.8 KB  |  849 lines

  1. /* vi:set ts=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.  */
  8.  
  9. /*
  10.  * message.c: functions for displaying messages on the command line
  11.  */
  12.  
  13. #include "vim.h"
  14. #include "globals.h"
  15. #define MESSAGE            /* don't include prototype for smsg() */
  16. #include "proto.h"
  17. #include "option.h"
  18. #ifdef __QNX__
  19. # include <stdarg.h>
  20. #endif
  21.  
  22. static void msg_screen_outchar __ARGS((int c));
  23. static int msg_check_screen __ARGS((void));
  24.  
  25. static int    lines_left = -1;            /* lines left for listing */
  26.  
  27. /*
  28.  * msg(s) - displays the string 's' on the status line
  29.  * When terminal not initialized (yet) fprintf(stderr,..) is used.
  30.  * return TRUE if wait_return not called
  31.  */
  32.     int
  33. msg(s)
  34.     char_u           *s;
  35. {
  36.     msg_start();
  37.     if (msg_highlight)
  38.         start_highlight();
  39.     msg_outtrans(s);
  40.     if (msg_highlight)
  41.     {
  42.         stop_highlight();
  43.         msg_highlight = FALSE;        /* clear for next call */
  44.     }
  45.     msg_clr_eos();
  46.     return msg_end();
  47. }
  48.  
  49. /*
  50.  * automatic prototype generation does not understand this function
  51.  */
  52. #ifndef PROTO
  53. #ifndef __QNX__
  54. int smsg __ARGS((char_u *, long, long, long,
  55.                         long, long, long, long, long, long, long));
  56.  
  57. /* VARARGS */
  58.     int
  59. smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  60.     char_u        *s;
  61.     long        a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  62. {
  63.     sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  64.     return msg(IObuff);
  65. }
  66. #else /* __QNX__ */
  67. void smsg(char_u *s, ...)
  68. {
  69.     va_list arglist;
  70.     va_start(arglist, s);
  71.     vsprintf((char *)IObuff, (char *)s, arglist);
  72.     va_end(arglist);
  73.     msg(IObuff);
  74. }
  75. #endif /* __QNX__ */
  76. #endif
  77.  
  78. /*
  79.  * emsg() - display an error message
  80.  *
  81.  * Rings the bell, if appropriate, and calls message() to do the real work
  82.  * When terminal not initialized (yet) fprintf(stderr,..) is used.
  83.  *
  84.  * return TRUE if wait_return not called
  85.  */
  86.     int
  87. emsg(s)
  88.     char_u           *s;
  89. {
  90.     char_u            *Buf;
  91. #ifdef SLEEP_IN_EMSG
  92.     int                retval;
  93. #endif
  94.     static int        last_lnum = 0;
  95.     static char_u    *last_sourcing_name = NULL;
  96.  
  97.     if (emsg_off)                /* no error messages at the moment */
  98.         return TRUE;
  99.  
  100.     if (global_busy)            /* break :global command */
  101.         ++global_busy;
  102.  
  103.     if (p_eb)
  104.         beep_flush();            /* also includes flush_buffers() */
  105.     else
  106.         flush_buffers(FALSE);    /* flush internal buffers */
  107.     did_emsg = TRUE;            /* flag for DoOneCmd() */
  108.     ++msg_scroll;                /* don't overwrite a previous message */
  109.     (void)set_highlight('e');    /* set highlight mode for error messages */
  110.     msg_highlight = TRUE;
  111.     if (msg_scrolled)
  112.         need_wait_return = TRUE;    /* needed in case emsg() is called after
  113.                                      * wait_return has reset need_wait_return
  114.                                      * and a redraw is expected because
  115.                                      * msg_scrolled is non-zero */
  116.  
  117. /*
  118.  * First output name and line number of source of error message
  119.  */
  120.     if (sourcing_name != NULL &&
  121.            (sourcing_name != last_sourcing_name || sourcing_lnum != last_lnum)
  122.                                       && (Buf = alloc(MAXPATHL + 30)) != NULL)
  123.     {
  124.         ++no_wait_return;
  125.         if (sourcing_name != last_sourcing_name)
  126.         {
  127.             sprintf((char *)Buf, "Error detected while processing %s:",
  128.                                             sourcing_name);
  129.             msg(Buf);
  130.             msg_highlight = TRUE;
  131.         }
  132.             /* lnum is 0 when executing a command from the command line
  133.              * argument, we don't want a line number then */
  134.         if (sourcing_lnum != 0)
  135.         {
  136.             (void)set_highlight('n');    /* highlight mode for line numbers */
  137.             sprintf((char *)Buf, "line %4ld:", sourcing_lnum);
  138.             msg(Buf);
  139.             (void)set_highlight('e');    /* highlight mode for error messages */
  140.             msg_highlight = TRUE;
  141.         }
  142.         --no_wait_return;
  143.         last_lnum = sourcing_lnum;    /* only once for each line */
  144.         vim_free(Buf);
  145.     }
  146.     last_sourcing_name = sourcing_name;    /* do this also when it is NULL */
  147.  
  148. #ifdef SLEEP_IN_EMSG
  149. /*
  150.  * Msg returns TRUE if wait_return() was not called.
  151.  * In that case may call sleep() to give the user a chance to read the message.
  152.  * Don't call sleep() if dont_sleep is set.
  153.  */
  154.     retval = msg(s);
  155.     if (retval)
  156.     {
  157.         if (dont_sleep || need_wait_return)
  158.             need_sleep = TRUE;    /* sleep before removing the message */
  159.         else
  160.             mch_delay(1000L, TRUE);    /* give user chance to read message */
  161.     }
  162.     /* --msg_scroll;            don't overwrite this message */
  163.     return retval;
  164. #else
  165.     emsg_on_display = TRUE;        /* remember there is an error message */
  166.     return msg(s);
  167. #endif
  168. }
  169.  
  170.     int
  171. emsg2(s, a1)
  172.     char_u *s, *a1;
  173. {
  174.     /* Check for NULL strings (just in case) */
  175.     if (a1 == NULL)
  176.         a1 = (char_u *)"[NULL]";
  177.     /* Check for very long strings (can happen with ":help ^A<CR>") */
  178.     if (STRLEN(s) + STRLEN(a1) >= (size_t)IOSIZE)
  179.         a1 = (char_u *)"[string too long]";
  180.     sprintf((char *)IObuff, (char *)s, (char *)a1);
  181.     return emsg(IObuff);
  182. }
  183.  
  184.     int
  185. emsgn(s, n)
  186.     char_u *s;
  187.     long    n;
  188. {
  189.     sprintf((char *)IObuff, (char *)s, n);
  190.     return emsg(IObuff);
  191. }
  192.  
  193. /*
  194.  * Like msg(), but truncate to a single line if p_shm contains 't'.
  195.  * Careful: The string may be changed!
  196.  */
  197.     int
  198. msg_trunc(s)
  199.     char_u    *s;
  200. {
  201.     int        n;
  202.  
  203.     if (shortmess(SHM_TRUNC) && (n = (int)STRLEN(s) -
  204.                     (int)(Rows - cmdline_row - 1) * Columns - sc_col + 1) > 0)
  205.     {
  206.         s[n] = '<';
  207.         return msg(s + n);
  208.     }
  209.     else
  210.         return msg(s);
  211. }
  212.  
  213. /*
  214.  * wait for the user to hit a key (normally a return)
  215.  * if 'redraw' is TRUE, clear and redraw the screen
  216.  * if 'redraw' is FALSE, just redraw the screen
  217.  * if 'redraw' is -1, don't redraw at all
  218.  */
  219.     void
  220. wait_return(redraw)
  221.     int        redraw;
  222. {
  223.     int                c;
  224.     int                oldState;
  225.     int                tmpState;
  226.  
  227.     if (redraw == TRUE)
  228.         must_redraw = CLEAR;
  229.  
  230. /*
  231.  * With the global command (and some others) we only need one return at the
  232.  * end. Adjust cmdline_row to avoid the next message overwriting the last one.
  233.  */
  234.     if (no_wait_return)
  235.     {
  236.         need_wait_return = TRUE;
  237.         cmdline_row = msg_row;
  238.         return;
  239.     }
  240.     oldState = State;
  241.     if (quit_more)
  242.     {
  243.         c = CR;                        /* just pretend CR was hit */
  244.         quit_more = FALSE;
  245.         got_int = FALSE;
  246.     }
  247.     else
  248.     {
  249.         State = HITRETURN;
  250. #ifdef USE_MOUSE
  251.         setmouse();
  252. #endif
  253.         if (msg_didout)                /* start on a new line */
  254.             msg_outchar('\n');
  255.         if (got_int)
  256.             MSG_OUTSTR("Interrupt: ");
  257.  
  258.         (void)set_highlight('r');
  259.         start_highlight();
  260. #ifdef ORG_HITRETURN
  261.         MSG_OUTSTR("Press RETURN to continue");
  262.         stop_highlight();
  263.         do {
  264.             c = vgetc();
  265.         } while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
  266.         if (c == ':')                     /* this can vi too (but not always!) */
  267.             stuffcharReadbuff(c);
  268. #else
  269.         MSG_OUTSTR("Press RETURN or enter command to continue");
  270.         stop_highlight();
  271.         do
  272.         {
  273.             c = vgetc();
  274.             if (!global_busy)
  275.                 got_int = FALSE;
  276.         } while (c == Ctrl('C')
  277. #ifdef USE_GUI
  278.                                 || c == K_SCROLLBAR || c == K_HORIZ_SCROLLBAR
  279. #endif
  280. #ifdef USE_MOUSE
  281.                                 || c == K_LEFTDRAG   || c == K_LEFTRELEASE
  282.                                 || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
  283.                                 || c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
  284.                                 || c == K_IGNORE     ||
  285.                                 (!mouse_has(MOUSE_RETURN) &&
  286.                                      (c == K_LEFTMOUSE ||
  287.                                       c == K_MIDDLEMOUSE ||
  288.                                       c == K_RIGHTMOUSE))
  289. #endif
  290.                                 );
  291.         mch_breakcheck();
  292. #ifdef USE_MOUSE
  293.         /*
  294.          * Avoid that the mouse-up event causes visual mode to start.
  295.          */
  296.         if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE)
  297.             jump_to_mouse(MOUSE_SETPOS);
  298.         else
  299. #endif
  300.             if (vim_strchr((char_u *)"\r\n ", c) == NULL)
  301.         {
  302.             stuffcharReadbuff(c);
  303.             do_redraw = TRUE;        /* need a redraw even though there is
  304.                                        something in the stuff buffer */
  305.         }
  306. #endif
  307.     }
  308.  
  309.     /*
  310.      * If the user hits ':', '?' or '/' we get a command line from the next
  311.      * line.
  312.      */
  313.     if (c == ':' || c == '?' || c == '/')
  314.     {
  315.         cmdline_row = msg_row;
  316.         skip_redraw = TRUE;            /* skip redraw once */
  317.         do_redraw = FALSE;
  318.     }
  319.  
  320. /*
  321.  * If the window size changed set_winsize() will redraw the screen.
  322.  * Otherwise the screen is only redrawn if 'redraw' is set and no ':' typed.
  323.  */
  324.     tmpState = State;
  325.     State = oldState;                /* restore State before set_winsize */
  326. #ifdef USE_MOUSE
  327.     setmouse();
  328. #endif
  329.     msg_check();
  330.  
  331.     need_wait_return = FALSE;
  332.     emsg_on_display = FALSE;    /* can delete error message now */
  333. #ifdef SLEEP_IN_EMSG
  334.     need_sleep = FALSE;            /* no need to call sleep() anymore */
  335. #endif
  336.     msg_didany = FALSE;            /* reset lines_left at next msg_start() */
  337.     lines_left = -1;
  338.     if (keep_msg != NULL && linetabsize(keep_msg) >=
  339.                                   (Rows - cmdline_row - 1) * Columns + sc_col)
  340.         keep_msg = NULL;            /* don't redisplay message, it's too long */
  341.  
  342.     if (tmpState == SETWSIZE)        /* got resize event while in vgetc() */
  343.     {
  344.         starttermcap();                /* start termcap before redrawing */
  345.         set_winsize(0, 0, FALSE);
  346.     }
  347.     else if (!skip_redraw && (redraw == TRUE || (msg_scrolled && redraw != -1)))
  348.     {
  349.         starttermcap();                /* start termcap before redrawing */
  350.         updateScreen(VALID);
  351.     }
  352.  
  353.     dont_wait_return = TRUE;        /* don't wait again in main() */
  354. }
  355.  
  356. /*
  357.  * Prepare for outputting characters in the command line.
  358.  */
  359.     void
  360. msg_start()
  361. {
  362.     keep_msg = NULL;                        /* don't display old message now */
  363.     keep_msg_highlight = 0;
  364.     if (!msg_scroll && full_screen)            /* overwrite last message */
  365.         msg_pos(cmdline_row, 0);
  366.     else if (msg_didout)                    /* start message on next line */
  367.     {
  368.         msg_outchar('\n');
  369.         cmdline_row = msg_row;
  370.     }
  371.     if (!msg_didany)
  372.         lines_left = cmdline_row;
  373.     msg_didout = FALSE;                        /* no output on current line yet */
  374.     cursor_off();
  375. }
  376.  
  377. /*
  378.  * Move message position. This should always be used after moving the cursor.
  379.  * Use negative value if row or col does not have to be changed.
  380.  */
  381.     void
  382. msg_pos(row, col)
  383.     int        row, col;
  384. {
  385.     if (row >= 0)
  386.         msg_row = row;
  387.     if (col >= 0)
  388.         msg_col = col;
  389. }
  390.  
  391.     void
  392. msg_outchar(c)
  393.     int        c;
  394. {
  395.     char_u        buf[4];
  396.  
  397.     if (IS_SPECIAL(c))
  398.     {
  399.         buf[0] = K_SPECIAL;
  400.         buf[1] = K_SECOND(c);
  401.         buf[2] = K_THIRD(c);
  402.         buf[3] = NUL;
  403.     }
  404.     else
  405.     {
  406.         buf[0] = c;
  407.         buf[1] = NUL;
  408.     }
  409.     msg_outstr(buf);
  410. }
  411.  
  412.     void
  413. msg_outnum(n)
  414.     long        n;
  415. {
  416.     char_u        buf[20];
  417.  
  418.     sprintf((char *)buf, "%ld", n);
  419.     msg_outstr(buf);
  420. }
  421.  
  422.     void
  423. msg_home_replace(fname)
  424.     char_u    *fname;
  425. {
  426.     char_u        *name;
  427.  
  428.     name = home_replace_save(NULL, fname);
  429.     if (name != NULL)
  430.         msg_outtrans(name);
  431.     vim_free(name);
  432. }
  433.  
  434. /*
  435.  * output 'len' characters in 'str' (including NULs) with translation
  436.  * if 'len' is -1, output upto a NUL character
  437.  * return the number of characters it takes on the screen
  438.  */
  439.     int
  440. msg_outtrans(str)
  441.     register char_u *str;
  442. {
  443.     return msg_outtrans_len(str, (int)STRLEN(str));
  444. }
  445.  
  446.     int
  447. msg_outtrans_len(str, len)
  448.     register char_u *str;
  449.     register int   len;
  450. {
  451.     int retval = 0;
  452.  
  453.     while (--len >= 0)
  454.     {
  455.         msg_outstr(transchar(*str));
  456.         retval += charsize(*str);
  457.         ++str;
  458.     }
  459.     return retval;
  460. }
  461.  
  462. /*
  463.  * Output the string 'str' upto a NUL character.
  464.  * Return the number of characters it takes on the screen.
  465.  *
  466.  * If K_SPECIAL is encountered, then it is taken in conjunction with the
  467.  * following character and shown as <F1>, <S-Up> etc.  In addition, if 'all'
  468.  * is TRUE, then any other character which has its 8th bit set is shown as
  469.  * <M-x>, where x is the equivalent character without its 8th bit set.  If a
  470.  * character is displayed in one of these special ways, is also highlighted
  471.  * (its highlight name is '8' in the p_hl variable).
  472.  * This function is used to show mappings, where we want to see how to type
  473.  * the character/string -- webb
  474.  */
  475.     int
  476. msg_outtrans_special(str, all)
  477.     register char_u *str;
  478.     register int    all;    /* <M-a> etc as well as <F1> etc */
  479. {
  480.     int        retval = 0;
  481.     char_u    *string;
  482.     int        c;
  483.     int        modifiers;
  484.  
  485.     set_highlight('8');
  486.     for (; *str; ++str)
  487.     {
  488.         c = *str;
  489.         if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
  490.         {
  491.             modifiers = 0x0;
  492.             if (str[1] == KS_MODIFIER)
  493.             {
  494.                 modifiers = str[2];
  495.                 str += 3;
  496.                 c = *str;
  497.             }
  498.             if (c == K_SPECIAL)
  499.             {
  500.                 c = TO_SPECIAL(str[1], str[2]);
  501.                 str += 2;
  502.                 if (c == K_ZERO)        /* display <Nul> as ^@ */
  503.                     c = NUL;
  504.             }
  505.             if (IS_SPECIAL(c) || modifiers)        /* special key */
  506.             {
  507.                 string = get_special_key_name(c, modifiers);
  508.                 start_highlight();
  509.                 msg_outstr(string);
  510.                 retval += STRLEN(string);
  511.                 stop_highlight();
  512.                 flushbuf();            /* Otherwise gets overwritten by spaces */
  513.                 continue;
  514.             }
  515.         }
  516.         if ((c & 0x80) && all)
  517.         {
  518.             string = get_special_key_name((c & 0x7f), MOD_MASK_ALT);
  519.             start_highlight();
  520.             msg_outstr(string);
  521.             retval += STRLEN(string);
  522.             stop_highlight();
  523.         }
  524.         else
  525.         {
  526.             msg_outstr(transchar(c));
  527.             retval += charsize(c);
  528.         }
  529.     }
  530.     return retval;
  531. }
  532.  
  533. /*
  534.  * print line for :p command
  535.  */
  536.     void
  537. msg_prt_line(s)
  538.     char_u           *s;
  539. {
  540.     register int    si = 0;
  541.     register int    c;
  542.     register int    col = 0;
  543.  
  544.     int             n_extra = 0;
  545.     int             n_spaces = 0;
  546.     char_u            *p = NULL;            /* init to make SASC shut up */
  547.     int             n;
  548.  
  549.     for (;;)
  550.     {
  551.         if (n_extra)
  552.         {
  553.             --n_extra;
  554.             c = *p++;
  555.         }
  556.         else if (n_spaces)
  557.         {
  558.             --n_spaces;
  559.             c = ' ';
  560.         }
  561.         else
  562.         {
  563.             c = s[si++];
  564.             if (c == TAB && !curwin->w_p_list)
  565.             {
  566.                 /* tab amount depends on current column */
  567.                 n_spaces = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
  568.                 c = ' ';
  569.             }
  570.             else if (c == NUL && curwin->w_p_list)
  571.             {
  572.                 p = (char_u *)"";
  573.                 n_extra = 1;
  574.                 c = '$';
  575.             }
  576.             else if (c != NUL && (n = charsize(c)) > 1)
  577.             {
  578.                 n_extra = n - 1;
  579.                 p = transchar(c);
  580.                 c = *p++;
  581.             }
  582.         }
  583.  
  584.         if (c == NUL)
  585.             break;
  586.  
  587.         msg_outchar(c);
  588.         col++;
  589.     }
  590. }
  591.  
  592. /*
  593.  * output a string to the screen at position msg_row, msg_col
  594.  * Update msg_row and msg_col for the next message.
  595.  */
  596.     void
  597. msg_outstr(s)
  598.     char_u        *s;
  599. {
  600.     int        oldState;
  601.     char_u    buf[20];
  602.  
  603.     /*
  604.      * If there is no valid screen, use fprintf so we can see error messages.
  605.      * If termcap is not active, we may be writing in an alternate console
  606.      * window, cursor positioning may not work correctly (window size may be
  607.      * different, e.g. for WIN32 console).
  608.      */
  609.     if (!msg_check_screen()
  610. #ifdef WIN32
  611.                             || !termcap_active
  612. #endif
  613.                                                 )
  614.     {
  615. #ifdef WIN32
  616.         mch_settmode(0);    /* cook so that \r and \n are handled correctly */
  617. #endif
  618.         fprintf(stderr, (char *)s);
  619.         msg_didout = TRUE;            /* assume that line is not empty */
  620. #ifdef WIN32
  621.         mch_settmode(1);
  622. #endif
  623.         return;
  624.     }
  625.  
  626.     msg_didany = TRUE;            /* remember that something was outputted */
  627.     while (*s)
  628.     {
  629.         /*
  630.          * The screen is scrolled up when:
  631.          * - When outputting a newline in the last row
  632.          * - when outputting a character in the last column of the last row
  633.          *   (some terminals scroll automatically, some don't. To avoid
  634.          *   problems we scroll ourselves)
  635.          */
  636.         if (msg_row >= Rows - 1 && (*s == '\n' || msg_col >= Columns - 1 ||
  637.                               (*s == TAB && msg_col >= ((Columns - 1) & ~7))))
  638.         {
  639.             screen_del_lines(0, 0, 1, (int)Rows, TRUE);    /* always works */
  640.             msg_row = Rows - 2;
  641.             if (msg_col >= Columns)        /* can happen after screen resize */
  642.                 msg_col = Columns - 1;
  643.             ++msg_scrolled;
  644.             need_wait_return = TRUE;    /* may need wait_return in main() */
  645.             if (cmdline_row > 0)
  646.                 --cmdline_row;
  647.             /*
  648.              * if screen is completely filled wait for a character
  649.              */
  650.             if (p_more && --lines_left == 0 && State != HITRETURN)
  651.             {
  652.                 oldState = State;
  653.                 State = ASKMORE;
  654. #ifdef USE_MOUSE
  655.                 setmouse();
  656. #endif
  657.                 msg_moremsg(FALSE);
  658.                 for (;;)
  659.                 {
  660.                     /*
  661.                      * Get a typed character directly from the user.
  662.                      * Don't use vgetc(), it syncs undo and eats mapped
  663.                      * characters.  Disadvantage: Special keys and mouse
  664.                      * cannot be used here, typeahead is ignored.
  665.                      */
  666.                     flushbuf();
  667.                     (void)mch_inchar(buf, 20, -1L);
  668.                     switch (buf[0])
  669.                     {
  670.                     case CR:            /* one extra line */
  671.                     case NL:
  672.                         lines_left = 1;
  673.                         break;
  674.                     case ':':            /* start new command line */
  675.                         stuffcharReadbuff(':');
  676.                         cmdline_row = Rows - 1;        /* put ':' on this line */
  677.                         skip_redraw = TRUE;            /* skip redraw once */
  678.                         dont_wait_return = TRUE;    /* don't wait in main() */
  679.                         /*FALLTHROUGH*/
  680.                     case 'q':            /* quit */
  681.                     case Ctrl('C'):
  682.                     case ESC:
  683.                         got_int = TRUE;
  684.                         quit_more = TRUE;
  685.                         break;
  686.                     case 'd':            /* Down half a page */
  687.                         lines_left = Rows / 2;
  688.                         break;
  689.                     case ' ':            /* one extra page */
  690.                         lines_left = Rows - 1;
  691.                         break;
  692.                     default:            /* no valid response */
  693.                         msg_moremsg(TRUE);
  694.                         continue;
  695.                     }
  696.                     break;
  697.                 }
  698.                 /* clear the --more-- message */
  699.                 screen_fill((int)Rows - 1, (int)Rows,
  700.                                                    0, (int)Columns, ' ', ' ');
  701.                 State = oldState;
  702. #ifdef USE_MOUSE
  703.                 setmouse();
  704. #endif
  705.                 if (quit_more)
  706.                 {
  707.                     msg_row = Rows - 1;
  708.                     msg_col = 0;
  709.                     return;            /* the string is not displayed! */
  710.                 }
  711.             }
  712.         }
  713.         if (*s == '\n')                /* go to next line */
  714.         {
  715.             msg_didout = FALSE;        /* remember that line is empty */
  716.             msg_col = 0;
  717.             if (++msg_row >= Rows)    /* safety check */
  718.                 msg_row = Rows - 1;
  719.         }
  720.         else if (*s == '\r')        /* go to column 0 */
  721.         {
  722.             msg_col = 0;
  723.         }
  724.         else if (*s == '\b')        /* go to previous char */
  725.         {
  726.             if (msg_col)
  727.                 --msg_col;
  728.         }
  729.         else if (*s == TAB)            /* translate into spaces */
  730.         {
  731.             do
  732.                 msg_screen_outchar(' ');
  733.             while (msg_col & 7);
  734.         }
  735.         else
  736.             msg_screen_outchar(*s);
  737.         ++s;
  738.     }
  739. }
  740.  
  741.     static void
  742. msg_screen_outchar(c)
  743.     int        c;
  744. {
  745.     msg_didout = TRUE;        /* remember that line is not empty */
  746.     screen_outchar(c, msg_row, msg_col);
  747.     if (++msg_col >= Columns)
  748.     {
  749.         msg_col = 0;
  750.         ++msg_row;
  751.     }
  752. }
  753.  
  754.     void
  755. msg_moremsg(full)
  756.     int        full;
  757. {
  758.     /*
  759.      * Need to restore old highlighting when we've finished with it
  760.      * because the output that's paging may be relying on it not
  761.      * changing -- webb
  762.      */
  763.     remember_highlight();
  764.     set_highlight('m');
  765.     start_highlight();
  766.     screen_msg((char_u *)"-- More --", (int)Rows - 1, 0);
  767.     if (full)
  768.         screen_msg((char_u *)" (RET: line, SPACE: page, d: half page, q: quit)",
  769.                                                            (int)Rows - 1, 10);
  770.     stop_highlight();
  771.     recover_old_highlight();
  772. }
  773.  
  774. /*
  775.  * msg_check_screen - check if the screen is initialized.
  776.  * Also check msg_row and msg_col, if they are too big it may cause a crash.
  777.  * While starting the GUI the terminal codes will be set for the GUI, but the
  778.  * output goes to the terminal.  Don't use the terminal codes then.
  779.  */
  780.     static int
  781. msg_check_screen()
  782. {
  783.     if (!full_screen || !screen_valid(FALSE))
  784.         return FALSE;
  785.     
  786.     if (msg_row >= Rows)
  787.         msg_row = Rows - 1;
  788.     if (msg_col >= Columns)
  789.         msg_col = Columns - 1;
  790.     return TRUE;
  791. }
  792.  
  793. /*
  794.  * clear from current message position to end of screen
  795.  * Note: msg_col is not updated, so we remember the end of the message
  796.  * for msg_check().
  797.  */
  798.     void
  799. msg_clr_eos()
  800. {
  801.     if (!msg_check_screen()
  802. #ifdef WIN32
  803.                             || !termcap_active
  804. #endif
  805.                                                 )
  806.         return;
  807.     screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ');
  808.     screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ');
  809. }
  810.  
  811. /*
  812.  * end putting a message on the screen
  813.  * call wait_return if the message does not fit in the available space
  814.  * return TRUE if wait_return not called.
  815.  */
  816.     int
  817. msg_end()
  818. {
  819.     /*
  820.      * if the string is larger than the window,
  821.      * or the ruler option is set and we run into it,
  822.      * we have to redraw the window.
  823.      * Do not do this if we are abandoning the file or editing the command line.
  824.      */
  825.     if (!exiting && msg_check() && State != CMDLINE)
  826.     {
  827.         wait_return(FALSE);
  828.         return FALSE;
  829.     }
  830.     flushbuf();
  831.     return TRUE;
  832. }
  833.  
  834. /*
  835.  * If the written message has caused the screen to scroll up, or if we
  836.  * run into the shown command or ruler, we have to redraw the window later.
  837.  */
  838.     int
  839. msg_check()
  840. {
  841.     if (msg_scrolled || (msg_row == Rows - 1 && msg_col >= sc_col))
  842.     {
  843.         redraw_later(NOT_VALID);
  844.         redraw_cmdline = TRUE;
  845.         return TRUE;
  846.     }
  847.     return FALSE;
  848. }
  849.