mirror of
https://github.com/vim/vim
synced 2025-07-30 02:11:39 +00:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
3bfd04e672 | |||
2fd8e35e16 | |||
8caaf82569 | |||
bf0eff0b72 | |||
2d247849ce | |||
c47ed44be7 | |||
815b76bff6 | |||
3a97bb3f0f | |||
7dd64a3e57 | |||
c28cb5b16d | |||
5d508dd39e | |||
1ab74a5af3 | |||
eea1699836 | |||
ccd6e3471d | |||
c6896e20f8 | |||
402502d0e4 | |||
ac1f1bc222 | |||
cc31ad9f9b | |||
54fabd4b5e | |||
b42301247d | |||
89adc3a137 |
@ -1,4 +1,4 @@
|
||||
*eval.txt* For Vim version 8.1. Last change: 2019 May 25
|
||||
*eval.txt* For Vim version 8.1. Last change: 2019 May 30
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -2087,12 +2087,12 @@ v:t_blob Value of |Blob| type. Read-only. See: |type()|
|
||||
*v:termresponse* *termresponse-variable*
|
||||
v:termresponse The escape sequence returned by the terminal for the |t_RV|
|
||||
termcap entry. It is set when Vim receives an escape sequence
|
||||
that starts with ESC [ or CSI and ends in a 'c', with only
|
||||
digits, ';' and '.' in between.
|
||||
that starts with ESC [ or CSI, then '>' or '?' and ends in a
|
||||
'c', with only digits and ';' in between.
|
||||
When this option is set, the TermResponse autocommand event is
|
||||
fired, so that you can react to the response from the
|
||||
terminal.
|
||||
The response from a new xterm is: "<Esc>[ Pp ; Pv ; Pc c". Pp
|
||||
The response from a new xterm is: "<Esc>[> Pp ; Pv ; Pc c". Pp
|
||||
is the terminal type: 0 for vt100 and 1 for vt220. Pv is the
|
||||
patch level (since this was introduced in patch 95, it's
|
||||
always 95 or bigger). Pc is always zero.
|
||||
@ -8400,6 +8400,8 @@ setreg({regname}, {value} [, {options}])
|
||||
settabvar({tabnr}, {varname}, {val}) *settabvar()*
|
||||
Set tab-local variable {varname} to {val} in tab page {tabnr}.
|
||||
|t:var|
|
||||
Note that autocommands are blocked, side effects may not be
|
||||
triggered, e.g. when setting 'filetype'.
|
||||
Note that the variable name without "t:" must be used.
|
||||
Tabs are numbered starting with one.
|
||||
This function is not available in the |sandbox|.
|
||||
@ -8411,6 +8413,8 @@ settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()*
|
||||
use |setwinvar()|.
|
||||
{winnr} can be the window number or the |window-ID|.
|
||||
When {winnr} is zero the current window is used.
|
||||
Note that autocommands are blocked, side effects may not be
|
||||
triggered, e.g. when setting 'filetype' or 'syntax'.
|
||||
This also works for a global or local buffer option, but it
|
||||
doesn't work for a global or local buffer variable.
|
||||
For a local buffer option the global value is unchanged.
|
||||
@ -10318,9 +10322,13 @@ wildmenumode() *wildmenumode()*
|
||||
win_execute({id}, {command} [, {silent}]) *win_execute()*
|
||||
Like `execute()` but in the context of window {id}.
|
||||
The window will temporarily be made the current window,
|
||||
without triggering autocommands.
|
||||
without triggering autocommands. When executing {command}
|
||||
autocommands will be triggered, this may have unexpected side
|
||||
effects. Use |:noautocmd| if needed.
|
||||
Example: >
|
||||
call win_execute(winid, 'syntax enable')
|
||||
call win_execute(winid, 'set syntax=python')
|
||||
< Doing the same with `setwinvar()` would not trigger
|
||||
autocommands and not actually show syntax highlighting.
|
||||
|
||||
win_findbuf({bufnr}) *win_findbuf()*
|
||||
Returns a list with |window-ID|s for windows that contain
|
||||
|
@ -1,4 +1,4 @@
|
||||
*popup.txt* For Vim version 8.1. Last change: 2019 May 26
|
||||
*popup.txt* For Vim version 8.1. Last change: 2019 Jun 01
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -13,9 +13,7 @@ THIS IS UNDER DESIGN - ANYTHING MAY STILL CHANGE
|
||||
3. Examples |popup-examples|
|
||||
|
||||
|
||||
{not available if the |+eval| feature was disabled at compile time}
|
||||
{not able to use text properties if the |+textprop| feature was disabled at
|
||||
compile time}
|
||||
{not available if the |+textprop| feature was disabled at compile time}
|
||||
|
||||
==============================================================================
|
||||
1. Introduction *popup-intro*
|
||||
@ -60,15 +58,22 @@ WINDOW POSITION AND SIZE *popup-position*
|
||||
|
||||
The height of the window is normally equal to the number of, possibly
|
||||
wrapping, lines in the buffer. It can be limited with the "maxheight"
|
||||
property. You can use empty lines to increase the height.
|
||||
property. You can use empty lines to increase the height or the "minheight"
|
||||
property.
|
||||
|
||||
The width of the window is normally equal to the longest line in the buffer.
|
||||
It can be limited with the "maxwidth" property. You can use spaces to
|
||||
increase the width.
|
||||
increase the width or the "minwidth" property.
|
||||
|
||||
By default the 'wrap' option is set, so that no text disappears. However, if
|
||||
there is not enough space, some text may be invisible.
|
||||
|
||||
Vim tries to show the popup in the location you specify. In some cases, e.g.
|
||||
when the popup would go outside of the Vim window, it will show it somewhere
|
||||
else. E.g. if you use `popup_atcursor()` the popup normally shows just above
|
||||
the current cursor position, but if the cursor is close to the top of the Vim
|
||||
window it will be placed below the cursor position.
|
||||
|
||||
|
||||
|
||||
TODO:
|
||||
@ -85,19 +90,20 @@ Probably 2. is the best choice.
|
||||
|
||||
IMPLEMENTATION:
|
||||
- Code is in popupwin.c
|
||||
- when creating the window set options to Vim default? (verify with 'number')
|
||||
- Implement filter.
|
||||
Check that popup_close() works in the filter.
|
||||
- Implement the "pos" option.
|
||||
- Handle screen resize in screenalloc().
|
||||
- Why does 'nrformats' leak from the popup window buffer???
|
||||
- Make redrawing more efficient and avoid flicker.
|
||||
Store popup info in a mask, use the mask in screen_line()
|
||||
Keep mask until next update_screen(), find differences and redraw affected
|
||||
windows/lines
|
||||
Fix redrawing problem with completion.
|
||||
Fix redrawing problem when scrolling non-current window
|
||||
Fix redrawing the statusline on top of a popup
|
||||
- Disable commands, feedkeys(), CTRL-W, etc. in a popup window.
|
||||
Use NOT_IN_POPUP_WINDOW for more commands.
|
||||
- Invoke filter with character before mapping?
|
||||
- Figure out the size and position better.
|
||||
if wrapping splits a double-wide character
|
||||
if wrapping has an indent
|
||||
if wrapping inserts indent
|
||||
- Can the buffer be re-used, to avoid using up lots of buffer numbers?
|
||||
- Implement all the unimplemented options and features.
|
||||
|
||||
@ -114,7 +120,7 @@ popup_create({text}, {options}) *popup_create()*
|
||||
- a string
|
||||
- a list of strings
|
||||
- a list of text lines with text properties
|
||||
{not implemented yet}
|
||||
|
||||
{options} is a dictionary with many possible entries.
|
||||
See |popup_create-usage| for details.
|
||||
|
||||
@ -160,10 +166,10 @@ popup_notification({text}, {options}) *popup_notification()*
|
||||
|
||||
|
||||
popup_atcursor({text}, {options}) *popup_atcursor()*
|
||||
{not implemented yet}
|
||||
Show the {text} above the cursor, and close it when the cursor
|
||||
moves. This works like: >
|
||||
call popup_create({text}, {
|
||||
\ 'pos': 'botleft',
|
||||
\ 'line': 'cursor-1',
|
||||
\ 'col': 'cursor',
|
||||
\ 'moved': 'WORD',
|
||||
@ -232,7 +238,8 @@ popup_setoptions({id}, {options}) *popup_setoptions()*
|
||||
|
||||
popup_getoptions({id}) *popup_getoptions()*
|
||||
Return the {options} for popup {id} in a Dict.
|
||||
A zero value means the option was not set.
|
||||
A zero value means the option was not set. For "zindex" the
|
||||
default value is returned, not zero.
|
||||
|
||||
The "highlight" entry is omitted, use the 'wincolor' option
|
||||
for that: >
|
||||
@ -240,17 +247,24 @@ popup_getoptions({id}) *popup_getoptions()*
|
||||
|
||||
< If popup window {id} is not found an empty Dict is returned.
|
||||
|
||||
popup_getposition({id}) *popup_getposition()*
|
||||
popup_getpos({id}) *popup_getpos()*
|
||||
Return the position and size of popup {id}. Returns a Dict
|
||||
with these entries:
|
||||
col screen column of the popup, one-based
|
||||
line screen line of the popup, one-based
|
||||
width width of the popup in screen cells
|
||||
height height of the popup in screen cells
|
||||
width width of the whole popup in screen cells
|
||||
height height of the whole popup in screen cells
|
||||
core_col screen column of the text box
|
||||
core_line screen line of the text box
|
||||
core_width width of the text box in screen cells
|
||||
core_height height of the text box in screen cells
|
||||
visible one if the popup is displayed, zero if hidden
|
||||
Note that these are the actual screen positions. They differ
|
||||
from the values in `popup_getoptions()` for the sizing and
|
||||
positioning mechanism applied.
|
||||
|
||||
The "core_" values exclude the padding and border.
|
||||
|
||||
If popup window {id} is not found an empty Dict is returned.
|
||||
|
||||
|
||||
@ -270,10 +284,11 @@ manipulation is restricted:
|
||||
- 'bufhidden' is "hide"
|
||||
- 'buflisted' is off
|
||||
- 'undolevels' is -1: no undo at all
|
||||
TODO: more
|
||||
- all other buffer-local and window_local options are set to their Vim default
|
||||
value.
|
||||
|
||||
It is possible to change these options, but anything might break then, so
|
||||
better leave them alone.
|
||||
It is possible to change the specifically mentioned options, but anything
|
||||
might break then, so better leave them alone.
|
||||
|
||||
The window does have a cursor position, but the cursor is not displayed.
|
||||
|
||||
@ -285,6 +300,8 @@ Options can be set on the window with `setwinvar()`, e.g.: >
|
||||
call setwinvar(winid, '&wrap', 0)
|
||||
And options can be set on the buffer with `setbufvar()`, e.g.: >
|
||||
call setbufvar(winbufnr(winid), '&filetype', 'java')
|
||||
Note that this does not trigger autocommands. Use `win_execute()` if you do
|
||||
need them.
|
||||
|
||||
|
||||
POPUP_CREATE() ARGUMENTS *popup_create-usage*
|
||||
@ -302,22 +319,22 @@ optionally text properties. It is in one of three forms:
|
||||
|popup-props|.
|
||||
|
||||
The second argument of |popup_create()| is a dictionary with options:
|
||||
line screen line where to position the popup; can use
|
||||
"cursor", "cursor+1" or "cursor-1" to use the line of
|
||||
the cursor and add or subtract a number of lines;
|
||||
default is "cursor-1".
|
||||
{only number is implemented}
|
||||
col screen column where to position the popup; can use
|
||||
"cursor" to use the column of the cursor, "cursor+99"
|
||||
and "cursor-99" to add or subtract a number of
|
||||
columns; default is "cursor"
|
||||
{only number is implemented}
|
||||
line screen line where to position the popup; can use a
|
||||
number or "cursor", "cursor+1" or "cursor-1" to use
|
||||
the line of the cursor and add or subtract a number of
|
||||
lines; if omitted the popup is vertically centered,
|
||||
otherwise "pos" is used.
|
||||
col screen column where to position the popup; can use a
|
||||
number or "cursor" to use the column of the cursor,
|
||||
"cursor+99" and "cursor-99" to add or subtract a
|
||||
number of columns; if omitted the popup is
|
||||
horizontally centered, otherwise "pos" is used
|
||||
pos "topleft", "topright", "botleft" or "botright":
|
||||
defines what corner of the popup "line" and "col" are
|
||||
used for. When not set "topleft" is used.
|
||||
Alternatively "center" can be used to position the
|
||||
popup in the center of the Vim window.
|
||||
{not implemented yet}
|
||||
popup in the center of the Vim window, in which case
|
||||
"line" and "col" are ignored.
|
||||
flip when TRUE (the default) and the position is relative
|
||||
to the cursor, flip to below or above the cursor to
|
||||
avoid overlap with the |popupmenu-completion| or
|
||||
@ -339,13 +356,19 @@ The second argument of |popup_create()| is a dictionary with options:
|
||||
popup, on top of any border
|
||||
{not implemented yet}
|
||||
wrap TRUE to make the lines wrap (default TRUE)
|
||||
{not implemented yet}
|
||||
highlight highlight group name to use for the text, stored in
|
||||
the 'wincolor' option
|
||||
padding list with numbers, defining the padding
|
||||
above/right/below/left of the popup (similar to CSS);
|
||||
an empty list uses a padding of 1 all around; the
|
||||
padding goes around the text, inside any border;
|
||||
padding uses the 'wincolor' highlight; Example: [1, 2,
|
||||
1, 3] has 1 line of padding above, 2 columns on the
|
||||
right, 1 line below and 3 columns on the left
|
||||
border list with numbers, defining the border thickness
|
||||
above/right/below/left of the popup; an empty list
|
||||
uses a border of 1 all around
|
||||
{not implemented yet}
|
||||
above/right/below/left of the popup (similar to CSS);
|
||||
only values of zero and non-zero are recognized;
|
||||
an empty list uses a border of 1 all around
|
||||
borderhighlight highlight group name to use for the border
|
||||
{not implemented yet}
|
||||
borderchars list with characters, defining the character to use
|
||||
@ -365,7 +388,6 @@ The second argument of |popup_create()| is a dictionary with options:
|
||||
{not implemented yet}
|
||||
filter a callback that can filter typed characters, see
|
||||
|popup-filter|
|
||||
{not implemented yet}
|
||||
callback a callback to be used when the popup closes, e.g. when
|
||||
using |popup_filter_menu()|, see |popup-callback|.
|
||||
{not implemented yet}
|
||||
@ -399,14 +421,13 @@ So we get:
|
||||
type name of the text property type, as added with
|
||||
|prop_type_add()|
|
||||
transparent do not show these characters, show the text under it;
|
||||
if there is an border character to the right or below
|
||||
if there is a border character to the right or below
|
||||
it will be made transparent as well
|
||||
{not implemented yet}
|
||||
|
||||
|
||||
POPUP FILTER *popup-filter*
|
||||
|
||||
{not implemented yet}
|
||||
A callback that gets any typed keys while a popup is displayed. The filter is
|
||||
not invoked when the popup is hidden.
|
||||
|
||||
@ -417,10 +438,23 @@ filter is also called. The filter of the popup window with the highest zindex
|
||||
is called first.
|
||||
|
||||
The filter function is called with two arguments: the ID of the popup and the
|
||||
key.
|
||||
key, e.g.: >
|
||||
func MyFilter(winid, key)
|
||||
if a:key == "\<F2>"
|
||||
" do something
|
||||
return 1
|
||||
endif
|
||||
if a:key == 'x'
|
||||
call popup_close(a:winid)
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunc
|
||||
|
||||
Currently the key is what results after any mapping. This may change...
|
||||
|
||||
Some common key actions:
|
||||
Esc close the popup
|
||||
x close the popup (see note below)
|
||||
cursor keys select another entry
|
||||
Tab accept current suggestion
|
||||
|
||||
@ -431,6 +465,11 @@ popup is col 1, row 1 (not counting the border).
|
||||
Vim provides standard filters |popup_filter_menu()| and
|
||||
|popup_filter_yesno()|.
|
||||
|
||||
Note that "x" is the normal way to close a popup. You may want to use Esc,
|
||||
but since many keys start with an Esc character, there may be a delay before
|
||||
Vim recognizes the Esc key. If you do use Esc, it is reecommended to set the
|
||||
'ttimeoutlen' option to 100 and set 'timeout' and/or 'ttimeout'.
|
||||
|
||||
|
||||
POPUP CALLBACK *popup-callback*
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
*quickref.txt* For Vim version 8.1. Last change: 2019 May 24
|
||||
*quickref.txt* For Vim version 8.1. Last change: 2019 May 31
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -982,6 +982,7 @@ Short explanation of each option: *option-list*
|
||||
'wildmode' 'wim' mode for 'wildchar' command-line expansion
|
||||
'wildoptions' 'wop' specifies how command line completion is done
|
||||
'winaltkeys' 'wak' when the windows system handles ALT keys
|
||||
'wincolor' 'wcr' window-local highlighting
|
||||
'window' 'wi' nr of lines to scroll for CTRL-F and CTRL-B
|
||||
'winheight' 'wh' minimum number of lines for the current window
|
||||
'winfixheight' 'wfh' keep window height when opening/closing windows
|
||||
|
@ -4742,6 +4742,7 @@ E99 diff.txt /*E99*
|
||||
E990 eval.txt /*E990*
|
||||
E991 eval.txt /*E991*
|
||||
E992 options.txt /*E992*
|
||||
E993 popup.txt /*E993*
|
||||
E999 repeat.txt /*E999*
|
||||
EX intro.txt /*EX*
|
||||
EXINIT starting.txt /*EXINIT*
|
||||
@ -8207,7 +8208,7 @@ popup_dialog() popup.txt /*popup_dialog()*
|
||||
popup_filter_menu() popup.txt /*popup_filter_menu()*
|
||||
popup_filter_yesno() popup.txt /*popup_filter_yesno()*
|
||||
popup_getoptions() popup.txt /*popup_getoptions()*
|
||||
popup_getposition() popup.txt /*popup_getposition()*
|
||||
popup_getpos() popup.txt /*popup_getpos()*
|
||||
popup_hide() popup.txt /*popup_hide()*
|
||||
popup_menu() popup.txt /*popup_menu()*
|
||||
popup_move() popup.txt /*popup_move()*
|
||||
@ -9853,6 +9854,7 @@ win32-vimrun gui_w32.txt /*win32-vimrun*
|
||||
win32-win3.1 os_win32.txt /*win32-win3.1*
|
||||
win32-win95 os_win32.txt /*win32-win95*
|
||||
win32s os_win32.txt /*win32s*
|
||||
win_execute() eval.txt /*win_execute()*
|
||||
win_findbuf() eval.txt /*win_findbuf()*
|
||||
win_getid() eval.txt /*win_getid()*
|
||||
win_gotoid() eval.txt /*win_gotoid()*
|
||||
|
@ -1,4 +1,4 @@
|
||||
*terminal.txt* For Vim version 8.1. Last change: 2019 May 20
|
||||
*terminal.txt* For Vim version 8.1. Last change: 2019 May 29
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -907,7 +907,7 @@ When 'background' is "dark":
|
||||
hi debugBreakpoint term=reverse ctermbg=red guibg=red
|
||||
|
||||
|
||||
Shorcuts *termdebug_shortcuts*
|
||||
Shortcuts *termdebug_shortcuts*
|
||||
|
||||
You can define your own shortcuts (mappings) to control gdb, that can work in
|
||||
any window, using the TermDebugSendCommand() function. Example: >
|
||||
|
@ -1,4 +1,4 @@
|
||||
*todo.txt* For Vim version 8.1. Last change: 2019 May 26
|
||||
*todo.txt* For Vim version 8.1. Last change: 2019 May 31
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -42,6 +42,8 @@ Ongoing work on text properties, see src/textprop.c
|
||||
|
||||
Popup windows are being implemented, see |popup-window|.
|
||||
|
||||
Listener causes extra } to be inserted. (Paul Jolly, #4455)
|
||||
|
||||
Patch to beautify the output of a test run. (Christian Brabandt, #4391)
|
||||
can be improved.
|
||||
|
||||
@ -52,6 +54,12 @@ remains equal? Then %argdel to clean it up. Do try this with 'hidden' set.
|
||||
|
||||
Patch for Chinese translations for nsis. (#4407) Comments handled?
|
||||
|
||||
Patch to add v:searchstat. (Takuya Fujiwara, #4446) Should be independent of
|
||||
'shortmess', filled on demand and cached until search changes.
|
||||
|
||||
listener callback is invoked while another is still busy? (Paul Jolly)
|
||||
Should not happen because of text lock.
|
||||
|
||||
'incsearch' with :s: (#3321)
|
||||
- Get E20 when using command history to get "'<,'>s/a/b" and no Visual area
|
||||
was set. (#3837)
|
||||
@ -130,6 +138,12 @@ Should do current file first and not split it up when more results are found.
|
||||
Adding "10" to 'spellsuggest' causes spell suggestions to become very slow.
|
||||
(#4087)
|
||||
|
||||
Problem with German spell file. Hint for solution by Klaus-Peter Schreiner in
|
||||
#4314, solves the Rasenmäher problem.
|
||||
|
||||
Visual highlight not removed when 'dipslay' is "lastline" and line doesn't
|
||||
fit. (Kevin Lawler, #4457)
|
||||
|
||||
Does not build with MinGW out of the box:
|
||||
- _stat64 is not defined, need to use "struct stat" in vim.h
|
||||
- WINVER conflict, should use 0x0600 by default?
|
||||
@ -177,6 +191,10 @@ register "", So that registers can be saved and fully restored.
|
||||
Add a way to create an empty, hidden buffer. Like doing ":new|hide".
|
||||
":let buf = bufcreate('name')
|
||||
|
||||
Session file contains absolute paths when "curdir" is removed form
|
||||
'sessionoptions', making it impossible to have a session with a relative path.
|
||||
(#4450)
|
||||
|
||||
When using a timer callback vgetc_busy is reset, allowing for using input().
|
||||
But in a channel callback this does not happen. We need to do something
|
||||
similar to check_due_timer(). Also see #3809.
|
||||
|
@ -1,4 +1,4 @@
|
||||
*usr_41.txt* For Vim version 8.1. Last change: 2019 May 16
|
||||
*usr_41.txt* For Vim version 8.1. Last change: 2019 May 29
|
||||
|
||||
VIM USER MANUAL - by Bram Moolenaar
|
||||
|
||||
@ -105,20 +105,21 @@ We won't explain how |:for| and |range()| work until later. Follow the links
|
||||
if you are impatient.
|
||||
|
||||
|
||||
THREE KINDS OF NUMBERS
|
||||
FOUR KINDS OF NUMBERS
|
||||
|
||||
Numbers can be decimal, hexadecimal or octal. A hexadecimal number starts
|
||||
with "0x" or "0X". For example "0x1f" is decimal 31. An octal number starts
|
||||
with a zero. "017" is decimal 15. Careful: don't put a zero before a decimal
|
||||
number, it will be interpreted as an octal number!
|
||||
Numbers can be decimal, hexadecimal, octal or binary. A hexadecimal number
|
||||
starts with "0x" or "0X". For example "0x1f" is decimal 31. An octal number
|
||||
starts with a zero. "017" is decimal 15. A binary number starts with "0b" or
|
||||
"0B". For example "0b101" is decimal 5. Careful: don't put a zero before a
|
||||
decimal number, it will be interpreted as an octal number!
|
||||
The ":echo" command always prints decimal numbers. Example: >
|
||||
|
||||
:echo 0x7f 036
|
||||
< 127 30 ~
|
||||
|
||||
A number is made negative with a minus sign. This also works for hexadecimal
|
||||
and octal numbers. A minus sign is also used for subtraction. Compare this
|
||||
with the previous example: >
|
||||
A number is made negative with a minus sign. This also works for hexadecimal,
|
||||
octal and binary numbers. A minus sign is also used for subtraction. Compare
|
||||
this with the previous example: >
|
||||
|
||||
:echo 0x7f -036
|
||||
< 97 ~
|
||||
@ -614,6 +615,7 @@ String manipulation: *string-functions*
|
||||
repeat() repeat a string multiple times
|
||||
eval() evaluate a string expression
|
||||
execute() execute an Ex command and get the output
|
||||
win_execute() like execute() but in a specified window
|
||||
trim() trim characters from a string
|
||||
|
||||
List manipulation: *list-functions*
|
||||
|
@ -25914,7 +25914,7 @@ Files: runtime/doc/eval.txt, runtime/doc/usr_41.txt, src/evalfunc.c,
|
||||
|
||||
Patch 8.1.0021
|
||||
Problem: Clang warns for undefined behavior.
|
||||
Solution: Move #ifdef outside of sprintf() call.(suggestion by Michael
|
||||
Solution: Move #ifdef outside of sprintf() call. (suggestion by Michael
|
||||
Jarvis, closes #2946)
|
||||
Files: src/term.c
|
||||
|
||||
@ -25930,7 +25930,7 @@ Solution: Use mch_memmove() instead of STRNCPY().
|
||||
Files: src/memline.c
|
||||
|
||||
Patch 8.1.0024
|
||||
Problem: % command not testded on #ifdef and comment.
|
||||
Problem: % command not tested on #ifdef and comment.
|
||||
Solution: Add tests. (Dominique Pelle, closes #2956)
|
||||
Files: src/testdir/test_goto.vim
|
||||
|
||||
@ -25946,7 +25946,7 @@ Files: src/testdir/test_terminal.vim
|
||||
|
||||
Patch 8.1.0027
|
||||
Problem: Difficult to make a plugin that feeds a line to a job.
|
||||
Solution: Add the nitial code for the "prompt" buftype.
|
||||
Solution: Add the initial code for the "prompt" buftype.
|
||||
Files: runtime/doc/channel.txt, runtime/doc/eval.txt,
|
||||
runtime/doc/options.txt, runtime/doc/tags, runtime/doc/todo.txt,
|
||||
src/Makefile, src/buffer.c, src/channel.c, src/diff.c, src/edit.c,
|
||||
@ -25966,7 +25966,7 @@ Solution: Skip test with redirection on MS-Windows.
|
||||
Files: src/testdir/test_terminal.vim
|
||||
|
||||
Patch 8.1.0030
|
||||
Problem: Stoping Vim running in a terminal may not work.
|
||||
Problem: Stopping Vim running in a terminal may not work.
|
||||
Solution: Instead of sending <Esc> send CTRL-O.
|
||||
Files: src/testdir/screendump.vim, src/testdir/test_prompt_buffer.vim
|
||||
|
||||
@ -26046,8 +26046,8 @@ Solution: Return FAIL from get_bad_opt() only when there is no valid
|
||||
Files: src/ex_docmd.c, src/testdir/test_plus_arg_edit.vim
|
||||
|
||||
Patch 8.1.0044
|
||||
Problem: If a test function exists Vim this may go unnoticed.
|
||||
Solution: Check for a test funtion quitting Vim. Fix tests that did exit
|
||||
Problem: If a test function exits Vim this may go unnoticed.
|
||||
Solution: Check for a test function quitting Vim. Fix tests that did exit
|
||||
Vim.
|
||||
Files: src/testdir/runtest.vim, src/testdir/test_assert.vim
|
||||
|
||||
@ -26330,7 +26330,7 @@ Solution: Only use debugbreak() on MS-Windows.
|
||||
Files: runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
|
||||
|
||||
Patch 8.1.0094
|
||||
Problem: Help text "usage:" is not capatalized.
|
||||
Problem: Help text "usage:" is not capitalized.
|
||||
Solution: Make it "Usage:". (closes #3044)
|
||||
Files: src/main.c
|
||||
|
||||
@ -26929,7 +26929,8 @@ Files: src/testdir/test_spell.vim
|
||||
|
||||
Patch 8.1.0201
|
||||
Problem: Newer Python uses "importlib" instead of "imp".
|
||||
Solution: Use "importlib" for newer Python versions. (closes #3163)
|
||||
Solution: Use "importlib" for newer Python versions. (Ozaki Kiichi,
|
||||
closes #3163)
|
||||
Files: src/if_py_both.h, src/testdir/test87.in
|
||||
|
||||
Patch 8.1.0202
|
||||
@ -27156,7 +27157,8 @@ Solution: Add a test that shows the behavior. (Christian Brabandt,
|
||||
Files: src/testdir/test_tabpage.vim
|
||||
|
||||
Patch 8.1.0242
|
||||
Problem: Insert mode completion may use an invalid buffer pointer.
|
||||
Problem: Insert mode completion may use an invalid buffer pointer. (Akib
|
||||
Nizam)
|
||||
Solution: Check for ins_buf to be valid. (closes #3290)
|
||||
Files: src/edit.c
|
||||
|
||||
@ -27692,7 +27694,7 @@ Solution: Allow :file without argument when curbuf_lock is set. (Jason
|
||||
Files: src/ex_docmd.c, src/testdir/test_quickfix.vim
|
||||
|
||||
Patch 8.1.0338
|
||||
Problem: MS-Windows: VTP doesn't work properly with Powershell.
|
||||
Problem: MS-Windows: VTP doesn't work properly with PowerShell.
|
||||
Solution: Adjust the color index. (Nobuhiro Takasaki, closes #3347)
|
||||
Files: src/os_win32.c
|
||||
|
||||
@ -27715,7 +27717,8 @@ Files: src/ex_cmds2.c, src/testdir/test_arglist.vim,
|
||||
src/testdir/test_command_count.vim
|
||||
|
||||
Patch 8.1.0342
|
||||
Problem: Crash when a callback deletes a window that is being used.
|
||||
Problem: Crash when a callback deletes a window that is being used. (Ozaki
|
||||
Kiichi)
|
||||
Solution: Do not unload a buffer that is being displayed while redrawing the
|
||||
screen. Also avoid invoking callbacks while redrawing.
|
||||
(closes #2107)
|
||||
@ -27795,7 +27798,7 @@ Files: src/testdir/test_packadd.vim
|
||||
|
||||
Patch 8.1.0355
|
||||
Problem: Incorrect adjusting the popup menu for the preview window.
|
||||
Solution: Compute position and height properl. (Ronan Pigott) Also show at
|
||||
Solution: Compute position and height properly. (Ronan Pigott) Also show at
|
||||
least ten items. (closes #3414)
|
||||
Files: src/popupmnu.c
|
||||
|
||||
@ -28388,7 +28391,7 @@ Files: src/os_win32.c, runtime/doc/mlang.txt
|
||||
|
||||
Patch 8.1.0453
|
||||
Problem: MS-Windows: executable() is not reliable.
|
||||
Solution: Use $PATHEXT properly. (Yasuhiro Matsumoto, closes #3412)
|
||||
Solution: Use $PATHEXT properly. (Yasuhiro Matsumoto, closes #3512)
|
||||
Files: src/os_win32.c, src/testdir/test_functions.vim
|
||||
|
||||
Patch 8.1.0454
|
||||
@ -28448,7 +28451,8 @@ Files: src/memline.c
|
||||
Patch 8.1.0464
|
||||
Problem: MS-Windows: job_info() has cmd without backslashes. (Daniel
|
||||
Hahler)
|
||||
Solution: Use rem_backslash(). (closes #3517, closes #3404)
|
||||
Solution: Use rem_backslash(). (closes #3517, closes #3404) Add a test.
|
||||
(Yasuhiro Matsumoto)
|
||||
Files: src/misc2.c, src/testdir/test_channel.vim
|
||||
|
||||
Patch 8.1.0465 (after 8.1.0452)
|
||||
@ -28535,7 +28539,7 @@ Files: src/Make_cyg_ming.mak
|
||||
Patch 8.1.0479
|
||||
Problem: Failure when setting 'varsofttabstop' to end in a comma. (Ralf
|
||||
Schandl)
|
||||
Solution: Reject value with trailing command. Add test for invalid values
|
||||
Solution: Reject value with trailing comma. Add test for invalid values
|
||||
(closes #3544)
|
||||
Files: src/testdir/test_vartabs.vim, src/option.c
|
||||
|
||||
@ -28596,7 +28600,7 @@ Solution: Return from qf_jump_edit_buffer() early. (Yegappan Lakshmanan)
|
||||
Files: src/quickfix.c, src/testdir/test_quickfix.vim
|
||||
|
||||
Patch 8.1.0490
|
||||
Problem: MS-Windows: doesn't handle missing glibwinpthread-1.dll.
|
||||
Problem: MS-Windows: doesn't handle missing libwinpthread-1.dll.
|
||||
Solution: Adjust Cygwin/MinGW build file. (Ken Takata, closes #2827)
|
||||
Files: src/Make_cyg_ming.mak
|
||||
|
||||
@ -28972,7 +28976,7 @@ Files: src/popupmnu.c, src/testdir/test_popup.vim,
|
||||
|
||||
Patch 8.1.0555
|
||||
Problem: Crash when last search pat is set but not last substitute pat.
|
||||
Solution: Do not mix up last search pattern and last subtitute pattern.
|
||||
Solution: Do not mix up last search pattern and last substitute pattern.
|
||||
(closes #3647)
|
||||
Files: src/search.c, src/testdir/test_search.vim
|
||||
|
||||
@ -28983,7 +28987,7 @@ Solution: Use a separate saved last_idx for saving search patterns for
|
||||
Files: src/search.c
|
||||
|
||||
Patch 8.1.0557
|
||||
Problem: Termdebug: gdb may use X.Y for breakpoint number.
|
||||
Problem: Termdebug: gdb may use X.Y for breakpoint number. (Ryou Ezoe)
|
||||
Solution: Handle X.Y breakpoint numbers. (Yasuhiro Matsumoto, close #3641)
|
||||
Files: runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
|
||||
|
||||
@ -29001,13 +29005,13 @@ Files: src/testdir/test_arglist.vim, src/testdir/test_filetype.vim,
|
||||
src/testdir/test_syntax.vim
|
||||
|
||||
Patch 8.1.0560
|
||||
Problem: Cannot use address type "other" with with user command.
|
||||
Problem: Cannot use address type "other" with user command.
|
||||
Solution: Add "other" to the list. (Daniel Hahler, closes #3655) Also
|
||||
reject "%" for commands with "other". Add some more tests.
|
||||
Files: src/ex_docmd.c, src/testdir/test_usercommands.vim
|
||||
|
||||
Patch 8.1.0561
|
||||
Problem: MSCV error format has changed.
|
||||
Problem: MSVC error format has changed.
|
||||
Solution: Make the space between the line number and colon optional.
|
||||
Files: src/option.h
|
||||
|
||||
@ -29069,7 +29073,7 @@ Files: src/evalfunc.c, src/testdir/test_execute_func.vim
|
||||
Patch 8.1.0572
|
||||
Problem: Stopping a job does not work properly on OpenBSD.
|
||||
Solution: Do not use getpgid() to check the process group of the job
|
||||
processs ID, always pass the negative process ID to kill().
|
||||
process ID, always pass the negative process ID to kill().
|
||||
(George Koehler, closes #3656)
|
||||
Files: src/os_unix.c
|
||||
|
||||
@ -29105,7 +29109,7 @@ Files: src/gui_gtk_x11.c, src/gui_mac.c, src/gui_motif.c, src/gui.c
|
||||
|
||||
Patch 8.1.0578
|
||||
Problem: Cannot disable arabic, rightleft and farsi in configure.
|
||||
Solution: Add configur flags. (Diego Fernando Carrión, closes #1867)
|
||||
Solution: Add configure flags. (Diego Fernando Carrión, closes #1867)
|
||||
Files: src/configure.ac, src/auto/configure, src/config.h.in,
|
||||
src/feature.h, src/Makefile
|
||||
|
||||
@ -29275,7 +29279,7 @@ Files: src/os_mswin.c, src/proto/buffer.pro, src/proto/ex_cmds.pro,
|
||||
src/proto/userfunc.pro
|
||||
|
||||
Patch 8.1.0608
|
||||
Problem: Coverals is not updating.
|
||||
Problem: Coveralls is not updating.
|
||||
Solution: Adjust path in Travis config.
|
||||
Files: .travis.yml
|
||||
|
||||
@ -29363,7 +29367,7 @@ Files: src/eval.c, src/proto/eval.pro, src/evalfunc.c,
|
||||
src/testdir/test_messages.vim, src/message.c
|
||||
|
||||
Patch 8.1.0620
|
||||
Problem: Overuling CONF_ARGS from the environment no longer works. (Tony
|
||||
Problem: Overruling CONF_ARGS from the environment no longer works. (Tony
|
||||
Mechelynck)
|
||||
Solution: Do not define any CONF_ARGS by default.
|
||||
Files: src/Makefile
|
||||
@ -29385,8 +29389,8 @@ Solution: Define FOR_ALL_FRAMES. (Yegappan Lakshmanan)
|
||||
Files: src/ex_docmd.c, src/globals.h, src/screen.c, src/window.c
|
||||
|
||||
Patch 8.1.0624 (after 8.2.0620)
|
||||
Problem: Overuling CONF_ARGS from the environment still does not work. (Tony
|
||||
Mechelynck)
|
||||
Problem: Overruling CONF_ARGS from the environment still does not work.
|
||||
(Tony Mechelynck)
|
||||
Solution: Add back CONF_ARGS next to the new numbered ones.
|
||||
Files: src/Makefile
|
||||
|
||||
@ -29480,7 +29484,7 @@ Files: src/testdir/test_textprop.vim
|
||||
|
||||
Patch 8.1.0640
|
||||
Problem: Get E14 while typing command :tab with 'incsearch' set.
|
||||
Solution: Do not give an error when looking for the command. (Yasuhiro
|
||||
Solution: Do not give an error when looking for the command. (Hirohito
|
||||
Higashi)
|
||||
Files: src/testdir/test_search.vim, src/ex_docmd.c
|
||||
|
||||
@ -29617,7 +29621,7 @@ Files: src/screen.c
|
||||
Patch 8.1.0664
|
||||
Problem: Configure "fail-if-missing" does not apply to the enable-gui
|
||||
argument. (Rhialto)
|
||||
Solution: Make configure fail if a GUI was specifified and "fail-if-missing"
|
||||
Solution: Make configure fail if a GUI was specified and "fail-if-missing"
|
||||
is enabled and the GUI test fails.
|
||||
Files: src/configure.ac, src/auto/configure
|
||||
|
||||
@ -29935,7 +29939,7 @@ Files: nsis/icons.zip, nsis/icons/disabled.bmp, nsis/icons/enabled.bmp,
|
||||
nsis/README.txt, Filelist, Makefile
|
||||
|
||||
Patch 8.1.0714
|
||||
Problem: Unessesary #if lines in GTK code.
|
||||
Problem: Unnecessary #if lines in GTK code.
|
||||
Solution: Remove the #if. (Ken Takata, closes #3785)
|
||||
Files: src/gui_beval.c, src/if_mzsch.c
|
||||
|
||||
@ -29970,7 +29974,7 @@ Files: src/evalfunc.c, src/version.c, src/normal.c, src/ops.c,
|
||||
src/feature.h, runtime/doc/various.txt
|
||||
|
||||
Patch 8.1.0720
|
||||
Problem: Cannot easily change the current quickfx list index.
|
||||
Problem: Cannot easily change the current quickfix list index.
|
||||
Solution: Add the "idx" argument to setqflist(). (Yegappan Lakshmanan,
|
||||
closes #3701)
|
||||
Files: runtime/doc/eval.txt, runtime/doc/quickfix.txt, src/quickfix.c,
|
||||
@ -30777,7 +30781,7 @@ Files: src/ui.c
|
||||
|
||||
Patch 8.1.0836
|
||||
Problem: User completion test can fail on MS-Windows.
|
||||
Solution: Allow for other names befor "Administrator".
|
||||
Solution: Allow for other names before "Administrator".
|
||||
Files: src/testdir/test_cmdline.vim
|
||||
|
||||
Patch 8.1.0837
|
||||
@ -30804,7 +30808,7 @@ Files: src/ui.c, src/testdir/test_timers.vim, src/gui_gtk_x11.c,
|
||||
|
||||
Patch 8.1.0841
|
||||
Problem: Travis config to get Lua on MacOS is too complicated.
|
||||
Solution: Use an addons entry. (Ozaki Kiichi, closes 3876)
|
||||
Solution: Use an addons entry. (Ozaki Kiichi, closes #3876)
|
||||
Files: .travis.yml
|
||||
|
||||
Patch 8.1.0842
|
||||
@ -30912,7 +30916,7 @@ Solution: Make them the same, update docs. (close #3882)
|
||||
Files: src/option.c, runtime/doc/options.txt, runtime/doc/indent.txt
|
||||
|
||||
Patch 8.1.0859
|
||||
Problem: "%v" in 'errorformat' does handle multi-byte characters.
|
||||
Problem: "%v" in 'errorformat' does not handle multi-byte characters.
|
||||
Solution: Handle multi-byte characters. (Yegappan Lakshmanan, closes #3700)
|
||||
Files: src/quickfix.c, src/testdir/test_quickfix.vim
|
||||
|
||||
@ -31034,7 +31038,7 @@ Files: src/testdir/test_functions.vim
|
||||
|
||||
Patch 8.1.0879
|
||||
Problem: MS-Windows: temp name encoding can be wrong.
|
||||
Solution: Convert from active code page to 'encoding'. (Ken Takata,
|
||||
Solution: Convert from active code page to 'encoding'. (Yasuhiro Matsumoto,
|
||||
closes #3520, closes #1698)
|
||||
Files: src/fileio.c
|
||||
|
||||
@ -31064,7 +31068,7 @@ Files: src/fileio.c
|
||||
|
||||
Patch 8.1.0883
|
||||
Problem: Missing some changes for Ex commands.
|
||||
Solution: Add mising changes in header file.
|
||||
Solution: Add missing changes in header file.
|
||||
Files: src/ex_cmds.h
|
||||
|
||||
Patch 8.1.0884
|
||||
@ -31111,7 +31115,7 @@ Solution: Correct using use_file_for_out in condition. (Ozaki Kiichi, closes
|
||||
Files: src/os_unix.c, src/testdir/test_channel.vim
|
||||
|
||||
Patch 8.1.0891
|
||||
Problem: Substitute command inssuficiently tested.
|
||||
Problem: Substitute command insufficiently tested.
|
||||
Solution: Add more test coverage. (Dominique Pelle)
|
||||
Files: src/testdir/test_substitute.vim
|
||||
|
||||
@ -31165,7 +31169,7 @@ Solution: Remove check_restricted().
|
||||
Files: src/eval.c
|
||||
|
||||
Patch 8.1.0900
|
||||
Problem: ConPTY many crash with 32-bit build.
|
||||
Problem: ConPTY may crash with 32-bit build.
|
||||
Solution: Fix function declarations. (Ken Takata, closes #3943)
|
||||
Files: src/terminal.c
|
||||
|
||||
@ -31219,7 +31223,7 @@ Files: runtime/doc/options.txt, src/os_win32.c, src/proto/os_win32.pro,
|
||||
|
||||
Patch 8.1.0910
|
||||
Problem: Crash with tricky search pattern. (Kuang-che Wu)
|
||||
Solution: Check for runnning out of memory. (closes #3950)
|
||||
Solution: Check for running out of memory. (closes #3950)
|
||||
Files: src/regexp_nfa.c, src/testdir/test_regexp_latin.vim
|
||||
|
||||
Patch 8.1.0911
|
||||
@ -31419,7 +31423,7 @@ Files: src/ex_docmd.c, src/normal.c, src/os_win32.c,
|
||||
src/proto/os_win32.pro
|
||||
|
||||
Patch 8.1.0941
|
||||
Problem: Macros for MS-Windows are inconsistent, using "32", "3264 and
|
||||
Problem: Macros for MS-Windows are inconsistent, using "32", "3264" and
|
||||
others.
|
||||
Solution: Use MSWIN for all MS-Windows builds. Use FEAT_GUI_MSWIN for the
|
||||
GUI build. (Hirohito Higashi, closes #3932)
|
||||
@ -31481,7 +31485,7 @@ Solution: Do not enable filetype detection.
|
||||
Files: runtime/defaults.vim
|
||||
|
||||
Patch 8.1.0949
|
||||
Problem: MS-windows defines GUI macros different than other systems.
|
||||
Problem: MS-Windows defines GUI macros different than other systems.
|
||||
Solution: Swap FEAT_GUI and FEAT_GUI_MSWIN. (Hirohito Higashi, closes #3996)
|
||||
Files: src/Make_bc5.mak, src/Make_cyg_ming.mak, src/Make_ivc.mak,
|
||||
src/Make_mvc.mak, src/if_ole.cpp, src/vim.h, src/vim.rc
|
||||
@ -31592,7 +31596,8 @@ Files: src/regexp_nfa.c, src/testdir/test_search.vim
|
||||
|
||||
Patch 8.1.0969
|
||||
Problem: Message written during startup is truncated.
|
||||
Solution: Restore message after truncating. (closes 3969)
|
||||
Solution: Restore message after truncating. (closes #3969) Add a test.
|
||||
(Yasuhiro Matsumoto)
|
||||
Files: src/message.c, src/testdir/test_startup.vim
|
||||
|
||||
Patch 8.1.0970
|
||||
@ -31634,7 +31639,7 @@ Files: src/screen.c, src/textprop.c
|
||||
|
||||
Patch 8.1.0976
|
||||
Problem: Dosinstall still has buffer overflow problems.
|
||||
Solution: Adjust buffer sizes. (Yasuhiro Matsumoto, closes #4002)
|
||||
Solution: Adjust buffer sizes. (Yasuhiro Matsumoto, closes #4002)
|
||||
Files: src/dosinst.c, src/dosinst.h, src/uninstal.c
|
||||
|
||||
Patch 8.1.0977
|
||||
@ -31685,7 +31690,7 @@ Solution: Check for long becoming negative int. (closes #4042)
|
||||
Files: src/regexp.c, src/testdir/test_search.vim
|
||||
|
||||
Patch 8.1.0986
|
||||
Problem: rename() is not propertly tested.
|
||||
Problem: rename() is not properly tested.
|
||||
Solution: Add tests. (Dominique Pelle, closes #4061)
|
||||
Files: src/testdir/Make_all.mak, src/testdir/test_alot.vim,
|
||||
src/testdir/test_rename.vim
|
||||
@ -31742,7 +31747,7 @@ Files: src/window.c, src/evalfunc.c, runtime/doc/eval.txt,
|
||||
Patch 8.1.0995
|
||||
Problem: A getchar() call while executing a register resets the
|
||||
reg_executing() result.
|
||||
Solution: Save and restore reg_executing. (closes #406
|
||||
Solution: Save and restore reg_executing. (closes #4066)
|
||||
Files: src/evalfunc.c, src/testdir/test_functions.vim
|
||||
|
||||
Patch 8.1.0996 (after 8.1.0994)
|
||||
@ -31847,7 +31852,7 @@ Files: src/os_win32.c
|
||||
|
||||
Patch 8.1.1014
|
||||
Problem: MS-Windows: /analyze only defined for non-debug version.
|
||||
Solution: Move adding of /analyze up. (Taro Muraoka, closes #4114)
|
||||
Solution: Move adding of /analyze up. (Ken Takata, closes #4114)
|
||||
Files: src/Make_mvc.mak
|
||||
|
||||
Patch 8.1.1015
|
||||
@ -31859,9 +31864,9 @@ Files: runtime/doc/eval.txt, runtime/doc/quickfix.txt, src/quickfix.c,
|
||||
src/testdir/test_quickfix.vim, src/window.c
|
||||
|
||||
Patch 8.1.1016
|
||||
Problem: MS-Windows: No color in shell when using "!" in 'guioptions.
|
||||
Problem: MS-Windows: No color in shell when using "!" in 'guioptions'.
|
||||
Solution: Don't stop termcap when using a terminal window for the shell.
|
||||
(vim-jp, closes #4117)
|
||||
(Nobuhiro Takasaki, vim-jp, closes #4117)
|
||||
Files: src/ex_cmds.c
|
||||
|
||||
Patch 8.1.1017
|
||||
@ -32049,7 +32054,7 @@ Files: src/undo.c, src/proto/undo.pro, src/normal.c,
|
||||
src/testdir/test_normal.vim
|
||||
|
||||
Patch 8.1.1050
|
||||
Problem: Blank srceen when DirectWrite failed.
|
||||
Problem: Blank screen when DirectWrite failed.
|
||||
Solution: Call redraw_later_clear() after recreating the Direct2D render
|
||||
target. (Ken Takata, closes #4172)
|
||||
Files: src/gui_dwrite.cpp
|
||||
@ -32411,7 +32416,7 @@ Files: src/Make_cyg.mak, src/Make_cyg_ming.mak, src/Make_mvc.mak,
|
||||
|
||||
Patch 8.1.1105
|
||||
Problem: Long escape sequences may be split up.
|
||||
Solution: Assume esccape sequences can be up to 80 bytes long. (Nobuhiro
|
||||
Solution: Assume escape sequences can be up to 80 bytes long. (Nobuhiro
|
||||
Takasaki, closes #4196)
|
||||
Files: src/term.c
|
||||
|
||||
@ -32471,7 +32476,8 @@ Files: src/autocmd.c
|
||||
|
||||
Patch 8.1.1116
|
||||
Problem: Cannot enforce a Vim script style.
|
||||
Solution: Add the :scriptversion command. (closes #3857)
|
||||
Solution: Add the :scriptversion command. (idea by Yasuhiro Matsumoto,
|
||||
closes #3857)
|
||||
Files: runtime/doc/repeat.txt, runtime/doc/eval.txt, src/eval.c,
|
||||
src/ex_cmds.h, src/evalfunc.c, src/ex_cmds2.c,
|
||||
src/proto/ex_cmds2.pro, src/structs.h, src/buffer.c, src/main.c,
|
||||
@ -32576,7 +32582,7 @@ Files: src/globals.h
|
||||
|
||||
Patch 8.1.1134
|
||||
Problem: Buffer for quickfix window is reused for another file.
|
||||
Solution: Don't reuse the quickfx buffer. (Yegappan Lakshmanan)
|
||||
Solution: Don't reuse the quickfix buffer. (Yegappan Lakshmanan)
|
||||
Files: src/buffer.c, src/testdir/test_quickfix.vim
|
||||
|
||||
Patch 8.1.1135 (after 8.1.1134)
|
||||
@ -32598,7 +32604,8 @@ Files: src/testdir/test_termcodes.vim
|
||||
|
||||
Patch 8.1.1138
|
||||
Problem: Plugins don't get notified when the popup menu changes.
|
||||
Solution: Add the CompleteChanged event. (Andy Massimino. closes #4176)
|
||||
Solution: Add the CompleteChanged event. (Qiming Zhao, Andy Massimino,
|
||||
closes #4176)
|
||||
Files: runtime/doc/autocmd.txt, src/autocmd.c, src/dict.c,
|
||||
src/insexpand.c, src/popupmnu.c, src/proto/autocmd.pro,
|
||||
src/proto/dict.pro, src/proto/popupmnu.pro,
|
||||
@ -32681,7 +32688,7 @@ Files: src/Makefile
|
||||
|
||||
Patch 8.1.1152
|
||||
Problem: Compiler warning with VS2019.
|
||||
Solution: Specify different offset for "AMD64". (closes #4235)
|
||||
Solution: Specify different offset for "AMD64". (Ken Takata, closes #4235)
|
||||
Files: src/GvimExt/Makefile
|
||||
|
||||
Patch 8.1.1153
|
||||
@ -32691,7 +32698,7 @@ Files: src/po/Makefile
|
||||
|
||||
Patch 8.1.1154
|
||||
Problem: Getting a newer msgfmt on Travis is too complicated.
|
||||
Solution: Use a "sourcline" entry. (Ozaki Kiichi, closes #4236)
|
||||
Solution: Use a "sourceline" entry. (Ozaki Kiichi, closes #4236)
|
||||
Files: .travis.yml
|
||||
|
||||
Patch 8.1.1155
|
||||
@ -32898,7 +32905,7 @@ Files: src/edit.c, src/testdir/test_bufline.vim,
|
||||
|
||||
Patch 8.1.1190
|
||||
Problem: has('vimscript-3') does not work.
|
||||
Solution: Add "vimscript-3" to the list of features.
|
||||
Solution: Add "vimscript-3" to the list of features. (partly by Ken Takata)
|
||||
Files: src/evalfunc.c, src/testdir/test_eval_stuff.vim
|
||||
|
||||
Patch 8.1.1191
|
||||
@ -32947,7 +32954,7 @@ Files: src/main.c, src/testdir/test_startup.vim,
|
||||
|
||||
Patch 8.1.1198
|
||||
Problem: Bracketed paste may remain active after Vim exists, because the
|
||||
terminal emulater restores the setting.
|
||||
terminal emulator restores the setting.
|
||||
Solution: Set/reset bracketed paste mode before setting the terminal mode.
|
||||
(closes #3579)
|
||||
Files: src/term.c
|
||||
@ -33331,8 +33338,8 @@ Solution: Adjust comment. Don't use different directory for DIRECTX. Do
|
||||
Files: src/Make_mvc.mak
|
||||
|
||||
Patch 8.1.1258
|
||||
Problem: The "N files to edit" message can not be surpressed.
|
||||
Solution: Surpress the message with --not-a-term. (closes #4320)
|
||||
Problem: The "N files to edit" message can not be suppressed.
|
||||
Solution: Suppress the message with --not-a-term. (closes #4320)
|
||||
Files: src/main.c
|
||||
|
||||
Patch 8.1.1259
|
||||
@ -33741,7 +33748,7 @@ Files: src/configure.ac, src/auto/configure, src/config.h.in,
|
||||
|
||||
Patch 8.1.1314
|
||||
Problem: MSVC makefile is not nicely indented.
|
||||
Solution: Addjust spaces in preprocessor directives. (Ken Takata)
|
||||
Solution: Adjust spaces in preprocessor directives. (Ken Takata)
|
||||
Files: src/Make_mvc.mak
|
||||
|
||||
Patch 8.1.1315
|
||||
@ -33757,7 +33764,8 @@ Files: src/undo.c
|
||||
|
||||
Patch 8.1.1317
|
||||
Problem: Output from Travis can be improved.
|
||||
Solution: Add section headers. Handle errors better. (closes #4098)
|
||||
Solution: Add section headers. Handle errors better. (Ozaki Kiichi,
|
||||
closes #4098)
|
||||
Files: .travis.yml, configure
|
||||
|
||||
Patch 8.1.1318
|
||||
@ -33790,7 +33798,7 @@ Files: runtime/doc/eval.txt, runtime/doc/usr_41.txt,
|
||||
|
||||
Patch 8.1.1322
|
||||
Problem: Cygwin makefile is not nicely indented.
|
||||
Solution: Addjust spaces in preprocessor directives. (Ken Takata)
|
||||
Solution: Adjust spaces in preprocessor directives. (Ken Takata)
|
||||
Files: src/Make_cyg_ming.mak
|
||||
|
||||
Patch 8.1.1323
|
||||
@ -34028,7 +34036,7 @@ Files: src/ex_cmds.c, src/testdir/test_textprop.vim, src/vim.h,
|
||||
|
||||
Patch 8.1.1360 (after Patch 8.1.1345)
|
||||
Problem: Buffer left 'nomodifiable' after :substitute. (Ingo Karkat)
|
||||
Solution: Save the value of 'modifiable' earlier' (Christian Brabandt,
|
||||
Solution: Save the value of 'modifiable' earlier. (Christian Brabandt,
|
||||
closes #4403)
|
||||
Files: src/ex_cmds.c, src/testdir/test_substitute.vim
|
||||
|
||||
@ -34098,7 +34106,7 @@ Patch 8.1.1371
|
||||
Problem: Cannot recover from a swap file.
|
||||
Solution: Do not expand environment variables in the swap file name.
|
||||
Do not check the extension when we already know a file is a swap
|
||||
file. (Ken Takata, closes 4415, closes #4369)
|
||||
file. (Ken Takata, closes #4415, closes #4369)
|
||||
Files: src/buffer.c, src/ex_cmds.c, src/ex_cmds2.c, src/ex_docmd.c,
|
||||
src/gui.c, src/if_cscope.c, src/main.c, src/memline.c,
|
||||
src/misc1.c, src/proto/memline.pro, src/proto/misc1.pro,
|
||||
@ -34109,7 +34117,7 @@ Patch 8.1.1372
|
||||
Problem: When evaluating 'statusline' the current window is unknown.
|
||||
(Daniel Hahler)
|
||||
Solution: Set "g:actual_curwin" for %{} items. Set "g:statusline_winid"
|
||||
when evaluationg %!. (closes #4406, closes #3299)
|
||||
when evaluating %!. (closes #4406, closes #3299)
|
||||
Files: src/buffer.c, runtime/doc/options.txt,
|
||||
src/testdir/test_statusline.vim
|
||||
|
||||
@ -34154,13 +34162,13 @@ Files: src/fileio.c, src/testdir/test_filechanged.vim
|
||||
|
||||
Patch 8.1.1380
|
||||
Problem: MS-Windows building VIMDLL with MSVC: SUBSYSTEM is not set.
|
||||
Solution: Invert condition. (closes #4422)
|
||||
Solution: Invert condition. (Ken Takata, closes #4422)
|
||||
Files: src/Make_mvc.mak
|
||||
|
||||
Patch 8.1.1381
|
||||
Problem: MS-Windows: missing build dependency.
|
||||
Solution: Make gui_dwrite.cpp depend on gui_dwrite.h. (Ken Takata,
|
||||
closes #4423
|
||||
closes #4423)
|
||||
Files: src/Make_cyg_ming.mak, src/Make_mvc.mak
|
||||
|
||||
Patch 8.1.1382
|
||||
@ -34202,7 +34210,7 @@ Solution: Use STRLEN() instead of strlen().
|
||||
Files: src/fileio.c
|
||||
|
||||
Patch 8.1.1386
|
||||
Problem: Unessesary type casts for lalloc().
|
||||
Problem: Unnecessary type casts for lalloc().
|
||||
Solution: Remove type casts. Change lalloc(size, TRUE) to alloc(size).
|
||||
Files: src/buffer.c, src/change.c, src/channel.c, src/diff.c, src/edit.c,
|
||||
src/eval.c, src/ex_cmds.c, src/ex_getln.c, src/fileio.c,
|
||||
|
@ -1,4 +1,4 @@
|
||||
*windows.txt* For Vim version 8.1. Last change: 2019 May 18
|
||||
*windows.txt* For Vim version 8.1. Last change: 2019 May 30
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -1030,6 +1030,13 @@ list of buffers. |unlisted-buffer|
|
||||
thus you can always go to a specific buffer with ":buffer N"
|
||||
or "N CTRL-^", where N is the buffer number.
|
||||
|
||||
For the file name these special values are used:
|
||||
[Prompt] |prompt-buffer|
|
||||
[Popup] buffer of a |popup-window|
|
||||
[Scratch] 'buftype' is "nofile"
|
||||
[No Name] no file name specified
|
||||
For a |terminal-window| buffer the status is used.
|
||||
|
||||
Indicators (chars in the same column are mutually exclusive):
|
||||
u an unlisted buffer (only displayed when [!] is used)
|
||||
|unlisted-buffer|
|
||||
|
@ -3,13 +3,16 @@
|
||||
[Desktop Entry]
|
||||
# Translators: This is the Application Name used in the GVim desktop file
|
||||
Name[de]=GVim
|
||||
Name[eo]=GVim
|
||||
Name=GVim
|
||||
# Translators: This is the Generic Application Name used in the Vim desktop file
|
||||
GenericName[de]=Texteditor
|
||||
GenericName[eo]=Tekstoredaktilo
|
||||
GenericName[ja]=テキストエディタ
|
||||
GenericName=Text Editor
|
||||
# Translators: This is the comment used in the Vim desktop file
|
||||
Comment[de]=Textdateien bearbeiten
|
||||
Comment[eo]=Redakti tekstajn dosierojn
|
||||
Comment[ja]=テキストファイルを編集します
|
||||
Comment=Edit text files
|
||||
# The translations should come from the po file. Leave them here for now, they will
|
||||
@ -92,10 +95,12 @@ Terminal=false
|
||||
Type=Application
|
||||
# Translators: Search terms to find this application. Do NOT change the semicolons! The list MUST also end with a semicolon!
|
||||
Keywords[de]=Text;Editor;
|
||||
Keywords[eo]=Teksto;redaktilo;
|
||||
Keywords[ja]=テキスト;エディタ;
|
||||
Keywords=Text;editor;
|
||||
# Translators: This is the Icon file name. Do NOT translate
|
||||
Icon[de]=gvim
|
||||
Icon[eo]=gvim
|
||||
Icon=gvim
|
||||
Categories=Utility;TextEditor;
|
||||
StartupNotify=true
|
||||
|
@ -6,8 +6,8 @@
|
||||
" Contributor: Leonard Ehrenfried <leonard.ehrenfried@web.de>
|
||||
" Contributor: Karsten Hopp <karsten@redhat.com>
|
||||
" Originally: 2009-07-09
|
||||
" Last Change: 2017 Oct 25
|
||||
" SSH Version: 7.6p1
|
||||
" Last Change: 2019-05-31
|
||||
" SSH Version: 7.9p1
|
||||
"
|
||||
|
||||
" Setup
|
||||
@ -137,7 +137,8 @@ syn case ignore
|
||||
|
||||
|
||||
" Keywords
|
||||
syn keyword sshdconfigMatch Host User Group Address
|
||||
" Also includes RDomain, but that is a keyword.
|
||||
syn keyword sshdconfigMatch Host User Group Address LocalAddress LocalPort
|
||||
|
||||
syn keyword sshdconfigKeyword AcceptEnv
|
||||
syn keyword sshdconfigKeyword AddressFamily
|
||||
@ -150,8 +151,11 @@ syn keyword sshdconfigKeyword AuthenticationMethods
|
||||
syn keyword sshdconfigKeyword AuthorizedKeysFile
|
||||
syn keyword sshdconfigKeyword AuthorizedKeysCommand
|
||||
syn keyword sshdconfigKeyword AuthorizedKeysCommandUser
|
||||
syn keyword sshdconfigKeyword AuthorizedPrincipalsCommand
|
||||
syn keyword sshdconfigKeyword AuthorizedPrincipalsCommandUser
|
||||
syn keyword sshdconfigKeyword AuthorizedPrincipalsFile
|
||||
syn keyword sshdconfigKeyword Banner
|
||||
syn keyword sshdconfigKeyword CASignatureAlgorithms
|
||||
syn keyword sshdconfigKeyword ChallengeResponseAuthentication
|
||||
syn keyword sshdconfigKeyword ChrootDirectory
|
||||
syn keyword sshdconfigKeyword Ciphers
|
||||
@ -162,13 +166,17 @@ syn keyword sshdconfigKeyword DebianBanner
|
||||
syn keyword sshdconfigKeyword DenyGroups
|
||||
syn keyword sshdconfigKeyword DenyUsers
|
||||
syn keyword sshdconfigKeyword DisableForwarding
|
||||
syn keyword sshdconfigKeyword ExposeAuthInfo
|
||||
syn keyword sshdconfigKeyword FingerprintHash
|
||||
syn keyword sshdconfigKeyword ForceCommand
|
||||
syn keyword sshdconfigKeyword GatewayPorts
|
||||
syn keyword sshdconfigKeyword GSSAPIAuthentication
|
||||
syn keyword sshdconfigKeyword GSSAPICleanupCredentials
|
||||
syn keyword sshdconfigKeyword GSSAPIEnablek5users
|
||||
syn keyword sshdconfigKeyword GSSAPIKeyExchange
|
||||
syn keyword sshdconfigKeyword GSSAPIKexAlgorithms
|
||||
syn keyword sshdconfigKeyword GSSAPIStoreCredentialsOnRekey
|
||||
syn keyword sshdconfigKeyword GSSAPIStrictAcceptorCheck
|
||||
syn keyword sshdconfigKeyword GatewayPorts
|
||||
syn keyword sshdconfigKeyword HostCertificate
|
||||
syn keyword sshdconfigKeyword HostKey
|
||||
syn keyword sshdconfigKeyword HostKeyAgent
|
||||
@ -184,6 +192,8 @@ syn keyword sshdconfigKeyword KerberosAuthentication
|
||||
syn keyword sshdconfigKeyword KerberosGetAFSToken
|
||||
syn keyword sshdconfigKeyword KerberosOrLocalPasswd
|
||||
syn keyword sshdconfigKeyword KerberosTicketCleanup
|
||||
syn keyword sshdconfigKeyword KerberosUniqueCCache
|
||||
syn keyword sshdconfigKeyword KerberosUseKuserok
|
||||
syn keyword sshdconfigKeyword KexAlgorithms
|
||||
syn keyword sshdconfigKeyword KeyRegenerationInterval
|
||||
syn keyword sshdconfigKeyword ListenAddress
|
||||
@ -197,6 +207,7 @@ syn keyword sshdconfigKeyword MaxStartups
|
||||
syn keyword sshdconfigKeyword PasswordAuthentication
|
||||
syn keyword sshdconfigKeyword PermitBlacklistedKeys
|
||||
syn keyword sshdconfigKeyword PermitEmptyPasswords
|
||||
syn keyword sshdconfigKeyword PermitListen
|
||||
syn keyword sshdconfigKeyword PermitOpen
|
||||
syn keyword sshdconfigKeyword PermitRootLogin
|
||||
syn keyword sshdconfigKeyword PermitTTY
|
||||
@ -213,10 +224,14 @@ syn keyword sshdconfigKeyword PubkeyAuthentication
|
||||
syn keyword sshdconfigKeyword RSAAuthentication
|
||||
syn keyword sshdconfigKeyword RekeyLimit
|
||||
syn keyword sshdconfigKeyword RevokedKeys
|
||||
syn keyword sshdconfigKeyword RDomain
|
||||
syn keyword sshdconfigKeyword RhostsRSAAuthentication
|
||||
syn keyword sshdconfigKeyword ServerKeyBits
|
||||
syn keyword sshdconfigKeyword SetEnv
|
||||
syn keyword sshdconfigKeyword ShowPatchLevel
|
||||
syn keyword sshdconfigKeyword StrictModes
|
||||
syn keyword sshdconfigKeyword StreamLocalBindMask
|
||||
syn keyword sshdconfigKeyword StreamLocalBindUnlink
|
||||
syn keyword sshdconfigKeyword Subsystem
|
||||
syn keyword sshdconfigKeyword SyslogFacility
|
||||
syn keyword sshdconfigKeyword TCPKeepAlive
|
||||
@ -227,6 +242,7 @@ syn keyword sshdconfigKeyword UsePAM
|
||||
syn keyword sshdconfigKeyword VersionAddendum
|
||||
syn keyword sshdconfigKeyword X11DisplayOffset
|
||||
syn keyword sshdconfigKeyword X11Forwarding
|
||||
syn keyword sshdconfigKeyword X11MaxDisplays
|
||||
syn keyword sshdconfigKeyword X11UseLocalhost
|
||||
syn keyword sshdconfigKeyword XAuthLocation
|
||||
|
||||
|
@ -3,13 +3,16 @@
|
||||
[Desktop Entry]
|
||||
# Translators: This is the Application Name used in the Vim desktop file
|
||||
Name[de]=Vim
|
||||
Name[eo]=Vim
|
||||
Name=Vim
|
||||
# Translators: This is the Generic Application Name used in the Vim desktop file
|
||||
GenericName[de]=Texteditor
|
||||
GenericName[eo]=Tekstoredaktilo
|
||||
GenericName[ja]=テキストエディタ
|
||||
GenericName=Text Editor
|
||||
# Translators: This is the comment used in the Vim desktop file
|
||||
Comment[de]=Textdateien bearbeiten
|
||||
Comment[eo]=Redakti tekstajn dosierojn
|
||||
Comment[ja]=テキストファイルを編集します
|
||||
Comment=Edit text files
|
||||
# The translations should come from the po file. Leave them here for now, they will
|
||||
@ -89,10 +92,12 @@ Terminal=true
|
||||
Type=Application
|
||||
# Translators: Search terms to find this application. Do NOT change the semicolons! The list MUST also end with a semicolon!
|
||||
Keywords[de]=Text;Editor;
|
||||
Keywords[eo]=Teksto;redaktilo;
|
||||
Keywords[ja]=テキスト;エディタ;
|
||||
Keywords=Text;editor;
|
||||
# Translators: This is the Icon file name. Do NOT translate
|
||||
Icon[de]=gvim
|
||||
Icon[eo]=gvim
|
||||
Icon=gvim
|
||||
Categories=Utility;TextEditor;
|
||||
StartupNotify=false
|
||||
|
@ -2181,7 +2181,6 @@ test_libvterm:
|
||||
# These do not depend on the executable, compile it when needed.
|
||||
test1 \
|
||||
test_eval \
|
||||
test3 \
|
||||
test39 \
|
||||
test42 test44 test48 test49 \
|
||||
test52 test59 \
|
||||
|
@ -1349,7 +1349,7 @@ ex_doautoall(exarg_T *eap)
|
||||
*/
|
||||
FOR_ALL_BUFFERS(buf)
|
||||
{
|
||||
if (buf->b_ml.ml_mfp != NULL && !bt_popup(buf))
|
||||
if (buf->b_ml.ml_mfp != NULL)
|
||||
{
|
||||
// find a window for this buffer and save some values
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
@ -1612,8 +1612,6 @@ apply_autocmds(
|
||||
int force, // when TRUE, ignore autocmd_busy
|
||||
buf_T *buf) // buffer for <abuf>
|
||||
{
|
||||
if (bt_popup(buf))
|
||||
return FALSE;
|
||||
return apply_autocmds_group(event, fname, fname_io, force,
|
||||
AUGROUP_ALL, buf, NULL);
|
||||
}
|
||||
|
@ -862,7 +862,7 @@ free_buffer(buf_T *buf)
|
||||
#endif
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
vim_free(buf->b_prompt_text);
|
||||
free_callback(buf->b_prompt_callback, buf->b_prompt_partial);
|
||||
free_callback(&buf->b_prompt_callback);
|
||||
#endif
|
||||
|
||||
buf_hashtab_remove(buf);
|
||||
@ -5781,6 +5781,10 @@ buf_spname(buf_T *buf)
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
if (bt_prompt(buf))
|
||||
return (char_u *)_("[Prompt]");
|
||||
#endif
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
if (bt_popup(buf))
|
||||
return (char_u *)_("[Popup]");
|
||||
#endif
|
||||
return (char_u *)_("[Scratch]");
|
||||
}
|
||||
|
24
src/change.c
24
src/change.c
@ -270,36 +270,34 @@ may_record_change(
|
||||
void
|
||||
f_listener_add(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *callback;
|
||||
partial_T *partial;
|
||||
callback_T callback;
|
||||
listener_T *lnr;
|
||||
buf_T *buf = curbuf;
|
||||
|
||||
callback = get_callback(&argvars[0], &partial);
|
||||
if (callback == NULL)
|
||||
callback = get_callback(&argvars[0]);
|
||||
if (callback.cb_name == NULL)
|
||||
return;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
buf = get_buf_arg(&argvars[1]);
|
||||
if (buf == NULL)
|
||||
{
|
||||
free_callback(&callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lnr = ALLOC_CLEAR_ONE(listener_T);
|
||||
if (lnr == NULL)
|
||||
{
|
||||
free_callback(callback, partial);
|
||||
free_callback(&callback);
|
||||
return;
|
||||
}
|
||||
lnr->lr_next = buf->b_listener;
|
||||
buf->b_listener = lnr;
|
||||
|
||||
if (partial == NULL)
|
||||
lnr->lr_callback = vim_strsave(callback);
|
||||
else
|
||||
lnr->lr_callback = callback; // pointer into the partial
|
||||
lnr->lr_partial = partial;
|
||||
set_callback(&lnr->lr_callback, &callback);
|
||||
|
||||
lnr->lr_id = ++next_listener_id;
|
||||
rettv->vval.v_number = lnr->lr_id;
|
||||
@ -344,7 +342,7 @@ f_listener_remove(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
prev->lr_next = lnr->lr_next;
|
||||
else
|
||||
buf->b_listener = lnr->lr_next;
|
||||
free_callback(lnr->lr_callback, lnr->lr_partial);
|
||||
free_callback(&lnr->lr_callback);
|
||||
vim_free(lnr);
|
||||
}
|
||||
prev = lnr;
|
||||
@ -418,8 +416,8 @@ invoke_listeners(buf_T *buf)
|
||||
|
||||
for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
|
||||
{
|
||||
call_func(lnr->lr_callback, -1, &rettv,
|
||||
5, argv, NULL, 0L, 0L, &dummy, TRUE, lnr->lr_partial, NULL);
|
||||
call_callback(&lnr->lr_callback, -1, &rettv,
|
||||
5, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||
clear_tv(&rettv);
|
||||
}
|
||||
|
||||
|
278
src/channel.c
278
src/channel.c
@ -348,7 +348,7 @@ channel_still_useful(channel_T *channel)
|
||||
return FALSE;
|
||||
|
||||
/* If there is a close callback it may still need to be invoked. */
|
||||
if (channel->ch_close_cb != NULL)
|
||||
if (channel->ch_close_cb.cb_name != NULL)
|
||||
return TRUE;
|
||||
|
||||
/* If reading from or a buffer it's still useful. */
|
||||
@ -366,12 +366,12 @@ channel_still_useful(channel_T *channel)
|
||||
has_err_msg = channel->ch_part[PART_ERR].ch_fd != INVALID_FD
|
||||
|| channel->ch_part[PART_ERR].ch_head.rq_next != NULL
|
||||
|| channel->ch_part[PART_ERR].ch_json_head.jq_next != NULL;
|
||||
return (channel->ch_callback != NULL && (has_sock_msg
|
||||
return (channel->ch_callback.cb_name != NULL && (has_sock_msg
|
||||
|| has_out_msg || has_err_msg))
|
||||
|| ((channel->ch_part[PART_OUT].ch_callback != NULL
|
||||
|| ((channel->ch_part[PART_OUT].ch_callback.cb_name != NULL
|
||||
|| channel->ch_part[PART_OUT].ch_bufref.br_buf != NULL)
|
||||
&& has_out_msg)
|
||||
|| ((channel->ch_part[PART_ERR].ch_callback != NULL
|
||||
|| ((channel->ch_part[PART_ERR].ch_callback.cb_name != NULL
|
||||
|| channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL)
|
||||
&& has_err_msg);
|
||||
}
|
||||
@ -1178,29 +1178,36 @@ find_buffer(char_u *name, int err, int msg)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy callback from "src" to "dest", incrementing the refcounts.
|
||||
*/
|
||||
static void
|
||||
set_callback(
|
||||
char_u **cbp,
|
||||
partial_T **pp,
|
||||
char_u *callback,
|
||||
partial_T *partial)
|
||||
copy_callback(callback_T *dest, callback_T *src)
|
||||
{
|
||||
free_callback(*cbp, *pp);
|
||||
if (callback != NULL && *callback != NUL)
|
||||
dest->cb_partial = src->cb_partial;
|
||||
if (dest->cb_partial != NULL)
|
||||
{
|
||||
if (partial != NULL)
|
||||
*cbp = partial_name(partial);
|
||||
else
|
||||
{
|
||||
*cbp = vim_strsave(callback);
|
||||
func_ref(*cbp);
|
||||
}
|
||||
dest->cb_name = src->cb_name;
|
||||
dest->cb_free_name = FALSE;
|
||||
++dest->cb_partial->pt_refcount;
|
||||
}
|
||||
else
|
||||
*cbp = NULL;
|
||||
*pp = partial;
|
||||
if (partial != NULL)
|
||||
++partial->pt_refcount;
|
||||
{
|
||||
dest->cb_name = vim_strsave(src->cb_name);
|
||||
dest->cb_free_name = TRUE;
|
||||
func_ref(src->cb_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_set_callback(callback_T *cbp, callback_T *callback)
|
||||
{
|
||||
free_callback(cbp);
|
||||
|
||||
if (callback->cb_name != NULL && *callback->cb_name != NUL)
|
||||
copy_callback(cbp, callback);
|
||||
else
|
||||
cbp->cb_name = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1233,19 +1240,15 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
|
||||
channel->ch_part[PART_IN].ch_block_write = 1;
|
||||
|
||||
if (opt->jo_set & JO_CALLBACK)
|
||||
set_callback(&channel->ch_callback, &channel->ch_partial,
|
||||
opt->jo_callback, opt->jo_partial);
|
||||
free_set_callback(&channel->ch_callback, &opt->jo_callback);
|
||||
if (opt->jo_set & JO_OUT_CALLBACK)
|
||||
set_callback(&channel->ch_part[PART_OUT].ch_callback,
|
||||
&channel->ch_part[PART_OUT].ch_partial,
|
||||
opt->jo_out_cb, opt->jo_out_partial);
|
||||
free_set_callback(&channel->ch_part[PART_OUT].ch_callback,
|
||||
&opt->jo_out_cb);
|
||||
if (opt->jo_set & JO_ERR_CALLBACK)
|
||||
set_callback(&channel->ch_part[PART_ERR].ch_callback,
|
||||
&channel->ch_part[PART_ERR].ch_partial,
|
||||
opt->jo_err_cb, opt->jo_err_partial);
|
||||
free_set_callback(&channel->ch_part[PART_ERR].ch_callback,
|
||||
&opt->jo_err_cb);
|
||||
if (opt->jo_set & JO_CLOSE_CALLBACK)
|
||||
set_callback(&channel->ch_close_cb, &channel->ch_close_partial,
|
||||
opt->jo_close_cb, opt->jo_close_partial);
|
||||
free_set_callback(&channel->ch_close_cb, &opt->jo_close_cb);
|
||||
channel->ch_drop_never = opt->jo_drop_never;
|
||||
|
||||
if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
|
||||
@ -1349,8 +1352,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
|
||||
channel_set_req_callback(
|
||||
channel_T *channel,
|
||||
ch_part_T part,
|
||||
char_u *callback,
|
||||
partial_T *partial,
|
||||
callback_T *callback,
|
||||
int id)
|
||||
{
|
||||
cbq_T *head = &channel->ch_part[part].ch_cb_head;
|
||||
@ -1358,17 +1360,7 @@ channel_set_req_callback(
|
||||
|
||||
if (item != NULL)
|
||||
{
|
||||
item->cq_partial = partial;
|
||||
if (partial != NULL)
|
||||
{
|
||||
++partial->pt_refcount;
|
||||
item->cq_callback = callback;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->cq_callback = vim_strsave(callback);
|
||||
func_ref(item->cq_callback);
|
||||
}
|
||||
copy_callback(&item->cq_callback, callback);
|
||||
item->cq_seq_nr = id;
|
||||
item->cq_prev = head->cq_prev;
|
||||
head->cq_prev = item;
|
||||
@ -1638,8 +1630,7 @@ channel_write_new_lines(buf_T *buf)
|
||||
* This does not redraw but sets channel_need_redraw;
|
||||
*/
|
||||
static void
|
||||
invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
|
||||
typval_T *argv)
|
||||
invoke_callback(channel_T *channel, callback_T *callback, typval_T *argv)
|
||||
{
|
||||
typval_T rettv;
|
||||
int dummy;
|
||||
@ -1650,8 +1641,8 @@ invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
|
||||
argv[0].v_type = VAR_CHANNEL;
|
||||
argv[0].vval.v_channel = channel;
|
||||
|
||||
call_func(callback, -1, &rettv, 2, argv, NULL,
|
||||
0L, 0L, &dummy, TRUE, partial, NULL);
|
||||
call_callback(callback, -1, &rettv, 2, argv, NULL,
|
||||
0L, 0L, &dummy, TRUE, NULL);
|
||||
clear_tv(&rettv);
|
||||
channel_need_redraw = TRUE;
|
||||
}
|
||||
@ -2414,12 +2405,12 @@ invoke_one_time_callback(
|
||||
typval_T *argv)
|
||||
{
|
||||
ch_log(channel, "Invoking one-time callback %s",
|
||||
(char *)item->cq_callback);
|
||||
(char *)item->cq_callback.cb_name);
|
||||
/* Remove the item from the list first, if the callback
|
||||
* invokes ch_close() the list will be cleared. */
|
||||
remove_cb_node(cbhead, item);
|
||||
invoke_callback(channel, item->cq_callback, item->cq_partial, argv);
|
||||
free_callback(item->cq_callback, item->cq_partial);
|
||||
invoke_callback(channel, &item->cq_callback, argv);
|
||||
free_callback(&item->cq_callback);
|
||||
vim_free(item);
|
||||
}
|
||||
|
||||
@ -2553,8 +2544,7 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
|
||||
ch_mode_T ch_mode = ch_part->ch_mode;
|
||||
cbq_T *cbhead = &ch_part->ch_cb_head;
|
||||
cbq_T *cbitem;
|
||||
char_u *callback = NULL;
|
||||
partial_T *partial = NULL;
|
||||
callback_T *callback = NULL;
|
||||
buf_T *buffer = NULL;
|
||||
char_u *p;
|
||||
|
||||
@ -2567,20 +2557,11 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
|
||||
if (cbitem->cq_seq_nr == 0)
|
||||
break;
|
||||
if (cbitem != NULL)
|
||||
{
|
||||
callback = cbitem->cq_callback;
|
||||
partial = cbitem->cq_partial;
|
||||
}
|
||||
else if (ch_part->ch_callback != NULL)
|
||||
{
|
||||
callback = ch_part->ch_callback;
|
||||
partial = ch_part->ch_partial;
|
||||
}
|
||||
else
|
||||
{
|
||||
callback = channel->ch_callback;
|
||||
partial = channel->ch_partial;
|
||||
}
|
||||
callback = &cbitem->cq_callback;
|
||||
else if (ch_part->ch_callback.cb_name != NULL)
|
||||
callback = &ch_part->ch_callback;
|
||||
else if (channel->ch_callback.cb_name != NULL)
|
||||
callback = &channel->ch_callback;
|
||||
|
||||
buffer = ch_part->ch_bufref.br_buf;
|
||||
if (buffer != NULL && (!bufref_valid(&ch_part->ch_bufref)
|
||||
@ -2642,7 +2623,7 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
|
||||
{
|
||||
/* If there is a close callback it may use ch_read() to get the
|
||||
* messages. */
|
||||
if (channel->ch_close_cb == NULL && !channel->ch_drop_never)
|
||||
if (channel->ch_close_cb.cb_name == NULL && !channel->ch_drop_never)
|
||||
drop_messages(channel, part);
|
||||
return FALSE;
|
||||
}
|
||||
@ -2761,8 +2742,8 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
|
||||
{
|
||||
/* invoke the channel callback */
|
||||
ch_log(channel, "Invoking channel callback %s",
|
||||
(char *)callback);
|
||||
invoke_callback(channel, callback, partial, argv);
|
||||
(char *)callback->cb_name);
|
||||
invoke_callback(channel, callback, argv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2956,18 +2937,18 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
||||
ch_part_T part;
|
||||
|
||||
/* Invoke callbacks and flush buffers before the close callback. */
|
||||
if (channel->ch_close_cb != NULL)
|
||||
if (channel->ch_close_cb.cb_name != NULL)
|
||||
ch_log(channel,
|
||||
"Invoking callbacks and flushing buffers before closing");
|
||||
for (part = PART_SOCK; part < PART_IN; ++part)
|
||||
{
|
||||
if (channel->ch_close_cb != NULL
|
||||
if (channel->ch_close_cb.cb_name != NULL
|
||||
|| channel->ch_part[part].ch_bufref.br_buf != NULL)
|
||||
{
|
||||
/* Increment the refcount to avoid the channel being freed
|
||||
* halfway. */
|
||||
++channel->ch_refcount;
|
||||
if (channel->ch_close_cb == NULL)
|
||||
if (channel->ch_close_cb.cb_name == NULL)
|
||||
ch_log(channel, "flushing %s buffers before closing",
|
||||
part_names[part]);
|
||||
while (may_invoke_callback(channel, part))
|
||||
@ -2976,7 +2957,7 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
||||
}
|
||||
}
|
||||
|
||||
if (channel->ch_close_cb != NULL)
|
||||
if (channel->ch_close_cb.cb_name != NULL)
|
||||
{
|
||||
typval_T argv[1];
|
||||
typval_T rettv;
|
||||
@ -2986,19 +2967,16 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
||||
* halfway. */
|
||||
++channel->ch_refcount;
|
||||
ch_log(channel, "Invoking close callback %s",
|
||||
(char *)channel->ch_close_cb);
|
||||
(char *)channel->ch_close_cb.cb_name);
|
||||
argv[0].v_type = VAR_CHANNEL;
|
||||
argv[0].vval.v_channel = channel;
|
||||
call_func(channel->ch_close_cb, -1,
|
||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||
channel->ch_close_partial, NULL);
|
||||
call_callback(&channel->ch_close_cb, -1,
|
||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||
clear_tv(&rettv);
|
||||
channel_need_redraw = TRUE;
|
||||
|
||||
/* the callback is only called once */
|
||||
free_callback(channel->ch_close_cb, channel->ch_close_partial);
|
||||
channel->ch_close_cb = NULL;
|
||||
channel->ch_close_partial = NULL;
|
||||
free_callback(&channel->ch_close_cb);
|
||||
|
||||
if (channel_need_redraw)
|
||||
{
|
||||
@ -3061,7 +3039,7 @@ channel_clear_one(channel_T *channel, ch_part_T part)
|
||||
cbq_T *node = cb_head->cq_next;
|
||||
|
||||
remove_cb_node(cb_head, node);
|
||||
free_callback(node->cq_callback, node->cq_partial);
|
||||
free_callback(&node->cq_callback);
|
||||
vim_free(node);
|
||||
}
|
||||
|
||||
@ -3071,9 +3049,7 @@ channel_clear_one(channel_T *channel, ch_part_T part)
|
||||
remove_json_node(json_head, json_head->jq_next);
|
||||
}
|
||||
|
||||
free_callback(ch_part->ch_callback, ch_part->ch_partial);
|
||||
ch_part->ch_callback = NULL;
|
||||
ch_part->ch_partial = NULL;
|
||||
free_callback(&ch_part->ch_callback);
|
||||
|
||||
while (ch_part->ch_writeque.wq_next != NULL)
|
||||
remove_from_writeque(&ch_part->ch_writeque,
|
||||
@ -3092,12 +3068,8 @@ channel_clear(channel_T *channel)
|
||||
channel_clear_one(channel, PART_OUT);
|
||||
channel_clear_one(channel, PART_ERR);
|
||||
channel_clear_one(channel, PART_IN);
|
||||
free_callback(channel->ch_callback, channel->ch_partial);
|
||||
channel->ch_callback = NULL;
|
||||
channel->ch_partial = NULL;
|
||||
free_callback(channel->ch_close_cb, channel->ch_close_partial);
|
||||
channel->ch_close_cb = NULL;
|
||||
channel->ch_close_partial = NULL;
|
||||
free_callback(&channel->ch_callback);
|
||||
free_callback(&channel->ch_close_cb);
|
||||
}
|
||||
|
||||
#if defined(EXITFREE) || defined(PROTO)
|
||||
@ -3991,19 +3963,18 @@ send_common(
|
||||
/* Set the callback. An empty callback means no callback and not reading
|
||||
* the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not
|
||||
* allowed. */
|
||||
if (opt->jo_callback != NULL && *opt->jo_callback != NUL)
|
||||
if (opt->jo_callback.cb_name != NULL && *opt->jo_callback.cb_name != NUL)
|
||||
{
|
||||
if (eval)
|
||||
{
|
||||
semsg(_("E917: Cannot use a callback with %s()"), fun);
|
||||
return NULL;
|
||||
}
|
||||
channel_set_req_callback(channel, *part_read,
|
||||
opt->jo_callback, opt->jo_partial, id);
|
||||
channel_set_req_callback(channel, *part_read, &opt->jo_callback, id);
|
||||
}
|
||||
|
||||
if (channel_send(channel, part_send, text, len, fun) == OK
|
||||
&& opt->jo_callback == NULL)
|
||||
&& opt->jo_callback.cb_name == NULL)
|
||||
return channel;
|
||||
return NULL;
|
||||
}
|
||||
@ -4559,26 +4530,26 @@ clear_job_options(jobopt_T *opt)
|
||||
void
|
||||
free_job_options(jobopt_T *opt)
|
||||
{
|
||||
if (opt->jo_partial != NULL)
|
||||
partial_unref(opt->jo_partial);
|
||||
else if (opt->jo_callback != NULL)
|
||||
func_unref(opt->jo_callback);
|
||||
if (opt->jo_out_partial != NULL)
|
||||
partial_unref(opt->jo_out_partial);
|
||||
else if (opt->jo_out_cb != NULL)
|
||||
func_unref(opt->jo_out_cb);
|
||||
if (opt->jo_err_partial != NULL)
|
||||
partial_unref(opt->jo_err_partial);
|
||||
else if (opt->jo_err_cb != NULL)
|
||||
func_unref(opt->jo_err_cb);
|
||||
if (opt->jo_close_partial != NULL)
|
||||
partial_unref(opt->jo_close_partial);
|
||||
else if (opt->jo_close_cb != NULL)
|
||||
func_unref(opt->jo_close_cb);
|
||||
if (opt->jo_exit_partial != NULL)
|
||||
partial_unref(opt->jo_exit_partial);
|
||||
else if (opt->jo_exit_cb != NULL)
|
||||
func_unref(opt->jo_exit_cb);
|
||||
if (opt->jo_callback.cb_partial != NULL)
|
||||
partial_unref(opt->jo_callback.cb_partial);
|
||||
else if (opt->jo_callback.cb_name != NULL)
|
||||
func_unref(opt->jo_callback.cb_name);
|
||||
if (opt->jo_out_cb.cb_partial != NULL)
|
||||
partial_unref(opt->jo_out_cb.cb_partial);
|
||||
else if (opt->jo_out_cb.cb_name != NULL)
|
||||
func_unref(opt->jo_out_cb.cb_name);
|
||||
if (opt->jo_err_cb.cb_partial != NULL)
|
||||
partial_unref(opt->jo_err_cb.cb_partial);
|
||||
else if (opt->jo_err_cb.cb_name != NULL)
|
||||
func_unref(opt->jo_err_cb.cb_name);
|
||||
if (opt->jo_close_cb.cb_partial != NULL)
|
||||
partial_unref(opt->jo_close_cb.cb_partial);
|
||||
else if (opt->jo_close_cb.cb_name != NULL)
|
||||
func_unref(opt->jo_close_cb.cb_name);
|
||||
if (opt->jo_exit_cb.cb_partial != NULL)
|
||||
partial_unref(opt->jo_exit_cb.cb_partial);
|
||||
else if (opt->jo_exit_cb.cb_name != NULL)
|
||||
func_unref(opt->jo_exit_cb.cb_name);
|
||||
if (opt->jo_env != NULL)
|
||||
dict_unref(opt->jo_env);
|
||||
}
|
||||
@ -4771,8 +4742,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
|
||||
if (!(supported & JO_CALLBACK))
|
||||
break;
|
||||
opt->jo_set |= JO_CALLBACK;
|
||||
opt->jo_callback = get_callback(item, &opt->jo_partial);
|
||||
if (opt->jo_callback == NULL)
|
||||
opt->jo_callback = get_callback(item);
|
||||
if (opt->jo_callback.cb_name == NULL)
|
||||
{
|
||||
semsg(_(e_invargval), "callback");
|
||||
return FAIL;
|
||||
@ -4783,8 +4754,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
|
||||
if (!(supported & JO_OUT_CALLBACK))
|
||||
break;
|
||||
opt->jo_set |= JO_OUT_CALLBACK;
|
||||
opt->jo_out_cb = get_callback(item, &opt->jo_out_partial);
|
||||
if (opt->jo_out_cb == NULL)
|
||||
opt->jo_out_cb = get_callback(item);
|
||||
if (opt->jo_out_cb.cb_name == NULL)
|
||||
{
|
||||
semsg(_(e_invargval), "out_cb");
|
||||
return FAIL;
|
||||
@ -4795,8 +4766,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
|
||||
if (!(supported & JO_ERR_CALLBACK))
|
||||
break;
|
||||
opt->jo_set |= JO_ERR_CALLBACK;
|
||||
opt->jo_err_cb = get_callback(item, &opt->jo_err_partial);
|
||||
if (opt->jo_err_cb == NULL)
|
||||
opt->jo_err_cb = get_callback(item);
|
||||
if (opt->jo_err_cb.cb_name == NULL)
|
||||
{
|
||||
semsg(_(e_invargval), "err_cb");
|
||||
return FAIL;
|
||||
@ -4807,8 +4778,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
|
||||
if (!(supported & JO_CLOSE_CALLBACK))
|
||||
break;
|
||||
opt->jo_set |= JO_CLOSE_CALLBACK;
|
||||
opt->jo_close_cb = get_callback(item, &opt->jo_close_partial);
|
||||
if (opt->jo_close_cb == NULL)
|
||||
opt->jo_close_cb = get_callback(item);
|
||||
if (opt->jo_close_cb.cb_name == NULL)
|
||||
{
|
||||
semsg(_(e_invargval), "close_cb");
|
||||
return FAIL;
|
||||
@ -4833,8 +4804,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
|
||||
if (!(supported & JO_EXIT_CB))
|
||||
break;
|
||||
opt->jo_set |= JO_EXIT_CB;
|
||||
opt->jo_exit_cb = get_callback(item, &opt->jo_exit_partial);
|
||||
if (opt->jo_exit_cb == NULL)
|
||||
opt->jo_exit_cb = get_callback(item);
|
||||
if (opt->jo_exit_cb.cb_name == NULL)
|
||||
{
|
||||
semsg(_(e_invargval), "exit_cb");
|
||||
return FAIL;
|
||||
@ -5201,7 +5172,7 @@ job_free_contents(job_T *job)
|
||||
#ifdef MSWIN
|
||||
vim_free(job->jv_tty_type);
|
||||
#endif
|
||||
free_callback(job->jv_exit_cb, job->jv_exit_partial);
|
||||
free_callback(&job->jv_exit_cb);
|
||||
if (job->jv_argv != NULL)
|
||||
{
|
||||
for (i = 0; job->jv_argv[i] != NULL; i++)
|
||||
@ -5289,7 +5260,7 @@ job_free_all(void)
|
||||
job_need_end_check(job_T *job)
|
||||
{
|
||||
return job->jv_status == JOB_STARTED
|
||||
&& (job->jv_stoponexit != NULL || job->jv_exit_cb != NULL);
|
||||
&& (job->jv_stoponexit != NULL || job->jv_exit_cb.cb_name != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5465,22 +5436,22 @@ job_cleanup(job_T *job)
|
||||
if (job->jv_channel != NULL)
|
||||
ch_close_part(job->jv_channel, PART_IN);
|
||||
|
||||
if (job->jv_exit_cb != NULL)
|
||||
if (job->jv_exit_cb.cb_name != NULL)
|
||||
{
|
||||
typval_T argv[3];
|
||||
typval_T rettv;
|
||||
int dummy;
|
||||
|
||||
/* Invoke the exit callback. Make sure the refcount is > 0. */
|
||||
ch_log(job->jv_channel, "Invoking exit callback %s", job->jv_exit_cb);
|
||||
ch_log(job->jv_channel, "Invoking exit callback %s",
|
||||
job->jv_exit_cb.cb_name);
|
||||
++job->jv_refcount;
|
||||
argv[0].v_type = VAR_JOB;
|
||||
argv[0].vval.v_job = job;
|
||||
argv[1].v_type = VAR_NUMBER;
|
||||
argv[1].vval.v_number = job->jv_exitval;
|
||||
call_func(job->jv_exit_cb, -1,
|
||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||
job->jv_exit_partial, NULL);
|
||||
call_callback(&job->jv_exit_cb, -1,
|
||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||
clear_tv(&rettv);
|
||||
--job->jv_refcount;
|
||||
channel_need_redraw = TRUE;
|
||||
@ -5622,26 +5593,14 @@ job_set_options(job_T *job, jobopt_T *opt)
|
||||
}
|
||||
if (opt->jo_set & JO_EXIT_CB)
|
||||
{
|
||||
free_callback(job->jv_exit_cb, job->jv_exit_partial);
|
||||
if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL)
|
||||
free_callback(&job->jv_exit_cb);
|
||||
if (opt->jo_exit_cb.cb_name == NULL || *opt->jo_exit_cb.cb_name == NUL)
|
||||
{
|
||||
job->jv_exit_cb = NULL;
|
||||
job->jv_exit_partial = NULL;
|
||||
job->jv_exit_cb.cb_name = NULL;
|
||||
job->jv_exit_cb.cb_partial = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
job->jv_exit_partial = opt->jo_exit_partial;
|
||||
if (job->jv_exit_partial != NULL)
|
||||
{
|
||||
job->jv_exit_cb = opt->jo_exit_cb;
|
||||
++job->jv_exit_partial->pt_refcount;
|
||||
}
|
||||
else
|
||||
{
|
||||
job->jv_exit_cb = vim_strsave(opt->jo_exit_cb);
|
||||
func_ref(job->jv_exit_cb);
|
||||
}
|
||||
}
|
||||
copy_callback(&job->jv_exit_cb, &opt->jo_exit_cb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5959,7 +5918,7 @@ job_info(job_T *job, dict_T *dict)
|
||||
dict_add_string(dict, "tty_out", job->jv_tty_out);
|
||||
|
||||
dict_add_number(dict, "exitval", job->jv_exitval);
|
||||
dict_add_string(dict, "exit_cb", job->jv_exit_cb);
|
||||
dict_add_string(dict, "exit_cb", job->jv_exit_cb.cb_name);
|
||||
dict_add_string(dict, "stoponexit", job->jv_stoponexit);
|
||||
#ifdef UNIX
|
||||
dict_add_string(dict, "termsig", job->jv_termsig);
|
||||
@ -6059,7 +6018,8 @@ invoke_prompt_callback(void)
|
||||
curwin->w_cursor.lnum = lnum + 1;
|
||||
curwin->w_cursor.col = 0;
|
||||
|
||||
if (curbuf->b_prompt_callback == NULL || *curbuf->b_prompt_callback == NUL)
|
||||
if (curbuf->b_prompt_callback.cb_name == NULL
|
||||
|| *curbuf->b_prompt_callback.cb_name == NUL)
|
||||
return;
|
||||
text = ml_get(lnum);
|
||||
prompt = prompt_text();
|
||||
@ -6069,9 +6029,8 @@ invoke_prompt_callback(void)
|
||||
argv[0].vval.v_string = vim_strsave(text);
|
||||
argv[1].v_type = VAR_UNKNOWN;
|
||||
|
||||
call_func(curbuf->b_prompt_callback, -1,
|
||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||
curbuf->b_prompt_partial, NULL);
|
||||
call_callback(&curbuf->b_prompt_callback, -1,
|
||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||
clear_tv(&argv[0]);
|
||||
clear_tv(&rettv);
|
||||
}
|
||||
@ -6086,15 +6045,14 @@ invoke_prompt_interrupt(void)
|
||||
int dummy;
|
||||
typval_T argv[1];
|
||||
|
||||
if (curbuf->b_prompt_interrupt == NULL
|
||||
|| *curbuf->b_prompt_interrupt == NUL)
|
||||
if (curbuf->b_prompt_interrupt.cb_name == NULL
|
||||
|| *curbuf->b_prompt_interrupt.cb_name == NUL)
|
||||
return FALSE;
|
||||
argv[0].v_type = VAR_UNKNOWN;
|
||||
|
||||
got_int = FALSE; // don't skip executing commands
|
||||
call_func(curbuf->b_prompt_interrupt, -1,
|
||||
&rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||
curbuf->b_prompt_int_partial, NULL);
|
||||
call_callback(&curbuf->b_prompt_interrupt, -1,
|
||||
&rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||
clear_tv(&rettv);
|
||||
return TRUE;
|
||||
}
|
||||
|
21
src/eval.c
21
src/eval.c
@ -5920,10 +5920,10 @@ set_ref_in_item(
|
||||
dtv.vval.v_channel = job->jv_channel;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
}
|
||||
if (job->jv_exit_partial != NULL)
|
||||
if (job->jv_exit_cb.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = job->jv_exit_partial;
|
||||
dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
}
|
||||
}
|
||||
@ -5946,29 +5946,30 @@ set_ref_in_item(
|
||||
set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
|
||||
for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
|
||||
cq = cq->cq_next)
|
||||
if (cq->cq_partial != NULL)
|
||||
if (cq->cq_callback.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = cq->cq_partial;
|
||||
dtv.vval.v_partial = cq->cq_callback.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
}
|
||||
if (ch->ch_part[part].ch_partial != NULL)
|
||||
if (ch->ch_part[part].ch_callback.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = ch->ch_part[part].ch_partial;
|
||||
dtv.vval.v_partial =
|
||||
ch->ch_part[part].ch_callback.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
}
|
||||
}
|
||||
if (ch->ch_partial != NULL)
|
||||
if (ch->ch_callback.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = ch->ch_partial;
|
||||
dtv.vval.v_partial = ch->ch_callback.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
}
|
||||
if (ch->ch_close_partial != NULL)
|
||||
if (ch->ch_close_cb.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = ch->ch_close_partial;
|
||||
dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
}
|
||||
}
|
||||
|
170
src/evalfunc.c
170
src/evalfunc.c
@ -809,10 +809,11 @@ static struct fst
|
||||
{"perleval", 1, 1, f_perleval},
|
||||
#endif
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
{"popup_atcursor", 2, 2, f_popup_atcursor},
|
||||
{"popup_close", 1, 1, f_popup_close},
|
||||
{"popup_create", 2, 2, f_popup_create},
|
||||
{"popup_getoptions", 1, 1, f_popup_getoptions},
|
||||
{"popup_getposition", 1, 1, f_popup_getposition},
|
||||
{"popup_getpos", 1, 1, f_popup_getpos},
|
||||
{"popup_hide", 1, 1, f_popup_hide},
|
||||
{"popup_move", 2, 2, f_popup_move},
|
||||
{"popup_show", 1, 1, f_popup_show},
|
||||
@ -6116,19 +6117,18 @@ f_win_execute(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
int id = (int)tv_get_number(argvars);
|
||||
win_T *wp = win_id2wp(id);
|
||||
win_T *save_curwin = curwin;
|
||||
win_T *save_curwin;
|
||||
tabpage_T *save_curtab;
|
||||
|
||||
if (wp != NULL)
|
||||
{
|
||||
curwin = wp;
|
||||
curbuf = curwin->w_buffer;
|
||||
check_cursor();
|
||||
execute_common(argvars, rettv, 1);
|
||||
if (win_valid(save_curwin))
|
||||
if (switch_win_noblock(&save_curwin, &save_curtab, wp, curtab, TRUE)
|
||||
== OK)
|
||||
{
|
||||
curwin = save_curwin;
|
||||
curbuf = curwin->w_buffer;
|
||||
check_cursor();
|
||||
execute_common(argvars, rettv, 1);
|
||||
}
|
||||
restore_win_noblock(save_curwin, save_curtab, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9200,8 +9200,7 @@ f_printf(typval_T *argvars, typval_T *rettv)
|
||||
f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
buf_T *buf;
|
||||
char_u *callback;
|
||||
partial_T *partial;
|
||||
callback_T callback;
|
||||
|
||||
if (check_secure())
|
||||
return;
|
||||
@ -9209,17 +9208,12 @@ f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
callback = get_callback(&argvars[1], &partial);
|
||||
if (callback == NULL)
|
||||
callback = get_callback(&argvars[1]);
|
||||
if (callback.cb_name == NULL)
|
||||
return;
|
||||
|
||||
free_callback(buf->b_prompt_callback, buf->b_prompt_partial);
|
||||
if (partial == NULL)
|
||||
buf->b_prompt_callback = vim_strsave(callback);
|
||||
else
|
||||
/* pointer into the partial */
|
||||
buf->b_prompt_callback = callback;
|
||||
buf->b_prompt_partial = partial;
|
||||
free_callback(&buf->b_prompt_callback);
|
||||
set_callback(&buf->b_prompt_callback, &callback);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -9229,8 +9223,7 @@ f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
buf_T *buf;
|
||||
char_u *callback;
|
||||
partial_T *partial;
|
||||
callback_T callback;
|
||||
|
||||
if (check_secure())
|
||||
return;
|
||||
@ -9238,17 +9231,12 @@ f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
callback = get_callback(&argvars[1], &partial);
|
||||
if (callback == NULL)
|
||||
callback = get_callback(&argvars[1]);
|
||||
if (callback.cb_name == NULL)
|
||||
return;
|
||||
|
||||
free_callback(buf->b_prompt_interrupt, buf->b_prompt_int_partial);
|
||||
if (partial == NULL)
|
||||
buf->b_prompt_interrupt = vim_strsave(callback);
|
||||
else
|
||||
/* pointer into the partial */
|
||||
buf->b_prompt_interrupt = callback;
|
||||
buf->b_prompt_int_partial = partial;
|
||||
free_callback(&buf->b_prompt_interrupt);
|
||||
set_callback(&buf->b_prompt_interrupt, &callback);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -14631,42 +14619,104 @@ f_test_settime(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
/*
|
||||
* Get a callback from "arg". It can be a Funcref or a function name.
|
||||
* When "arg" is zero return an empty string.
|
||||
* Return NULL for an invalid argument.
|
||||
* "cb_name" is not allocated.
|
||||
* "cb_name" is set to NULL for an invalid argument.
|
||||
*/
|
||||
char_u *
|
||||
get_callback(typval_T *arg, partial_T **pp)
|
||||
callback_T
|
||||
get_callback(typval_T *arg)
|
||||
{
|
||||
callback_T res;
|
||||
|
||||
res.cb_free_name = FALSE;
|
||||
if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL)
|
||||
{
|
||||
*pp = arg->vval.v_partial;
|
||||
++(*pp)->pt_refcount;
|
||||
return partial_name(*pp);
|
||||
res.cb_partial = arg->vval.v_partial;
|
||||
++res.cb_partial->pt_refcount;
|
||||
res.cb_name = partial_name(res.cb_partial);
|
||||
}
|
||||
*pp = NULL;
|
||||
if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
|
||||
else
|
||||
{
|
||||
func_ref(arg->vval.v_string);
|
||||
return arg->vval.v_string;
|
||||
res.cb_partial = NULL;
|
||||
if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
|
||||
{
|
||||
// Note that we don't make a copy of the string.
|
||||
res.cb_name = arg->vval.v_string;
|
||||
func_ref(res.cb_name);
|
||||
}
|
||||
else if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
|
||||
{
|
||||
res.cb_name = (char_u *)"";
|
||||
}
|
||||
else
|
||||
{
|
||||
emsg(_("E921: Invalid callback argument"));
|
||||
res.cb_name = NULL;
|
||||
}
|
||||
}
|
||||
if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
|
||||
return (char_u *)"";
|
||||
emsg(_("E921: Invalid callback argument"));
|
||||
return NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unref/free "callback" and "partial" returned by get_callback().
|
||||
* Copy a callback into a typval_T.
|
||||
*/
|
||||
void
|
||||
free_callback(char_u *callback, partial_T *partial)
|
||||
put_callback(callback_T *cb, typval_T *tv)
|
||||
{
|
||||
if (partial != NULL)
|
||||
partial_unref(partial);
|
||||
else if (callback != NULL)
|
||||
if (cb->cb_partial != NULL)
|
||||
{
|
||||
func_unref(callback);
|
||||
vim_free(callback);
|
||||
tv->v_type = VAR_PARTIAL;
|
||||
tv->vval.v_partial = cb->cb_partial;
|
||||
++tv->vval.v_partial->pt_refcount;
|
||||
}
|
||||
else
|
||||
{
|
||||
tv->v_type = VAR_FUNC;
|
||||
tv->vval.v_string = vim_strsave(cb->cb_name);
|
||||
func_ref(cb->cb_name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a copy of "src" into "dest", allocating the function name if needed,
|
||||
* without incrementing the refcount.
|
||||
*/
|
||||
void
|
||||
set_callback(callback_T *dest, callback_T *src)
|
||||
{
|
||||
if (src->cb_partial == NULL)
|
||||
{
|
||||
// just a function name, make a copy
|
||||
dest->cb_name = vim_strsave(src->cb_name);
|
||||
dest->cb_free_name = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// cb_name is a pointer into cb_partial
|
||||
dest->cb_name = src->cb_name;
|
||||
dest->cb_free_name = FALSE;
|
||||
}
|
||||
dest->cb_partial = src->cb_partial;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unref/free "callback" returned by get_callback() or set_callback().
|
||||
*/
|
||||
void
|
||||
free_callback(callback_T *callback)
|
||||
{
|
||||
if (callback->cb_partial != NULL)
|
||||
{
|
||||
partial_unref(callback->cb_partial);
|
||||
callback->cb_partial = NULL;
|
||||
}
|
||||
else if (callback->cb_name != NULL)
|
||||
func_unref(callback->cb_name);
|
||||
if (callback->cb_free_name)
|
||||
{
|
||||
vim_free(callback->cb_name);
|
||||
callback->cb_free_name = FALSE;
|
||||
}
|
||||
callback->cb_name = NULL;
|
||||
}
|
||||
|
||||
#ifdef FEAT_TIMERS
|
||||
@ -14723,9 +14773,8 @@ f_timer_start(typval_T *argvars, typval_T *rettv)
|
||||
long msec = (long)tv_get_number(&argvars[0]);
|
||||
timer_T *timer;
|
||||
int repeat = 0;
|
||||
char_u *callback;
|
||||
callback_T callback;
|
||||
dict_T *dict;
|
||||
partial_T *partial;
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
if (check_secure())
|
||||
@ -14742,21 +14791,16 @@ f_timer_start(typval_T *argvars, typval_T *rettv)
|
||||
repeat = dict_get_number(dict, (char_u *)"repeat");
|
||||
}
|
||||
|
||||
callback = get_callback(&argvars[1], &partial);
|
||||
if (callback == NULL)
|
||||
callback = get_callback(&argvars[1]);
|
||||
if (callback.cb_name == NULL)
|
||||
return;
|
||||
|
||||
timer = create_timer(msec, repeat);
|
||||
if (timer == NULL)
|
||||
free_callback(callback, partial);
|
||||
free_callback(&callback);
|
||||
else
|
||||
{
|
||||
if (partial == NULL)
|
||||
timer->tr_callback = vim_strsave(callback);
|
||||
else
|
||||
/* pointer into the partial */
|
||||
timer->tr_callback = callback;
|
||||
timer->tr_partial = partial;
|
||||
set_callback(&timer->tr_callback, &callback);
|
||||
rettv->vval.v_number = (varnumber_T)timer->tr_id;
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ remove_timer(timer_T *timer)
|
||||
static void
|
||||
free_timer(timer_T *timer)
|
||||
{
|
||||
free_callback(timer->tr_callback, timer->tr_partial);
|
||||
free_callback(&timer->tr_callback);
|
||||
vim_free(timer);
|
||||
}
|
||||
|
||||
@ -325,9 +325,8 @@ timer_callback(timer_T *timer)
|
||||
argv[0].vval.v_number = (varnumber_T)timer->tr_id;
|
||||
argv[1].v_type = VAR_UNKNOWN;
|
||||
|
||||
call_func(timer->tr_callback, -1,
|
||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
|
||||
timer->tr_partial, NULL);
|
||||
call_callback(&timer->tr_callback, -1,
|
||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||
clear_tv(&rettv);
|
||||
}
|
||||
|
||||
@ -542,17 +541,8 @@ add_timer_info(typval_T *rettv, timer_T *timer)
|
||||
{
|
||||
if (dict_add(dict, di) == FAIL)
|
||||
vim_free(di);
|
||||
else if (timer->tr_partial != NULL)
|
||||
{
|
||||
di->di_tv.v_type = VAR_PARTIAL;
|
||||
di->di_tv.vval.v_partial = timer->tr_partial;
|
||||
++timer->tr_partial->pt_refcount;
|
||||
}
|
||||
else
|
||||
{
|
||||
di->di_tv.v_type = VAR_FUNC;
|
||||
di->di_tv.vval.v_string = vim_strsave(timer->tr_callback);
|
||||
}
|
||||
put_callback(&timer->tr_callback, &di->di_tv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -578,15 +568,15 @@ set_ref_in_timer(int copyID)
|
||||
|
||||
for (timer = first_timer; timer != NULL; timer = timer->tr_next)
|
||||
{
|
||||
if (timer->tr_partial != NULL)
|
||||
if (timer->tr_callback.cb_partial != NULL)
|
||||
{
|
||||
tv.v_type = VAR_PARTIAL;
|
||||
tv.vval.v_partial = timer->tr_partial;
|
||||
tv.vval.v_partial = timer->tr_callback.cb_partial;
|
||||
}
|
||||
else
|
||||
{
|
||||
tv.v_type = VAR_FUNC;
|
||||
tv.vval.v_string = timer->tr_callback;
|
||||
tv.vval.v_string = timer->tr_callback.cb_name;
|
||||
}
|
||||
abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
|
||||
}
|
||||
@ -1874,6 +1864,8 @@ do_argfile(exarg_T *eap, int argn)
|
||||
char_u *p;
|
||||
int old_arg_idx = curwin->w_arg_idx;
|
||||
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
if (argn < 0 || argn >= ARGCOUNT)
|
||||
{
|
||||
if (ARGCOUNT <= 1)
|
||||
|
@ -5452,6 +5452,8 @@ ex_doautocmd(exarg_T *eap)
|
||||
static void
|
||||
ex_bunload(exarg_T *eap)
|
||||
{
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
eap->errmsg = do_bufdel(
|
||||
eap->cmdidx == CMD_bdelete ? DOBUF_DEL
|
||||
: eap->cmdidx == CMD_bwipeout ? DOBUF_WIPE
|
||||
@ -5466,6 +5468,8 @@ ex_bunload(exarg_T *eap)
|
||||
static void
|
||||
ex_buffer(exarg_T *eap)
|
||||
{
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
if (*eap->arg)
|
||||
eap->errmsg = e_trailing;
|
||||
else
|
||||
@ -6768,6 +6772,9 @@ ex_splitview(exarg_T *eap)
|
||||
|| eap->cmdidx == CMD_tabfind
|
||||
|| eap->cmdidx == CMD_tabnew;
|
||||
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
|
||||
#ifdef FEAT_GUI
|
||||
need_mouse_correct = TRUE;
|
||||
#endif
|
||||
@ -6895,6 +6902,8 @@ ex_tabnext(exarg_T *eap)
|
||||
{
|
||||
int tab_number;
|
||||
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
switch (eap->cmdidx)
|
||||
{
|
||||
case CMD_tabfirst:
|
||||
@ -7146,6 +7155,8 @@ do_exedit(
|
||||
int need_hide;
|
||||
int exmode_was = exmode_active;
|
||||
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
/*
|
||||
* ":vi" command ends Ex mode.
|
||||
*/
|
||||
|
@ -1801,6 +1801,10 @@ vgetc(void)
|
||||
ui_remove_balloon();
|
||||
}
|
||||
#endif
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
if (popup_do_filter(c))
|
||||
c = K_IGNORE;
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
@ -339,3 +339,9 @@
|
||||
|
||||
/* Wether a command index indicates a user command. */
|
||||
#define IS_USER_CMDIDX(idx) ((int)(idx) < 0)
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
# define NOT_IN_POPUP_WINDOW not_in_popup_window()
|
||||
#else
|
||||
# define NOT_IN_POPUP_WINDOW 0
|
||||
#endif
|
||||
|
27
src/misc2.c
27
src/misc2.c
@ -2057,6 +2057,13 @@ ga_grow(garray_T *gap, int n)
|
||||
{
|
||||
if (n < gap->ga_growsize)
|
||||
n = gap->ga_growsize;
|
||||
|
||||
// A linear growth is very inefficient when the array grows big. This
|
||||
// is a compromise between allocating memory that won't be used and too
|
||||
// many copy operations. A factor of 1.5 seems reasonable.
|
||||
if (n < gap->ga_len / 2)
|
||||
n = gap->ga_len / 2;
|
||||
|
||||
new_len = gap->ga_itemsize * (gap->ga_len + n);
|
||||
pp = vim_realloc(gap->ga_data, new_len);
|
||||
if (pp == NULL)
|
||||
@ -2724,17 +2731,31 @@ get_special_key_name(int c, int modifiers)
|
||||
trans_special(
|
||||
char_u **srcp,
|
||||
char_u *dst,
|
||||
int keycode, /* prefer key code, e.g. K_DEL instead of DEL */
|
||||
int in_string) /* TRUE when inside a double quoted string */
|
||||
int keycode, // prefer key code, e.g. K_DEL instead of DEL
|
||||
int in_string) // TRUE when inside a double quoted string
|
||||
{
|
||||
int modifiers = 0;
|
||||
int key;
|
||||
int dlen = 0;
|
||||
|
||||
key = find_special_key(srcp, &modifiers, keycode, FALSE, in_string);
|
||||
if (key == 0)
|
||||
return 0;
|
||||
|
||||
return special_to_buf(key, modifiers, keycode, dst);
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the character sequence for "key" with "modifiers" into "dst" and return
|
||||
* the resulting length.
|
||||
* When "keycode" is TRUE prefer key code, e.g. K_DEL instead of DEL.
|
||||
* The sequence is not NUL terminated.
|
||||
* This is how characters in a string are encoded.
|
||||
*/
|
||||
int
|
||||
special_to_buf(int key, int modifiers, int keycode, char_u *dst)
|
||||
{
|
||||
int dlen = 0;
|
||||
|
||||
/* Put the appropriate modifier in a string */
|
||||
if (modifiers != 0)
|
||||
{
|
||||
|
1178
src/po/eo.po
1178
src/po/eo.po
File diff suppressed because it is too large
Load Diff
427
src/popupwin.c
427
src/popupwin.c
@ -15,23 +15,155 @@
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
|
||||
typedef struct {
|
||||
char *pp_name;
|
||||
poppos_T pp_val;
|
||||
} poppos_entry_T;
|
||||
|
||||
static poppos_entry_T poppos_entries[] = {
|
||||
{"botleft", POPPOS_BOTLEFT},
|
||||
{"topleft", POPPOS_TOPLEFT},
|
||||
{"botright", POPPOS_BOTRIGHT},
|
||||
{"topright", POPPOS_TOPRIGHT},
|
||||
{"center", POPPOS_CENTER}
|
||||
};
|
||||
|
||||
/*
|
||||
* Get option value for"key", which is "line" or "col".
|
||||
* Handles "cursor+N" and "cursor-N".
|
||||
*/
|
||||
static int
|
||||
popup_options_one(dict_T *dict, char_u *key)
|
||||
{
|
||||
dictitem_T *di;
|
||||
char_u *val;
|
||||
char_u *s;
|
||||
char_u *endp;
|
||||
int n = 0;
|
||||
|
||||
di = dict_find(dict, key, -1);
|
||||
if (di == NULL)
|
||||
return 0;
|
||||
|
||||
val = tv_get_string(&di->di_tv);
|
||||
if (STRNCMP(val, "cursor", 6) != 0)
|
||||
return dict_get_number(dict, key);
|
||||
|
||||
setcursor_mayforce(TRUE);
|
||||
s = val + 6;
|
||||
if (*s != NUL)
|
||||
{
|
||||
n = strtol((char *)s, (char **)&endp, 10);
|
||||
if (endp != NULL && *skipwhite(endp) != NUL)
|
||||
{
|
||||
semsg(_(e_invexpr2), val);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (STRCMP(key, "line") == 0)
|
||||
n = screen_screenrow() + 1 + n;
|
||||
else // "col"
|
||||
n = screen_screencol() + 1 + n;
|
||||
|
||||
if (n < 1)
|
||||
n = 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
get_pos_options(win_T *wp, dict_T *dict)
|
||||
{
|
||||
char_u *str;
|
||||
int nr;
|
||||
|
||||
nr = popup_options_one(dict, (char_u *)"line");
|
||||
if (nr > 0)
|
||||
wp->w_wantline = nr;
|
||||
nr = popup_options_one(dict, (char_u *)"col");
|
||||
if (nr > 0)
|
||||
wp->w_wantcol = nr;
|
||||
|
||||
str = dict_get_string(dict, (char_u *)"pos", FALSE);
|
||||
if (str != NULL)
|
||||
{
|
||||
for (nr = 0;
|
||||
nr < (int)(sizeof(poppos_entries) / sizeof(poppos_entry_T));
|
||||
++nr)
|
||||
if (STRCMP(str, poppos_entries[nr].pp_name) == 0)
|
||||
{
|
||||
wp->w_popup_pos = poppos_entries[nr].pp_val;
|
||||
nr = -1;
|
||||
break;
|
||||
}
|
||||
if (nr != -1)
|
||||
semsg(_(e_invarg2), str);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_padding_border(dict_T *dict, int *array, char *name, int max_val)
|
||||
{
|
||||
dictitem_T *di;
|
||||
|
||||
vim_memset(array, 0, sizeof(int) * 4);
|
||||
di = dict_find(dict, (char_u *)name, -1);
|
||||
if (di != NULL)
|
||||
{
|
||||
if (di->di_tv.v_type != VAR_LIST)
|
||||
emsg(_(e_listreq));
|
||||
else
|
||||
{
|
||||
list_T *list = di->di_tv.vval.v_list;
|
||||
listitem_T *li;
|
||||
int i;
|
||||
int nr;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
array[i] = 1;
|
||||
if (list != NULL)
|
||||
for (i = 0, li = list->lv_first; i < 4 && i < list->lv_len;
|
||||
++i, li = li->li_next)
|
||||
{
|
||||
nr = (int)tv_get_number(&li->li_tv);
|
||||
if (nr >= 0)
|
||||
array[i] = nr > max_val ? max_val : nr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the options in "dict" and apply them to buffer "buf" displayed in
|
||||
* popup window "wp".
|
||||
* When called from f_popup_atcursor() "atcursor" is TRUE.
|
||||
*/
|
||||
static void
|
||||
apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict)
|
||||
apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict, int atcursor)
|
||||
{
|
||||
int nr;
|
||||
char_u *str;
|
||||
int nr;
|
||||
char_u *str;
|
||||
dictitem_T *di;
|
||||
|
||||
wp->w_minwidth = dict_get_number(dict, (char_u *)"minwidth");
|
||||
wp->w_minheight = dict_get_number(dict, (char_u *)"minheight");
|
||||
wp->w_maxwidth = dict_get_number(dict, (char_u *)"maxwidth");
|
||||
wp->w_maxheight = dict_get_number(dict, (char_u *)"maxheight");
|
||||
|
||||
wp->w_wantline = dict_get_number(dict, (char_u *)"line");
|
||||
wp->w_wantcol = dict_get_number(dict, (char_u *)"col");
|
||||
if (atcursor)
|
||||
{
|
||||
wp->w_popup_pos = POPPOS_BOTLEFT;
|
||||
setcursor_mayforce(TRUE);
|
||||
wp->w_wantline = screen_screenrow();
|
||||
if (wp->w_wantline == 0) // cursor in first line
|
||||
{
|
||||
wp->w_wantline = 2;
|
||||
wp->w_popup_pos = POPPOS_TOPLEFT;
|
||||
}
|
||||
wp->w_wantcol = screen_screencol() + 1;
|
||||
}
|
||||
|
||||
get_pos_options(wp, dict);
|
||||
|
||||
wp->w_zindex = dict_get_number(dict, (char_u *)"zindex");
|
||||
|
||||
@ -49,18 +181,36 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict)
|
||||
if (get_lambda_tv(&ptr, &tv, TRUE) == OK)
|
||||
{
|
||||
wp->w_popup_timer = create_timer(nr, 0);
|
||||
wp->w_popup_timer->tr_callback =
|
||||
vim_strsave(partial_name(tv.vval.v_partial));
|
||||
func_ref(wp->w_popup_timer->tr_callback);
|
||||
wp->w_popup_timer->tr_partial = tv.vval.v_partial;
|
||||
wp->w_popup_timer->tr_callback = get_callback(&tv);
|
||||
clear_tv(&tv);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
str = dict_get_string(dict, (char_u *)"highlight", TRUE);
|
||||
// Option values resulting in setting an option.
|
||||
str = dict_get_string(dict, (char_u *)"highlight", FALSE);
|
||||
if (str != NULL)
|
||||
set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1,
|
||||
str, OPT_FREE|OPT_LOCAL, 0);
|
||||
|
||||
di = dict_find(dict, (char_u *)"wrap", -1);
|
||||
if (di != NULL)
|
||||
{
|
||||
nr = dict_get_number(dict, (char_u *)"wrap");
|
||||
wp->w_p_wrap = nr != 0;
|
||||
}
|
||||
|
||||
di = dict_find(dict, (char_u *)"filter", -1);
|
||||
if (di != NULL)
|
||||
{
|
||||
callback_T callback = get_callback(&di->di_tv);
|
||||
|
||||
if (callback.cb_name != NULL)
|
||||
set_callback(&wp->w_filter_cb, &callback);
|
||||
}
|
||||
|
||||
get_padding_border(dict, wp->w_popup_padding, "padding", 999);
|
||||
get_padding_border(dict, wp->w_popup_border, "border", 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -157,24 +307,42 @@ popup_adjust_position(win_T *wp)
|
||||
linenr_T lnum;
|
||||
int wrapped = 0;
|
||||
int maxwidth;
|
||||
int center_vert = FALSE;
|
||||
int center_hor = FALSE;
|
||||
|
||||
// TODO: Compute the size and position properly.
|
||||
if (wp->w_wantline > 0)
|
||||
wp->w_winrow = wp->w_wantline - 1;
|
||||
wp->w_winrow = 0;
|
||||
wp->w_wincol = 0;
|
||||
if (wp->w_popup_pos == POPPOS_CENTER)
|
||||
{
|
||||
// center after computing the size
|
||||
center_vert = TRUE;
|
||||
center_hor = TRUE;
|
||||
}
|
||||
else
|
||||
// TODO: better default
|
||||
wp->w_winrow = Rows > 5 ? Rows / 2 - 2 : 0;
|
||||
if (wp->w_winrow >= Rows)
|
||||
wp->w_winrow = Rows - 1;
|
||||
{
|
||||
if (wp->w_wantline == 0)
|
||||
center_vert = TRUE;
|
||||
else if (wp->w_popup_pos == POPPOS_TOPLEFT
|
||||
|| wp->w_popup_pos == POPPOS_TOPRIGHT)
|
||||
{
|
||||
wp->w_winrow = wp->w_wantline - 1;
|
||||
if (wp->w_winrow >= Rows)
|
||||
wp->w_winrow = Rows - 1;
|
||||
}
|
||||
|
||||
if (wp->w_wantcol > 0)
|
||||
wp->w_wincol = wp->w_wantcol - 1;
|
||||
else
|
||||
// TODO: better default
|
||||
wp->w_wincol = Columns > 20 ? Columns / 2 - 10 : 0;
|
||||
if (wp->w_wincol >= Columns - 3)
|
||||
wp->w_wincol = Columns - 3;
|
||||
if (wp->w_wantcol == 0)
|
||||
center_hor = TRUE;
|
||||
else if (wp->w_popup_pos == POPPOS_TOPLEFT
|
||||
|| wp->w_popup_pos == POPPOS_BOTLEFT)
|
||||
{
|
||||
wp->w_wincol = wp->w_wantcol - 1;
|
||||
if (wp->w_wincol >= Columns - 3)
|
||||
wp->w_wincol = Columns - 3;
|
||||
}
|
||||
}
|
||||
|
||||
// When centering or right aligned, use maximum width.
|
||||
// When left aligned use the space available.
|
||||
maxwidth = Columns - wp->w_wincol;
|
||||
if (wp->w_maxwidth > 0 && maxwidth > wp->w_maxwidth)
|
||||
maxwidth = wp->w_maxwidth;
|
||||
@ -200,6 +368,16 @@ popup_adjust_position(win_T *wp)
|
||||
wp->w_width = wp->w_minwidth;
|
||||
if (wp->w_width > maxwidth)
|
||||
wp->w_width = maxwidth;
|
||||
if (center_hor)
|
||||
wp->w_wincol = (Columns - wp->w_width) / 2;
|
||||
else if (wp->w_popup_pos == POPPOS_BOTRIGHT
|
||||
|| wp->w_popup_pos == POPPOS_TOPRIGHT)
|
||||
{
|
||||
// Right aligned: move to the right if needed.
|
||||
// No truncation, because that would change the height.
|
||||
if (wp->w_width < wp->w_wantcol)
|
||||
wp->w_wincol = wp->w_wantcol - wp->w_width;
|
||||
}
|
||||
|
||||
if (wp->w_height <= 1)
|
||||
wp->w_height = wp->w_buffer->b_ml.ml_line_count + wrapped;
|
||||
@ -210,14 +388,29 @@ popup_adjust_position(win_T *wp)
|
||||
if (wp->w_height > Rows - wp->w_winrow)
|
||||
wp->w_height = Rows - wp->w_winrow;
|
||||
|
||||
if (center_vert)
|
||||
wp->w_winrow = (Rows - wp->w_height) / 2;
|
||||
else if (wp->w_popup_pos == POPPOS_BOTRIGHT
|
||||
|| wp->w_popup_pos == POPPOS_BOTLEFT)
|
||||
{
|
||||
if (wp->w_height <= wp->w_wantline)
|
||||
// bottom aligned: may move down
|
||||
wp->w_winrow = wp->w_wantline - wp->w_height;
|
||||
else
|
||||
// not enough space, make top aligned
|
||||
wp->w_winrow = wp->w_wantline + 1;
|
||||
}
|
||||
|
||||
wp->w_popup_last_changedtick = CHANGEDTICK(wp->w_buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* popup_create({text}, {options})
|
||||
* popup_atcursor({text}, {options})
|
||||
* When called from f_popup_atcursor() "atcursor" is TRUE.
|
||||
*/
|
||||
void
|
||||
f_popup_create(typval_T *argvars, typval_T *rettv)
|
||||
static void
|
||||
popup_create(typval_T *argvars, typval_T *rettv, int atcursor)
|
||||
{
|
||||
win_T *wp;
|
||||
buf_T *buf;
|
||||
@ -247,7 +440,7 @@ f_popup_create(typval_T *argvars, typval_T *rettv)
|
||||
if (wp == NULL)
|
||||
return;
|
||||
rettv->vval.v_number = wp->w_id;
|
||||
wp->w_p_wrap = TRUE; // 'wrap' is default on
|
||||
wp->w_popup_pos = POPPOS_TOPLEFT;
|
||||
|
||||
buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY);
|
||||
if (buf == NULL)
|
||||
@ -265,6 +458,10 @@ f_popup_create(typval_T *argvars, typval_T *rettv)
|
||||
buf->b_p_swf = FALSE; // no swap file
|
||||
buf->b_p_bl = FALSE; // unlisted buffer
|
||||
buf->b_locked = TRUE;
|
||||
wp->w_p_wrap = TRUE; // 'wrap' is default on
|
||||
|
||||
// Avoid that 'buftype' is reset when this buffer is entered.
|
||||
buf->b_p_initialized = TRUE;
|
||||
|
||||
nr = (int)dict_get_number(d, (char_u *)"tab");
|
||||
if (nr == 0)
|
||||
@ -307,7 +504,7 @@ f_popup_create(typval_T *argvars, typval_T *rettv)
|
||||
curbuf = curwin->w_buffer;
|
||||
|
||||
// Deal with options.
|
||||
apply_options(wp, buf, argvars[1].vval.v_dict);
|
||||
apply_options(wp, buf, argvars[1].vval.v_dict, atcursor);
|
||||
|
||||
// set default values
|
||||
if (wp->w_zindex == 0)
|
||||
@ -320,6 +517,24 @@ f_popup_create(typval_T *argvars, typval_T *rettv)
|
||||
redraw_all_later(NOT_VALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* popup_create({text}, {options})
|
||||
*/
|
||||
void
|
||||
f_popup_create(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
popup_create(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* popup_atcursor({text}, {options})
|
||||
*/
|
||||
void
|
||||
f_popup_atcursor(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
popup_create(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the popup window with window-ID "id".
|
||||
* If the popup window does not exist NULL is returned.
|
||||
@ -378,6 +593,7 @@ f_popup_hide(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
if (wp != NULL && (wp->w_popup_flags & POPF_HIDDEN) == 0)
|
||||
{
|
||||
wp->w_popup_flags |= POPF_HIDDEN;
|
||||
--wp->w_buffer->b_nwindows;
|
||||
redraw_all_later(NOT_VALID);
|
||||
}
|
||||
}
|
||||
@ -394,6 +610,7 @@ f_popup_show(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
if (wp != NULL && (wp->w_popup_flags & POPF_HIDDEN) != 0)
|
||||
{
|
||||
wp->w_popup_flags &= ~POPF_HIDDEN;
|
||||
++wp->w_buffer->b_nwindows;
|
||||
redraw_all_later(NOT_VALID);
|
||||
}
|
||||
}
|
||||
@ -501,11 +718,7 @@ f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
wp->w_maxwidth = nr;
|
||||
if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0)
|
||||
wp->w_maxheight = nr;
|
||||
if ((nr = dict_get_number(d, (char_u *)"line")) > 0)
|
||||
wp->w_wantline = nr;
|
||||
if ((nr = dict_get_number(d, (char_u *)"col")) > 0)
|
||||
wp->w_wantcol = nr;
|
||||
// TODO: "pos"
|
||||
get_pos_options(wp, d);
|
||||
|
||||
if (wp->w_winrow + wp->w_height >= cmdline_row)
|
||||
clear_cmdline = TRUE;
|
||||
@ -514,24 +727,36 @@ f_popup_move(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
}
|
||||
|
||||
/*
|
||||
* popup_getposition({id})
|
||||
* popup_getpos({id})
|
||||
*/
|
||||
void
|
||||
f_popup_getposition(typval_T *argvars, typval_T *rettv)
|
||||
f_popup_getpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
dict_T *dict;
|
||||
int id = (int)tv_get_number(argvars);
|
||||
win_T *wp = find_popup_win(id);
|
||||
int top_extra;
|
||||
int left_extra;
|
||||
|
||||
if (rettv_dict_alloc(rettv) == OK)
|
||||
{
|
||||
if (wp == NULL)
|
||||
return; // invalid {id}
|
||||
top_extra = wp->w_popup_border[0] + wp->w_popup_padding[0];
|
||||
left_extra = wp->w_popup_border[3] + wp->w_popup_padding[3];
|
||||
|
||||
dict = rettv->vval.v_dict;
|
||||
|
||||
dict_add_number(dict, "line", wp->w_winrow + 1);
|
||||
dict_add_number(dict, "col", wp->w_wincol + 1);
|
||||
dict_add_number(dict, "width", wp->w_width);
|
||||
dict_add_number(dict, "height", wp->w_height);
|
||||
dict_add_number(dict, "width", wp->w_width + left_extra + wp->w_popup_border[1] + wp->w_popup_padding[1]);
|
||||
dict_add_number(dict, "height", wp->w_height + top_extra + wp->w_popup_border[2] + wp->w_popup_padding[2]);
|
||||
|
||||
dict_add_number(dict, "core_line", wp->w_winrow + 1 + top_extra);
|
||||
dict_add_number(dict, "core_col", wp->w_wincol + 1 + left_extra);
|
||||
dict_add_number(dict, "core_width", wp->w_width);
|
||||
dict_add_number(dict, "core_height", wp->w_height);
|
||||
|
||||
dict_add_number(dict, "visible",
|
||||
(wp->w_popup_flags & POPF_HIDDEN) == 0);
|
||||
}
|
||||
@ -546,6 +771,7 @@ f_popup_getoptions(typval_T *argvars, typval_T *rettv)
|
||||
dict_T *dict;
|
||||
int id = (int)tv_get_number(argvars);
|
||||
win_T *wp = find_popup_win(id);
|
||||
int i;
|
||||
|
||||
if (rettv_dict_alloc(rettv) == OK)
|
||||
{
|
||||
@ -560,10 +786,137 @@ f_popup_getoptions(typval_T *argvars, typval_T *rettv)
|
||||
dict_add_number(dict, "maxheight", wp->w_maxheight);
|
||||
dict_add_number(dict, "maxwidth", wp->w_maxwidth);
|
||||
dict_add_number(dict, "zindex", wp->w_zindex);
|
||||
|
||||
for (i = 0; i < (int)(sizeof(poppos_entries) / sizeof(poppos_entry_T));
|
||||
++i)
|
||||
if (wp->w_popup_pos == poppos_entries[i].pp_val)
|
||||
{
|
||||
dict_add_string(dict, "pos",
|
||||
(char_u *)poppos_entries[i].pp_name);
|
||||
break;
|
||||
}
|
||||
|
||||
# if defined(FEAT_TIMERS)
|
||||
dict_add_number(dict, "time", wp->w_popup_timer != NULL
|
||||
? (long)wp->w_popup_timer->tr_interval : 0L);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
not_in_popup_window()
|
||||
{
|
||||
if (bt_popup(curwin->w_buffer))
|
||||
{
|
||||
emsg(_("E994: Not allowed in a popup window"));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset all the POPF_HANDLED flags in global popup windows and popup windows
|
||||
* in the current tab.
|
||||
*/
|
||||
void
|
||||
popup_reset_handled()
|
||||
{
|
||||
win_T *wp;
|
||||
|
||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
wp->w_popup_flags &= ~POPF_HANDLED;
|
||||
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
wp->w_popup_flags &= ~POPF_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next visible popup where POPF_HANDLED is not set.
|
||||
* Must have called popup_reset_handled() first.
|
||||
* When "lowest" is TRUE find the popup with the lowest zindex, otherwise the
|
||||
* popup with the highest zindex.
|
||||
*/
|
||||
win_T *
|
||||
find_next_popup(int lowest)
|
||||
{
|
||||
win_T *wp;
|
||||
win_T *found_wp;
|
||||
int found_zindex;
|
||||
|
||||
found_zindex = lowest ? INT_MAX : 0;
|
||||
found_wp = NULL;
|
||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
if ((wp->w_popup_flags & (POPF_HANDLED|POPF_HIDDEN)) == 0
|
||||
&& (lowest ? wp->w_zindex < found_zindex
|
||||
: wp->w_zindex > found_zindex))
|
||||
{
|
||||
found_zindex = wp->w_zindex;
|
||||
found_wp = wp;
|
||||
}
|
||||
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
if ((wp->w_popup_flags & (POPF_HANDLED|POPF_HIDDEN)) == 0
|
||||
&& (lowest ? wp->w_zindex < found_zindex
|
||||
: wp->w_zindex > found_zindex))
|
||||
{
|
||||
found_zindex = wp->w_zindex;
|
||||
found_wp = wp;
|
||||
}
|
||||
|
||||
if (found_wp != NULL)
|
||||
found_wp->w_popup_flags |= POPF_HANDLED;
|
||||
return found_wp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke the filter callback for window "wp" with typed character "c".
|
||||
* Uses the global "mod_mask" for modifiers.
|
||||
* Returns the return value of the filter.
|
||||
* Careful: The filter may make "wp" invalid!
|
||||
*/
|
||||
static int
|
||||
invoke_popup_filter(win_T *wp, int c)
|
||||
{
|
||||
int res;
|
||||
typval_T rettv;
|
||||
int dummy;
|
||||
typval_T argv[3];
|
||||
char_u buf[NUMBUFLEN];
|
||||
|
||||
argv[0].v_type = VAR_NUMBER;
|
||||
argv[0].vval.v_number = (varnumber_T)wp->w_id;
|
||||
|
||||
// Convert the number to a string, so that the function can use:
|
||||
// if a:c == "\<F2>"
|
||||
buf[special_to_buf(c, mod_mask, TRUE, buf)] = NUL;
|
||||
argv[1].v_type = VAR_STRING;
|
||||
argv[1].vval.v_string = vim_strsave(buf);
|
||||
|
||||
argv[2].v_type = VAR_UNKNOWN;
|
||||
|
||||
call_callback(&wp->w_filter_cb, -1,
|
||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
||||
res = tv_get_number(&rettv);
|
||||
vim_free(argv[1].vval.v_string);
|
||||
clear_tv(&rettv);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when "c" was typed: invoke popup filter callbacks.
|
||||
* Returns TRUE when the character was consumed,
|
||||
*/
|
||||
int
|
||||
popup_do_filter(int c)
|
||||
{
|
||||
int res = FALSE;
|
||||
win_T *wp;
|
||||
|
||||
popup_reset_handled();
|
||||
|
||||
while (!res && (wp = find_next_popup(FALSE)) != NULL)
|
||||
if (wp->w_filter_cb.cb_name != NULL)
|
||||
res = invoke_popup_filter(wp, c);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // FEAT_TEXT_PROP
|
||||
|
@ -12,7 +12,7 @@ channel_T *channel_open_func(typval_T *argvars);
|
||||
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
|
||||
void channel_set_job(channel_T *channel, job_T *job, jobopt_T *options);
|
||||
void channel_set_options(channel_T *channel, jobopt_T *opt);
|
||||
void channel_set_req_callback(channel_T *channel, ch_part_T part, char_u *callback, partial_T *partial, int id);
|
||||
void channel_set_req_callback(channel_T *channel, ch_part_T part, callback_T *callback, int id);
|
||||
void channel_buffer_free(buf_T *buf);
|
||||
void channel_write_any_lines(void);
|
||||
void channel_write_new_lines(buf_T *buf);
|
||||
|
@ -11,6 +11,8 @@ void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
|
||||
float_T vim_round(float_T f);
|
||||
long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
|
||||
void f_string(typval_T *argvars, typval_T *rettv);
|
||||
char_u *get_callback(typval_T *arg, partial_T **pp);
|
||||
void free_callback(char_u *callback, partial_T *partial);
|
||||
callback_T get_callback(typval_T *arg);
|
||||
void put_callback(callback_T *cb, typval_T *tv);
|
||||
void set_callback(callback_T *dest, callback_T *src);
|
||||
void free_callback(callback_T *callback);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -69,6 +69,7 @@ int simplify_key(int key, int *modifiers);
|
||||
int handle_x_keys(int key);
|
||||
char_u *get_special_key_name(int c, int modifiers);
|
||||
int trans_special(char_u **srcp, char_u *dst, int keycode, int in_string);
|
||||
int special_to_buf(int key, int modifiers, int keycode, char_u *dst);
|
||||
int find_special_key(char_u **srcp, int *modp, int keycode, int keep_x_key, int in_string);
|
||||
int extract_modifiers(int key, int *modp);
|
||||
int find_special_key_in_table(int c);
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* popupwin.c */
|
||||
void popup_adjust_position(win_T *wp);
|
||||
void f_popup_create(typval_T *argvars, typval_T *rettv);
|
||||
void f_popup_atcursor(typval_T *argvars, typval_T *rettv);
|
||||
int popup_any_visible(void);
|
||||
void f_popup_close(typval_T *argvars, typval_T *rettv);
|
||||
void f_popup_hide(typval_T *argvars, typval_T *rettv);
|
||||
@ -10,6 +11,10 @@ void popup_close_tabpage(tabpage_T *tp, int id);
|
||||
void close_all_popups(void);
|
||||
void ex_popupclear(exarg_T *eap);
|
||||
void f_popup_move(typval_T *argvars, typval_T *rettv);
|
||||
void f_popup_getpos(typval_T *argvars, typval_T *rettv);
|
||||
void f_popup_getoptions(typval_T *argvars, typval_T *rettv);
|
||||
void f_popup_getposition(typval_T *argvars, typval_T *rettv);
|
||||
int not_in_popup_window(void);
|
||||
void popup_reset_handled(void);
|
||||
win_T *find_next_popup(int lowest);
|
||||
int popup_do_filter(int c);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -8,6 +8,7 @@ void save_funccal(funccal_entry_T *entry);
|
||||
void restore_funccal(void);
|
||||
void free_all_functions(void);
|
||||
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
|
||||
int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars, int (*argv_func)(int, typval_T *, int), linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict);
|
||||
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, int (*argv_func)(int, typval_T *, int), linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
|
||||
char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T *fdp, partial_T **partial);
|
||||
void ex_function(exarg_T *eap);
|
||||
|
@ -77,7 +77,9 @@ void reset_lnums(void);
|
||||
void make_snapshot(int idx);
|
||||
void restore_snapshot(int idx, int close_curwin);
|
||||
int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, int no_display);
|
||||
int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, int no_display);
|
||||
void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display);
|
||||
void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab, int no_display);
|
||||
void switch_buffer(bufref_T *save_curbuf, buf_T *buf);
|
||||
void restore_buffer(bufref_T *save_curbuf);
|
||||
int win_hasvertsplit(void);
|
||||
|
221
src/screen.c
221
src/screen.c
@ -991,57 +991,6 @@ update_debug_sign(buf_T *buf, linenr_T lnum)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
static void
|
||||
update_popups(void)
|
||||
{
|
||||
win_T *wp;
|
||||
win_T *lowest_wp;
|
||||
int lowest_zindex;
|
||||
|
||||
// Reset all the VALID_POPUP flags.
|
||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
wp->w_popup_flags &= ~POPF_REDRAWN;
|
||||
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
wp->w_popup_flags &= ~POPF_REDRAWN;
|
||||
|
||||
// TODO: don't redraw every popup every time.
|
||||
for (;;)
|
||||
{
|
||||
// Find the window with the lowest zindex that hasn't been updated yet,
|
||||
// so that the window with a higher zindex is drawn later, thus goes on
|
||||
// top.
|
||||
lowest_zindex = INT_MAX;
|
||||
lowest_wp = NULL;
|
||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
if ((wp->w_popup_flags & (POPF_REDRAWN|POPF_HIDDEN)) == 0
|
||||
&& wp->w_zindex < lowest_zindex)
|
||||
{
|
||||
lowest_zindex = wp->w_zindex;
|
||||
lowest_wp = wp;
|
||||
}
|
||||
for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
if ((wp->w_popup_flags & (POPF_REDRAWN|POPF_HIDDEN)) == 0
|
||||
&& wp->w_zindex < lowest_zindex)
|
||||
{
|
||||
lowest_zindex = wp->w_zindex;
|
||||
lowest_wp = wp;
|
||||
}
|
||||
|
||||
if (lowest_wp == NULL)
|
||||
break;
|
||||
|
||||
// Recompute the position if the text changed.
|
||||
if (lowest_wp->w_popup_last_changedtick
|
||||
!= CHANGEDTICK(lowest_wp->w_buffer))
|
||||
popup_adjust_position(lowest_wp);
|
||||
|
||||
win_update(lowest_wp);
|
||||
lowest_wp->w_popup_flags |= POPF_REDRAWN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup
|
||||
* window then get the "Pmenu" highlight attribute.
|
||||
@ -1060,6 +1009,149 @@ get_wcr_attr(win_T *wp)
|
||||
return wcr_attr;
|
||||
}
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
/*
|
||||
* Return a string of "len" spaces in IObuff.
|
||||
*/
|
||||
static char_u *
|
||||
get_spaces(int len)
|
||||
{
|
||||
vim_memset(IObuff, ' ', (size_t)len);
|
||||
IObuff[len] = NUL;
|
||||
return IObuff;
|
||||
}
|
||||
|
||||
static void
|
||||
update_popups(void)
|
||||
{
|
||||
win_T *wp;
|
||||
int top_off;
|
||||
int left_off;
|
||||
int total_width;
|
||||
int total_height;
|
||||
int popup_attr;
|
||||
int row;
|
||||
int tl_corner_char = '+';
|
||||
char *tr_corner_str = "+";
|
||||
int bl_corner_char = '+';
|
||||
char *br_corner_str = "+";
|
||||
int hor_line_char = '-';
|
||||
char *ver_line_str = "|";
|
||||
|
||||
// Find the window with the lowest zindex that hasn't been updated yet,
|
||||
// so that the window with a higher zindex is drawn later, thus goes on
|
||||
// top.
|
||||
// TODO: don't redraw every popup every time.
|
||||
popup_reset_handled();
|
||||
while ((wp = find_next_popup(TRUE)) != NULL)
|
||||
{
|
||||
// Recompute the position if the text changed.
|
||||
if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
|
||||
popup_adjust_position(wp);
|
||||
|
||||
// adjust w_winrow and w_wincol for border and padding, since
|
||||
// win_update() doesn't handle them.
|
||||
top_off = wp->w_popup_padding[0] + wp->w_popup_border[0];
|
||||
left_off = wp->w_popup_padding[3] + wp->w_popup_border[3];
|
||||
wp->w_winrow += top_off;
|
||||
wp->w_wincol += left_off;
|
||||
|
||||
// Draw the popup text.
|
||||
win_update(wp);
|
||||
|
||||
wp->w_winrow -= top_off;
|
||||
wp->w_wincol -= left_off;
|
||||
|
||||
total_width = wp->w_popup_border[3] + wp->w_popup_padding[3]
|
||||
+ wp->w_width + wp->w_popup_padding[1] + wp->w_popup_border[1];
|
||||
total_height = wp->w_popup_border[0] + wp->w_popup_padding[0]
|
||||
+ wp->w_height + wp->w_popup_padding[2] + wp->w_popup_border[2];
|
||||
popup_attr = get_wcr_attr(wp);
|
||||
|
||||
if (enc_utf8)
|
||||
{
|
||||
tl_corner_char = 0x2554;
|
||||
tr_corner_str = "\xe2\x95\x97";
|
||||
bl_corner_char = 0x255a;
|
||||
br_corner_str = "\xe2\x95\x9d";
|
||||
hor_line_char = 0x2550;
|
||||
ver_line_str = "\xe2\x95\x91";
|
||||
}
|
||||
|
||||
if (wp->w_popup_border[0] > 0)
|
||||
{
|
||||
// top border
|
||||
screen_fill(wp->w_winrow, wp->w_winrow + 1,
|
||||
wp->w_wincol,
|
||||
wp->w_wincol + total_width,
|
||||
wp->w_popup_border[3] != 0
|
||||
? tl_corner_char : hor_line_char,
|
||||
hor_line_char, popup_attr);
|
||||
if (wp->w_popup_border[1] > 0)
|
||||
screen_puts((char_u *)tr_corner_str, wp->w_winrow,
|
||||
wp->w_wincol + total_width - 1, popup_attr);
|
||||
}
|
||||
|
||||
if (wp->w_popup_padding[0] > 0)
|
||||
{
|
||||
// top padding
|
||||
row = wp->w_winrow + wp->w_popup_border[0];
|
||||
screen_fill(row, row + wp->w_popup_padding[0],
|
||||
wp->w_wincol + wp->w_popup_border[3],
|
||||
wp->w_wincol + total_width - wp->w_popup_border[1],
|
||||
' ', ' ', popup_attr);
|
||||
}
|
||||
|
||||
for (row = wp->w_winrow + wp->w_popup_border[0];
|
||||
row < wp->w_winrow + total_height - wp->w_popup_border[2];
|
||||
++row)
|
||||
{
|
||||
// left border
|
||||
if (wp->w_popup_border[3] > 0)
|
||||
screen_puts((char_u *)ver_line_str, row, wp->w_wincol, popup_attr);
|
||||
// left padding
|
||||
if (wp->w_popup_padding[3] > 0)
|
||||
screen_puts(get_spaces(wp->w_popup_padding[3]), row,
|
||||
wp->w_wincol + wp->w_popup_border[3], popup_attr);
|
||||
// right border
|
||||
if (wp->w_popup_border[1] > 0)
|
||||
screen_puts((char_u *)ver_line_str, row,
|
||||
wp->w_wincol + total_width - 1, popup_attr);
|
||||
// right padding
|
||||
if (wp->w_popup_padding[1] > 0)
|
||||
screen_puts(get_spaces(wp->w_popup_padding[1]), row,
|
||||
wp->w_wincol + wp->w_popup_border[3]
|
||||
+ wp->w_popup_padding[3] + wp->w_width, popup_attr);
|
||||
}
|
||||
|
||||
if (wp->w_popup_padding[2] > 0)
|
||||
{
|
||||
// bottom padding
|
||||
row = wp->w_winrow + wp->w_popup_border[0]
|
||||
+ wp->w_popup_padding[0] + wp->w_height;
|
||||
screen_fill(row, row + wp->w_popup_padding[2],
|
||||
wp->w_wincol + wp->w_popup_border[3],
|
||||
wp->w_wincol + total_width - wp->w_popup_border[1],
|
||||
' ', ' ', popup_attr);
|
||||
}
|
||||
|
||||
if (wp->w_popup_border[2] > 0)
|
||||
{
|
||||
// bottom border
|
||||
row = wp->w_winrow + total_height - 1;
|
||||
screen_fill(row , row + 1,
|
||||
wp->w_wincol,
|
||||
wp->w_wincol + total_width,
|
||||
wp->w_popup_border[3] != 0 ? bl_corner_char : hor_line_char,
|
||||
hor_line_char, popup_attr);
|
||||
if (wp->w_popup_border[1] > 0)
|
||||
screen_puts((char_u *)br_corner_str, row,
|
||||
wp->w_wincol + total_width - 1, popup_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FEAT_GUI) || defined(PROTO)
|
||||
/*
|
||||
* Update a single window, its status line and maybe the command line msg.
|
||||
@ -8921,6 +9013,15 @@ retry:
|
||||
win_free_lsize(wp);
|
||||
if (aucmd_win != NULL)
|
||||
win_free_lsize(aucmd_win);
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
// global popup windows
|
||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
win_free_lsize(wp);
|
||||
// tab-local popup windows
|
||||
FOR_ALL_TABPAGES(tp)
|
||||
for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
win_free_lsize(wp);
|
||||
#endif
|
||||
|
||||
new_ScreenLines = LALLOC_MULT(schar_T, (Rows + 1) * Columns);
|
||||
vim_memset(new_ScreenLinesC, 0, sizeof(u8char_T *) * MAX_MCO);
|
||||
@ -8949,6 +9050,24 @@ retry:
|
||||
if (aucmd_win != NULL && aucmd_win->w_lines == NULL
|
||||
&& win_alloc_lines(aucmd_win) == FAIL)
|
||||
outofmem = TRUE;
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
// global popup windows
|
||||
for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
if (win_alloc_lines(wp) == FAIL)
|
||||
{
|
||||
outofmem = TRUE;
|
||||
goto give_up;
|
||||
}
|
||||
// tab-local popup windows
|
||||
FOR_ALL_TABPAGES(tp)
|
||||
for (wp = tp->tp_first_popupwin; wp != NULL; wp = wp->w_next)
|
||||
if (win_alloc_lines(wp) == FAIL)
|
||||
{
|
||||
outofmem = TRUE;
|
||||
goto give_up;
|
||||
}
|
||||
#endif
|
||||
|
||||
give_up:
|
||||
|
||||
for (i = 0; i < p_mco; ++i)
|
||||
|
@ -1237,6 +1237,17 @@ typedef struct dictvar_S dict_T;
|
||||
typedef struct partial_S partial_T;
|
||||
typedef struct blobvar_S blob_T;
|
||||
|
||||
// Struct that holds both a normal function name and a partial_T, as used for a
|
||||
// callback argument.
|
||||
// When used temporarily "cb_name" is not allocated. The refcounts to either
|
||||
// the function or the partial are incremented and need to be decremented
|
||||
// later with free_callback().
|
||||
typedef struct {
|
||||
char_u *cb_name;
|
||||
partial_T *cb_partial;
|
||||
int cb_free_name; // cb_name was allocated
|
||||
} callback_T;
|
||||
|
||||
typedef struct jobvar_S job_T;
|
||||
typedef struct readq_S readq_T;
|
||||
typedef struct writeq_S writeq_T;
|
||||
@ -1566,8 +1577,7 @@ struct jobvar_S
|
||||
char_u *jv_tty_type; // allocated
|
||||
#endif
|
||||
int jv_exitval;
|
||||
char_u *jv_exit_cb; /* allocated */
|
||||
partial_T *jv_exit_partial;
|
||||
callback_T jv_exit_cb;
|
||||
|
||||
buf_T *jv_in_buf; /* buffer from "in-name" */
|
||||
|
||||
@ -1606,8 +1616,7 @@ struct jsonq_S
|
||||
|
||||
struct cbq_S
|
||||
{
|
||||
char_u *cq_callback;
|
||||
partial_T *cq_partial;
|
||||
callback_T cq_callback;
|
||||
int cq_seq_nr;
|
||||
cbq_T *cq_next;
|
||||
cbq_T *cq_prev;
|
||||
@ -1689,8 +1698,7 @@ typedef struct {
|
||||
writeq_T ch_writeque; /* header for write queue */
|
||||
|
||||
cbq_T ch_cb_head; /* dummy node for per-request callbacks */
|
||||
char_u *ch_callback; /* call when a msg is not handled */
|
||||
partial_T *ch_partial;
|
||||
callback_T ch_callback; /* call when a msg is not handled */
|
||||
|
||||
bufref_T ch_bufref; /* buffer to read from or write to */
|
||||
int ch_nomodifiable; /* TRUE when buffer can be 'nomodifiable' */
|
||||
@ -1731,10 +1739,8 @@ struct channel_S {
|
||||
#ifdef MSWIN
|
||||
int ch_named_pipe; /* using named pipe instead of pty */
|
||||
#endif
|
||||
char_u *ch_callback; /* call when any msg is not handled */
|
||||
partial_T *ch_partial;
|
||||
char_u *ch_close_cb; /* call when channel is closed */
|
||||
partial_T *ch_close_partial;
|
||||
callback_T ch_callback; /* call when any msg is not handled */
|
||||
callback_T ch_close_cb; /* call when channel is closed */
|
||||
int ch_drop_never;
|
||||
int ch_keep_open; /* do not close on read error */
|
||||
int ch_nonblock;
|
||||
@ -1833,16 +1839,11 @@ typedef struct
|
||||
linenr_T jo_in_top;
|
||||
linenr_T jo_in_bot;
|
||||
|
||||
char_u *jo_callback; /* not allocated! */
|
||||
partial_T *jo_partial; /* not referenced! */
|
||||
char_u *jo_out_cb; /* not allocated! */
|
||||
partial_T *jo_out_partial; /* not referenced! */
|
||||
char_u *jo_err_cb; /* not allocated! */
|
||||
partial_T *jo_err_partial; /* not referenced! */
|
||||
char_u *jo_close_cb; /* not allocated! */
|
||||
partial_T *jo_close_partial; /* not referenced! */
|
||||
char_u *jo_exit_cb; /* not allocated! */
|
||||
partial_T *jo_exit_partial; /* not referenced! */
|
||||
callback_T jo_callback;
|
||||
callback_T jo_out_cb;
|
||||
callback_T jo_err_cb;
|
||||
callback_T jo_close_cb;
|
||||
callback_T jo_exit_cb;
|
||||
int jo_drop_never;
|
||||
int jo_waittime;
|
||||
int jo_timeout;
|
||||
@ -1886,8 +1887,7 @@ struct listener_S
|
||||
{
|
||||
listener_T *lr_next;
|
||||
int lr_id;
|
||||
char_u *lr_callback;
|
||||
partial_T *lr_partial;
|
||||
callback_T lr_callback;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -1950,13 +1950,12 @@ struct timer_S
|
||||
#ifdef FEAT_TIMERS
|
||||
timer_T *tr_next;
|
||||
timer_T *tr_prev;
|
||||
proftime_T tr_due; /* when the callback is to be invoked */
|
||||
char tr_firing; /* when TRUE callback is being called */
|
||||
char tr_paused; /* when TRUE callback is not invoked */
|
||||
int tr_repeat; /* number of times to repeat, -1 forever */
|
||||
long tr_interval; /* msec */
|
||||
char_u *tr_callback; /* allocated */
|
||||
partial_T *tr_partial;
|
||||
proftime_T tr_due; // when the callback is to be invoked
|
||||
char tr_firing; // when TRUE callback is being called
|
||||
char tr_paused; // when TRUE callback is not invoked
|
||||
int tr_repeat; // number of times to repeat, -1 forever
|
||||
long tr_interval; // msec
|
||||
callback_T tr_callback;
|
||||
int tr_emsg_count;
|
||||
#endif
|
||||
};
|
||||
@ -1982,6 +1981,15 @@ typedef struct {
|
||||
// # define CRYPT_NOT_INPLACE 1
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
typedef enum {
|
||||
POPPOS_BOTLEFT,
|
||||
POPPOS_TOPLEFT,
|
||||
POPPOS_BOTRIGHT,
|
||||
POPPOS_TOPRIGHT,
|
||||
POPPOS_CENTER
|
||||
} poppos_T;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These are items normally related to a buffer. But when using ":ownsyntax"
|
||||
@ -2500,13 +2508,11 @@ struct file_buffer
|
||||
int b_shortname; /* this file has an 8.3 file name */
|
||||
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
char_u *b_prompt_text; // set by prompt_setprompt()
|
||||
char_u *b_prompt_callback; // set by prompt_setcallback()
|
||||
partial_T *b_prompt_partial; // set by prompt_setcallback()
|
||||
char_u *b_prompt_interrupt; // set by prompt_setinterrupt()
|
||||
partial_T *b_prompt_int_partial; // set by prompt_setinterrupt()
|
||||
int b_prompt_insert; // value for restart_edit when entering
|
||||
// a prompt buffer window.
|
||||
char_u *b_prompt_text; // set by prompt_setprompt()
|
||||
callback_T b_prompt_callback; // set by prompt_setcallback()
|
||||
callback_T b_prompt_interrupt; // set by prompt_setinterrupt()
|
||||
int b_prompt_insert; // value for restart_edit when entering
|
||||
// a prompt buffer window.
|
||||
#endif
|
||||
#ifdef FEAT_MZSCHEME
|
||||
void *b_mzscheme_ref; /* The MzScheme reference to this buffer */
|
||||
@ -2873,7 +2879,8 @@ struct window_S
|
||||
int w_vsep_width; /* Number of separator columns (0 or 1). */
|
||||
pos_save_T w_save_cursor; /* backup of cursor pos and topline */
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
int w_popup_flags; // PFL_ values
|
||||
int w_popup_flags; // POPF_ values
|
||||
poppos_T w_popup_pos;
|
||||
int w_zindex;
|
||||
int w_minheight; // "minheight" for popup window
|
||||
int w_minwidth; // "minwidth" for popup window
|
||||
@ -2881,8 +2888,11 @@ struct window_S
|
||||
int w_maxwidth; // "maxwidth" for popup window
|
||||
int w_wantline; // "line" for popup window
|
||||
int w_wantcol; // "col" for popup window
|
||||
int w_popup_padding[4]; // popup padding top/right/bot/left
|
||||
int w_popup_border[4]; // popup border top/right/bot/left
|
||||
varnumber_T w_popup_last_changedtick; // b:changedtick when position was
|
||||
// computed
|
||||
callback_T w_filter_cb; // popup filter callback
|
||||
# if defined(FEAT_TIMERS)
|
||||
timer_T *w_popup_timer; // timer for closing popup window
|
||||
# endif
|
||||
|
@ -13,7 +13,6 @@ SCRIPTS_FIRST = \
|
||||
|
||||
# Tests that run on all systems.
|
||||
SCRIPTS_ALL = \
|
||||
test3.out \
|
||||
test39.out \
|
||||
test42.out \
|
||||
test44.out \
|
||||
|
@ -73,7 +73,7 @@ VIMPROG = <->vim.exe
|
||||
|
||||
.SUFFIXES : .out .in
|
||||
|
||||
SCRIPT = test1.out test3.out \
|
||||
SCRIPT = test1.out \
|
||||
test39.out \
|
||||
test42.out test44.out test48.out test49.out \
|
||||
test64.out test69.out \
|
||||
|
10
src/testdir/dumps/Test_popupwin_10.dump
Normal file
10
src/testdir/dumps/Test_popupwin_10.dump
Normal file
@ -0,0 +1,10 @@
|
||||
>1+0&#ffffff0| @73
|
||||
|2| @73
|
||||
|3| @22|#+0#e000e06#5fd7ff255|i|n|c|l|u|d|e| |<+0#e000002&|s|t|d|i|o|.|h|>| +0#0000000#ffffff0@32
|
||||
|4| @22|i+0#00e0003#5fd7ff255|n|t| +0#0000000&|m|a|i|n|(|v+0#00e0003&|o|i|d|)+0#0000000&| @3| +0&#ffffff0@32
|
||||
|5| @22|{+0fd7ff255| @16| +0&#ffffff0@32
|
||||
|6| @22| +0fd7ff255@3|p|r|i|n|t|f|(|1+0#e000002&|2|3|)+0#0000000&|;| @1| +0&#ffffff0@32
|
||||
|7| @22|}+0fd7ff255| @16| +0&#ffffff0@32
|
||||
|8| @73
|
||||
|9| @73
|
||||
@57|1|,|1| @10|T|o|p|
|
10
src/testdir/dumps/Test_popupwin_11.dump
Normal file
10
src/testdir/dumps/Test_popupwin_11.dump
Normal file
@ -0,0 +1,10 @@
|
||||
>1+0&#ffffff0| @73
|
||||
|2| @73
|
||||
|3| @18|#+0#e000e06#e0e0e08|i|n|c|l|u|d|e| |<+0#e000002&|s|t|d|i|o|.|h|>| +0#0000000#ffffff0@36
|
||||
|4| @18|i+0#00e0003#e0e0e08|n|t| +0#0000000&|m|a|i|n|(|v+0#00e0003&|o|i|d|)+0#0000000&| @3| +0&#ffffff0@36
|
||||
|5| @18|{+0&#e0e0e08| @16| +0&#ffffff0@36
|
||||
|6| @18| +0&#e0e0e08@3|p|r|i|n|t|f|(|5+0#e000002&|6|7|)+0#0000000&|;| @1| +0&#ffffff0@36
|
||||
|7| @18|}+0&#e0e0e08| @16| +0&#ffffff0@36
|
||||
|8| @73
|
||||
|9| @73
|
||||
@57|1|,|1| @10|T|o|p|
|
15
src/testdir/dumps/Test_popupwin_20.dump
Normal file
15
src/testdir/dumps/Test_popupwin_20.dump
Normal file
@ -0,0 +1,15 @@
|
||||
>1+0&#ffffff0| @73
|
||||
|2| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@18
|
||||
|3| ||+0#0000001#ffd7ff255|h|e|l@1|o| |b|o|r|d|e|r||| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255|h|e|l@1|o| |p|a|d@1|i|n|g| | +0#0000000#ffffff0@4||+0#0000001#ffd7ff255| @11||| +0#0000000#ffffff0@18
|
||||
|4| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4||+0#0000001#ffd7ff255| |h|e|l@1|o| |b|o|t|h| ||| +0#0000000#ffffff0@18
|
||||
|5| @40||+0#0000001#ffd7ff255| @11||| +0#0000000#ffffff0@18
|
||||
|6| |++0#0000001#ffd7ff255|-@8| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@18
|
||||
|7| ||+0#0000001#ffd7ff255|b|o|r|d|e|r| |T|L| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@3|p|a|d@1|i|n|g|s| @2| +0#0000000#ffffff0@37
|
||||
|8| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@37
|
||||
|9| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@37
|
||||
|1|0| @72
|
||||
|1@1| @72
|
||||
|1|2| @72
|
||||
|1|3| @72
|
||||
|1|4| @72
|
||||
@57|1|,|1| @10|T|o|p|
|
15
src/testdir/dumps/Test_popupwin_21.dump
Normal file
15
src/testdir/dumps/Test_popupwin_21.dump
Normal file
@ -0,0 +1,15 @@
|
||||
>1+0&#ffffff0| @73
|
||||
|2| |╔+0#0000001#ffd7ff255|═@11|╗| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|╔+0#0000001#ffd7ff255|═@11|╗| +0#0000000#ffffff0@18
|
||||
|3| |║+0#0000001#ffd7ff255|h|e|l@1|o| |b|o|r|d|e|r|║| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255|h|e|l@1|o| |p|a|d@1|i|n|g| | +0#0000000#ffffff0@4|║+0#0000001#ffd7ff255| @11|║| +0#0000000#ffffff0@18
|
||||
|4| |╚+0#0000001#ffd7ff255|═@11|╝| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|║+0#0000001#ffd7ff255| |h|e|l@1|o| |b|o|t|h| |║| +0#0000000#ffffff0@18
|
||||
|5| @40|║+0#0000001#ffd7ff255| @11|║| +0#0000000#ffffff0@18
|
||||
|6| |╔+0#0000001#ffd7ff255|═@8| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|╚+0#0000001#ffd7ff255|═@11|╝| +0#0000000#ffffff0@18
|
||||
|7| |║+0#0000001#ffd7ff255|b|o|r|d|e|r| |T|L| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@3|p|a|d@1|i|n|g|s| @2| +0#0000000#ffffff0@37
|
||||
|8| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@37
|
||||
|9| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@37
|
||||
|1|0| @72
|
||||
|1@1| @72
|
||||
|1|2| @72
|
||||
|1|3| @72
|
||||
|1|4| @72
|
||||
@57|1|,|1| @10|T|o|p|
|
10
src/testdir/dumps/Test_popupwin_nowrap.dump
Normal file
10
src/testdir/dumps/Test_popupwin_nowrap.dump
Normal file
@ -0,0 +1,10 @@
|
||||
>1+0&#ffffff0| @73
|
||||
|2| @73
|
||||
|3| @17|a+0#0000001#ffd7ff255| |l|o|n|g| |l|i|n| +0#0000000#ffffff0@45
|
||||
|4| @73
|
||||
|5| @73
|
||||
|6| @73
|
||||
|7| @73
|
||||
|8| @73
|
||||
|9| @73
|
||||
@57|1|,|1| @10|T|o|p|
|
10
src/testdir/dumps/Test_popupwin_wrap.dump
Normal file
10
src/testdir/dumps/Test_popupwin_wrap.dump
Normal file
@ -0,0 +1,10 @@
|
||||
>1+0&#ffffff0| @73
|
||||
|2| @73
|
||||
|3| @17|a+0#0000001#ffd7ff255| |l|o|n|g| |l|i|n| +0#0000000#ffffff0@45
|
||||
|4| @17|e+0#0000001#ffd7ff255| |t|h|a|t| |w|o|n| +0#0000000#ffffff0@45
|
||||
|5| @17|t+0#0000001#ffd7ff255| |f|i|t| @4| +0#0000000#ffffff0@45
|
||||
|6| @73
|
||||
|7| @73
|
||||
|8| @73
|
||||
|9| @73
|
||||
@57|1|,|1| @10|T|o|p|
|
2354
src/testdir/test3.in
2354
src/testdir/test3.in
File diff suppressed because it is too large
Load Diff
2102
src/testdir/test3.ok
2102
src/testdir/test3.ok
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -94,8 +94,6 @@ func Test_win_execute()
|
||||
let line = win_execute(popupwin, 'echo getline(1)')
|
||||
call assert_match('the popup win', line)
|
||||
|
||||
call assert_fails('call win_execute(popupwin, "bwipe!")', 'E937:')
|
||||
|
||||
call popup_close(popupwin)
|
||||
endif
|
||||
|
||||
|
@ -97,13 +97,14 @@ func Test_memory_func_capture_vargs()
|
||||
let after = s:monitor_memory_usage(vim.pid)
|
||||
|
||||
" Estimate the limit of max usage as 2x initial usage.
|
||||
" The lower limit can fluctuate a bit, use 98%.
|
||||
call assert_inrange(before * 98 / 100, 2 * before, after.max)
|
||||
" The lower limit can fluctuate a bit, use 97%.
|
||||
call assert_inrange(before * 97 / 100, 2 * before, after.max)
|
||||
|
||||
" In this case, garbage collecting is not needed.
|
||||
" The value might fluctuate a bit, allow for 3% tolerance.
|
||||
" The value might fluctuate a bit, allow for 3% tolerance below and 5% above.
|
||||
" Based on various test runs.
|
||||
let lower = after.last * 97 / 100
|
||||
let upper = after.last * 103 / 100
|
||||
let upper = after.last * 105 / 100
|
||||
call assert_inrange(lower, upper, after.max)
|
||||
|
||||
call vim.stop()
|
||||
|
@ -56,6 +56,171 @@ func Test_simple_popup()
|
||||
call delete('XtestPopup')
|
||||
endfunc
|
||||
|
||||
func Test_popup_with_border_and_padding()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
|
||||
for iter in range(0, 1)
|
||||
call writefile([iter == 1 ? '' : 'set enc=latin1',
|
||||
\ "call setline(1, range(1, 100))",
|
||||
\ "call popup_create('hello border', {'line': 2, 'col': 3, 'border': []})",
|
||||
\ "call popup_create('hello padding', {'line': 2, 'col': 23, 'padding': []})",
|
||||
\ "call popup_create('hello both', {'line': 2, 'col': 43, 'border': [], 'padding': []})",
|
||||
\ "call popup_create('border TL', {'line': 6, 'col': 3, 'border': [1, 0, 0, 4]})",
|
||||
\ "call popup_create('paddings', {'line': 6, 'col': 23, 'padding': [1, 3, 2, 4]})",
|
||||
\], 'XtestPopupBorder')
|
||||
let buf = RunVimInTerminal('-S XtestPopupBorder', {'rows': 15})
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_2' .. iter, {})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopupBorder')
|
||||
endfor
|
||||
|
||||
let with_border_or_padding = {
|
||||
\ 'line': 2,
|
||||
\ 'core_line': 3,
|
||||
\ 'col': 3,
|
||||
\ 'core_col': 4,
|
||||
\ 'width': 14,
|
||||
\ 'core_width': 12,
|
||||
\ 'height': 3,
|
||||
\ 'core_height': 1,
|
||||
\ 'visible': 1}
|
||||
let winid = popup_create('hello border', {'line': 2, 'col': 3, 'border': []})",
|
||||
call assert_equal(with_border_or_padding, popup_getpos(winid))
|
||||
|
||||
let winid = popup_create('hello paddng', {'line': 2, 'col': 3, 'padding': []})
|
||||
call assert_equal(with_border_or_padding, popup_getpos(winid))
|
||||
|
||||
let winid = popup_create('hello both', {'line': 3, 'col': 8, 'border': [], 'padding': []})
|
||||
call assert_equal({
|
||||
\ 'line': 3,
|
||||
\ 'core_line': 5,
|
||||
\ 'col': 8,
|
||||
\ 'core_col': 10,
|
||||
\ 'width': 14,
|
||||
\ 'core_width': 10,
|
||||
\ 'height': 5,
|
||||
\ 'core_height': 1,
|
||||
\ 'visible': 1}, popup_getpos(winid))
|
||||
endfunc
|
||||
|
||||
func Test_popup_with_syntax_win_execute()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
call writefile([
|
||||
\ "call setline(1, range(1, 100))",
|
||||
\ "hi PopupColor ctermbg=lightblue",
|
||||
\ "let winid = popup_create([",
|
||||
\ "\\ '#include <stdio.h>',",
|
||||
\ "\\ 'int main(void)',",
|
||||
\ "\\ '{',",
|
||||
\ "\\ ' printf(123);',",
|
||||
\ "\\ '}',",
|
||||
\ "\\], {'line': 3, 'col': 25, 'highlight': 'PopupColor'})",
|
||||
\ "call win_execute(winid, 'set syntax=cpp')",
|
||||
\], 'XtestPopup')
|
||||
let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10})
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_10', {})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopup')
|
||||
endfunc
|
||||
|
||||
func Test_popup_with_syntax_setbufvar()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
let lines =<< trim END
|
||||
call setline(1, range(1, 100))
|
||||
hi PopupColor ctermbg=lightgrey
|
||||
let winid = popup_create([
|
||||
\ '#include <stdio.h>',
|
||||
\ 'int main(void)',
|
||||
\ '{',
|
||||
\ ' printf(567);',
|
||||
\ '}',
|
||||
\], {'line': 3, 'col': 21, 'highlight': 'PopupColor'})
|
||||
call setbufvar(winbufnr(winid), '&syntax', 'cpp')
|
||||
END
|
||||
call writefile(lines, 'XtestPopup')
|
||||
let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10})
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_11', {})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopup')
|
||||
endfunc
|
||||
|
||||
func Test_win_execute_closing_curwin()
|
||||
split
|
||||
let winid = popup_create('some text', {})
|
||||
call assert_fails('call win_execute(winid, winnr() .. "close")', 'E994')
|
||||
popupclear
|
||||
endfunc
|
||||
|
||||
func Test_win_execute_not_allowed()
|
||||
let winid = popup_create('some text', {})
|
||||
call assert_fails('call win_execute(winid, "split")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "vsplit")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "close")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "bdelete")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "bwipe!")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "tabnew")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "tabnext")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "next")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "rewind")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "buf")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "edit")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "enew")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "wincmd x")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "wincmd w")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "wincmd t")', 'E994:')
|
||||
call assert_fails('call win_execute(winid, "wincmd b")', 'E994:')
|
||||
popupclear
|
||||
endfunc
|
||||
|
||||
func Test_popup_with_wrap()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
let lines =<< trim END
|
||||
call setline(1, range(1, 100))
|
||||
let winid = popup_create(
|
||||
\ 'a long line that wont fit',
|
||||
\ {'line': 3, 'col': 20, 'maxwidth': 10, 'wrap': 1})
|
||||
END
|
||||
call writefile(lines, 'XtestPopup')
|
||||
let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10})
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_wrap', {})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopup')
|
||||
endfunc
|
||||
|
||||
func Test_popup_without_wrap()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
let lines =<< trim END
|
||||
call setline(1, range(1, 100))
|
||||
let winid = popup_create(
|
||||
\ 'a long line that wont fit',
|
||||
\ {'line': 3, 'col': 20, 'maxwidth': 10, 'wrap': 0})
|
||||
END
|
||||
call writefile(lines, 'XtestPopup')
|
||||
let buf = RunVimInTerminal('-S XtestPopup', {'rows': 10})
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_nowrap', {})
|
||||
|
||||
" clean up
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopup')
|
||||
endfunc
|
||||
|
||||
func Test_popup_time()
|
||||
if !has('timers')
|
||||
return
|
||||
@ -108,19 +273,23 @@ func Test_popup_hide()
|
||||
redraw
|
||||
let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '')
|
||||
call assert_equal('world', line)
|
||||
call assert_equal(1, popup_getposition(winid).visible)
|
||||
call assert_equal(1, popup_getpos(winid).visible)
|
||||
" buffer is still listed and active
|
||||
call assert_match(winbufnr(winid) .. 'u a.*\[Popup\]', execute('ls u'))
|
||||
|
||||
call popup_hide(winid)
|
||||
redraw
|
||||
let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '')
|
||||
call assert_equal('hello', line)
|
||||
call assert_equal(0, popup_getposition(winid).visible)
|
||||
call assert_equal(0, popup_getpos(winid).visible)
|
||||
" buffer is still listed but hidden
|
||||
call assert_match(winbufnr(winid) .. 'u h.*\[Popup\]', execute('ls u'))
|
||||
|
||||
call popup_show(winid)
|
||||
redraw
|
||||
let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '')
|
||||
call assert_equal('world', line)
|
||||
call assert_equal(1, popup_getposition(winid).visible)
|
||||
call assert_equal(1, popup_getpos(winid).visible)
|
||||
|
||||
|
||||
call popup_close(winid)
|
||||
@ -168,7 +337,7 @@ func Test_popup_move()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_popup_getposition()
|
||||
func Test_popup_getpos()
|
||||
let winid = popup_create('hello', {
|
||||
\ 'line': 2,
|
||||
\ 'col': 3,
|
||||
@ -176,7 +345,7 @@ func Test_popup_getposition()
|
||||
\ 'minheight': 11,
|
||||
\})
|
||||
redraw
|
||||
let res = popup_getposition(winid)
|
||||
let res = popup_getpos(winid)
|
||||
call assert_equal(2, res.line)
|
||||
call assert_equal(3, res.col)
|
||||
call assert_equal(10, res.width)
|
||||
@ -198,7 +367,7 @@ func Test_popup_width_longest()
|
||||
for test in tests
|
||||
let winid = popup_create(test[0], {'line': 2, 'col': 3})
|
||||
redraw
|
||||
let position = popup_getposition(winid)
|
||||
let position = popup_getpos(winid)
|
||||
call assert_equal(test[1], position.width)
|
||||
call popup_close(winid)
|
||||
endfor
|
||||
@ -214,12 +383,12 @@ func Test_popup_wraps()
|
||||
let winid = popup_create(test[0],
|
||||
\ {'line': 2, 'col': 3, 'maxwidth': 12})
|
||||
redraw
|
||||
let position = popup_getposition(winid)
|
||||
let position = popup_getpos(winid)
|
||||
call assert_equal(test[1], position.width)
|
||||
call assert_equal(test[2], position.height)
|
||||
|
||||
call popup_close(winid)
|
||||
call assert_equal({}, popup_getposition(winid))
|
||||
call assert_equal({}, popup_getpos(winid))
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
@ -287,3 +456,113 @@ func Test_popup_option_values()
|
||||
call popup_close(winid)
|
||||
bwipe
|
||||
endfunc
|
||||
|
||||
func Test_popup_atcursor()
|
||||
topleft vnew
|
||||
call setline(1, [
|
||||
\ 'xxxxxxxxxxxxxxxxx',
|
||||
\ 'xxxxxxxxxxxxxxxxx',
|
||||
\ 'xxxxxxxxxxxxxxxxx',
|
||||
\])
|
||||
|
||||
call cursor(2, 2)
|
||||
redraw
|
||||
let winid = popup_atcursor('vim', {})
|
||||
redraw
|
||||
let line = join(map(range(1, 17), 'screenstring(1, v:val)'), '')
|
||||
call assert_equal('xvimxxxxxxxxxxxxx', line)
|
||||
call popup_close(winid)
|
||||
|
||||
call cursor(3, 4)
|
||||
redraw
|
||||
let winid = popup_atcursor('vim', {})
|
||||
redraw
|
||||
let line = join(map(range(1, 17), 'screenstring(2, v:val)'), '')
|
||||
call assert_equal('xxxvimxxxxxxxxxxx', line)
|
||||
call popup_close(winid)
|
||||
|
||||
call cursor(1, 1)
|
||||
redraw
|
||||
let winid = popup_create('vim', {
|
||||
\ 'line': 'cursor+2',
|
||||
\ 'col': 'cursor+1',
|
||||
\})
|
||||
redraw
|
||||
let line = join(map(range(1, 17), 'screenstring(3, v:val)'), '')
|
||||
call assert_equal('xvimxxxxxxxxxxxxx', line)
|
||||
call popup_close(winid)
|
||||
|
||||
call cursor(3, 3)
|
||||
redraw
|
||||
let winid = popup_create('vim', {
|
||||
\ 'line': 'cursor-2',
|
||||
\ 'col': 'cursor-1',
|
||||
\})
|
||||
redraw
|
||||
let line = join(map(range(1, 17), 'screenstring(1, v:val)'), '')
|
||||
call assert_equal('xvimxxxxxxxxxxxxx', line)
|
||||
call popup_close(winid)
|
||||
|
||||
" just enough room above
|
||||
call cursor(3, 3)
|
||||
redraw
|
||||
let winid = popup_atcursor(['vim', 'is great'], {})
|
||||
redraw
|
||||
let pos = popup_getpos(winid)
|
||||
call assert_equal(1, pos.line)
|
||||
call popup_close(winid)
|
||||
|
||||
" not enough room above, popup goes below the cursor
|
||||
call cursor(3, 3)
|
||||
redraw
|
||||
let winid = popup_atcursor(['vim', 'is', 'great'], {})
|
||||
redraw
|
||||
let pos = popup_getpos(winid)
|
||||
call assert_equal(4, pos.line)
|
||||
call popup_close(winid)
|
||||
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_popup_filter()
|
||||
new
|
||||
call setline(1, 'some text')
|
||||
|
||||
func MyPopupFilter(winid, c)
|
||||
if a:c == 'e'
|
||||
let g:eaten = 'e'
|
||||
return 1
|
||||
endif
|
||||
if a:c == '0'
|
||||
let g:ignored = '0'
|
||||
return 0
|
||||
endif
|
||||
if a:c == 'x'
|
||||
call popup_close(a:winid)
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunc
|
||||
|
||||
let winid = popup_create('something', {'filter': 'MyPopupFilter'})
|
||||
redraw
|
||||
|
||||
" e is consumed by the filter
|
||||
call feedkeys('e', 'xt')
|
||||
call assert_equal('e', g:eaten)
|
||||
|
||||
" 0 is ignored by the filter
|
||||
normal $
|
||||
call assert_equal(9, getcurpos()[2])
|
||||
call feedkeys('0', 'xt')
|
||||
call assert_equal('0', g:ignored)
|
||||
call assert_equal(1, getcurpos()[2])
|
||||
|
||||
" x closes the popup
|
||||
call feedkeys('x', 'xt')
|
||||
call assert_equal('e', g:eaten)
|
||||
call assert_equal(-1, winbufnr(winid))
|
||||
|
||||
delfunc MyPopupFilter
|
||||
popupclear
|
||||
endfunc
|
||||
|
@ -38,7 +38,7 @@ func Test_writefile_fails_conversion()
|
||||
endif
|
||||
" Without a backup file the write won't happen if there is a conversion
|
||||
" error.
|
||||
set nobackup nowritebackup
|
||||
set nobackup nowritebackup backupdir=. backupskip=
|
||||
new
|
||||
let contents = ["line one", "line two"]
|
||||
call writefile(contents, 'Xfile')
|
||||
@ -49,7 +49,7 @@ func Test_writefile_fails_conversion()
|
||||
|
||||
call delete('Xfile')
|
||||
bwipe!
|
||||
set backup& writebackup&
|
||||
set backup& writebackup& backupdir&vim backupskip&vim
|
||||
endfunc
|
||||
|
||||
func Test_writefile_fails_conversion2()
|
||||
@ -58,7 +58,7 @@ func Test_writefile_fails_conversion2()
|
||||
endif
|
||||
" With a backup file the write happens even if there is a conversion error,
|
||||
" but then the backup file must remain
|
||||
set nobackup writebackup
|
||||
set nobackup writebackup backupdir=. backupskip=
|
||||
let contents = ["line one", "line two"]
|
||||
call writefile(contents, 'Xfile_conversion_err')
|
||||
edit Xfile_conversion_err
|
||||
@ -71,6 +71,7 @@ func Test_writefile_fails_conversion2()
|
||||
call delete('Xfile_conversion_err')
|
||||
call delete('Xfile_conversion_err~')
|
||||
bwipe!
|
||||
set backup& writebackup& backupdir&vim backupskip&vim
|
||||
endfunc
|
||||
|
||||
func SetFlag(timer)
|
||||
|
@ -1446,6 +1446,30 @@ func_call(
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke call_func() with a callback.
|
||||
*/
|
||||
int
|
||||
call_callback(
|
||||
callback_T *callback,
|
||||
int len, // length of "name" or -1 to use strlen()
|
||||
typval_T *rettv, // return value goes here
|
||||
int argcount, // number of "argvars"
|
||||
typval_T *argvars, // vars for arguments, must have "argcount"
|
||||
// PLUS ONE elements!
|
||||
int (* argv_func)(int, typval_T *, int),
|
||||
// function to fill in argvars
|
||||
linenr_T firstline, // first line of range
|
||||
linenr_T lastline, // last line of range
|
||||
int *doesrange, // return: function handled range
|
||||
int evaluate,
|
||||
dict_T *selfdict) // Dictionary for "self"
|
||||
{
|
||||
return call_func(callback->cb_name, len, rettv, argcount, argvars,
|
||||
argv_func, firstline, lastline, doesrange, evaluate,
|
||||
callback->cb_partial, selfdict);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call a function with its resolved parameters
|
||||
*
|
||||
|
@ -767,6 +767,46 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1444,
|
||||
/**/
|
||||
1443,
|
||||
/**/
|
||||
1442,
|
||||
/**/
|
||||
1441,
|
||||
/**/
|
||||
1440,
|
||||
/**/
|
||||
1439,
|
||||
/**/
|
||||
1438,
|
||||
/**/
|
||||
1437,
|
||||
/**/
|
||||
1436,
|
||||
/**/
|
||||
1435,
|
||||
/**/
|
||||
1434,
|
||||
/**/
|
||||
1433,
|
||||
/**/
|
||||
1432,
|
||||
/**/
|
||||
1431,
|
||||
/**/
|
||||
1430,
|
||||
/**/
|
||||
1429,
|
||||
/**/
|
||||
1428,
|
||||
/**/
|
||||
1427,
|
||||
/**/
|
||||
1426,
|
||||
/**/
|
||||
1425,
|
||||
/**/
|
||||
1424,
|
||||
/**/
|
||||
|
@ -615,7 +615,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
|
||||
|
||||
// Values for w_popup_flags.
|
||||
#define POPF_HIDDEN 1 // popup is not displayed
|
||||
#define POPF_REDRAWN 2 // popup was just redrawn
|
||||
#define POPF_HANDLED 2 // popup was just redrawn or filtered
|
||||
|
||||
/*
|
||||
* Terminal highlighting attribute bits.
|
||||
|
60
src/window.c
60
src/window.c
@ -87,7 +87,8 @@ do_window(
|
||||
#endif
|
||||
char_u cbuf[40];
|
||||
|
||||
Prenum1 = Prenum == 0 ? 1 : Prenum;
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
|
||||
#ifdef FEAT_CMDWIN
|
||||
# define CHECK_CMDWIN \
|
||||
@ -102,6 +103,8 @@ do_window(
|
||||
# define CHECK_CMDWIN do { /**/ } while (0)
|
||||
#endif
|
||||
|
||||
Prenum1 = Prenum == 0 ? 1 : Prenum;
|
||||
|
||||
switch (nchar)
|
||||
{
|
||||
/* split current window in two parts, horizontally */
|
||||
@ -732,6 +735,9 @@ cmd_with_count(
|
||||
int
|
||||
win_split(int size, int flags)
|
||||
{
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return FAIL;
|
||||
|
||||
/* When the ":tab" modifier was used open a new tab page instead. */
|
||||
if (may_open_tabpage() == OK)
|
||||
return OK;
|
||||
@ -1509,7 +1515,9 @@ win_exchange(long Prenum)
|
||||
win_T *wp2;
|
||||
int temp;
|
||||
|
||||
if (ONE_WINDOW) /* just one window */
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
if (ONE_WINDOW) // just one window
|
||||
{
|
||||
beep_flush();
|
||||
return;
|
||||
@ -2363,6 +2371,9 @@ win_close(win_T *win, int free_buf)
|
||||
tabpage_T *prev_curtab = curtab;
|
||||
frame_T *win_frame = win->w_frame->fr_parent;
|
||||
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return FAIL;
|
||||
|
||||
if (last_window())
|
||||
{
|
||||
emsg(_("E444: Cannot close last window"));
|
||||
@ -4221,6 +4232,8 @@ win_goto(win_T *wp)
|
||||
win_T *owp = curwin;
|
||||
#endif
|
||||
|
||||
if (NOT_IN_POPUP_WINDOW)
|
||||
return;
|
||||
if (text_locked())
|
||||
{
|
||||
beep_flush();
|
||||
@ -4831,6 +4844,9 @@ win_free(
|
||||
#ifdef FEAT_MENU
|
||||
remove_winbar(wp);
|
||||
#endif
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
free_callback(&wp->w_filter_cb);
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_SYN_HL
|
||||
vim_free(wp->w_p_cc_cols);
|
||||
@ -6495,6 +6511,20 @@ switch_win(
|
||||
int no_display)
|
||||
{
|
||||
block_autocmds();
|
||||
return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
|
||||
}
|
||||
|
||||
/*
|
||||
* As switch_win() but without blocking autocommands.
|
||||
*/
|
||||
int
|
||||
switch_win_noblock(
|
||||
win_T **save_curwin,
|
||||
tabpage_T **save_curtab,
|
||||
win_T *win,
|
||||
tabpage_T *tp,
|
||||
int no_display)
|
||||
{
|
||||
*save_curwin = curwin;
|
||||
if (tp != NULL)
|
||||
{
|
||||
@ -6524,9 +6554,22 @@ switch_win(
|
||||
*/
|
||||
void
|
||||
restore_win(
|
||||
win_T *save_curwin UNUSED,
|
||||
tabpage_T *save_curtab UNUSED,
|
||||
int no_display UNUSED)
|
||||
win_T *save_curwin,
|
||||
tabpage_T *save_curtab,
|
||||
int no_display)
|
||||
{
|
||||
restore_win_noblock(save_curwin, save_curtab, no_display);
|
||||
unblock_autocmds();
|
||||
}
|
||||
|
||||
/*
|
||||
* As restore_win() but without unblocking autocommands.
|
||||
*/
|
||||
void
|
||||
restore_win_noblock(
|
||||
win_T *save_curwin,
|
||||
tabpage_T *save_curtab,
|
||||
int no_display)
|
||||
{
|
||||
if (save_curtab != NULL && valid_tabpage(save_curtab))
|
||||
{
|
||||
@ -6546,7 +6589,12 @@ restore_win(
|
||||
curwin = save_curwin;
|
||||
curbuf = curwin->w_buffer;
|
||||
}
|
||||
unblock_autocmds();
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
else if (bt_popup(curwin->w_buffer))
|
||||
// original window was closed and now we're in a popup window: Go
|
||||
// to the first valid window.
|
||||
win_goto(firstwin);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user