From 6ad84ab3e48d9490e4139df04f2c55b136f5501d Mon Sep 17 00:00:00 2001
From: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Fri, 31 Dec 2021 12:59:53 +0000
Subject: [PATCH] patch 8.2.3953: insert completion code is too complicated

Problem:    Insert completion code is too complicated.
Solution:   More refactoring.  Move function arguments into a struct.
(Yegappan Lakshmanan, closes #9437)
---
 src/insexpand.c | 196 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 107 insertions(+), 89 deletions(-)

diff --git a/src/insexpand.c b/src/insexpand.c
index 66a836e..3b4d530 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -407,6 +407,111 @@ ins_compl_accept_char(int c)
 }
 
 /*
+ * Get the completed text by inferring the case of the originally typed text.
+ */
+    static char_u *
+ins_compl_infercase_gettext(
+	char_u	*str,
+	int	actual_len,
+	int	actual_compl_length,
+	int	min_len)
+{
+    int		*wca;			// Wide character array.
+    char_u	*p;
+    int		i, c;
+    int		has_lower = FALSE;
+    int		was_letter = FALSE;
+
+    IObuff[0] = NUL;
+
+    // Allocate wide character array for the completion and fill it.
+    wca = ALLOC_MULT(int, actual_len);
+    if (wca == NULL)
+	return IObuff;
+
+    p = str;
+    for (i = 0; i < actual_len; ++i)
+	if (has_mbyte)
+	    wca[i] = mb_ptr2char_adv(&p);
+	else
+	    wca[i] = *(p++);
+
+    // Rule 1: Were any chars converted to lower?
+    p = compl_orig_text;
+    for (i = 0; i < min_len; ++i)
+    {
+	if (has_mbyte)
+	    c = mb_ptr2char_adv(&p);
+	else
+	    c = *(p++);
+	if (MB_ISLOWER(c))
+	{
+	    has_lower = TRUE;
+	    if (MB_ISUPPER(wca[i]))
+	    {
+		// Rule 1 is satisfied.
+		for (i = actual_compl_length; i < actual_len; ++i)
+		    wca[i] = MB_TOLOWER(wca[i]);
+		break;
+	    }
+	}
+    }
+
+    // Rule 2: No lower case, 2nd consecutive letter converted to
+    // upper case.
+    if (!has_lower)
+    {
+	p = compl_orig_text;
+	for (i = 0; i < min_len; ++i)
+	{
+	    if (has_mbyte)
+		c = mb_ptr2char_adv(&p);
+	    else
+		c = *(p++);
+	    if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
+	    {
+		// Rule 2 is satisfied.
+		for (i = actual_compl_length; i < actual_len; ++i)
+		    wca[i] = MB_TOUPPER(wca[i]);
+		break;
+	    }
+	    was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
+	}
+    }
+
+    // Copy the original case of the part we typed.
+    p = compl_orig_text;
+    for (i = 0; i < min_len; ++i)
+    {
+	if (has_mbyte)
+	    c = mb_ptr2char_adv(&p);
+	else
+	    c = *(p++);
+	if (MB_ISLOWER(c))
+	    wca[i] = MB_TOLOWER(wca[i]);
+	else if (MB_ISUPPER(c))
+	    wca[i] = MB_TOUPPER(wca[i]);
+    }
+
+    // Generate encoding specific output from wide character array.
+    // Multi-byte characters can occupy up to five bytes more than
+    // ASCII characters, and we also need one byte for NUL, so stay
+    // six bytes away from the edge of IObuff.
+    p = IObuff;
+    i = 0;
+    while (i < actual_len && (p - IObuff + 6) < IOSIZE)
+	if (has_mbyte)
+	    p += (*mb_char2bytes)(wca[i++], p);
+	else
+	    *(p++) = wca[i++];
+    *p = NUL;
+
+    vim_free(wca);
+
+    return IObuff;
+}
+
+/*
  * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
  * case of the originally typed text is used, and the case of the completed
  * text is inferred, ie this tries to work out what case you probably wanted
@@ -423,13 +528,9 @@ ins_compl_add_infercase(
 {
     char_u	*str = str_arg;
     char_u	*p;
-    int		i, c;
     int		actual_len;		// Take multi-byte characters
     int		actual_compl_length;	// into account.
     int		min_len;
-    int		*wca;			// Wide character array.
-    int		has_lower = FALSE;
-    int		was_letter = FALSE;
     int		flags = 0;
 
     if (p_ic && curbuf->b_p_inf && len > 0)
@@ -469,91 +570,8 @@ ins_compl_add_infercase(
 	min_len = actual_len < actual_compl_length
 					   ? actual_len : actual_compl_length;
 
-	// Allocate wide character array for the completion and fill it.
-	wca = ALLOC_MULT(int, actual_len);
-	if (wca != NULL)
-	{
-	    p = str;
-	    for (i = 0; i < actual_len; ++i)
-		if (has_mbyte)
-		    wca[i] = mb_ptr2char_adv(&p);
-		else
-		    wca[i] = *(p++);
-
-	    // Rule 1: Were any chars converted to lower?
-	    p = compl_orig_text;
-	    for (i = 0; i < min_len; ++i)
-	    {
-		if (has_mbyte)
-		    c = mb_ptr2char_adv(&p);
-		else
-		    c = *(p++);
-		if (MB_ISLOWER(c))
-		{
-		    has_lower = TRUE;
-		    if (MB_ISUPPER(wca[i]))
-		    {
-			// Rule 1 is satisfied.
-			for (i = actual_compl_length; i < actual_len; ++i)
-			    wca[i] = MB_TOLOWER(wca[i]);
-			break;
-		    }
-		}
-	    }
-
-	    // Rule 2: No lower case, 2nd consecutive letter converted to
-	    // upper case.
-	    if (!has_lower)
-	    {
-		p = compl_orig_text;
-		for (i = 0; i < min_len; ++i)
-		{
-		    if (has_mbyte)
-			c = mb_ptr2char_adv(&p);
-		    else
-			c = *(p++);
-		    if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
-		    {
-			// Rule 2 is satisfied.
-			for (i = actual_compl_length; i < actual_len; ++i)
-			    wca[i] = MB_TOUPPER(wca[i]);
-			break;
-		    }
-		    was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
-		}
-	    }
-
-	    // Copy the original case of the part we typed.
-	    p = compl_orig_text;
-	    for (i = 0; i < min_len; ++i)
-	    {
-		if (has_mbyte)
-		    c = mb_ptr2char_adv(&p);
-		else
-		    c = *(p++);
-		if (MB_ISLOWER(c))
-		    wca[i] = MB_TOLOWER(wca[i]);
-		else if (MB_ISUPPER(c))
-		    wca[i] = MB_TOUPPER(wca[i]);
-	    }
-
-	    // Generate encoding specific output from wide character array.
-	    // Multi-byte characters can occupy up to five bytes more than
-	    // ASCII characters, and we also need one byte for NUL, so stay
-	    // six bytes away from the edge of IObuff.
-	    p = IObuff;
-	    i = 0;
-	    while (i < actual_len && (p - IObuff + 6) < IOSIZE)
-		if (has_mbyte)
-		    p += (*mb_char2bytes)(wca[i++], p);
-		else
-		    *(p++) = wca[i++];
-	    *p = NUL;
-
-	    vim_free(wca);
-	}
-
-	str = IObuff;
+	str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length,
+								min_len);
     }
     if (cont_s_ipos)
 	flags |= CP_CONT_S_IPOS;
-- 
1.8.3.1

