Patch 8.1.1966
Problem:    Some code in options.c fits better elsewhere.
Solution:   Move functions from options.c to other files. (Yegappan
            Lakshmanan, closes #4889)
Files:      src/evalfunc.c, src/globals.h, src/indent.c, src/map.c,
            src/option.c, src/proto/map.pro, src/proto/option.pro,
            src/proto/quickfix.pro, src/proto/screen.pro, src/proto/spell.pro,
            src/proto/window.pro, src/quickfix.c, src/screen.c, src/spell.c,
            src/window.c


*** ../vim-8.1.1965/src/evalfunc.c      2019-09-01 20:16:48.003438501 +0200
--- src/evalfunc.c      2019-09-02 22:17:58.065928246 +0200
***************
*** 25,31 ****
  #endif
  
  static char *e_listblobarg = N_("E899: Argument of %s must be a List or 
Blob");
- static char *e_stringreq = N_("E928: String required");
  
  #ifdef FEAT_FLOAT
  static void f_abs(typval_T *argvars, typval_T *rettv);
--- 25,30 ----
***************
*** 141,151 ****
  static void f_getftype(typval_T *argvars, typval_T *rettv);
  static void f_getjumplist(typval_T *argvars, typval_T *rettv);
  static void f_getline(typval_T *argvars, typval_T *rettv);
- static void f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED);
  static void f_getpid(typval_T *argvars, typval_T *rettv);
  static void f_getcurpos(typval_T *argvars, typval_T *rettv);
  static void f_getpos(typval_T *argvars, typval_T *rettv);
- static void f_getqflist(typval_T *argvars, typval_T *rettv);
  static void f_getreg(typval_T *argvars, typval_T *rettv);
  static void f_getregtype(typval_T *argvars, typval_T *rettv);
  static void f_gettabinfo(typval_T *argvars, typval_T *rettv);
--- 140,148 ----
***************
*** 279,287 ****
  static void f_setenv(typval_T *argvars, typval_T *rettv);
  static void f_setfperm(typval_T *argvars, typval_T *rettv);
  static void f_setline(typval_T *argvars, typval_T *rettv);
- static void f_setloclist(typval_T *argvars, typval_T *rettv);
  static void f_setpos(typval_T *argvars, typval_T *rettv);
- static void f_setqflist(typval_T *argvars, typval_T *rettv);
  static void f_setreg(typval_T *argvars, typval_T *rettv);
  static void f_settagstack(typval_T *argvars, typval_T *rettv);
  #ifdef FEAT_CRYPT
--- 276,282 ----
***************
*** 4771,4819 ****
      get_buffer_lines(curbuf, lnum, end, retlist, rettv);
  }
  
- #ifdef FEAT_QUICKFIX
-     static void
- get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
- {
-     if (what_arg->v_type == VAR_UNKNOWN)
-     {
-       if (rettv_list_alloc(rettv) == OK)
-           if (is_qf || wp != NULL)
-               (void)get_errorlist(NULL, wp, -1, rettv->vval.v_list);
-     }
-     else
-     {
-       if (rettv_dict_alloc(rettv) == OK)
-           if (is_qf || (wp != NULL))
-           {
-               if (what_arg->v_type == VAR_DICT)
-               {
-                   dict_T      *d = what_arg->vval.v_dict;
- 
-                   if (d != NULL)
-                       qf_get_properties(wp, d, rettv->vval.v_dict);
-               }
-               else
-                   emsg(_(e_dictreq));
-           }
-     }
- }
- #endif
- 
- /*
-  * "getloclist()" function
-  */
-     static void
- f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
- {
- #ifdef FEAT_QUICKFIX
-     win_T     *wp;
- 
-     wp = find_win_by_nr_or_id(&argvars[0]);
-     get_qf_loc_list(FALSE, wp, &argvars[1], rettv);
- #endif
- }
- 
  /*
   * "getpid()" function
   */
--- 4766,4771 ----
***************
*** 4895,4911 ****
  }
  
  /*
-  * "getqflist()" function
-  */
-     static void
- f_getqflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
- {
- #ifdef FEAT_QUICKFIX
-     get_qf_loc_list(TRUE, NULL, &argvars[0], rettv);
- #endif
- }
- 
- /*
   * "getreg()" function
   */
      static void
