Compare commits

..

5 Commits

Author SHA1 Message Date
Hirohito Higashi
44f707da6a patch 9.2.0389: DECRQM still leaves stray "pp" on Apple Terminal.app
Problem:  DECRQM was still sent to Apple Terminal.app before its DA2
          reply was processed, leaving a literal "pp" on screen.
          may_req_decrqm() was called from vim_main2()
          right after may_req_termresponse(), at which point
          term_props[TPR_DECRQM].tpr_status was still TPR_UNKNOWN, so
          the `!= TPR_NO` guard let the request through (after v9.2.0387)
Solution: Send DECRQM from handle_version_response() once
          term_props[TPR_DECRQM].tpr_status == TPR_YES, the same
          pattern already used for t_RS (TPR_CURSOR_STYLE) and t_RC
          (TPR_CURSOR_BLINK), which deliberately wait for the DA2
          reply to avoid the same echo-on-screen issue on Apple
          Terminal.app and Gnome terminal.  Drop the now-unused
          may_req_decrqm() helper and its call site in vim_main2()
          (Hirohito Higashi).

fixes:   #19852
related: #19938
closes:  #20038

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: John Marriott <basilisk@internode.on.net>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-04-22 20:29:08 +00:00
zeertzjq
f194676c93 patch 9.2.0388: strange indent in update_topline()
Problem:  strange indent in update_topline()
Solution: Fix the indentation (zeertzjq)

closes: #20033

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-04-22 16:09:06 +00:00
Hirohito Higashi
cee8fd73eb patch 9.2.0387: DECRQM request may leave stray chars in terminal
Problem:  Sending DECRQM from handle_version_response() caused DECRPM
          responses to arrive during user input processing, leaving
          bytes in typebuf when clear_showcmd() ran.  This made
          visual-mode showcmd (e.g. "7" line count after V<C-D><C-D>)
          intermittently disappear, failing many screendump tests on CI.
Solution: Move DECRQM request out of handle_version_response() and send
          it at startup via may_req_decrqm(), following the existing
          may_req_termresponse() and may_req_bg_color() pattern.
          Add TPR_DECRQM property set per terminal from the DA2 reply,
          and route DECRQM sends through a may_req_decrqm() helper using
          the termrequest_T pattern, skipping terminals known to
          mishandle it (Foxe Chen, Hirohito Higashi).

fixes:  #19852
closes: #19938

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-04-21 21:03:25 +00:00
Yasuhiro Matsumoto
2ea4a7c3b7 patch 9.2.0386: No scroll/scrollbar support in the tabpanel
Problem:  No scroll/scrollbar support in the tabpanel
Solution: Add support for it (Yasuhiro Matsumoto)

