Compare commits

...

19 Commits

Author SHA1 Message Date
Bram Moolenaar
74240d3feb patch 8.0.1384: not enough quickfix help; confusing winid
Problem:    Not enough quickfix help; confusing winid.
Solution:   Add more examples in the help. When the quickfix window is not
            present, return zero for getqflist() with 'winid'. Add more tests
            for jumping to quickfix list entries. (Yegappan Lakshmanan, closes
            #2427)
2017-12-10 15:26:15 +01:00
Bram Moolenaar
35c5e8155d patch 8.0.1383: local additions in help skips some files
Problem:    Local additions in help skips some files. (joshklod)
Solution:   Check the base file name length equals.
2017-12-09 21:10:13 +01:00
Bram Moolenaar
f405c8fe85 patch 8.0.1382: get "no write since last change" message if terminal is open
Problem:    Get "no write since last change" message if a terminal is open.
            (Fritz mehner)
Solution:   Don't consider a buffer changed if it's a terminal window.
2017-12-09 19:51:49 +01:00
Bram Moolenaar
620ca2da37 patch 8.0.1381: ch_readraw() waits for NL if channel mode is NL
Problem:    ch_readraw() waits for NL if channel mode is NL.
Solution:   Pass a "raw" flag to channel_read_block(). (Yasuhiro Matsumoto)
2017-12-09 19:13:13 +01:00
Bram Moolenaar
05684310a5 patch 8.0.1380: using "vim -r swapfile" the hit-enter prompt is misplaced.
Problem:    When recovering a file with "vim -r swapfile" the hit-enter prompt
            is at the top of the window.
Solution:   Invalidate the cursor position.
2017-12-09 15:11:24 +01:00
Bram Moolenaar
e4b78e2a42 patch 8.0.1379: configure check for selinux does not check for header file
Problem:    Configure check for selinux does not check for header file.
Solution:   Add an AC_CHECK_HEADER(). (Benny Siegert)
2017-12-07 22:29:11 +01:00
Bram Moolenaar
3388d33457 patch 8.0.1378: autoload script sources itself when defining function
Problem:    Autoload script sources itself when defining function.
Solution:   Pass TFN_NO_AUTOLOAD to trans_function_name(). (Yasuhiro
            Matsumoto, closes #2423)
2017-12-07 22:23:04 +01:00
Bram Moolenaar
6e65d594aa patch 8.0.1377: cannot call a dict function in autoloaded dict
Problem:    Cannot call a dict function in autoloaded dict.
Solution:   Call get_lval() passing the read-only flag.
2017-12-07 22:11:27 +01:00
Bram Moolenaar
23c1b2b018 patch 8.0.1376: cursor in terminal not always updated
Problem:    Cursor in terminal not always updated.
Solution:   Call gui_mch_flush(). (Ken Takata)
2017-12-05 21:32:33 +01:00
Bram Moolenaar
415a6939a4 patch 8.0.1375: window size wrong after maximizing with WinBar
Problem:    Window size wrong after maximizing with WinBar. (Lifepillar)
Solution:   Fix height computations. Redraw window when it is zero height but
            has a WinBar. (closes #2356)
2017-12-05 20:31:07 +01:00
Bram Moolenaar
5fe6bdf858 patch 8.0.1374: CTRL-A does not work with an empty line
Problem:    CTRL-A does not work with an empty line. (Alex)
Solution:   Decrement the end only once. (Hirohito Higashi, closes #2387)
2017-12-05 17:22:12 +01:00
Bram Moolenaar
3767c6e9ee patch 8.0.1373: no error when settting 'renderoptions' before starting GUI
Problem:    No error when settting 'renderoptions' to an invalid value before
            starting the GUI.
Solution:   Always check the value. (Ken Takata, closes #2413)
2017-12-05 16:57:56 +01:00
Bram Moolenaar
ac112f01a6 patch 8.0.1372: profile log may be truncated halfway a character
Problem:    Profile log may be truncated halfway a character.
Solution:   Find the start of the character. (Ozaki Kiichi, closes #2385)
2017-12-05 16:46:28 +01:00
Bram Moolenaar
feeb4d0901 patch 8.0.1371: Shift-Insert doesn't always work in MS-Windows console
Problem:    Shift-Insert doesn't always work in MS-Windows console.
Solution:   Handle K_NUL differently if the second character is more than one
            byte. (Yasuhiro Matsumoto, closes #2381)
2017-12-05 15:14:46 +01:00
Bram Moolenaar
1eca6f13d6 patch 8.0.1370: channel test for callback is flaky
Problem:    Channel test for callback is flaky.
Solution:   Add the test to thelist of flaky tests.
2017-12-05 14:04:27 +01:00
Bram Moolenaar
92467d3351 patch 8.0.1369: MS-Windows: drawing underline slow, mFallbackDC not updated
Problem:    MS-Windows: drawing underline, curl and strike-throw is slow,
            mFallbackDC not properly updated.
Solution:   Several performance improvements. (Ken Takata, Taro Muraoka,
            Yasuhiro Matsumoto, closes #2401)
2017-12-05 13:22:16 +01:00
Bram Moolenaar
ce6179c799 patch 8.0.1368: cannot drag status or separator of new terminal window
Problem:    Cannot drag status line or vertical separator of new terminal
            window. (UncleBill)
Solution:   Adjust mouse row and column computation. (Yasuhiro Matsumoto,
            closes #2410)
2017-12-05 13:06:16 +01:00
Bram Moolenaar
461fe50fea patch 8.0.1367: terminal test hangs, executing abcde
Problem:    terminal test hangs, executing abcde. (Stucki)
Solution:   Rename abcde to abxde.
2017-12-05 12:30:03 +01:00
Bram Moolenaar
1ad022a9b8 patch 8.0.1367 2017-12-03 18:20:32 +01:00
43 changed files with 930 additions and 209 deletions

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.0. Last change: 2017 Nov 24
*eval.txt* For Vim version 8.0. Last change: 2017 Dec 09
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -2031,7 +2031,7 @@ assert_true({actual} [, {msg}]) none assert {actual} is true
asin({expr}) Float arc sine of {expr}
atan({expr}) Float arc tangent of {expr}
atan2({expr1}, {expr2}) Float arc tangent of {expr1} / {expr2}
balloon_show({msg}) none show {msg} inside the balloon
balloon_show({expr}) none show {expr} inside the balloon
balloon_split({msg}) List split {msg} as used for a balloon
browse({save}, {title}, {initdir}, {default})
String put up a file requester
@@ -3056,12 +3056,16 @@ ch_open({address} [, {options}]) *ch_open()*
ch_read({handle} [, {options}]) *ch_read()*
Read from {handle} and return the received message.
{handle} can be a Channel or a Job that has a Channel.
For a NL channel this waits for a NL to arrive, except when
there is nothing more to read (channel was closed).
See |channel-more|.
{only available when compiled with the |+channel| feature}
ch_readraw({handle} [, {options}]) *ch_readraw()*
Like ch_read() but for a JS and JSON channel does not decode
the message. See |channel-more|.
the message. For a NL channel it does not block waiting for
the NL to arrive, but otherwise works like ch_read().
See |channel-more|.
{only available when compiled with the |+channel| feature}
ch_sendexpr({handle}, {expr} [, {options}]) *ch_sendexpr()*
@@ -4679,9 +4683,10 @@ getqflist([{what}]) *getqflist()*
the last quickfix list
size number of entries in the quickfix list
title get the list title
winid get the |window-ID| (if opened)
winid get the quickfix |window-ID|
all all of the above quickfix properties
Non-string items in {what} are ignored.
Non-string items in {what} are ignored. To get the value of a
particular item, set it to one.
If "nr" is not present then the current quickfix list is used.
If both "nr" and a non-zero "id" are specified, then the list
specified by "id" is used.
@@ -4702,7 +4707,7 @@ getqflist([{what}]) *getqflist()*
nr quickfix list number
size number of entries in the quickfix list
title quickfix list title text
winid quickfix |window-ID| (if opened)
winid quickfix |window-ID|. If not present, set to 0
Examples: >
:echo getqflist({'all': 1})
@@ -8793,8 +8798,8 @@ writefile({list}, {fname} [, {flags}])
the file. This flushes the file to disk, if possible. This
takes more time but avoids losing the file if the system
crashes.
When {flags} does not contain "S" or "s" then fsync is called
if the 'fsync' option is set.
When {flags} does not contain "S" or "s" then fsync() is
called if the 'fsync' option is set.
When {flags} contains "S" then fsync() is not called, even
when 'fsync' is set.

View File

@@ -6122,9 +6122,10 @@ A jump table for the options with a short description can be found at |Q_op|.
geom pixelGeometry int 0 - 2 (see below)
renmode renderingMode int 0 - 6 (see below)
taamode textAntialiasMode int 0 - 3 (see below)
scrlines Scroll Lines int >= 0 (see below)
See this URL for detail:
http://msdn.microsoft.com/en-us/library/dd368190.aspx
See this URL for detail (except for scrlines):
https://msdn.microsoft.com/en-us/library/dd368190.aspx
For geom: structure of a device pixel.
0 - DWRITE_PIXEL_GEOMETRY_FLAT
@@ -6132,7 +6133,7 @@ A jump table for the options with a short description can be found at |Q_op|.
2 - DWRITE_PIXEL_GEOMETRY_BGR
See this URL for detail:
http://msdn.microsoft.com/en-us/library/dd368114.aspx
https://msdn.microsoft.com/en-us/library/dd368114.aspx
For renmode: method of rendering glyphs.
0 - DWRITE_RENDERING_MODE_DEFAULT
@@ -6144,7 +6145,7 @@ A jump table for the options with a short description can be found at |Q_op|.
6 - DWRITE_RENDERING_MODE_OUTLINE
See this URL for detail:
http://msdn.microsoft.com/en-us/library/dd368118.aspx
https://msdn.microsoft.com/en-us/library/dd368118.aspx
For taamode: antialiasing mode used for drawing text.
0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT
@@ -6153,7 +6154,25 @@ A jump table for the options with a short description can be found at |Q_op|.
3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED
See this URL for detail:
http://msdn.microsoft.com/en-us/library/dd368170.aspx
https://msdn.microsoft.com/en-us/library/dd368170.aspx
For scrlines: threshold for lines to be scrolled.
0 - Always use scrolling. (default)
1 - Use full page redrawing.
> 1 - If the lines to be scrolled is grater or equal to the
specified value, use redrawing. Otherwise use
scrolling.
If you feel scrolling a page (CTRL-F) is too slow with DirectX
renderer, try this "scrlines" option.
When set it "1", Vim uses full page redrawing instead of
scrolling. Redrawing a page is faster than scrolling a
page in some environments.
After that, when you feel scrolling lines (CTRL-Y) becomes
slow, please try "2" or greater value for this option.
It works threshold line number to switch scrolling to
redrawing. Scrolling a few lines might be faster than
redrawing a page in some environments.
Example: >
set encoding=utf-8
@@ -6162,13 +6181,12 @@ A jump table for the options with a short description can be found at |Q_op|.
<
If select a raster font (Courier, Terminal or FixedSys which
have ".fon" extension in file name) to 'guifont', it will be
drawn by GDI as a fallback. This fallback will cause
significant slow down on drawing.
drawn by GDI as a fallback.
NOTE: It is known that some fonts and options combination
causes trouble on drawing glyphs.
- 'rendmode:5' and 'renmode:6' will not work with some
- 'renmode:5' and 'renmode:6' will not work with some
special made fonts (True-Type fonts which includes only
bitmap glyphs).
- 'taamode:3' will not work with some vector fonts.

View File

@@ -341,6 +341,50 @@ use this code: >
au QuickfixCmdPost make call QfMakeConv()
Another option is using 'makeencoding'.
*quickfix-title*
Every quickfix and location list has a title. By default the title is set to
the command that created the list. The |getqflist()| and |getloclist()|
functions can be used to get the title of a quickfix and a location list
respectively. The |setqflist()| and |setloclist()| functions can be used to
modify the title of a quickfix and location list respectively. Examples: >
call setqflist([], 'a', {'title' : 'Cmd output'})
echo getqflist({'title' : 1})
call setloclist(3, [], 'a', {'title' : 'Cmd output'})
echo getloclist(3, {'title' : 1})
<
*quickfix-size*
You can get the number of entries (size) in a quickfix and a location list
using the |getqflist()| and |getloclist()| functions respectively. Examples: >
echo getqflist({'size' : 1})
echo getloclist(5, {'size' : 1})
<
*quickfix-context*
Any Vim type can be associated as a context with a quickfix or location list.
The |setqflist()| and the |setloclist()| functions can be used to associate a
context with a quickfix and a location list respectively. The |getqflist()|
and the |getloclist()| functions can be used to retrieve the context of a
quickifx and a location list respectively. This is useful for a Vim plugin
dealing with multiple quickfix/location lists.
Examples: >
let somectx = {'name' : 'Vim', 'type' : 'Editor'}
call setqflist([], 'a', {'context' : somectx})
echo getqflist({'context' : 1})
let newctx = ['red', 'green', 'blue']
call setloclist(2, [], 'a', {'id' : qfid, 'context' : newctx})
echo getloclist(2, {'id' : qfid, 'context' : 1})
<
*quickfix-parse*
You can parse a list of lines using 'erroformat' without creating or modifying
a quickfix list using the |getqflist()| function. Examples: >
echo getqflist({'lines' : ["F1:10:Line10", "F2:20:Line20"]})
echo getqflist({'lines' : systemlist('grep -Hn quickfix *')})
This returns a dictionary where the 'items' key contains the list of quickfix
entries parsed from lines. The following shows how to use a custom
'errorformat' to parse the lines without modifying the 'erroformat' option: >
echo getqflist({'efm' : '%f#%l#%m', 'lines' : ['F1#10#Line']})
<
EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
*:cdo*
@@ -542,6 +586,13 @@ In all of the above cases, if the location list for the selected window is not
yet set, then it is set to the location list displayed in the location list
window.
*quickfix-window-ID*
You can use the |getqflist()| and |getloclist()| functions to obtain the
window ID of the quickfix window and location list window respectively (if
present). Examples: >
echo getqflist({'winid' : 1}).winid
echo getloclist(2, {'winid' : 1}).winid
<
=============================================================================
3. Using more than one list of errors *quickfix-error-lists*
@@ -586,6 +637,14 @@ list, one newer list is overwritten. This is especially useful if you are
browsing with ":grep" |grep|. If you want to keep the more recent error
lists, use ":cnewer 99" first.
To get the number of lists in the quickfix and location list stack, you can
use the |getqflist()| and |getloclist()| functions respectively with the list
number set to the special value '$'. Examples: >
echo getqflist({'nr' : '$'}).nr
echo getloclist(3, {'nr' : '$'}).nr
To get the number of the current list in the stack: >
echo getqflist({'nr' : 0}).nr
<
=============================================================================
4. Using :make *:make_makeprg*

View File

@@ -2120,6 +2120,7 @@ test_arglist \
test_assign \
test_autochdir \
test_autocmd \
test_autoload \
test_backspace_opt \
test_breakindent \
test_bufline \

7
src/auto/configure vendored
View File

@@ -4781,8 +4781,13 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_is_selinux_enabled" >&5
$as_echo "$ac_cv_lib_selinux_is_selinux_enabled" >&6; }
if test "x$ac_cv_lib_selinux_is_selinux_enabled" = xyes; then :
ac_fn_c_check_header_mongrel "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default"
if test "x$ac_cv_header_selinux_selinux_h" = xyes; then :
LIBS="$LIBS -lselinux"
$as_echo "#define HAVE_SELINUX 1" >>confdefs.h
$as_echo "#define HAVE_SELINUX 1" >>confdefs.h
fi
fi

View File

@@ -50,7 +50,7 @@ get_beval_info(
}
#endif
wp = mouse_find_win(&row, &col);
if (wp != NULL && row < wp->w_height && col < wp->w_width)
if (wp != NULL && row >= 0 && row < wp->w_height && col < wp->w_width)
{
/* Found a window and the cursor is in the text. Now find the line
* number. */

View File

@@ -3313,11 +3313,12 @@ channel_read(channel_T *channel, ch_part_T part, char *func)
/*
* Read from RAW or NL "channel"/"part". Blocks until there is something to
* read or the timeout expires.
* When "raw" is TRUE don't block waiting on a NL.
* Returns what was read in allocated memory.
* Returns NULL in case of error or timeout.
*/
char_u *
channel_read_block(channel_T *channel, ch_part_T part, int timeout)
static char_u *
channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw)
{
char_u *buf;
char_u *msg;
@@ -3327,7 +3328,7 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout)
readq_T *node;
ch_log(channel, "Blocking %s read, timeout: %d msec",
mode == MODE_RAW ? "RAW" : "NL", timeout);
mode == MODE_RAW ? "RAW" : "NL", timeout);
while (TRUE)
{
@@ -3340,6 +3341,10 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout)
break;
if (channel_collapse(channel, part, mode == MODE_NL) == OK)
continue;
/* If not blocking or nothing more is coming then return what we
* have. */
if (raw || fd == INVALID_FD)
break;
}
/* Wait for up to the channel timeout. */
@@ -3366,11 +3371,16 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout)
nl = channel_first_nl(node);
/* Convert NUL to NL, the internal representation. */
for (p = buf; p < nl && p < buf + node->rq_buflen; ++p)
for (p = buf; (nl == NULL || p < nl) && p < buf + node->rq_buflen; ++p)
if (*p == NUL)
*p = NL;
if (nl + 1 == buf + node->rq_buflen)
if (nl == NULL)
{
/* must be a closed channel with missing NL */
msg = channel_get(channel, part);
}
else if (nl + 1 == buf + node->rq_buflen)
{
/* get the whole buffer */
msg = channel_get(channel, part);
@@ -3513,7 +3523,8 @@ common_channel_read(typval_T *argvars, typval_T *rettv, int raw)
timeout = opt.jo_timeout;
if (raw || mode == MODE_RAW || mode == MODE_NL)
rettv->vval.v_string = channel_read_block(channel, part, timeout);
rettv->vval.v_string = channel_read_block(channel, part,
timeout, raw);
else
{
if (opt.jo_set & JO_ID)
@@ -3955,7 +3966,8 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval)
timeout = opt.jo_timeout;
else
timeout = channel_get_timeout(channel, part_read);
rettv->vval.v_string = channel_read_block(channel, part_read, timeout);
rettv->vval.v_string = channel_read_block(channel, part_read,
timeout, TRUE);
}
free_job_options(&opt);
}

View File

@@ -433,8 +433,9 @@ if test "x$found_smack" = "x"; then
if test "$enable_selinux" = "yes"; then
AC_MSG_RESULT(no)
AC_CHECK_LIB(selinux, is_selinux_enabled,
[AC_CHECK_HEADER(selinux/selinux.h,
[LIBS="$LIBS -lselinux"
AC_DEFINE(HAVE_SELINUX)])
AC_DEFINE(HAVE_SELINUX)])])
else
AC_MSG_RESULT(yes)
fi

View File

@@ -1956,7 +1956,10 @@ get_lval(
cc = *p;
*p = NUL;
v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD);
/* Only pass &ht when we would write to the variable, it prevents autoload
* as well. */
v = find_var(lp->ll_name, (flags & GLV_READ_ONLY) ? NULL : &ht,
flags & GLV_NO_AUTOLOAD);
if (v == NULL && !quiet)
EMSG2(_(e_undefvar), lp->ll_name);
*p = cc;
@@ -6610,6 +6613,8 @@ get_vim_var_nr(int idx)
/*
* Get string v: variable value. Uses a static buffer, can only be used once.
* If the String variable has never been set, return an empty string.
* Never returns NULL;
*/
char_u *
get_vim_var_str(int idx)

View File

@@ -1482,7 +1482,7 @@ do_shell(
#endif
&& msg_silent == 0)
FOR_ALL_BUFFERS(buf)
if (bufIsChanged(buf))
if (bufIsChangedNotTerm(buf))
{
#ifdef FEAT_GUI_MSWIN
if (!winstart)
@@ -6934,13 +6934,10 @@ fix_help_buffer(void)
&& fcount > 0)
{
#ifdef FEAT_MULTI_LANG
int i1;
int i2;
char_u *f1;
char_u *f2;
char_u *t1;
char_u *e1;
char_u *e2;
int i1, i2;
char_u *f1, *f2;
char_u *t1, *t2;
char_u *e1, *e2;
/* If foo.abx is found use it instead of foo.txt in
* the same directory. */
@@ -6955,10 +6952,9 @@ fix_help_buffer(void)
f1 = fnames[i1];
f2 = fnames[i2];
t1 = gettail(f1);
if (fnamencmp(f1, f2, t1 - f1) != 0)
continue;
t2 = gettail(f2);
e1 = vim_strrchr(t1, '.');
e2 = vim_strrchr(gettail(f2), '.');
e2 = vim_strrchr(t2, '.');
if (e1 == NULL || e2 == NULL)
continue;
if (fnamecmp(e1, ".txt") != 0
@@ -6969,7 +6965,8 @@ fix_help_buffer(void)
fnames[i1] = NULL;
continue;
}
if (fnamencmp(f1, f2, e1 - f1) != 0)
if (e1 - f1 != e2 - f2
|| fnamencmp(f1, f2, e1 - f1) != 0)
continue;
if (fnamecmp(e1, ".txt") == 0
&& fnamecmp(e2, fname + 4) == 0)

View File

@@ -1834,6 +1834,26 @@ script_dump_profile(FILE *fd)
{
if (vim_fgets(IObuff, IOSIZE, sfd))
break;
/* When a line has been truncated, append NL, taking care
* of multi-byte characters . */
if (IObuff[IOSIZE - 2] != NUL && IObuff[IOSIZE - 2] != NL)
{
int n = IOSIZE - 2;
# ifdef FEAT_MBYTE
if (enc_utf8)
{
/* Move to the first byte of this char.
* utf_head_off() doesn't work, because it checks
* for a truncated character. */
while (n > 0 && (IObuff[n] & 0xc0) == 0x80)
--n;
}
else if (has_mbyte)
n -= mb_head_off(IObuff, IObuff + n);
# endif
IObuff[n] = NL;
IObuff[n + 1] = NUL;
}
if (i < si->sn_prl_ga.ga_len
&& (pp = &PRL_ITEM(si, i))->snp_count > 0)
{

View File

@@ -263,14 +263,24 @@ private:
}
};
enum DrawingMode {
DM_GDI = 0,
DM_DIRECTX = 1,
DM_INTEROP = 2,
};
struct DWriteContext {
HDC mHDC;
RECT mBindRect;
DrawingMode mDMode;
HDC mInteropHDC;
bool mDrawing;
bool mFallbackDC;
ID2D1Factory *mD2D1Factory;
ID2D1DCRenderTarget *mRT;
ID2D1GdiInteropRenderTarget *mGDIRT;
ID2D1SolidColorBrush *mBrush;
IDWriteFactory *mDWriteFactory;
@@ -292,6 +302,10 @@ struct DWriteContext {
virtual ~DWriteContext();
HRESULT CreateDeviceResources();
void DiscardDeviceResources();
HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
IDWriteTextFormat **ppTextFormat);
@@ -299,17 +313,21 @@ struct DWriteContext {
void SetFont(HFONT hFont);
void BindDC(HDC hdc, RECT *rect);
void BindDC(HDC hdc, const RECT *rect);
void AssureDrawing();
HRESULT SetDrawingMode(DrawingMode mode);
ID2D1Brush* SolidBrush(COLORREF color);
void DrawText(const WCHAR* text, int len,
void DrawText(const WCHAR *text, int len,
int x, int y, int w, int h, int cellWidth, COLORREF color,
UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx);
UINT fuOptions, const RECT *lprc, const INT *lpDx);
void FillRect(RECT *rc, COLORREF color);
void FillRect(const RECT *rc, COLORREF color);
void DrawLine(int x1, int y1, int x2, int y2, COLORREF color);
void SetPixel(int x, int y, COLORREF color);
void Flush();
@@ -561,10 +579,14 @@ private:
DWriteContext::DWriteContext() :
mHDC(NULL),
mBindRect(),
mDMode(DM_GDI),
mInteropHDC(NULL),
mDrawing(false),
mFallbackDC(false),
mD2D1Factory(NULL),
mRT(NULL),
mGDIRT(NULL),
mBrush(NULL),
mDWriteFactory(NULL),
mDWriteFactory2(NULL),
@@ -584,25 +606,7 @@ DWriteContext::DWriteContext() :
_RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory);
if (SUCCEEDED(hr))
{
D2D1_RENDER_TARGET_PROPERTIES props = {
D2D1_RENDER_TARGET_TYPE_DEFAULT,
{ DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
0, 0,
D2D1_RENDER_TARGET_USAGE_NONE,
D2D1_FEATURE_LEVEL_DEFAULT
};
hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT);
_RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT);
}
if (SUCCEEDED(hr))
{
hr = mRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&mBrush);
_RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush);
}
hr = CreateDeviceResources();
if (SUCCEEDED(hr))
{
@@ -645,10 +649,66 @@ DWriteContext::~DWriteContext()
SafeRelease(&mDWriteFactory);
SafeRelease(&mDWriteFactory2);
SafeRelease(&mBrush);
SafeRelease(&mGDIRT);
SafeRelease(&mRT);
SafeRelease(&mD2D1Factory);
}
HRESULT
DWriteContext::CreateDeviceResources()
{
HRESULT hr;
if (mRT != NULL)
return S_OK;
D2D1_RENDER_TARGET_PROPERTIES props = {
D2D1_RENDER_TARGET_TYPE_DEFAULT,
{ DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
0, 0,
D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,
D2D1_FEATURE_LEVEL_DEFAULT
};
hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT);
_RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT);
if (SUCCEEDED(hr))
{
// This always succeeds.
mRT->QueryInterface(
__uuidof(ID2D1GdiInteropRenderTarget),
reinterpret_cast<void**>(&mGDIRT));
_RPT1(_CRT_WARN, "GdiInteropRenderTarget: p=%p\n", mGDIRT);
}
if (SUCCEEDED(hr))
{
hr = mRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&mBrush);
_RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush);
}
if (SUCCEEDED(hr))
{
if (mHDC != NULL)
{
mRT->BindDC(mHDC, &mBindRect);
mRT->SetTransform(D2D1::IdentityMatrix());
}
}
return hr;
}
void
DWriteContext::DiscardDeviceResources()
{
SafeRelease(&mBrush);
SafeRelease(&mGDIRT);
SafeRelease(&mRT);
}
HRESULT
DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
IDWriteTextFormat **ppTextFormat)
@@ -817,27 +877,77 @@ DWriteContext::SetFont(HFONT hFont)
item.pTextFormat = mTextFormat;
item.fontWeight = mFontWeight;
item.fontStyle = mFontStyle;
mFallbackDC = false;
}
else
mFallbackDC = true;
mFontCache.put(item);
}
void
DWriteContext::BindDC(HDC hdc, RECT *rect)
DWriteContext::BindDC(HDC hdc, const RECT *rect)
{
Flush();
mRT->BindDC(hdc, rect);
mRT->SetTransform(D2D1::IdentityMatrix());
mHDC = hdc;
mBindRect = *rect;
}
void
DWriteContext::AssureDrawing()
HRESULT
DWriteContext::SetDrawingMode(DrawingMode mode)
{
if (mDrawing == false)
HRESULT hr = S_OK;
switch (mode)
{
mRT->BeginDraw();
mDrawing = true;
default:
case DM_GDI:
if (mInteropHDC != NULL)
{
mGDIRT->ReleaseDC(NULL);
mInteropHDC = NULL;
}
if (mDrawing)
{
hr = mRT->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
{
hr = S_OK;
DiscardDeviceResources();
CreateDeviceResources();
}
mDrawing = false;
}
break;
case DM_DIRECTX:
if (mInteropHDC != NULL)
{
mGDIRT->ReleaseDC(NULL);
mInteropHDC = NULL;
}
else if (mDrawing == false)
{
CreateDeviceResources();
mRT->BeginDraw();
mDrawing = true;
}
break;
case DM_INTEROP:
if (mDrawing == false)
{
CreateDeviceResources();
mRT->BeginDraw();
mDrawing = true;
}
if (mInteropHDC == NULL)
hr = mGDIRT->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &mInteropHDC);
break;
}
mDMode = mode;
return hr;
}
ID2D1Brush*
@@ -849,22 +959,31 @@ DWriteContext::SolidBrush(COLORREF color)
}
void
DWriteContext::DrawText(const WCHAR* text, int len,
DWriteContext::DrawText(const WCHAR *text, int len,
int x, int y, int w, int h, int cellWidth, COLORREF color,
UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx)
UINT fuOptions, const RECT *lprc, const INT *lpDx)
{
if (mFallbackDC)
{
Flush();
ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx);
// Fall back to GDI rendering.
HRESULT hr = SetDrawingMode(DM_INTEROP);
if (SUCCEEDED(hr))
{
HGDIOBJ hFont = ::GetCurrentObject(mHDC, OBJ_FONT);
HGDIOBJ hOldFont = ::SelectObject(mInteropHDC, hFont);
::SetTextColor(mInteropHDC, color);
::SetBkMode(mInteropHDC, ::GetBkMode(mHDC));
::ExtTextOutW(mInteropHDC, x, y, fuOptions, lprc, text, len, lpDx);
::SelectObject(mInteropHDC, hOldFont);
}
return;
}
AssureDrawing();
HRESULT hr;
IDWriteTextLayout *textLayout = NULL;
SetDrawingMode(DM_DIRECTX);
hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat,
FLOAT(w), FLOAT(h), &textLayout);
@@ -883,23 +1002,74 @@ DWriteContext::DrawText(const WCHAR* text, int len,
}
void
DWriteContext::FillRect(RECT *rc, COLORREF color)
DWriteContext::FillRect(const RECT *rc, COLORREF color)
{
AssureDrawing();
mRT->FillRectangle(
D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top),
FLOAT(rc->right), FLOAT(rc->bottom)),
SolidBrush(color));
if (mDMode == DM_INTEROP)
{
// GDI functions are used before this call. Keep using GDI.
// (Switching to Direct2D causes terrible slowdown.)
HBRUSH hbr = ::CreateSolidBrush(color);
::FillRect(mInteropHDC, rc, hbr);
::DeleteObject(HGDIOBJ(hbr));
}
else
{
SetDrawingMode(DM_DIRECTX);
mRT->FillRectangle(
D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top),
FLOAT(rc->right), FLOAT(rc->bottom)),
SolidBrush(color));
}
}
void
DWriteContext::DrawLine(int x1, int y1, int x2, int y2, COLORREF color)
{
if (mDMode == DM_INTEROP)
{
// GDI functions are used before this call. Keep using GDI.
// (Switching to Direct2D causes terrible slowdown.)
HPEN hpen = ::CreatePen(PS_SOLID, 1, color);
HGDIOBJ old_pen = ::SelectObject(mInteropHDC, HGDIOBJ(hpen));
::MoveToEx(mInteropHDC, x1, y1, NULL);
::LineTo(mInteropHDC, x2, y2);
::SelectObject(mInteropHDC, old_pen);
::DeleteObject(HGDIOBJ(hpen));
}
else
{
SetDrawingMode(DM_DIRECTX);
mRT->DrawLine(
D2D1::Point2F(FLOAT(x1), FLOAT(y1) + 0.5f),
D2D1::Point2F(FLOAT(x2), FLOAT(y2) + 0.5f),
SolidBrush(color));
}
}
void
DWriteContext::SetPixel(int x, int y, COLORREF color)
{
if (mDMode == DM_INTEROP)
{
// GDI functions are used before this call. Keep using GDI.
// (Switching to Direct2D causes terrible slowdown.)
::SetPixel(mInteropHDC, x, y, color);
}
else
{
SetDrawingMode(DM_DIRECTX);
// Direct2D doesn't have SetPixel API. Use DrawLine instead.
mRT->DrawLine(
D2D1::Point2F(FLOAT(x), FLOAT(y) + 0.5f),
D2D1::Point2F(FLOAT(x+1), FLOAT(y) + 0.5f),
SolidBrush(color));
}
}
void
DWriteContext::Flush()
{
if (mDrawing)
{
mRT->EndDraw();
mDrawing = false;
}
SetDrawingMode(DM_GDI);
}
void
@@ -1000,7 +1170,7 @@ DWriteContext_Open(void)
}
void
DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect)
DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect)
{
if (ctx != NULL)
ctx->BindDC(hdc, rect);
@@ -1016,7 +1186,7 @@ DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont)
void
DWriteContext_DrawText(
DWriteContext *ctx,
const WCHAR* text,
const WCHAR *text,
int len,
int x,
int y,
@@ -1025,8 +1195,8 @@ DWriteContext_DrawText(
int cellWidth,
COLORREF color,
UINT fuOptions,
CONST RECT *lprc,
CONST INT * lpDx)
const RECT *lprc,
const INT *lpDx)
{
if (ctx != NULL)
ctx->DrawText(text, len, x, y, w, h, cellWidth, color,
@@ -1034,12 +1204,27 @@ DWriteContext_DrawText(
}
void
DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color)
DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color)
{
if (ctx != NULL)
ctx->FillRect(rc, color);
}
void
DWriteContext_DrawLine(DWriteContext *ctx, int x1, int y1, int x2, int y2,
COLORREF color)
{
if (ctx != NULL)
ctx->DrawLine(x1, y1, x2, y2, color);
}
void
DWriteContext_SetPixel(DWriteContext *ctx, int x, int y, COLORREF color)
{
if (ctx != NULL)
ctx->SetPixel(x, y, color);
}
void
DWriteContext_Flush(DWriteContext *ctx)
{

View File

@@ -55,11 +55,11 @@ void DWrite_Init(void);
void DWrite_Final(void);
DWriteContext *DWriteContext_Open(void);
void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect);
void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect);
void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont);
void DWriteContext_DrawText(
DWriteContext *ctx,
const WCHAR* text,
const WCHAR *text,
int len,
int x,
int y,
@@ -68,9 +68,12 @@ void DWriteContext_DrawText(
int cellWidth,
COLORREF color,
UINT fuOptions,
CONST RECT *lprc,
CONST INT * lpDx);
void DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color);
const RECT *lprc,
const INT *lpDx);
void DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color);
void DWriteContext_DrawLine(DWriteContext *ctx, int x1, int y1, int x2, int y2,
COLORREF color);
void DWriteContext_SetPixel(DWriteContext *ctx, int x, int y, COLORREF color);
void DWriteContext_Flush(DWriteContext *ctx);
void DWriteContext_Close(DWriteContext *ctx);