--- 4847,4852 ----
***************
*** 9626,9715 ****
  }
  
  /*
-  * Used by "setqflist()" and "setloclist()" functions
-  */
-     static void
- set_qf_ll_list(
-     win_T     *wp UNUSED,
-     typval_T  *list_arg UNUSED,
-     typval_T  *action_arg UNUSED,
-     typval_T  *what_arg UNUSED,
-     typval_T  *rettv)
- {
- #ifdef FEAT_QUICKFIX
-     static char *e_invact = N_("E927: Invalid action: '%s'");
-     char_u    *act;
-     int               action = 0;
-     static int        recursive = 0;
- #endif
- 
-     rettv->vval.v_number = -1;
- 
- #ifdef FEAT_QUICKFIX
-     if (list_arg->v_type != VAR_LIST)
-       emsg(_(e_listreq));
-     else if (recursive != 0)
-       emsg(_(e_au_recursive));
-     else
-     {
-       list_T  *l = list_arg->vval.v_list;
-       dict_T  *d = NULL;
-       int     valid_dict = TRUE;
- 
-       if (action_arg->v_type == VAR_STRING)
-       {
-           act = tv_get_string_chk(action_arg);
-           if (act == NULL)
-               return;         /* type error; errmsg already given */
-           if ((*act == 'a' || *act == 'r' || *act == ' ' || *act == 'f') &&
-                   act[1] == NUL)
-               action = *act;
-           else
-               semsg(_(e_invact), act);
-       }
-       else if (action_arg->v_type == VAR_UNKNOWN)
-           action = ' ';
-       else
-           emsg(_(e_stringreq));
- 
-       if (action_arg->v_type != VAR_UNKNOWN
-               && what_arg->v_type != VAR_UNKNOWN)
-       {
-           if (what_arg->v_type == VAR_DICT)
-               d = what_arg->vval.v_dict;
-           else
-           {
-               emsg(_(e_dictreq));
-               valid_dict = FALSE;
-           }
-       }
- 
-       ++recursive;
-       if (l != NULL && action && valid_dict && set_errorlist(wp, l, action,
-                    (char_u *)(wp == NULL ? ":setqflist()" : ":setloclist()"),
-                    d) == OK)
-           rettv->vval.v_number = 0;
-       --recursive;
-     }
- #endif
- }
- 
- /*
-  * "setloclist()" function
-  */
-     static void
- f_setloclist(typval_T *argvars, typval_T *rettv)
- {
-     win_T     *win;
- 
-     rettv->vval.v_number = -1;
- 
-     win = find_win_by_nr_or_id(&argvars[0]);
-     if (win != NULL)
-       set_qf_ll_list(win, &argvars[1], &argvars[2], &argvars[3], rettv);
- }
- 
- /*
   * "setpos()" function
   */
      static void
--- 9567,9572 ----
***************
*** 9753,9767 ****
  }
  
  /*
-  * "setqflist()" function
-  */
-     static void
- f_setqflist(typval_T *argvars, typval_T *rettv)
- {
-     set_qf_ll_list(NULL, &argvars[0], &argvars[1], &argvars[2], rettv);
- }
- 
- /*
   * "setreg()" function
   */
      static void