closes: #19979

Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-04-21 20:39:22 +00:00
D. Ben Knoble
10040bc9cd runtime(sh): allow "#" in special derefs
Code like ${!#} flags the "#" as shDerefWordError [1]; the "!prefix"
syntax region delegates to one of the shDerefSpecial handlers via
@shDerefList, but it misses the "#" case as valid for ${##} and ${!#}.

[1]: https://vi.stackexchange.com/q/48617/10604

Correct that. Indirection is only valid in Bash in Ksh, so rearrange the
"!" handling to be conditional.

closes: #20016

Helped-by: Christian Brabandt <cb@256bit.org>
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-04-21 19:59:07 +00:00
24 changed files with 535 additions and 95 deletions

View File

@@ -1,4 +1,4 @@
*builtin.txt* For Vim version 9.2. Last change: 2026 Apr 20
*builtin.txt* For Vim version 9.2. Last change: 2026 Apr 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -11990,6 +11990,7 @@ terminalprops() *terminalprops()*
underline_rgb whether |t_8u| works **
mouse mouse type supported
kitty whether Kitty terminal was detected
decrqm whether sending DECRQM sequences work
** value 'u' for unknown, 'y' for yes, 'n' for no
@@ -12009,6 +12010,9 @@ terminalprops() *terminalprops()*
For "mouse" the value 'u' is unknown
If "decrqm" is 'y', then Vim will query support for the
'termsync' and 'termresize' ("inband") options.
Also see:
- 'ambiwidth' - detected by using |t_u7|.
- |v:termstyleresp| and |v:termblinkresp| for the response to

View File

@@ -1,4 +1,4 @@
*options.txt* For Vim version 9.2. Last change: 2026 Apr 20
*options.txt* For Vim version 9.2. Last change: 2026 Apr 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -9065,6 +9065,23 @@ A jump table for the options with a short description can be found at |Q_op|.
tab panel will not be displayed.
(default 20)
scroll Enable mouse wheel scrolling over the tabpanel
area when the tab list exceeds the visible
screen height. The scroll step is controlled
by 'mousescroll'. When disabled (the default),
the tabpanel shows the page containing the
current tab, with no way to view tabs outside
that page.
scrollbar Reserve a one-column scrollbar in the tabpanel
showing the current scroll position. The
scrollbar uses the |hl-PmenuSbar| and
|hl-PmenuThumb| highlight groups for the track
and thumb respectively. Clicking on the
scrollbar column jumps the thumb to that
position; the thumb can also be dragged.
Implies "scroll".
vert Use a vertical separator for tabpanel.
The vertical separator character is taken from
"tpl_vert" in 'fillchars'.

View File

@@ -1,4 +1,4 @@
*tabpage.txt* For Vim version 9.2. Last change: 2026 Feb 14
*tabpage.txt* For Vim version 9.2. Last change: 2026 Apr 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -482,6 +482,37 @@ The vertical separator character is taken from "tpl_vert" in 'fillchars'.
You can customize the appearance of the tab page labels using the highlight
groups: |hl-TabPanel| |hl-TabPanelSel| |hl-TabPanelFill|
SCROLLING IN THE TABPANEL: *tabpanel-scroll*
When the total height of the tab list exceeds the visible screen height, the
tabpanel by default displays the "page" that contains the current tab and
offers no way to view tabs outside that page.
To make the tabpanel scrollable, add "scroll" to 'tabpanelopt': >
:set tabpanelopt+=scroll
With "scroll" enabled, mouse wheel events over the tabpanel area scroll the
tab list up or down. The scroll step follows the 'mousescroll' setting.
Wheel events inside the tabpanel area are consumed by the tabpanel and do not
trigger |<ScrollWheelUp>| or |<ScrollWheelDown>| mappings.
To additionally show a vertical scrollbar indicating the current scroll
position, use "scrollbar": >
:set tabpanelopt+=scrollbar
The "scrollbar" value implies "scroll". A one-column scrollbar is reserved at
the edge of the tabpanel; clicking on the scrollbar column moves the thumb to
the click position, and the thumb can be dragged to scroll continuously.
When "vert" is combined with "scrollbar", the scrollbar is drawn next to the
vertical separator, on the panel side.
The scrollbar uses the |hl-PmenuSbar| highlight group for the track and
|hl-PmenuThumb| for the thumb.
The scroll offset is remembered across redraws but is reset when "scroll" or
"scrollbar" is toggled off and back on.
==============================================================================
6. Setting 'guitablabel' *setting-guitablabel*

View File

@@ -10889,6 +10889,7 @@ tabpagebuflist() builtin.txt /*tabpagebuflist()*
tabpagenr() builtin.txt /*tabpagenr()*
tabpagewinnr() builtin.txt /*tabpagewinnr()*
tabpanel tabpage.txt /*tabpanel*
tabpanel-scroll tabpage.txt /*tabpanel-scroll*
tag tagsrch.txt /*tag*
tag-! tagsrch.txt /*tag-!*
tag-binary-search tagsrch.txt /*tag-binary-search*

View File

@@ -52616,6 +52616,9 @@ Other ~
- Allow mouse clickable regions in the 'statusline', 'tabline' and the
'tabpanel' using the |stl-%[FuncName]| atom.
- Enable reflow support in the |:terminal|.
- Added "scroll" and "scrollbar" sub-options to 'tabpanelopt' so the
tabpanel can scroll when the tab list exceeds the visible screen
height.
Platform specific ~
-----------------

View File

@@ -24,6 +24,7 @@
" 2026 Feb 15 improve comment handling #19414
" 2026 Mar 23 improve matching of function definitions #19638
" 2026 Apr 02 improve matching of function definitions #19849
" 2026 Apr 19 improve detection of special variables #20016
" }}}
" Version: 208
" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
@@ -751,13 +752,15 @@ endif
if exists("b:is_bash")
syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOffset
syn match shDerefVar contained "{\@<=!\h\w*" nextgroup=@shDerefVarList
syn match shDerefSpecial contained "\({!\)\@<=[[:alnum:]*#@_]\+" nextgroup=@shDerefVarList,shDerefOp
endif
if (exists("b:is_kornshell") && !exists("b:is_ksh88"))
syn match shDerefVar contained "{\@<=!\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList
syn match shDerefSpecial contained "\({!\)\@<=[[:alnum:]*#@_]\+" nextgroup=@shDerefVarList,shDerefOp
endif
syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOffset,shDerefOpError
syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp
syn match shDerefSpecial contained "\({[#]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp
syn match shDerefVar contained "{\@<=\h\w*" nextgroup=@shDerefVarList
syn match shDerefVar contained '\d' nextgroup=@shDerefVarList
if exists("b:is_kornshell") || exists("b:is_posix")

View File

@@ -17,4 +17,4 @@
|:+0#0000e05&| +0#0000000&|'+0#af5f00255&|$+0#e000002&|{|V|a|r|i|a|b|l|e|B|:|-|$|{|V|a|r|i|a|b|l|e|C|:|-|e|n|g|}@1|'+0#af5f00255&| +0#0000000&@39
@75
|#+0#0000e05&| |A|n|o|t|h|e|r| |t|e|s|t| +0#0000000&@60
@57|1|8|,|0|-|1| @7|8|1|%|
@57|1|8|,|0|-|1| @7|6|5|%|

View File

@@ -1,7 +1,11 @@
|#+0#0000e05#ffffff0| |A|n|o|t|h|e|r| |t|e|s|t| +0#0000000&@60
|V+0#00e0e07&|a|r|i|a|b|l|e|=+0#0000000&|$+0#e000e06&|{|V|a|r|i|a|b|l|e|B|:+0#af5f00255&|-|$+0#e000e06&|{|V|a|r|i|a|b|l|e|C|:+0#af5f00255&|-|$+0#e000e06&|{|V|a|r|i|a|b|l|e|D|:+0#af5f00255&|-|$+0#e000e06&|{|V|a|r|i|a|b|l|e|E|:+0#af5f00255&|=|e+0#0000000&|n|g|}+0#e000e06&@3| +0#0000000&@6
@7|:+0#0000e05&| +0#0000000&@7|$+0#e000e06&|{|V|a|r|i|a|b|l|e|B|:+0#af5f00255&|=|$+0#e000e06&|{|V|a|r|i|a|b|l|e|C|:+0#af5f00255&|-|$+0#e000e06&|{|V|a|r|i|a|b|l|e|D|:+0#af5f00255&|-|$+0#e000e06&|{|V|a|r|i|a|b|l|e|E|:+0#af5f00255&|=|e+0#0000000&|n|g|}+0#e000e06&@3
> +0#0000000&@74
| +0#0000000&@74
|#+0#0000e05&| |s|p|e|c|i|a|l| |v|a|r|i|a|b|l|e|s| +0#0000000&@55
>e+0#af5f00255&|c|h|o| +0#e000002&|"+0#af5f00255&|$+0#e000e06&|{|!|#|}|"+0#af5f00255&| +0#e000002&@11|#+0#0000e05&| |l|a|s|t| |p|o|s|i|t|i|o|n|a|l| |a|r|g|u|m|e|n|t| +0#0000000&@24
|e+0#af5f00255&|c|h|o| +0#e000002&|"+0#af5f00255&|$+0#e000e06&|{|!|@|}|"+0#af5f00255&| +0#e000002&@11|#+0#0000e05&| |d|e|r|e|f| +0#0000000&@43
|e+0#af5f00255&|c|h|o| +0#e000002&|"+0#af5f00255&|$+0#e000e06&|{|#|P|A|T|H|}|"+0#af5f00255&| +0#e000002&@8|#+0#0000e05&| |l|e|n|g|t|h| +0#0000000&@42
|~+0#4040ff13&| @73
|~| @73
|~| @73
@@ -13,8 +17,4 @@
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
| +0#0000000&@56|3@1|,|0|-|1| @7|B|o|t|
| +0#0000000&@56|3|5|,|1| @9|B|o|t|

View File

@@ -14,7 +14,7 @@
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|s+0#e000002&|e|v|e|n|'+0#af5f00255&| +0#e000002&@3|;+0#e000e06&|}| +0#0000000&@48
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|e+0#e000002&|i|g|h|t|'+0#af5f00255&|;+0#e000e06&| @2|}| +0#0000000&@49
|t+0#af5f00255&|y|p|e|s|e|t| +0#e000e06&|n+0#00e0e07&|i|n|e|=+0#0000000&|$+0#e000e06&|{| |p+0#af5f00255&|w|d|;| +0#e000e06&|}| +0#0000000&@52
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|n+0#e000002&|i|n|e|'+0#af5f00255&| +0#e000002&|;+0#e000e06&| | +0#0000000&@52
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|n+0#e000002&|i|n|e|'+0#af5f00255&| +0#e000002&|;+0#e000e06&| +0#0000000&@53
| +0#e000e06&|}| +0#0000000&@72
@75
|i|s|_|b|a|s|h|:| |1|,| @45|1|,|1| @10|T|o|p|

View File

@@ -1,7 +1,7 @@
|e+0#af5f00255#ffffff0|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|s+0#e000002&|e|v|e|n|'+0#af5f00255&| +0#e000002&@3|;+0#e000e06&|}| +0#0000000&@48
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|e+0#e000002&|i|g|h|t|'+0#af5f00255&|;+0#e000e06&| @2|}| +0#0000000&@49
|t+0#af5f00255&|y|p|e|s|e|t| +0#e000e06&|n+0#00e0e07&|i|n|e|=+0#0000000&|$+0#e000e06&|{| |p+0#af5f00255&|w|d|;| +0#e000e06&|}| +0#0000000&@52
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|n+0#e000002&|i|n|e|'+0#af5f00255&| +0#e000002&|;+0#e000e06&| | +0#0000000&@52
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|n+0#e000002&|i|n|e|'+0#af5f00255&| +0#e000002&|;+0#e000e06&| +0#0000000&@53
| +0#e000e06&|}| +0#0000000&@72
> @74
|v+0#e000e06&|a|l|s|u|b|f|u|n|c|(|)| |{| +0#0000000&@60
@@ -12,9 +12,9 @@
|p+0#af5f00255&|r|i|n|t|f| +0#e000e06&|'+0#af5f00255&|%+0#e000002&|s|\|n|'+0#af5f00255&| +0#e000e06&|"+0#af5f00255&|$+0#e000e06&|{|||v|a|l|s|u|b|f|u|n|c| |t|w|e|l|v|e| @4|;|}|"+0#af5f00255&| +0#0000000&@31
|u+0#00e0e07&|n|l|u|c|k|y|=+0#0000000&|$+0#e000e06&|{||+0#af5f00255&|v+0#e000e06&|a|l|s|u|b|f|u|n|c| |t|h|i|r|t|e@1|n| +0#0000000&@44
|}+0#e000e06&| +0#0000000&@73
|t+0#af5f00255&|y|p|e|s|e|t| +0#e000e06&|n+0#00e0e07&|o|t|a|f|l|o|a|t|=+0#0000000&|$+0#e000e06&|{||+0#af5f00255&|v+0#e000e06&|a|l|s|u|b|f|u|n|c| |n|o|t|a|n|u|m|b|e|r| @5|;+0#af5f00255&| +0#e000e06&| +0#0000000&@24
|t+0#af5f00255&|y|p|e|s|e|t| +0#e000e06&|n+0#00e0e07&|o|t|a|f|l|o|a|t|=+0#0000000&|$+0#e000e06&|{||+0#af5f00255&|v+0#e000e06&|a|l|s|u|b|f|u|n|c| |n|o|t|a|n|u|m|b|e|r| @5|;+0#af5f00255&| +0#0000000&@25
| +0#e000e06&|}| +0#0000000&@72
|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|u|n|l|u|c|k|y| +0#e000002&|$+0#e000e06&|n|o|t|a|n|u|m|b|e|r| +0#0000000&@49
|$+0#e000e06&|{||+0#af5f00255&|e|c|h|o| +0#e000002&|f|o|u|r|t|e@1|n|;+0#af5f00255&|}+0#e000e06&| +0#0000000&@56
|$+0#e000e06&|{||+0#af5f00255&|e|c|h|o| +0#e000002&|f|i|f|t|e@1|n| +0#0000000&@59
@57|1|9|,|0|-|1| @7|9|2|%|
@57|1|9|,|0|-|1| @7|7|2|%|

View File

@@ -1,5 +1,9 @@
|$+0#e000e06#ffffff0|{||+0#af5f00255&|e|c|h|o| +0#e000002&|f|i|f|t|e@1|n| +0#0000000&@59
>}+0#e000e06&| +0#0000000&@73
|}+0#e000e06&| +0#0000000&@73
@75
|e+0#af5f00255&|c|h|o| +0#e000002&|"+0#af5f00255&|$+0#e000e06&|{|!|#|}|"+0#af5f00255&| +0#e000002&@11|#+0#0000e05&| |l|a|s|t| |p|o|s|i|t|i|o|n|a|l| |a|r|g|u|m|e|n|t| +0#0000000&@24
|e+0#af5f00255&|c|h|o| +0#e000002&|"+0#af5f00255&|$+0#e000e06&|{|!|@|}|"+0#af5f00255&| +0#e000002&@11|#+0#0000e05&| |d|e|r|e|f| +0#0000000&@43
>e+0#af5f00255&|c|h|o| +0#e000002&|"+0#af5f00255&|$+0#e000e06&|{|#|P|A|T|H|}|"+0#af5f00255&| +0#e000002&@8|#+0#0000e05&| |l|e|n|g|t|h| +0#0000000&@42
|~+0#4040ff13&| @73
|~| @73
|~| @73
@@ -13,8 +17,4 @@
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
| +0#0000000&@56|3@1|,|1| @9|B|o|t|
| +0#0000000&@56|3|7|,|1| @9|B|o|t|

View File

@@ -31,3 +31,7 @@ Variable="${VariableB:-${VariableC:-eng}}" # :- is ksh and bash
Variable=${VariableB:-${VariableC:-${VariableD:-${VariableE:=eng}}}}
: ${VariableB:=${VariableC:-${VariableD:-${VariableE:=eng}}}}
# special variables
echo "${!#}" # last positional argument
echo "${!@}" # deref
echo "${#PATH}" # length

View File

@@ -14,7 +14,7 @@ echo ${ echo 'six'
echo ${ echo 'seven' ;}
echo ${ echo 'eight'; }
typeset nine=${ pwd; }
echo ${ echo 'nine' ;
echo ${ echo 'nine' ;
}
valsubfunc() {
@@ -25,9 +25,13 @@ echo "${|valsubfunc eleven; }"
printf '%s\n' "${|valsubfunc twelve ;}"
unlucky=${|valsubfunc thirteen
}
typeset notafloat=${|valsubfunc notanumber ;
typeset notafloat=${|valsubfunc notanumber ;
}
echo $unlucky $notanumber
${|echo fourteen;}
${|echo fifteen
}
echo "${!#}" # last positional argument
echo "${!@}" # deref
echo "${#PATH}" # length

View File

@@ -4946,6 +4946,9 @@ build_stl_str_hl_local(
maxwid = 50;
}
}
// Keep the uncapped value for %N[FuncName] click-region IDs; the 50
// cap below applies only when minwid is used as a padding width.
int raw_minwid = minwid * l;
minwid = (minwid > 50 ? 50 : minwid) * l;
if (*s == '(')
{
@@ -5306,7 +5309,11 @@ build_stl_str_hl_local(
{
stl_items[curitem].stl_type = ClickFunc;
stl_items[curitem].stl_start = p;
stl_items[curitem].stl_minwid = minwid;
// The stl_minwid field is overloaded: it may be the
// "min" part of %<min>.<max> used for padding, or an
// identifier passed to the %N[FuncName] callback. Store
// the uncapped value so IDs above 50 are preserved.
stl_items[curitem].stl_minwid = raw_minwid;
stl_items[curitem].stl_clickfunc =
vim_strnsave(s, rb - s);
s = rb + 1;

View File

@@ -893,9 +893,6 @@ vim_main2(void)
may_req_bg_color();
# endif
// Same reason for termresponse, don't want the terminal sending out the
// DECRPM response after Vim has exited.
send_decrqm_modes();
// start in insert mode
if (p_im)

View File

@@ -240,6 +240,9 @@ do_mouse(
int in_status_line; // mouse in status line
static int in_tab_line = FALSE; // mouse clicked in tab line
static int in_tabpanel = FALSE; // mouse clicked in tabpanel
#ifdef FEAT_TABPANEL
static bool in_tabpanel_scrollbar = false; // dragging tabpanel scrollbar
#endif
int in_sep_line; // mouse in vertical separator line
int c1, c2;
#if defined(FEAT_FOLDING)
@@ -346,6 +349,9 @@ do_mouse(
got_click = TRUE;
in_tab_line = FALSE;
in_tabpanel = FALSE;
#ifdef FEAT_TABPANEL
in_tabpanel_scrollbar = false;
#endif
}
else
{
@@ -354,15 +360,31 @@ do_mouse(
if (!is_drag) // release, reset got_click
{
got_click = FALSE;
if (in_tab_line || in_tabpanel)
if (in_tab_line || in_tabpanel
#ifdef FEAT_TABPANEL
|| in_tabpanel_scrollbar
#endif
)
{
in_tab_line = FALSE;
in_tabpanel = FALSE;
#ifdef FEAT_TABPANEL
in_tabpanel_scrollbar = false;
#endif
return FALSE;
}
}
}
#ifdef FEAT_TABPANEL
// Continue a scrollbar drag before any tab-selection handling.
if (is_drag && in_tabpanel_scrollbar)
{
tabpanel_drag_scrollbar(mouse_row);
return FALSE;
}
#endif
// CTRL right mouse button does CTRL-T
if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT)
{
@@ -494,6 +516,15 @@ do_mouse(
if (mouse_col < firstwin->w_wincol
|| mouse_col >= firstwin->w_wincol + topframe->fr_width)
{
// A click on the scrollbar column starts a drag interaction and
// preempts tab-selection.
if (is_click && !is_drag && mouse_on_tabpanel_scrollbar())
{
in_tabpanel_scrollbar = TRUE;
tabpanel_drag_scrollbar(mouse_row);
return FALSE;
}
// Dispatch 'tabpanel' %[FuncName] click regions before falling through
// to tab-page selection. On drag events fall through to the normal
// tab-drag handling.
@@ -1276,6 +1307,17 @@ ins_mousescroll(int dir)
cap.oap = &oa;
cap.arg = dir;
#ifdef FEAT_TABPANEL
if (mouse_row >= 0 && mouse_col >= 0
&& (dir == MSCR_UP || dir == MSCR_DOWN)
&& mouse_on_tabpanel())
{
(void)tabpanel_scroll(dir == MSCR_UP ? 1 : -1,
mouse_vert_step > 0 ? mouse_vert_step : 3);
return;
}
#endif
switch (dir)
{
case MSCR_UP:
@@ -2409,6 +2451,17 @@ nv_mousescroll(cmdarg_T *cap)
{
win_T *old_curwin = curwin;
#ifdef FEAT_TABPANEL
if (mouse_row >= 0 && mouse_col >= 0
&& (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
&& mouse_on_tabpanel())
{
(void)tabpanel_scroll(cap->arg == MSCR_UP ? 1 : -1,
mouse_vert_step > 0 ? mouse_vert_step : 3);
return;
}
#endif
if (mouse_row >= 0 && mouse_col >= 0)
{
// Find the window at the mouse pointer coordinates.

View File

@@ -477,39 +477,40 @@ update_topline(void)
{
if (curwin->w_cursor.lnum < curwin->w_botline)
{
if (((long)curwin->w_cursor.lnum
if (((long)curwin->w_cursor.lnum
>= (long)curwin->w_botline - *so_ptr
#ifdef FEAT_FOLDING
|| hasAnyFolding(curwin)
#endif
))
{
lineoff_T loff;
// Cursor is (a few lines) above botline, check if there are
// 'scrolloff' window lines below the cursor. If not, need to
// scroll.
n = eof_pressure ? 0 : curwin->w_empty_rows;
loff.lnum = curwin->w_cursor.lnum;
#ifdef FEAT_FOLDING
// In a fold go to its last line.
(void)hasFolding(loff.lnum, NULL, &loff.lnum);
#endif
#ifdef FEAT_DIFF
loff.fill = 0;
n += curwin->w_filler_rows;
#endif
loff.height = 0;
while (loff.lnum < curwin->w_botline
#ifdef FEAT_DIFF
&& (loff.lnum + 1 < curwin->w_botline || loff.fill == 0)
#endif
)
{
n += loff.height;
if (n >= *so_ptr)
break;
botline_forw(&loff);
lineoff_T loff;
// Cursor is (a few lines) above botline, check if there
// are 'scrolloff' window lines below the cursor.
// If not, need to scroll.
n = eof_pressure ? 0 : curwin->w_empty_rows;
loff.lnum = curwin->w_cursor.lnum;
#ifdef FEAT_FOLDING
// In a fold go to its last line.
(void)hasFolding(loff.lnum, NULL, &loff.lnum);
#endif
#ifdef FEAT_DIFF
loff.fill = 0;
n += curwin->w_filler_rows;
#endif
loff.height = 0;
while (loff.lnum < curwin->w_botline
#ifdef FEAT_DIFF
&& (loff.lnum + 1 < curwin->w_botline
|| loff.fill == 0)
#endif
)
{
n += loff.height;
if (n >= *so_ptr)
break;
botline_forw(&loff);
}
if (n >= *so_ptr && !eof_pressure)
// sufficient context, no need to scroll

View File

@@ -4,4 +4,8 @@ int tabpanel_width(void);
int tabpanel_leftcol(void);
void draw_tabpanel(void);
int get_tabpagenr_on_tabpanel(void);
bool mouse_on_tabpanel(void);
bool mouse_on_tabpanel_scrollbar(void);
bool tabpanel_drag_scrollbar(int screen_row);
bool tabpanel_scroll(int dir, int count);
/* vim: set ft=c : */

View File

@@ -96,7 +96,6 @@ void swap_tcap(void);
void ansi_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx);
void cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx);
int term_replace_keycodes(char_u *ta_buf, int ta_len, int len_arg);
void send_decrqm_modes(void);
void term_disable_dec(void);
void term_set_win_resize(bool state);
void term_set_sync_output(int flags);

