summaryrefslogtreecommitdiffstats
path: root/src/misc1.c
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2022-04-09 18:17:34 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-09 18:17:34 +0100
commit2bf52dd065495cbf28e28792f2c2d50d44546d9f (patch)
treef6c2fabb35e2f7f12f441d76048b3f1575f4a6b4 /src/misc1.c
parent81b46a6ccd818609e1ca8cd410e26a58428c30ba (diff)
patch 8.2.4723: the ModeChanged autocmd event is inefficientv8.2.4723
Problem: The ModeChanged autocmd event is inefficient. Solution: Avoid allocating memory. (closes #10134) Rename trigger_modechanged() to may_trigger_modechanged().
Diffstat (limited to 'src/misc1.c')
-rw-r--r--src/misc1.c117
1 files changed, 60 insertions, 57 deletions
diff --git a/src/misc1.c b/src/misc1.c
index 7fc625b51d..82dbbba6e6 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -625,105 +625,119 @@ ask_yesno(char_u *str, int direct)
#if defined(FEAT_EVAL) || defined(PROTO)
/*
- * "mode()" function
+ * Returns the current mode as a string in "buf[MODE_MAX_LENGTH]", NUL
+ * terminated.
+ * The first character represents the major mode, the following ones the minor
+ * ones.
*/
void
-f_mode(typval_T *argvars, typval_T *rettv)
+get_mode(char_u *buf)
{
- char_u buf[MODE_MAX_LENGTH];
-
- if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL)
- return;
-
- CLEAR_FIELD(buf);
+ int i = 0;
if (time_for_testing == 93784)
{
// Testing the two-character code.
- buf[0] = 'x';
- buf[1] = '!';
+ buf[i++] = 'x';
+ buf[i++] = '!';
}
#ifdef FEAT_TERMINAL
else if (term_use_loop())
- buf[0] = 't';
+ buf[i++] = 't';
#endif
else if (VIsual_active)
{
if (VIsual_select)
- buf[0] = VIsual_mode + 's' - 'v';
+ buf[i++] = VIsual_mode + 's' - 'v';
else
{
- buf[0] = VIsual_mode;
+ buf[i++] = VIsual_mode;
if (restart_VIsual_select)
- buf[1] = 's';
+ buf[i++] = 's';
}
}
else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE
|| State == CONFIRM)
{
- buf[0] = 'r';
+ buf[i++] = 'r';
if (State == ASKMORE)
- buf[1] = 'm';
+ buf[i++] = 'm';
else if (State == CONFIRM)
- buf[1] = '?';
+ buf[i++] = '?';
}
else if (State == EXTERNCMD)
- buf[0] = '!';
+ buf[i++] = '!';
else if (State & INSERT)
{
if (State & VREPLACE_FLAG)
{
- buf[0] = 'R';
- buf[1] = 'v';
+ buf[i++] = 'R';
+ buf[i++] = 'v';
if (ins_compl_active())
- buf[2] = 'c';
+ buf[i++] = 'c';
else if (ctrl_x_mode_not_defined_yet())
- buf[2] = 'x';
+ buf[i++] = 'x';
}
else
{
if (State & REPLACE_FLAG)
- buf[0] = 'R';
+ buf[i++] = 'R';
else
- buf[0] = 'i';
+ buf[i++] = 'i';
if (ins_compl_active())
- buf[1] = 'c';
+ buf[i++] = 'c';
else if (ctrl_x_mode_not_defined_yet())
- buf[1] = 'x';
+ buf[i++] = 'x';
}
}
else if ((State & CMDLINE) || exmode_active)
{
- buf[0] = 'c';
+ buf[i++] = 'c';
if (exmode_active == EXMODE_VIM)
- buf[1] = 'v';
+ buf[i++] = 'v';
else if (exmode_active == EXMODE_NORMAL)
- buf[1] = 'e';
+ buf[i++] = 'e';
}
else
{
- buf[0] = 'n';
+ buf[i++] = 'n';
if (finish_op)
{
- buf[1] = 'o';
+ buf[i++] = 'o';
// to be able to detect force-linewise/blockwise/characterwise
// operations
- buf[2] = motion_force;
+ buf[i++] = motion_force;
}
else if (restart_edit == 'I' || restart_edit == 'R'
|| restart_edit == 'V')
{
- buf[1] = 'i';
- buf[2] = restart_edit;
+ buf[i++] = 'i';
+ buf[i++] = restart_edit;
}
#ifdef FEAT_TERMINAL
else if (term_in_normal_mode())
- buf[1] = 't';
+ buf[i++] = 't';
#endif
}
+ buf[i] = NUL;
+}
+
+/*
+ * "mode()" function
+ */
+ void
+f_mode(typval_T *argvars, typval_T *rettv)
+{
+ char_u buf[MODE_MAX_LENGTH];
+
+ if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL)
+ return;
+
+ get_mode(buf);
+
// Clear out the minor mode when the argument is not a non-zero number or
// non-empty string.
if (!non_zero_arg(&argvars[0]))
@@ -2691,47 +2705,36 @@ restore_v_event(dict_T *v_event, save_v_event_T *sve)
#endif
/*
- * Fires a ModeChanged autocmd
+ * Fires a ModeChanged autocmd event if appropriate.
*/
void
-trigger_modechanged()
+may_trigger_modechanged()
{
#ifdef FEAT_EVAL
dict_T *v_event;
- typval_T rettv;
- typval_T tv[2];
- char_u *pat_pre;
- char_u *pat;
save_v_event_T save_v_event;
+ char_u curr_mode[MODE_MAX_LENGTH];
+ char_u pattern_buf[2 * MODE_MAX_LENGTH];
if (!has_modechanged())
return;
- tv[0].v_type = VAR_NUMBER;
- tv[0].vval.v_number = 1; // get full mode
- tv[1].v_type = VAR_UNKNOWN;
- f_mode(tv, &rettv);
- if (STRCMP(rettv.vval.v_string, last_mode) == 0)
- {
- vim_free(rettv.vval.v_string);
+ get_mode(curr_mode);
+ if (STRCMP(curr_mode, last_mode) == 0)
return;
- }
v_event = get_v_event(&save_v_event);
- (void)dict_add_string(v_event, "new_mode", rettv.vval.v_string);
+ (void)dict_add_string(v_event, "new_mode", curr_mode);
(void)dict_add_string(v_event, "old_mode", last_mode);
dict_set_items_ro(v_event);
// concatenate modes in format "old_mode:new_mode"
- pat_pre = concat_str(last_mode, (char_u*)":");
- pat = concat_str(pat_pre, rettv.vval.v_string);
- vim_free(pat_pre);
+ vim_snprintf((char *)pattern_buf, sizeof(pattern_buf), "%s:%s", last_mode,
+ curr_mode);
- apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf);
- STRCPY(last_mode, rettv.vval.v_string);
+ apply_autocmds(EVENT_MODECHANGED, pattern_buf, NULL, FALSE, curbuf);
+ STRCPY(last_mode, curr_mode);
- vim_free(pat);
restore_v_event(v_event, &save_v_event);
- vim_free(rettv.vval.v_string);
#endif
}