[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     ! 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: }