--- 9610,9615 ----
*** ../vim-8.1.1965/src/globals.h       2019-09-01 16:01:25.584754569 +0200
--- src/globals.h       2019-09-02 22:17:58.065928246 +0200
***************
*** 1550,1555 ****
--- 1550,1556 ----
  EXTERN char e_cannot_mod[]    INIT(= N_("E995: Cannot modify existing 
variable"));
  EXTERN char e_readonlyvar[]   INIT(= N_("E46: Cannot change read-only 
variable \"%s\""));
  EXTERN char e_readonlysbx[]   INIT(= N_("E794: Cannot set variable in the 
sandbox: \"%s\""));
+ EXTERN char e_stringreq[]     INIT(= N_("E928: String required"));
  EXTERN char e_emptykey[]      INIT(= N_("E713: Cannot use empty key for 
Dictionary"));
  EXTERN char e_dictreq[]       INIT(= N_("E715: Dictionary required"));
  EXTERN char e_listidx[]       INIT(= N_("E684: list index out of range: 
%ld"));
*** ../vim-8.1.1965/src/indent.c        2019-08-21 14:36:29.387376100 +0200
--- src/indent.c        2019-09-02 22:26:07.515680305 +0200
***************
*** 4457,4459 ****
--- 4457,4817 ----
  }
  
  #endif
+ 
+ #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;
+ }
*** ../vim-8.1.1965/src/map.c   2019-08-18 22:25:54.665447991 +0200
--- src/map.c   2019-09-02 22:26:52.303474156 +0200
***************
*** 2193,2198 ****
--- 2193,2389 ----
  }
  #endif
  
+ #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
+ }
+ 
+     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!
+  */
+     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
+ 
      static void
  do_exmap(exarg_T *eap, int isabbrev)
  {
*** ../vim-8.1.1965/src/option.c        2019-08-24 15:50:42.814107646 +0200
--- src/option.c        2019-09-02 22:17:58.069928229 +0200
***************
*** 3244,3260 ****
  #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
--- 3244,3255 ----
***************
*** 3276,3285 ****
  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
--- 3271,3276 ----
***************
*** 6158,6164 ****
   * Return TRUE if "val" is a valid name: only consists of alphanumeric ASCII
   * characters or characters in "allowed".
   */
!     static int
  valid_name(char_u *val, char *allowed)
  {
      char_u *s;
--- 6149,6155 ----
   * Return TRUE if "val" is a valid name: only consists of alphanumeric ASCII
   * characters or characters in "allowed".
   */
!     int
  valid_name(char_u *val, char *allowed)
  {
      char_u *s;
***************
*** 6179,6209 ****
      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.
--- 6170,6175 ----
***************
*** 8000,8216 ****
      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.
--- 7966,7971 ----
***************
*** 8376,8446 ****
  }
  #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
--- 8131,8136 ----
***************
*** 10839,10893 ****
      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<".
--- 10529,10534 ----
***************
*** 12307,12503 ****
      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.
--- 11948,11953 ----
***************
*** 13012,13375 ****
      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.
--- 12462,12467 ----
*** ../vim-8.1.1965/src/proto/map.pro   2019-08-01 14:26:53.196455837 +0200
--- src/proto/map.pro   2019-09-02 22:17:58.069928229 +0200
***************
*** 19,24 ****
--- 19,27 ----
  void get_maparg(typval_T *argvars, typval_T *rettv, int exact);
  void init_mappings(void);
  void add_map(char_u *map, int mode);
+ int langmap_adjust_mb(int c);
+ void langmap_init(void);
+ void langmap_set(void);
  void ex_abbreviate(exarg_T *eap);
  void ex_map(exarg_T *eap);
  void ex_unmap(exarg_T *eap);
*** ../vim-8.1.1965/src/proto/option.pro        2019-08-24 15:50:42.814107646 
+0200
--- src/proto/option.pro        2019-09-02 22:17:58.069928229 +0200
***************
*** 22,29 ****
  void set_string_option_direct(char_u *name, int opt_idx, char_u *val, int 
opt_flags, int set_sid);
  void set_string_option_direct_in_win(win_T *wp, char_u *name, int opt_idx, 
char_u *val, int opt_flags, int set_sid);
  void set_string_option_direct_in_buf(buf_T *buf, char_u *name, int opt_idx, 
char_u *val, int opt_flags, int set_sid);
! int valid_spellang(char_u *val);
! char *check_colorcolumn(win_T *wp);
  void set_term_option_sctx_idx(char *name, int opt_idx);
  int get_option_value(char_u *name, long *numval, char_u **stringval, int 
opt_flags);
  int get_option_value_strict(char_u *name, long *numval, char_u **stringval, 
int opt_type, void *from);
--- 22,28 ----
  void set_string_option_direct(char_u *name, int opt_idx, char_u *val, int 
opt_flags, int set_sid);
  void set_string_option_direct_in_win(win_T *wp, char_u *name, int opt_idx, 
char_u *val, int opt_flags, int set_sid);
  void set_string_option_direct_in_buf(buf_T *buf, char_u *name, int opt_idx, 
char_u *val, int opt_flags, int set_sid);
! int valid_name(char_u *val, char *allowed);
  void set_term_option_sctx_idx(char *name, int opt_idx);
  int get_option_value(char_u *name, long *numval, char_u **stringval, int 
opt_flags);
  int get_option_value_strict(char_u *name, long *numval, char_u **stringval, 
int opt_type, void *from);
***************
*** 38,44 ****
  void free_termoptions(void);
  void free_one_termoption(char_u *var);
  void set_term_defaults(void);
- void comp_col(void);
  void unset_global_local_option(char_u *name, void *from);
  char_u *get_equalprg(void);
  void win_copy_options(win_T *wp_from, win_T *wp_to);
--- 37,42 ----
***************
*** 51,57 ****
  void set_context_in_set_cmd(expand_T *xp, char_u *arg, int opt_flags);
  int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u 
***file);
  int ExpandOldSetting(int *num_file, char_u ***file);
- int langmap_adjust_mb(int c);
  int has_format_option(int x);
  int shortmess(int x);
  void vimrc_found(char_u *fname, char_u *envname);
--- 49,54 ----
*** ../vim-8.1.1965/src/proto/quickfix.pro      2019-08-20 20:13:40.330821936 
+0200
--- src/proto/quickfix.pro      2019-09-02 22:17:58.069928229 +0200
***************
*** 26,36 ****
  void ex_cbelow(exarg_T *eap);
  void ex_cfile(exarg_T *eap);
  void ex_vimgrep(exarg_T *eap);
- int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list);
- int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict);
  int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T 
*what);
  int set_ref_in_quickfix(int copyID);
  void ex_cbuffer(exarg_T *eap);
  void ex_cexpr(exarg_T *eap);
  void ex_helpgrep(exarg_T *eap);
  /* vim: set ft=c : */
