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.c139
1 files changed, 76 insertions, 63 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 4082208dd4..1b7eeeecb8 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -126,7 +126,8 @@
// temporary buffer for rendering a single screenline, so it can be
-// comparared with previous contents to calculate smallest delta.
+// compared with previous contents to calculate smallest delta.
+// Per-cell attributes
static size_t linebuf_size = 0;
static schar_T *linebuf_char = NULL;
static sattr_T *linebuf_attr = NULL;
@@ -1814,27 +1815,6 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
col++;
}
- // 2. Add the 'foldcolumn'
- // Reduce the width when there is not enough space.
- fdc = compute_foldcolumn(wp, col);
- if (fdc > 0) {
- fill_foldcolumn(buf, wp, TRUE, lnum);
- if (wp->w_p_rl) {
- int i;
-
- copy_text_attr(off + wp->w_grid.Columns - fdc - col, buf, fdc,
- win_hl_attr(wp, HLF_FC));
- // reverse the fold column
- for (i = 0; i < fdc; i++) {
- schar_from_ascii(linebuf_char[off + wp->w_grid.Columns - i - 1 - col],
- buf[i]);
- }
- } else {
- copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC));
- }
- col += fdc;
- }
-
# define RL_MEMSET(p, v, l) \
do { \
if (wp->w_p_rl) { \
@@ -1848,6 +1828,25 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
} \
} while (0)
+ // 2. Add the 'foldcolumn'
+ // Reduce the width when there is not enough space.
+ fdc = compute_foldcolumn(wp, col);
+ if (fdc > 0) {
+ fill_foldcolumn(buf, wp, true, lnum);
+ const char_u *it = &buf[0];
+ for (int i = 0; i < fdc; i++) {
+ int mb_c = mb_ptr2char_adv(&it);
+ if (wp->w_p_rl) {
+ schar_from_char(linebuf_char[off + wp->w_grid.Columns - i - 1 - col],
+ mb_c);
+ } else {
+ schar_from_char(linebuf_char[off + col + i], mb_c);
+ }
+ }
+ RL_MEMSET(col, win_hl_attr(wp, HLF_FC), fdc);
+ col += fdc;
+ }
+
/* Set all attributes of the 'number' or 'relativenumber' column and the
* text */
RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_grid.Columns - col);
@@ -2068,58 +2067,73 @@ static void copy_text_attr(int off, char_u *buf, int len, int attr)
}
}
-/*
- * Fill the foldcolumn at "p" for window "wp".
- * Only to be called when 'foldcolumn' > 0.
- */
-static void
-fill_foldcolumn (
+/// Fills the foldcolumn at "p" for window "wp".
+/// Only to be called when 'foldcolumn' > 0.
+///
+/// @param[out] p Char array to write into
+/// @param lnum Absolute current line number
+/// @param closed Whether it is in 'foldcolumn' mode
+///
+/// Assume monocell characters
+/// @return number of chars added to \param p
+static size_t
+fill_foldcolumn(
char_u *p,
win_T *wp,
- int closed, /* TRUE of FALSE */
- linenr_T lnum /* current line number */
+ int closed,
+ linenr_T lnum
)
{
int i = 0;
int level;
int first_level;
- int empty;
- int fdc = compute_foldcolumn(wp, 0);
-
+ int fdc = compute_foldcolumn(wp, 0); // available cell width
+ size_t char_counter = 0;
+ int symbol = 0;
+ int len = 0;
// Init to all spaces.
- memset(p, ' ', (size_t)fdc);
+ memset(p, ' ', MAX_MCO * fdc + 1);
level = win_foldinfo.fi_level;
- if (level > 0) {
- // If there is only one column put more info in it.
- empty = (fdc == 1) ? 0 : 1;
-
- // If the column is too narrow, we start at the lowest level that
- // fits and use numbers to indicated the depth.
- first_level = level - fdc - closed + 1 + empty;
- if (first_level < 1) {
- first_level = 1;
- }
-
- for (i = 0; i + empty < fdc; i++) {
- if (win_foldinfo.fi_lnum == lnum
- && first_level + i >= win_foldinfo.fi_low_level) {
- p[i] = '-';
- } else if (first_level == 1) {
- p[i] = '|';
- } else if (first_level + i <= 9) {
- p[i] = '0' + first_level + i;
- } else {
- p[i] = '>';
- }
- if (first_level + i == level) {
- break;
- }
+
+ // If the column is too narrow, we start at the lowest level that
+ // fits and use numbers to indicated the depth.
+ first_level = level - fdc - closed + 1;
+ if (first_level < 1) {
+ first_level = 1;
+ }
+
+ for (i = 0; i < MIN(fdc, level); i++) {
+ if (win_foldinfo.fi_lnum == lnum
+ && first_level + i >= win_foldinfo.fi_low_level) {
+ symbol = wp->w_p_fcs_chars.foldopen;
+ } else if (first_level == 1) {
+ symbol = wp->w_p_fcs_chars.foldsep;
+ } else if (first_level + i <= 9) {
+ symbol = '0' + first_level + i;
+ } else {
+ symbol = '>';
+ }
+
+ len = utf_char2bytes(symbol, &p[char_counter]);
+ char_counter += len;
+ if (first_level + i >= level) {
+ i++;
+ break;
}
}
+
if (closed) {
- p[i >= fdc ? i - 1 : i] = '+';
+ if (symbol != 0) {
+ // rollback length
+ char_counter -= len;
+ }
+ symbol = wp->w_p_fcs_chars.foldclosed;
+ len = utf_char2bytes(symbol, &p[char_counter]);
+ char_counter += len;
}
+
+ return MAX(char_counter + (fdc-i), (size_t)fdc);
}
/*
@@ -2807,9 +2821,8 @@ win_line (
// Draw the 'foldcolumn'. Allocate a buffer, "extra" may
// already be in use.
xfree(p_extra_free);
- p_extra_free = xmalloc(12 + 1);
- fill_foldcolumn(p_extra_free, wp, false, lnum);
- n_extra = fdc;
+ p_extra_free = xmalloc(MAX_MCO * fdc + 1);
+ n_extra = fill_foldcolumn(p_extra_free, wp, false, lnum);
p_extra_free[n_extra] = NUL;
p_extra = p_extra_free;
c_extra = NUL;