diff options
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r-- | src/nvim/buffer.c | 282 |
1 files changed, 147 insertions, 135 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 86067aceac..0ebe33f2f8 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -220,13 +220,8 @@ int open_buffer( int perm; perm = os_getperm((const char *)curbuf->b_ffname); - if (perm >= 0 && (0 -# ifdef S_ISFIFO - || S_ISFIFO(perm) -# endif -# ifdef S_ISSOCK + if (perm >= 0 && (0 || S_ISFIFO(perm) || S_ISSOCK(perm) -# endif # ifdef OPEN_CHR_FILES || (S_ISCHR(perm) && is_dev_fd_file(curbuf->b_ffname)) @@ -837,7 +832,7 @@ static void clear_wininfo(buf_T *buf) buf->b_wininfo = wip->wi_next; if (wip->wi_optset) { clear_winopt(&wip->wi_opt); - deleteFoldRecurse(&wip->wi_folds); + deleteFoldRecurse(buf, &wip->wi_folds); } xfree(wip); } @@ -1623,7 +1618,7 @@ void enter_buffer(buf_T *buf) } curbuf->b_last_used = time(NULL); - redraw_later(NOT_VALID); + redraw_later(curwin, NOT_VALID); } // Change to the directory of the current buffer. @@ -1941,6 +1936,7 @@ void free_buf_options(buf_T *buf, int free_p_ff) vim_regfree(buf->b_s.b_cap_prog); buf->b_s.b_cap_prog = NULL; clear_string_option(&buf->b_s.b_p_spl); + clear_string_option(&buf->b_s.b_p_spo); clear_string_option(&buf->b_p_sua); clear_string_option(&buf->b_p_ft); clear_string_option(&buf->b_p_cink); @@ -2502,7 +2498,7 @@ void buflist_setfpos(buf_T *const buf, win_T *const win, } if (copy_options && wip->wi_optset) { clear_winopt(&wip->wi_opt); - deleteFoldRecurse(&wip->wi_folds); + deleteFoldRecurse(buf, &wip->wi_folds); } } if (lnum != 0) { @@ -2650,7 +2646,7 @@ void buflist_list(exarg_T *eap) int i; garray_T buflist; - buf_T **buflist_data = NULL, **p; + buf_T **buflist_data = NULL; if (vim_strchr(eap->arg, 't')) { ga_init(&buflist, sizeof(buf_T *), 50); @@ -2662,13 +2658,14 @@ void buflist_list(exarg_T *eap) qsort(buflist.ga_data, (size_t)buflist.ga_len, sizeof(buf_T *), buf_time_compare); - p = buflist_data = (buf_T **)buflist.ga_data; - buf = *p; + buflist_data = (buf_T **)buflist.ga_data; + buf = *buflist_data; } + buf_T **p = buflist_data; for (; buf != NULL && !got_int; - buf = buflist_data + buf = buflist_data != NULL ? (++p < buflist_data + buflist.ga_len ? *p : NULL) : buf->b_next) { const bool is_terminal = buf->terminal; @@ -3438,31 +3435,17 @@ int build_stl_str_hl( int use_sandbox, char_u fillchar, int maxwidth, - struct stl_hlrec *hltab, - StlClickRecord *tabtab + stl_hlrec_t **hltab, + StlClickRecord **tabtab ) { - int groupitems[STL_MAX_ITEM]; - struct stl_item { - // Where the item starts in the status line output buffer - char_u *start; - // Function to run for ClickFunc items. - char *cmd; - // The minimum width of the item - int minwid; - // The maximum width of the item - int maxwid; - enum { - Normal, - Empty, - Group, - Separate, - Highlight, - TabPage, - ClickFunc, - Trunc - } type; - } items[STL_MAX_ITEM]; + static size_t stl_items_len = 20; // Initial value, grows as needed. + static stl_item_t *stl_items = NULL; + static int *stl_groupitems = NULL; + static stl_hlrec_t *stl_hltab = NULL; + static StlClickRecord *stl_tabtab = NULL; + static int *stl_separator_locations = NULL; + #define TMPLEN 70 char_u buf_tmp[TMPLEN]; char_u win_tmp[TMPLEN]; @@ -3470,6 +3453,14 @@ int build_stl_str_hl( const int save_must_redraw = must_redraw; const int save_redr_type = curwin->w_redr_type; + 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(stl_hlrec_t) * stl_items_len); + stl_separator_locations = xmalloc(sizeof(int) * stl_items_len); + } + // When the format starts with "%!" then evaluate it as an expression and // use the result as the actual format string. if (fmt[0] == '%' && fmt[1] == '!') { @@ -3538,14 +3529,17 @@ int build_stl_str_hl( // Proceed character by character through the statusline format string // fmt_p is the current positon in the input buffer for (char_u *fmt_p = usefmt; *fmt_p; ) { - if (curitem == STL_MAX_ITEM) { - // There are too many items. Add the error code to the statusline - // to give the user a hint about what went wrong. - if (out_p + 5 < out_end_p) { - memmove(out_p, " E541", (size_t)5); - out_p += 5; - } - break; + if (curitem == (int)stl_items_len) { + size_t new_len = stl_items_len * 3 / 2; + + 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_separator_locations = + xrealloc(stl_separator_locations, sizeof(int) * new_len); + + stl_items_len = new_len; } if (*fmt_p != NUL && *fmt_p != '%') { @@ -3589,16 +3583,16 @@ int build_stl_str_hl( if (groupdepth > 0) { continue; } - items[curitem].type = Separate; - items[curitem++].start = out_p; + stl_items[curitem].type = Separate; + stl_items[curitem++].start = out_p; continue; } // STL_TRUNCMARK: Where to begin truncating if the statusline is too long. if (*fmt_p == STL_TRUNCMARK) { fmt_p++; - items[curitem].type = Trunc; - items[curitem++].start = out_p; + stl_items[curitem].type = Trunc; + stl_items[curitem++].start = out_p; continue; } @@ -3614,7 +3608,7 @@ int build_stl_str_hl( // Determine how long the group is. // Note: We set the current output position to null // so `vim_strsize` will work. - char_u *t = items[groupitems[groupdepth]].start; + char_u *t = stl_items[stl_groupitems[groupdepth]].start; *out_p = NUL; long group_len = vim_strsize(t); @@ -3624,34 +3618,40 @@ int build_stl_str_hl( // move the output pointer back to where the group started. // Note: This erases any non-item characters that were in the group. // Otherwise there would be no reason to do this step. - if (curitem > groupitems[groupdepth] + 1 - && items[groupitems[groupdepth]].minwid == 0) { + if (curitem > stl_groupitems[groupdepth] + 1 + && stl_items[stl_groupitems[groupdepth]].minwid == 0) { // remove group if all items are empty and highlight group // doesn't change int group_start_userhl = 0; int group_end_userhl = 0; int n; - for (n = groupitems[groupdepth] - 1; n >= 0; n--) { - if (items[n].type == Highlight) { - group_start_userhl = group_end_userhl = items[n].minwid; + for (n = stl_groupitems[groupdepth] - 1; n >= 0; n--) { + if (stl_items[n].type == Highlight) { + group_start_userhl = group_end_userhl = stl_items[n].minwid; break; } } - for (n = groupitems[groupdepth] + 1; n < curitem; n++) { - if (items[n].type == Normal) { + for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) { + if (stl_items[n].type == Normal) { break; } - if (items[n].type == Highlight) { - group_end_userhl = items[n].minwid; + if (stl_items[n].type == Highlight) { + group_end_userhl = stl_items[n].minwid; } } if (n == curitem && group_start_userhl == group_end_userhl) { + // empty group out_p = t; group_len = 0; - // do not use the highlighting from the removed group - for (n = groupitems[groupdepth] + 1; n < curitem; n++) { - if (items[n].type == Highlight) { - items[n].type = Empty; + for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) { + // do not use the highlighting from the removed group + if (stl_items[n].type == Highlight) { + stl_items[n].type = Empty; + } + // adjust the start position of TabPage to the next + // item position + if (stl_items[n].type == TabPage) { + stl_items[n].start = out_p; } } } @@ -3659,18 +3659,19 @@ int build_stl_str_hl( // If the group is longer than it is allowed to be // truncate by removing bytes from the start of the group text. - if (group_len > items[groupitems[groupdepth]].maxwid) { + if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid) { // { Determine the number of bytes to remove long n; if (has_mbyte) { // Find the first character that should be included. n = 0; - while (group_len >= items[groupitems[groupdepth]].maxwid) { + while (group_len >= stl_items[stl_groupitems[groupdepth]].maxwid) { group_len -= ptr2cells(t + n); n += (*mb_ptr2len)(t + n); } } else { - n = (long)(out_p - t) - items[groupitems[groupdepth]].maxwid + 1; + n = (long)(out_p - t) + - stl_items[stl_groupitems[groupdepth]].maxwid + 1; } // } @@ -3681,25 +3682,26 @@ int build_stl_str_hl( memmove(t + 1, t + n, (size_t)(out_p - (t + n))); out_p = out_p - n + 1; // Fill up space left over by half a double-wide char. - while (++group_len < items[groupitems[groupdepth]].minwid) { + while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) { *out_p++ = fillchar; } // } // correct the start of the items for the truncation - for (int idx = groupitems[groupdepth] + 1; idx < curitem; idx++) { + for (int idx = stl_groupitems[groupdepth] + 1; idx < curitem; idx++) { // Shift everything back by the number of removed bytes - items[idx].start -= n; + stl_items[idx].start -= n; // If the item was partially or completely truncated, set its // start to the start of the group - if (items[idx].start < t) { - items[idx].start = t; + if (stl_items[idx].start < t) { + stl_items[idx].start = t; } } // If the group is shorter than the minimum width, add padding characters. - } else if (abs(items[groupitems[groupdepth]].minwid) > group_len) { - long min_group_width = items[groupitems[groupdepth]].minwid; + } else if ( + abs(stl_items[stl_groupitems[groupdepth]].minwid) > group_len) { + long min_group_width = stl_items[stl_groupitems[groupdepth]].minwid; // If the group is left-aligned, add characters to the right. if (min_group_width < 0) { min_group_width = 0 - min_group_width; @@ -3718,8 +3720,8 @@ int build_stl_str_hl( // } // Adjust item start positions - for (int n = groupitems[groupdepth] + 1; n < curitem; n++) { - items[n].start += group_len; + for (int n = stl_groupitems[groupdepth] + 1; n < curitem; n++) { + stl_items[n].start += group_len; } // Prepend the fill characters @@ -3755,9 +3757,9 @@ int build_stl_str_hl( // User highlight groups override the min width field // to denote the styling to use. if (*fmt_p == STL_USER_HL) { - items[curitem].type = Highlight; - items[curitem].start = out_p; - items[curitem].minwid = minwid > 9 ? 1 : minwid; + stl_items[curitem].type = Highlight; + stl_items[curitem].start = out_p; + stl_items[curitem].minwid = minwid > 9 ? 1 : minwid; fmt_p++; curitem++; continue; @@ -3791,8 +3793,8 @@ int build_stl_str_hl( if (minwid == 0) { // %X ends the close label, go back to the previous tab label nr. for (long n = curitem - 1; n >= 0; n--) { - if (items[n].type == TabPage && items[n].minwid >= 0) { - minwid = items[n].minwid; + if (stl_items[n].type == TabPage && stl_items[n].minwid >= 0) { + minwid = stl_items[n].minwid; break; } } @@ -3801,9 +3803,9 @@ int build_stl_str_hl( minwid = -minwid; } } - items[curitem].type = TabPage; - items[curitem].start = out_p; - items[curitem].minwid = minwid; + stl_items[curitem].type = TabPage; + stl_items[curitem].start = out_p; + stl_items[curitem].minwid = minwid; fmt_p++; curitem++; continue; @@ -3818,10 +3820,10 @@ int build_stl_str_hl( if (*fmt_p != STL_CLICK_FUNC) { break; } - items[curitem].type = ClickFunc; - items[curitem].start = out_p; - items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t))); - items[curitem].minwid = minwid; + stl_items[curitem].type = ClickFunc; + stl_items[curitem].start = out_p; + stl_items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t))); + stl_items[curitem].minwid = minwid; fmt_p++; curitem++; continue; @@ -3842,11 +3844,11 @@ int build_stl_str_hl( // Denotes the start of a new group if (*fmt_p == '(') { - groupitems[groupdepth++] = curitem; - items[curitem].type = Group; - items[curitem].start = out_p; - items[curitem].minwid = minwid; - items[curitem].maxwid = maxwid; + stl_groupitems[groupdepth++] = curitem; + stl_items[curitem].type = Group; + stl_items[curitem].start = out_p; + stl_items[curitem].minwid = minwid; + stl_items[curitem].maxwid = maxwid; fmt_p++; curitem++; continue; @@ -4141,9 +4143,9 @@ int build_stl_str_hl( // Create a highlight item based on the name if (*fmt_p == '#') { - items[curitem].type = Highlight; - items[curitem].start = out_p; - items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); + stl_items[curitem].type = Highlight; + stl_items[curitem].start = out_p; + stl_items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t)); curitem++; fmt_p++; } @@ -4154,8 +4156,8 @@ int build_stl_str_hl( // If we made it this far, the item is normal and starts at // our current position in the output buffer. // Non-normal items would have `continued`. - items[curitem].start = out_p; - items[curitem].type = Normal; + stl_items[curitem].start = out_p; + stl_items[curitem].type = Normal; // Copy the item string into the output buffer if (str != NULL && *str) { @@ -4313,7 +4315,7 @@ int build_stl_str_hl( // Otherwise, there was nothing to print so mark the item as empty } else { - items[curitem].type = Empty; + stl_items[curitem].type = Empty; } // Only free the string buffer if we allocated it. @@ -4354,13 +4356,13 @@ int build_stl_str_hl( // Otherwise, look for the truncation item } else { // Default to truncating at the first item - trunc_p = items[0].start; + trunc_p = stl_items[0].start; item_idx = 0; for (int i = 0; i < itemcnt; i++) { - if (items[i].type == Trunc) { - // Truncate at %< items. - trunc_p = items[i].start; + if (stl_items[i].type == Trunc) { + // Truncate at %< stl_items. + trunc_p = stl_items[i].start; item_idx = i; break; } @@ -4395,7 +4397,7 @@ int build_stl_str_hl( // Ignore any items in the statusline that occur after // the truncation point for (int i = 0; i < itemcnt; i++) { - if (items[i].start > trunc_p) { + if (stl_items[i].start > trunc_p) { itemcnt = i; break; } @@ -4450,12 +4452,12 @@ int build_stl_str_hl( for (int i = item_idx; i < itemcnt; i++) { // Items starting at or after the end of the truncated section need // to be moved backwards. - if (items[i].start >= trunc_end_p) { - items[i].start -= item_offset; + if (stl_items[i].start >= trunc_end_p) { + stl_items[i].start -= item_offset; // Anything inside the truncated area is set to start // at the `<` truncation character. } else { - items[i].start = trunc_p; + stl_items[i].start = trunc_p; } } // } @@ -4471,7 +4473,7 @@ int build_stl_str_hl( // figuring out how many groups there are. int num_separators = 0; for (int i = 0; i < itemcnt; i++) { - if (items[i].type == Separate) { + if (stl_items[i].type == Separate) { num_separators++; } } @@ -4480,11 +4482,10 @@ int build_stl_str_hl( if (num_separators) { // Create an array of the start location for each // separator mark. - int separator_locations[STL_MAX_ITEM]; int index = 0; for (int i = 0; i < itemcnt; i++) { - if (items[i].type == Separate) { - separator_locations[index] = i; + if (stl_items[i].type == Separate) { + stl_separator_locations[index] = i; index++; } } @@ -4496,16 +4497,17 @@ int build_stl_str_hl( for (int i = 0; i < num_separators; i++) { int dislocation = (i == (num_separators - 1)) ? final_spaces : standard_spaces; - char_u *seploc = items[separator_locations[i]].start + dislocation; - STRMOVE(seploc, items[separator_locations[i]].start); - for (char_u *s = items[separator_locations[i]].start; s < seploc; s++) { + 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 (int item_idx = separator_locations[i] + 1; + for (int item_idx = stl_separator_locations[i] + 1; item_idx < itemcnt; item_idx++) { - items[item_idx].start += dislocation; + stl_items[item_idx].start += dislocation; } } @@ -4515,11 +4517,12 @@ int build_stl_str_hl( // Store the info about highlighting. if (hltab != NULL) { - struct stl_hlrec *sp = hltab; + *hltab = stl_hltab; + stl_hlrec_t *sp = stl_hltab; for (long l = 0; l < itemcnt; l++) { - if (items[l].type == Highlight) { - sp->start = items[l].start; - sp->userhl = items[l].minwid; + if (stl_items[l].type == Highlight) { + sp->start = stl_items[l].start; + sp->userhl = stl_items[l].minwid; sp++; } } @@ -4529,16 +4532,17 @@ int build_stl_str_hl( // Store the info about tab pages labels. if (tabtab != NULL) { - StlClickRecord *cur_tab_rec = tabtab; + *tabtab = stl_tabtab; + StlClickRecord *cur_tab_rec = stl_tabtab; for (long l = 0; l < itemcnt; l++) { - if (items[l].type == TabPage) { - cur_tab_rec->start = (char *)items[l].start; - if (items[l].minwid == 0) { + if (stl_items[l].type == TabPage) { + cur_tab_rec->start = (char *)stl_items[l].start; + if (stl_items[l].minwid == 0) { cur_tab_rec->def.type = kStlClickDisabled; cur_tab_rec->def.tabnr = 0; } else { - int tabnr = items[l].minwid; - if (items[l].minwid > 0) { + int tabnr = stl_items[l].minwid; + if (stl_items[l].minwid > 0) { cur_tab_rec->def.type = kStlClickTabSwitch; } else { cur_tab_rec->def.type = kStlClickTabClose; @@ -4548,11 +4552,11 @@ int build_stl_str_hl( } cur_tab_rec->def.func = NULL; cur_tab_rec++; - } else if (items[l].type == ClickFunc) { - cur_tab_rec->start = (char *)items[l].start; + } else if (stl_items[l].type == ClickFunc) { + cur_tab_rec->start = (char *)stl_items[l].start; cur_tab_rec->def.type = kStlClickFuncRun; - cur_tab_rec->def.tabnr = items[l].minwid; - cur_tab_rec->def.func = items[l].cmd; + cur_tab_rec->def.tabnr = stl_items[l].minwid; + cur_tab_rec->def.func = stl_items[l].cmd; cur_tab_rec++; } } @@ -5389,13 +5393,11 @@ bool buf_hide(const buf_T *const buf) char_u *buf_spname(buf_T *buf) { if (bt_quickfix(buf)) { - win_T *win; - tabpage_T *tp; + win_T *win; + tabpage_T *tp; - /* - * For location list window, w_llist_ref points to the location list. - * For quickfix window, w_llist_ref is NULL. - */ + // For location list window, w_llist_ref points to the location list. + // For quickfix window, w_llist_ref is NULL. if (find_win_for_buf(buf, &win, &tp) && win->w_llist_ref != NULL) { return (char_u *)_(msg_loclist); } else { @@ -5414,7 +5416,7 @@ char_u *buf_spname(buf_T *buf) return (char_u *)_("[Scratch]"); } if (buf->b_fname == NULL) { - return (char_u *)_("[No Name]"); + return buf_get_fname(buf); } return NULL; } @@ -5475,6 +5477,16 @@ int buf_signcols(buf_T *buf) return buf->b_signcols; } +// Get "buf->b_fname", use "[No Name]" if it is NULL. +char_u *buf_get_fname(const buf_T *buf) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + if (buf->b_fname == NULL) { + return (char_u *)_("[No Name]"); + } + return buf->b_fname; +} + /* * Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed. */ |