patch 8.2.4465: fuzzy completion does not order matches properly

Problem:    Fuzzy completion does not order matches properly.
Solution:   Do not use regular expression match. (Yegappan Lakshmanan,
            closes #9843)
diff --git a/src/cmdexpand.c b/src/cmdexpand.c
index 909706d..94781f8 100644
--- a/src/cmdexpand.c
+++ b/src/cmdexpand.c
@@ -2633,6 +2633,7 @@
     int			score = 0;
     int		fuzzy = (fuzzystr != NULL);
     int		funcsort = FALSE;
+    int		match;
 
     // do this loop twice:
     // round == 0: count the number of matching names
@@ -2647,44 +2648,52 @@
 	    if (*str == NUL)	    // skip empty strings
 		continue;
 
-	    if (vim_regexec(regmatch, str, (colnr_T)0) ||
-		    (fuzzy && ((score = fuzzy_match_str(str, fuzzystr)) != 0)))
+	    if (!fuzzy)
+	       match = vim_regexec(regmatch, str, (colnr_T)0);
+	    else
 	    {
-		if (round)
-		{
-		    if (escaped)
-			str = vim_strsave_escaped(str, (char_u *)" \t\\.");
-		    else
-			str = vim_strsave(str);
-		    if (str == NULL)
-		    {
-			FreeWild(count, *matches);
-			if (fuzzy)
-			    fuzmatch_str_free(fuzmatch, count);
-			*numMatches = 0;
-			*matches = NULL;
-			return FAIL;
-		    }
-		    if (fuzzy)
-		    {
-			fuzmatch[count].idx = count;
-			fuzmatch[count].str = str;
-			fuzmatch[count].score = score;
-		    }
-		    else
-			(*matches)[count] = str;
-# ifdef FEAT_MENU
-		    if (func == get_menu_names && str != NULL)
-		    {
-			// test for separator added by get_menu_names()
-			str += STRLEN(str) - 1;
-			if (*str == '\001')
-			    *str = '.';
-		    }
-# endif
-		}
-		++count;
+		score = fuzzy_match_str(str, fuzzystr);
+		match = (score != 0);
 	    }
+
+	    if (!match)
+		continue;
+
+	    if (round)
+	    {
+		if (escaped)
+		    str = vim_strsave_escaped(str, (char_u *)" \t\\.");
+		else
+		    str = vim_strsave(str);
+		if (str == NULL)
+		{
+		    if (fuzzy)
+			fuzmatch_str_free(fuzmatch, count);
+		    else if (count > 0)
+			FreeWild(count, *matches);
+		    *numMatches = 0;
+		    *matches = NULL;
+		    return FAIL;
+		}
+		if (fuzzy)
+		{
+		    fuzmatch[count].idx = count;
+		    fuzmatch[count].str = str;
+		    fuzmatch[count].score = score;
+		}
+		else
+		    (*matches)[count] = str;
+# ifdef FEAT_MENU
+		if (func == get_menu_names && str != NULL)
+		{
+		    // test for separator added by get_menu_names()
+		    str += STRLEN(str) - 1;
+		    if (*str == '\001')
+			*str = '.';
+		}
+# endif
+	    }
+	    ++count;
 	}
 	if (round == 0)
 	{
diff --git a/src/search.c b/src/search.c
index 00a9fdf..063058d 100644
--- a/src/search.c
+++ b/src/search.c
@@ -5001,7 +5001,7 @@
 fuzzy_match_str(char_u *str, char_u *pat)
 {
     int		score = 0;
-    int_u	matchpos[256];
+    int_u	matchpos[MAX_FUZZY_MATCHES];
 
     if (str == NULL || pat == NULL)
 	return 0;
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 1ee0d71..73d39e3 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -2757,6 +2757,25 @@
   call feedkeys(":let SVar\<Tab>\<C-B>\"\<CR>", 'tx')
   call assert_equal('"let SomeVariable', @:)
 
+  " Test for sorting the results by the best match
+  %bw!
+  command T123format :
+  command T123goformat :
+  command T123TestFOrmat :
+  command T123fendoff :
+  command T123state :
+  command T123FendingOff :
+  set wildoptions=fuzzy
+  call feedkeys(":T123fo\<C-A>\<C-B>\"\<CR>", 'tx')
+  call assert_equal('"T123format T123TestFOrmat T123FendingOff T123goformat T123fendoff', @:)
+  delcommand T123format
+  delcommand T123goformat
+  delcommand T123TestFOrmat
+  delcommand T123fendoff
+  delcommand T123state
+  delcommand T123FendingOff
+  %bw
+
   set wildoptions&
   %bw!
 endfunc
diff --git a/src/version.c b/src/version.c
index 69be8cd..94479e3 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4465,
+/**/
     4464,
 /**/
     4463,