@@ -44,13 +44,12 @@ struct cmdline_info
4444# endif
4545};
4646
47- /* The current cmdline_info. It is initialized in getcmdline() and after that
48- * used by other functions. When invoking getcmdline() recursively it needs
49- * to be saved with save_cmdline() and restored with restore_cmdline().
50- * TODO: make it local to getcmdline() and pass it around. */
47+ // The current cmdline_info. It is initialized in getcmdline() and after that
48+ // used by other functions. When invoking getcmdline() recursively it needs
49+ // to be saved with save_cmdline() and restored with restore_cmdline().
5150static struct cmdline_info ccline ;
5251
53- static int cmd_showtail ; /* Only show path tail in lists ? */
52+ static int cmd_showtail ; /* Only show path tail in lists ? */
5453
5554#ifdef FEAT_EVAL
5655static int new_cmdpos ; /* position set by set_cmdline_pos() */
@@ -91,6 +90,7 @@ static int cmd_hkmap = 0; /* Hebrew mapping during command line */
9190static int cmd_fkmap = 0 ; /* Farsi mapping during command line */
9291#endif
9392
93+ static char_u * getcmdline_int (int firstc , long count , int indent , int init_ccline );
9494static int cmdline_charsize (int idx );
9595static void set_cmdspos (void );
9696static void set_cmdspos_cursor (void );
@@ -463,7 +463,6 @@ may_do_incsearch_highlighting(
463463 int skiplen , patlen ;
464464 int found ; // do_search() result
465465 pos_T end_pos ;
466- struct cmdline_info save_ccline ;
467466#ifdef FEAT_RELTIME
468467 proftime_T tm ;
469468#endif
@@ -601,9 +600,7 @@ may_do_incsearch_highlighting(
601600 if (p_ru && curwin -> w_status_height > 0 )
602601 curwin -> w_redr_status = TRUE;
603602
604- save_cmdline (& save_ccline );
605603 update_screen (SOME_VALID );
606- restore_cmdline (& save_ccline );
607604 restore_last_search_pattern ();
608605
609606 // Leave it at the end to make CTRL-R CTRL-W work. But not when beyond the
@@ -800,8 +797,18 @@ may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state)
800797 char_u *
801798getcmdline (
802799 int firstc ,
803- long count UNUSED , /* only used for incremental search */
804- int indent ) /* indent for inside conditionals */
800+ long count , // only used for incremental search
801+ int indent ) // indent for inside conditionals
802+ {
803+ return getcmdline_int (firstc , count , indent , TRUE);
804+ }
805+
806+ static char_u *
807+ getcmdline_int (
808+ int firstc ,
809+ long count UNUSED , // only used for incremental search
810+ int indent , // indent for inside conditionals
811+ int init_ccline ) // clear ccline first
805812{
806813 int c ;
807814 int i ;
@@ -832,14 +839,20 @@ getcmdline(
832839#endif
833840 expand_T xpc ;
834841 long * b_im_ptr = NULL ;
835- #if defined(FEAT_WILDMENU ) || defined(FEAT_EVAL )
836- /* Everything that may work recursively should save and restore the
837- * current command line in save_ccline. That includes update_screen(), a
838- * custom status line may invoke ":normal". */
839842 struct cmdline_info save_ccline ;
840- #endif
843+ int did_save_ccline = FALSE;
841844 int cmdline_type ;
842845
846+ if (ccline .cmdbuff != NULL )
847+ {
848+ // Being called recursively. Since ccline is global, we need to save
849+ // the current buffer and restore it when returning.
850+ save_cmdline (& save_ccline );
851+ did_save_ccline = TRUE;
852+ }
853+ if (init_ccline )
854+ vim_memset (& ccline , 0 , sizeof (struct cmdline_info ));
855+
843856#ifdef FEAT_EVAL
844857 if (firstc == -1 )
845858 {
@@ -868,7 +881,7 @@ getcmdline(
868881 /* alloc initial ccline.cmdbuff */
869882 alloc_cmdbuff (exmode_active ? 250 : indent + 1 );
870883 if (ccline .cmdbuff == NULL )
871- return NULL ; /* out of memory */
884+ goto theend ; // out of memory
872885 ccline .cmdlen = ccline .cmdpos = 0 ;
873886 ccline .cmdbuff [0 ] = NUL ;
874887 sb_text_start_cmdline ();
@@ -1125,9 +1138,7 @@ getcmdline(
11251138 p_ls = save_p_ls ;
11261139 p_wmh = save_p_wmh ;
11271140 last_status (FALSE);
1128- save_cmdline (& save_ccline );
11291141 update_screen (VALID ); /* redraw the screen NOW */
1130- restore_cmdline (& save_ccline );
11311142 redrawcmd ();
11321143 save_p_ls = -1 ;
11331144 }
@@ -1333,19 +1344,15 @@ getcmdline(
13331344 else
13341345 new_cmdpos = ccline .cmdpos ;
13351346
1336- save_cmdline (& save_ccline );
13371347 c = get_expr_register ();
1338- restore_cmdline (& save_ccline );
13391348 if (c == '=' )
13401349 {
13411350 /* Need to save and restore ccline. And set "textlock"
13421351 * to avoid nasty things like going to another buffer when
13431352 * evaluating an expression. */
1344- save_cmdline (& save_ccline );
13451353 ++ textlock ;
13461354 p = get_expr_line ();
13471355 -- textlock ;
1348- restore_cmdline (& save_ccline );
13491356
13501357 if (p != NULL )
13511358 {
@@ -1812,11 +1819,7 @@ getcmdline(
18121819 c = ESC ;
18131820 }
18141821 else
1815- {
1816- save_cmdline (& save_ccline );
18171822 c = get_expr_register ();
1818- restore_cmdline (& save_ccline );
1819- }
18201823 }
18211824#endif
18221825 if (c != ESC ) /* use ESC to cancel inserting register */
@@ -2187,7 +2190,7 @@ getcmdline(
21872190 int len ;
21882191 int old_firstc ;
21892192
2190- vim_free (ccline .cmdbuff );
2193+ VIM_CLEAR (ccline .cmdbuff );
21912194 xpc .xp_context = EXPAND_NOTHING ;
21922195 if (hiscnt == hislen )
21932196 p = lookfor ; /* back to the old one */
@@ -2486,11 +2489,14 @@ getcmdline(
24862489#endif
24872490 sb_text_end_cmdline ();
24882491
2492+ theend :
24892493 {
24902494 char_u * p = ccline .cmdbuff ;
24912495
2492- /* Make ccline empty, getcmdline() may try to use it. */
2493- ccline .cmdbuff = NULL ;
2496+ if (did_save_ccline )
2497+ restore_cmdline (& save_ccline );
2498+ else
2499+ ccline .cmdbuff = NULL ;
24942500 return p ;
24952501 }
24962502}
@@ -2512,10 +2518,18 @@ getcmdline_prompt(
25122518{
25132519 char_u * s ;
25142520 struct cmdline_info save_ccline ;
2521+ int did_save_ccline = FALSE;
25152522 int msg_col_save = msg_col ;
25162523 int msg_silent_save = msg_silent ;
25172524
2518- save_cmdline (& save_ccline );
2525+ if (ccline .cmdbuff != NULL )
2526+ {
2527+ // Save the values of the current cmdline and restore them below.
2528+ save_cmdline (& save_ccline );
2529+ did_save_ccline = TRUE;
2530+ }
2531+
2532+ vim_memset (& ccline , 0 , sizeof (struct cmdline_info ));
25192533 ccline .cmdprompt = prompt ;
25202534 ccline .cmdattr = attr ;
25212535# ifdef FEAT_EVAL
@@ -2524,8 +2538,11 @@ getcmdline_prompt(
25242538 ccline .input_fn = (firstc == '@' );
25252539# endif
25262540 msg_silent = 0 ;
2527- s = getcmdline (firstc , 1L , 0 );
2528- restore_cmdline (& save_ccline );
2541+ s = getcmdline_int (firstc , 1L , 0 , FALSE);
2542+
2543+ if (did_save_ccline )
2544+ restore_cmdline (& save_ccline );
2545+
25292546 msg_silent = msg_silent_save ;
25302547 /* Restore msg_col, the prompt from input() may have changed it.
25312548 * But only if called recursively and the commandline is therefore being
@@ -3121,7 +3138,6 @@ redrawcmd_preedit(void)
31213138/*
31223139 * Allocate a new command line buffer.
31233140 * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
3124- * Returns the new value of ccline.cmdbuff and ccline.cmdbufflen.
31253141 */
31263142 static void
31273143alloc_cmdbuff (int len )
@@ -3542,9 +3558,7 @@ save_cmdline(struct cmdline_info *ccp)
35423558 }
35433559 * ccp = prev_ccline ;
35443560 prev_ccline = ccline ;
3545- ccline .cmdbuff = NULL ;
3546- ccline .cmdprompt = NULL ;
3547- ccline .xpc = NULL ;
3561+ ccline .cmdbuff = NULL ; // signal that ccline is not in use
35483562}
35493563
35503564/*
@@ -3557,37 +3571,6 @@ restore_cmdline(struct cmdline_info *ccp)
35573571 prev_ccline = * ccp ;
35583572}
35593573
3560- #if defined(FEAT_EVAL ) || defined(PROTO )
3561- /*
3562- * Save the command line into allocated memory. Returns a pointer to be
3563- * passed to restore_cmdline_alloc() later.
3564- * Returns NULL when failed.
3565- */
3566- char_u *
3567- save_cmdline_alloc (void )
3568- {
3569- struct cmdline_info * p ;
3570-
3571- p = (struct cmdline_info * )alloc ((unsigned )sizeof (struct cmdline_info ));
3572- if (p != NULL )
3573- save_cmdline (p );
3574- return (char_u * )p ;
3575- }
3576-
3577- /*
3578- * Restore the command line from the return value of save_cmdline_alloc().
3579- */
3580- void
3581- restore_cmdline_alloc (char_u * p )
3582- {
3583- if (p != NULL )
3584- {
3585- restore_cmdline ((struct cmdline_info * )p );
3586- vim_free (p );
3587- }
3588- }
3589- #endif
3590-
35913574/*
35923575 * Paste a yank register into the command line.
35933576 * Used by CTRL-R command in command-line mode.
@@ -3606,7 +3589,6 @@ cmdline_paste(
36063589 char_u * arg ;
36073590 char_u * p ;
36083591 int allocated ;
3609- struct cmdline_info save_ccline ;
36103592
36113593 /* check for valid regname; also accept special characters for CTRL-R in
36123594 * the command line */
@@ -3625,13 +3607,11 @@ cmdline_paste(
36253607 regname = may_get_selection (regname );
36263608#endif
36273609
3628- /* Need to save and restore ccline. And set "textlock" to avoid nasty
3629- * things like going to another buffer when evaluating an expression. */
3630- save_cmdline (& save_ccline );
3610+ // Need to set "textlock" to avoid nasty things like going to another
3611+ // buffer when evaluating an expression.
36313612 ++ textlock ;
36323613 i = get_spec_reg (regname , & arg , & allocated , TRUE);
36333614 -- textlock ;
3634- restore_cmdline (& save_ccline );
36353615
36363616 if (i )
36373617 {
@@ -5601,7 +5581,6 @@ call_user_expand_func(
56015581 sctx_T save_current_sctx = current_sctx ;
56025582 char_u * pat = NULL ;
56035583 void * ret ;
5604- struct cmdline_info save_ccline ;
56055584
56065585 if (xp -> xp_arg == NULL || xp -> xp_arg [0 ] == '\0' || xp -> xp_line == NULL )
56075586 return NULL ;
@@ -5624,15 +5603,10 @@ call_user_expand_func(
56245603 args [2 ].vval .v_number = xp -> xp_col ;
56255604 args [3 ].v_type = VAR_UNKNOWN ;
56265605
5627- /* Save the cmdline, we don't know what the function may do. */
5628- save_ccline = ccline ;
5629- ccline .cmdbuff = NULL ;
5630- ccline .cmdprompt = NULL ;
56315606 current_sctx = xp -> xp_script_ctx ;
56325607
56335608 ret = user_expand_func (xp -> xp_arg , 3 , args );
56345609
5635- ccline = save_ccline ;
56365610 current_sctx = save_current_sctx ;
56375611 if (ccline .cmdbuff != NULL )
56385612 ccline .cmdbuff [ccline .cmdlen ] = keep ;
@@ -6481,7 +6455,7 @@ remove_key_from_history(void)
64816455
64826456#if defined(FEAT_EVAL ) || defined(FEAT_CMDWIN ) || defined(PROTO )
64836457/*
6484- * Get pointer to the command line info to use. cmdline_paste () may clear
6458+ * Get pointer to the command line info to use. save_ccline () may clear
64856459 * ccline and put the previous value in prev_ccline.
64866460 */
64876461 static struct cmdline_info *
@@ -7072,6 +7046,12 @@ finish_viminfo_history(vir_T *virp)
70727046 }
70737047}
70747048
7049+ void
7050+ cmdline_init (void )
7051+ {
7052+ vim_memset (& ccline , 0 , sizeof (struct cmdline_info ));
7053+ }
7054+
70757055/*
70767056 * Write history to viminfo file in "fp".
70777057 * When "merge" is TRUE merge history lines with a previously read viminfo
@@ -7238,7 +7218,6 @@ cmd_gchar(int offset)
72387218 static int
72397219open_cmdwin (void )
72407220{
7241- struct cmdline_info save_ccline ;
72427221 bufref_T old_curbuf ;
72437222 win_T * old_curwin = curwin ;
72447223 bufref_T bufref ;
@@ -7355,9 +7334,6 @@ open_cmdwin(void)
73557334 invalidate_botline ();
73567335 redraw_later (SOME_VALID );
73577336
7358- /* Save the command line info, can be used recursively. */
7359- save_cmdline (& save_ccline );
7360-
73617337 /* No Ex mode here! */
73627338 exmode_active = 0 ;
73637339
@@ -7394,10 +7370,7 @@ open_cmdwin(void)
73947370 KeyTyped = save_KeyTyped ;
73957371# endif
73967372
7397- /* Restore the command line info. */
7398- restore_cmdline (& save_ccline );
73997373 cmdwin_type = 0 ;
7400-
74017374 exmode_active = save_exmode ;
74027375
74037376 /* Safety check: The old window or buffer was deleted: It's a bug when
0 commit comments