View File

@@ -33,6 +33,7 @@
static DWriteContext *s_dwc = NULL;
static int s_directx_enabled = 0;
static int s_directx_load_attempted = 0;
static int s_directx_scrlines = 0;
# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL)
static int directx_enabled(void);
static void directx_binddc(void);
@@ -57,6 +58,7 @@ gui_mch_set_rendering_options(char_u *s)
int dx_geom = 0;
int dx_renmode = 0;
int dx_taamode = 0;
int dx_scrlines = 0;
/* parse string as rendering options. */
for (p = s; p != NULL && *p != NUL; )
@@ -117,10 +119,17 @@ gui_mch_set_rendering_options(char_u *s)
if (dx_taamode < 0 || dx_taamode > 3)
return FAIL;
}
else if (STRCMP(name, "scrlines") == 0)
{
dx_scrlines = atoi((char *)value);
}
else
return FAIL;
}
if (!gui.in_use)
return OK; /* only checking the syntax of the value */
/* Enable DirectX/DirectWrite */
if (dx_enable)
{
@@ -147,6 +156,7 @@ gui_mch_set_rendering_options(char_u *s)
}
}
s_directx_enabled = dx_enable;
s_directx_scrlines = dx_scrlines;
return OK;
#else
@@ -283,6 +293,7 @@ typedef int UINT_PTR;
#endif
static void _OnPaint( HWND hwnd);
static void fill_rect(const RECT *rcp, HBRUSH hbr, COLORREF color);
static void clear_rect(RECT *rcp);
static WORD s_dlgfntheight; /* height of the dialog font */
@@ -605,10 +616,7 @@ _OnBlinkTimer(
blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
(TIMERPROC)_OnBlinkTimer);
}
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
gui_mch_flush();
}
static void
@@ -634,7 +642,10 @@ gui_mch_stop_blink(void)
{
gui_mswin_rm_blink_timer();
if (blink_state == BLINK_OFF)
{
gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
}
blink_state = BLINK_NONE;
}
@@ -654,6 +665,7 @@ gui_mch_start_blink(void)
(TIMERPROC)_OnBlinkTimer);
blink_state = BLINK_ON;
gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
}
}
@@ -1730,7 +1742,6 @@ gui_mch_draw_part_cursor(
int h,
guicolor_T color)
{
HBRUSH hbr;
RECT rc;
/*
@@ -1746,14 +1757,7 @@ gui_mch_draw_part_cursor(
rc.right = rc.left + w;
rc.bottom = rc.top + h;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
hbr = CreateSolidBrush(color);
FillRect(s_hdc, &rc, hbr);
DeleteBrush(hbr);
fill_rect(&rc, NULL, color);
}
@@ -3122,13 +3126,8 @@ gui_mch_delete_lines(
int num_lines)
{
RECT rc;
intel_gpu_workaround();
#if defined(FEAT_DIRECTX)
// Commit drawing queue before ScrollWindowEx.
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
int use_redraw = 0;
#endif
rc.left = FILL_X(gui.scroll_region_left);
@@ -3136,8 +3135,24 @@ gui_mch_delete_lines(
rc.top = FILL_Y(row);
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
{
if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines)
{
RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE);
use_redraw = 1;
}
else
DWriteContext_Flush(s_dwc);
}
if (!use_redraw)
#endif
{
intel_gpu_workaround();
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
&rc, &rc, NULL, NULL, get_scroll_flags());
}
UpdateWindow(s_textArea);
/* This seems to be required to avoid the cursor disappearing when
@@ -3161,23 +3176,35 @@ gui_mch_insert_lines(
int num_lines)
{
RECT rc;
intel_gpu_workaround();
#if defined(FEAT_DIRECTX)
// Commit drawing queue before ScrollWindowEx.
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
int use_redraw = 0;
#endif
rc.left = FILL_X(gui.scroll_region_left);
rc.right = FILL_X(gui.scroll_region_right + 1);
rc.top = FILL_Y(row);
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
/* The SW_INVALIDATE is required when part of the window is covered or
* off-screen. How do we avoid it when it's not needed? */
ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
{
if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines)
{
RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE);
use_redraw = 1;
}
else
DWriteContext_Flush(s_dwc);
}
if (!use_redraw)
#endif
{
intel_gpu_workaround();
/* The SW_INVALIDATE is required when part of the window is covered or
* off-screen. How do we avoid it when it's not needed? */
ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
&rc, &rc, NULL, NULL, get_scroll_flags());
}
UpdateWindow(s_textArea);
@@ -5853,6 +5880,7 @@ _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData UNUSED)
}
}
gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
lResult = 0;
break;
}
@@ -6181,6 +6209,67 @@ RevOut( HDC s_hdc,
}
#endif
static void
draw_line(
int x1,
int y1,
int x2,
int y2,
COLORREF color)
{
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_DrawLine(s_dwc, x1, y1, x2, y2, color);
else
#endif
{
HPEN hpen = CreatePen(PS_SOLID, 1, color);
HPEN old_pen = SelectObject(s_hdc, hpen);
MoveToEx(s_hdc, x1, y1, NULL);
/* Note: LineTo() excludes the last pixel in the line. */
LineTo(s_hdc, x2, y2);
DeleteObject(SelectObject(s_hdc, old_pen));
}
}
static void
set_pixel(
int x,
int y,
COLORREF color)
{
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_SetPixel(s_dwc, x, y, color);
else
#endif
SetPixel(s_hdc, x, y, color);
}
static void
fill_rect(
const RECT *rcp,
HBRUSH hbr,
COLORREF color)
{
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_FillRect(s_dwc, rcp, color);
else
#endif
{
HBRUSH hbr2;
if (hbr == NULL)
hbr2 = CreateSolidBrush(color);
else
hbr2 = hbr;
FillRect(s_hdc, rcp, hbr2);
if (hbr == NULL)
DeleteBrush(hbr2);
}
}
void
gui_mch_draw_string(
int row,
@@ -6200,7 +6289,6 @@ gui_mch_draw_string(
static int unibuflen = 0;
int n = 0;
#endif
HPEN hpen, old_pen;
int y;
/*
@@ -6263,11 +6351,7 @@ gui_mch_draw_string(
brush_lru = !brush_lru;
}
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_FillRect(s_dwc, &rc, gui.currBgColor);
#endif
FillRect(s_hdc, &rc, hbr);
fill_rect(&rc, hbr, gui.currBgColor);
SetBkMode(s_hdc, TRANSPARENT);
@@ -6462,38 +6546,22 @@ gui_mch_draw_string(
foptions, pcliprect, (char *)text, len, padding);
}
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX() &&
(flags & (DRAW_UNDERL | DRAW_STRIKE | DRAW_UNDERC | DRAW_CURSOR)))
DWriteContext_Flush(s_dwc);
#endif
/* Underline */
if (flags & DRAW_UNDERL)
{
hpen = CreatePen(PS_SOLID, 1, gui.currFgColor);
old_pen = SelectObject(s_hdc, hpen);
/* When p_linespace is 0, overwrite the bottom row of pixels.
* Otherwise put the line just below the character. */
y = FILL_Y(row + 1) - 1;
if (p_linespace > 1)
y -= p_linespace - 1;
MoveToEx(s_hdc, FILL_X(col), y, NULL);
/* Note: LineTo() excludes the last pixel in the line. */
LineTo(s_hdc, FILL_X(col + len), y);
DeleteObject(SelectObject(s_hdc, old_pen));
draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currFgColor);
}
/* Strikethrough */
if (flags & DRAW_STRIKE)
{
hpen = CreatePen(PS_SOLID, 1, gui.currSpColor);
old_pen = SelectObject(s_hdc, hpen);
y = FILL_Y(row + 1) - gui.char_height/2;
MoveToEx(s_hdc, FILL_X(col), y, NULL);
/* Note: LineTo() excludes the last pixel in the line. */
LineTo(s_hdc, FILL_X(col + len), y);
DeleteObject(SelectObject(s_hdc, old_pen));
draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currSpColor);
}
/* Undercurl */
@@ -6507,7 +6575,7 @@ gui_mch_draw_string(
for (x = FILL_X(col); x < FILL_X(col + len); ++x)
{
offset = val[x % 8];
SetPixel(s_hdc, x, y - offset, gui.currSpColor);
set_pixel(x, y - offset, gui.currSpColor);
}
}
}
@@ -6541,19 +6609,7 @@ gui_mch_flush(void)
static void
clear_rect(RECT *rcp)
{
HBRUSH hbr;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
{
DWriteContext_FillRect(s_dwc, rcp, gui.back_pixel);
return;
}
#endif
hbr = CreateSolidBrush(gui.back_pixel);
FillRect(s_hdc, rcp, hbr);
DeleteBrush(hbr);
fill_rect(rcp, NULL, gui.back_pixel);
}

