aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r--src/nvim/screen.c881
1 files changed, 148 insertions, 733 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index cec5753879..8ba7de83a6 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -130,7 +130,6 @@
#include "nvim/spell.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
-#include "nvim/term.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/version.h"
@@ -146,12 +145,6 @@
*/
static int screen_attr = 0;
-/*
- * Positioning the cursor is reduced by remembering the last position.
- * Mostly used by windgoto() and screen_char().
- */
-static int screen_cur_row, screen_cur_col; /* last known cursor position */
-
static match_T search_hl; /* used for 'hlsearch' highlight matching */
static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
@@ -422,7 +415,7 @@ void update_screen(int type)
search_hl.rm.regprog = NULL;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_redr_type != 0) {
- cursor_off();
+ ui_cursor_off();
if (!did_one) {
did_one = TRUE;
start_search_hl();
@@ -432,7 +425,7 @@ void update_screen(int type)
/* redraw status line after the window to minimize cursor movement */
if (wp->w_redr_status) {
- cursor_off();
+ ui_cursor_off();
win_redr_status(wp);
}
}
@@ -507,7 +500,6 @@ void update_single_line(win_T *wp, linenr_T lnum)
row = 0;
for (j = 0; j < wp->w_lines_valid; ++j) {
if (lnum == wp->w_lines[j].wl_lnum) {
- screen_start(); /* not sure of screen cursor */
init_search_hl(wp);
start_search_hl();
prepare_search_hl(wp, lnum);
@@ -528,7 +520,7 @@ void update_single_line(win_T *wp, linenr_T lnum)
*/
static void update_prepare(void)
{
- cursor_off();
+ ui_cursor_off();
updating_screen = TRUE;
start_search_hl();
}
@@ -4065,7 +4057,7 @@ win_line (
break;
}
- if (screen_cur_row == screen_row - 1
+ if (ui_current_row() == screen_row - 1
&& filler_todo <= 0
&& wp->w_width == Columns) {
/* Remember that the line wraps, used for modeless copy. */
@@ -4096,7 +4088,7 @@ win_line (
* then output the same character again to let the
* terminal know about the wrap. If the terminal doesn't
* auto-wrap, we overwrite the character. */
- if (screen_cur_col != wp->w_width)
+ if (ui_current_col() != wp->w_width)
screen_char(LineOffset[screen_row - 1]
+ (unsigned)Columns - 1,
screen_row - 1, (int)(Columns - 1));
@@ -4105,14 +4097,13 @@ win_line (
* space to keep it simple. */
if (has_mbyte && MB_BYTE2LEN(ScreenLines[LineOffset[
screen_row -
- 1] + (Columns - 1)]) > 1)
- out_char(' ');
- else
- out_char(ScreenLines[LineOffset[screen_row - 1]
- + (Columns - 1)]);
+ 1] + (Columns - 1)]) > 1) {
+ ui_putc(' ');
+ } else {
+ ui_putc(ScreenLines[LineOffset[screen_row - 1] + (Columns - 1)]);
+ }
/* force a redraw of the first char on the next line */
ScreenAttrs[LineOffset[screen_row]] = (sattr_T)-1;
- screen_start(); /* don't know where cursor is now */
}
}
@@ -4271,42 +4262,6 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl
if (redraw_this) {
- /*
- * Special handling when 'xs' termcap flag set (hpterm):
- * Attributes for characters are stored at the position where the
- * cursor is when writing the highlighting code. The
- * start-highlighting code must be written with the cursor on the
- * first highlighted character. The stop-highlighting code must
- * be written with the cursor just after the last highlighted
- * character.
- * Overwriting a character doesn't remove it's highlighting. Need
- * to clear the rest of the line, and force redrawing it
- * completely.
- */
- if ( p_wiv
- && !force
- && ScreenAttrs[off_to] != 0
- && ScreenAttrs[off_from] != ScreenAttrs[off_to]) {
- /*
- * Need to remove highlighting attributes here.
- */
- windgoto(row, col + coloff);
- out_str(T_CE); /* clear rest of this screen line */
- screen_start(); /* don't know where cursor is now */
- force = TRUE; /* force redraw of rest of the line */
- redraw_next = TRUE; /* or else next char would miss out */
-
- /*
- * If the previous character was highlighted, need to stop
- * highlighting at this character.
- */
- if (col + coloff > 0 && ScreenAttrs[off_to - 1] != 0) {
- screen_attr = ScreenAttrs[off_to - 1];
- term_windgoto(row, col + coloff);
- screen_stop_highlight();
- } else
- screen_attr = 0; /* highlighting has stopped */
- }
if (enc_dbcs != 0) {
/* Check if overwriting a double-byte with a single-byte or
* the other way around requires another character to be
@@ -4369,16 +4324,6 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl
screen_char_2(off_to, row, col + coloff);
else
screen_char(off_to, row, col + coloff);
- } else if ( p_wiv
- && col + coloff > 0) {
- if (ScreenAttrs[off_to] == ScreenAttrs[off_to - 1]) {
- /*
- * Don't output stop-highlight when moving the cursor, it will
- * stop the highlighting when it should continue.
- */
- screen_attr = 0;
- } else if (screen_attr != 0)
- screen_stop_highlight();
}
off_to += CHAR_CELLS;
@@ -4720,7 +4665,7 @@ win_redr_status_matches (
/* Put the wildmenu just above the command line. If there is
* no room, scroll the screen one line up. */
if (cmdline_row == Rows - 1) {
- screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL);
+ screen_del_lines(0, 0, 1, (int)Rows, NULL);
++msg_scrolled;
} else {
++cmdline_row;
@@ -5686,25 +5631,15 @@ next_search_hl_pos(
return false;
}
-
static void screen_start_highlight(int attr)
{
screen_attr = attr;
- if (full_screen) {
- char buf[20];
- sprintf(buf, "\033|%dh", attr);
- OUT_STR(buf);
- }
+ ui_start_highlight(attr);
}
void screen_stop_highlight(void)
{
- if (screen_attr != 0) {
- // Handled in ui.c
- char buf[20];
- sprintf(buf, "\033|%dH", screen_attr);
- OUT_STR(buf);
- }
+ ui_stop_highlight();
screen_attr = 0;
}
@@ -5741,7 +5676,7 @@ static void screen_char(unsigned off, int row, int col)
if (screen_attr != attr)
screen_stop_highlight();
- windgoto(row, col);
+ ui_cursor_goto(row, col);
if (screen_attr != attr)
screen_start_highlight(attr);
@@ -5749,25 +5684,18 @@ static void screen_char(unsigned off, int row, int col)
if (enc_utf8 && ScreenLinesUC[off] != 0) {
char_u buf[MB_MAXBYTES + 1];
- /* Convert UTF-8 character to bytes and write it. */
-
+ // Convert UTF-8 character to bytes and write it.
buf[utfc_char2bytes(off, buf)] = NUL;
-
- out_str(buf);
- if (utf_char2cells(ScreenLinesUC[off]) > 1)
- ++screen_cur_col;
+ ui_puts(buf);
} else {
- out_flush_check();
- out_char(ScreenLines[off]);
- /* double-byte character in single-width cell */
- if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
- out_char(ScreenLines2[off]);
+ ui_putc(ScreenLines[off]);
+ // double-byte character in single-width cell
+ if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) {
+ ui_putc(ScreenLines2[off]);
+ }
}
-
- screen_cur_col++;
}
-
/*
* Used for enc_dbcs only: Put one double-wide character at ScreenLines["off"]
* on the screen at position 'row' and 'col'.
@@ -5790,60 +5718,7 @@ static void screen_char_2(unsigned off, int row, int col)
/* Output the first byte normally (positions the cursor), then write the
* second byte directly. */
screen_char(off, row, col);
- out_char(ScreenLines[off + 1]);
- ++screen_cur_col;
-}
-
-/*
- * Draw a rectangle of the screen, inverted when "invert" is TRUE.
- * This uses the contents of ScreenLines[] and doesn't change it.
- */
-void screen_draw_rectangle(int row, int col, int height, int width, int invert)
-{
- int r, c;
- int off;
- int max_off;
-
- /* Can't use ScreenLines unless initialized */
- if (ScreenLines == NULL)
- return;
-
- if (invert)
- screen_char_attr = HL_INVERSE;
- for (r = row; r < row + height; ++r) {
- off = LineOffset[r];
- max_off = off + screen_Columns;
- for (c = col; c < col + width; ++c) {
- if (enc_dbcs != 0 && dbcs_off2cells(off + c, max_off) > 1) {
- screen_char_2(off + c, r, c);
- ++c;
- } else {
- screen_char(off + c, r, c);
- if (utf_off2cells(off + c, max_off) > 1)
- ++c;
- }
- }
- }
- screen_char_attr = 0;
-}
-
-/*
- * Redraw the characters for a vertically split window.
- */
-static void redraw_block(int row, int end, win_T *wp)
-{
- int col;
- int width;
-
-
- if (wp == NULL) {
- col = 0;
- width = Columns;
- } else {
- col = wp->w_wincol;
- width = wp->w_width;
- }
- screen_draw_rectangle(row, col, end - row, width, FALSE);
+ ui_putc(ScreenLines[off + 1]);
}
/*
@@ -5859,9 +5734,6 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
int end_off;
int did_delete;
int c;
-#if defined(FEAT_GUI) || defined(UNIX)
- int force_next = FALSE;
-#endif
if (end_row > screen_Rows) /* safety check */
end_row = screen_Rows;
@@ -5874,16 +5746,17 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
/* it's a "normal" terminal when not in a GUI or cterm */
for (row = start_row; row < end_row; ++row) {
- if (has_mbyte
- ) {
- /* When drawing over the right halve of a double-wide char clear
- * out the left halve. When drawing over the left halve of a
- * double wide-char clear out the right halve. Only needed in a
- * terminal. */
- if (start_col > 0 && mb_fix_col(start_col, row) != start_col)
+ if (has_mbyte) {
+ // When drawing over the right halve of a double-wide char clear
+ // out the left halve. When drawing over the left halve of a
+ // double wide-char clear out the right halve. Only needed in a
+ // terminal.
+ if (start_col > 0 && mb_fix_col(start_col, row) != start_col) {
screen_puts_len((char_u *)" ", 1, row, start_col - 1, 0);
- if (end_col < screen_Columns && mb_fix_col(end_col, row) != end_col)
+ }
+ if (end_col < screen_Columns && mb_fix_col(end_col, row) != end_col) {
screen_puts_len((char_u *)" ", 1, row, end_col, 0);
+ }
}
/*
* Try to use delete-line termcap code, when no attributes or in a
@@ -5916,9 +5789,8 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
if (off < end_off) { /* something to be cleared */
col = off - LineOffset[row];
screen_stop_highlight();
- term_windgoto(row, col); /* clear rest of this screen line */
- out_str(T_CE);
- screen_start(); /* don't know where cursor is now */
+ ui_cursor_goto(row, col); // clear rest of this screen line
+ ui_eol_clear();
col = end_col - col;
while (col--) { /* clear chars in ScreenLines */
ScreenLines[off] = ' ';
@@ -5938,9 +5810,6 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
|| (enc_utf8 && (int)ScreenLinesUC[off]
!= (c >= 0x80 ? c : 0))
|| ScreenAttrs[off] != attr
-#if defined(FEAT_GUI) || defined(UNIX)
- || force_next
-#endif
) {
ScreenLines[off] = c;
if (enc_utf8) {
@@ -5982,7 +5851,7 @@ void check_for_delay(int check_msg_scroll)
if ((emsg_on_display || (check_msg_scroll && msg_scroll))
&& !did_wait_return
&& emsg_silent == 0) {
- out_flush();
+ ui_flush();
os_delay(1000L, true);
emsg_on_display = FALSE;
if (check_msg_scroll)
@@ -6290,7 +6159,7 @@ static void screenclear2(void)
LineWraps[i] = FALSE;
}
- out_str(T_CL); /* clear the display */
+ ui_clear(); // clear the display
clear_cmdline = FALSE;
mode_displayed = FALSE;
screen_cleared = TRUE; /* can use contents of ScreenLines now */
@@ -6303,7 +6172,6 @@ static void screenclear2(void)
compute_cmdrow();
msg_row = cmdline_row; /* put cursor on last line for messages */
msg_col = 0;
- screen_start(); /* don't know where cursor is now */
msg_scrolled = 0; /* can't scroll back */
msg_didany = FALSE;
msg_didout = FALSE;
@@ -6348,238 +6216,13 @@ static void linecopy(int to, int from, win_T *wp)
}
/*
- * Reset cursor position. Use whenever cursor was moved because of outputting
- * something directly to the screen (shell commands) or a terminal control
- * code.
- */
-void screen_start(void)
-{
- screen_cur_row = screen_cur_col = 9999;
-}
-
-/*
- * Move the cursor to position "row","col" in the screen.
- * This tries to find the most efficient way to move, minimizing the number of
- * characters sent to the terminal.
- */
-void windgoto(int row, int col)
-{
- sattr_T *p;
- int i;
- int plan;
- int cost;
- int wouldbe_col;
- int noinvcurs;
- char_u *bs;
- int goto_cost;
- int attr;
-
-#define GOTO_COST 7 /* assume a term_windgoto() takes about 7 chars */
-#define HIGHL_COST 5 /* assume unhighlight takes 5 chars */
-
-#define PLAN_LE 1
-#define PLAN_CR 2
-#define PLAN_NL 3
-#define PLAN_WRITE 4
- /* Can't use ScreenLines unless initialized */
- if (ScreenLines == NULL)
- return;
-
- if (col != screen_cur_col || row != screen_cur_row) {
- /* Check for valid position. */
- if (row < 0) /* window without text lines? */
- row = 0;
- if (row >= screen_Rows)
- row = screen_Rows - 1;
- if (col >= screen_Columns)
- col = screen_Columns - 1;
-
- /* check if no cursor movement is allowed in highlight mode */
- if (screen_attr && *T_MS == NUL)
- noinvcurs = HIGHL_COST;
- else
- noinvcurs = 0;
- goto_cost = GOTO_COST + noinvcurs;
-
- /*
- * Plan how to do the positioning:
- * 1. Use CR to move it to column 0, same row.
- * 2. Use T_LE to move it a few columns to the left.
- * 3. Use NL to move a few lines down, column 0.
- * 4. Move a few columns to the right with T_ND or by writing chars.
- *
- * Don't do this if the cursor went beyond the last column, the cursor
- * position is unknown then (some terminals wrap, some don't )
- *
- * First check if the highlighting attributes allow us to write
- * characters to move the cursor to the right.
- */
- if (row >= screen_cur_row && screen_cur_col < Columns) {
- /*
- * If the cursor is in the same row, bigger col, we can use CR
- * or T_LE.
- */
- bs = NULL; /* init for GCC */
- attr = screen_attr;
- if (row == screen_cur_row && col < screen_cur_col) {
- /* "le" is preferred over "bc", because "bc" is obsolete */
- if (*T_LE)
- bs = T_LE; /* "cursor left" */
- else
- bs = T_BC; /* "backspace character (old) */
- if (*bs)
- cost = (screen_cur_col - col) * (int)STRLEN(bs);
- else
- cost = 999;
- if (col + 1 < cost) { /* using CR is less characters */
- plan = PLAN_CR;
- wouldbe_col = 0;
- cost = 1; /* CR is just one character */
- } else {
- plan = PLAN_LE;
- wouldbe_col = col;
- }
- if (noinvcurs) { /* will stop highlighting */
- cost += noinvcurs;
- attr = 0;
- }
- }
- /*
- * If the cursor is above where we want to be, we can use CR LF.
- */
- else if (row > screen_cur_row) {
- plan = PLAN_NL;
- wouldbe_col = 0;
- cost = (row - screen_cur_row) * 2; /* CR LF */
- if (noinvcurs) { /* will stop highlighting */
- cost += noinvcurs;
- attr = 0;
- }
- }
- /*
- * If the cursor is in the same row, smaller col, just use write.
- */
- else {
- plan = PLAN_WRITE;
- wouldbe_col = screen_cur_col;
- cost = 0;
- }
-
- /*
- * Check if any characters that need to be written have the
- * correct attributes. Also avoid UTF-8 characters.
- */
- i = col - wouldbe_col;
- if (i > 0)
- cost += i;
- if (cost < goto_cost && i > 0) {
- /*
- * Check if the attributes are correct without additionally
- * stopping highlighting.
- */
- p = ScreenAttrs + LineOffset[row] + wouldbe_col;
- while (i && *p++ == attr)
- --i;
- if (i != 0) {
- /*
- * Try if it works when highlighting is stopped here.
- */
- if (*--p == 0) {
- cost += noinvcurs;
- while (i && *p++ == 0)
- --i;
- }
- if (i != 0)
- cost = 999; /* different attributes, don't do it */
- }
- if (enc_utf8) {
- /* Don't use an UTF-8 char for positioning, it's slow. */
- for (i = wouldbe_col; i < col; ++i)
- if (ScreenLinesUC[LineOffset[row] + i] != 0) {
- cost = 999;
- break;
- }
- }
- }
-
- /*
- * We can do it without term_windgoto()!
- */
- if (cost < goto_cost) {
- if (plan == PLAN_LE) {
- if (noinvcurs)
- screen_stop_highlight();
- while (screen_cur_col > col) {
- out_str(bs);
- --screen_cur_col;
- }
- } else if (plan == PLAN_CR) {
- if (noinvcurs)
- screen_stop_highlight();
- out_char('\r');
- screen_cur_col = 0;
- } else if (plan == PLAN_NL) {
- if (noinvcurs)
- screen_stop_highlight();
- while (screen_cur_row < row) {
- out_char('\n');
- ++screen_cur_row;
- }
- screen_cur_col = 0;
- }
-
- i = col - screen_cur_col;
- if (i > 0) {
- /*
- * Use cursor-right if it's one character only. Avoids
- * removing a line of pixels from the last bold char, when
- * using the bold trick in the GUI.
- */
- if (T_ND[0] != NUL && T_ND[1] == NUL) {
- while (i-- > 0)
- out_char(*T_ND);
- } else {
- int off;
-
- off = LineOffset[row] + screen_cur_col;
- while (i-- > 0) {
- if (ScreenAttrs[off] != screen_attr)
- screen_stop_highlight();
- out_flush_check();
- out_char(ScreenLines[off]);
- if (enc_dbcs == DBCS_JPNU
- && ScreenLines[off] == 0x8e)
- out_char(ScreenLines2[off]);
- ++off;
- }
- }
- }
- }
- } else
- cost = 999;
-
- if (cost >= goto_cost) {
- if (noinvcurs)
- screen_stop_highlight();
- if (row == screen_cur_row && (col > screen_cur_col) &&
- *T_CRI != NUL)
- term_cursor_right(col - screen_cur_col);
- else
- term_windgoto(row, col);
- }
- screen_cur_row = row;
- screen_cur_col = col;
- }
-}
-
-/*
* Set cursor to its position in the current window.
*/
void setcursor(void)
{
if (redrawing()) {
validate_cursor();
- windgoto(curwin->w_winrow + curwin->w_wrow,
+ ui_cursor_goto(curwin->w_winrow + curwin->w_wrow,
curwin->w_wincol + (
/* With 'rightleft' set and the cursor on a double-wide
* character, position it on the leftmost column. */
@@ -6628,7 +6271,7 @@ int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear)
did_delete = FALSE;
if (wp->w_next != NULL || wp->w_status_height) {
if (screen_del_lines(0, wp->w_winrow + wp->w_height - line_count,
- line_count, (int)Rows, FALSE, NULL) == OK)
+ line_count, (int)Rows, NULL) == OK)
did_delete = TRUE;
else if (wp->w_next)
return FAIL;
@@ -6683,8 +6326,9 @@ int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear)
return retval;
if (screen_del_lines(0, wp->w_winrow + row, line_count,
- (int)Rows, FALSE, NULL) == FAIL)
+ (int)Rows, NULL) == FAIL) {
return FAIL;
+ }
/*
* If there are windows or status lines below, try to put them at the
@@ -6706,29 +6350,21 @@ int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear)
return OK;
}
-/*
- * Common code for win_ins_lines() and win_del_lines().
- * Returns OK or FAIL when the work has been done.
- * Returns MAYBE when not finished yet.
- */
+// Common code for win_ins_lines() and win_del_lines().
+// Returns OK or FAIL when the work has been done.
static int win_do_lines(win_T *wp, int row, int line_count, int mayclear, int del)
{
- int retval;
-
- if (!redrawing() || line_count <= 0)
+ if (!redrawing() || line_count <= 0) {
return FAIL;
+ }
- /* only a few lines left: redraw is faster */
- if (mayclear && Rows - line_count < 5
- && wp->w_width == Columns
- ) {
+ // only a few lines left: redraw is faster
+ if (mayclear && Rows - line_count < 5 && wp->w_width == Columns) {
screenclear(); /* will set wp->w_lines_valid to 0 */
return FAIL;
}
- /*
- * Delete all remaining lines
- */
+ // Delete all remaining lines
if (row + line_count >= wp->w_height) {
screen_fill(wp->w_winrow + row, wp->w_winrow + wp->w_height,
wp->w_wincol, (int)W_ENDCOL(wp),
@@ -6736,42 +6372,20 @@ static int win_do_lines(win_T *wp, int row, int line_count, int mayclear, int de
return OK;
}
- /*
- * when scrolling, the message on the command line should be cleared,
- * otherwise it will stay there forever.
- */
+ // when scrolling, the message on the command line should be cleared,
+ // otherwise it will stay there forever.
clear_cmdline = TRUE;
-
- /*
- * If the terminal can set a scroll region, use that.
- * Always do this in a vertically split window. This will redraw from
- * ScreenLines[] when t_CV isn't defined. That's faster than using
- * win_line().
- * Don't use a scroll region when we are going to redraw the text, writing
- * a character in the lower right corner of the scroll region causes a
- * scroll-up in the DJGPP version.
- */
- if (scroll_region
- || wp->w_width != Columns
- ) {
- if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL))
- scroll_region_set(wp, row);
- if (del)
- retval = screen_del_lines(wp->w_winrow + row, 0, line_count,
- wp->w_height - row, FALSE, wp);
- else
- retval = screen_ins_lines(wp->w_winrow + row, 0, line_count,
- wp->w_height - row, wp);
- if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL))
- scroll_region_reset();
- return retval;
- }
-
- if (wp->w_next != NULL) {
- return FAIL;
+ int retval;
+ ui_set_scroll_region(wp, row);
+ if (del) {
+ retval = screen_del_lines(wp->w_winrow + row, 0, line_count,
+ wp->w_height - row, wp);
+ } else {
+ retval = screen_ins_lines(wp->w_winrow + row, 0, line_count,
+ wp->w_height - row, wp);
}
-
- return MAYBE;
+ ui_reset_scroll_region();
+ return retval;
}
/*
@@ -6810,16 +6424,13 @@ static void win_rest_invalid(win_T *wp)
#define USE_T_CD 8
#define USE_REDRAW 9
-/*
- * insert lines on the screen and update ScreenLines[]
- * 'end' is the line after the scrolled part. Normally it is Rows.
- * When scrolling region used 'off' is the offset from the top for the region.
- * 'row' and 'end' are relative to the start of the region.
- *
- * return FAIL for failure, OK for success.
- */
-int
-screen_ins_lines (
+// insert lines on the screen and update ScreenLines[]
+// 'end' is the line after the scrolled part. Normally it is Rows.
+// When scrolling region used 'off' is the offset from the top for the region.
+// 'row' and 'end' are relative to the start of the region.
+//
+// return FAIL for failure, OK for success.
+int screen_ins_lines (
int off,
int row,
int line_count,
@@ -6830,101 +6441,27 @@ screen_ins_lines (
int i;
int j;
unsigned temp;
- int cursor_row;
- int type;
- int result_empty;
- int can_ce = true;
- /*
- * FAIL if
- * - there is no valid screen
- * - the screen has to be redrawn completely
- * - the line count is less than one
- * - the line count is more than 'ttyscroll'
- */
- if (!screen_valid(TRUE) || line_count <= 0 || line_count > p_ttyscroll)
+ // FAIL if
+ // - there is no valid screen
+ // - the screen has to be redrawn completely
+ // - the line count is less than one
+ // - the line count is more than 'ttyscroll'
+ if (!screen_valid(TRUE) || line_count <= 0) {
return FAIL;
+ }
- /*
- * There are seven ways to insert lines:
- * 0. When in a vertically split window and t_CV isn't set, redraw the
- * characters from ScreenLines[].
- * 1. Use T_CD (clear to end of display) if it exists and the result of
- * the insert is just empty lines
- * 2. Use T_CAL (insert multiple lines) if it exists and T_AL is not
- * present or line_count > 1. It looks better if we do all the inserts
- * at once.
- * 3. Use T_CDL (delete multiple lines) if it exists and the result of the
- * insert is just empty lines and T_CE is not present or line_count >
- * 1.
- * 4. Use T_AL (insert line) if it exists.
- * 5. Use T_CE (erase line) if it exists and the result of the insert is
- * just empty lines.
- * 6. Use T_DL (delete line) if it exists and the result of the insert is
- * just empty lines.
- * 7. Use T_SR (scroll reverse) if it exists and inserting at row 0 and
- * the 'da' flag is not set or we have clear line capability.
- * 8. redraw the characters from ScreenLines[].
- *
- * Careful: In a hpterm scroll reverse doesn't work as expected, it moves
- * the scrollbar for the window. It does have insert line, use that if it
- * exists.
- */
- result_empty = (row + line_count >= end);
- if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL)
- type = USE_REDRAW;
- else if (result_empty)
- type = USE_T_CD;
- else if (*T_CAL != NUL && (line_count > 1 || *T_AL == NUL))
- type = USE_T_CAL;
- else if (*T_CDL != NUL && result_empty && (line_count > 1 || !can_ce))
- type = USE_T_CDL;
- else if (*T_AL != NUL)
- type = USE_T_AL;
- else if (can_ce && result_empty)
- type = USE_T_CE;
- else if (*T_DL != NUL && result_empty)
- type = USE_T_DL;
- else if (*T_SR != NUL && row == 0 && (*T_DA == NUL || can_ce))
- type = USE_T_SR;
- else
- return FAIL;
-
- /*
- * For clearing the lines screen_del_lines() is used. This will also take
- * care of t_db if necessary.
- */
- if (type == USE_T_CD || type == USE_T_CDL ||
- type == USE_T_CE || type == USE_T_DL)
- return screen_del_lines(off, row, line_count, end, FALSE, wp);
-
- /*
- * If text is retained below the screen, first clear or delete as many
- * lines at the bottom of the window as are about to be inserted so that
- * the deleted lines won't later surface during a screen_del_lines.
- */
- if (*T_DB)
- screen_del_lines(off, end - line_count, line_count, end, FALSE, wp);
-
-
-
- if (*T_CCS != NUL) /* cursor relative to region */
- cursor_row = row;
- else
- cursor_row = row + off;
-
- /*
- * Shift LineOffset[] line_count down to reflect the inserted lines.
- * Clear the inserted lines in ScreenLines[].
- */
+ // Shift LineOffset[] line_count down to reflect the inserted lines.
+ // Clear the inserted lines in ScreenLines[].
row += off;
end += off;
for (i = 0; i < line_count; ++i) {
if (wp != NULL && wp->w_width != Columns) {
- /* need to copy part of a line */
+ // need to copy part of a line
j = end - 1 - i;
- while ((j -= line_count) >= row)
+ while ((j -= line_count) >= row) {
linecopy(j + line_count, j, wp);
+ }
j += line_count;
lineclear(LineOffset[j] + wp->w_wincol, wp->w_width);
LineWraps[j] = FALSE;
@@ -6941,151 +6478,54 @@ screen_ins_lines (
}
}
- screen_stop_highlight();
- windgoto(cursor_row, 0);
-
- /* redraw the characters */
- if (type == USE_REDRAW)
- redraw_block(row, end, wp);
- else if (type == USE_T_CAL) {
- term_append_lines(line_count);
- screen_start(); /* don't know where cursor is now */
- } else {
- for (i = 0; i < line_count; i++) {
- if (type == USE_T_AL) {
- if (i && cursor_row != 0)
- windgoto(cursor_row, 0);
- out_str(T_AL);
- } else /* type == USE_T_SR */
- out_str(T_SR);
- screen_start(); /* don't know where cursor is now */
- }
- }
-
- /*
- * With scroll-reverse and 'da' flag set we need to clear the lines that
- * have been scrolled down into the region.
- */
- if (type == USE_T_SR && *T_DA) {
- for (i = 0; i < line_count; ++i) {
- windgoto(off + i, 0);
- out_str(T_CE);
- screen_start(); /* don't know where cursor is now */
- }
- }
+ ui_append_lines(line_count);
return OK;
}
-/*
- * delete lines on the screen and update ScreenLines[]
- * 'end' is the line after the scrolled part. Normally it is Rows.
- * When scrolling region used 'off' is the offset from the top for the region.
- * 'row' and 'end' are relative to the start of the region.
- *
- * Return OK for success, FAIL if the lines are not deleted.
- */
-int
-screen_del_lines (
+// delete lines on the screen and update ScreenLines[]
+// 'end' is the line after the scrolled part. Normally it is Rows.
+// When scrolling region used 'off' is the offset from the top for the region.
+// 'row' and 'end' are relative to the start of the region.
+//
+// Return OK for success, FAIL if the lines are not deleted.
+int screen_del_lines (
int off,
int row,
int line_count,
int end,
- int force, /* even when line_count > p_ttyscroll */
win_T *wp /* NULL or window to use width from */
)
{
int j;
int i;
unsigned temp;
- int cursor_row;
- int cursor_end;
- int result_empty; /* result is empty until end of region */
- int can_delete; /* deleting line codes can be used */
- int type;
- /*
- * FAIL if
- * - there is no valid screen
- * - the screen has to be redrawn completely
- * - the line count is less than one
- * - the line count is more than 'ttyscroll'
- */
- if (!screen_valid(TRUE) || line_count <= 0 ||
- (!force && line_count > p_ttyscroll))
- return FAIL;
-
- /*
- * Check if the rest of the current region will become empty.
- */
- result_empty = row + line_count >= end;
-
- /*
- * We can delete lines only when 'db' flag not set or when 'ce' option
- * available.
- */
- can_delete = true;
-
- /*
- * There are six ways to delete lines:
- * 0. When in a vertically split window and t_CV isn't set, redraw the
- * characters from ScreenLines[].
- * 1. Use T_CD if it exists and the result is empty.
- * 2. Use newlines if row == 0 and count == 1 or T_CDL does not exist.
- * 3. Use T_CDL (delete multiple lines) if it exists and line_count > 1 or
- * none of the other ways work.
- * 4. Use T_CE (erase line) if the result is empty.
- * 5. Use T_DL (delete line) if it exists.
- * 6. redraw the characters from ScreenLines[].
- */
- if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL)
- type = USE_REDRAW;
- else if (result_empty)
- type = USE_T_CD;
- else if (row == 0 && (
- /* On the Amiga, somehow '\n' on the last line doesn't always scroll
- * up, so use delete-line command */
- line_count == 1 ||
- *T_CDL == NUL))
- type = USE_NL;
- else if (*T_CDL != NUL && line_count > 1 && can_delete)
- type = USE_T_CDL;
- else if (result_empty && (wp == NULL || wp->w_width == Columns))
- type = USE_T_CE;
- else if (*T_DL != NUL && can_delete)
- type = USE_T_DL;
- else if (*T_CDL != NUL && can_delete)
- type = USE_T_CDL;
- else
+ // FAIL if
+ // - there is no valid screen
+ // - the screen has to be redrawn completely
+ // - the line count is less than one
+ // - the line count is more than 'ttyscroll'
+ if (!screen_valid(TRUE) || line_count <= 0) {
return FAIL;
-
-
-
- if (*T_CCS != NUL) { /* cursor relative to region */
- cursor_row = row;
- cursor_end = end;
- } else {
- cursor_row = row + off;
- cursor_end = end + off;
}
- /*
- * Now shift LineOffset[] line_count up to reflect the deleted lines.
- * Clear the inserted lines in ScreenLines[].
- */
+ // Now shift LineOffset[] line_count up to reflect the deleted lines.
+ // Clear the inserted lines in ScreenLines[].
row += off;
end += off;
for (i = 0; i < line_count; ++i) {
if (wp != NULL && wp->w_width != Columns) {
- /* need to copy part of a line */
+ // need to copy part of a line
j = row + i;
- while ((j += line_count) <= end - 1)
+ while ((j += line_count) <= end - 1) {
linecopy(j - line_count, j, wp);
+ }
j -= line_count;
lineclear(LineOffset[j] + wp->w_wincol, wp->w_width);
LineWraps[j] = FALSE;
} else {
- /* whole width, moving the line pointers is faster */
+ // whole width, moving the line pointers is faster
j = row + i;
temp = LineOffset[j];
while ((j += line_count) <= end - 1) {
@@ -7098,54 +6538,7 @@ screen_del_lines (
}
}
- screen_stop_highlight();
-
- /* redraw the characters */
- if (type == USE_REDRAW)
- redraw_block(row, end, wp);
- else if (type == USE_T_CD) { /* delete the lines */
- windgoto(cursor_row, 0);
- out_str(T_CD);
- screen_start(); /* don't know where cursor is now */
- } else if (type == USE_T_CDL) {
- windgoto(cursor_row, 0);
- term_delete_lines(line_count);
- screen_start(); /* don't know where cursor is now */
- }
- /*
- * Deleting lines at top of the screen or scroll region: Just scroll
- * the whole screen (scroll region) up by outputting newlines on the
- * last line.
- */
- else if (type == USE_NL) {
- windgoto(cursor_end - 1, 0);
- for (i = line_count; --i >= 0; )
- out_char('\n'); /* cursor will remain on same line */
- } else {
- for (i = line_count; --i >= 0; ) {
- if (type == USE_T_DL) {
- windgoto(cursor_row, 0);
- out_str(T_DL); /* delete a line */
- } else { /* type == USE_T_CE */
- windgoto(cursor_row + i, 0);
- out_str(T_CE); /* erase a line */
- }
- screen_start(); /* don't know where cursor is now */
- }
- }
-
- /*
- * If the 'db' flag is set, we need to clear the lines that have been
- * scrolled up at the bottom of the region.
- */
- if (*T_DB && (type == USE_T_DL || type == USE_T_CDL)) {
- for (i = line_count; i > 0; --i) {
- windgoto(cursor_end - i, 0);
- out_str(T_CE); /* erase a line */
- screen_start(); /* don't know where cursor is now */
- }
- }
-
+ ui_delete_lines(line_count);
return OK;
}
@@ -7195,7 +6588,7 @@ int showmode(void)
/* Position on the last line in the window, column 0 */
msg_pos_mode();
- cursor_off();
+ ui_cursor_off();
attr = hl_attr(HLF_CM); /* Highlight mode */
if (do_mode) {
MSG_PUTS_ATTR("--", attr);
@@ -7644,7 +7037,7 @@ static void win_redr_ruler(win_T *wp, int always)
|| wp->w_buffer->b_ml.ml_line_count != wp->w_ru_line_count
|| wp->w_topfill != wp->w_ru_topfill
|| empty_line != wp->w_ru_empty) {
- cursor_off();
+ ui_cursor_off();
int width;
int row;
@@ -7781,24 +7174,6 @@ int number_width(win_T *wp)
}
/*
- * Return the current cursor column. This is the actual position on the
- * screen. First column is 0.
- */
-int screen_screencol(void)
-{
- return screen_cur_col;
-}
-
-/*
- * Return the current cursor row. This is the actual position on the screen.
- * First row is 0.
- */
-int screen_screenrow(void)
-{
- return screen_cur_row;
-}
-
-/*
* Set size of the Vim shell.
* If 'mustset' is TRUE, we must set Rows and Columns, do not get the real
* window size (this is used for the :win command).
@@ -7839,19 +7214,15 @@ void screen_resize(int width, int height)
check_shellsize();
height = Rows;
width = Columns;
- // Clear the output buffer to ensure UIs don't receive redraw command meant
- // for invalid screen sizes.
- out_buf_clear();
ui_resize(width, height);
/* The window layout used to be adjusted here, but it now happens in
* screenalloc() (also invoked from screenclear()). That is because the
* "busy" check above may skip this, but not screenalloc(). */
- if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM)
+ if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM) {
screenclear();
- else
- screen_start(); /* don't know where cursor is now */
+ }
if (starting != NO_SCREEN) {
maketitle();
@@ -7889,8 +7260,52 @@ void screen_resize(int width, int height)
setcursor();
}
}
- cursor_on(); /* redrawing may have switched it off */
+ ui_cursor_on(); /* redrawing may have switched it off */
}
- out_flush();
+ ui_flush();
--busy;
}
+
+// Check if the new shell size is valid, correct it if it's too small or way
+// too big.
+void check_shellsize(void)
+{
+ if (Rows < min_rows()) {
+ // need room for one window and command line
+ Rows = min_rows();
+ }
+ limit_screen_size();
+}
+
+// Limit Rows and Columns to avoid an overflow in Rows * Columns.
+void limit_screen_size(void)
+{
+ if (Columns < MIN_COLUMNS) {
+ Columns = MIN_COLUMNS;
+ } else if (Columns > 10000) {
+ Columns = 10000;
+ }
+
+ if (Rows > 1000) {
+ Rows = 1000;
+ }
+}
+
+void win_new_shellsize(void)
+{
+ static long old_Rows = 0;
+ static long old_Columns = 0;
+
+ if (old_Rows != Rows) {
+ // if 'window' uses the whole screen, keep it using that */
+ if (p_window == old_Rows - 1 || old_Rows == 0) {
+ p_window = Rows - 1;
+ }
+ old_Rows = Rows;
+ shell_new_rows(); // update window sizes
+ }
+ if (old_Columns != Columns) {
+ old_Columns = Columns;
+ shell_new_columns(); // update window sizes
+ }
+}