patch 9.2.0506: home_replace() function can be improved
Commit:
https://github.com/vim/vim/commit/a0931a90eeee6692556f330b5ba1fb413f9ea85d
Author: John Marriott <
basi...@internode.on.net>
Date: Wed May 20 18:38:55 2026 +0000
patch 9.2.0506: home_replace() function can be improved
Problem: home_replace() function can be improved
Solution: Refactor home_replace() to return the length of the string
(John Marriott).
In addition:
- in function set_b0_fname() move ulen into the block where it is used.
- In function findswapname() rework logic around displaying "swap file
already exists" dialogue so that literal message text is set once.
closes: #20249
Signed-off-by: John Marriott <
basi...@internode.on.net>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/buffer.c b/src/buffer.c
index 43cba3ad8..a903ab375 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -3948,9 +3948,8 @@ fileinfo(
name = curbuf->b_fname;
else
name = curbuf->b_ffname;
- home_replace(shorthelp ? curbuf : NULL, name, (char_u *)buffer + bufferlen,
- IOSIZE - (int)bufferlen, TRUE);
- bufferlen += STRLEN(buffer + bufferlen);
+ bufferlen += home_replace(shorthelp ? curbuf : NULL, name,
+ (char_u *)buffer + bufferlen, IOSIZE - (int)bufferlen, TRUE);
}
bufferlen += vim_snprintf_safelen(
diff --git a/src/fileio.c b/src/fileio.c
index 1a7ee9b94..af0360dc8 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3200,11 +3200,13 @@ set_rw_fname(char_u *fname, char_u *sfname)
void
msg_add_fname(buf_T *buf, char_u *fname)
{
+ size_t IObufflen = 0;
+
if (fname == NULL)
fname = (char_u *)"-stdin-";
- home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
- IObuff[0] = '"';
- STRCAT(IObuff, "\" ");
+ IObuff[IObufflen++] = '"';
+ IObufflen += home_replace(buf, fname, IObuff + IObufflen, IOSIZE - 4, TRUE);
+ STRCPY(IObuff + IObufflen, "\" ");
}
/*
diff --git a/src/filepath.c b/src/filepath.c
index a41f8c27f..8bdba335c 100644
--- a/src/filepath.c
+++ b/src/filepath.c
@@ -442,27 +442,29 @@ repeat:
if (p != NULL)
{
+ size_t dirnamelen = 0;
+
if (c == '.')
{
- size_t namelen;
-
mch_dirname(dirname, MAXPATHL);
if (has_homerelative)
{
s = vim_strsave(dirname);
if (s != NULL)
{
- home_replace(NULL, s, dirname, MAXPATHL, TRUE);
+ dirnamelen = home_replace(NULL, s, dirname, MAXPATHL, TRUE);
vim_free(s);
}
}
- namelen = STRLEN(dirname);
+
+ if (dirnamelen == 0)
+ dirnamelen = STRLEN(dirname);
// Do not call shorten_fname() here since it removes the prefix
// even though the path does not have a prefix.
- if (fnamencmp(p, dirname, namelen) == 0)
+ if (fnamencmp(p, dirname, dirnamelen) == 0)
{
- p += namelen;
+ p += dirnamelen;
if (vim_ispathsep(*p))
{
while (*p && vim_ispathsep(*p))
@@ -480,11 +482,11 @@ repeat:
}
else
{
- home_replace(NULL, p, dirname, MAXPATHL, TRUE);
+ dirnamelen = home_replace(NULL, p, dirname, MAXPATHL, TRUE);
// Only replace it when it starts with '~'
if (*dirname == '~')
{
- s = vim_strsave(dirname);
+ s = vim_strnsave(dirname, dirnamelen);
if (s != NULL)
{
*fnamep = s;
@@ -2724,7 +2726,7 @@ f_filecopy(typval_T *argvars, typval_T *rettv)
* 'src'.
* If anything fails (except when out of space) dst equals src.
*/
- void
+ size_t
home_replace(
buf_T *buf, // when not NULL, check for help files
char_u *src, // input file name
@@ -2737,21 +2739,19 @@ home_replace(
size_t len;
char_u *homedir_env, *homedir_env_orig;
char_u *p;
+ char_u *dst_start;
if (src == NULL)
{
*dst = NUL;
- return;
+ return 0;
}
/*
* If the file is a help file, remove the path completely.
*/
if (buf != NULL && buf->b_help)
- {
- vim_snprintf((char *)dst, dstlen, "%s", gettail(src));
- return;
- }
+ return vim_snprintf_safelen((char *)dst, dstlen, "%s", gettail(src));
/*
* We check both the value of the $HOME environment variable and the
@@ -2793,6 +2793,7 @@ home_replace(
if (!one)
src = skipwhite(src);
+ dst_start = dst; // remember the start
while (*src && dstlen > 0)
{
/*
@@ -2842,6 +2843,8 @@ home_replace(
if (homedir_env != homedir_env_orig)
vim_free(homedir_env);
+
+ return (size_t)(dst - dst_start);
}
/*
diff --git a/src/memline.c b/src/memline.c
index ffd3fbd72..51b09cc1c 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -1021,7 +1021,7 @@ set_b0_fname(ZERO_BL *b0p, buf_T *buf)
forward_slash(b0p->b0_fname);
# endif
#else
- size_t flen, ulen;
+ size_t flen;
char_u uname[B0_UNAME_SIZE];
/*
@@ -1031,11 +1031,12 @@ set_b0_fname(ZERO_BL *b0p, buf_T *buf)
* First replace home dir path with "~/" with home_replace().
* Then insert the user name to get "~user/".
*/
- home_replace(NULL, buf->b_ffname, b0p->b0_fname,
+ flen = home_replace(NULL, buf->b_ffname, b0p->b0_fname,
B0_FNAME_SIZE_CRYPT, TRUE);
if (b0p->b0_fname[0] == '~')
{
- flen = STRLEN(b0p->b0_fname);
+ size_t ulen;
+
// If there is no user name or it is too long, don't use "~/"
if (get_user_name(uname, B0_UNAME_SIZE) == FAIL
|| (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE_CRYPT - 1)
@@ -5343,24 +5344,32 @@ findswapname(
if (swap_exists_action != SEA_NONE
&& choice == SEA_CHOICE_NONE)
{
- char_u *name;
- int dialog_result;
- size_t len = STRLEN(_("Swap file \""));
-
- name = alloc(STRLEN(fname)
- + len
- + STRLEN(_("\" already exists!")) + 5);
- if (name != NULL)
+ string_T prefix = {(char_u *)_("Swap file \""), 0};
+ string_T suffix = {(char_u *)_("\" already exists!"), 0};
+ size_t message_size;
+ string_T message;
+ char_u *tofree;
+ int dialog_result;
+
+ prefix.length = STRLEN(prefix.string);
+ suffix.length = STRLEN(suffix.string);
+ message_size = prefix.length
+ + STRLEN(fname)
+ + suffix.length + 5;
+ message.string = tofree = alloc(message_size);
+ if (message.string != NULL)
{
- STRCPY(name, _("Swap file \""));
- home_replace(NULL, fname, name + len, 1000, TRUE);
- STRCAT(name, _("\" already exists!"));
+ STRCPY(message.string, prefix.string);
+ message.length = prefix.length;
+ message.length += home_replace(NULL, fname,
+ message.string + message.length, (int)(message_size - message.length), TRUE);
+ STRCPY(message.string + message.length, suffix.string);
}
+ else
+ message.string = (char_u *)_("Swap file already exists!");
dialog_result = do_dialog(VIM_WARNING,
(char_u *)_("VIM - ATTENTION"),
- name == NULL
- ? (char_u *)_("Swap file already exists!")
- : name,
+ message.string,
# ifdef HAVE_PROCESS_STILL_RUNNING
process_still_running
? (char_u *)_("&Open Read-Only
&Edit anyway
&Recover
&Quit
&Abort") :
@@ -5373,7 +5382,7 @@ findswapname(
dialog_result++;
# endif
choice = dialog_result;
- vim_free(name);
+ vim_free(tofree);
// pretend screen didn't scroll, need redraw anyway
msg_scrolled = 0;
diff --git a/src/po/vim.pot b/src/po/vim.pot
index 2057c23a9..e5cf8c102 100644
--- a/src/po/vim.pot
+++ b/src/po/vim.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Vim
"
"Report-Msgid-Bugs-To:
vim...@vim.org
"
-"POT-Creation-Date: 2026-05-19 18:20+0000
"
+"POT-Creation-Date: 2026-05-20 18:41+0000
"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>
"
"Language-Team: LANGUAGE <
L...@li.org>
"
@@ -2169,10 +2169,10 @@ msgstr ""
msgid "\" already exists!"
msgstr ""
-msgid "VIM - ATTENTION"
+msgid "Swap file already exists!"
msgstr ""
-msgid "Swap file already exists!"
+msgid "VIM - ATTENTION"
msgstr ""
msgid ""
diff --git a/src/proto/
filepath.pro b/src/proto/
filepath.pro
index d00a66775..ac8762383 100644
--- a/src/proto/
filepath.pro
+++ b/src/proto/
filepath.pro
@@ -36,7 +36,7 @@ char_u *do_browse(int flags, char_u *title, char_u *dflt, char_u *ext, char_u *i
void f_browse(typval_T *argvars, typval_T *rettv);
void f_browsedir(typval_T *argvars, typval_T *rettv);
void f_filecopy(typval_T *argvars, typval_T *rettv);
-void home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, int one);
+size_t home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, int one);
char_u *home_replace_save(buf_T *buf, char_u *src);
int fullpathcmp(char_u *s1, char_u *s2, int checkname, int expandenv);
char_u *gettail(char_u *fname);
diff --git a/src/version.c b/src/version.c
index f46d48acc..dc31e54a7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 506,
/**/
505,
/**/
diff --git a/src/viminfo.c b/src/viminfo.c
index bb84726c8..95ec55ebb 100644
--- a/src/viminfo.c
+++ b/src/viminfo.c
@@ -435,6 +435,8 @@ write_viminfo_bufferlist(FILE *fp)
fputs(_("
# Buffer list:
"), fp);
FOR_ALL_BUFFERS(buf)
{
+ size_t linelen;
+
if (buf->b_fname == NULL
|| !buf->b_p_bl
|| bt_quickfix(buf)
@@ -445,8 +447,8 @@ write_viminfo_bufferlist(FILE *fp)
if (max_buffers-- == 0)
break;
putc('%', fp);
- home_replace(NULL, buf->b_ffname, line, MAXPATHL, TRUE);
- vim_snprintf_add((char *)line, LINE_BUF_LEN, " %ld %d",
+ linelen = home_replace(NULL, buf->b_ffname, line, MAXPATHL, TRUE);
+ vim_snprintf((char *)line + linelen, LINE_BUF_LEN - linelen, " %ld %d",
(long)buf->b_last_cursor.lnum,
buf->b_last_cursor.col);
viminfo_writestring(fp, line);