diff options
| author | Björn Linse <bjorn.linse@gmail.com> | 2018-12-31 17:37:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-31 17:37:50 +0100 |
| commit | 6427894d891100c0a41f569ecde65bfdce2ea00c (patch) | |
| tree | c34bef18907b53dc98e0009ff69a799440080384 /src/nvim | |
| parent | ccbcd390d42d33a15f15c29fab5d6076a6d3ac08 (diff) | |
| parent | c72d9ce0a602ba53b99145f64f0d43327a4e3eb3 (diff) | |
| download | rneovim-6427894d891100c0a41f569ecde65bfdce2ea00c.tar.gz rneovim-6427894d891100c0a41f569ecde65bfdce2ea00c.tar.bz2 rneovim-6427894d891100c0a41f569ecde65bfdce2ea00c.zip | |
Merge pull request #8455 from UtkarshMe/grid-split
implement ext_multigrid: draw each window on a separate resizable grid.
Diffstat (limited to 'src/nvim')
34 files changed, 1456 insertions, 1031 deletions
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 390b7e8363..feca140547 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -6,6 +6,7 @@ #include <string.h> #include "nvim/func_attr.h" +#include "nvim/types.h" #define ARRAY_DICT_INIT {.size = 0, .capacity = 0, .items = NULL} #define STRING_INIT {.data = NULL, .size = 0} @@ -20,8 +21,6 @@ # define DictionaryOf(...) Dictionary #endif -typedef int handle_T; - // Basic types typedef enum { kErrorTypeNone = -1, diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 01f8c9f71c..7ba5251c60 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -126,7 +126,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, } } - if (ui->ui_ext[kUIHlState]) { + if (ui->ui_ext[kUIHlState] || ui->ui_ext[kUIMultigrid]) { ui->ui_ext[kUILinegrid] = true; } @@ -245,6 +245,28 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, name.data); } +/// Tell nvim to resize a grid. Nvim sends grid_resize event with the +/// requested grid size is within size limits and with maximum allowed size +/// otherwise. +/// +/// On invalid grid handle, fails with error. +/// +/// @param grid The handle of the grid to be changed. +/// @param width The new requested width. +/// @param height The new requested height. +void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, + Integer height, Error *error) + FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY +{ + if (!pmap_has(uint64_t)(connected_uis, channel_id)) { + api_set_error(error, kErrorTypeException, + "UI not attached to channel: %" PRId64, channel_id); + return; + } + + ui_grid_resize((handle_T)grid, (int)width, (int)height, error); +} + /// Pushes data into UI.UIData, to be consumed later by remote_ui_flush(). static void push_call(UI *ui, const char *name, Array args) { diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 10331fd5c2..59a7780651 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -81,8 +81,21 @@ void grid_line(Integer grid, Integer row, Integer col_start, Array data) void grid_scroll(Integer grid, Integer top, Integer bot, Integer left, Integer right, Integer rows, Integer cols) FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL; +void grid_destroy(Integer grid) + FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; -void popupmenu_show(Array items, Integer selected, Integer row, Integer col) +void win_pos(Integer grid, Integer win, Integer startrow, + Integer startcol, Integer width, Integer height) + FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; +void win_hide(Integer grid) + FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; +void win_scroll_over_start(void) + FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; +void win_scroll_over_reset(void) + FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; + +void popupmenu_show(Array items, Integer selected, + Integer row, Integer col, Integer grid) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void popupmenu_hide(void) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ecfff1ea8f..2a724a85ec 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1920,13 +1920,13 @@ Object nvim_get_proc(Integer pid, Error *err) Array nvim__inspect_cell(Integer row, Integer col, Error *err) { Array ret = ARRAY_DICT_INIT; - if (row < 0 || row >= screen_Rows - || col < 0 || col >= screen_Columns) { + if (row < 0 || row >= default_grid.Rows + || col < 0 || col >= default_grid.Columns) { return ret; } - size_t off = LineOffset[(size_t)row] + (size_t)col; - ADD(ret, STRING_OBJ(cstr_to_string((char *)ScreenLines[off]))); - int attr = ScreenAttrs[off]; + size_t off = default_grid.line_offset[(size_t)row] + (size_t)col; + ADD(ret, STRING_OBJ(cstr_to_string((char *)default_grid.chars[off]))); + int attr = default_grid.attrs[off]; ADD(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, err))); // will not work first time if (!highlight_use_hlstate()) { diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index d270714611..05688790c2 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -18,6 +18,8 @@ typedef struct { // for garray_T #include "nvim/garray.h" +// for ScreenGrid +#include "nvim/grid_defs.h" // for HLF_COUNT #include "nvim/highlight_defs.h" // for pos_T, lpos_T and linenr_T @@ -1183,6 +1185,9 @@ struct window_S { int w_tagstackidx; /* idx just below active entry */ int w_tagstacklen; /* number of tags on stack */ + ScreenGrid w_grid; // the grid specific to the window + bool w_pos_changed; // true if window position changed + /* * w_fraction is the fractional row of the cursor within the window, from * 0 at the top row to FRACTION_MULT at the last row. diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 4e8bb3b0d7..c220c4e347 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1022,12 +1022,12 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he && vim_isbreak(c) && !vim_isbreak((int)s[1]) && wp->w_p_wrap - && (wp->w_width != 0)) { + && (wp->w_grid.Columns != 0)) { // Count all characters from first non-blank after a blank up to next // non-blank after a blank. numberextra = win_col_off(wp); col2 = col; - colmax = (colnr_T)(wp->w_width - numberextra - col_adj); + colmax = (colnr_T)(wp->w_grid.Columns - numberextra - col_adj); if (col >= colmax) { colmax += col_adj; @@ -1076,9 +1076,9 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he numberextra = numberwidth; col += numberextra + mb_added; - if (col >= (colnr_T)wp->w_width) { - col -= wp->w_width; - numberextra = wp->w_width - (numberextra - win_col_off2(wp)); + if (col >= (colnr_T)wp->w_grid.Columns) { + col -= wp->w_grid.Columns; + numberextra = wp->w_grid.Columns - (numberextra - win_col_off2(wp)); if (col >= numberextra && numberextra > 0) { col %= numberextra; } @@ -1097,16 +1097,17 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he numberwidth -= win_col_off2(wp); } - if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width)) { + if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_grid.Columns)) { added = 0; if (*p_sbr != NUL) { - if (size + sbrlen + numberwidth > (colnr_T)wp->w_width) { + if (size + sbrlen + numberwidth > (colnr_T)wp->w_grid.Columns) { // Calculate effective window width. - int width = (colnr_T)wp->w_width - sbrlen - numberwidth; - int prev_width = col ? ((colnr_T)wp->w_width - (sbrlen + col)) : 0; + int width = (colnr_T)wp->w_grid.Columns - sbrlen - numberwidth; + int prev_width = col ? ((colnr_T)wp->w_grid.Columns - (sbrlen + col)) + : 0; if (width == 0) { - width = (colnr_T)wp->w_width; + width = (colnr_T)wp->w_grid.Columns; } added += ((size - prev_width) / width) * vim_strsize(p_sbr); if ((size - prev_width) % width) { @@ -1175,11 +1176,11 @@ bool in_win_border(win_T *wp, colnr_T vcol) int width1; // width of first line (after line number) int width2; // width of further lines - if (wp->w_width == 0) { + if (wp->w_grid.Columns == 0) { // there is no border return false; } - width1 = wp->w_width - win_col_off(wp); + width1 = wp->w_grid.Columns - win_col_off(wp); if ((int)vcol < width1 - 1) { return false; diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 0fda941a51..ee1bc6cf31 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -120,11 +120,11 @@ static int coladvance2( --curwin->w_curswant; } } else { - int width = curwin->w_width - win_col_off(curwin); + int width = curwin->w_grid.Columns - win_col_off(curwin); if (finetune && curwin->w_p_wrap - && curwin->w_width != 0 + && curwin->w_grid.Columns != 0 && wcol >= (colnr_T)width) { csize = linetabsize(line); if (csize > 0) @@ -223,9 +223,10 @@ static int coladvance2( } else { int b = (int)wcol - (int)col; - /* The difference between wcol and col is used to set coladd. */ - if (b > 0 && b < (MAXCOL - 2 * curwin->w_width)) + // The difference between wcol and col is used to set coladd. + if (b > 0 && b < (MAXCOL - 2 * curwin->w_grid.Columns)) { pos->coladd = b; + } col += b; } @@ -436,7 +437,7 @@ bool leftcol_changed(void) bool retval = false; changed_cline_bef_curs(); - lastcol = curwin->w_leftcol + curwin->w_width - curwin_col_off() - 1; + lastcol = curwin->w_leftcol + curwin->w_grid.Columns - curwin_col_off() - 1; validate_virtcol(); /* diff --git a/src/nvim/edit.c b/src/nvim/edit.c index c04190eaba..41a2be6ad4 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -560,7 +560,7 @@ static int insert_check(VimState *state) if (curwin->w_wcol < s->mincol - curbuf->b_p_ts && curwin->w_wrow == curwin->w_winrow - + curwin->w_height - 1 - p_so + + curwin->w_grid.Rows - 1 - p_so && (curwin->w_cursor.lnum != curwin->w_topline || curwin->w_topfill > 0)) { if (curwin->w_topfill > 0) { @@ -1494,40 +1494,41 @@ void edit_putchar(int c, int highlight) { int attr; - if (ScreenLines != NULL) { - update_topline(); /* just in case w_topline isn't valid */ + if (curwin->w_grid.chars != NULL || default_grid.chars != NULL) { + update_topline(); // just in case w_topline isn't valid validate_cursor(); if (highlight) { attr = HL_ATTR(HLF_8); } else { attr = 0; } - pc_row = curwin->w_winrow + curwin->w_wrow; - pc_col = curwin->w_wincol; + pc_row = curwin->w_wrow; + pc_col = 0; pc_status = PC_STATUS_UNSET; if (curwin->w_p_rl) { - pc_col += curwin->w_width - 1 - curwin->w_wcol; + pc_col += curwin->w_grid.Columns - 1 - curwin->w_wcol; if (has_mbyte) { - int fix_col = mb_fix_col(pc_col, pc_row); + int fix_col = grid_fix_col(&curwin->w_grid, pc_col, pc_row); if (fix_col != pc_col) { - screen_putchar(' ', pc_row, fix_col, attr); - --curwin->w_wcol; + grid_putchar(&curwin->w_grid, ' ', pc_row, fix_col, attr); + curwin->w_wcol--; pc_status = PC_STATUS_RIGHT; } } } else { pc_col += curwin->w_wcol; - if (mb_lefthalve(pc_row, pc_col)) + if (grid_lefthalve(&curwin->w_grid, pc_row, pc_col)) { pc_status = PC_STATUS_LEFT; + } } /* save the character to be able to put it back */ if (pc_status == PC_STATUS_UNSET) { - screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr); + grid_getbytes(&curwin->w_grid, pc_row, pc_col, pc_bytes, &pc_attr); pc_status = PC_STATUS_SET; } - screen_putchar(c, pc_row, pc_col, attr); + grid_putchar(&curwin->w_grid, c, pc_row, pc_col, attr); } } @@ -1543,7 +1544,8 @@ void edit_unputchar(void) if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) { redrawWinline(curwin, curwin->w_cursor.lnum, false); } else { - screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); + grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col, + pc_attr); } } } @@ -1566,8 +1568,8 @@ void display_dollar(colnr_T col) char_u *p = get_cursor_line_ptr(); curwin->w_cursor.col -= utf_head_off(p, p + col); curs_columns(false); // Recompute w_wrow and w_wcol - if (curwin->w_wcol < curwin->w_width) { - edit_putchar('$', FALSE); + if (curwin->w_wcol < curwin->w_grid.Columns) { + edit_putchar('$', false); dollar_vcol = curwin->w_virtcol; } curwin->w_cursor.col = save_col; @@ -5825,7 +5827,7 @@ static void check_auto_format( /* * Find out textwidth to be used for formatting: * if 'textwidth' option is set, use it - * else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin' + * else if 'wrapmargin' option is set, use curwin->w_grid.Columns-'wrapmargin' * if invalid value, use 0. * Set default to window width (maximum 79) for "gq" operator. */ @@ -5840,9 +5842,10 @@ comp_textwidth ( if (textwidth == 0 && curbuf->b_p_wm) { /* The width is the window width minus 'wrapmargin' minus all the * things that add to the margin. */ - textwidth = curwin->w_width - curbuf->b_p_wm; - if (cmdwin_type != 0) + textwidth = curwin->w_grid.Columns - curbuf->b_p_wm; + if (cmdwin_type != 0) { textwidth -= 1; + } textwidth -= curwin->w_p_fdc; if (signcolumn_on(curwin)) { @@ -5855,9 +5858,10 @@ comp_textwidth ( if (textwidth < 0) textwidth = 0; if (ff && textwidth == 0) { - textwidth = curwin->w_width - 1; - if (textwidth > 79) + textwidth = curwin->w_grid.Columns - 1; + if (textwidth > 79) { textwidth = 79; + } } return textwidth; } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index d67818aa81..3a231ab8f1 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -14023,11 +14023,11 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) const int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1; const int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1; - if (row < 0 || row >= screen_Rows - || col < 0 || col >= screen_Columns) { + if (row < 0 || row >= default_grid.Rows + || col < 0 || col >= default_grid.Columns) { c = -1; } else { - c = ScreenAttrs[LineOffset[row] + col]; + c = default_grid.attrs[default_grid.line_offset[row] + col]; } rettv->vval.v_number = c; } @@ -14042,12 +14042,12 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) const int row = tv_get_number_chk(&argvars[0], NULL) - 1; const int col = tv_get_number_chk(&argvars[1], NULL) - 1; - if (row < 0 || row >= screen_Rows - || col < 0 || col >= screen_Columns) { + if (row < 0 || row >= default_grid.Rows + || col < 0 || col >= default_grid.Columns) { c = -1; } else { - off = LineOffset[row] + col; - c = utf_ptr2char(ScreenLines[off]); + off = default_grid.line_offset[row] + col; + c = utf_ptr2char(default_grid.chars[off]); } rettv->vval.v_number = c; } @@ -16774,10 +16774,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - uint16_t term_width = MAX(0, curwin->w_width - win_col_off(curwin)); + uint16_t term_width = MAX(0, curwin->w_grid.Columns - win_col_off(curwin)); Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, true, false, false, cwd, - term_width, curwin->w_height, + term_width, curwin->w_grid.Rows, xstrdup("xterm-256color"), &rettv->vval.v_number); if (rettv->vval.v_number <= 0) { diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 36c4e333cf..0067445b38 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -256,10 +256,12 @@ void ex_align(exarg_T *eap) */ if (width <= 0) width = curbuf->b_p_tw; - if (width == 0 && curbuf->b_p_wm > 0) - width = curwin->w_width - curbuf->b_p_wm; - if (width <= 0) + if (width == 0 && curbuf->b_p_wm > 0) { + width = curwin->w_grid.Columns - curbuf->b_p_wm; + } + if (width <= 0) { width = 80; + } } if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL) @@ -2870,11 +2872,11 @@ void ex_z(exarg_T *eap) // Vi compatible: ":z!" uses display height, without a count uses // 'scroll' if (eap->forceit) { - bigness = curwin->w_height; + bigness = curwin->w_grid.Rows; } else if (ONE_WINDOW) { bigness = curwin->w_p_scr * 2; } else { - bigness = curwin->w_height - 3; + bigness = curwin->w_grid.Rows - 3; } if (bigness < 1) { bigness = 1; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 4ef332186e..8bc6193d08 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -9194,10 +9194,10 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin) /* restore height when not full height */ if (wp->w_height + wp->w_status_height < topframe->fr_height && (fprintf(fd, - "exe '%dresize ' . ((&lines * %" PRId64 - " + %" PRId64 ") / %" PRId64 ")", - n, (int64_t)wp->w_height, - (int64_t)(Rows / 2), (int64_t)Rows) < 0 + "exe '%dresize ' . ((&lines * %" PRId64 + " + %" PRId64 ") / %" PRId64 ")", + n, (int64_t)wp->w_grid.Rows, + (int64_t)(Rows / 2), (int64_t)Rows) < 0 || put_eol(fd) == FAIL)) return FAIL; @@ -9459,8 +9459,8 @@ put_view( " * winheight(0) + %" PRId64 ") / %" PRId64 ")", (int64_t)wp->w_cursor.lnum, (int64_t)(wp->w_cursor.lnum - wp->w_topline), - (int64_t)(wp->w_height / 2), - (int64_t)wp->w_height) < 0 + (int64_t)(wp->w_grid.Rows / 2), + (int64_t)wp->w_grid.Rows) < 0 || put_eol(fd) == FAIL || put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL || put_line(fd, "exe s:l") == FAIL diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 94702a9a3a..53e9846c2d 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2120,8 +2120,8 @@ static int vgetorpeek(int advance) ++col; } curwin->w_wrow = curwin->w_cline_row - + curwin->w_wcol / curwin->w_width; - curwin->w_wcol %= curwin->w_width; + + curwin->w_wcol / curwin->w_grid.Columns; + curwin->w_wcol %= curwin->w_grid.Columns; curwin->w_wcol += curwin_col_off(); col = 0; /* no correction needed */ } else { @@ -2129,8 +2129,8 @@ static int vgetorpeek(int advance) col = curwin->w_cursor.col - 1; } } else if (curwin->w_p_wrap && curwin->w_wrow) { - --curwin->w_wrow; - curwin->w_wcol = curwin->w_width - 1; + curwin->w_wrow--; + curwin->w_wcol = curwin->w_grid.Columns - 1; col = curwin->w_cursor.col - 1; } if (col > 0 && curwin->w_wcol > 0) { diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 04ff1320ce..f2bd6408e8 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -91,9 +91,10 @@ EXTERN struct nvim_stats_s { /* * Number of Rows and Columns in the screen. * Must be long to be able to use them as options in option.c. - * Note: Use screen_Rows and screen_Columns to access items in ScreenLines[]. - * They may have different values when the screen wasn't (re)allocated yet - * after setting Rows or Columns (e.g., when starting up). + * Note: Use default_grid.Rows and default_grid.Columns to access items in + * default_grid.chars[]. They may have different values when the screen + * wasn't (re)allocated yet after setting Rows or Columns (e.g., when starting + * up). */ #define DFLT_COLS 80 // default value for 'columns' #define DFLT_ROWS 24 // default value for 'lines' @@ -129,45 +130,6 @@ typedef off_t off_T; #endif /* - * The characters and attributes cached for the screen. - */ -typedef char_u schar_T[(MAX_MCO+1) * 4 + 1]; -typedef int16_t sattr_T; - -/// ScreenLines[] contains a copy of the whole screen, as it currently is -/// displayed. It is a single block of screen cells, the size of the screen -/// plus one line. The extra line used as a buffer while redrawing a window -/// line, so it can be compared with the previous state of that line. This way -/// we can avoid sending bigger updates than neccessary to the Ul layer. -/// -/// Screen cells are stored as NUL-terminated UTF-8 strings, and a cell can -/// contain up to MAX_MCO composing characters after the base character. -/// The composing characters are to be drawn on top of the original character. -/// The content after the NUL is not defined (so comparison must be done a -/// single cell at a time). Double-width characters are stored in the left cell, -/// and the right cell should only contain the empty string. When a part of the -/// screen is cleared, the cells should be filled with a single whitespace char. -/// -/// ScreenAttrs[] contains the highlighting attribute for each cell. -/// LineOffset[n] is the offset from ScreenLines[] and ScreenAttrs[] for the -/// start of line 'n'. These offsets are in general not linear, as full screen -/// scrolling is implemented by rotating the offsets in the LineOffset array. -/// LineWraps[] is an array of boolean flags indicating if the screen line wraps -/// to the next line. It can only be true if a window occupies the entire screen -/// width. -/// -/// -/// Note: before the screen is initialized and when out of memory these can be -/// NULL. -EXTERN schar_T *ScreenLines INIT(= NULL); -EXTERN sattr_T *ScreenAttrs INIT(= NULL); -EXTERN unsigned *LineOffset INIT(= NULL); -EXTERN char_u *LineWraps INIT(= NULL); /* line wraps to next line */ - -EXTERN int screen_Rows INIT(= 0); /* actual size of ScreenLines[] */ -EXTERN int screen_Columns INIT(= 0); /* actual size of ScreenLines[] */ - -/* * When vgetc() is called, it sets mod_mask to the set of modifiers that are * held down based on the MOD_MASK_* symbols that are read first. */ @@ -228,11 +190,8 @@ EXTERN int compl_cont_status INIT(= 0); # define CONT_LOCAL 32 /* for ctrl_x_mode 0, ^X^P/^X^N do a local * expansion, (eg use complete=.) */ -/* - * Functions for putting characters in the command line, - * while keeping ScreenLines[] updated. - */ -EXTERN int cmdmsg_rl INIT(= FALSE); /* cmdline is drawn right to left */ +// state for putting characters in the message area +EXTERN int cmdmsg_rl INIT(= false); // cmdline is drawn right to left EXTERN int msg_col; EXTERN int msg_row; EXTERN int msg_scrolled; /* Number of screen lines that windows have diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h new file mode 100644 index 0000000000..37d85ead0c --- /dev/null +++ b/src/nvim/grid_defs.h @@ -0,0 +1,59 @@ +#ifndef NVIM_GRID_DEFS_H +#define NVIM_GRID_DEFS_H + +#include <stdint.h> + +#include "nvim/types.h" + +#define MAX_MCO 6 // maximum value for 'maxcombine' + +// The characters and attributes drawn on grids. +typedef char_u schar_T[(MAX_MCO+1) * 4 + 1]; +typedef int16_t sattr_T; + +/// ScreenGrid represents a resizable rectuangular grid displayed by UI clients. +/// +/// chars[] contains the UTF-8 text that is currently displayed on the grid. +/// It is stored as a single block of cells. When redrawing a part of the grid, +/// the new state can be compared with the existing state of the grid. This way +/// we can avoid sending bigger updates than neccessary to the Ul layer. +/// +/// Screen cells are stored as NUL-terminated UTF-8 strings, and a cell can +/// contain up to MAX_MCO composing characters after the base character. +/// The composing characters are to be drawn on top of the original character. +/// The content after the NUL is not defined (so comparison must be done a +/// single cell at a time). Double-width characters are stored in the left cell, +/// and the right cell should only contain the empty string. When a part of the +/// screen is cleared, the cells should be filled with a single whitespace char. +/// +/// attrs[] contains the highlighting attribute for each cell. +/// line_offset[n] is the offset from chars[] and attrs[] for the +/// start of line 'n'. These offsets are in general not linear, as full screen +/// scrolling is implemented by rotating the offsets in the line_offset array. +/// line_wraps[] is an array of boolean flags indicating if the screen line +/// wraps to the next line. It can only be true if a window occupies the entire +/// screen width. +typedef struct { + handle_T handle; + + schar_T *chars; + sattr_T *attrs; + unsigned *line_offset; + char_u *line_wraps; + + // the size of the allocated grid. + int Rows; + int Columns; + + // offsets for the grid relative to the global screen + int row_offset; + int col_offset; + + // grid size requested by the UI. Used for window grids only. + int requested_rows; + int requested_cols; + + int was_resized; +} ScreenGrid; + +#endif // NVIM_GRID_DEFS_H diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index a8731d5bd7..983dbb7bbe 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -582,8 +582,9 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, */ static void prt_message(char_u *s) { - screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); - screen_puts(s, (int)Rows - 1, 0, HL_ATTR(HLF_R)); + grid_fill(&default_grid, (int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', + 0); + grid_puts(&default_grid, s, (int)Rows - 1, 0, HL_ATTR(HLF_R)); ui_flush(); } diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 5a9727f46e..41d60fa3ea 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -98,7 +98,7 @@ static int get_attr_entry(HlEntry entry) return id; } -/// When a UI connects, we need to send it the table of higlights used so far. +/// When a UI connects, we need to send it the table of highlights used so far. void ui_send_all_hls(UI *ui) { for (size_t i = 1; i < kv_size(attr_entries); i++ |