diff options
Diffstat (limited to 'src/nvim/buffer.c')
| -rw-r--r-- | src/nvim/buffer.c | 160 | 
1 files changed, 89 insertions, 71 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 89baea83f8..9e82b4e80b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -846,7 +846,7 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)      enter_cleanup(&cs);      // Quitting means closing the split window, nothing else. -    win_close(curwin, true); +    win_close(curwin, true, false);      swap_exists_action = SEA_NONE;      swap_exists_did_quit = true; @@ -1237,7 +1237,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)      while (buf == curbuf             && !(curwin->w_closing || curwin->w_buffer->b_locked > 0)             && (!ONE_WINDOW || first_tabpage->tp_next != NULL)) { -      if (win_close(curwin, false) == FAIL) { +      if (win_close(curwin, false, false) == FAIL) {          break;        }      } @@ -1441,7 +1441,7 @@ void set_curbuf(buf_T *buf, int action)    set_bufref(&prevbufref, prevbuf);    set_bufref(&newbufref, buf); -  // Autocommands may delete the curren buffer and/or the buffer we want to go +  // Autocommands may delete the current buffer and/or the buffer we want to go    // to.  In those cases don't close the buffer.    if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf)        || (bufref_valid(&prevbufref) && bufref_valid(&newbufref) @@ -1454,7 +1454,11 @@ void set_curbuf(buf_T *buf, int action)      }      if (bufref_valid(&prevbufref) && !aborting()) {        win_T *previouswin = curwin; -      if (prevbuf == curbuf) { + +      // Do not sync when in Insert mode and the buffer is open in +      // another window, might be a timer doing something in another +      // window. +      if (prevbuf == curbuf && ((State & INSERT) == 0 || curbuf->b_nwindows <= 1)) {          u_sync(false);        }        close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, @@ -1494,6 +1498,11 @@ void set_curbuf(buf_T *buf, int action)   */  void enter_buffer(buf_T *buf)  { +  // Get the buffer in the current window. +  curwin->w_buffer = buf; +  curbuf = buf; +  curbuf->b_nwindows++; +    // Copy buffer and window local option values.  Not for a help buffer.    buf_copy_options(buf, BCO_ENTER | BCO_NOHELP);    if (!buf->b_help) { @@ -1504,11 +1513,6 @@ void enter_buffer(buf_T *buf)    }    foldUpdateAll(curwin);        // update folds (later). -  // Get the buffer in the current window. -  curwin->w_buffer = buf; -  curbuf = buf; -  curbuf->b_nwindows++; -    if (curwin->w_p_diff) {      diff_buf_add(curbuf);    } @@ -1896,10 +1900,8 @@ void free_buf_options(buf_T *buf, int free_p_ff)    clear_string_option(&buf->b_p_flp);    clear_string_option(&buf->b_p_isk);    clear_string_option(&buf->b_p_vsts); -  xfree(buf->b_p_vsts_nopaste); -  buf->b_p_vsts_nopaste = NULL; -  xfree(buf->b_p_vsts_array); -  buf->b_p_vsts_array = NULL; +  XFREE_CLEAR(buf->b_p_vsts_nopaste); +  XFREE_CLEAR(buf->b_p_vsts_array);    clear_string_option(&buf->b_p_vts);    XFREE_CLEAR(buf->b_p_vts_array);    clear_string_option(&buf->b_p_keymap); @@ -3326,7 +3328,7 @@ void maketitle(void)        len = (int)STRLEN(buf_p);        if (len > 100) {          len -= 100; -        len += (*mb_tail_off)(buf_p, buf_p + len) + 1; +        len += mb_tail_off(buf_p, buf_p + len) + 1;          buf_p += len;        }        STRCPY(icon_str, buf_p); @@ -3418,7 +3420,7 @@ typedef enum {  ///  /// @return The final width of the statusline  int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use_sandbox, -                     char_u fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab) +                     int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)  {    static size_t stl_items_len = 20;  // Initial value, grows as needed.    static stl_item_t *stl_items = NULL; @@ -3437,8 +3439,12 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use    if (stl_items == NULL) {      stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);      stl_groupitems = xmalloc(sizeof(int) * stl_items_len); -    stl_hltab  = xmalloc(sizeof(stl_hlrec_t) * stl_items_len); -    stl_tabtab = xmalloc(sizeof(StlClickRecord) * stl_items_len); + +    // Allocate one more, because the last element is used to indicate the +    // end of the list. +    stl_hltab  = xmalloc(sizeof(stl_hlrec_t) * (stl_items_len + 1)); +    stl_tabtab = xmalloc(sizeof(StlClickRecord) * (stl_items_len + 1)); +      stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);    } @@ -3461,9 +3467,6 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use    if (fillchar == 0) {      fillchar = ' '; -  } else if (utf_char2len(fillchar) > 1) { -    // Can't handle a multi-byte fill character yet. -    fillchar = '-';    }    // The cursor in windows other than the current one isn't always @@ -3516,8 +3519,8 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use        stl_items = xrealloc(stl_items, sizeof(stl_item_t) * new_len);        stl_groupitems = xrealloc(stl_groupitems, sizeof(int) * new_len); -      stl_hltab = xrealloc(stl_hltab, sizeof(stl_hlrec_t) * new_len); -      stl_tabtab = xrealloc(stl_tabtab, sizeof(StlClickRecord) * new_len); +      stl_hltab = xrealloc(stl_hltab, sizeof(stl_hlrec_t) * (new_len + 1)); +      stl_tabtab = xrealloc(stl_tabtab, sizeof(StlClickRecord) * (new_len + 1));        stl_separator_locations =          xrealloc(stl_separator_locations, sizeof(int) * new_len); @@ -3661,7 +3664,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use          out_p = out_p - n + 1;          // Fill up space left over by half a double-wide char.          while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) { -          *out_p++ = fillchar; +          MB_CHAR2BYTES(fillchar, out_p);          }          // } @@ -3684,14 +3687,14 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use          if (min_group_width < 0) {            min_group_width = 0 - min_group_width;            while (group_len++ < min_group_width && out_p < out_end_p) { -            *out_p++ = fillchar; +            MB_CHAR2BYTES(fillchar, out_p);            }            // If the group is right-aligned, shift everything to the right and            // prepend with filler characters.          } else {            // { Move the group to the right -          memmove(t + min_group_width - group_len, t, (size_t)(out_p - t)); -          group_len = min_group_width - group_len; +          group_len = (min_group_width - group_len) * utf_char2len(fillchar); +          memmove(t + group_len, t, (size_t)(out_p - t));            if (out_p + group_len >= (out_end_p + 1)) {              group_len = (long)(out_end_p - out_p);            } @@ -3705,7 +3708,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use            // Prepend the fill characters            for (; group_len > 0; group_len--) { -            *t++ = fillchar; +            MB_CHAR2BYTES(fillchar, t);            }          }        } @@ -4001,14 +4004,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use      case STL_VIRTCOL:      case STL_VIRTCOL_ALT: { -      // In list mode virtcol needs to be recomputed -      colnr_T virtcol = wp->w_virtcol; -      if (wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL) { -        wp->w_p_list = false; -        getvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL); -        wp->w_p_list = true; -      } -      virtcol++; +      colnr_T virtcol = wp->w_virtcol + 1;        // Don't display %V if it's the same as %c.        if (opt == STL_VIRTCOL_ALT            && (virtcol == (colnr_T)(!(State & INSERT) && empty_line @@ -4237,7 +4233,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use            if (l + 1 == minwid && fillchar == '-' && ascii_isdigit(*t)) {              *out_p++ = ' ';            } else { -            *out_p++ = fillchar; +            MB_CHAR2BYTES(fillchar, out_p);            }          }          minwid = 0; @@ -4248,20 +4244,21 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use        }        // { Copy the string text into the output buffer -      while (*t && out_p < out_end_p) { -        *out_p++ = *t++; +      for (; *t && out_p < out_end_p; t++) {          // Change a space by fillchar, unless fillchar is '-' and a          // digit follows. -        if (fillable && out_p[-1] == ' ' -            && (!ascii_isdigit(*t) || fillchar != '-')) { -          out_p[-1] = fillchar; +        if (fillable && *t == ' ' +            && (!ascii_isdigit(*(t + 1)) || fillchar != '-')) { +          MB_CHAR2BYTES(fillchar, out_p); +        } else { +          *out_p++ = *t;          }        }        // }        // For left-aligned items, fill any remaining space with the fillchar        for (; l < minwid && out_p < out_end_p; l++) { -        *out_p++ = fillchar; +        MB_CHAR2BYTES(fillchar, out_p);        }        // Otherwise if the item is a number, copy that to the output buffer. @@ -4351,7 +4348,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use      // Only free the string buffer if we allocated it.      // Note: This is not needed if `str` is pointing at `tmp`      if (opt == STL_VIM_EXPR) { -      xfree(str); +      XFREE_CLEAR(str);      }      if (num >= 0 || (!itemisflag && str && *str)) { @@ -4454,7 +4451,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use        // Fill up for half a double-wide character.        while (++width < maxwidth) { -        *trunc_p++ = fillchar; +        MB_CHAR2BYTES(fillchar, trunc_p);          *trunc_p = NUL;        }        // } @@ -4505,13 +4502,13 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use                           standard_spaces * (num_separators - 1);        for (int i = 0; i < num_separators; i++) { -        int dislocation = (i == (num_separators - 1)) -                          ? final_spaces : standard_spaces; +        int dislocation = (i == (num_separators - 1)) ? final_spaces : standard_spaces; +        dislocation *= utf_char2len(fillchar);          char_u *start = stl_items[stl_separator_locations[i]].start;          char_u *seploc = start + dislocation;          STRMOVE(seploc, start); -        for (char_u *s = start; s < seploc; s++) { -          *s = fillchar; +        for (char_u *s = start; s < seploc; ) { +          MB_CHAR2BYTES(fillchar, s);          }          for (int item_idx = stl_separator_locations[i] + 1; @@ -4576,7 +4573,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use      cur_tab_rec->def.func = NULL;    } -  // When inside update_screen we do not want redrawing a stausline, ruler, +  // When inside update_screen we do not want redrawing a statusline, ruler,    // title, etc. to trigger another redraw, it may cause an endless loop.    if (updating_screen) {      must_redraw = save_must_redraw; @@ -4830,7 +4827,7 @@ void do_arg_all(int count, int forceit, int keep_tabs)                && (first_tabpage->tp_next == NULL || !had_tab)) {              use_firstwin = true;            } else { -            win_close(wp, !buf_hide(buf) && !bufIsChanged(buf)); +            win_close(wp, !buf_hide(buf) && !bufIsChanged(buf), false);              // check if autocommands removed the next window              if (!win_valid(wpnext)) {                // start all over... @@ -5021,7 +5018,7 @@ void ex_buffer_all(exarg_T *eap)            && !ONE_WINDOW            && !(wp->w_closing                 || wp->w_buffer->b_locked > 0)) { -        win_close(wp, false); +        win_close(wp, false, false);          wpnext = firstwin;              // just in case an autocommand does                                          // something strange with windows          tpnext = first_tabpage;         // start all over... @@ -5102,7 +5099,7 @@ void ex_buffer_all(exarg_T *eap)          enter_cleanup(&cs);          // User selected Quit at ATTENTION prompt; close this window. -        win_close(curwin, true); +        win_close(curwin, true, false);          open_wins--;          swap_exists_action = SEA_NONE;          swap_exists_did_quit = true; @@ -5144,7 +5141,7 @@ void ex_buffer_all(exarg_T *eap)        // BufWrite Autocommands made the window invalid, start over        wp = lastwin;      } else if (r) { -      win_close(wp, !buf_hide(wp->w_buffer)); +      win_close(wp, !buf_hide(wp->w_buffer), false);        open_wins--;        wp = lastwin;      } else { @@ -5463,33 +5460,54 @@ bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp)    return false;  } -int buf_signcols(buf_T *buf) +static int buf_signcols_inner(buf_T *buf, int maximum)  { -  if (!buf->b_signcols_valid) { -    sign_entry_T *sign;  // a sign in the sign list -    int signcols = 0; -    int linesum = 0; -    linenr_T curline = 0; - -    FOR_ALL_SIGNS_IN_BUF(buf, sign) { -      if (sign->se_lnum > curline) { -        if (linesum > signcols) { -          signcols = linesum; +  sign_entry_T *sign;  // a sign in the sign list +  int signcols = 0; +  int linesum = 0; +  linenr_T curline = 0; + +  FOR_ALL_SIGNS_IN_BUF(buf, sign) { +    if (sign->se_lnum > curline) { +      if (linesum > signcols) { +        signcols = linesum; +        if (signcols >= maximum) { +          return maximum;          } -        curline = sign->se_lnum; -        linesum = 0; -      } -      if (sign->se_has_text_or_icon) { -        linesum++;        } +      curline = sign->se_lnum; +      linesum = 0;      } -    if (linesum > signcols) { -      signcols = linesum; +    if (sign->se_has_text_or_icon) { +      linesum++;      } +  } +  if (linesum > signcols) { +    signcols = linesum; +    if (signcols >= maximum) { +      return maximum; +    } +  } + +  return signcols; +} + +int buf_signcols(buf_T *buf, int maximum) +{ +  // The maximum can be determined from 'signcolumn' which is window scoped so +  // need to invalidate signcols if the maximum is greater than the previous +  // maximum. +  if (maximum > buf->b_signcols_max) { +    buf->b_signcols_valid = false; +  } + +  if (!buf->b_signcols_valid) { +    int signcols = buf_signcols_inner(buf, maximum);      // Check if we need to redraw      if (signcols != buf->b_signcols) {        buf->b_signcols = signcols; +      buf->b_signcols_max = maximum;        redraw_buf_later(buf, NOT_VALID);      }  | 
