[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.2

1.2     ! downsj      1: /* $OpenBSD: message.c,v 1.1.1.1 1996/09/07 21:40:25 downsj Exp $  */
1.1       downsj      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"
1.2     ! downsj     19: #ifdef __QNX__
        !            20: # include <stdarg.h>
        !            21: #endif
1.1       downsj     22:
                     23: static void msg_screen_outchar __ARGS((int c));
                     24: static int msg_check_screen __ARGS((void));
                     25:
                     26: static int lines_left = -1;            /* lines left for listing */
                     27:
                     28: /*
                     29:  * msg(s) - displays the string 's' on the status line
                     30:  * When terminal not initialized (yet) fprintf(stderr,..) is used.
                     31:  * return TRUE if wait_return not called
                     32:  */
                     33:    int
                     34: msg(s)
                     35:    char_u         *s;
                     36: {
                     37:    msg_start();
                     38:    if (msg_highlight)
                     39:        start_highlight();
                     40:    msg_outtrans(s);
                     41:    if (msg_highlight)
                     42:    {
                     43:        stop_highlight();
                     44:        msg_highlight = FALSE;      /* clear for next call */
                     45:    }
                     46:    msg_clr_eos();
                     47:    return msg_end();
                     48: }
                     49:
                     50: /*
                     51:  * automatic prototype generation does not understand this function
                     52:  */
                     53: #ifndef PROTO
1.2     ! downsj     54: #ifndef __QNX__
1.1       downsj     55: int smsg __ARGS((char_u *, long, long, long,
                     56:                        long, long, long, long, long, long, long));
                     57:
                     58: /* VARARGS */
                     59:    int
                     60: smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
                     61:    char_u      *s;
                     62:    long        a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
                     63: {
                     64:    sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
                     65:    return msg(IObuff);
                     66: }
1.2     ! downsj     67: #else /* __QNX__ */
        !            68: void smsg(char_u *s, ...)
        !            69: {
        !            70:    va_list arglist;
        !            71:    va_start(arglist, s);
        !            72:    vsprintf((char *)IObuff, (char *)s, arglist);
        !            73:    va_end(arglist);
        !            74:    msg(IObuff);
        !            75: }
        !            76: #endif /* __QNX__ */
1.1       downsj     77: #endif
                     78:
                     79: /*
                     80:  * emsg() - display an error message
                     81:  *
                     82:  * Rings the bell, if appropriate, and calls message() to do the real work
                     83:  * When terminal not initialized (yet) fprintf(stderr,..) is used.
                     84:  *
                     85:  * return TRUE if wait_return not called
                     86:  */
                     87:    int
                     88: emsg(s)
                     89:    char_u         *s;
                     90: {
                     91:    char_u          *Buf;
                     92: #ifdef SLEEP_IN_EMSG
                     93:    int             retval;
                     94: #endif
                     95:    static int      last_lnum = 0;
                     96:    static char_u   *last_sourcing_name = NULL;
                     97:
                     98:    if (emsg_off)               /* no error messages at the moment */
                     99:        return TRUE;
                    100:
                    101:    if (global_busy)            /* break :global command */
                    102:        ++global_busy;
                    103:
                    104:    if (p_eb)
                    105:        beep_flush();           /* also includes flush_buffers() */
                    106:    else
                    107:        flush_buffers(FALSE);   /* flush internal buffers */
                    108:    did_emsg = TRUE;            /* flag for DoOneCmd() */
                    109:    ++msg_scroll;               /* don't overwrite a previous message */
                    110:    (void)set_highlight('e');   /* set highlight mode for error messages */
                    111:    msg_highlight = TRUE;
                    112:    if (msg_scrolled)
                    113:        need_wait_return = TRUE;    /* needed in case emsg() is called after
                    114:                                     * wait_return has reset need_wait_return
                    115:                                     * and a redraw is expected because
                    116:                                     * msg_scrolled is non-zero */
                    117:
                    118: /*
                    119:  * First output name and line number of source of error message
                    120:  */
                    121:    if (sourcing_name != NULL &&
                    122:           (sourcing_name != last_sourcing_name || sourcing_lnum != last_lnum)
                    123:                                      && (Buf = alloc(MAXPATHL + 30)) != NULL)
                    124:    {
                    125:        ++no_wait_return;
                    126:        if (sourcing_name != last_sourcing_name)
                    127:        {
                    128:            sprintf((char *)Buf, "Error detected while processing %s:",
                    129:                                            sourcing_name);
                    130:            msg(Buf);
                    131:            msg_highlight = TRUE;
                    132:        }
                    133:            /* lnum is 0 when executing a command from the command line
                    134:             * argument, we don't want a line number then */
                    135:        if (sourcing_lnum != 0)
                    136:        {
                    137:            (void)set_highlight('n');   /* highlight mode for line numbers */
                    138:            sprintf((char *)Buf, "line %4ld:", sourcing_lnum);
                    139:            msg(Buf);
                    140:            (void)set_highlight('e');   /* highlight mode for error messages */
                    141:            msg_highlight = TRUE;
                    142:        }
                    143:        --no_wait_return;
                    144:        last_lnum = sourcing_lnum;  /* only once for each line */
                    145:        vim_free(Buf);
                    146:    }
                    147:    last_sourcing_name = sourcing_name; /* do this also when it is NULL */
                    148:
                    149: #ifdef SLEEP_IN_EMSG
                    150: /*
                    151:  * Msg returns TRUE if wait_return() was not called.
                    152:  * In that case may call sleep() to give the user a chance to read the message.
                    153:  * Don't call sleep() if dont_sleep is set.
                    154:  */
                    155:    retval = msg(s);
                    156:    if (retval)
                    157:    {
                    158:        if (dont_sleep || need_wait_return)
                    159:            need_sleep = TRUE;  /* sleep before removing the message */
                    160:        else
                    161:            mch_delay(1000L, TRUE); /* give user chance to read message */
                    162:    }
                    163:    /* --msg_scroll;            don't overwrite this message */
                    164:    return retval;
                    165: #else
                    166:    emsg_on_display = TRUE;     /* remember there is an error message */
                    167:    return msg(s);
                    168: #endif
                    169: }
                    170:
                    171:    int
                    172: emsg2(s, a1)
                    173:    char_u *s, *a1;
                    174: {
                    175:    /* Check for NULL strings (just in case) */
                    176:    if (a1 == NULL)
                    177:        a1 = (char_u *)"[NULL]";
                    178:    /* Check for very long strings (can happen with ":help ^A<CR>") */
1.2     ! downsj    179:    if (STRLEN(s) + STRLEN(a1) >= (size_t)IOSIZE)
1.1       downsj    180:        a1 = (char_u *)"[string too long]";
                    181:    sprintf((char *)IObuff, (char *)s, (char *)a1);
                    182:    return emsg(IObuff);
                    183: }
                    184:
                    185:    int
                    186: emsgn(s, n)
                    187:    char_u *s;
                    188:    long    n;
                    189: {
                    190:    sprintf((char *)IObuff, (char *)s, n);
                    191:    return emsg(IObuff);
                    192: }
                    193:
                    194: /*
                    195:  * Like msg(), but truncate to a single line if p_shm contains 't'.
                    196:  * Careful: The string may be changed!
                    197:  */
                    198:    int
                    199: msg_trunc(s)
                    200:    char_u  *s;
                    201: {
                    202:    int     n;
                    203:
                    204:    if (shortmess(SHM_TRUNC) && (n = (int)STRLEN(s) -
                    205:                    (int)(Rows - cmdline_row - 1) * Columns - sc_col + 1) > 0)
                    206:    {
                    207:        s[n] = '<';
                    208:        return msg(s + n);
                    209:    }
                    210:    else
                    211:        return msg(s);
                    212: }
                    213:
                    214: /*
                    215:  * wait for the user to hit a key (normally a return)
                    216:  * if 'redraw' is TRUE, clear and redraw the screen
                    217:  * if 'redraw' is FALSE, just redraw the screen
                    218:  * if 'redraw' is -1, don't redraw at all
                    219:  */
                    220:    void
                    221: wait_return(redraw)
                    222:    int     redraw;
                    223: {
                    224:    int             c;
                    225:    int             oldState;
                    226:    int             tmpState;
                    227:
                    228:    if (redraw == TRUE)
                    229:        must_redraw = CLEAR;
                    230:
                    231: /*
                    232:  * With the global command (and some others) we only need one return at the
                    233:  * end. Adjust cmdline_row to avoid the next message overwriting the last one.
                    234:  */
                    235:    if (no_wait_return)
                    236:    {
                    237:        need_wait_return = TRUE;
                    238:        cmdline_row = msg_row;
                    239:        return;
                    240:    }
                    241:    oldState = State;
                    242:    if (quit_more)
                    243:    {
                    244:        c = CR;                     /* just pretend CR was hit */
                    245:        quit_more = FALSE;
                    246:        got_int = FALSE;
                    247:    }
                    248:    else
                    249:    {
                    250:        State = HITRETURN;
                    251: #ifdef USE_MOUSE
                    252:        setmouse();
                    253: #endif
                    254:        if (msg_didout)             /* start on a new line */
                    255:            msg_outchar('\n');
                    256:        if (got_int)
                    257:            MSG_OUTSTR("Interrupt: ");
                    258:
                    259:        (void)set_highlight('r');
                    260:        start_highlight();
                    261: #ifdef ORG_HITRETURN
                    262:        MSG_OUTSTR("Press RETURN to continue");
                    263:        stop_highlight();
                    264:        do {
                    265:            c = vgetc();
                    266:        } while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
                    267:        if (c == ':')                   /* this can vi too (but not always!) */
                    268:            stuffcharReadbuff(c);
                    269: #else
                    270:        MSG_OUTSTR("Press RETURN or enter command to continue");
                    271:        stop_highlight();
                    272:        do
                    273:        {
                    274:            c = vgetc();
                    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:            start_highlight();
                    519:            MSG_OUTSTR("<M-");
                    520:            msg_outstr(transchar(c & 0x7f));
                    521:            retval += 2 + charsize(c & 0x7f);
                    522:            MSG_OUTSTR(">");
                    523:            stop_highlight();
                    524:        }
                    525:        else
                    526:        {
                    527:            msg_outstr(transchar(c));
                    528:            retval += charsize(c);
                    529:        }
                    530:    }
                    531:    return retval;
                    532: }
                    533:
                    534: /*
                    535:  * print line for :p command
                    536:  */
                    537:    void
                    538: msg_prt_line(s)
                    539:    char_u         *s;
                    540: {
                    541:    register int    si = 0;
                    542:    register int    c;
                    543:    register int    col = 0;
                    544:
                    545:    int             n_extra = 0;
                    546:    int             n_spaces = 0;
                    547:    char_u          *p = NULL;          /* init to make SASC shut up */
                    548:    int             n;
                    549:
                    550:    for (;;)
                    551:    {
                    552:        if (n_extra)
                    553:        {
                    554:            --n_extra;
                    555:            c = *p++;
                    556:        }
                    557:        else if (n_spaces)
                    558:        {
                    559:            --n_spaces;
                    560:            c = ' ';
                    561:        }
                    562:        else
                    563:        {
                    564:            c = s[si++];
                    565:            if (c == TAB && !curwin->w_p_list)
                    566:            {
                    567:                /* tab amount depends on current column */
                    568:                n_spaces = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
                    569:                c = ' ';
                    570:            }
                    571:            else if (c == NUL && curwin->w_p_list)
                    572:            {
                    573:                p = (char_u *)"";
                    574:                n_extra = 1;
                    575:                c = '$';
                    576:            }
                    577:            else if (c != NUL && (n = charsize(c)) > 1)
                    578:            {
                    579:                n_extra = n - 1;
                    580:                p = transchar(c);
                    581:                c = *p++;
                    582:            }
                    583:        }
                    584:
                    585:        if (c == NUL)
                    586:            break;
                    587:
                    588:        msg_outchar(c);
                    589:        col++;
                    590:    }
                    591: }
                    592:
                    593: /*
                    594:  * output a string to the screen at position msg_row, msg_col
                    595:  * Update msg_row and msg_col for the next message.
                    596:  */
                    597:    void
                    598: msg_outstr(s)
                    599:    char_u      *s;
                    600: {
                    601:    int     oldState;
                    602:    char_u  buf[20];
                    603:
                    604:    /*
                    605:     * If there is no valid screen, use fprintf so we can see error messages.
                    606:     * If termcap is not active, we may be writing in an alternate console
                    607:     * window, cursor positioning may not work correctly (window size may be
                    608:     * different, e.g. for WIN32 console).
                    609:     */
                    610:    if (!msg_check_screen()
                    611: #ifdef WIN32
                    612:                            || !termcap_active
                    613: #endif
                    614:                                                )
                    615:    {
                    616: #ifdef WIN32
                    617:        mch_settmode(0);    /* cook so that \r and \n are handled correctly */
                    618: #endif
                    619:        fprintf(stderr, (char *)s);
                    620:        msg_didout = TRUE;          /* assume that line is not empty */
                    621: #ifdef WIN32
                    622:        mch_settmode(1);
                    623: #endif
                    624:        return;
                    625:    }
                    626:
                    627:    msg_didany = TRUE;          /* remember that something was outputted */
                    628:    while (*s)
                    629:    {
                    630:        /*
                    631:         * The screen is scrolled up when:
                    632:         * - When outputting a newline in the last row
                    633:         * - when outputting a character in the last column of the last row
                    634:         *   (some terminals scroll automatically, some don't. To avoid
                    635:         *   problems we scroll ourselves)
                    636:         */
                    637:        if (msg_row >= Rows - 1 && (*s == '\n' || msg_col >= Columns - 1 ||
                    638:                              (*s == TAB && msg_col >= ((Columns - 1) & ~7))))
                    639:        {
                    640:            screen_del_lines(0, 0, 1, (int)Rows, TRUE); /* always works */
                    641:            msg_row = Rows - 2;
                    642:            if (msg_col >= Columns)     /* can happen after screen resize */
                    643:                msg_col = Columns - 1;
                    644:            ++msg_scrolled;
                    645:            need_wait_return = TRUE;    /* may need wait_return in main() */
                    646:            if (cmdline_row > 0)
                    647:                --cmdline_row;
                    648:            /*
                    649:             * if screen is completely filled wait for a character
                    650:             */
                    651:            if (p_more && --lines_left == 0 && State != HITRETURN)
                    652:            {
                    653:                oldState = State;
                    654:                State = ASKMORE;
                    655: #ifdef USE_MOUSE
                    656:                setmouse();
                    657: #endif
                    658:                msg_moremsg(FALSE);
                    659:                for (;;)
                    660:                {
                    661:                    /*
                    662:                     * Get a typed character directly from the user.
                    663:                     * Don't use vgetc(), it syncs undo and eats mapped
                    664:                     * characters.  Disadvantage: Special keys and mouse
                    665:                     * cannot be used here, typeahead is ignored.
                    666:                     */
                    667:                    flushbuf();
                    668:                    (void)mch_inchar(buf, 20, -1L);
                    669:                    switch (buf[0])
                    670:                    {
                    671:                    case CR:            /* one extra line */
                    672:                    case NL:
                    673:                        lines_left = 1;
                    674:                        break;
                    675:                    case ':':           /* start new command line */
                    676:                        stuffcharReadbuff(':');
                    677:                        cmdline_row = Rows - 1;     /* put ':' on this line */
                    678:                        skip_redraw = TRUE;         /* skip redraw once */
                    679:                        dont_wait_return = TRUE;    /* don't wait in main() */
                    680:                        /*FALLTHROUGH*/
                    681:                    case 'q':           /* quit */
                    682:                    case Ctrl('C'):
                    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:  */
                    778:    static int
                    779: msg_check_screen()
                    780: {
                    781:    if (!full_screen || !screen_valid(FALSE))
                    782:        return FALSE;
                    783:
                    784:    if (msg_row >= Rows)
                    785:        msg_row = Rows - 1;
                    786:    if (msg_col >= Columns)
                    787:        msg_col = Columns - 1;
                    788:    return TRUE;
                    789: }
                    790:
                    791: /*
                    792:  * clear from current message position to end of screen
                    793:  * Note: msg_col is not updated, so we remember the end of the message
                    794:  * for msg_check().
                    795:  */
                    796:    void
                    797: msg_clr_eos()
                    798: {
                    799:    if (!msg_check_screen()
                    800: #ifdef WIN32
                    801:                            || !termcap_active
                    802: #endif
                    803:                                                )
                    804:        return;
                    805:    screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ');
                    806:    screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ');
                    807: }
                    808:
                    809: /*
                    810:  * end putting a message on the screen
                    811:  * call wait_return if the message does not fit in the available space
                    812:  * return TRUE if wait_return not called.
                    813:  */
                    814:    int
                    815: msg_end()
                    816: {
                    817:    /*
                    818:     * if the string is larger than the window,
                    819:     * or the ruler option is set and we run into it,
                    820:     * we have to redraw the window.
                    821:     * Do not do this if we are abandoning the file or editing the command line.
                    822:     */
                    823:    if (!exiting && msg_check() && State != CMDLINE)
                    824:    {
                    825:        wait_return(FALSE);
                    826:        return FALSE;
                    827:    }
                    828:    flushbuf();
                    829:    return TRUE;
                    830: }
                    831:
                    832: /*
                    833:  * If the written message has caused the screen to scroll up, or if we
                    834:  * run into the shown command or ruler, we have to redraw the window later.
                    835:  */
                    836:    int
                    837: msg_check()
                    838: {
                    839:    if (msg_scrolled || (msg_row == Rows - 1 && msg_col >= sc_col))
                    840:    {
                    841:        redraw_later(NOT_VALID);
                    842:        redraw_cmdline = TRUE;
                    843:        return TRUE;
                    844:    }
                    845:    return FALSE;
                    846: }