0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

patch 8.1.1966: some code in options.c fits better elsewhere

Problem:    Some code in options.c fits better elsewhere.
Solution:   Move functions from options.c to other files. (Yegappan
            Lakshmanan, closes #4889)
This commit is contained in:
Bram Moolenaar
2019-09-02 22:31:11 +02:00
parent 359ad1a6f9
commit e677df8d93
16 changed files with 1066 additions and 1071 deletions

View File

@@ -3244,17 +3244,12 @@ static long_u *insecure_flag(int opt_idx, int opt_flags);
#endif
static void set_string_option_global(int opt_idx, char_u **varp);
static char *did_set_string_option(int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char *errbuf, int opt_flags, int *value_checked);
static char *set_chars_option(char_u **varp);
#ifdef FEAT_STL_OPT
static char *check_stl_option(char_u *s);
#endif
#ifdef FEAT_CLIPBOARD
static char *check_clipboard_option(void);
#endif
#ifdef FEAT_SPELL
static char *did_set_spell_option(int is_spellfile);
static char *compile_cap_prog(synblock_T *synblock);
#endif
#ifdef FEAT_EVAL
static void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx);
#endif
@@ -3276,10 +3271,6 @@ static void check_win_options(win_T *win);
static void option_value2string(struct vimoption *, int opt_flags);
static void check_winopt(winopt_T *wop);
static int wc_use_keyname(char_u *varp, long *wcp);
#ifdef FEAT_LANGMAP
static void langmap_init(void);
static void langmap_set(void);
#endif
static void paste_option_changed(void);
static void compatible_set(void);
#ifdef FEAT_LINEBREAK
@@ -6158,7 +6149,7 @@ set_string_option(
* Return TRUE if "val" is a valid name: only consists of alphanumeric ASCII
* characters or characters in "allowed".
*/
static int
int
valid_name(char_u *val, char *allowed)
{
char_u *s;
@@ -6179,31 +6170,6 @@ valid_filetype(char_u *val)
return valid_name(val, ".-_");
}
#if defined(FEAT_SPELL) || defined(PROTO)
/*
* Return TRUE if "val" is a valid 'spellang' value.
*/
int
valid_spellang(char_u *val)
{
return valid_name(val, ".-_,@");
}
/*
* Return TRUE if "val" is a valid 'spellfile' value.
*/
static int
valid_spellfile(char_u *val)
{
char_u *s;
for (s = val; *s != NUL; ++s)
if (!vim_isfilec(*s) && *s != ',')
return FALSE;
return TRUE;
}
#endif
/*
* Handle string options that need some action to perform when changed.
* Returns NULL for success, or an error message for an error.
@@ -8000,217 +7966,6 @@ did_set_string_option(
return errmsg;
}
#if defined(FEAT_SYN_HL) || defined(PROTO)
/*
* Simple int comparison function for use with qsort()
*/
static int
int_cmp(const void *a, const void *b)
{
return *(const int *)a - *(const int *)b;
}
/*
* Handle setting 'colorcolumn' or 'textwidth' in window "wp".
* Returns error message, NULL if it's OK.
*/
char *
check_colorcolumn(win_T *wp)
{
char_u *s;
int col;
int count = 0;
int color_cols[256];
int i;
int j = 0;
if (wp->w_buffer == NULL)
return NULL; /* buffer was closed */
for (s = wp->w_p_cc; *s != NUL && count < 255;)
{
if (*s == '-' || *s == '+')
{
/* -N and +N: add to 'textwidth' */
col = (*s == '-') ? -1 : 1;
++s;
if (!VIM_ISDIGIT(*s))
return e_invarg;
col = col * getdigits(&s);
if (wp->w_buffer->b_p_tw == 0)
goto skip; /* 'textwidth' not set, skip this item */
col += wp->w_buffer->b_p_tw;
if (col < 0)
goto skip;
}
else if (VIM_ISDIGIT(*s))
col = getdigits(&s);
else
return e_invarg;
color_cols[count++] = col - 1; /* 1-based to 0-based */
skip:
if (*s == NUL)
break;
if (*s != ',')
return e_invarg;
if (*++s == NUL)
return e_invarg; /* illegal trailing comma as in "set cc=80," */
}
vim_free(wp->w_p_cc_cols);
if (count == 0)
wp->w_p_cc_cols = NULL;
else
{
wp->w_p_cc_cols = ALLOC_MULT(int, count + 1);
if (wp->w_p_cc_cols != NULL)
{
/* sort the columns for faster usage on screen redraw inside
* win_line() */
qsort(color_cols, count, sizeof(int), int_cmp);
for (i = 0; i < count; ++i)
/* skip duplicates */
if (j == 0 || wp->w_p_cc_cols[j - 1] != color_cols[i])
wp->w_p_cc_cols[j++] = color_cols[i];
wp->w_p_cc_cols[j] = -1; /* end marker */
}
}
return NULL; /* no error */
}
#endif
/*
* Handle setting 'listchars' or 'fillchars'.
* Returns error message, NULL if it's OK.
*/
static char *
set_chars_option(char_u **varp)
{
int round, i, len, entries;
char_u *p, *s;
int c1 = 0, c2 = 0, c3 = 0;
struct charstab
{
int *cp;
char *name;
};
static struct charstab filltab[] =
{
{&fill_stl, "stl"},
{&fill_stlnc, "stlnc"},
{&fill_vert, "vert"},
{&fill_fold, "fold"},
{&fill_diff, "diff"},
};
static struct charstab lcstab[] =
{
{&lcs_eol, "eol"},
{&lcs_ext, "extends"},
{&lcs_nbsp, "nbsp"},
{&lcs_prec, "precedes"},
{&lcs_space, "space"},
{&lcs_tab2, "tab"},
{&lcs_trail, "trail"},
#ifdef FEAT_CONCEAL
{&lcs_conceal, "conceal"},
#else
{NULL, "conceal"},
#endif
};
struct charstab *tab;
if (varp == &p_lcs)
{
tab = lcstab;
entries = sizeof(lcstab) / sizeof(struct charstab);
}
else
{
tab = filltab;
entries = sizeof(filltab) / sizeof(struct charstab);
}
/* first round: check for valid value, second round: assign values */
for (round = 0; round <= 1; ++round)
{
if (round > 0)
{
/* After checking that the value is valid: set defaults: space for
* 'fillchars', NUL for 'listchars' */
for (i = 0; i < entries; ++i)
if (tab[i].cp != NULL)
*(tab[i].cp) = (varp == &p_lcs ? NUL : ' ');
if (varp == &p_lcs)
{
lcs_tab1 = NUL;
lcs_tab3 = NUL;
}
else
fill_diff = '-';
}
p = *varp;
while (*p)
{
for (i = 0; i < entries; ++i)
{
len = (int)STRLEN(tab[i].name);
if (STRNCMP(p, tab[i].name, len) == 0
&& p[len] == ':'
&& p[len + 1] != NUL)
{
c2 = c3 = 0;
s = p + len + 1;
c1 = mb_ptr2char_adv(&s);
if (mb_char2cells(c1) > 1)
continue;
if (tab[i].cp == &lcs_tab2)
{
if (*s == NUL)
continue;
c2 = mb_ptr2char_adv(&s);
if (mb_char2cells(c2) > 1)
continue;
if (!(*s == ',' || *s == NUL))
{
c3 = mb_ptr2char_adv(&s);
if (mb_char2cells(c3) > 1)
continue;
}
}
if (*s == ',' || *s == NUL)
{
if (round)
{
if (tab[i].cp == &lcs_tab2)
{
lcs_tab1 = c1;
lcs_tab2 = c2;
lcs_tab3 = c3;
}
else if (tab[i].cp != NULL)
*(tab[i].cp) = c1;
}
p = s;
break;
}
}
}
if (i == entries)
return e_invarg;
if (*p == ',')
++p;
}
}
return NULL; /* no error */
}
#ifdef FEAT_STL_OPT
/*
* Check validity of options with the 'statusline' format.
@@ -8376,71 +8131,6 @@ check_clipboard_option(void)
}
#endif
#ifdef FEAT_SPELL
/*
* Handle side effects of setting 'spell'.
* Return an error message or NULL for success.
*/
static char *
did_set_spell_option(int is_spellfile)
{
char *errmsg = NULL;
win_T *wp;
int l;
if (is_spellfile)
{
l = (int)STRLEN(curwin->w_s->b_p_spf);
if (l > 0 && (l < 4
|| STRCMP(curwin->w_s->b_p_spf + l - 4, ".add") != 0))
errmsg = e_invarg;
}
if (errmsg == NULL)
{
FOR_ALL_WINDOWS(wp)
if (wp->w_buffer == curbuf && wp->w_p_spell)
{
errmsg = did_set_spelllang(wp);
break;
}
}
return errmsg;
}
/*
* Set curbuf->b_cap_prog to the regexp program for 'spellcapcheck'.
* Return error message when failed, NULL when OK.
*/
static char *
compile_cap_prog(synblock_T *synblock)
{
regprog_T *rp = synblock->b_cap_prog;
char_u *re;
if (*synblock->b_p_spc == NUL)
synblock->b_cap_prog = NULL;
else
{
/* Prepend a ^ so that we only match at one column */
re = concat_str((char_u *)"^", synblock->b_p_spc);
if (re != NULL)
{
synblock->b_cap_prog = vim_regcomp(re, RE_MAGIC);
vim_free(re);
if (synblock->b_cap_prog == NULL)
{
synblock->b_cap_prog = rp; /* restore the previous program */
return e_invarg;
}
}
}
vim_regfree(rp);
return NULL;
}
#endif
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Set the script_ctx for an option, taking care of setting the buffer- or
@@ -10839,55 +10529,6 @@ istermoption(struct vimoption *p)
return (p->fullname[0] == 't' && p->fullname[1] == '_');
}
/*
* Compute columns for ruler and shown command. 'sc_col' is also used to
* decide what the maximum length of a message on the status line can be.
* If there is a status line for the last window, 'sc_col' is independent
* of 'ru_col'.
*/
#define COL_RULER 17 /* columns needed by standard ruler */
void
comp_col(void)
{
#if defined(FEAT_CMDL_INFO)
int last_has_status = (p_ls == 2 || (p_ls == 1 && !ONE_WINDOW));
sc_col = 0;
ru_col = 0;
if (p_ru)
{
# ifdef FEAT_STL_OPT
ru_col = (ru_wid ? ru_wid : COL_RULER) + 1;
# else
ru_col = COL_RULER + 1;
# endif
/* no last status line, adjust sc_col */
if (!last_has_status)
sc_col = ru_col;
}
if (p_sc)
{
sc_col += SHOWCMD_COLS;
if (!p_ru || last_has_status) /* no need for separating space */
++sc_col;
}
sc_col = Columns - sc_col;
ru_col = Columns - ru_col;
if (sc_col <= 0) /* screen too narrow, will become a mess */
sc_col = 1;
if (ru_col <= 0)
ru_col = 1;
#else
sc_col = Columns;
ru_col = Columns;
#endif
#ifdef FEAT_EVAL
set_vim_var_nr(VV_ECHOSPACE, sc_col - 1);
#endif
}
#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
/*
* Unset local option value, similar to ":set opt<".
@@ -12307,197 +11948,6 @@ wc_use_keyname(char_u *varp, long *wcp)
return FALSE;
}
#if defined(FEAT_LANGMAP) || defined(PROTO)
/*
* Any character has an equivalent 'langmap' character. This is used for
* keyboards that have a special language mode that sends characters above
* 128 (although other characters can be translated too). The "to" field is a
* Vim command character. This avoids having to switch the keyboard back to
* ASCII mode when leaving Insert mode.
*
* langmap_mapchar[] maps any of 256 chars to an ASCII char used for Vim
* commands.
* langmap_mapga.ga_data is a sorted table of langmap_entry_T. This does the
* same as langmap_mapchar[] for characters >= 256.
*
* Use growarray for 'langmap' chars >= 256
*/
typedef struct
{
int from;
int to;
} langmap_entry_T;
static garray_T langmap_mapga;
/*
* Search for an entry in "langmap_mapga" for "from". If found set the "to"
* field. If not found insert a new entry at the appropriate location.
*/
static void
langmap_set_entry(int from, int to)
{
langmap_entry_T *entries = (langmap_entry_T *)(langmap_mapga.ga_data);
int a = 0;
int b = langmap_mapga.ga_len;
/* Do a binary search for an existing entry. */
while (a != b)
{
int i = (a + b) / 2;
int d = entries[i].from - from;
if (d == 0)
{
entries[i].to = to;
return;
}
if (d < 0)
a = i + 1;
else
b = i;
}
if (ga_grow(&langmap_mapga, 1) != OK)
return; /* out of memory */
/* insert new entry at position "a" */
entries = (langmap_entry_T *)(langmap_mapga.ga_data) + a;
mch_memmove(entries + 1, entries,
(langmap_mapga.ga_len - a) * sizeof(langmap_entry_T));
++langmap_mapga.ga_len;
entries[0].from = from;
entries[0].to = to;
}
/*
* Apply 'langmap' to multi-byte character "c" and return the result.
*/
int
langmap_adjust_mb(int c)
{
langmap_entry_T *entries = (langmap_entry_T *)(langmap_mapga.ga_data);
int a = 0;
int b = langmap_mapga.ga_len;
while (a != b)
{
int i = (a + b) / 2;
int d = entries[i].from - c;
if (d == 0)
return entries[i].to; /* found matching entry */
if (d < 0)
a = i + 1;
else
b = i;
}
return c; /* no entry found, return "c" unmodified */
}
static void
langmap_init(void)
{
int i;
for (i = 0; i < 256; i++)
langmap_mapchar[i] = i; /* we init with a one-to-one map */
ga_init2(&langmap_mapga, sizeof(langmap_entry_T), 8);
}
/*
* Called when langmap option is set; the language map can be
* changed at any time!
*/
static void
langmap_set(void)
{
char_u *p;
char_u *p2;
int from, to;
ga_clear(&langmap_mapga); /* clear the previous map first */
langmap_init(); /* back to one-to-one map */
for (p = p_langmap; p[0] != NUL; )
{
for (p2 = p; p2[0] != NUL && p2[0] != ',' && p2[0] != ';';
MB_PTR_ADV(p2))
{
if (p2[0] == '\\' && p2[1] != NUL)
++p2;
}
if (p2[0] == ';')
++p2; /* abcd;ABCD form, p2 points to A */
else
p2 = NULL; /* aAbBcCdD form, p2 is NULL */
while (p[0])
{
if (p[0] == ',')
{
++p;
break;
}
if (p[0] == '\\' && p[1] != NUL)
++p;
from = (*mb_ptr2char)(p);
to = NUL;
if (p2 == NULL)
{
MB_PTR_ADV(p);
if (p[0] != ',')
{
if (p[0] == '\\')
++p;
to = (*mb_ptr2char)(p);
}
}
else
{
if (p2[0] != ',')
{
if (p2[0] == '\\')
++p2;
to = (*mb_ptr2char)(p2);
}
}
if (to == NUL)
{
semsg(_("E357: 'langmap': Matching character missing for %s"),
transchar(from));
return;
}
if (from >= 256)
langmap_set_entry(from, to);
else
langmap_mapchar[from & 255] = to;
/* Advance to next pair */
MB_PTR_ADV(p);
if (p2 != NULL)
{
MB_PTR_ADV(p2);
if (*p == ';')
{
p = p2;
if (p[0] != NUL)
{
if (p[0] != ',')
{
semsg(_("E358: 'langmap': Extra characters after semicolon: %s"), p);
return;
}
++p;
}
break;
}
}
}
}
}
#endif
/*
* Return TRUE if format option 'x' is in effect.
* Take care of no formatting when 'paste' is set.
@@ -13012,364 +12462,6 @@ check_ff_value(char_u *p)
return check_opt_strings(p, p_ff_values, FALSE);
}
#if defined(FEAT_VARTABS) || defined(PROTO)
/*
* Set the integer values corresponding to the string setting of 'vartabstop'.
* "array" will be set, caller must free it if needed.
*/
int
tabstop_set(char_u *var, int **array)
{
int valcount = 1;
int t;
char_u *cp;
if (var[0] == NUL || (var[0] == '0' && var[1] == NUL))
{
*array = NULL;
return TRUE;
}
for (cp = var; *cp != NUL; ++cp)
{
if (cp == var || cp[-1] == ',')
{
char_u *end;
if (strtol((char *)cp, (char **)&end, 10) <= 0)
{
if (cp != end)
emsg(_(e_positive));
else
emsg(_(e_invarg));
return FALSE;
}
}
if (VIM_ISDIGIT(*cp))
continue;
if (cp[0] == ',' && cp > var && cp[-1] != ',' && cp[1] != NUL)
{
++valcount;
continue;
}
emsg(_(e_invarg));
return FALSE;
}
*array = ALLOC_MULT(int, valcount + 1);
if (*array == NULL)
return FALSE;
(*array)[0] = valcount;
t = 1;
for (cp = var; *cp != NUL;)
{
(*array)[t++] = atoi((char *)cp);
while (*cp != NUL && *cp != ',')
++cp;
if (*cp != NUL)
++cp;
}
return TRUE;
}
/*
* Calculate the number of screen spaces a tab will occupy.
* If "vts" is set then the tab widths are taken from that array,
* otherwise the value of ts is used.
*/
int
tabstop_padding(colnr_T col, int ts_arg, int *vts)
{
int ts = ts_arg == 0 ? 8 : ts_arg;
int tabcount;
colnr_T tabcol = 0;
int t;
int padding = 0;
if (vts == NULL || vts[0] == 0)
return ts - (col % ts);
tabcount = vts[0];
for (t = 1; t <= tabcount; ++t)
{
tabcol += vts[t];
if (tabcol > col)
{
padding = (int)(tabcol - col);
break;
}
}
if (t > tabcount)
padding = vts[tabcount] - (int)((col - tabcol) % vts[tabcount]);
return padding;
}
/*
* Find the size of the tab that covers a particular column.
*/
int
tabstop_at(colnr_T col, int ts, int *vts)
{
int tabcount;
colnr_T tabcol = 0;
int t;
int tab_size = 0;
if (vts == 0 || vts[0] == 0)
return ts;
tabcount = vts[0];
for (t = 1; t <= tabcount; ++t)
{
tabcol += vts[t];
if (tabcol > col)
{
tab_size = vts[t];
break;
}
}
if (t > tabcount)
tab_size = vts[tabcount];
return tab_size;
}
/*
* Find the column on which a tab starts.
*/
colnr_T
tabstop_start(colnr_T col, int ts, int *vts)
{
int tabcount;
colnr_T tabcol = 0;
int t;
int excess;
if (vts == NULL || vts[0] == 0)
return (col / ts) * ts;
tabcount = vts[0];
for (t = 1; t <= tabcount; ++t)
{
tabcol += vts[t];
if (tabcol > col)
return tabcol - vts[t];
}
excess = tabcol % vts[tabcount];
return excess + ((col - excess) / vts[tabcount]) * vts[tabcount];
}
/*
* Find the number of tabs and spaces necessary to get from one column
* to another.
*/
void
tabstop_fromto(
colnr_T start_col,
colnr_T end_col,
int ts_arg,
int *vts,
int *ntabs,
int *nspcs)
{
int spaces = end_col - start_col;
colnr_T tabcol = 0;
int padding = 0;
int tabcount;
int t;
int ts = ts_arg == 0 ? curbuf->b_p_ts : ts_arg;
if (vts == NULL || vts[0] == 0)
{
int tabs = 0;
int initspc = 0;
initspc = ts - (start_col % ts);
if (spaces >= initspc)
{
spaces -= initspc;
tabs++;
}
tabs += spaces / ts;
spaces -= (spaces / ts) * ts;
*ntabs = tabs;
*nspcs = spaces;
return;
}
/* Find the padding needed to reach the next tabstop. */
tabcount = vts[0];
for (t = 1; t <= tabcount; ++t)
{
tabcol += vts[t];
if (tabcol > start_col)
{
padding = (int)(tabcol - start_col);
break;
}
}
if (t > tabcount)
padding = vts[tabcount] - (int)((start_col - tabcol) % vts[tabcount]);
/* If the space needed is less than the padding no tabs can be used. */
if (spaces < padding)
{
*ntabs = 0;
*nspcs = spaces;
return;
}
*ntabs = 1;
spaces -= padding;
/* At least one tab has been used. See if any more will fit. */
while (spaces != 0 && ++t <= tabcount)
{
padding = vts[t];
if (spaces < padding)
{
*nspcs = spaces;
return;
}
++*ntabs;
spaces -= padding;
}
*ntabs += spaces / vts[tabcount];
*nspcs = spaces % vts[tabcount];
}
/*
* See if two tabstop arrays contain the same values.
*/
int
tabstop_eq(int *ts1, int *ts2)
{
int t;
if ((ts1 == 0 && ts2) || (ts1 && ts2 == 0))
return FALSE;
if (ts1 == ts2)
return TRUE;
if (ts1[0] != ts2[0])
return FALSE;
for (t = 1; t <= ts1[0]; ++t)
if (ts1[t] != ts2[t])
return FALSE;
return TRUE;
}
#if defined(FEAT_BEVAL) || defined(PROTO)
/*
* Copy a tabstop array, allocating space for the new array.
*/
int *
tabstop_copy(int *oldts)
{
int *newts;
int t;
if (oldts == NULL)
return NULL;
newts = ALLOC_MULT(int, oldts[0] + 1);
if (newts != NULL)
for (t = 0; t <= oldts[0]; ++t)
newts[t] = oldts[t];
return newts;
}
#endif
/*
* Return a count of the number of tabstops.
*/
int
tabstop_count(int *ts)
{
return ts != NULL ? ts[0] : 0;
}
/*
* Return the first tabstop, or 8 if there are no tabstops defined.
*/
int
tabstop_first(int *ts)
{
return ts != NULL ? ts[1] : 8;
}
#endif
/*
* Return the effective shiftwidth value for current buffer, using the
* 'tabstop' value when 'shiftwidth' is zero.
*/
long
get_sw_value(buf_T *buf)
{
return get_sw_value_col(buf, 0);
}
/*
* Idem, using "pos".
*/
static long
get_sw_value_pos(buf_T *buf, pos_T *pos)
{
pos_T save_cursor = curwin->w_cursor;
long sw_value;
curwin->w_cursor = *pos;
sw_value = get_sw_value_col(buf, get_nolist_virtcol());
curwin->w_cursor = save_cursor;
return sw_value;
}
/*
* Idem, using the first non-black in the current line.
*/
long
get_sw_value_indent(buf_T *buf)
{
pos_T pos = curwin->w_cursor;
pos.col = getwhitecols_curline();
return get_sw_value_pos(buf, &pos);
}
/*
* Idem, using virtual column "col".
*/
long
get_sw_value_col(buf_T *buf, colnr_T col UNUSED)
{
return buf->b_p_sw ? buf->b_p_sw :
#ifdef FEAT_VARTABS
tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array);
#else
buf->b_p_ts;
#endif
}
/*
* Return the effective softtabstop value for the current buffer, using the
* 'shiftwidth' value when 'softtabstop' is negative.
*/
long
get_sts_value(void)
{
return curbuf->b_p_sts < 0 ? get_sw_value(curbuf) : curbuf->b_p_sts;
}
/*
* Return the effective 'scrolloff' value for the current window, using the
* global value when appropriate.