--- 26,38 ----
  void ex_cbelow(exarg_T *eap);
  void ex_cfile(exarg_T *eap);
  void ex_vimgrep(exarg_T *eap);
  int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T 
*what);
  int set_ref_in_quickfix(int copyID);
  void ex_cbuffer(exarg_T *eap);
  void ex_cexpr(exarg_T *eap);
  void ex_helpgrep(exarg_T *eap);
+ void f_getloclist(typval_T *argvars, typval_T *rettv);
+ void f_getqflist(typval_T *argvars, typval_T *rettv);
+ void f_setloclist(typval_T *argvars, typval_T *rettv);
+ void f_setqflist(typval_T *argvars, typval_T *rettv);
  /* vim: set ft=c : */
*** ../vim-8.1.1965/src/proto/screen.pro        2019-06-14 19:23:35.502289836 
+0200
--- src/proto/screen.pro        2019-09-02 22:17:58.069928229 +0200
***************
*** 59,65 ****
--- 59,67 ----
  int redrawing(void);
  int messaging(void);
  void showruler(int always);
+ void comp_col(void);
  int number_width(win_T *wp);
  int screen_screencol(void);
  int screen_screenrow(void);
+ char *set_chars_option(char_u **varp);
  /* vim: set ft=c : */
*** ../vim-8.1.1965/src/proto/spell.pro 2019-08-20 20:13:40.330821936 +0200
--- src/proto/spell.pro 2019-09-02 22:17:58.069928229 +0200
***************
*** 34,37 ****
--- 34,41 ----
  int spell_word_start(int startcol);
  void spell_expand_check_cap(colnr_T col);
  int expand_spelling(linenr_T lnum, char_u *pat, char_u ***matchp);
+ int valid_spellang(char_u *val);
+ int valid_spellfile(char_u *val);
+ char *did_set_spell_option(int is_spellfile);
+ char *compile_cap_prog(synblock_T *synblock);
  /* vim: set ft=c : */
*** ../vim-8.1.1965/src/proto/window.pro        2019-08-30 15:46:27.188906163 
+0200
--- src/proto/window.pro        2019-09-02 22:17:58.069928229 +0200
***************
*** 82,87 ****
--- 82,88 ----
  int win_hasvertsplit(void);
  int get_win_number(win_T *wp, win_T *first_win);
  int get_tab_number(tabpage_T *tp);
+ char *check_colorcolumn(win_T *wp);
  int win_getid(typval_T *argvars);
  int win_gotoid(typval_T *argvars);
  void win_id2tabwin(typval_T *argvars, list_T *list);
