@@ -125,8 +125,6 @@ init_history(void)
125125{
126126 int newlen ; // new length of history table
127127 histentry_T * temp ;
128- int i ;
129- int j ;
130128 int type ;
131129
132130 // If size of history table changed, reallocate it
@@ -159,11 +157,16 @@ init_history(void)
159157
160158 if (hisidx [type ] < 0 ) // there are no entries yet
161159 {
160+ int i ;
161+
162162 for (i = 0 ; i < newlen ; ++ i )
163163 clear_hist_entry (& temp [i ]);
164164 }
165165 else if (newlen > hislen ) // array becomes bigger
166166 {
167+ int i ;
168+ int j ;
169+
167170 for (i = 0 ; i <= hisidx [type ]; ++ i )
168171 temp [i ] = history [type ][i ];
169172 j = i ;
@@ -174,13 +177,19 @@ init_history(void)
174177 }
175178 else // array becomes smaller or 0
176179 {
180+ int i ;
181+ int j ;
182+
177183 j = hisidx [type ];
178184 for (i = newlen - 1 ; ; -- i )
179185 {
180186 if (i >= 0 ) // copy newest entries
181187 temp [i ] = history [type ][j ];
182188 else // remove older entries
189+ {
183190 vim_free (history [type ][j ].hisstr );
191+ history [type ][j ].hisstrlen = 0 ;
192+ }
184193 if (-- j < 0 )
185194 j = hislen - 1 ;
186195 if (j == hisidx [type ])
@@ -200,6 +209,7 @@ clear_hist_entry(histentry_T *hisptr)
200209 hisptr -> hisnum = 0 ;
201210 hisptr -> viminfo = FALSE;
202211 hisptr -> hisstr = NULL ;
212+ hisptr -> hisstrlen = 0 ;
203213 hisptr -> time_set = 0 ;
204214}
205215
@@ -218,6 +228,7 @@ in_history(
218228 int i ;
219229 int last_i = -1 ;
220230 char_u * p ;
231+ size_t len ;
221232
222233 if (hisidx [type ] < 0 )
223234 return FALSE;
@@ -232,7 +243,7 @@ in_history(
232243 p = history [type ][i ].hisstr ;
233244 if (STRCMP (str , p ) == 0
234245 && !(writing && history [type ][i ].viminfo )
235- && (type != HIST_SEARCH || sep == p [STRLEN ( p ) + 1 ]))
246+ && (type != HIST_SEARCH || sep == p [history [ type ][ i ]. hisstrlen + 1 ]))
236247 {
237248 if (!move_to_front )
238249 return TRUE;
@@ -247,6 +258,7 @@ in_history(
247258 return FALSE;
248259
249260 str = history [type ][i ].hisstr ;
261+ len = history [type ][i ].hisstrlen ;
250262 while (i != hisidx [type ])
251263 {
252264 if (++ i >= hislen )
@@ -257,6 +269,7 @@ in_history(
257269 history [type ][i ].hisnum = ++ hisnum [type ];
258270 history [type ][i ].viminfo = FALSE;
259271 history [type ][i ].hisstr = str ;
272+ history [type ][i ].hisstrlen = len ;
260273 history [type ][i ].time_set = vim_time ();
261274 return TRUE;
262275}
@@ -337,8 +350,13 @@ add_to_history(
337350
338351 // Store the separator after the NUL of the string.
339352 hisptr -> hisstr = vim_strnsave (new_entry , new_entrylen + 2 );
340- if (hisptr -> hisstr != NULL )
353+ if (hisptr -> hisstr == NULL )
354+ hisptr -> hisstrlen = 0 ;
355+ else
356+ {
341357 hisptr -> hisstr [new_entrylen + 1 ] = sep ;
358+ hisptr -> hisstrlen = new_entrylen ;
359+ }
342360
343361 hisptr -> hisnum = ++ hisnum [histype ];
344362 hisptr -> viminfo = FALSE;
@@ -405,20 +423,6 @@ calc_hist_idx(int histype, int num)
405423 return -1 ;
406424}
407425
408- /*
409- * Get a history entry by its index.
410- * "histype" may be one of the HIST_ values.
411- */
412- static char_u *
413- get_history_entry (int histype , int idx )
414- {
415- idx = calc_hist_idx (histype , idx );
416- if (idx >= 0 )
417- return history [histype ][idx ].hisstr ;
418- else
419- return (char_u * )"" ;
420- }
421-
422426/*
423427 * Clear all entries of a history.
424428 * "histype" may be one of the HIST_ values.
@@ -517,6 +521,7 @@ del_history_idx(int histype, int idx)
517521 return FALSE;
518522 idx = hisidx [histype ];
519523 vim_free (history [histype ][i ].hisstr );
524+ history [histype ][i ].hisstrlen = 0 ;
520525
521526 // When deleting the last added search string in a mapping, reset
522527 // last_maptick, so that the last added search string isn't deleted again.
@@ -576,7 +581,6 @@ f_histadd(typval_T *argvars UNUSED, typval_T *rettv)
576581f_histdel (typval_T * argvars UNUSED , typval_T * rettv UNUSED )
577582{
578583 int n ;
579- char_u buf [NUMBUFLEN ];
580584 char_u * str ;
581585
582586 if (in_vim9script ()
@@ -595,9 +599,14 @@ f_histdel(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
595599 n = del_history_idx (get_histtype (str ),
596600 (int )tv_get_number (& argvars [1 ]));
597601 else
602+ {
603+ char_u buf [NUMBUFLEN ];
604+
598605 // string given: remove all matching entries
599606 n = del_history_entry (get_histtype (str ),
600607 tv_get_string_buf (& argvars [1 ], buf ));
608+ }
609+
601610 rettv -> vval .v_number = n ;
602611}
603612
@@ -607,9 +616,7 @@ f_histdel(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
607616 void
608617f_histget (typval_T * argvars UNUSED , typval_T * rettv )
609618{
610- int type ;
611- int idx ;
612- char_u * str ;
619+ char_u * str ;
613620
614621 if (in_vim9script ()
615622 && (check_for_string_arg (argvars , 0 ) == FAIL
@@ -621,13 +628,21 @@ f_histget(typval_T *argvars UNUSED, typval_T *rettv)
621628 rettv -> vval .v_string = NULL ;
622629 else
623630 {
631+ int type ;
632+ int idx ;
633+
624634 type = get_histtype (str );
625635 if (argvars [1 ].v_type == VAR_UNKNOWN )
626636 idx = get_history_idx (type );
627637 else
628638 idx = (int )tv_get_number_chk (& argvars [1 ], NULL );
629639 // -1 on type error
630- rettv -> vval .v_string = vim_strsave (get_history_entry (type , idx ));
640+
641+ idx = calc_hist_idx (type , idx );
642+ if (idx < 0 )
643+ rettv -> vval .v_string = vim_strnsave ((char_u * )"" , 0 );
644+ else
645+ rettv -> vval .v_string = vim_strnsave (history [type ][idx ].hisstr , history [type ][idx ].hisstrlen );
631646 }
632647 rettv -> v_type = VAR_STRING ;
633648}
@@ -647,10 +662,9 @@ f_histnr(typval_T *argvars UNUSED, typval_T *rettv)
647662 histname = tv_get_string_chk (& argvars [0 ]);
648663 i = histname == NULL ? HIST_CMD - 1 : get_histtype (histname );
649664 if (i >= HIST_CMD && i < HIST_COUNT )
650- i = get_history_idx (i );
665+ rettv -> vval . v_number = get_history_idx (i );
651666 else
652- i = -1 ;
653- rettv -> vval .v_number = i ;
667+ rettv -> vval .v_number = -1 ;
654668}
655669#endif // FEAT_EVAL
656670
@@ -662,17 +676,21 @@ f_histnr(typval_T *argvars UNUSED, typval_T *rettv)
662676 void
663677remove_key_from_history (void )
664678{
679+ char_u * p_start ;
680+ char_u * p_end ;
665681 char_u * p ;
666682 int i ;
667683
668684 i = hisidx [HIST_CMD ];
669685 if (i < 0 )
670686 return ;
671- p = history [HIST_CMD ][i ].hisstr ;
672- if (p == NULL )
687+ p_start = history [HIST_CMD ][i ].hisstr ;
688+ if (p_start == NULL )
673689 return ;
674690
675- for ( ; * p ; ++ p )
691+ p_end = p_start + history [HIST_CMD ][i ].hisstrlen ;
692+ for (p = p_start ; * p ; ++ p )
693+ {
676694 if (STRNCMP (p , "key" , 3 ) == 0 && !SAFE_isalpha (p [3 ]))
677695 {
678696 p = vim_strchr (p + 3 , '=' );
@@ -682,9 +700,14 @@ remove_key_from_history(void)
682700 for (i = 0 ; p [i ] && !VIM_ISWHITE (p [i ]); ++ i )
683701 if (p [i ] == '\\' && p [i + 1 ])
684702 ++ i ;
685- STRMOVE (p , p + i );
703+
704+ mch_memmove (p , p + i , (p_end - (p + i )) + 1 ); // +1 for the NUL
705+ p_end -= i ; // adjust p_end for shortened string
686706 -- p ;
687707 }
708+ }
709+
710+ history [HIST_CMD ][i ].hisstrlen = (size_t )(p_end - p_start );
688711}
689712#endif
690713
@@ -750,17 +773,16 @@ ex_history(exarg_T *eap)
750773
751774 for (; !got_int && histype1 <= histype2 ; ++ histype1 )
752775 {
753- STRCPY (IObuff , "\n # " );
754- STRCAT (STRCAT (IObuff , history_names [histype1 ]), " history" );
776+ vim_snprintf ((char * )IObuff , IOSIZE , "\n # %s history" , history_names [histype1 ]);
755777 msg_puts_title ((char * )IObuff );
756778 idx = hisidx [histype1 ];
757779 hist = history [histype1 ];
758780 j = hisidx1 ;
759781 k = hisidx2 ;
760782 if (j < 0 )
761- j = (- j > hislen ) ? 0 : hist [(hislen + j + idx + 1 ) % hislen ].hisnum ;
783+ j = (- j > hislen ) ? 0 : hist [(hislen + j + idx + 1 ) % hislen ].hisnum ;
762784 if (k < 0 )
763- k = (- k > hislen ) ? 0 : hist [(hislen + k + idx + 1 ) % hislen ].hisnum ;
785+ k = (- k > hislen ) ? 0 : hist [(hislen + k + idx + 1 ) % hislen ].hisnum ;
764786 if (idx >= 0 && j <= k )
765787 for (i = idx + 1 ; !got_int ; ++ i )
766788 {
@@ -770,14 +792,16 @@ ex_history(exarg_T *eap)
770792 && hist [i ].hisnum >= j && hist [i ].hisnum <= k
771793 && !message_filtered (hist [i ].hisstr ))
772794 {
795+ int len ;
796+
773797 msg_putchar ('\n' );
774- sprintf ((char * )IObuff , "%c%6d " , i == idx ? '>' : ' ' ,
775- hist [i ].hisnum );
798+ len = vim_snprintf ((char * )IObuff , IOSIZE ,
799+ "%c%6d " , i == idx ? '>' : ' ' , hist [i ].hisnum );
776800 if (vim_strsize (hist [i ].hisstr ) > (int )Columns - 10 )
777- trunc_string (hist [i ].hisstr , IObuff + STRLEN ( IObuff ) ,
778- (int )Columns - 10 , IOSIZE - (int )STRLEN ( IObuff ) );
801+ trunc_string (hist [i ].hisstr , IObuff + len ,
802+ (int )Columns - 10 , IOSIZE - (int )len );
779803 else
780- STRCAT (IObuff , hist [i ].hisstr );
804+ STRCPY (IObuff + len , hist [i ].hisstr );
781805 msg_outtrans (IObuff );
782806 out_flush ();
783807 }
0 commit comments