View File

@@ -5433,7 +5433,7 @@ op_addsub(
}
else /* oap->motion_type == MCHAR */
{
if (!oap->inclusive)
if (pos.lnum == oap->start.lnum && !oap->inclusive)
dec(&(oap->end));
length = (colnr_T)STRLEN(ml_get(pos.lnum));
pos.col = 0;

View File

@@ -7406,7 +7406,7 @@ did_set_string_option(
#if defined(FEAT_RENDER_OPTIONS)
/* 'renderoptions' */
else if (varp == &p_rop && gui.in_use)
else if (varp == &p_rop)
{
if (!gui_mch_set_rendering_options(p_rop))
errmsg = e_invarg;

View File

@@ -1816,9 +1816,18 @@ mch_inchar(
typeahead[typeaheadlen] = c;
if (ch2 != NUL)
{
typeahead[typeaheadlen + n] = 3;
typeahead[typeaheadlen + n + 1] = (char_u)ch2;
n += 2;
if (c == K_NUL && (ch2 & 0xff00) != 0)
{
/* fAnsiKey with modifier keys */
typeahead[typeaheadlen + n] = (char_u)ch2;
n++;
}
else
{
typeahead[typeaheadlen + n] = 3;
typeahead[typeaheadlen + n + 1] = (char_u)ch2;
n += 2;
}
}
/* Use the ALT key to set the 8th bit of the character

View File

@@ -31,7 +31,6 @@ void channel_close(channel_T *channel, int invoke_close_cb);
void channel_close_in(channel_T *channel);
void channel_clear(channel_T *channel);
void channel_free_all(void);
char_u *channel_read_block(channel_T *channel, ch_part_T part, int timeout);
void common_channel_read(typval_T *argvars, typval_T *rettv, int raw);
channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp);
void channel_handle_events(int only_keep_open);

View File

@@ -25,6 +25,7 @@ void u_clearline(void);
void u_undoline(void);
void u_blockfree(buf_T *buf);
int bufIsChanged(buf_T *buf);
int bufIsChangedNotTerm(buf_T *buf);
int curbufIsChanged(void);
void u_eval_tree(u_header_T *first_uhp, list_T *list);
/* vim: set ft=c : */

View File

@@ -4949,9 +4949,12 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
if ((status == OK) && (flags & QF_GETLIST_WINID))
{
win_T *win;
int win_id = 0;
win = qf_find_win(qi);
if (win != NULL)
status = dict_add_nr_str(retdict, "winid", win->w_id, NULL);
win_id = win->w_id;
status = dict_add_nr_str(retdict, "winid", win_id, NULL);
}
if ((status == OK) && (flags & QF_GETLIST_ITEMS))
{

View File

@@ -1154,7 +1154,7 @@ win_update(win_T *wp)
}
/* Window is zero-height: nothing to draw. */
if (wp->w_height == 0)
if (wp->w_height + WINBAR_HEIGHT(wp) == 0)
{
wp->w_redr_type = 0;
return;

View File

@@ -3510,6 +3510,9 @@ may_req_ambiguous_char_width(void)
out_str((char_u *)" ");
term_windgoto(0, 0);
/* Need to reset the known cursor position. */
screen_start();
/* check for the characters now, otherwise they might be eaten by
* get_keystroke() */
out_flush();
@@ -4585,7 +4588,7 @@ check_termcode(
is_mac_terminal = TRUE;
}
# ifdef FEAT_MOUSE_SGR
/* Iterm2 sends 0;95;0 */
/* iTerm2 sends 0;95;0 */
if (STRNCMP(tp + extra - 2, "0;95;0c", 7) == 0)
is_iterm2 = TRUE;
# endif
@@ -4597,7 +4600,7 @@ check_termcode(
{
# ifdef FEAT_MOUSE_SGR
/* Xterm version 277 supports SGR. Also support
* Terminal.app and iterm2. */
* Terminal.app and iTerm2. */
if (version >= 277 || is_iterm2 || is_mac_terminal)
set_option_value((char_u *)"ttym", 0L,
(char_u *)"sgr", 0);

View File

@@ -675,7 +675,10 @@ update_cursor(term_T *term, int redraw)
out_flush();
#ifdef FEAT_GUI
if (gui.in_use)
{
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
}
#endif
}
}
@@ -1308,12 +1311,13 @@ send_keys_to_term(term_T *term, int c, int typed)
case K_MOUSELEFT:
case K_MOUSERIGHT:
if (mouse_row < W_WINROW(curwin)
|| mouse_row > (W_WINROW(curwin) + curwin->w_height)
|| mouse_row >= (W_WINROW(curwin) + curwin->w_height)
|| mouse_col < curwin->w_wincol
|| mouse_col > W_ENDCOL(curwin)
|| mouse_col >= W_ENDCOL(curwin)
|| dragging_outside)
{
/* click or scroll outside the current window */
/* click or scroll outside the current window or on status line
* or vertical separator */
if (typed)
{
stuffcharReadbuff(c);

View File

@@ -73,6 +73,7 @@ NEW_TESTS = test_arabic.res \
test_assert.res \
test_autochdir.res \
test_autocmd.res \
test_autoload.res \
test_backspace_opt.res \
test_breakindent.res \
test_bufwintabinfo.res \

View File

@@ -251,6 +251,7 @@ let s:flaky = [
\ 'Test_exit_callback_interval()',
\ 'Test_nb_basic()',
\ 'Test_oneshot()',
\ 'Test_out_cb()',
\ 'Test_paused()',
\ 'Test_pipe_through_sort_all()',
\ 'Test_pipe_through_sort_some()',

View File

@@ -0,0 +1,7 @@
let g:loaded_foo_vim += 1
let foo#bar = {}
func foo#bar.echo()
let g:called_foo_bar_echo += 1
endfunc

View File

@@ -0,0 +1 @@
" used by Test_globpath()

View File

@@ -0,0 +1 @@
" used by Test_globpath()

View File

@@ -0,0 +1,3 @@
let g:loaded_sourced_vim += 1
func! sourced#something()
endfunc

View File

@@ -0,0 +1,17 @@
" Tests for autoload
set runtimepath=./sautest
func Test_autoload_dict_func()
let g:loaded_foo_vim = 0
let g:called_foo_bar_echo = 0
call g:foo#bar.echo()
call assert_equal(1, g:loaded_foo_vim)
call assert_equal(1, g:called_foo_bar_echo)
endfunc
func Test_source_autoload()
let g:loaded_sourced_vim = 0
source sautest/autoload/sourced.vim
call assert_equal(1, g:loaded_sourced_vim)
endfunc

View File

@@ -515,7 +515,7 @@ func Test_nl_pipe()
call assert_equal("AND this", ch_readraw(handle))
call ch_sendraw(handle, "split this line\n")
call assert_equal("this linethis linethis line", ch_readraw(handle))
call assert_equal("this linethis linethis line", ch_read(handle))
let reply = ch_evalraw(handle, "quit\n")
call assert_equal("Goodbye!", reply)
@@ -1266,6 +1266,31 @@ func Test_read_in_close_cb()
endtry
endfunc
" Use channel in NL mode but received text does not end in NL.
func Test_read_in_close_cb_incomplete()
if !has('job')
return
endif
call ch_log('Test_read_in_close_cb_incomplete()')
let g:Ch_received = ''
func! CloseHandler(chan)
while ch_status(a:chan, {'part': 'out'}) == 'buffered'
let g:Ch_received .= ch_read(a:chan)
endwhile
endfunc
let job = job_start(s:python . " test_channel_pipe.py incomplete",
\ {'close_cb': 'CloseHandler'})
call assert_equal("run", job_status(job))
try
call WaitFor('g:Ch_received != ""')
call assert_equal('incomplete', g:Ch_received)
finally
call job_stop(job)
delfunc CloseHandler
endtry
endfunc
func Test_out_cb_lambda()
if !has('job')
return

View File

@@ -14,6 +14,10 @@ if __name__ == "__main__":
if sys.argv[1].startswith("err"):
print(sys.argv[1], file=sys.stderr)
sys.stderr.flush()
elif sys.argv[1].startswith("incomplete"):
print(sys.argv[1], end='')
sys.stdout.flush()
sys.exit(0)
else:
print(sys.argv[1])
sys.stdout.flush()

View File

@@ -25,8 +25,8 @@ function Test_glob()
endfunction
function Test_globpath()
call assert_equal("sautest/autoload/Test104.vim\nsautest/autoload/footest.vim",
\ globpath('sautest/autoload', '*.vim'))
call assert_equal(['sautest/autoload/Test104.vim', 'sautest/autoload/footest.vim'],
\ globpath('sautest/autoload', '*.vim', 0, 1))
call assert_equal("sautest/autoload/globone.vim\nsautest/autoload/globtwo.vim",
\ globpath('sautest/autoload', 'glob*.vim'))
call assert_equal(['sautest/autoload/globone.vim', 'sautest/autoload/globtwo.vim'],
\ globpath('sautest/autoload', 'glob*.vim', 0, 1))
endfunction

View File

@@ -30,3 +30,22 @@ func Test_help_keyword()
close
bwipe!
endfunc
func Test_help_local_additions()
call mkdir('Xruntime/doc', 'p')
call writefile(['*mydoc.txt* my awesome doc'], 'Xruntime/doc/mydoc.txt')
call writefile(['*mydoc-ext.txt* my extended awesome doc'], 'Xruntime/doc/mydoc-ext.txt')
let rtp_save = &rtp
set rtp+=./Xruntime
help
1
call search('mydoc.txt')
call assert_equal('|mydoc.txt| my awesome doc', getline('.'))
1
call search('mydoc-ext.txt')
call assert_equal('|mydoc-ext.txt| my extended awesome doc', getline('.'))
close
call delete('Xruntime', 'rf')
let &rtp = rtp_save
endfunc

View File

@@ -364,11 +364,25 @@ endfunc
" Expected:
" 1) Ctrl-a on visually selected zero
" 111
"
" Also: 019 with "01" selected increments to "029".
func Test_visual_increment_15()
call setline(1, ["101"])
exec "norm! lv\<C-A>"
call assert_equal(["111"], getline(1, '$'))
call assert_equal([0, 1, 2, 0], getpos('.'))
call setline(1, ["019"])
exec "norm! 0vl\<C-A>"
call assert_equal("029", getline(1))
call setline(1, ["01239"])
exec "norm! 0vlll\<C-A>"
call assert_equal("01249", getline(1))
call setline(1, ["01299"])
exec "norm! 0vlll\<C-A>"
call assert_equal("1309", getline(1))
endfunc
" 16) increment right aligned numbers
@@ -756,5 +770,12 @@ func Test_normal_increment_03()
call assert_equal([0, 3, 25, 0], getpos('.'))
endfunc
func Test_increment_empty_line()
new
call setline(1, ['0', '0', '0', '0', '0', '0', ''])
exe "normal Gvgg\<C-A>"
call assert_equal(['1', '1', '1', '1', '1', '1', ''], getline(1, 7))
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -181,3 +181,44 @@ func Test_profile_errors()
call assert_fails("profile pause", 'E750:')
call assert_fails("profile continue", 'E750:')
endfunc
func Test_profile_truncate_mbyte()
if !has('multi_byte') || &enc !=# 'utf-8'
return
endif
let lines = [
\ 'scriptencoding utf-8',
\ 'func! Foo()',
\ ' return [',
\ ' \ "' . join(map(range(0x4E00, 0x4E00 + 340), 'nr2char(v:val)'), '') . '",',
\ ' \ "' . join(map(range(0x4F00, 0x4F00 + 340), 'nr2char(v:val)'), '') . '",',
\ ' \ ]',
\ 'endfunc',
\ 'call Foo()',
\ ]
call writefile(lines, 'Xprofile_file.vim')
call system(v:progpath
\ . ' -es --clean --cmd "set enc=utf-8"'
\ . ' -c "profile start Xprofile_file.log"'
\ . ' -c "profile file Xprofile_file.vim"'
\ . ' -c "so Xprofile_file.vim"'
\ . ' -c "qall!"')
call assert_equal(0, v:shell_error)
split Xprofile_file.log
if &fenc != ''
call assert_equal('utf-8', &fenc)
endif
/func! Foo()
let lnum = line('.')
call assert_match('^\s*return \[$', getline(lnum + 1))
call assert_match("\u4F52$", getline(lnum + 2))
call assert_match("\u5052$", getline(lnum + 3))
call assert_match('^\s*\\ \]$', getline(lnum + 4))
bwipe!
call delete('Xprofile_file.vim')
call delete('Xprofile_file.log')
endfunc

View File

@@ -28,7 +28,7 @@ func s:setup_commands(cchar)
command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>clast<bang> <args>
command! -nargs=* -bang Xnfile <mods>cnfile<bang> <args>
command! -nargs=* -bang -range Xnfile <mods><count>cnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
command! -nargs=* Xexpr <mods>cexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args>
@@ -36,6 +36,7 @@ func s:setup_commands(cchar)
command! -nargs=* Xgrep <mods> grep <args>
command! -nargs=* Xgrepadd <mods> grepadd <args>
command! -nargs=* Xhelpgrep helpgrep <args>
command! -nargs=0 -count Xcc <count>cc
let g:Xgetlist = function('getqflist')
let g:Xsetlist = function('setqflist')
call setqflist([], 'f')
@@ -60,7 +61,7 @@ func s:setup_commands(cchar)
command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>llast<bang> <args>
command! -nargs=* -bang Xnfile <mods>lnfile<bang> <args>
command! -nargs=* -bang -range Xnfile <mods><count>lnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
command! -nargs=* Xexpr <mods>lexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
@@ -68,6 +69,7 @@ func s:setup_commands(cchar)
command! -nargs=* Xgrep <mods> lgrep <args>
command! -nargs=* Xgrepadd <mods> lgrepadd <args>
command! -nargs=* Xhelpgrep lhelpgrep <args>
command! -nargs=0 -count Xcc <count>ll
let g:Xgetlist = function('getloclist', [0])
let g:Xsetlist = function('setloclist', [0])
call setloclist(0, [], 'f')
@@ -382,12 +384,18 @@ endfunc
func Xtest_browse(cchar)
call s:setup_commands(a:cchar)
call g:Xsetlist([], 'f')
" Jumping to first or next location list entry without any error should
" result in failure
if a:cchar == 'l'
call assert_fails('lfirst', 'E776:')
call assert_fails('lnext', 'E776:')
if a:cchar == 'c'
let err = 'E42:'
else
let err = 'E776:'
endif
call assert_fails('Xnext', err)
call assert_fails('Xprev', err)
call assert_fails('Xnfile', err)
call assert_fails('Xpfile', err)
call s:create_test_file('Xqftestfile1')
call s:create_test_file('Xqftestfile2')
@@ -408,6 +416,12 @@ func Xtest_browse(cchar)
Xpfile
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal(6, line('.'))
5Xcc
call assert_equal(5, g:Xgetlist({'idx':0}).idx)
2Xcc
call assert_equal(2, g:Xgetlist({'idx':0}).idx)
10Xcc
call assert_equal(6, g:Xgetlist({'idx':0}).idx)
Xlast
Xprev
call assert_equal('Xqftestfile2', bufname('%'))
@@ -425,6 +439,23 @@ func Xtest_browse(cchar)
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal(5, line('.'))
" Jumping to an error from the error window using cc command
Xgetexpr ['Xqftestfile1:5:Line5',
\ 'Xqftestfile1:6:Line6',
\ 'Xqftestfile2:10:Line10',
\ 'Xqftestfile2:11:Line11']
Xopen
10Xcc
call assert_equal(11, line('.'))
call assert_equal('Xqftestfile2', bufname('%'))
" Jumping to an error from the error window (when only the error window is
" present)
Xopen | only
Xlast 1
call assert_equal(5, line('.'))
call assert_equal('Xqftestfile1', bufname('%'))
Xexpr ""
call assert_fails('Xnext', 'E42:')
@@ -1497,13 +1528,18 @@ func Test_switchbuf()
set switchbuf=usetab
tabedit Xqftestfile1
tabedit Xqftestfile2
tabedit Xqftestfile3
tabfirst
cfirst | cnext
call assert_equal(2, tabpagenr())
2cnext
call assert_equal(3, tabpagenr())
2cnext
call assert_equal(3, tabpagenr())
6cnext
call assert_equal(4, tabpagenr())
2cpfile
call assert_equal(2, tabpagenr())
2cnfile
call assert_equal(4, tabpagenr())
tabfirst | tabonly | enew
set switchbuf=split
@@ -2320,7 +2356,7 @@ func XfreeTests(cchar)
Xclose
endfunc
" Tests for the quickifx free functionality
" Tests for the quickfix free functionality
func Test_qf_free()
call XfreeTests('c')
call XfreeTests('l')
@@ -2747,3 +2783,100 @@ func Test_qf_id()
call Xqfid_tests('c')
call Xqfid_tests('l')
endfunc
func Xqfjump_tests(cchar)
call s:setup_commands(a:cchar)
call writefile(["Line1\tFoo", "Line2"], 'F1')
call writefile(["Line1\tBar", "Line2"], 'F2')
call writefile(["Line1\tBaz", "Line2"], 'F3')
call g:Xsetlist([], 'f')
" Tests for
" Jumping to a line using a pattern
" Jumping to a column greater than the last column in a line
" Jumping to a line greater than the last line in the file
let l = []
for i in range(1, 7)
call add(l, {})
endfor
let l[0].filename='F1'
let l[0].pattern='Line1'
let l[1].filename='F2'
let l[1].pattern='Line1'
let l[2].filename='F3'
let l[2].pattern='Line1'
let l[3].filename='F3'
let l[3].lnum=1
let l[3].col=9
let l[3].vcol=1
let l[4].filename='F3'
let l[4].lnum=99
let l[5].filename='F3'
let l[5].lnum=1
let l[5].col=99
let l[5].vcol=1
let l[6].filename='F3'
let l[6].pattern='abcxyz'
call g:Xsetlist([], ' ', {'items' : l})
Xopen | only
2Xnext
call assert_equal(3, g:Xgetlist({'idx' : 0}).idx)
call assert_equal('F3', bufname('%'))
Xnext
call assert_equal(7, col('.'))
Xnext
call assert_equal(2, line('.'))
Xnext
call assert_equal(9, col('.'))
2
Xnext
call assert_equal(2, line('.'))
if a:cchar == 'l'
" When jumping to a location list entry in the location list window and
" no usable windows are available, then a new window should be opened.
enew! | new | only
call g:Xsetlist([], 'f')
setlocal buftype=nofile
new
call g:Xsetlist([], ' ', {'lines' : ['F1:1:1:Line1', 'F1:2:2:Line2', 'F2:1:1:Line1', 'F2:2:2:Line2', 'F3:1:1:Line1', 'F3:2:2:Line2']})
Xopen
let winid = win_getid()
wincmd p
close
call win_gotoid(winid)
Xnext
call assert_equal(3, winnr('$'))
call assert_equal(1, winnr())
call assert_equal(2, line('.'))
" When jumping to an entry in the location list window and the window
" associated with the location list is not present and a window containing
" the file is already present, then that window should be used.
close
belowright new
call g:Xsetlist([], 'f')
edit F3
call win_gotoid(winid)
Xlast
call assert_equal(3, winnr())
call assert_equal(6, g:Xgetlist({'size' : 1}).size)
call assert_equal(winid, g:Xgetlist({'winid' : 1}).winid)
endif
" Cleanup
enew!
new | only
call delete('F1')
call delete('F2')
call delete('F3')
endfunc
func Test_qfjump()
call Xqfjump_tests('c')
call Xqfjump_tests('l')
endfunc

View File

@@ -673,15 +673,16 @@ func TerminalTmap(remap)
else
tnoremap 123 456
endif
tmap 456 abcde
" don't use abcde, it's an existing command
tmap 456 abxde
call assert_equal('456', maparg('123', 't'))
call assert_equal('abcde', maparg('456', 't'))
call assert_equal('abxde', maparg('456', 't'))
call feedkeys("123", 'tx')
let g:buf = buf
call WaitFor("term_getline(g:buf,term_getcursor(g:buf)[0]) =~ 'abcde\\|456'")
call WaitFor("term_getline(g:buf,term_getcursor(g:buf)[0]) =~ 'abxde\\|456'")
let lnum = term_getcursor(buf)[0]
if a:remap
call assert_match('abcde', term_getline(buf, lnum))
call assert_match('abxde', term_getline(buf, lnum))
else
call assert_match('456', term_getline(buf, lnum))
endif

View File

@@ -3523,6 +3523,8 @@ u_save_line(linenr_T lnum)
* Check if the 'modified' flag is set, or 'ff' has changed (only need to
* check the first character, because it can only be "dos", "unix" or "mac").
* "nofile" and "scratch" type buffers are considered to always be unchanged.
* Also considers a buffer changed when a terminal window contains a running
* job.
*/
int
bufIsChanged(buf_T *buf)
@@ -3531,6 +3533,15 @@ bufIsChanged(buf_T *buf)
if (term_job_running(buf->b_term))
return TRUE;
#endif
return bufIsChangedNotTerm(buf);
}
/*
* Like bufIsChanged() but ignoring a terminal window.
*/
int
bufIsChangedNotTerm(buf_T *buf)
{
return !bt_dontwrite(buf)
&& (buf->b_changed || file_ff_differs(buf, TRUE));
}

View File

@@ -1594,7 +1594,7 @@ trans_function_name(
start += lead;
/* Note that TFN_ flags use the same values as GLV_ flags. */
end = get_lval(start, NULL, &lv, FALSE, skip, flags,
end = get_lval(start, NULL, &lv, FALSE, skip, flags | GLV_READ_ONLY,
lead > 2 ? 0 : FNE_CHECK_START);
if (end == start)
{
@@ -1886,7 +1886,7 @@ ex_function(exarg_T *eap)
* g:func global function name, same as "func"
*/
p = eap->arg;
name = trans_function_name(&p, eap->skip, 0, &fudi, NULL);
name = trans_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL);
paren = (vim_strchr(p, '(') != NULL);
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
{

View File

@@ -771,6 +771,44 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1384,
/**/
1383,
/**/
1382,
/**/
1381,
/**/
1380,
/**/
1379,
/**/
1378,
/**/
1377,
/**/
1376,
/**/
1375,
/**/
1374,
/**/
1373,
/**/
1372,
/**/
1371,
/**/
1370,
/**/
1369,
/**/
1368,
/**/
1367,
/**/
1366,
/**/
1365,
/**/

View File

@@ -1478,8 +1478,10 @@ typedef UINT32_TYPEDEF UINT32_T;
#define STATUS_HEIGHT 1 /* height of a status line under a window */
#ifdef FEAT_MENU /* height of a status line under a window */
# define WINBAR_HEIGHT(wp) (wp)->w_winbar_height
# define VISIBLE_HEIGHT(wp) ((wp)->w_height + (wp)->w_winbar_height)
#else
# define WINBAR_HEIGHT(wp) 0
# define VISIBLE_HEIGHT(wp) (wp)->w_height
#endif
#define QF_WINHEIGHT 10 /* default height for quickfix window */

View File

@@ -782,7 +782,7 @@ win_split_ins(
/* add a status line when p_ls == 1 and splitting the first window */
if (ONE_WINDOW && p_ls == 1 && oldwin->w_status_height == 0)
{
if (oldwin->w_height <= p_wmh && new_wp == NULL)
if (VISIBLE_HEIGHT(oldwin) <= p_wmh && new_wp == NULL)
{
EMSG(_(e_noroom));
return FAIL;
@@ -892,7 +892,7 @@ win_split_ins(
* height.
*/
/* Current window requires at least 1 space. */
wmh1 = (p_wmh == 0 ? 1 : p_wmh);
wmh1 = (p_wmh == 0 ? 1 : p_wmh) + WINBAR_HEIGHT(curwin);
needed = wmh1 + STATUS_HEIGHT;
if (flags & WSP_ROOM)
needed += p_wh - wmh1;
@@ -1105,7 +1105,7 @@ win_split_ins(
{
/* height and row of new window is same as current window */
wp->w_winrow = oldwin->w_winrow;
win_new_height(wp, oldwin->w_height + WINBAR_HEIGHT(oldwin));
win_new_height(wp, VISIBLE_HEIGHT(oldwin));
wp->w_status_height = oldwin->w_status_height;
}
frp->fr_height = curfrp->fr_height;
@@ -1180,8 +1180,8 @@ win_split_ins(
}
else /* new window below current one */
{
wp->w_winrow = oldwin->w_winrow + oldwin->w_height
+ STATUS_HEIGHT + WINBAR_HEIGHT(oldwin);
wp->w_winrow = oldwin->w_winrow + VISIBLE_HEIGHT(oldwin)
+ STATUS_HEIGHT;
wp->w_status_height = oldwin->w_status_height;
if (!(flags & WSP_BOT))
oldwin->w_status_height = STATUS_HEIGHT;
@@ -1422,7 +1422,7 @@ make_windows(
else
{
/* Each window needs at least 'winminheight' lines and a status line. */
maxcount = (curwin->w_height + curwin->w_status_height
maxcount = (VISIBLE_HEIGHT(curwin) + curwin->w_status_height
- (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
}
@@ -3204,8 +3204,7 @@ frame_fix_width(win_T *wp)
static void
frame_fix_height(win_T *wp)
{
wp->w_frame->fr_height = wp->w_height + wp->w_status_height
+ WINBAR_HEIGHT(wp) ;
wp->w_frame->fr_height = VISIBLE_HEIGHT(wp) + wp->w_status_height;
}
/*
@@ -3230,9 +3229,14 @@ frame_minheight(frame_T *topfrp, win_T *next_curwin)
{
/* window: minimal height of the window plus status line */
m = p_wmh + topfrp->fr_win->w_status_height;
/* Current window is minimal one line high */
if (p_wmh == 0 && topfrp->fr_win == curwin && next_curwin == NULL)
++m;
if (topfrp->fr_win == curwin && next_curwin == NULL)
{
/* Current window is minimal one line high and WinBar is
* visible. */
if (p_wmh == 0)
++m;
m += WINBAR_HEIGHT(curwin);
}
}
}
else if (topfrp->fr_layout == FR_ROW)
@@ -4972,6 +4976,7 @@ frame_comp_pos(frame_T *topfrp, int *row, int *col)
frame_T *frp;
int startcol;
int startrow;
int h;
wp = topfrp->fr_win;
if (wp != NULL)
@@ -4984,7 +4989,9 @@ frame_comp_pos(frame_T *topfrp, int *row, int *col)
redraw_win_later(wp, NOT_VALID);
wp->w_redr_status = TRUE;
}
*row += wp->w_height + wp->w_status_height;
/* WinBar will not show if the window height is zero */
h = VISIBLE_HEIGHT(wp) + wp->w_status_height;
*row += h > topfrp->fr_height ? topfrp->fr_height : h;
*col += wp->w_width + wp->w_vsep_width;
}
else
@@ -5029,6 +5036,7 @@ win_setheight_win(int height, win_T *win)
height = p_wmh;
if (height == 0)
height = 1;
height += WINBAR_HEIGHT(curwin);
}
frame_setheight(win->w_frame, height + win->w_status_height);
@@ -5126,7 +5134,8 @@ frame_setheight(frame_T *curfrp, int height)
else
{
room_cmdline = Rows - p_ch - (lastwin->w_winrow
+ lastwin->w_height + lastwin->w_status_height);
+ VISIBLE_HEIGHT(lastwin)
+ lastwin->w_status_height);
if (room_cmdline < 0)
room_cmdline = 0;
}
@@ -5415,7 +5424,7 @@ win_setminheight(void)
/* TODO: handle vertical splits */
room = -p_wh;
FOR_ALL_WINDOWS(wp)
room += wp->w_height - p_wmh;
room += VISIBLE_HEIGHT(wp) - p_wmh;
if (room >= 0)
break;
--p_wmh;