*** ../vim-8.1.1965/src/quickfix.c      2019-08-20 20:13:40.334821916 +0200
--- src/quickfix.c      2019-09-02 22:27:33.731283427 +0200
***************
*** 6305,6311 ****
   * Add each quickfix error to list "list" as a dictionary.
   * If qf_idx is -1, use the current list. Otherwise, use the specified list.
   */
!     int
  get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
  {
      qf_info_T *qi = qi_arg;
--- 6305,6311 ----
   * Add each quickfix error to list "list" as a dictionary.
   * If qf_idx is -1, use the current list. Otherwise, use the specified list.
   */
!     static int
  get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
  {
      qf_info_T *qi = qi_arg;
***************
*** 6678,6684 ****
   * dictionary. 'what' contains the details to return. If 'list_idx' is -1,
   * then current list is used. Otherwise the specified list is used.
   */
!     int
  qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
  {
      qf_info_T *qi = &ql_info;
--- 6678,6684 ----
   * dictionary. 'what' contains the details to return. If 'list_idx' is -1,
   * then current list is used. Otherwise the specified list is used.
   */
!     static int
  qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
  {
      qf_info_T *qi = &ql_info;
***************
*** 7824,7828 ****
            curwin->w_llist = qi;
      }
  }
- 
  #endif /* FEAT_QUICKFIX */
--- 7824,7976 ----
            curwin->w_llist = qi;
      }
  }
  #endif /* FEAT_QUICKFIX */
+ 
+ #if defined(FEAT_EVAL) || defined(PROTO)
+ # ifdef FEAT_QUICKFIX
+     static void
+ get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
+ {
+     if (what_arg->v_type == VAR_UNKNOWN)
+     {
+       if (rettv_list_alloc(rettv) == OK)
+           if (is_qf || wp != NULL)
+               (void)get_errorlist(NULL, wp, -1, rettv->vval.v_list);
+     }
+     else
+     {
+       if (rettv_dict_alloc(rettv) == OK)
+           if (is_qf || (wp != NULL))
+           {
+               if (what_arg->v_type == VAR_DICT)
+               {
+                   dict_T      *d = what_arg->vval.v_dict;
+ 
+                   if (d != NULL)
+                       qf_get_properties(wp, d, rettv->vval.v_dict);
+               }
+               else
+                   emsg(_(e_dictreq));
+           }
+     }
+ }
+ # endif
+ 
+ /*
+  * "getloclist()" function
+  */
+     void
+ f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+ {
+ # ifdef FEAT_QUICKFIX
+     win_T     *wp;
+ 
+     wp = find_win_by_nr_or_id(&argvars[0]);
+     get_qf_loc_list(FALSE, wp, &argvars[1], rettv);
+ # endif
+ }
+ 
+ /*
+  * "getqflist()" function
+  */
+     void
+ f_getqflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+ {
+ # ifdef FEAT_QUICKFIX
+     get_qf_loc_list(TRUE, NULL, &argvars[0], rettv);
+ # endif
+ }
+ 
+ /*
+  * Used by "setqflist()" and "setloclist()" functions
+  */
+     static void
+ set_qf_ll_list(
+     win_T     *wp UNUSED,
+     typval_T  *list_arg UNUSED,
+     typval_T  *action_arg UNUSED,
+     typval_T  *what_arg UNUSED,
+     typval_T  *rettv)
+ {
+ # ifdef FEAT_QUICKFIX
+     static char *e_invact = N_("E927: Invalid action: '%s'");
+     char_u    *act;
+     int               action = 0;
+     static int        recursive = 0;
+ # endif
+ 
+     rettv->vval.v_number = -1;
+ 
+ # ifdef FEAT_QUICKFIX
+     if (list_arg->v_type != VAR_LIST)
+       emsg(_(e_listreq));
+     else if (recursive != 0)
+       emsg(_(e_au_recursive));
+     else
+     {
+       list_T  *l = list_arg->vval.v_list;
+       dict_T  *d = NULL;
+       int     valid_dict = TRUE;
+ 
+       if (action_arg->v_type == VAR_STRING)
+       {
+           act = tv_get_string_chk(action_arg);
+           if (act == NULL)
+               return;         // type error; errmsg already given
+           if ((*act == 'a' || *act == 'r' || *act == ' ' || *act == 'f') &&
+                   act[1] == NUL)
+               action = *act;
+           else
+               semsg(_(e_invact), act);
+       }
+       else if (action_arg->v_type == VAR_UNKNOWN)
+           action = ' ';
+       else
+           emsg(_(e_stringreq));
+ 
+       if (action_arg->v_type != VAR_UNKNOWN
+               && what_arg->v_type != VAR_UNKNOWN)
+       {
+           if (what_arg->v_type == VAR_DICT)
+               d = what_arg->vval.v_dict;
+           else
+           {
+               emsg(_(e_dictreq));
+               valid_dict = FALSE;
+           }
+       }
+ 
+       ++recursive;
+       if (l != NULL && action && valid_dict && set_errorlist(wp, l, action,
+                    (char_u *)(wp == NULL ? ":setqflist()" : ":setloclist()"),
+                    d) == OK)
+           rettv->vval.v_number = 0;
+       --recursive;
+     }
+ # endif
+ }
+ 
+ /*
+  * "setloclist()" function
+  */
+     void
+ f_setloclist(typval_T *argvars, typval_T *rettv)
+ {
+     win_T     *win;
+ 
+     rettv->vval.v_number = -1;
+ 
+     win = find_win_by_nr_or_id(&argvars[0]);
+     if (win != NULL)
+       set_qf_ll_list(win, &argvars[1], &argvars[2], &argvars[3], rettv);
+ }
+ 
+ /*
+  * "setqflist()" function
+  */
+     void
+ f_setqflist(typval_T *argvars, typval_T *rettv)
+ {
+     set_qf_ll_list(NULL, &argvars[0], &argvars[1], &argvars[2], rettv);
+ }
+ #endif
*** ../vim-8.1.1965/src/screen.c        2019-08-24 20:54:15.979845564 +0200
--- src/screen.c        2019-09-02 22:28:45.642952273 +0200
***************
*** 10771,10776 ****
--- 10771,10825 ----
  }
  #endif
  
