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