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

1.3     ! downsj      1: /* $OpenBSD: message.c,v 1.2 1996/09/21 06:23:09 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:
1.3     ! downsj     26: /* lines_left moved to globals so do_exmode could see it */
1.1       downsj     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:    }
1.3     ! downsj    248:    else if (exmode_active)
        !           249:    {
        !           250:        MSG_OUTSTR(" ");    /* make sure the cursor is on the right line */
        !           251:        c = CR;                     /* no need for a return in ex mode */
        !           252:        got_int = FALSE;
        !           253:    }
1.1       downsj    254:    else
                    255:    {
                    256:        State = HITRETURN;
                    257: #ifdef USE_MOUSE
                    258:        setmouse();
                    259: #endif
                    260:        if (msg_didout)             /* start on a new line */
                    261:            msg_outchar('\n');
                    262:        if (got_int)
                    263:            MSG_OUTSTR("Interrupt: ");
                    264:
                    265:        (void)set_highlight('r');
                    266:        start_highlight();
                    267: #ifdef ORG_HITRETURN
                    268:        MSG_OUTSTR("Press RETURN to continue");
                    269:        stop_highlight();
                    270:        do {
                    271:            c = vgetc();
                    272:        } while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
                    273:        if (c == ':')                   /* this can vi too (but not always!) */
                    274:            stuffcharReadbuff(c);
                    275: #else
                    276:        MSG_OUTSTR("Press RETURN or enter command to continue");
                    277:        stop_highlight();
                    278:        do
                    279:        {
                    280:            c = vgetc();
                    281:            got_int = FALSE;
                    282:        } while (c == Ctrl('C')
                    283: #ifdef USE_GUI
                    284:                                || c == K_SCROLLBAR || c == K_HORIZ_SCROLLBAR
                    285: #endif
                    286: #ifdef USE_MOUSE
                    287:                                || c == K_LEFTDRAG   || c == K_LEFTRELEASE
                    288:                                || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
                    289:                                || c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
                    290:                                || c == K_IGNORE     ||
                    291:                                (!mouse_has(MOUSE_RETURN) &&
                    292:                                     (c == K_LEFTMOUSE ||
                    293:                                      c == K_MIDDLEMOUSE ||
                    294:                                      c == K_RIGHTMOUSE))
                    295: #endif
                    296:                                );
                    297:        mch_breakcheck();
                    298: #ifdef USE_MOUSE
                    299:        /*
                    300:         * Avoid that the mouse-up event causes visual mode to start.
                    301:         */
                    302:        if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE)
                    303:            jump_to_mouse(MOUSE_SETPOS);
                    304:        else
                    305: #endif
                    306:            if (vim_strchr((char_u *)"\r\n ", c) == NULL)
                    307:        {
                    308:            stuffcharReadbuff(c);
                    309:            do_redraw = TRUE;       /* need a redraw even though there is
                    310:                                       something in the stuff buffer */
                    311:        }
                    312: #endif
                    313:    }
                    314:
                    315:    /*
                    316:     * If the user hits ':', '?' or '/' we get a command line from the next
                    317:     * line.
                    318:     */
                    319:    if (c == ':' || c == '?' || c == '/')
                    320:    {
                    321:        cmdline_row = msg_row;
                    322:        skip_redraw = TRUE;         /* skip redraw once */
                    323:        do_redraw = FALSE;
                    324:    }
                    325:
                    326: /*
                    327:  * If the window size changed set_winsize() will redraw the screen.
                    328:  * Otherwise the screen is only redrawn if 'redraw' is set and no ':' typed.
                    329:  */
                    330:    tmpState = State;
                    331:    State = oldState;               /* restore State before set_winsize */
                    332: #ifdef USE_MOUSE
                    333:    setmouse();
                    334: #endif
                    335:    msg_check();
                    336:
                    337:    need_wait_return = FALSE;
                    338:    emsg_on_display = FALSE;    /* can delete error message now */
                    339: #ifdef SLEEP_IN_EMSG
                    340:    need_sleep = FALSE;         /* no need to call sleep() anymore */
                    341: #endif
                    342:    msg_didany = FALSE;         /* reset lines_left at next msg_start() */
                    343:    lines_left = -1;
                    344:    if (keep_msg != NULL && linetabsize(keep_msg) >=
                    345:                                  (Rows - cmdline_row - 1) * Columns + sc_col)
                    346:        keep_msg = NULL;            /* don't redisplay message, it's too long */
                    347:
                    348:    if (tmpState == SETWSIZE)       /* got resize event while in vgetc() */
                    349:    {
                    350:        starttermcap();             /* start termcap before redrawing */
                    351:        set_winsize(0, 0, FALSE);
                    352:    }
                    353:    else if (!skip_redraw && (redraw == TRUE || (msg_scrolled && redraw != -1)))
                    354:    {
                    355:        starttermcap();             /* start termcap before redrawing */
                    356:        updateScreen(VALID);
                    357:    }
                    358:
                    359:    dont_wait_return = TRUE;        /* don't wait again in main() */
                    360: }
                    361:
                    362: /*
                    363:  * Prepare for outputting characters in the command line.
                    364:  */
                    365:    void
                    366: msg_start()
                    367: {
                    368:    keep_msg = NULL;                        /* don't display old message now */
                    369:    keep_msg_highlight = 0;
                    370:    if (!msg_scroll && full_screen)         /* overwrite last message */
                    371:        msg_pos(cmdline_row, 0);
                    372:    else if (msg_didout)                    /* start message on next line */
                    373:    {
                    374:        msg_outchar('\n');
                    375:        cmdline_row = msg_row;
                    376:    }
                    377:    if (!msg_didany)
                    378:        lines_left = cmdline_row;
                    379:    msg_didout = FALSE;                     /* no output on current line yet */
                    380:    cursor_off();
                    381: }
                    382:
                    383: /*
                    384:  * Move message position. This should always be used after moving the cursor.
                    385:  * Use negative value if row or col does not have to be changed.
                    386:  */
                    387:    void
                    388: msg_pos(row, col)
                    389:    int     row, col;
                    390: {
                    391:    if (row >= 0)
                    392:        msg_row = row;
                    393:    if (col >= 0)
                    394:        msg_col = col;
                    395: }
                    396:
                    397:    void
                    398: msg_outchar(c)
                    399:    int     c;
                    400: {
                    401:    char_u      buf[4];
                    402:
                    403:    if (IS_SPECIAL(c))
                    404:    {
                    405:        buf[0] = K_SPECIAL;
                    406:        buf[1] = K_SECOND(c);
                    407:        buf[2] = K_THIRD(c);
                    408:        buf[3] = NUL;
                    409:    }
                    410:    else
                    411:    {
                    412:        buf[0] = c;
                    413:        buf[1] = NUL;
                    414:    }
                    415:    msg_outstr(buf);
                    416: }
                    417:
                    418:    void
                    419: msg_outnum(n)
                    420:    long        n;
                    421: {
                    422:    char_u      buf[20];
                    423:
                    424:    sprintf((char *)buf, "%ld", n);
                    425:    msg_outstr(buf);
                    426: }
                    427:
                    428:    void
                    429: msg_home_replace(fname)
                    430:    char_u  *fname;
                    431: {
                    432:    char_u      *name;
                    433:
                    434:    name = home_replace_save(NULL, fname);
                    435:    if (name != NULL)
                    436:        msg_outtrans(name);
                    437:    vim_free(name);
                    438: }
                    439:
                    440: /*
                    441:  * output 'len' characters in 'str' (including NULs) with translation
                    442:  * if 'len' is -1, output upto a NUL character
                    443:  * return the number of characters it takes on the screen
                    444:  */
                    445:    int
                    446: msg_outtrans(str)
                    447:    register char_u *str;
                    448: {
                    449:    return msg_outtrans_len(str, (int)STRLEN(str));
                    450: }
                    451:
                    452:    int
                    453: msg_outtrans_len(str, len)
                    454:    register char_u *str;
                    455:    register int   len;
                    456: {
                    457:    int retval = 0;
                    458:
                    459:    while (--len >= 0)
                    460:    {
                    461:        msg_outstr(transchar(*str));
                    462:        retval += charsize(*str);
                    463:        ++str;
                    464:    }
                    465:    return retval;
                    466: }
                    467:
                    468: /*
                    469:  * Output the string 'str' upto a NUL character.
                    470:  * Return the number of characters it takes on the screen.
                    471:  *
                    472:  * If K_SPECIAL is encountered, then it is taken in conjunction with the
                    473:  * following character and shown as <F1>, <S-Up> etc.  In addition, if 'all'
                    474:  * is TRUE, then any other character which has its 8th bit set is shown as
                    475:  * <M-x>, where x is the equivalent character without its 8th bit set.  If a
                    476:  * character is displayed in one of these special ways, is also highlighted
                    477:  * (its highlight name is '8' in the p_hl variable).
                    478:  * This function is used to show mappings, where we want to see how to type
                    479:  * the character/string -- webb
                    480:  */
                    481:    int
                    482: msg_outtrans_special(str, all)
                    483:    register char_u *str;
                    484:    register int    all;    /* <M-a> etc as well as <F1> etc */
                    485: {
                    486:    int     retval = 0;
                    487:    char_u  *string;
                    488:    int     c;
                    489:    int     modifiers;
                    490:
                    491:    set_highlight('8');
                    492:    for (; *str; ++str)
                    493:    {
                    494:        c = *str;
                    495:        if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
                    496:        {
                    497:            modifiers = 0x0;
                    498:            if (str[1] == KS_MODIFIER)
                    499:            {
                    500:                modifiers = str[2];
                    501:                str += 3;
                    502:                c = *str;
                    503:            }
                    504:            if (c == K_SPECIAL)
                    505:            {
                    506:                c = TO_SPECIAL(str[1], str[2]);
                    507:                str += 2;
                    508:                if (c == K_ZERO)        /* display <Nul> as ^@ */
                    509:                    c = NUL;
                    510:            }
                    511:            if (IS_SPECIAL(c) || modifiers)     /* special key */
                    512:            {
                    513:                string = get_special_key_name(c, modifiers);
                    514:                start_highlight();
                    515:                msg_outstr(string);
                    516:                retval += STRLEN(string);
                    517:                stop_highlight();
                    518:                flushbuf();         /* Otherwise gets overwritten by spaces */
                    519:                continue;
                    520:            }
                    521:        }
                    522:        if ((c & 0x80) && all)
                    523:        {
                    524:            start_highlight();
                    525:            MSG_OUTSTR("<M-");
                    526:            msg_outstr(transchar(c & 0x7f));
                    527:            retval += 2 + charsize(c & 0x7f);
                    528:            MSG_OUTSTR(">");
                    529:            stop_highlight();
                    530:        }
                    531:        else
                    532:        {
                    533:            msg_outstr(transchar(c));
                    534:            retval += charsize(c);
                    535:        }
                    536:    }
                    537:    return retval;
                    538: }
                    539:
                    540: /*
                    541:  * print line for :p command
                    542:  */
                    543:    void
                    544: msg_prt_line(s)
                    545:    char_u         *s;
                    546: {
                    547:    register int    si = 0;
                    548:    register int    c;
                    549:    register int    col = 0;
                    550:
                    551:    int             n_extra = 0;
                    552:    int             n_spaces = 0;
                    553:    char_u          *p = NULL;          /* init to make SASC shut up */
                    554:    int             n;
1.3     ! downsj    555:
        !           556:    /*
        !           557:     * if it's a blank line, echo a space, because otherwise if we're
        !           558:     * in ex mode, the : for the next command will end up on the wrong
        !           559:     * line.  I don't know why -- hooray for cargo cult programming!
        !           560:     */
        !           561:
        !           562:    if (*s == 0) {
        !           563:        msg_outchar(' ');
        !           564:    }
1.1       downsj    565:
                    566:    for (;;)
                    567:    {
                    568:        if (n_extra)
                    569:        {
                    570:            --n_extra;
                    571:            c = *p++;
                    572:        }
                    573:        else if (n_spaces)
                    574:        {
                    575:            --n_spaces;
                    576:            c = ' ';
                    577:        }
                    578:        else
                    579:        {
                    580:            c = s[si++];
                    581:            if (c == TAB && !curwin->w_p_list)
                    582:            {
                    583:                /* tab amount depends on current column */
                    584:                n_spaces = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
                    585:                c = ' ';
                    586:            }
                    587:            else if (c == NUL && curwin->w_p_list)
                    588:            {
                    589:                p = (char_u *)"";
                    590:                n_extra = 1;
                    591:                c = '$';
                    592:            }
                    593:            else if (c != NUL && (n = charsize(c)) > 1)
                    594:            {
                    595:                n_extra = n - 1;
                    596:                p = transchar(c);
                    597:                c = *p++;
                    598:            }
                    599:        }
                    600:
                    601:        if (c == NUL)
                    602:            break;
                    603:
                    604:        msg_outchar(c);
                    605:        col++;
                    606:    }
                    607: }
                    608:
                    609: /*
                    610:  * output a string to the screen at position msg_row, msg_col
                    611:  * Update msg_row and msg_col for the next message.
                    612:  */
                    613:    void
                    614: msg_outstr(s)
                    615:    char_u      *s;
                    616: {
                    617:    int     oldState;
                    618:    char_u  buf[20];
                    619:
                    620:    /*
                    621:     * If there is no valid screen, use fprintf so we can see error messages.
                    622:     * If termcap is not active, we may be writing in an alternate console
                    623:     * window, cursor positioning may not work correctly (window size may be
                    624:     * different, e.g. for WIN32 console).
                    625:     */
                    626:    if (!msg_check_screen()
                    627: #ifdef WIN32
                    628:                            || !termcap_active
                    629: #endif
                    630:                                                )
                    631:    {
                    632: #ifdef WIN32
                    633:        mch_settmode(0);    /* cook so that \r and \n are handled correctly */
                    634: #endif
                    635:        fprintf(stderr, (char *)s);
                    636:        msg_didout = TRUE;          /* assume that line is not empty */
                    637: #ifdef WIN32
                    638:        mch_settmode(1);
                    639: #endif
                    640:        return;
                    641:    }
                    642:
                    643:    msg_didany = TRUE;          /* remember that something was outputted */
                    644:    while (*s)
                    645:    {
                    646:        /*
                    647:         * The screen is scrolled up when:
                    648:         * - When outputting a newline in the last row
                    649:         * - when outputting a character in the last column of the last row
                    650:         *   (some terminals scroll automatically, some don't. To avoid
                    651:         *   problems we scroll ourselves)
                    652:         */
                    653:        if (msg_row >= Rows - 1 && (*s == '\n' || msg_col >= Columns - 1 ||
                    654:                              (*s == TAB && msg_col >= ((Columns - 1) & ~7))))
                    655:        {
                    656:            screen_del_lines(0, 0, 1, (int)Rows, TRUE); /* always works */
                    657:            msg_row = Rows - 2;
                    658:            if (msg_col >= Columns)     /* can happen after screen resize */
                    659:                msg_col = Columns - 1;
                    660:            ++msg_scrolled;
                    661:            need_wait_return = TRUE;    /* may need wait_return in main() */
                    662:            if (cmdline_row > 0)
                    663:                --cmdline_row;
                    664:            /*
                    665:             * if screen is completely filled wait for a character
                    666:             */
                    667:            if (p_more && --lines_left == 0 && State != HITRETURN)
                    668:            {
                    669:                oldState = State;
                    670:                State = ASKMORE;
                    671: #ifdef USE_MOUSE
                    672:                setmouse();
                    673: #endif
                    674:                msg_moremsg(FALSE);
                    675:                for (;;)
                    676:                {
                    677:                    /*
                    678:                     * Get a typed character directly from the user.
                    679:                     * Don't use vgetc(), it syncs undo and eats mapped
                    680:                     * characters.  Disadvantage: Special keys and mouse
                    681:                     * cannot be used here, typeahead is ignored.
                    682:                     */
                    683:                    flushbuf();
                    684:                    (void)mch_inchar(buf, 20, -1L);
                    685:                    switch (buf[0])
                    686:                    {
                    687:                    case CR:            /* one extra line */
                    688:                    case NL:
                    689:                        lines_left = 1;
                    690:                        break;
                    691:                    case ':':           /* start new command line */
                    692:                        stuffcharReadbuff(':');
                    693:                        cmdline_row = Rows - 1;     /* put ':' on this line */
                    694:                        skip_redraw = TRUE;         /* skip redraw once */
                    695:                        dont_wait_return = TRUE;    /* don't wait in main() */
                    696:                        /*FALLTHROUGH*/
                    697:                    case 'q':           /* quit */
                    698:                    case Ctrl('C'):
                    699:                        got_int = TRUE;
                    700:                        quit_more = TRUE;
                    701:                        break;
                    702:                    case 'd':           /* Down half a page */
                    703:                        lines_left = Rows / 2;
                    704:                        break;
                    705:                    case ' ':           /* one extra page */
                    706:                        lines_left = Rows - 1;
                    707:                        break;
                    708:                    default:            /* no valid response */
                    709:                        msg_moremsg(TRUE);
                    710:                        continue;
                    711:                    }
                    712:                    break;
                    713:                }
                    714:                /* clear the --more-- message */
                    715:                screen_fill((int)Rows - 1, (int)Rows,
                    716:                                                   0, (int)Columns, ' ', ' ');
                    717:                State = oldState;
                    718: #ifdef USE_MOUSE
                    719:                setmouse();
                    720: #endif
                    721:                if (quit_more)
                    722:                {
                    723:                    msg_row = Rows - 1;
                    724:                    msg_col = 0;
                    725:                    return;         /* the string is not displayed! */
                    726:                }
                    727:            }
                    728:        }
                    729:        if (*s == '\n')             /* go to next line */
                    730:        {
                    731:            msg_didout = FALSE;     /* remember that line is empty */
                    732:            msg_col = 0;
                    733:            if (++msg_row >= Rows)  /* safety check */
                    734:                msg_row = Rows - 1;
                    735:        }
                    736:        else if (*s == '\r')        /* go to column 0 */
                    737:        {
                    738:            msg_col = 0;
                    739:        }
                    740:        else if (*s == '\b')        /* go to previous char */
                    741:        {
                    742:            if (msg_col)
                    743:                --msg_col;
                    744:        }
                    745:        else if (*s == TAB)         /* translate into spaces */
                    746:        {
                    747:            do
                    748:                msg_screen_outchar(' ');
                    749:            while (msg_col & 7);
                    750:        }
                    751:        else
                    752:            msg_screen_outchar(*s);
                    753:        ++s;
                    754:    }
                    755: }
                    756:
                    757:    static void
                    758: msg_screen_outchar(c)
                    759:    int     c;
                    760: {
                    761:    msg_didout = TRUE;      /* remember that line is not empty */
                    762:    screen_outchar(c, msg_row, msg_col);
                    763:    if (++msg_col >= Columns)
                    764:    {
                    765:        msg_col = 0;
                    766:        ++msg_row;
                    767:    }
                    768: }
                    769:
                    770:    void
                    771: msg_moremsg(full)
                    772:    int     full;
                    773: {
                    774:    /*
                    775:     * Need to restore old highlighting when we've finished with it
                    776:     * because the output that's paging may be relying on it not
                    777:     * changing -- webb
                    778:     */
                    779:    remember_highlight();
                    780:    set_highlight('m');
                    781:    start_highlight();
                    782:    screen_msg((char_u *)"-- More --", (int)Rows - 1, 0);
                    783:    if (full)
                    784:        screen_msg((char_u *)" (RET: line, SPACE: page, d: half page, q: quit)",
                    785:                                                           (int)Rows - 1, 10);
                    786:    stop_highlight();
                    787:    recover_old_highlight();
                    788: }
                    789:
                    790: /*
                    791:  * msg_check_screen - check if the screen is initialized.
                    792:  * Also check msg_row and msg_col, if they are too big it may cause a crash.
                    793:  */
                    794:    static int
                    795: msg_check_screen()
                    796: {
                    797:    if (!full_screen || !screen_valid(FALSE))
                    798:        return FALSE;
                    799:
                    800:    if (msg_row >= Rows)
                    801:        msg_row = Rows - 1;
                    802:    if (msg_col >= Columns)
                    803:        msg_col = Columns - 1;
                    804:    return TRUE;
                    805: }
                    806:
                    807: /*
                    808:  * clear from current message position to end of screen
                    809:  * Note: msg_col is not updated, so we remember the end of the message
                    810:  * for msg_check().
                    811:  */
                    812:    void
                    813: msg_clr_eos()
                    814: {
                    815:    if (!msg_check_screen()
                    816: #ifdef WIN32
                    817:                            || !termcap_active
                    818: #endif
                    819:                                                )
                    820:        return;
                    821:    screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ');
                    822:    screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ');
                    823: }
                    824:
                    825: /*
                    826:  * end putting a message on the screen
                    827:  * call wait_return if the message does not fit in the available space
                    828:  * return TRUE if wait_return not called.
                    829:  */
                    830:    int
                    831: msg_end()
                    832: {
                    833:    /*
                    834:     * if the string is larger than the window,
                    835:     * or the ruler option is set and we run into it,
                    836:     * we have to redraw the window.
                    837:     * Do not do this if we are abandoning the file or editing the command line.
                    838:     */
                    839:    if (!exiting && msg_check() && State != CMDLINE)
                    840:    {
                    841:        wait_return(FALSE);
                    842:        return FALSE;
                    843:    }
                    844:    flushbuf();
                    845:    return TRUE;
                    846: }
                    847:
                    848: /*
                    849:  * If the written message has caused the screen to scroll up, or if we
                    850:  * run into the shown command or ruler, we have to redraw the window later.
                    851:  */
                    852:    int
                    853: msg_check()
                    854: {
                    855:    if (msg_scrolled || (msg_row == Rows - 1 && msg_col >= sc_col))
                    856:    {
                    857:        redraw_later(NOT_VALID);
                    858:        redraw_cmdline = TRUE;
                    859:        return TRUE;
                    860:    }
                    861:    return FALSE;
                    862: }