diff options
Diffstat (limited to 'src/nvim/ex_getln.c')
| -rw-r--r-- | src/nvim/ex_getln.c | 80 | 
1 files changed, 42 insertions, 38 deletions
| diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1810056a4a..7f40a984d1 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -177,10 +177,6 @@ typedef struct command_line_state {    int break_ctrl_c;    expand_T xpc;    long *b_im_ptr; -  // Everything that may work recursively should save and restore the -  // current command line in save_ccline.  That includes update_screen(), a -  // custom status line may invoke ":normal". -  struct cmdline_info save_ccline;  } CommandLineState;  typedef struct cmdline_info CmdlineInfo; @@ -225,11 +221,19 @@ static bool need_cursor_update = false;  # include "ex_getln.c.generated.h"  #endif -static int cmd_hkmap = 0;       /* Hebrew mapping during command line */ +static int cmd_hkmap = 0;  // Hebrew mapping during command line +static int cmd_fkmap = 0;  // Farsi mapping during command line -static int cmd_fkmap = 0;       /* Farsi mapping during command line */ +/// Internal entry point for cmdline mode. +/// +/// caller must use save_cmdline and restore_cmdline. Best is to use +/// getcmdline or getcmdline_prompt, instead of calling this directly.  static uint8_t *command_line_enter(int firstc, long count, int indent)  { +  // can be invoked recursively, identify each level +  static int cmdline_level = 0; +  cmdline_level++; +    CommandLineState state, *s = &state;    memset(s, 0, sizeof(CommandLineState));    s->firstc = firstc; @@ -257,7 +261,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)    }    ccline.prompt_id = last_prompt_id++; -  ccline.level++; +  ccline.level = cmdline_level;    ccline.overstrike = false;                // always start in insert mode    clearpos(&s->match_end);    s->save_cursor = curwin->w_cursor;        // may be restored later @@ -489,19 +493,14 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)    sb_text_end_cmdline(); -  { -    char_u *p = ccline.cmdbuff; - -    // Make ccline empty, getcmdline() may try to use it. -    ccline.cmdbuff = NULL; +  char_u *p = ccline.cmdbuff; -    if (ui_is_external(kUICmdline)) { -      ccline.redraw_state = kCmdRedrawNone; -      ui_call_cmdline_hide(ccline.level); -    } -    ccline.level--; -    return p; +  if (ui_is_external(kUICmdline)) { +    ui_call_cmdline_hide(ccline.level);    } + +  cmdline_level--; +  return p;  }  static int command_line_check(VimState *state) @@ -641,9 +640,7 @@ static int command_line_execute(VimState *state, int key)          p_ls = save_p_ls;          p_wmh = save_p_wmh;          last_status(false); -        save_cmdline(&s->save_ccline);          update_screen(VALID);                 // redraw the screen NOW -        restore_cmdline(&s->save_ccline);          redrawcmd();          save_p_ls = -1;          wild_menu_showing = 0; @@ -818,18 +815,17 @@ static int command_line_execute(VimState *state, int key)          new_cmdpos = ccline.cmdpos;        } -      save_cmdline(&s->save_ccline);        s->c = get_expr_register(); -      restore_cmdline(&s->save_ccline);        if (s->c == '=') {          // Need to save and restore ccline.  And set "textlock"          // to avoid nasty things like going to another buffer when          // evaluating an expression. -        save_cmdline(&s->save_ccline); -        ++textlock; +        CmdlineInfo save_ccline; +        save_cmdline(&save_ccline); +        textlock++;          p = get_expr_line(); -        --textlock; -        restore_cmdline(&s->save_ccline); +        textlock--; +        restore_cmdline(&save_ccline);          if (p != NULL) {            len = (int)STRLEN(p); @@ -1362,9 +1358,10 @@ static int command_line_handle_key(CommandLineState *s)          beep_flush();          s->c = ESC;        } else { -        save_cmdline(&s->save_ccline); +        CmdlineInfo save_ccline; +        save_cmdline(&save_ccline);          s->c = get_expr_register(); -        restore_cmdline(&s->save_ccline); +        restore_cmdline(&save_ccline);        }      } @@ -1899,9 +1896,7 @@ static int command_line_changed(CommandLineState *s)        curwin->w_redr_status = true;      } -    save_cmdline(&s->save_ccline);      update_screen(SOME_VALID); -    restore_cmdline(&s->save_ccline);      restore_last_search_pattern();      // Leave it at the end to make CTRL-R CTRL-W work. @@ -1996,7 +1991,14 @@ getcmdline (      int indent               // indent for inside conditionals  )  { -  return command_line_enter(firstc, count, indent); +  // Be prepared for situations where cmdline can be invoked recursively. +  // That includes cmd mappings, event handlers, as well as update_screen() +  // (custom status line eval), which all may invoke ":normal :". +  CmdlineInfo save_ccline; +  save_cmdline(&save_ccline); +  char_u *retval = command_line_enter(firstc, count, indent); +  restore_cmdline(&save_ccline); +  return retval;  }  /// Get a command line with a prompt @@ -2020,7 +2022,7 @@ char *getcmdline_prompt(const char firstc, const char *const prompt,  {    const int msg_col_save = msg_col; -  struct cmdline_info save_ccline; +  CmdlineInfo save_ccline;    save_cmdline(&save_ccline);    ccline.prompt_id = last_prompt_id++; @@ -2034,7 +2036,7 @@ char *getcmdline_prompt(const char firstc, const char *const prompt,    int msg_silent_saved = msg_silent;    msg_silent = 0; -  char *const ret = (char *)getcmdline(firstc, 1L, 0); +  char *const ret = (char *)command_line_enter(firstc, 1L, 0);    restore_cmdline(&save_ccline);    msg_silent = msg_silent_saved; @@ -2176,6 +2178,7 @@ getexline (    /* When executing a register, remove ':' that's in front of each line. */    if (exec_from_reg && vpeekc() == ':')      (void)vgetc(); +    return getcmdline(c, 1L, indent);  } @@ -3019,16 +3022,16 @@ void cmdline_screen_cleared(void)    }    int prev_level = ccline.level-1; -  CmdlineInfo *prev_ccline = ccline.prev_ccline; -  while (prev_level > 0 && prev_ccline) { -    if (prev_ccline->level == prev_level) { +  CmdlineInfo *line = ccline.prev_ccline; +  while (prev_level > 0 && line) { +    if (line->level == prev_level) {        // don't redraw a cmdline already shown in the cmdline window        if (prev_level != cmdwin_level) { -        prev_ccline->redraw_state = kCmdRedrawAll; +        line->redraw_state = kCmdRedrawAll;        }        prev_level--;      } -    prev_ccline = prev_ccline->prev_ccline; +    line = line->prev_ccline;    }    need_cursor_update = true; @@ -3244,6 +3247,7 @@ static void save_cmdline(struct cmdline_info *ccp)    ccline.cmdprompt = NULL;    ccline.xpc = NULL;    ccline.special_char = NUL; +  ccline.level = 0;  }  /* | 
