From 8c6173c7d3431dd8bc2b6ffc076ef49512a7e175 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 30 Aug 2019 22:08:34 +0200 Subject: patch 8.1.1949: cannot scroll a popup window to the very bottom Problem: Cannot scroll a popup window to the very bottom. Solution: Scroll to the bottom when the "firstline" property was set to -1. (closes #4577) Allow resetting min/max width/height. --- src/dict.c | 12 +++++++- src/popupwin.c | 37 ++++++++++++++++++------ src/proto/dict.pro | 1 + src/testdir/dumps/Test_popupwin_firstline.dump | 10 ------- src/testdir/dumps/Test_popupwin_firstline_1.dump | 10 +++++++ src/testdir/dumps/Test_popupwin_firstline_2.dump | 10 +++++++ src/testdir/dumps/Test_popupwin_scroll_10.dump | 10 +++++++ src/testdir/test_popupwin.vim | 12 ++++++-- src/version.c | 2 ++ 9 files changed, 82 insertions(+), 22 deletions(-) delete mode 100644 src/testdir/dumps/Test_popupwin_firstline.dump create mode 100644 src/testdir/dumps/Test_popupwin_firstline_1.dump create mode 100644 src/testdir/dumps/Test_popupwin_firstline_2.dump create mode 100644 src/testdir/dumps/Test_popupwin_scroll_10.dump diff --git a/src/dict.c b/src/dict.c index b2c3fbcdee..649a7da71c 100644 --- a/src/dict.c +++ b/src/dict.c @@ -616,12 +616,22 @@ dict_get_string(dict_T *d, char_u *key, int save) */ varnumber_T dict_get_number(dict_T *d, char_u *key) +{ + return dict_get_number_def(d, key, 0); +} + +/* + * Get a number item from a dictionary. + * Returns "def" if the entry doesn't exist. + */ + varnumber_T +dict_get_number_def(dict_T *d, char_u *key, int def) { dictitem_T *di; di = dict_find(d, key, -1); if (di == NULL) - return 0; + return def; return tv_get_number(&di->di_tv); } diff --git a/src/popupwin.c b/src/popupwin.c index 8d4a9f21a0..c277de29eb 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -399,13 +399,13 @@ apply_move_options(win_T *wp, dict_T *d) char_u *str; dictitem_T *di; - if ((nr = dict_get_number(d, (char_u *)"minwidth")) > 0) + if ((nr = dict_get_number_def(d, (char_u *)"minwidth", -1)) >= 0) wp->w_minwidth = nr; - if ((nr = dict_get_number(d, (char_u *)"minheight")) > 0) + if ((nr = dict_get_number_def(d, (char_u *)"minheight", -1)) >= 0) wp->w_minheight = nr; - if ((nr = dict_get_number(d, (char_u *)"maxwidth")) > 0) + if ((nr = dict_get_number_def(d, (char_u *)"maxwidth", -1)) >= 0) wp->w_maxwidth = nr; - if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0) + if ((nr = dict_get_number_def(d, (char_u *)"maxheight", -1)) >= 0) wp->w_maxheight = nr; nr = popup_options_one(d, (char_u *)"line"); @@ -609,9 +609,11 @@ apply_general_options(win_T *wp, dict_T *dict) di = dict_find(dict, (char_u *)"firstline", -1); if (di != NULL) + { wp->w_firstline = dict_get_number(dict, (char_u *)"firstline"); - if (wp->w_firstline < 0) - wp->w_firstline = 0; + if (wp->w_firstline < 0) + wp->w_firstline = -1; + } di = dict_find(dict, (char_u *)"scrollbar", -1); if (di != NULL) @@ -1146,7 +1148,7 @@ popup_adjust_position(win_T *wp) } // start at the desired first line - if (wp->w_firstline != 0) + if (wp->w_firstline > 0) wp->w_topline = wp->w_firstline; if (wp->w_topline > wp->w_buffer->b_ml.ml_line_count) wp->w_topline = wp->w_buffer->b_ml.ml_line_count; @@ -1154,9 +1156,15 @@ popup_adjust_position(win_T *wp) // Compute width based on longest text line and the 'wrap' option. // Use a minimum width of one, so that something shows when there is no // text. + // When "firstline" is -1 then start with the last buffer line and go + // backwards. // TODO: more accurate wrapping wp->w_width = 1; - for (lnum = wp->w_topline; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum) + if (wp->w_firstline < 0) + lnum = wp->w_buffer->b_ml.ml_line_count; + else + lnum = wp->w_topline; + while (lnum >= 1 && lnum <= wp->w_buffer->b_ml.ml_line_count) { int len; int w_width = wp->w_width; @@ -1206,10 +1214,21 @@ popup_adjust_position(win_T *wp) } // do not use the width of lines we're not going to show if (wp->w_maxheight > 0 - && lnum - wp->w_topline + 1 + wrapped > wp->w_maxheight) + && (wp->w_firstline >= 0 + ? lnum - wp->w_topline + : wp->w_buffer->b_ml.ml_line_count - lnum) + + 1 + wrapped > wp->w_maxheight) break; + + if (wp->w_firstline < 0) + --lnum; + else + ++lnum; } + if (wp->w_firstline < 0) + wp->w_topline = lnum > 0 ? lnum + 1 : lnum; + wp->w_has_scrollbar = wp->w_want_scrollbar && (wp->w_topline > 1 || lnum <= wp->w_buffer->b_ml.ml_line_count); if (wp->w_has_scrollbar) diff --git a/src/proto/dict.pro b/src/proto/dict.pro index 388ddac9e6..3185edc8c3 100644 --- a/src/proto/dict.pro +++ b/src/proto/dict.pro @@ -26,6 +26,7 @@ long dict_len(dict_T *d); dictitem_T *dict_find(dict_T *d, char_u *key, int len); char_u *dict_get_string(dict_T *d, char_u *key, int save); varnumber_T dict_get_number(dict_T *d, char_u *key); +varnumber_T dict_get_number_def(dict_T *d, char_u *key, int def); varnumber_T dict_get_number_check(dict_T *d, char_u *key); char_u *dict2string(typval_T *tv, int copyID, int restore_copyID); int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, int literal); diff --git a/src/testdir/dumps/Test_popupwin_firstline.dump b/src/testdir/dumps/Test_popupwin_firstline.dump deleted file mode 100644 index b3b0349305..0000000000 --- a/src/testdir/dumps/Test_popupwin_firstline.dump +++ /dev/null @@ -1,10 +0,0 @@ ->1+0&#ffffff0| @73 -|2| @73 -|3| @73 -|4| @32|3+0#0000001#ffd7ff255@4| | +0#0000000#a8a8a8255| +0&#ffffff0@33 -|5| @32|4+0#0000001#ffd7ff255@1| @3| +0#0000000#0000001| +0&#ffffff0@33 -|6| @32|5+0#0000001#ffd7ff255| @4| +0#0000000#0000001| +0&#ffffff0@33 -|7| @32|6+0#0000001#ffd7ff255@5| +0#0000000#a8a8a8255| +0&#ffffff0@33 -|8| @73 -|9| @73 -@57|1|,|1| @10|T|o|p| diff --git a/src/testdir/dumps/Test_popupwin_firstline_1.dump b/src/testdir/dumps/Test_popupwin_firstline_1.dump new file mode 100644 index 0000000000..b3b0349305 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_firstline_1.dump @@ -0,0 +1,10 @@ +>1+0&#ffffff0| @73 +|2| @73 +|3| @73 +|4| @32|3+0#0000001#ffd7ff255@4| | +0#0000000#a8a8a8255| +0&#ffffff0@33 +|5| @32|4+0#0000001#ffd7ff255@1| @3| +0#0000000#0000001| +0&#ffffff0@33 +|6| @32|5+0#0000001#ffd7ff255| @4| +0#0000000#0000001| +0&#ffffff0@33 +|7| @32|6+0#0000001#ffd7ff255@5| +0#0000000#a8a8a8255| +0&#ffffff0@33 +|8| @73 +|9| @73 +@57|1|,|1| @10|T|o|p| diff --git a/src/testdir/dumps/Test_popupwin_firstline_2.dump b/src/testdir/dumps/Test_popupwin_firstline_2.dump new file mode 100644 index 0000000000..6b95fb5921 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_firstline_2.dump @@ -0,0 +1,10 @@ +>1+0&#ffffff0| @73 +|2| @73 +|3| @73 +|4| @27|6+0#0000001#ffd7ff255@5| @9| +0#0000000#a8a8a8255| +0&#ffffff0@28 +|5| @27|7+0#0000001#ffd7ff255@4| @10| +0#0000000#a8a8a8255| +0&#ffffff0@28 +|6| @27|8+0#0000001#ffd7ff255@2| @12| +0#0000000#0000001| +0&#ffffff0@28 +|7| @27|9+0#0000001#ffd7ff255@15| +0#0000000#0000001| +0&#ffffff0@28 +|8| @73 +|9| @73 +|:| @55|1|,|1| @10|T|o|p| diff --git a/src/testdir/dumps/Test_popupwin_scroll_10.dump b/src/testdir/dumps/Test_popupwin_scroll_10.dump new file mode 100644 index 0000000000..d469fd7773 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_scroll_10.dump @@ -0,0 +1,10 @@ +>1+0&#ffffff0| @73 +|2| @31|╔+0#0000001#ffd7ff255|═@5|X| +0#0000000#ffffff0@33 +|3| @31|║+0#0000001#ffd7ff255|f|i|v|e| | +0#0000000#ff404010|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@33 +|4| @31|║+0#0000001#ffd7ff255|s|i|x| @1| +0#0000000#ff404010|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@33 +|5| @31|║+0#0000001#ffd7ff255|s|e|v|e|n| +0#0000000#4040ff13|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@33 +|6| @31|║+0#0000001#ffd7ff255|e|i|g|h|t| +0#0000000#4040ff13|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@33 +|7| @31|║+0#0000001#ffd7ff255|n|i|n|e| | +0#0000000#4040ff13|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@33 +|8| @31|╚+0#0000001#ffd7ff255|═@5|╝| +0#0000000#ffffff0@33 +|9| @73 +|:|c|a|l@1| |p|o|p|u|p|_|s|e|t|o|p|t|i|o|n|s|(|w|i|n|i|d|,| |#|{|m|a|x|h|e|i|g|h|t|:| |0|,| |m|i|n|w|i|d|t|h|:| |0|1|,|1| @10|T|o|p| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index d7130863c5..123d12aa77 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -313,14 +313,18 @@ func Test_popup_firstline() let lines =<< trim END call setline(1, range(1, 20)) - call popup_create(['1111', '222222', '33333', '44', '5', '666666', '77777', '888', '9999999999999999'], #{ + let winid = popup_create(['1111', '222222', '33333', '44', '5', '666666', '77777', '888', '9999999999999999'], #{ \ maxheight: 4, \ firstline: 3, \ }) END call writefile(lines, 'XtestPopupFirstline') let buf = RunVimInTerminal('-S XtestPopupFirstline', #{rows: 10}) - call VerifyScreenDump(buf, 'Test_popupwin_firstline', {}) + call VerifyScreenDump(buf, 'Test_popupwin_firstline_1', {}) + + call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: -1})\") + call term_sendkeys(buf, ":\") + call VerifyScreenDump(buf, 'Test_popupwin_firstline_2', {}) " clean up call StopVimInTerminal(buf) @@ -1729,6 +1733,10 @@ func Test_popup_scrollbar() call term_sendkeys(buf, ":call ClickBot()\") call VerifyScreenDump(buf, 'Test_popupwin_scroll_9', {}) + " remove the minwidth and maxheight + call term_sendkeys(buf, ":call popup_setoptions(winid, #{maxheight: 0, minwidth: 0})\") + call VerifyScreenDump(buf, 'Test_popupwin_scroll_10', {}) + " clean up call StopVimInTerminal(buf) call delete('XtestPopupScroll') diff --git a/src/version.c b/src/version.c index f9e0f7b5f0..c406005081 100644 --- a/src/version.c +++ b/src/version.c @@ -761,6 +761,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1949, /**/ 1948, /**/ -- cgit v1.2.3