]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1650: popup: window may not properly resize v9.1.1650
authorglepnir <glephunter@gmail.com>
Mon, 18 Aug 2025 19:14:48 +0000 (21:14 +0200)
committerChristian Brabandt <cb@256bit.org>
Mon, 18 Aug 2025 19:16:42 +0000 (21:16 +0200)
Problem:  After scrolling a popup and then using popup_settext() with
          fewer lines, the popup fails to resize properly because
          firstline points beyond the new buffer content (lifepillar)
Solution: In popup_adjust_position(), validate that firstline doesn't
          exceed buffer line count and reset to 0 (auto-position) if it
          does (glepnir)

fixes: #14745
closes: #18031

Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/popupwin.c
src/testdir/dumps/Test_popupwin_first_after_scroll.dump [new file with mode: 0644]
src/testdir/test_popupwin.vim
src/version.c

index 7b1237c5f59b471330a807f54ee58968d4b94e93..2f956a3adb360607254b44a38ac27630d4f668a1 100644 (file)
@@ -1403,7 +1403,15 @@ popup_adjust_position(win_T *wp)
 
     // start at the desired first line
     if (wp->w_firstline > 0)
-       wp->w_topline = wp->w_firstline;
+    {
+       // If firstline is beyond the buffer content, reset it to auto-position.
+       // This can happen when the popup was scrolled and then the buffer
+       // content was changed to have fewer lines.
+       if (wp->w_firstline > wp->w_buffer->b_ml.ml_line_count)
+           wp->w_firstline = 0;
+       else
+           wp->w_topline = wp->w_firstline;
+    }
     if (wp->w_topline < 1)
        wp->w_topline = 1;
     else if (wp->w_topline > wp->w_buffer->b_ml.ml_line_count)
diff --git a/src/testdir/dumps/Test_popupwin_first_after_scroll.dump b/src/testdir/dumps/Test_popupwin_first_after_scroll.dump
new file mode 100644 (file)
index 0000000..74591df
--- /dev/null
@@ -0,0 +1,20 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~|╔+0#0000001#ffd7ff255|═@69|╗| +0#4040ff13#ffffff0@1
+|~|║+0#0000001#ffd7ff255|a| @68|║| +0#4040ff13#ffffff0@1
+|~|║+0#0000001#ffd7ff255|b| @68|║| +0#4040ff13#ffffff0@1
+|~|║+0#0000001#ffd7ff255|c| @68|║| +0#4040ff13#ffffff0@1
+|~|╚+0#0000001#ffd7ff255|═@69|╝| +0#4040ff13#ffffff0@1
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|1|0@1|1|,| |[|'|a|'|,| |'|b|'|,| |'|c|'|]|)| @14|0|,|0|-|1| @8|A|l@1| 
index ab99e5d7c52dac691a15303d1f111819490fdd67..ed903bdbb3c75461d290d43643f0d5fdaacbeb10 100644 (file)
@@ -4533,4 +4533,41 @@ func Test_popupwin_closing_buffer()
   %bd!
 endfunc
 
+func Test_popupwin_firstline_after_scroll()
+  CheckScreendump
+
+  let lines =<< trim END
+    vim9script
+
+    def Popup(): number
+      return popup_create([], {
+        border: [1, 1, 1, 1],
+        close: 'click',
+        minheight: 1,
+        maxheight: 10,
+        scrollbar: true,
+        minwidth: &columns - 5,
+        maxwidth: &columns - 5,
+      })
+    enddef
+
+    var id = Popup()
+    g:popup_id = id
+    popup_settext(id, repeat(['abcd'], 20))
+  END
+  call writefile(lines, 'XtestPopupScroll_win', 'D')
+  let buf = RunVimInTerminal('-S XtestPopupScroll_win', {})
+  call TermWait(buf, 50)
+
+  call term_sendkeys(buf, ":call popup_setoptions(g:popup_id, {'firstline': 6})\<CR>")
+  call TermWait(buf, 50)
+  call term_sendkeys(buf, ":call popup_settext(g:popup_id, [])\<CR>")
+  call TermWait(buf, 50)
+  call term_sendkeys(buf, ":call popup_settext(1001, ['a', 'b', 'c'])\<CR>")
+  call TermWait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_popupwin_first_after_scroll', {})
+
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2
index 8f351ed07d41eeb74c336c29666e172aa4901ee6..a50755f53fb67bf5e7bcb9783426e92ef4248784 100644 (file)
@@ -719,6 +719,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1650,
 /**/
     1649,
 /**/