aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-09-30 17:38:05 +0800
committerGitHub <noreply@github.com>2023-09-30 17:38:05 +0800
commit2af9fac0a6ce3b01f22802511cf1ed7b0734cb2e (patch)
tree289f258f9c3bcaaab42e0efb65a90d9af8853aea
parentdc6d0d2daf69e2fdadda81feb97906dbc962a239 (diff)
downloadrneovim-2af9fac0a6ce3b01f22802511cf1ed7b0734cb2e.tar.gz
rneovim-2af9fac0a6ce3b01f22802511cf1ed7b0734cb2e.tar.bz2
rneovim-2af9fac0a6ce3b01f22802511cf1ed7b0734cb2e.zip
refactor: align set_chars_option() with Vim (#25438)
Needed for completion of 'listchars'/'fillchars' values.
-rw-r--r--src/nvim/buffer_defs.h82
-rw-r--r--src/nvim/optionstr.c137
2 files changed, 121 insertions, 98 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index ebaad45960..7cf28ee0ab 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -988,6 +988,45 @@ typedef struct {
pos_T w_cursor_corr; // corrected cursor position
} pos_save_T;
+/// Characters from the 'listchars' option.
+typedef struct {
+ int eol;
+ int ext;
+ int prec;
+ int nbsp;
+ int space;
+ int tab1; ///< first tab character
+ int tab2; ///< second tab character
+ int tab3; ///< third tab character
+ int lead;
+ int trail;
+ int *multispace;
+ int *leadmultispace;
+ int conceal;
+} lcs_chars_T;
+
+/// Characters from the 'fillchars' option.
+typedef struct {
+ int stl;
+ int stlnc;
+ int wbr;
+ int horiz;
+ int horizup;
+ int horizdown;
+ int vert;
+ int vertleft;
+ int vertright;
+ int verthoriz;
+ int fold;
+ int foldopen; ///< when fold is open
+ int foldclosed; ///< when fold is closed
+ int foldsep; ///< continuous fold marker
+ int diff;
+ int msgsep;
+ int eob;
+ int lastline;
+} fcs_chars_T;
+
/// Structure which contains all information that belongs to a window.
///
/// All row numbers are relative to the start of the window, except w_winrow.
@@ -1043,44 +1082,11 @@ struct window_S {
linenr_T w_last_cursor_lnum_rnu; ///< cursor lnum when 'rnu' was last redrawn
- // 'listchars' characters. Defaults set in set_chars_option().
- struct {
- int eol;
- int ext;
- int prec;
- int nbsp;
- int space;
- int tab1; ///< first tab character
- int tab2; ///< second tab character
- int tab3; ///< third tab character
- int lead;
- int trail;
- int *multispace;
- int *leadmultispace;
- int conceal;
- } w_p_lcs_chars;
-
- // 'fillchars' characters. Defaults set in set_chars_option().
- struct {
- int stl;
- int stlnc;
- int wbr;
- int horiz;
- int horizup;
- int horizdown;
- int vert;
- int vertleft;
- int vertright;
- int verthoriz;
- int fold;
- int foldopen; ///< when fold is open
- int foldclosed; ///< when fold is closed
- int foldsep; ///< continuous fold marker
- int diff;
- int msgsep;
- int eob;
- int lastline;
- } w_p_fcs_chars;
+ /// 'listchars' characters. Defaults set in set_chars_option().
+ lcs_chars_T w_p_lcs_chars;
+
+ /// 'fillchars' characters. Defaults set in set_chars_option().
+ fcs_chars_T w_p_fcs_chars;
// "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for
// displaying the buffer.
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 3ab40b48c8..62073a2323 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -2299,6 +2299,48 @@ static int get_encoded_char_adv(const char **p)
return c;
}
+struct chars_tab {
+ int *cp; ///< char value
+ const char *name; ///< char id
+ int def; ///< default value
+ int fallback; ///< default value when "def" isn't single-width
+};
+
+static fcs_chars_T fcs_chars;
+static const struct chars_tab fcs_tab[] = {
+ { &fcs_chars.stl, "stl", ' ', NUL },
+ { &fcs_chars.stlnc, "stlnc", ' ', NUL },
+ { &fcs_chars.wbr, "wbr", ' ', NUL },
+ { &fcs_chars.horiz, "horiz", 0x2500, '-' }, // ─
+ { &fcs_chars.horizup, "horizup", 0x2534, '-' }, // ┴
+ { &fcs_chars.horizdown, "horizdown", 0x252c, '-' }, // ┬
+ { &fcs_chars.vert, "vert", 0x2502, '|' }, // │
+ { &fcs_chars.vertleft, "vertleft", 0x2524, '|' }, // ┤
+ { &fcs_chars.vertright, "vertright", 0x251c, '|' }, // ├
+ { &fcs_chars.verthoriz, "verthoriz", 0x253c, '+' }, // ┼
+ { &fcs_chars.fold, "fold", 0x00b7, '-' }, // ·
+ { &fcs_chars.foldopen, "foldopen", '-', NUL },
+ { &fcs_chars.foldclosed, "foldclose", '+', NUL },
+ { &fcs_chars.foldsep, "foldsep", 0x2502, '|' }, // │
+ { &fcs_chars.diff, "diff", '-', NUL },
+ { &fcs_chars.msgsep, "msgsep", ' ', NUL },
+ { &fcs_chars.eob, "eob", '~', NUL },
+ { &fcs_chars.lastline, "lastline", '@', NUL },
+};
+
+static lcs_chars_T lcs_chars;
+static const struct chars_tab lcs_tab[] = {
+ { &lcs_chars.eol, "eol", NUL, NUL },
+ { &lcs_chars.ext, "extends", NUL, NUL },
+ { &lcs_chars.nbsp, "nbsp", NUL, NUL },
+ { &lcs_chars.prec, "precedes", NUL, NUL },
+ { &lcs_chars.space, "space", NUL, NUL },
+ { &lcs_chars.tab2, "tab", NUL, NUL },
+ { &lcs_chars.lead, "lead", NUL, NUL },
+ { &lcs_chars.trail, "trail", NUL, NUL },
+ { &lcs_chars.conceal, "conceal", NUL, NUL },
+};
+
/// Handle setting 'listchars' or 'fillchars'.
/// Assume monocell characters
///
@@ -2314,47 +2356,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
int multispace_len = 0; // Length of lcs-multispace string
int lead_multispace_len = 0; // Length of lcs-leadmultispace string
- struct chars_tab {
- int *cp; ///< char value
- char *name; ///< char id
- int def; ///< default value
- };
-
- // XXX: Characters taking 2 columns is forbidden (TUI limitation?). Set old defaults in this case.
- struct chars_tab fcs_tab[] = {
- { &wp->w_p_fcs_chars.stl, "stl", ' ' },
- { &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' },
- { &wp->w_p_fcs_chars.wbr, "wbr", ' ' },
- { &wp->w_p_fcs_chars.horiz, "horiz", char2cells(0x2500) == 1 ? 0x2500 : '-' }, // ─
- { &wp->w_p_fcs_chars.horizup, "horizup", char2cells(0x2534) == 1 ? 0x2534 : '-' }, // ┴
- { &wp->w_p_fcs_chars.horizdown, "horizdown", char2cells(0x252c) == 1 ? 0x252c : '-' }, // ┬
- { &wp->w_p_fcs_chars.vert, "vert", char2cells(0x2502) == 1 ? 0x2502 : '|' }, // │
- { &wp->w_p_fcs_chars.vertleft, "vertleft", char2cells(0x2524) == 1 ? 0x2524 : '|' }, // ┤
- { &wp->w_p_fcs_chars.vertright, "vertright", char2cells(0x251c) == 1 ? 0x251c : '|' }, // ├
- { &wp->w_p_fcs_chars.verthoriz, "verthoriz", char2cells(0x253c) == 1 ? 0x253c : '+' }, // ┼
- { &wp->w_p_fcs_chars.fold, "fold", char2cells(0x00b7) == 1 ? 0x00b7 : '-' }, // ·
- { &wp->w_p_fcs_chars.foldopen, "foldopen", '-' },
- { &wp->w_p_fcs_chars.foldclosed, "foldclose", '+' },
- { &wp->w_p_fcs_chars.foldsep, "foldsep", char2cells(0x2502) == 1 ? 0x2502 : '|' }, // │
- { &wp->w_p_fcs_chars.diff, "diff", '-' },
- { &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' },
- { &wp->w_p_fcs_chars.eob, "eob", '~' },
- { &wp->w_p_fcs_chars.lastline, "lastline", '@' },
- };
-
- struct chars_tab lcs_tab[] = {
- { &wp->w_p_lcs_chars.eol, "eol", NUL },
- { &wp->w_p_lcs_chars.ext, "extends", NUL },
- { &wp->w_p_lcs_chars.nbsp, "nbsp", NUL },
- { &wp->w_p_lcs_chars.prec, "precedes", NUL },
- { &wp->w_p_lcs_chars.space, "space", NUL },
- { &wp->w_p_lcs_chars.tab2, "tab", NUL },
- { &wp->w_p_lcs_chars.lead, "lead", NUL },
- { &wp->w_p_lcs_chars.trail, "trail", NUL },
- { &wp->w_p_lcs_chars.conceal, "conceal", NUL },
- };
-
- struct chars_tab *tab;
+ const struct chars_tab *tab;
int entries;
if (is_listchars) {
tab = lcs_tab;
@@ -2376,31 +2378,32 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
// After checking that the value is valid: set defaults
for (int i = 0; i < entries; i++) {
if (tab[i].cp != NULL) {
- *(tab[i].cp) = tab[i].def;
+ // XXX: Characters taking 2 columns is forbidden (TUI limitation?).
+ // Set old defaults in this case.
+ *(tab[i].cp) = char2cells(tab[i].def) == 1 ? tab[i].def : tab[i].fallback;
}
}
+
if (is_listchars) {
- wp->w_p_lcs_chars.tab1 = NUL;
- wp->w_p_lcs_chars.tab3 = NUL;
+ lcs_chars.tab1 = NUL;
+ lcs_chars.tab3 = NUL;
- xfree(wp->w_p_lcs_chars.multispace);
if (multispace_len > 0) {
- wp->w_p_lcs_chars.multispace = xmalloc(((size_t)multispace_len + 1) * sizeof(int));
- wp->w_p_lcs_chars.multispace[multispace_len] = NUL;
+ lcs_chars.multispace = xmalloc(((size_t)multispace_len + 1) * sizeof(int));
+ lcs_chars.multispace[multispace_len] = NUL;
} else {
- wp->w_p_lcs_chars.multispace = NULL;
+ lcs_chars.multispace = NULL;
}
- xfree(wp->w_p_lcs_chars.leadmultispace);
if (lead_multispace_len > 0) {
- wp->w_p_lcs_chars.leadmultispace
- = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(int));
- wp->w_p_lcs_chars.leadmultispace[lead_multispace_len] = NUL;
+ lcs_chars.leadmultispace = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(int));
+ lcs_chars.leadmultispace[lead_multispace_len] = NUL;
} else {
- wp->w_p_lcs_chars.leadmultispace = NULL;
+ lcs_chars.leadmultispace = NULL;
}
}
}
+
const char *p = value;
while (*p) {
int i;
@@ -2415,7 +2418,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
return e_invarg;
}
int c2 = 0, c3 = 0;
- if (tab[i].cp == &wp->w_p_lcs_chars.tab2) {
+ if (tab[i].cp == &lcs_chars.tab2) {
if (*s == NUL) {
return e_invarg;
}
@@ -2430,12 +2433,13 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
}
}
}
+
if (*s == ',' || *s == NUL) {
if (round > 0) {
- if (tab[i].cp == &wp->w_p_lcs_chars.tab2) {
- wp->w_p_lcs_chars.tab1 = c1;
- wp->w_p_lcs_chars.tab2 = c2;
- wp->w_p_lcs_chars.tab3 = c3;
+ if (tab[i].cp == &lcs_chars.tab2) {
+ lcs_chars.tab1 = c1;
+ lcs_chars.tab2 = c2;
+ lcs_chars.tab3 = c3;
} else if (tab[i].cp != NULL) {
*(tab[i].cp) = c1;
}
@@ -2475,7 +2479,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
while (*s != NUL && *s != ',') {
int c1 = get_encoded_char_adv(&s);
if (p == last_multispace) {
- wp->w_p_lcs_chars.multispace[multispace_pos++] = c1;
+ lcs_chars.multispace[multispace_pos++] = c1;
}
}
p = s;
@@ -2506,7 +2510,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
while (*s != NUL && *s != ',') {
int c1 = get_encoded_char_adv(&s);
if (p == last_lmultispace) {
- wp->w_p_lcs_chars.leadmultispace[multispace_pos++] = c1;
+ lcs_chars.leadmultispace[multispace_pos++] = c1;
}
}
p = s;
@@ -2522,6 +2526,19 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
}
}
+ if (apply) {
+ if (is_listchars) {
+ xfree(wp->w_p_lcs_chars.multispace);
+ xfree(wp->w_p_lcs_chars.leadmultispace);
+ wp->w_p_lcs_chars = lcs_chars;
+ } else {
+ wp->w_p_fcs_chars = fcs_chars;
+ }
+ } else if (is_listchars) {
+ xfree(lcs_chars.multispace);
+ xfree(lcs_chars.leadmultispace);
+ }
+
return NULL; // no error
}