To: vim_dev@googlegroups.com Subject: Patch 8.1.2046 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2046 Problem: SafeState may be triggered at the wrong moment. Solution: Move it up higher to after where messages are processed. Add a SafeStateAgain event to tigger there. Files: runtime/doc/autocmd.txt, src/main.c, src/proto/main.pro, src/getchar.c, src/channel.c, src/autocmd.c, src/vim.h *** ../vim-8.1.2045/runtime/doc/autocmd.txt 2019-09-15 23:02:00.387231965 +0200 --- runtime/doc/autocmd.txt 2019-09-16 21:56:58.233025424 +0200 *************** *** 357,362 **** --- 357,363 ---- |SafeState| nothing pending, going to wait for the user to type a character + |SafeStateAgain| repeated SafeState |ColorSchemePre| before loading a color scheme |ColorScheme| after loading a color scheme *************** *** 979,984 **** --- 979,989 ---- Depending on what you want to do, you may also check more with `state()`, e.g. whether the screen was scrolled for messages. + *SafeStateAgain* + SafeStateAgain Like SafeState but after processing any + messages and invoking callbacks. This may be + triggered often, don't do something that takes + time. *SessionLoadPost* SessionLoadPost After loading the session file created using *** ../vim-8.1.2045/src/main.c 2019-09-15 23:02:00.387231965 +0200 --- src/main.c 2019-09-16 21:51:54.090121706 +0200 *************** *** 1029,1036 **** } static int was_safe = FALSE; - static int not_safe_now = 0; /* * Trigger SafeState if currently in a safe state for main_loop(). --- 1029,1036 ---- } + // When TRUE in a safe state when starting to wait for a character. static int was_safe = FALSE; /* * Trigger SafeState if currently in a safe state for main_loop(). *************** *** 1057,1062 **** --- 1057,1063 ---- int is_safe = safe && stuff_empty() && typebuf.tb_len == 0 + && scriptin[curscript] == NULL && !global_busy; if (is_safe) *************** *** 1065,1088 **** } /* ! * Entering a not-safe state. */ void ! enter_unsafe_state(void) { ! ++not_safe_now; } /* ! * Leaving a not-safe state. Trigger SafeState if we were in a safe state ! * before first calling enter_not_safe_state(). */ void leave_unsafe_state(void) { ! --not_safe_now; ! if (not_safe_now == 0 && was_safe) ! apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf); } --- 1066,1090 ---- } /* ! * Something changed which causes the state possibly to be unsafe, e.g. a ! * character was typed. It will remain unsafe until the next call to ! * may_trigger_safestate(). */ void ! state_no_longer_safe(void) { ! was_safe = FALSE; } /* ! * Invoked when leaving code that invokes callbacks. Then trigger ! * SafeStateAgain, if it was safe when starting to wait for a character. */ void leave_unsafe_state(void) { ! if (was_safe) ! apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf); } *** ../vim-8.1.2045/src/proto/main.pro 2019-09-15 23:02:00.387231965 +0200 --- src/proto/main.pro 2019-09-16 21:49:55.022549676 +0200 *************** *** 3,9 **** void common_init(mparm_T *paramp); int is_not_a_term(void); void may_trigger_safestate(int safe); ! void enter_unsafe_state(void); void leave_unsafe_state(void); void main_loop(int cmdwin, int noexmode); void getout_preserve_modified(int exitval); --- 3,9 ---- void common_init(mparm_T *paramp); int is_not_a_term(void); void may_trigger_safestate(int safe); ! void state_no_longer_safe(void); void leave_unsafe_state(void); void main_loop(int cmdwin, int noexmode); void getout_preserve_modified(int exitval); *** ../vim-8.1.2045/src/getchar.c 2019-09-15 21:00:51.358604291 +0200 --- src/getchar.c 2019-09-16 21:49:39.066607001 +0200 *************** *** 933,938 **** --- 933,939 ---- init_typebuf(); if (++typebuf.tb_change_cnt == 0) typebuf.tb_change_cnt = 1; + state_no_longer_safe(); addlen = (int)STRLEN(str); *************** *** 1779,1788 **** */ may_garbage_collect = FALSE; #endif #ifdef FEAT_BEVAL_TERM if (c != K_MOUSEMOVE && c != K_IGNORE && c != K_CURSORHOLD) { ! /* Don't trigger 'balloonexpr' unless only the mouse was moved. */ bevalexpr_due_set = FALSE; ui_remove_balloon(); } --- 1780,1790 ---- */ may_garbage_collect = FALSE; #endif + #ifdef FEAT_BEVAL_TERM if (c != K_MOUSEMOVE && c != K_IGNORE && c != K_CURSORHOLD) { ! // Don't trigger 'balloonexpr' unless only the mouse was moved. bevalexpr_due_set = FALSE; ui_remove_balloon(); } *************** *** 1792,1797 **** --- 1794,1804 ---- c = K_IGNORE; #endif + // Need to process the character before we know it's safe to do something + // else. + if (c != K_IGNORE) + state_no_longer_safe(); + return c; } *************** *** 2039,2050 **** --- 2046,2060 ---- int old_curbuf_fnum = curbuf->b_fnum; int i; int save_may_garbage_collect = may_garbage_collect; + static int entered = 0; // Do not handle messages while redrawing, because it may cause buffers to // change or be wiped while they are being redrawn. if (updating_screen) return; + ++entered; + // may_garbage_collect is set in main_loop() to do garbage collection when // blocking to wait on a character. We don't want that while parsing // messages, a callback may invoke vgetc() while lists and dicts are in use *************** *** 2090,2101 **** --- 2100,2118 ---- break; } + // When not nested we'll go back to waiting for a typed character. If it + // was safe before then this triggers a SafeStateAgain autocommand event. + if (entered == 1) + leave_unsafe_state(); + may_garbage_collect = save_may_garbage_collect; // If the current window or buffer changed we need to bail out of the // waiting loop. E.g. when a job exit callback closes the terminal window. if (curwin->w_id != old_curwin_id || curbuf->b_fnum != old_curbuf_fnum) ins_char_typebuf(K_IGNORE); + + --entered; } #endif *** ../vim-8.1.2045/src/channel.c 2019-09-15 23:02:00.387231965 +0200 --- src/channel.c 2019-09-16 21:28:26.819018925 +0200 *************** *** 3593,3602 **** ch_log(channel, "Blocking read JSON for id %d", id); - // Not considered a safe state here, since we are processing a JSON message - // and parsing other messages while waiting. - enter_unsafe_state(); - if (id >= 0) channel_add_block_id(chanpart, id); --- 3593,3598 ---- *************** *** 3666,3674 **** if (id >= 0) channel_remove_block_id(chanpart, id); - // This may trigger a SafeState autocommand. - leave_unsafe_state(); - return retval; } --- 3662,3667 ---- *** ../vim-8.1.2045/src/autocmd.c 2019-09-15 23:02:00.387231965 +0200 --- src/autocmd.c 2019-09-16 21:31:46.302365909 +0200 *************** *** 156,161 **** --- 156,162 ---- {"QuitPre", EVENT_QUITPRE}, {"RemoteReply", EVENT_REMOTEREPLY}, {"SafeState", EVENT_SAFESTATE}, + {"SafeStateAgain", EVENT_SAFESTATEAGAIN}, {"SessionLoadPost", EVENT_SESSIONLOADPOST}, {"ShellCmdPost", EVENT_SHELLCMDPOST}, {"ShellFilterPost", EVENT_SHELLFILTERPOST}, *** ../vim-8.1.2045/src/vim.h 2019-09-15 23:02:00.387231965 +0200 --- src/vim.h 2019-09-16 21:32:13.858273782 +0200 *************** *** 1316,1321 **** --- 1316,1322 ---- EVENT_QUITPRE, // before :quit EVENT_REMOTEREPLY, // upon string reception from a remote vim EVENT_SAFESTATE, // going to wait for a character + EVENT_SAFESTATEAGAIN, // still waiting for a character EVENT_SESSIONLOADPOST, // after loading a session file EVENT_SHELLCMDPOST, // after ":!cmd" EVENT_SHELLFILTERPOST, // after ":1,2!cmd", ":w !cmd", ":r !cmd". *** ../vim-8.1.2045/src/version.c 2019-09-16 21:05:21.127911692 +0200 --- src/version.c 2019-09-16 21:56:18.445169041 +0200 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 2046, /**/ -- ARTHUR: (as the MAN next to him is squashed by a sheep) Knights! Run away! Midst echoing shouts of "run away" the KNIGHTS retreat to cover with the odd cow or goose hitting them still. The KNIGHTS crouch down under cover. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///