diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
commit | d5f194ce780c95821a855aca3c19426576d28ae0 (patch) | |
tree | d45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/buffer.c | |
parent | c5d770d311841ea5230426cc4c868e8db27300a8 (diff) | |
parent | 44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff) | |
download | rneovim-rahm.tar.gz rneovim-rahm.tar.bz2 rneovim-rahm.zip |
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r-- | src/nvim/buffer.c | 233 |
1 files changed, 69 insertions, 164 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index abcce0dfe8..9e6877cbfa 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -875,6 +875,7 @@ static void free_buffer(buf_T *buf) aubuflocal_remove(buf); xfree(buf->additional_data); xfree(buf->b_prompt_text); + kv_destroy(buf->b_wininfo); callback_free(&buf->b_prompt_callback); callback_free(&buf->b_prompt_interrupt); clear_fmark(&buf->b_last_cursor, 0); @@ -901,13 +902,10 @@ static void free_buffer(buf_T *buf) /// Free the b_wininfo list for buffer "buf". static void clear_wininfo(buf_T *buf) { - wininfo_T *wip; - - while (buf->b_wininfo != NULL) { - wip = buf->b_wininfo; - buf->b_wininfo = wip->wi_next; - free_wininfo(wip, buf); + for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) { + free_wininfo(kv_A(buf->b_wininfo, i), buf); } + kv_size(buf->b_wininfo) = 0; } /// Free stuff in the buffer for ":bdel" and when wiping out the buffer. @@ -1393,7 +1391,7 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags) // If the buffer to be deleted is not the current one, delete it here. if (buf != curbuf) { - if (jop_flags & JOP_CLEAN) { + if (jop_flags & kOptJopFlagClean) { // Remove the buffer to be deleted from the jump list. mark_jumplist_forget_file(curwin, buf_fnum); } @@ -1419,7 +1417,7 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags) if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) { buf = au_new_curbuf.br_buf; } else if (curwin->w_jumplistlen > 0) { - if (jop_flags & JOP_CLEAN) { + if (jop_flags & kOptJopFlagClean) { // Remove the buffer from the jump list. mark_jumplist_forget_file(curwin, buf_fnum); } @@ -1429,7 +1427,7 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags) if (curwin->w_jumplistlen > 0) { int jumpidx = curwin->w_jumplistidx; - if (jop_flags & JOP_CLEAN) { + if (jop_flags & kOptJopFlagClean) { // If the index is the same as the length, the current position was not yet added to the // jump list. So we can safely go back to the last entry and search from there. if (jumpidx == curwin->w_jumplistlen) { @@ -1443,7 +1441,7 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags) } forward = jumpidx; - while ((jop_flags & JOP_CLEAN) || jumpidx != curwin->w_jumplistidx) { + while ((jop_flags & kOptJopFlagClean) || jumpidx != curwin->w_jumplistidx) { buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum); if (buf != NULL) { @@ -1460,7 +1458,7 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags) } } if (buf != NULL) { // found a valid buffer: stop searching - if (jop_flags & JOP_CLEAN) { + if (jop_flags & kOptJopFlagClean) { curwin->w_jumplistidx = jumpidx; update_jumplist = false; } @@ -1926,7 +1924,8 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) } clear_wininfo(buf); - buf->b_wininfo = xcalloc(1, sizeof(wininfo_T)); + WinInfo *curwin_info = xcalloc(1, sizeof(WinInfo)); + kv_push(buf->b_wininfo, curwin_info); if (buf == curbuf) { free_buffer_stuff(buf, kBffInitChangedtick); // delete local vars et al. @@ -1964,9 +1963,9 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) buf_copy_options(buf, BCO_ALWAYS); } - buf->b_wininfo->wi_mark = (fmark_T)INIT_FMARK; - buf->b_wininfo->wi_mark.mark.lnum = lnum; - buf->b_wininfo->wi_win = curwin; + curwin_info->wi_mark = (fmark_T)INIT_FMARK; + curwin_info->wi_mark.mark.lnum = lnum; + curwin_info->wi_win = curwin; hash_init(&buf->b_s.b_keywtab); hash_init(&buf->b_s.b_keywtab_ic); @@ -2159,11 +2158,11 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit) // If 'switchbuf' contains "split", "vsplit" or "newtab" and the // current buffer isn't empty: open new tab or window - if (wp == NULL && (swb_flags & (SWB_VSPLIT | SWB_SPLIT | SWB_NEWTAB)) + if (wp == NULL && (swb_flags & (kOptSwbFlagVsplit | kOptSwbFlagSplit | kOptSwbFlagNewtab)) && !buf_is_empty(curbuf)) { - if (swb_flags & SWB_NEWTAB) { + if (swb_flags & kOptSwbFlagNewtab) { tabpage_new(); - } else if (win_split(0, (swb_flags & SWB_VSPLIT) ? WSP_VERT : 0) + } else if (win_split(0, (swb_flags & kOptSwbFlagVsplit) ? WSP_VERT : 0) == FAIL) { return FAIL; } @@ -2183,7 +2182,7 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit) curwin->w_cursor.coladd = 0; curwin->w_set_curswant = true; } - if (jop_flags & JOP_VIEW && restore_view) { + if (jop_flags & kOptJopFlagView && restore_view) { mark_view_restore(fm); } return OK; @@ -2631,30 +2630,26 @@ void buflist_setfpos(buf_T *const buf, win_T *const win, linenr_T lnum, colnr_T bool copy_options) FUNC_ATTR_NONNULL_ARG(1) { - wininfo_T *wip; + WinInfo *wip; - for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) { + size_t i; + for (i = 0; i < kv_size(buf->b_wininfo); i++) { + wip = kv_A(buf->b_wininfo, i); if (wip->wi_win == win) { break; } } - if (wip == NULL) { + + if (i == kv_size(buf->b_wininfo)) { // allocate a new entry - wip = xcalloc(1, sizeof(wininfo_T)); + wip = xcalloc(1, sizeof(WinInfo)); wip->wi_win = win; if (lnum == 0) { // set lnum even when it's 0 lnum = 1; } } else { // remove the entry from the list - if (wip->wi_prev) { - wip->wi_prev->wi_next = wip->wi_next; - } else { - buf->b_wininfo = wip->wi_next; - } - if (wip->wi_next) { - wip->wi_next->wi_prev = wip->wi_prev; - } + kv_shift(buf->b_wininfo, i, 1); if (copy_options && wip->wi_optset) { clear_winopt(&wip->wi_opt); deleteFoldRecurse(buf, &wip->wi_folds); @@ -2679,17 +2674,15 @@ void buflist_setfpos(buf_T *const buf, win_T *const win, linenr_T lnum, colnr_T } // insert the entry in front of the list - wip->wi_next = buf->b_wininfo; - buf->b_wininfo = wip; - wip->wi_prev = NULL; - if (wip->wi_next) { - wip->wi_next->wi_prev = wip; - } + kv_pushp(buf->b_wininfo); + memmove(&kv_A(buf->b_wininfo, 1), &kv_A(buf->b_wininfo, 0), + (kv_size(buf->b_wininfo) - 1) * sizeof(kv_A(buf->b_wininfo, 0))); + kv_A(buf->b_wininfo, 0) = wip; } /// Check that "wip" has 'diff' set and the diff is only for another tab page. /// That's because a diff is local to a tab page. -static bool wininfo_other_tab_diff(wininfo_T *wip) +static bool wininfo_other_tab_diff(WinInfo *wip) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { if (!wip->wi_opt.wo_diff) { @@ -2713,42 +2706,38 @@ static bool wininfo_other_tab_diff(wininfo_T *wip) /// @param skip_diff_buffer when true, avoid windows with 'diff' set that is in another tab page. /// /// @return NULL when there isn't any info. -static wininfo_T *find_wininfo(buf_T *buf, bool need_options, bool skip_diff_buffer) +static WinInfo *find_wininfo(buf_T *buf, bool need_options, bool skip_diff_buffer) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE { - wininfo_T *wip; - - for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) { + for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) { + WinInfo *wip = kv_A(buf->b_wininfo, i); if (wip->wi_win == curwin && (!skip_diff_buffer || !wininfo_other_tab_diff(wip)) && (!need_options || wip->wi_optset)) { - break; + return wip; } } - if (wip != NULL) { - return wip; - } - // If no wininfo for curwin, use the first in the list (that doesn't have // 'diff' set and is in another tab page). // If "need_options" is true skip entries that don't have options set, // unless the window is editing "buf", so we can copy from the window // itself. if (skip_diff_buffer) { - for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) { + for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) { + WinInfo *wip = kv_A(buf->b_wininfo, i); if (!wininfo_other_tab_diff(wip) && (!need_options || wip->wi_optset || (wip->wi_win != NULL && wip->wi_win->w_buffer == buf))) { - break; + return wip; } } - } else { - wip = buf->b_wininfo; + } else if (kv_size(buf->b_wininfo)) { + return kv_A(buf->b_wininfo, 0); } - return wip; + return NULL; } /// Reset the local window options to the values last used in this window. @@ -2760,7 +2749,7 @@ void get_winopts(buf_T *buf) clear_winopt(&curwin->w_onebuf_opt); clearFolding(curwin); - wininfo_T *const wip = find_wininfo(buf, true, true); + WinInfo *const wip = find_wininfo(buf, true, true); if (wip != NULL && wip->wi_win != curwin && wip->wi_win != NULL && wip->wi_win->w_buffer == buf) { win_T *wp = wip->wi_win; @@ -2800,7 +2789,7 @@ fmark_T *buflist_findfmark(buf_T *buf) { static fmark_T no_position = { { 1, 0, 0 }, 0, 0, { 0 }, NULL }; - wininfo_T *const wip = find_wininfo(buf, false, false); + WinInfo *const wip = find_wininfo(buf, false, false); return (wip == NULL) ? &no_position : &(wip->wi_mark); } @@ -2819,6 +2808,7 @@ void buflist_list(exarg_T *eap) garray_T buflist; buf_T **buflist_data = NULL; + msg_ext_set_kind("list_cmd"); if (vim_strchr(eap->arg, 't')) { ga_init(&buflist, sizeof(buf_T *), 50); for (buf = firstbuf; buf != NULL; buf = buf->b_next) { @@ -3267,8 +3257,8 @@ void fileinfo(int fullname, int shorthelp, bool dont_truncate) n); validate_virtcol(curwin); size_t len = strlen(buffer); - col_print(buffer + len, IOSIZE - len, - (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); + (void)col_print(buffer + len, IOSIZE - len, + (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); } append_arg_number(curwin, buffer, IOSIZE); @@ -3296,13 +3286,13 @@ void fileinfo(int fullname, int shorthelp, bool dont_truncate) xfree(buffer); } -void col_print(char *buf, size_t buflen, int col, int vcol) +int col_print(char *buf, size_t buflen, int col, int vcol) { if (col == vcol) { - vim_snprintf(buf, buflen, "%d", col); - } else { - vim_snprintf(buf, buflen, "%d-%d", col, vcol); + return vim_snprintf(buf, buflen, "%d", col); } + + return vim_snprintf(buf, buflen, "%d-%d", col, vcol); } static char *lasttitle = NULL; @@ -3341,96 +3331,11 @@ void maketitle(void) title_str = p_titlestring; } } else { - // Format: "fname + (path) (1 of 2) - VIM". - -#define SPACE_FOR_FNAME (sizeof(buf) - 100) -#define SPACE_FOR_DIR (sizeof(buf) - 20) -#define SPACE_FOR_ARGNR (sizeof(buf) - 10) // At least room for " - Nvim". - char *buf_p = buf; - if (curbuf->b_fname == NULL) { - const size_t size = xstrlcpy(buf_p, _("[No Name]"), - SPACE_FOR_FNAME + 1); - buf_p += MIN(size, SPACE_FOR_FNAME); - } else { - buf_p += transstr_buf(path_tail(curbuf->b_fname), -1, buf_p, SPACE_FOR_FNAME + 1, true); - } - - switch (bufIsChanged(curbuf) - | (curbuf->b_p_ro << 1) - | (!MODIFIABLE(curbuf) << 2)) { - case 0: - break; - case 1: - buf_p = strappend(buf_p, " +"); break; - case 2: - buf_p = strappend(buf_p, " ="); break; - case 3: - buf_p = strappend(buf_p, " =+"); break; - case 4: - case 6: - buf_p = strappend(buf_p, " -"); break; - case 5: - case 7: - buf_p = strappend(buf_p, " -+"); break; - default: - abort(); - } - - if (curbuf->b_fname != NULL) { - // Get path of file, replace home dir with ~. - *buf_p++ = ' '; - *buf_p++ = '('; - home_replace(curbuf, curbuf->b_ffname, buf_p, - (SPACE_FOR_DIR - (size_t)(buf_p - buf)), true); -#ifdef BACKSLASH_IN_FILENAME - // Avoid "c:/name" to be reduced to "c". - if (isalpha((uint8_t)(*buf_p)) && *(buf_p + 1) == ':') { - buf_p += 2; - } -#endif - // Remove the file name. - char *p = path_tail_with_sep(buf_p); - if (p == buf_p) { - // Must be a help buffer. - xstrlcpy(buf_p, _("help"), SPACE_FOR_DIR - (size_t)(buf_p - buf)); - } else { - *p = NUL; - } - - // Translate unprintable chars and concatenate. Keep some - // room for the server name. When there is no room (very long - // file name) use (...). - if ((size_t)(buf_p - buf) < SPACE_FOR_DIR) { - char *const tbuf = transstr(buf_p, true); - const size_t free_space = SPACE_FOR_DIR - (size_t)(buf_p - buf) + 1; - const size_t dir_len = xstrlcpy(buf_p, tbuf, free_space); - buf_p += MIN(dir_len, free_space - 1); - xfree(tbuf); - } else { - const size_t free_space = SPACE_FOR_ARGNR - (size_t)(buf_p - buf) + 1; - const size_t dots_len = xstrlcpy(buf_p, "...", free_space); - buf_p += MIN(dots_len, free_space - 1); - } - *buf_p++ = ')'; - *buf_p = NUL; - } else { - *buf_p = NUL; - } - - append_arg_number(curwin, buf_p, (int)(SPACE_FOR_ARGNR - (size_t)(buf_p - buf))); - - xstrlcat(buf_p, " - Nvim", (sizeof(buf) - (size_t)(buf_p - buf))); - - if (maxlen > 0) { - // Make it shorter by removing a bit in the middle. - if (vim_strsize(buf) > maxlen) { - trunc_string(buf, buf, maxlen, sizeof(buf)); - } - } + // Format: "fname + (path) (1 of 2) - Nvim". + char *default_titlestring = "%t%( %M%)%( (%{expand(\"%:~:h\")})%)%a - Nvim"; + build_stl_str_hl(curwin, buf, sizeof(buf), default_titlestring, + kOptTitlestring, 0, 0, maxlen, NULL, NULL, NULL, NULL); title_str = buf; -#undef SPACE_FOR_FNAME -#undef SPACE_FOR_DIR -#undef SPACE_FOR_ARGNR } } bool mustset = value_change(title_str, &lasttitle); @@ -3511,15 +3416,16 @@ void free_titles(void) /// Get relative cursor position in window into "buf[buflen]", in the localized /// percentage form like %99, 99%; using "Top", "Bot" or "All" when appropriate. -void get_rel_pos(win_T *wp, char *buf, int buflen) +int get_rel_pos(win_T *wp, char *buf, int buflen) { // Need at least 3 chars for writing. if (buflen < 3) { - return; + return 0; } linenr_T above; // number of lines above window linenr_T below; // number of lines below window + int len; above = wp->w_topline - 1; above += win_get_fill(wp, wp->w_topline) - wp->w_topfill; @@ -3530,25 +3436,24 @@ void get_rel_pos(win_T *wp, char *buf, int buflen) } below = wp->w_buffer->b_ml.ml_line_count - wp->w_botline + 1; if (below <= 0) { - xstrlcpy(buf, (above == 0 ? _("All") : _("Bot")), (size_t)buflen); + len = vim_snprintf(buf, (size_t)buflen, "%s", (above == 0) ? _("All") : _("Bot")); } else if (above <= 0) { - xstrlcpy(buf, _("Top"), (size_t)buflen); + len = vim_snprintf(buf, (size_t)buflen, "%s", _("Top")); } else { int perc = (above > 1000000 ? (above / ((above + below) / 100)) : (above * 100 / (above + below))); - - char *p = buf; - size_t l = (size_t)buflen; - if (perc < 10) { - // prepend one space - buf[0] = ' '; - p++; - l--; - } // localized percentage value - vim_snprintf(p, l, _("%d%%"), perc); + len = vim_snprintf(buf, (size_t)buflen, _("%s%d%%"), (perc < 10) ? " " : "", perc); } + if (len < 0) { + buf[0] = NUL; + len = 0; + } else if (len > buflen - 1) { + len = buflen - 1; + } + + return len; } /// Append (2 of 8) to "buf[buflen]", if editing more than one file. @@ -3722,7 +3627,7 @@ void ex_buffer_all(exarg_T *eap) // Open the buffer in this window. swap_exists_action = SEA_DIALOG; - set_curbuf(buf, DOBUF_GOTO, !(jop_flags & JOP_CLEAN)); + set_curbuf(buf, DOBUF_GOTO, !(jop_flags & kOptJopFlagClean)); if (!bufref_valid(&bufref)) { // Autocommands deleted the buffer. swap_exists_action = SEA_NONE; |