patch 9.1.1435: completion: various flaws in fuzzy completion

Problem:  completion: various flaws in fuzzy completion
Solution: fix the issues (Girish Palya)

- Remove the brittle `qsort()` on `compl_match_array`.
- Add a stable, non-recursive `mergesort` for the internal doubly
  linked list of matches.
- The sort now happens directly on the internal representation (`compl_T`),
  preserving sync with external structures and making sorting stable.
- Update fuzzy match logic to enforce `max_matches` limits after
  sorting.
- Remove `trim_compl_match_array()`, which is no longer necessary.
- Fixe test failures by correctly setting `selected` index and
  maintaining match consistency.
- Introduce `mergesort_list()` in `misc2.c`, which operates generically
  over doubly linked lists.
- Remove `pum_score` and `pum_idx` variables

fixes: #17387
closes: #17430

Signed-off-by: Girish Palya <girishji@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 7d67e9f..fcd2e6c 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -3466,7 +3466,7 @@
   set cot+=noinsert
   call feedkeys("i\<C-R>=CompAnother()\<CR>f", 'tx')
   call assert_equal("for", g:abbr)
-  call assert_equal(2, g:selected)
+  call assert_equal(0, g:selected)
 
   set cot=menu,menuone,noselect,fuzzy
   call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>\<C-N>\<C-N>", 'tx')
@@ -3703,7 +3703,7 @@
   call assert_equal('hello', getline('.'))
 
   " continue search for new leader after insert common prefix
-  exe "normal ohellokate\<CR>h\<C-X>\<C-N>k\<C-y>\<esc>"
+  exe "normal ohellokate\<CR>h\<C-X>\<C-N>k\<C-N>\<C-y>\<esc>"
   call assert_equal('hellokate', getline('.'))
 
   bw!
@@ -4110,6 +4110,12 @@
   set cpt=.^1,w
   exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>"
   call assert_equal('f{''matches'': [''fo''], ''selected'': -1}', getline(5))
+  " With non-matching items
+  %d
+  call setline(1, ["free", "freebar", "foo", "fobarbaz"])
+  set cpt=.^2,w
+  exe "normal! Gofo\<c-n>\<c-r>=PrintMenuWords()\<cr>"
+  call assert_equal('fo{''matches'': [''foo'', ''fobarbaz''], ''selected'': -1}', getline(5))
   set cot&
 
   func ComplFunc(findstart, base)
@@ -4199,16 +4205,21 @@
   bw!
 
   " Test 'fuzzy' with max_items
-  " XXX: Cannot use complete_info() since it is broken for 'fuzzy'
   new
   set completeopt=menu,noselect,fuzzy
   set complete=.
   call setline(1, ["abcd", "abac", "abdc"])
-  execute "normal Goa\<c-n>c\<c-n>"
+  exe "normal! Goa\<c-n>c\<c-r>=PrintMenuWords()\<cr>"
+  call assert_equal('ac{''matches'': [''abac'', ''abcd'', ''abdc''], ''selected'': -1}', getline(4))
+  exe "normal! Sa\<c-n>c\<c-n>\<c-n>\<c-p>\<c-r>=PrintMenuWords()\<cr>"
+  call assert_equal('abac{''matches'': [''abac'', ''abcd'', ''abdc''], ''selected'': 0}', getline(4))
+  execute "normal Sa\<c-n>c\<c-n>"
   call assert_equal('abac', getline(4))
   execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>"
   call assert_equal('abac', getline(4))
   set complete=.^1
+  exe "normal! Sa\<c-n>c\<c-n>\<c-n>\<c-p>\<c-r>=PrintMenuWords()\<cr>"
+  call assert_equal('abac{''matches'': [''abac''], ''selected'': 0}', getline(4))
   execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>"
   call assert_equal('abac', getline(4))
   set complete=.^2