mirror of
https://github.com/neovim/neovim.git
synced 2025-10-09 19:36:40 +00:00
fix(extmarks): problems with folded virtual lines (#21930)
Problem: When a folded line has virtual lines attached, the following problems occur: - The virtual lines are drawn empty. - The 'foldtext' line is drawn empty. - The cursor is drawn incorrectly. Solution: Check whether virtual lines belong to a folded line. Fix #17027 Fix #19557 Fix #21837 Co-authored-by: zeertzjq <zeertzjq@outlook.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include "nvim/decoration.h"
|
||||
#include "nvim/drawscreen.h"
|
||||
#include "nvim/extmark.h"
|
||||
#include "nvim/fold.h"
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/highlight_group.h"
|
||||
#include "nvim/memory.h"
|
||||
@@ -550,7 +551,8 @@ void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col,
|
||||
decor_add(&decor_state, start_row, start_col, end_row, end_col, decor, true, ns_id, mark_id);
|
||||
}
|
||||
|
||||
int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
|
||||
/// @param has_fold whether line "lnum" has a fold, or kNone when not calculated yet
|
||||
int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines, TriState has_fold)
|
||||
{
|
||||
buf_T *buf = wp->w_buffer;
|
||||
if (!buf->b_virt_line_blocks) {
|
||||
@@ -564,6 +566,10 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
|
||||
int end_row = (int)lnum;
|
||||
MarkTreeIter itr[1] = { 0 };
|
||||
marktree_itr_get(buf->b_marktree, row, 0, itr);
|
||||
bool below_fold = lnum > 1 && hasFoldingWin(wp, lnum - 1, NULL, NULL, true, NULL);
|
||||
if (has_fold == kNone) {
|
||||
has_fold = hasFoldingWin(wp, lnum, NULL, NULL, true, NULL);
|
||||
}
|
||||
while (true) {
|
||||
mtkey_t mark = marktree_itr_current(itr);
|
||||
if (mark.pos.row < 0 || mark.pos.row >= end_row) {
|
||||
@@ -572,8 +578,9 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
|
||||
goto next_mark;
|
||||
}
|
||||
bool above = mark.pos.row > (lnum - 2);
|
||||
bool has_fold_cur = above ? has_fold : below_fold;
|
||||
Decoration *decor = mark.decor_full;
|
||||
if (decor && decor->virt_lines_above == above) {
|
||||
if (!has_fold_cur && decor && decor->virt_lines_above == above) {
|
||||
virt_lines += (int)kv_size(decor->virt_lines);
|
||||
if (lines) {
|
||||
kv_splice(*lines, decor->virt_lines);
|
||||
|
@@ -940,7 +940,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
area_highlighting = true;
|
||||
}
|
||||
VirtLines virt_lines = KV_INITIAL_VALUE;
|
||||
int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines);
|
||||
int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold);
|
||||
filler_lines += n_virt_lines;
|
||||
if (lnum == wp->w_topline) {
|
||||
filler_lines = wp->w_topfill;
|
||||
@@ -1507,7 +1507,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
&& has_fold
|
||||
&& col == win_col_offset
|
||||
&& n_extra == 0
|
||||
&& row == startrow) {
|
||||
&& row == startrow + filler_lines) {
|
||||
char_attr = win_hl_attr(wp, HLF_FL);
|
||||
|
||||
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
|
||||
@@ -1528,7 +1528,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
&& has_fold
|
||||
&& col < grid->cols
|
||||
&& n_extra == 0
|
||||
&& row == startrow) {
|
||||
&& row == startrow + filler_lines) {
|
||||
// fill rest of line with 'fold'
|
||||
c_extra = wp->w_p_fcs_chars.fold;
|
||||
c_final = NUL;
|
||||
@@ -1540,7 +1540,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
&& has_fold
|
||||
&& col >= grid->cols
|
||||
&& n_extra != 0
|
||||
&& row == startrow) {
|
||||
&& row == startrow + filler_lines) {
|
||||
// Truncate the folding.
|
||||
n_extra = 0;
|
||||
}
|
||||
@@ -2753,7 +2753,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
// 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 ? (col < 0) : (col >= grid->cols))
|
||||
&& foldinfo.fi_lines == 0
|
||||
&& (!has_fold || virt_line_offset >= 0)
|
||||
&& (draw_state != WL_LINE
|
||||
|| *ptr != NUL
|
||||
|| filler_todo > 0
|
||||
|
@@ -1906,7 +1906,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
||||
if (j > 0 && !wp->w_botfill && row < wp->w_grid.rows) {
|
||||
// Display filler text below last line. win_line() will check
|
||||
// for ml_line_count+1 and only draw filler lines
|
||||
foldinfo_T info = FOLDINFO_INIT;
|
||||
foldinfo_T info = { 0 };
|
||||
row = win_line(wp, wp->w_botline, row, wp->w_grid.rows,
|
||||
false, false, info, &line_providers, &provider_err);
|
||||
}
|
||||
|
@@ -20,8 +20,6 @@ typedef struct foldinfo {
|
||||
linenr_T fi_lines;
|
||||
} foldinfo_T;
|
||||
|
||||
#define FOLDINFO_INIT { 0, 0, 0, 0 }
|
||||
|
||||
EXTERN int disable_fold_update INIT(= 0);
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
|
@@ -51,7 +51,7 @@ int plines_win(win_T *wp, linenr_T lnum, bool winheight)
|
||||
/// @return Number of filler lines above lnum
|
||||
int win_get_fill(win_T *wp, linenr_T lnum)
|
||||
{
|
||||
int virt_lines = decor_virt_lines(wp, lnum, NULL);
|
||||
int virt_lines = decor_virt_lines(wp, lnum, NULL, kNone);
|
||||
|
||||
// be quick when there are no filler lines
|
||||
if (diffopt_filler()) {
|
||||
|
Reference in New Issue
Block a user