From: Hirohito Higashi Date: Tue, 5 May 2026 19:02:59 +0000 (+0000) Subject: patch 9.2.0443: GUI: cancelling save dialog overwrites or discards unnamed buffer X-Git-Tag: v9.2.0443^0 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf947e7ef09fc8a63f447b54b107585b8f3b7abe;p=thirdparty%2Fvim.git patch 9.2.0443: GUI: cancelling save dialog overwrites or discards unnamed buffer Problem: When closing gvim with an unsaved unnamed buffer, choosing "Yes" in the "Save changes?" dialog and then "Cancel" in the file selection dialog either silently writes the buffer to a file named "Untitled" (overwriting any existing file with that name) or discards the buffer altogether (vibs29, after v9.1.0265). Solution: In dialog_changed(), if browse_save_fname() leaves the buffer without a file name, treat it as a cancel and return without saving. Also stop clearing the modified flag in the restore path on write failure, so the unsaved changes are kept and the caller (e.g. gui_shell_closed()) can also cancel the close. Pre-fill the file dialog with "Untitled" to match the preceding "Save changes to ..." prompt. Add a test for the write-failure path (Hirohito Higashi). fixes: #20132 closes: #20143 Signed-off-by: Hirohito Higashi Signed-off-by: Christian Brabandt --- diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 7012c98962..afe9c4b58a 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -141,7 +141,7 @@ browse_save_fname(buf_T *buf) char_u *fname; fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"), - NULL, NULL, NULL, NULL, buf); + (char_u *)"Untitled", NULL, NULL, NULL, buf); if (fname == NULL) return; @@ -182,6 +182,10 @@ dialog_changed( # ifdef FEAT_BROWSE // May get file name, when there is none browse_save_fname(buf); + + // User cancelled the file dialog; keep the buffer modified. + if (buf->b_fname == NULL) + return; # endif empty_bufname = buf->b_fname == NULL ? TRUE : FALSE; if (empty_bufname) @@ -194,13 +198,12 @@ dialog_changed( return; } - // restore to empty when write failed + // restore to empty when write failed or was cancelled if (empty_bufname) { buf->b_fname = NULL; VIM_CLEAR(buf->b_ffname); VIM_CLEAR(buf->b_sfname); - unchanged(buf, TRUE, FALSE); } } else if (ret == VIM_NO) diff --git a/src/testdir/test_buffer.vim b/src/testdir/test_buffer.vim index 934bc6fe1e..4f0f1acb24 100644 --- a/src/testdir/test_buffer.vim +++ b/src/testdir/test_buffer.vim @@ -342,6 +342,28 @@ func Test_goto_buf_with_confirm() close! endfunc +" Test for issue #20132: when saving an unnamed buffer fails the modified +" flag must be kept, otherwise the buffer is silently discarded. +func Test_dialog_changed_keep_modified_on_write_fail() + CheckUnix + CheckNotGui + CheckFeature dialog_con + CheckNotFeature dialog_con_gui + CheckNotRoot + + call writefile(['existing'], 'Untitled', 'D') + call setfperm('Untitled', 'r--r--r--') + + new + call setline(1, 'test') + call feedkeys('y', 'L') + silent! confirm bdel + call assert_true(&modified) + call assert_equal(['existing'], readfile('Untitled')) + + bw! +endfunc + " Test for splitting buffer with 'switchbuf' func Test_buffer_switchbuf() new Xswitchbuf diff --git a/src/version.c b/src/version.c index 5dde38b7b4..61342e15f0 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 */ +/**/ + 443, /**/ 442, /**/