+ /*
+  * 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_LINEBREAK) || defined(PROTO)
  /*
   * Return the width of the 'number' and 'relativenumber' column.
***************
*** 10840,10842 ****
--- 10889,11021 ----
      return screen_cur_row;
  }
  #endif
+ 
+ /*
+  * Handle setting 'listchars' or 'fillchars'.
+  * Returns error message, NULL if it's OK.
+  */
+     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
+ }
*** ../vim-8.1.1965/src/spell.c 2019-08-21 14:36:29.391376081 +0200
--- src/spell.c 2019-09-02 22:29:11.610832640 +0200
***************
*** 8833,8836 ****
      return ga.ga_len;
  }
  
! #endif  /* FEAT_SPELL */
--- 8833,8922 ----
      return ga.ga_len;
  }
  
! /*
!  * 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.
!  */
!     int
! valid_spellfile(char_u *val)
! {
!     char_u *s;
! 
!     for (s = val; *s != NUL; ++s)
!       if (!vim_isfilec(*s) && *s != ',')
!           return FALSE;
!     return TRUE;
! }
! 
! /*
!  * Handle side effects of setting 'spell'.
!  * Return an error message or NULL for success.
!  */
!     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.
!  */
!     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  // FEAT_SPELL
*** ../vim-8.1.1965/src/window.c        2019-09-01 20:21:53.070152262 +0200
--- src/window.c        2019-09-02 22:24:30.776125352 +0200
***************
*** 6816,6821 ****
--- 6816,6902 ----
      return TRUE;
  }
  
+ #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
+ 
  #if defined(FEAT_EVAL) || defined(PROTO)
      int
  win_getid(typval_T *argvars)
*** ../vim-8.1.1965/src/version.c       2019-09-02 21:44:55.598219399 +0200
--- src/version.c       2019-09-02 22:29:31.350741708 +0200
***************
*** 763,764 ****
--- 763,766 ----
  {   /* Add new patch number below this line */
+ /**/
+     1966,
  /**/

-- 
Apathy Error: Don't bother striking any key.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201909022032.x82KWGW9012678%40masaka.moolenaar.net.

Raspunde prin e-mail lui