@@ -524,29 +524,32 @@ ins_compl_accept_char(int c)
524524
525525/*
526526 * Get the completed text by inferring the case of the originally typed text.
527+ * If the result is in allocated memory "tofree" is set to it.
527528 */
528529 static char_u *
529530ins_compl_infercase_gettext (
530531 char_u * str ,
531- int actual_len ,
532- int actual_compl_length ,
533- int min_len )
532+ int char_len ,
533+ int compl_char_len ,
534+ int min_len ,
535+ char_u * * tofree )
534536{
535537 int * wca ; // Wide character array.
536538 char_u * p ;
537539 int i , c ;
538540 int has_lower = FALSE;
539541 int was_letter = FALSE;
542+ garray_T gap ;
540543
541544 IObuff [0 ] = NUL ;
542545
543546 // Allocate wide character array for the completion and fill it.
544- wca = ALLOC_MULT (int , actual_len );
547+ wca = ALLOC_MULT (int , char_len );
545548 if (wca == NULL )
546549 return IObuff ;
547550
548551 p = str ;
549- for (i = 0 ; i < actual_len ; ++ i )
552+ for (i = 0 ; i < char_len ; ++ i )
550553 if (has_mbyte )
551554 wca [i ] = mb_ptr2char_adv (& p );
552555 else
@@ -566,7 +569,7 @@ ins_compl_infercase_gettext(
566569 if (MB_ISUPPER (wca [i ]))
567570 {
568571 // Rule 1 is satisfied.
569- for (i = actual_compl_length ; i < actual_len ; ++ i )
572+ for (i = compl_char_len ; i < char_len ; ++ i )
570573 wca [i ] = MB_TOLOWER (wca [i ]);
571574 break ;
572575 }
@@ -587,7 +590,7 @@ ins_compl_infercase_gettext(
587590 if (was_letter && MB_ISUPPER (c ) && MB_ISLOWER (wca [i ]))
588591 {
589592 // Rule 2 is satisfied.
590- for (i = actual_compl_length ; i < actual_len ; ++ i )
593+ for (i = compl_char_len ; i < char_len ; ++ i )
591594 wca [i ] = MB_TOUPPER (wca [i ]);
592595 break ;
593596 }
@@ -610,20 +613,52 @@ ins_compl_infercase_gettext(
610613 }
611614
612615 // Generate encoding specific output from wide character array.
613- // Multi-byte characters can occupy up to five bytes more than
614- // ASCII characters, and we also need one byte for NUL, so stay
615- // six bytes away from the edge of IObuff.
616616 p = IObuff ;
617617 i = 0 ;
618- while (i < actual_len && (p - IObuff + 6 ) < IOSIZE )
619- if (has_mbyte )
618+ ga_init2 (& gap , 1 , 500 );
619+ while (i < char_len )
620+ {
621+ if (gap .ga_data != NULL )
622+ {
623+ if (ga_grow (& gap , 10 ) == FAIL )
624+ {
625+ ga_clear (& gap );
626+ return (char_u * )"[failed]" ;
627+ }
628+ p = (char_u * )gap .ga_data + gap .ga_len ;
629+ if (has_mbyte )
630+ gap .ga_len += (* mb_char2bytes )(wca [i ++ ], p );
631+ else
632+ {
633+ * p = wca [i ++ ];
634+ ++ gap .ga_len ;
635+ }
636+ }
637+ else if ((p - IObuff ) + 6 >= IOSIZE )
638+ {
639+ // Multi-byte characters can occupy up to five bytes more than
640+ // ASCII characters, and we also need one byte for NUL, so when
641+ // getting to six bytes from the edge of IObuff switch to using a
642+ // growarray. Add the character in the next round.
643+ if (ga_grow (& gap , IOSIZE ) == FAIL )
644+ return (char_u * )"[failed]" ;
645+ STRCPY (gap .ga_data , IObuff );
646+ gap .ga_len = STRLEN (IObuff );
647+ }
648+ else if (has_mbyte )
620649 p += (* mb_char2bytes )(wca [i ++ ], p );
621650 else
622651 * (p ++ ) = wca [i ++ ];
623- * p = NUL ;
624-
652+ }
625653 vim_free (wca );
626654
655+ if (gap .ga_data != NULL )
656+ {
657+ * tofree = gap .ga_data ;
658+ return gap .ga_data ;
659+ }
660+
661+ * p = NUL ;
627662 return IObuff ;
628663}
629664
@@ -644,10 +679,12 @@ ins_compl_add_infercase(
644679{
645680 char_u * str = str_arg ;
646681 char_u * p ;
647- int actual_len ; // Take multi-byte characters
648- int actual_compl_length ; // into account.
682+ int char_len ; // count multi-byte characters
683+ int compl_char_len ;
649684 int min_len ;
650685 int flags = 0 ;
686+ int res ;
687+ char_u * tofree = NULL ;
651688
652689 if (p_ic && curbuf -> b_p_inf && len > 0 )
653690 {
@@ -657,44 +694,45 @@ ins_compl_add_infercase(
657694 if (has_mbyte )
658695 {
659696 p = str ;
660- actual_len = 0 ;
697+ char_len = 0 ;
661698 while (* p != NUL )
662699 {
663700 MB_PTR_ADV (p );
664- ++ actual_len ;
701+ ++ char_len ;
665702 }
666703 }
667704 else
668- actual_len = len ;
705+ char_len = len ;
669706
670707 // Find actual length of original text.
671708 if (has_mbyte )
672709 {
673710 p = compl_orig_text ;
674- actual_compl_length = 0 ;
711+ compl_char_len = 0 ;
675712 while (* p != NUL )
676713 {
677714 MB_PTR_ADV (p );
678- ++ actual_compl_length ;
715+ ++ compl_char_len ;
679716 }
680717 }
681718 else
682- actual_compl_length = compl_length ;
719+ compl_char_len = compl_length ;
683720
684- // "actual_len " may be smaller than "actual_compl_length " when using
721+ // "char_len " may be smaller than "compl_char_len " when using
685722 // thesaurus, only use the minimum when comparing.
686- min_len = actual_len < actual_compl_length
687- ? actual_len : actual_compl_length ;
723+ min_len = char_len < compl_char_len ? char_len : compl_char_len ;
688724
689- str = ins_compl_infercase_gettext (str , actual_len , actual_compl_length ,
690- min_len );
725+ str = ins_compl_infercase_gettext (str , char_len ,
726+ compl_char_len , min_len , & tofree );
691727 }
692728 if (cont_s_ipos )
693729 flags |= CP_CONT_S_IPOS ;
694730 if (icase )
695731 flags |= CP_ICASE ;
696732
697- return ins_compl_add (str , len , fname , NULL , NULL , dir , flags , FALSE);
733+ res = ins_compl_add (str , len , fname , NULL , NULL , dir , flags , FALSE);
734+ vim_free (tofree );
735+ return res ;
698736}
699737
700738/*
0 commit comments