summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-09-18 21:15:31 +0200
committerBram Moolenaar <Bram@vim.org>2019-09-18 21:15:31 +0200
commitd103ee78432f9036d243b18dd5aac1263d3b7dc9 (patch)
tree5b63ac38b27bdf3459ef73f82eff2b2376da41c1 /src/main.c
parent7a9bd7c1e0ce1baf5a02daf36eeae3638aa315c7 (diff)
downloadvim-git-d103ee78432f9036d243b18dd5aac1263d3b7dc9.tar.gz
patch 8.1.2053: SafeStateAgain not triggered if callback uses feedkeys()v8.1.2053
Problem: SafeStateAgain not triggered if callback uses feedkeys(). Solution: Check for safe state in the input loop. Make log messages easier to find. Add 'S' flag to state().
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/main.c b/src/main.c
index 52bbafe6c..8c56c17b5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1049,24 +1049,33 @@ op_pending(void)
}
/*
+ * Return whether currently it is safe, assuming it was safe before (high level
+ * state didn't change).
+ */
+ static int
+is_safe_now(void)
+{
+ return stuff_empty()
+ && typebuf.tb_len == 0
+ && scriptin[curscript] == NULL
+ && !global_busy;
+}
+
+/*
* Trigger SafeState if currently in s safe state, that is "safe" is TRUE and
* there is no typeahead.
*/
void
may_trigger_safestate(int safe)
{
- int is_safe = safe
- && stuff_empty()
- && typebuf.tb_len == 0
- && scriptin[curscript] == NULL
- && !global_busy;
+ int is_safe = safe && is_safe_now();
#ifdef FEAT_JOB_CHANNEL
if (was_safe != is_safe)
// Only log when the state changes, otherwise it happens at nearly
// every key stroke.
- ch_log(NULL, is_safe ? "Start triggering SafeState"
- : "Stop triggering SafeState");
+ ch_log(NULL, is_safe ? "SafeState: Start triggering"
+ : "SafeState: Stop triggering");
#endif
if (is_safe)
apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf);
@@ -1079,15 +1088,21 @@ may_trigger_safestate(int safe)
* may_trigger_safestate().
*/
void
-state_no_longer_safe(void)
+state_no_longer_safe(char *reason UNUSED)
{
#ifdef FEAT_JOB_CHANNEL
if (was_safe)
- ch_log(NULL, "safe state reset");
+ ch_log(NULL, "SafeState: reset: %s", reason);
#endif
was_safe = FALSE;
}
+ int
+get_was_safe_state(void)
+{
+ return was_safe;
+}
+
/*
* Invoked when leaving code that invokes callbacks. Then trigger
* SafeStateAgain, if it was safe when starting to wait for a character.
@@ -1095,16 +1110,28 @@ state_no_longer_safe(void)
void
may_trigger_safestateagain(void)
{
+ if (!was_safe)
+ {
+ // If the safe state was reset in state_no_longer_safe(), e.g. because
+ // of calling feedkeys(), we check if it's now safe again (all keys
+ // were consumed).
+ was_safe = is_safe_now();
+#ifdef FEAT_JOB_CHANNEL
+ if (was_safe)
+ ch_log(NULL, "SafeState: undo reset");
+#endif
+ }
if (was_safe)
{
#ifdef FEAT_JOB_CHANNEL
- ch_log(NULL, "Leaving unsafe area, triggering SafeStateAgain");
+ ch_log(NULL, "SafeState: back to waiting, triggering SafeStateAgain");
#endif
apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf);
}
#ifdef FEAT_JOB_CHANNEL
else
- ch_log(NULL, "Leaving unsafe area, not triggering SafeStateAgain");
+ ch_log(NULL,
+ "SafeState: back to waiting, not triggering SafeStateAgain");
#endif
}