View File

@@ -20,6 +20,7 @@ static void do_by_tplmode(int tplmode, int col_start, int col_end,
static void tabpanel_free_click_regions(void);
static void tabpanel_append_click_regions(stl_clickrec_T *clicktab,
char_u *buf, int row, int col_start, int col_end, int tabnr);
static void draw_tabpanel_scrollbar(int screen_col);
// set pcurtab_row. don't redraw tabpanel.
#define TPLMODE_GET_CURTAB_ROW 0
@@ -31,6 +32,7 @@ static void tabpanel_append_click_regions(stl_clickrec_T *clicktab,
#define TPL_FILLCHAR ' '
#define VERT_LEN 1
#define SCROLL_LEN 1
// tpl_align's values
#define ALIGN_LEFT 0
@@ -40,7 +42,12 @@ static char_u *opt_name = (char_u *)"tabpanel";
static int opt_scope = OPT_LOCAL;
static int tpl_align = ALIGN_LEFT;
static int tpl_columns = 20;
static int tpl_is_vert = FALSE;
static bool tpl_is_vert = false;
static bool tpl_scroll = false;
static bool tpl_scrollbar = false;
static int tpl_scroll_offset = 0;
static int tpl_total_rows = 0;
static int tpl_scrollbar_col = -1; // screen column of scrollbar, -1 if none
typedef struct {
win_T *wp;
@@ -61,7 +68,9 @@ tabpanelopt_changed(void)
char_u *p;
int new_align = ALIGN_LEFT;
long new_columns = 20;
int new_is_vert = FALSE;
bool new_is_vert = false;
bool new_scroll = false;
bool new_scrollbar = false;
p = p_tplo;
while (*p != NUL)
@@ -92,7 +101,18 @@ tabpanelopt_changed(void)
else if (STRNCMP(p, "vert", 4) == 0)
{
p += 4;
new_is_vert = TRUE;
new_is_vert = true;
}
else if (STRNCMP(p, "scrollbar", 9) == 0)
{
p += 9;
new_scrollbar = true;
new_scroll = true;
}
else if (STRNCMP(p, "scroll", 6) == 0)
{
p += 6;
new_scroll = true;
}
if (*p != ',' && *p != NUL)
@@ -104,6 +124,10 @@ tabpanelopt_changed(void)
tpl_align = new_align;
tpl_columns = new_columns;
tpl_is_vert = new_is_vert;
if (tpl_scroll != new_scroll)
tpl_scroll_offset = 0;
tpl_scroll = new_scroll;
tpl_scrollbar = new_scrollbar;
shell_new_columns();
return OK;
@@ -266,39 +290,65 @@ draw_tabpanel(void)
// Reset got_int to avoid build_stl_str_hl() isn't evaluated.
got_int = FALSE;
int sb_len = tpl_scrollbar ? SCROLL_LEN : 0;
int sb_screen_col = -1;
if (tpl_is_vert)
{
if (is_right)
{
// draw main contents in tabpanel
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, VERT_LEN,
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, VERT_LEN + sb_len,
maxwidth - VERT_LEN, &curtab_row, NULL);
do_by_tplmode(TPLMODE_REDRAW, VERT_LEN, maxwidth, &curtab_row,
NULL);
do_by_tplmode(TPLMODE_REDRAW, VERT_LEN + sb_len, maxwidth,
&curtab_row, NULL);
// draw vert separator in tabpanel
for (vsrow = 0; vsrow < Rows; vsrow++)
screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
topframe->fr_width, vs_attr);
if (tpl_scrollbar)
sb_screen_col = topframe->fr_width + VERT_LEN;
}
else
{
// draw main contents in tabpanel
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth - VERT_LEN,
&curtab_row, NULL);
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - VERT_LEN,
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0,
maxwidth - VERT_LEN - sb_len, &curtab_row, NULL);
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - VERT_LEN - sb_len,
&curtab_row, NULL);
// draw vert separator in tabpanel
for (vsrow = 0; vsrow < Rows; vsrow++)
screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
maxwidth - VERT_LEN, vs_attr);
if (tpl_scrollbar)
sb_screen_col = maxwidth - VERT_LEN - SCROLL_LEN;
}
}
else
{
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth, &curtab_row, NULL);
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth, &curtab_row, NULL);
if (is_right)
{
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, sb_len, maxwidth,
&curtab_row, NULL);
do_by_tplmode(TPLMODE_REDRAW, sb_len, maxwidth, &curtab_row, NULL);
if (tpl_scrollbar)
sb_screen_col = topframe->fr_width;
}
else
{
do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth - sb_len,
&curtab_row, NULL);
do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - sb_len,
&curtab_row, NULL);
if (tpl_scrollbar)
sb_screen_col = maxwidth - SCROLL_LEN;
}
}
tpl_scrollbar_col = sb_screen_col;
if (sb_screen_col >= 0)
draw_tabpanel_scrollbar(sb_screen_col);
got_int |= saved_got_int;
// A user function may reset KeyTyped, restore it.
@@ -556,8 +606,13 @@ do_by_tplmode(
args.col_end = col_end;
if (tplmode != TPLMODE_GET_CURTAB_ROW && args.maxrow > 0)
while (args.offsetrow + args.maxrow <= *pcurtab_row)
args.offsetrow += args.maxrow;
{
if (tpl_scroll)
args.offsetrow = tpl_scroll_offset;
else
while (args.offsetrow + args.maxrow <= *pcurtab_row)
args.offsetrow += args.maxrow;
}
tp = first_tabpage;
@@ -579,8 +634,13 @@ do_by_tplmode(
if (tplmode == TPLMODE_GET_CURTAB_ROW)
{
*pcurtab_row = row;
do_unlet((char_u *)"g:actual_curtabpage", TRUE);
break;
// When scroll mode is active keep iterating so tpl_total_rows
// receives the true content height; otherwise bail out early.
if (!tpl_scroll)
{
do_unlet((char_u *)"g:actual_curtabpage", TRUE);
break;
}
}
}
else
@@ -608,7 +668,8 @@ do_by_tplmode(
stl_hlrec_T *tabtab;
stl_clickrec_T *clicktab = NULL;
if (args.maxrow <= row - args.offsetrow)
if (tplmode != TPLMODE_GET_CURTAB_ROW
&& args.maxrow <= row - args.offsetrow)
break;
buf[0] = NUL;
@@ -677,6 +738,142 @@ do_by_tplmode(
// fill the area of TabPanelFill.
screen_fill_tailing_area(tplmode, MAX(row - args.offsetrow, 0), args.maxrow,
args.col_start, args.col_end, attr_tplf);
// Capture the true content height during the GET_CURTAB_ROW pass, which
// ignores maxrow and therefore walks every tab. REDRAW stops at the
// visible edge so its "row" is clamped and unusable here.
if (tplmode == TPLMODE_GET_CURTAB_ROW && tpl_scroll)
tpl_total_rows = row;
}
/*
* Draw the tabpanel scrollbar (track + thumb) at screen column 'screen_col'.
* The scrollbar spans the full screen height. The thumb position and size
* are derived from tpl_scroll_offset, tpl_total_rows and Rows.
*/
static void
draw_tabpanel_scrollbar(int screen_col)
{
int attr_sb = HL_ATTR(HLF_PSB);
int attr_thumb = HL_ATTR(HLF_PST);
int thumb_top = 0;
int thumb_height = 0;
if (tpl_total_rows > Rows && Rows > 0)
{
thumb_height = Rows * Rows / tpl_total_rows;
if (thumb_height < 1)
thumb_height = 1;
thumb_top = Rows * tpl_scroll_offset / tpl_total_rows;
if (thumb_top + thumb_height > Rows)
thumb_top = Rows - thumb_height;
if (thumb_top < 0)
thumb_top = 0;
}
for (int r = 0; r < Rows; r++)
{
bool on_thumb = thumb_height > 0
&& r >= thumb_top && r < thumb_top + thumb_height;
screen_putchar(TPL_FILLCHAR, r, screen_col,
on_thumb ? attr_thumb : attr_sb);
}
}
/*
* Return true if the mouse is currently positioned over the tabpanel area.
*/
bool
mouse_on_tabpanel(void)
{
if (tabpanel_width() == 0)
return false;
return mouse_col < firstwin->w_wincol
|| mouse_col >= firstwin->w_wincol + topframe->fr_width;
}
/*
* Return true if the mouse is currently on the scrollbar column.
* The scrollbar column is tracked by draw_tabpanel() and is -1 when the
* scrollbar is not enabled or not yet drawn.
*/
bool
mouse_on_tabpanel_scrollbar(void)
{
return tpl_scrollbar && tpl_scrollbar_col >= 0
&& mouse_col == tpl_scrollbar_col;
}
/*
* Move the scrollbar thumb so it is vertically centred on screen row
* 'screen_row', updating tpl_scroll_offset accordingly. Used for both
* initial clicks and subsequent drag events.
* Returns true if the event was consumed (offset changed or not).
*/
bool
tabpanel_drag_scrollbar(int screen_row)
{
int thumb_height;
int max_offset;
int track_range;
int thumb_top;
int new_offset;
if (!tpl_scrollbar || Rows <= 0 || tpl_total_rows <= Rows)
return false;
thumb_height = Rows * Rows / tpl_total_rows;
if (thumb_height < 1)
thumb_height = 1;
track_range = Rows - thumb_height;
if (track_range <= 0)
return true;
max_offset = tpl_total_rows - Rows;
thumb_top = screen_row - thumb_height / 2;
if (thumb_top < 0)
thumb_top = 0;
if (thumb_top > track_range)
thumb_top = track_range;
new_offset = thumb_top * max_offset / track_range;
if (new_offset != tpl_scroll_offset)
{
tpl_scroll_offset = new_offset;
redraw_tabpanel = TRUE;
}
return true;
}
/*
* Scroll the tabpanel by 'count' rows in direction 'dir' (1 = down, -1 = up).
* Returns true if the offset changed and a redraw was scheduled.
* Has no effect unless 'tabpanelopt' contains "scroll".
*/
bool
tabpanel_scroll(int dir, int count)
{
int max_offset;
int new_offset;
if (!tpl_scroll || tabpanel_width() == 0)
return false;
max_offset = tpl_total_rows - Rows;
if (max_offset < 0)
max_offset = 0;
new_offset = tpl_scroll_offset + (dir > 0 ? count : -count);
if (new_offset < 0)
new_offset = 0;
if (new_offset > max_offset)
new_offset = max_offset;
if (new_offset == tpl_scroll_offset)
return false;
tpl_scroll_offset = new_offset;
redraw_tabpanel = TRUE;
return true;
}
#endif // FEAT_TABPANEL

View File

@@ -154,6 +154,9 @@ static termrequest_T rcs_status = TERMREQUEST_INIT;
// Request window's position report:
static termrequest_T winpos_status = TERMREQUEST_INIT;
// Request DECRQM (DEC mode) report:
static termrequest_T decrqm_status = TERMREQUEST_INIT;
static termrequest_T *all_termrequests[] = {
&crv_status,
&u7_status,
@@ -165,6 +168,7 @@ static termrequest_T *all_termrequests[] = {
&rbm_status,
&rcs_status,
&winpos_status,
&decrqm_status,
NULL
};
@@ -686,15 +690,17 @@ static tcap_entry_T builtin_sync_output[] = {
};
#endif
#ifdef FEAT_TERMRESPONSE
/*
* List of DECRQM modes that Vim supports
*/
static const int dec_modes[] = {
2026, // Synchronized output
#ifdef UNIX
# ifdef UNIX
2048 // In-band terminal resize events
#endif
# endif
};
#endif
#ifdef FEAT_TERMGUICOLORS
/*
@@ -1539,8 +1545,10 @@ typedef struct {
#define TPR_MOUSE 3
// term response indicates kitty
#define TPR_KITTY 4
// can send DECRQM requests to terminal
#define TPR_DECRQM 5
// table size
#define TPR_COUNT 5
#define TPR_COUNT 6
static termprop_T term_props[TPR_COUNT];
@@ -1564,6 +1572,8 @@ init_term_props(int all)
term_props[TPR_MOUSE].tpr_set_by_termresponse = TRUE;
term_props[TPR_KITTY].tpr_name = "kitty";
term_props[TPR_KITTY].tpr_set_by_termresponse = FALSE;
term_props[TPR_DECRQM].tpr_name = "decrqm";
term_props[TPR_DECRQM].tpr_set_by_termresponse = TRUE;
for (i = 0; i < TPR_COUNT; ++i)
if (all || term_props[i].tpr_set_by_termresponse)
@@ -5172,21 +5182,27 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
may_adjust_color_count(256);
// Libvterm can handle SGR mouse reporting.
term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
term_props[TPR_DECRQM].tpr_status = TPR_YES;
}
if (version == 95)
{
// Mac Terminal.app sends 1;95;0
//
// Terminal.app doesn't seem to handle DECRQM sequences
// properly, see issue #19852.
if (arg[0] == 1 && arg[2] == 0)
{
term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
term_props[TPR_DECRQM].tpr_status = TPR_NO;
}
// iTerm2 sends 0;95;0
else if (arg[0] == 0 && arg[2] == 0)
{
// iTerm2 can do SGR mouse reporting
term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
term_props[TPR_DECRQM].tpr_status = TPR_YES;
}
// old iTerm2 sends 0;95;
else if (arg[0] == 0 && arg[2] == -1)
@@ -5212,6 +5228,7 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
else if (version >= 95)
term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_XTERM2;
term_props[TPR_DECRQM].tpr_status = TPR_YES;
}
// Detect terminals that set $TERM to something like
@@ -5224,11 +5241,15 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
// Assuming any version number over 2500 is not an
// xterm (without the limit for rxvt and screen).
if (arg[1] >= 2500)
{
term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
term_props[TPR_DECRQM].tpr_status = TPR_YES;
}
else if (version == 136 && arg[2] == 0)
{
term_props[TPR_UNDERLINE_RGB].tpr_status = TPR_YES;
term_props[TPR_DECRQM].tpr_status = TPR_YES;
// PuTTY sends 0;136;0
if (arg[0] == 0)
@@ -5252,6 +5273,7 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
// Kitty can handle SGR mouse reporting.
term_props[TPR_MOUSE].tpr_status = TPR_MOUSE_SGR;
term_props[TPR_DECRQM].tpr_status = TPR_YES;
}
// GNU screen sends 83;30600;0, 83;40500;0, etc.
@@ -5262,6 +5284,9 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
{
term_props[TPR_CURSOR_STYLE].tpr_status = TPR_NO;
term_props[TPR_CURSOR_BLINK].tpr_status = TPR_NO;
term_props[TPR_DECRQM].tpr_status = TPR_NO; // screen doesn't seem
// to handle DECRQM
// sequences
}
// Xterm first responded to this request at patch level
@@ -5345,6 +5370,23 @@ handle_version_response(int first, int *arg, int argc, char_u *tp)
need_flush = TRUE;
}
// Only request DEC modes via DECRQM when the terminal is known to
// handle it. Not for Apple Terminal.app or GNU screen, they echo
// the trailing "p" to the screen. See issue #19852.
if (decrqm_status.tr_progress == STATUS_GET
&& term_props[TPR_DECRQM].tpr_status == TPR_YES)
{
MAY_WANT_TO_LOG_THIS;
LOG_TR1("Sending DECRQM requests");
for (int i = 0; i < (int)ARRAY_LENGTH(dec_modes); i++)
{
vim_snprintf((char *)IObuff, IOSIZE, "\033[?%d$p", dec_modes[i]);
out_str(IObuff);
}
termrequest_sent(&decrqm_status);
need_flush = TRUE;
}
if (need_flush)
out_flush();
#endif
@@ -5753,6 +5795,13 @@ handle_csi(
key_name[0] = (int)KS_EXTRA;
key_name[1] = (int)KE_IGNORE;
#ifdef FEAT_TERMRESPONSE
// Mark the DECRQM request as answered so it is not sent again and
// stoptermcap() does not wait for it.
if (decrqm_status.tr_progress == STATUS_SENT)
decrqm_status.tr_progress = STATUS_GOT;
#endif
if (setting >= 0 && setting <= 4)
{
LOG_TRN("Received DECRPM mode %d: %s", arg[0], tp);
@@ -7987,24 +8036,6 @@ term_replace_keycodes(char_u *ta_buf, int ta_len, int len_arg)
return len;
}
/*
* Query the settings for the DEC modes we support
*/
void
send_decrqm_modes(void)
{
if (termcap_active && cur_tmode == TMODE_RAW)
{
// Request setting of relevant DEC modes via DECRQM
for (int i = 0; i < (int)ARRAY_LENGTH(dec_modes); i++)
{
vim_snprintf((char *)IObuff, IOSIZE, "\033[?%d$p", dec_modes[i]);
out_str(IObuff);
}
out_flush();
}
}
/*
* Should be called when cleaning up terminal state.
*/

View File

@@ -962,8 +962,68 @@ func Test_tabpanel_large_columns()
call assert_fails(':set tabpanelopt=columns:-1', 'E474:')
endfunc
func Test_tabpanel_scrollopt_accepted()
" 'scroll' / 'scrollbar' must be accepted in 'tabpanelopt'.
set tabpanelopt=scroll
call assert_equal('scroll', &tabpanelopt)
set tabpanelopt=scrollbar
call assert_equal('scrollbar', &tabpanelopt)
" Combination with other values.
set tabpanelopt=align:right,scroll
call assert_equal('align:right,scroll', &tabpanelopt)
set tabpanelopt=columns:15,vert,scrollbar
call assert_equal('columns:15,vert,scrollbar', &tabpanelopt)
set tabpanelopt=align:right,columns:12,vert,scrollbar
call assert_equal('align:right,columns:12,vert,scrollbar', &tabpanelopt)
" Unknown values must still fail.
call assert_fails(':set tabpanelopt=scrol', 'E474:')
call assert_fails(':set tabpanelopt=scrollbarx', 'E474:')
call s:reset()
endfunc
func Test_tabpanel_scroll_many_tabs()
let save_lines = &lines
let save_showtabpanel = &showtabpanel
let save_tabpanelopt = &tabpanelopt
" Make the screen short so the tab list exceeds the visible height.
set lines=8
set showtabpanel=2
set tabpanelopt=scroll
for i in range(20)
tabnew
endfor
" Should not crash with many tabs and scroll enabled.
redraw!
" Switching to scrollbar resets the offset but must also not crash.
set tabpanelopt=scrollbar
redraw!
" Disabling scroll returns to normal behavior.
set tabpanelopt=
redraw!
" Right alignment with scrollbar.
set tabpanelopt=align:right,scrollbar
redraw!
" Vertical separator with scrollbar.
set tabpanelopt=columns:10,vert,scrollbar
redraw!
" Cleanup.
%bwipeout!
let &tabpanelopt = save_tabpanelopt
let &showtabpanel = save_showtabpanel
let &lines = save_lines
endfunc
func Test_tabpanel_variable_height()
CheckFeature tabpanel
let save_lines = &lines
let save_showtabpanel = &showtabpanel

View File

@@ -359,7 +359,7 @@ func Test_term_mouse_middle_click_insert_mode()
let &term = save_term
let &ttymouse = save_ttymouse
call test_override('no_query_mouse', 0)
close!
bw!
endfunc
" Test for switching window using mouse in insert mode
@@ -1720,6 +1720,7 @@ func Test_xx01_term_style_response()
\ underline_rgb: 'u',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
set t_RV=
@@ -1755,6 +1756,7 @@ func Test_xx02_iTerm2_response()
\ underline_rgb: 'u',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
set t_RV=
@@ -1775,6 +1777,7 @@ func Run_libvterm_konsole_response(code)
\ underline_rgb: 'u',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
endfunc
@@ -1818,6 +1821,7 @@ func Test_xx04_Mac_Terminal_response()
\ underline_rgb: 'y',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'n'
\ }, terminalprops())
call assert_equal("\<Esc>[58;2;%lu;%lu;%lum", &t_8u)
@@ -1849,6 +1853,7 @@ func Test_xx05_mintty_response()
\ underline_rgb: 'y',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
set t_RV=
@@ -1885,6 +1890,7 @@ func Test_xx06_screen_response()
\ underline_rgb: 'y',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'n'
\ }, terminalprops())
set t_RV=
@@ -1910,6 +1916,7 @@ func Do_check_t_8u_set_reset(set_by_user)
\ underline_rgb: 'u',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
call assert_equal(a:set_by_user ? default_value : '', &t_8u)
endfunc
@@ -1949,6 +1956,7 @@ func Test_xx07_xterm_response()
\ underline_rgb: 'y',
\ mouse: 'u',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
" xterm >= 95 < 277 "xterm2"
@@ -1965,6 +1973,7 @@ func Test_xx07_xterm_response()
\ underline_rgb: 'u',
\ mouse: '2',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
" xterm >= 277: "sgr"
@@ -1981,6 +1990,7 @@ func Test_xx07_xterm_response()
\ underline_rgb: 'u',
\ mouse: 's',
\ kitty: 'u',
\ decrqm: 'y'
\ }, terminalprops())
" xterm >= 279: "sgr" and cursor_style not reset; also check t_8u reset,
@@ -2010,6 +2020,7 @@ func Test_xx08_kitty_response()
\ underline_rgb: 'y',
\ mouse: 's',
\ kitty: 'y',
\ decrqm: 'y'
\ }, terminalprops())
call feedkeys("\<Esc>[?1u") " simulate the kitty keyboard protocol is enabled
@@ -3055,6 +3066,11 @@ func Test_term_win_resize()
let buf = RunVimInTerminal('-S XTestWinResize', #{rows: 15, cols: 20})
" Must add a delay, since status report is sent internally by vim only when
" version response is received, which may come after we send the status report
" here.
sleep 100m
" Send status report
call term_sendkeys(buf, "\<Esc>[?2048;1$y")
call TermWait(buf)

View File

@@ -729,6 +729,14 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
389,
/**/
388,
/**/
387,
/**/
386,
/**/
385,
/**/