[BACK]Return to message.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vim

Annotation of src/usr.bin/vim/message.c, Revision 1.1.1.1

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