# HG changeset patch # User Christian Brabandt # Date 1451770204 -3600 # Node ID 15eefe1b0dadbbd57dfc7d9f10a2feadd3acb208 # Parent 58a20453ab002d5a8b072cbf52d8f544457cb4c2 commit https://github.com/vim/vim/commit/027387f70c671f62e3e08e0bdd09ec05b0232735 Author: Bram Moolenaar Date: Sat Jan 2 22:25:52 2016 +0100 patch 7.4.1037 Problem: Using "q!" when there is a modified hidden buffer does not unload the current buffer, resulting in the need to abandon it again. Solution: When using "q!" unload the current buffer when needed. (Yasuhiro Matsumoto, Hirohito Higashi) diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1105,10 +1105,10 @@ 5. Writing and quitting *write-quit* the last file in the argument list has not been edited. See |:confirm| and 'confirm'. {not in Vi} -:q[uit]! Quit without writing, also when currently visible - buffers have changes. Does not exit when this is the - last window and there is a changed hidden buffer. - In this case, the first changed hidden buffer becomes +:q[uit]! Quit without writing, also when currentl buffer has + changes. If this is the last window and there is a + modified hidden buffer, the current buffer is + abandoned and the first changed hidden buffer becomes the current buffer. Use ":qall!" to exit always. diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1636,10 +1636,13 @@ add_bufnum(bufnrs, bufnump, nr) /* * Return TRUE if any buffer was changed and cannot be abandoned. * That changed buffer becomes the current buffer. + * When "unload" is true the current buffer is unloaded instead of making it + * hidden. This is used for ":q!". */ int -check_changed_any(hidden) +check_changed_any(hidden, unload) int hidden; /* Only check hidden buffers */ + int unload; { int ret = FALSE; buf_T *buf; @@ -1750,7 +1753,7 @@ buf_found: /* Open the changed buffer in the current window. */ if (buf != curbuf) - set_curbuf(buf, DOBUF_GOTO); + set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO); theend: vim_free(bufnrs); diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -7143,7 +7143,7 @@ ex_quit(eap) | (eap->forceit ? CCGD_FORCEIT : 0) | CCGD_EXCMD)) || check_more(TRUE, eap->forceit) == FAIL - || (only_one_window() && check_changed_any(eap->forceit))) + || (only_one_window() && check_changed_any(eap->forceit, TRUE))) { not_exiting(); } @@ -7214,7 +7214,7 @@ ex_quit_all(eap) #endif exiting = TRUE; - if (eap->forceit || !check_changed_any(FALSE)) + if (eap->forceit || !check_changed_any(FALSE, FALSE)) getout(0); not_exiting(); } @@ -7609,7 +7609,7 @@ ex_exit(eap) || curbufIsChanged()) && do_write(eap) == FAIL) || check_more(TRUE, eap->forceit) == FAIL - || (only_one_window() && check_changed_any(eap->forceit))) + || (only_one_window() && check_changed_any(eap->forceit, FALSE))) { not_exiting(); } diff --git a/src/gui.c b/src/gui.c --- a/src/gui.c +++ b/src/gui.c @@ -825,7 +825,7 @@ gui_shell_closed() # endif /* If there are changed buffers, present the user with a dialog if * possible, otherwise give an error message. */ - if (!check_changed_any(FALSE)) + if (!check_changed_any(FALSE, FALSE)) getout(0); exiting = FALSE; diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -2003,7 +2003,7 @@ sm_client_check_changed_any(GnomeClient * If there are changed buffers, present the user with * a dialog if possible, otherwise give an error message. */ - shutdown_cancelled = check_changed_any(FALSE); + shutdown_cancelled = check_changed_any(FALSE, FALSE); exiting = FALSE; cmdmod = save_cmdmod; diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -7132,7 +7132,7 @@ xsmp_handle_interaction(smc_conn, client save_cmdmod = cmdmod; cmdmod.confirm = TRUE; - if (check_changed_any(FALSE)) + if (check_changed_any(FALSE, FALSE)) /* Mustn't logout */ cancel_shutdown = True; cmdmod = save_cmdmod; diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -39,7 +39,7 @@ int check_changed __ARGS((buf_T *buf, in void browse_save_fname __ARGS((buf_T *buf)); void dialog_changed __ARGS((buf_T *buf, int checkall)); int can_abandon __ARGS((buf_T *buf, int forceit)); -int check_changed_any __ARGS((int hidden)); +int check_changed_any __ARGS((int hidden, int unload)); int check_fname __ARGS((void)); int buf_write_all __ARGS((buf_T *buf, int forceit)); int get_arglist __ARGS((garray_T *gap, char_u *str)); diff --git a/src/testdir/test31.in b/src/testdir/test31.in --- a/src/testdir/test31.in +++ b/src/testdir/test31.in @@ -69,6 +69,26 @@ A 3:close! GA 4:all! :1wincmd w :w >>test.out +:" +:" test ":q!" and hidden buffer. +:bw! Xtest1 Xtest2 Xtest3 Xtest4 +:sp Xtest1 +:wincmd w +:bw! +:set modified +:bot sp Xtest2 +:set modified +:bot sp Xtest3 +:set modified +:wincmd t +:hide +:q! +:w >>test.out +:q! +:w >>test.out +:q! +:call append(line('$'), "Oh, Not finished yet.") +:w >>test.out :qa! ENDTEST diff --git a/src/testdir/test31.ok b/src/testdir/test31.ok --- a/src/testdir/test31.ok +++ b/src/testdir/test31.ok @@ -10,3 +10,5 @@ testtext 1 testtext 3 3 3 testtext 1 testtext 2 2 2 +testtext 3 +testtext 1 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1037, +/**/ 1036, /**/ 1035,