diff options
author | bfredl <bjorn.linse@gmail.com> | 2023-11-03 20:25:52 +0100 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2023-11-05 21:19:35 +0100 |
commit | 83db9115af94992a2fb32e927b7349283434ff5d (patch) | |
tree | 63f3d371491755e8b6bdbb8648d396ffba5a4218 | |
parent | acc646ad8fc3ef11fcc63b69f3d8484e4a91accd (diff) | |
download | rneovim-83db9115af94992a2fb32e927b7349283434ff5d.tar.gz rneovim-83db9115af94992a2fb32e927b7349283434ff5d.tar.bz2 rneovim-83db9115af94992a2fb32e927b7349283434ff5d.zip |
refactor(grid): reimplement 'rightleft' as a post-processing step
problem: checks for wp->w_p_rl are all over the place, making simple
things like "advance column one cell" incredibly complicated.
solution: always fill linebuf_char[] using an incrementing counter,
and then mirror the buffer as a post-processing step
This was "easier" that I first feared, because the stupid but simple
workaround for things like keeping linenumbers still left-right,
e.g. "mirror them and them mirror them once more" is more or less
what vim did already. So let's just keep doing that.
-rw-r--r-- | src/nvim/charset.c | 4 | ||||
-rw-r--r-- | src/nvim/drawline.c | 254 | ||||
-rw-r--r-- | src/nvim/grid.c | 34 | ||||
-rw-r--r-- | src/nvim/spellsuggest.c | 4 |
4 files changed, 97 insertions, 199 deletions
diff --git a/src/nvim/charset.c b/src/nvim/charset.c index eb858b8d5e..95229c5ffb 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -650,9 +650,9 @@ size_t transchar_hex(char *const buf, const int c) /// Mirror text "str" for right-left displaying. /// Only works for single-byte characters (e.g., numbers). -void rl_mirror_ascii(char *str) +void rl_mirror_ascii(char *str, char *end) { - for (char *p1 = str, *p2 = str + strlen(str) - 1; p1 < p2; p1++, p2--) { + for (char *p1 = str, *p2 = (end ? end : str + strlen(str)) - 1; p1 < p2; p1++, p2--) { char t = *p1; *p1 = *p2; *p2 = t; diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index a28b6a8aa1..c353583dfa 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -201,20 +201,13 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col) prev_col_off = cur_col_off; } -/// If one half of a double-width char will be overwritten, -/// change the other half to a space so that grid redraws properly. -static void line_check_overwrite(schar_T *dest, int cells, int maxcells, bool rl) -{ - assert(cells > 0); - if (cells < maxcells && dest[rl ? -cells + 1 : cells] == 0) { - dest[rl ? -cells : cells] = schar_from_ascii(' '); - } -} - /// Put a single char from an UTF-8 buffer into a line buffer. /// +/// If `*pp` is a double-width char and only one cell is left, emit a space, +/// and don't advance *pp +/// /// Handles composing chars -static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells, bool rl, int vcol) +static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells, int vcol) { const char *p = *pp; int cells = utf_ptr2cells(p); @@ -222,17 +215,21 @@ static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells int u8c, u8cc[MAX_MCO]; assert(maxcells > 0); if (cells > maxcells) { - return -1; + dest[0] = schar_from_ascii(' '); + return 1; } + u8c = utfc_ptr2char(p, u8cc); if (*p == TAB) { cells = MIN(tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array), maxcells); } - line_check_overwrite(dest, cells, maxcells, rl); + if (cells < maxcells && dest[cells] == 0) { + dest[cells] = schar_from_ascii(' '); + } if (*p == TAB) { for (int c = 0; c < cells; c++) { - dest[rl ? -c : c] = schar_from_ascii(' '); + dest[c] = schar_from_ascii(' '); } goto done; } else if ((uint8_t)(*p) < 0x80 && u8cc[0] == 0) { @@ -241,7 +238,7 @@ static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells dest[0] = schar_from_cc(u8c, u8cc); } if (cells > 1) { - dest[rl ? -1 : 1] = 0; + dest[1] = 0; } done: *pp += c_len; @@ -251,7 +248,7 @@ done: static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int win_row) { DecorState *state = &decor_state; - const int max_col = wp->w_p_rl ? -1 : wp->w_grid.cols; + const int max_col = wp->w_grid.cols; int right_pos = max_col; bool do_eol = state->eol_col > -1; for (size_t i = 0; i < kv_size(state->active); i++) { @@ -262,20 +259,12 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int if (item->draw_col == -1) { bool updated = true; if (item->decor.virt_text_pos == kVTRightAlign) { - if (wp->w_p_rl) { - right_pos += item->decor.virt_text_width; - } else { - right_pos -= item->decor.virt_text_width; - } + right_pos -= item->decor.virt_text_width; item->draw_col = right_pos; } else if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) { item->draw_col = state->eol_col; } else if (item->decor.virt_text_pos == kVTWinCol) { - if (wp->w_p_rl) { - item->draw_col = MIN(col_off - item->decor.col, wp->w_grid.cols - 1); - } else { - item->draw_col = MAX(col_off + item->decor.col, 0); - } + item->draw_col = MAX(col_off + item->decor.col, 0); } else { updated = false; } @@ -295,35 +284,27 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int kv_push(win_extmark_arr, m); } if (kv_size(item->decor.virt_text)) { - int vcol = wp->w_p_rl ? col_off - item->draw_col : item->draw_col - col_off; + int vcol = item->draw_col - col_off; col = draw_virt_text_item(buf, item->draw_col, item->decor.virt_text, - item->decor.hl_mode, max_col, vcol, wp->w_p_rl); + item->decor.hl_mode, max_col, vcol); } item->draw_col = INT_MIN; // deactivate if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) { - if (wp->w_p_rl) { - state->eol_col = col - 1; - } else { - state->eol_col = col + 1; - } + state->eol_col = col + 1; } - if (wp->w_p_rl) { - *end_col = MIN(*end_col, col); - } else { - *end_col = MAX(*end_col, col); - } + *end_col = MAX(*end_col, col); } } static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, int max_col, - int vcol, bool rl) + int vcol) { const char *p = ""; int virt_attr = 0; size_t virt_pos = 0; - while (rl ? col > max_col : col < max_col) { + while (col < max_col) { if (!*p) { if (virt_pos >= kv_size(vt)) { break; @@ -348,23 +329,12 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, attr = virt_attr; } schar_T dummy[2]; - int maxcells = rl ? col - max_col : max_col - col; + int maxcells = max_col - col; int cells = line_putchar(buf, &p, through ? dummy : &linebuf_char[col], - maxcells, rl, vcol); - // If we failed to emit a char, we still need to put a space and advance. - if (cells < 1) { - assert(!through); - cells = 1; - line_check_overwrite(&linebuf_char[col], cells, maxcells, rl); - linebuf_char[col] = schar_from_ascii(' '); - } + maxcells, vcol); for (int c = 0; c < cells; c++) { linebuf_attr[col] = attr; - if (rl) { - col--; - } else { - col++; - } + col++; } vcol += cells; } @@ -642,15 +612,9 @@ static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int num_signs, int si *wlv->p_extra = '-'; } } - if (wp->w_p_rl) { // reverse line numbers - // like rl_mirror_ascii(), but keep the space at the end - char *p2 = skipwhite(wlv->extra); - p2 = skiptowhite(p2) - 1; - for (char *p1 = skipwhite(wlv->extra); p1 < p2; p1++, p2--) { - const char t = *p1; - *p1 = *p2; - *p2 = t; - } + if (wp->w_p_rl) { // reverse line numbers + char *num = skipwhite(wlv->extra); + rl_mirror_ascii(num, skiptowhite(num)); } wlv->p_extra = wlv->extra; wlv->c_extra = NUL; @@ -808,11 +772,7 @@ static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv) // clear-to-end-of-line. wlv->c_extra = ' '; wlv->c_final = NUL; - if (wp->w_p_rl) { - wlv->n_extra = wlv->col + 1; - } else { - wlv->n_extra = wp->w_grid.cols - wlv->col; - } + wlv->n_extra = wp->w_grid.cols - wlv->col; wlv->char_attr = 0; } else if (wlv->filler_todo > 0) { // Draw "deleted" diff line(s) @@ -823,11 +783,7 @@ static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv) wlv->c_extra = wp->w_p_fcs_chars.diff; wlv->c_final = NUL; } - if (wp->w_p_rl) { - wlv->n_extra = wlv->col + 1; - } else { - wlv->n_extra = wp->w_grid.cols - wlv->col; - } + wlv->n_extra = wp->w_grid.cols - wlv->col; wlv->char_attr = win_hl_attr(wp, HLF_DED); } @@ -1030,14 +986,6 @@ static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra) wlv->off = 0; wlv->need_lbr = false; - if (wp->w_p_rl) { - // Rightleft window: process the text in the normal direction, but put - // it in linebuf_char[wlv.off] from right to left. Start at the - // rightmost column of the window. - wlv->col = wp->w_grid.cols - 1; - wlv->off += wlv->col; - } - if (save_extra) { // reset the drawing state for the start of a wrapped line wlv->draw_state = WL_START; @@ -1707,9 +1655,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // Skip fold, sign and number states if 'statuscolumn' is set. wlv.draw_state = WL_STC - 1; } - if (virt_line_offset >= 0 && wp->w_p_rl) { - virt_line_offset = wp->w_grid.cols - 1 - virt_line_offset; - } } if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) { @@ -1801,7 +1746,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl || (number_only && wlv.draw_state > WL_STC)) && wlv.filler_todo <= 0) { draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row); - win_put_linebuf(wp, wlv.row, 0, wlv.col, -grid->cols, bg_attr, false); + // don't clear anything after wlv.col + win_put_linebuf(wp, wlv.row, 0, wlv.col, wlv.col, bg_attr, false); // Pretend we have finished updating the window. Except when // 'cursorcolumn' is set. if (wp->w_p_cuc) { @@ -1978,7 +1924,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // Fill rest of line with 'fold'. wlv.c_extra = wp->w_p_fcs_chars.fold; wlv.c_final = NUL; - wlv.n_extra = wp->w_p_rl ? (wlv.col + 1) : (grid->cols - wlv.col); + wlv.n_extra = grid->cols - wlv.col; } if (draw_folded && wlv.n_extra != 0 && wlv.col >= grid->cols) { @@ -2020,8 +1966,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl } // If a double-width char doesn't fit display a '>' in the last column. - if ((wp->w_p_rl ? (wlv.col <= 0) : (wlv.col >= grid->cols - 1)) - && utf_char2cells(mb_c) == 2) { + if (wlv.col >= grid->cols - 1 && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; mb_l = 1; @@ -2118,7 +2063,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // Non-BMP character : display as ? or fullwidth ?. transchar_hex(wlv.extra, mb_c); if (wp->w_p_rl) { // reverse - rl_mirror_ascii(wlv.extra); + rl_mirror_ascii(wlv.extra, NULL); } wlv.p_extra = wlv.extra; @@ -2139,8 +2084,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // If a double-width char doesn't fit display a '>' in the // last column; the character is displayed at the start of the // next line. - if ((wp->w_p_rl ? (wlv.col <= 0) : (wlv.col >= grid->cols - 1)) - && utf_char2cells(mb_c) == 2) { + if (wlv.col >= grid->cols - 1 && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; mb_utf8 = false; @@ -2546,7 +2490,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl || ((wlv.fromcol >= 0 || fromcol_prev >= 0) && wlv.tocol > wlv.vcol && VIsual_mode != Ctrl_V - && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols)) + && wlv.col < grid->cols && !(noinvcur && lnum == wp->w_cursor.lnum && wlv.vcol == wp->w_virtcol))) @@ -2581,7 +2525,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl wlv.n_extra = byte2cells(c) - 1; } if ((dy_flags & DY_UHEX) && wp->w_p_rl) { - rl_mirror_ascii(wlv.p_extra); // reverse "<12>" + rl_mirror_ascii(wlv.p_extra, NULL); // reverse "<12>" } wlv.c_extra = NUL; wlv.c_final = NUL; @@ -2610,7 +2554,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl && virtual_active() && wlv.tocol != MAXCOL && wlv.vcol < wlv.tocol - && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols))) { + && wlv.col < grid->cols) { c = ' '; ptr--; // put it back at the NUL } @@ -2652,13 +2596,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl } wlv.vcol += wlv.n_extra; if (wp->w_p_wrap && wlv.n_extra > 0) { - if (wp->w_p_rl) { - wlv.col -= wlv.n_extra; - wlv.boguscols -= wlv.n_extra; - } else { - wlv.boguscols += wlv.n_extra; - wlv.col += wlv.n_extra; - } + wlv.boguscols += wlv.n_extra; + wlv.col += wlv.n_extra; } wlv.n_extra = 0; wlv.n_attr = 0; @@ -2685,11 +2624,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl && wp == curwin && lnum == wp->w_cursor.lnum && conceal_cursor_line(wp) && (int)wp->w_virtcol <= wlv.vcol + wlv.skip_cells) { - if (wp->w_p_rl) { - wp->w_wcol = grid->cols - wlv.col + wlv.boguscols - 1; - } else { - wp->w_wcol = wlv.col - wlv.boguscols; - } + wp->w_wcol = wlv.col - wlv.boguscols; wp->w_wrow = wlv.row; did_wcol = true; wp->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL; @@ -2753,14 +2688,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl || prevcol_hl_flag)) { int n = 0; - if (wp->w_p_rl) { - if (wlv.col < 0) { - n = 1; - } - } else { - if (wlv.col >= grid->cols) { - n = -1; - } + if (wlv.col >= grid->cols) { + n = -1; } if (n != 0) { // At the window boundary, highlight the last character @@ -2786,13 +2715,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl } linebuf_attr[wlv.off] = eol_attr; linebuf_vcol[wlv.off] = MAXCOL; - if (wp->w_p_rl) { - wlv.col--; - wlv.off--; - } else { - wlv.col++; - wlv.off++; - } + wlv.col++; + wlv.off++; wlv.vcol++; eol_hl_off = 1; } @@ -2827,8 +2751,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl ? 1 : 0); if (has_decor) { - has_virttext = decor_redraw_eol(wp, &decor_state, &wlv.line_attr, - wlv.col + (wp->w_p_rl ? -eol_skip : eol_skip)); + has_virttext = decor_redraw_eol(wp, &decor_state, &wlv.line_attr, wlv.col + eol_skip); } if (((wp->w_p_cuc @@ -2868,12 +2791,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl rightmost_vcol = INT_MAX; } - int col_stride = wp->w_p_rl ? -1 : 1; - - while (wp->w_p_rl ? wlv.col >= 0 : wlv.col < grid->cols) { + while (wlv.col < grid->cols) { linebuf_char[wlv.off] = schar_from_ascii(' '); linebuf_vcol[wlv.off] = MAXCOL; - wlv.col += col_stride; + wlv.col++; if (draw_color_col) { draw_color_col = advance_color_col(VCOL_HLC, &color_cols); } @@ -2889,7 +2810,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl col_attr = hl_combine_attr(col_attr, wlv.line_attr); linebuf_attr[wlv.off] = col_attr; - wlv.off += col_stride; + wlv.off++; if (VCOL_HLC >= rightmost_vcol) { break; @@ -2901,22 +2822,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // TODO(bfredl): integrate with the common beyond-the-end-loop if (wp->w_buffer->terminal) { - // terminal buffers may need to highlight beyond the end of the - // logical line - int n = wp->w_p_rl ? -1 : 1; + // terminal buffers may need to highlight beyond the end of the logical line while (wlv.col >= 0 && wlv.col < grid->cols) { linebuf_char[wlv.off] = schar_from_ascii(' '); linebuf_attr[wlv.off] = wlv.vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[wlv.vcol]; linebuf_vcol[wlv.off] = wlv.vcol; - wlv.off += n; - wlv.vcol += n; - wlv.col += n; + wlv.off++; + wlv.vcol++; + wlv.col++; } } if (kv_size(fold_vt) > 0) { - draw_virt_text_item(buf, win_col_offset, fold_vt, kHlModeCombine, - wp->w_p_rl ? -1 : grid->cols, 0, wp->w_p_rl); + draw_virt_text_item(buf, win_col_offset, fold_vt, kHlModeCombine, grid->cols, 0); } draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row); win_put_linebuf(wp, wlv.row, 0, wlv.col, grid->cols, bg_attr, false); @@ -2941,7 +2859,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl && wp->w_p_list && !wp->w_p_wrap && wlv.filler_todo <= 0 - && (wp->w_p_rl ? wlv.col == 0 : wlv.col == grid->cols - 1) + && wlv.col == grid->cols - 1 && !has_fold) { if (has_decor && *ptr == NUL && lcs_eol_one == 0) { // Tricky: there might be a virtual text just _after_ the last char @@ -3000,11 +2918,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // Skip characters that are left of the screen for 'nowrap'. if (wlv.draw_state < WL_LINE || wlv.skip_cells <= 0) { // Store the character. - if (wp->w_p_rl && utf_char2cells(mb_c) > 1) { - // A double-wide character is: put first half in left cell. - wlv.off--; - wlv.col--; - } if (mb_utf8) { linebuf_char[wlv.off] = schar_from_cc(mb_c, u8cc); } else { @@ -3049,20 +2962,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl if (wlv.tocol == wlv.vcol) { wlv.tocol++; } - - if (wp->w_p_rl) { - // now it's time to backup one cell - wlv.off--; - wlv.col--; - } - } - if (wp->w_p_rl) { - wlv.off--; - wlv.col--; - } else { - wlv.off++; - wlv.col++; } + wlv.off++; + wlv.col++; } else if (wp->w_p_cole > 0 && is_concealing) { wlv.skip_cells--; wlv.vcol_off++; @@ -3083,35 +2985,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // of bad columns we have advanced. if (wlv.n_extra > 0) { wlv.vcol += wlv.n_extra; - if (wp->w_p_rl) { - wlv.col -= wlv.n_extra; - wlv.boguscols -= wlv.n_extra; - } else { - wlv.col += wlv.n_extra; - wlv.boguscols += wlv.n_extra; - } + wlv.col += wlv.n_extra; + wlv.boguscols += wlv.n_extra; wlv.n_extra = 0; wlv.n_attr = 0; } if (utf_char2cells(mb_c) > 1) { // Need to fill two screen columns. - if (wp->w_p_rl) { - wlv.boguscols--; - wlv.col--; - } else { - wlv.boguscols++; - wlv.col++; - } - } - - if (wp->w_p_rl) { - wlv.boguscols--; - wlv.col--; - } else { wlv.boguscols++; wlv.col++; } + + wlv.boguscols++; + wlv.col++; } else { if (wlv.n_extra > 0) { wlv.vcol += wlv.n_extra; @@ -3150,8 +3037,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl wlv.char_attr = saved_attr2; } - if (has_decor && wlv.filler_todo <= 0 - && (wp->w_p_rl ? (wlv.col < 0) : (wlv.col >= grid->cols))) { + if (has_decor && wlv.filler_todo <= 0 && wlv.col >= grid->cols) { // At the end of screen line: might need to peek for decorations just after // this position. if (!has_fold && wp->w_p_wrap && wlv.n_extra == 0) { @@ -3167,8 +3053,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // At end of screen line and there is more to come: Display the line // so far. If there is no more to display it is caught above. - if ((wp->w_p_rl ? (wlv.col < 0) : (wlv.col >= grid->cols)) - && (!has_fold || virt_line_offset >= 0) + if (wlv.col >= grid->cols && (!has_fold || virt_line_offset >= 0) && (wlv.draw_state != WL_LINE || *ptr != NUL || wlv.filler_todo > 0 @@ -3187,7 +3072,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl int draw_col = wlv.col - wlv.boguscols; if (virt_line_offset >= 0) { draw_virt_text_item(buf, virt_line_offset, kv_A(virt_lines, virt_line_index).line, - kHlModeReplace, wp->w_p_rl ? -1 : grid->cols, 0, wp->w_p_rl); + kHlModeReplace, grid->cols, 0); } else if (wlv.filler_todo <= 0) { draw_virt_text(wp, buf, win_col_offset, &draw_col, wlv.row); } @@ -3266,6 +3151,13 @@ static void win_put_linebuf(win_T *wp, int row, int coloff, int endcol, int clea { ScreenGrid *grid = &wp->w_grid; + int start_col = 0; + + if (wp->w_p_rl) { + linebuf_mirror(&start_col, &clear_width, grid->cols); + endcol = grid->cols - 1 - endcol; + } + // Take care of putting "<<<" on the first line for 'smoothscroll'. if (row == 0 && wp->w_skipcol > 0 // do not overwrite the 'showbreak' text with "<<<" @@ -3293,5 +3185,5 @@ static void win_put_linebuf(win_T *wp, int row, int coloff, int endcol, int clea } grid_adjust(&grid, &row, &coloff); - grid_put_linebuf(grid, row, coloff, 0, endcol, clear_width, wp->w_p_rl, bg_attr, wrap); + grid_put_linebuf(grid, row, coloff, start_col, endcol, clear_width, wp->w_p_rl, bg_attr, wrap); } diff --git a/src/nvim/grid.c b/src/nvim/grid.c index d59c3b4803..45bffdcab5 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -477,14 +477,21 @@ void grid_line_mirror(void) if (grid_line_first >= grid_line_last) { return; } + linebuf_mirror(&grid_line_first, &grid_line_last, grid_line_maxcol); +} + +void linebuf_mirror(int *firstp, int *lastp, int maxcol) +{ + int first = *firstp; + int last = *lastp; - size_t n = (size_t)(grid_line_last - grid_line_first); - int mirror = grid_line_maxcol - 1; // Mirrors are more fun than television. + size_t n = (size_t)(last - first); + int mirror = maxcol - 1; // Mirrors are more fun than television. schar_T *scratch_char = (schar_T *)linebuf_scratch; - memcpy(scratch_char + grid_line_first, linebuf_char + grid_line_first, n * sizeof(schar_T)); - for (int col = grid_line_first; col < grid_line_last; col++) { + memcpy(scratch_char + first, linebuf_char + first, n * sizeof(schar_T)); + for (int col = first; col < last; col++) { int rev = mirror - col; - if (col + 1 < grid_line_last && scratch_char[col + 1] == 0) { + if (col + 1 < last && scratch_char[col + 1] == 0) { linebuf_char[rev - 1] = scratch_char[col]; linebuf_char[rev] = 0; col++; @@ -495,20 +502,19 @@ void grid_line_mirror(void) // for attr and vcol: assumes doublewidth chars are self-consistent sattr_T *scratch_attr = (sattr_T *)linebuf_scratch; - memcpy(scratch_attr + grid_line_first, linebuf_attr + grid_line_first, n * sizeof(sattr_T)); - for (int col = grid_line_first; col < grid_line_last; col++) { + memcpy(scratch_attr + first, linebuf_attr + first, n * sizeof(sattr_T)); + for (int col = first; col < last; col++) { linebuf_attr[mirror - col] = scratch_attr[col]; } colnr_T *scratch_vcol = (colnr_T *)linebuf_scratch; - memcpy(scratch_vcol + grid_line_first, linebuf_vcol + grid_line_first, n * sizeof(colnr_T)); - for (int col = grid_line_first; col < grid_line_last; col++) { + memcpy(scratch_vcol + first, linebuf_vcol + first, n * sizeof(colnr_T)); + for (int col = first; col < last; col++) { linebuf_vcol[mirror - col] = scratch_vcol[col]; } - int grid_line_last_copy = grid_line_last; - grid_line_last = grid_line_maxcol - grid_line_first; - grid_line_first = grid_line_maxcol - grid_line_last_copy; + *lastp = maxcol - first; + *firstp = maxcol - last; } /// End a group of grid_line_puts calls and send the screen buffer to the UI layer. @@ -698,10 +704,10 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol } } col = endcol + 1; - endcol = (clear_width > 0 ? clear_width : -clear_width); + endcol = clear_width; } - if (p_arshape && !p_tbidi) { + if (p_arshape && !p_tbidi && endcol > col) { line_do_arabic_shape(linebuf_char + col, endcol - col); } diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index d1f63e537b..938e8cec8f 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -566,7 +566,7 @@ void spell_suggest(int count) } vim_snprintf(IObuff, IOSIZE, "%2d", i + 1); if (cmdmsg_rl) { - rl_mirror_ascii(IObuff); + rl_mirror_ascii(IObuff, NULL); } msg_puts(IObuff); @@ -592,7 +592,7 @@ void spell_suggest(int count) } if (cmdmsg_rl) { // Mirror the numbers, but keep the leading space. - rl_mirror_ascii(IObuff + 1); + rl_mirror_ascii(IObuff + 1, NULL); } msg_advance(30); msg_puts(IObuff); |