Compare commits

...

31 Commits

Author SHA1 Message Date
Bram Moolenaar
08cab96087 patch 8.0.0405: v:progpath may become invalid after :cd
Problem:    v:progpath may become invalid after ":cd".
Solution:   Turn v:progpath into a full path if needed.
2017-03-04 14:37:18 +01:00
Bram Moolenaar
391b1dd040 patch 8.0.0404: not enough testing for quickfix
Problem:    Not enough testing for quickfix.
Solution:   Add some more tests. (Yegappan Lakshmanan)
2017-03-04 13:47:11 +01:00
Bram Moolenaar
24d7636e98 patch 8.0.0403: GUI tests may fail
Problem:    GUI tests may fail.
Solution:   Ignore the E285 error better. (Kazunobu Kuriyama)
2017-03-04 13:32:10 +01:00
Bram Moolenaar
cf5fdf7d16 patch 8.0.0402: :map completion does not have <special>
Problem:    :map completion does not have <special>. (Dominique Pelle)
Solution:   Recognize <special> in completion.  Add a test.
2017-03-02 23:05:51 +01:00
Bram Moolenaar
a0107bdf87 patch 8.0.0401: test fails with missing balloon feature
Problem:    Test fails with missing balloon feature.
Solution:   Add check for balloon feature.
2017-03-02 22:48:01 +01:00
Bram Moolenaar
358f6b0a36 patch 8.0.0400: some tests have a one second delay
Problem:    Some tests have a one second delay.
Solution:   Add --not-a-term in RunVim().
2017-03-02 22:43:01 +01:00
Bram Moolenaar
caf6434ac9 patch 8.0.0399: crash when using balloon_show() when not supported
Problem:    Crash when using balloon_show() when not supported. (Hirohito
            Higashi)
Solution:   Check for balloonEval not to be NULL. (Ken Takata)
2017-03-02 22:11:33 +01:00
Bram Moolenaar
66727e1607 patch 8.0.0398: illegal memory access with "t"
Problem:    Illegal memory access with "t".
Solution:   Use strncmp() instead of memcmp(). (Dominique Pelle, closes #1528)
2017-03-01 22:17:05 +01:00
Bram Moolenaar
5a66dfb25e patch 8.0.0397: can't build with +viminfo but without +eval
Problem:    Cannot build with the viminfo feature but without the eval
            feature.
Solution:   Adjust #ifdef. (John Marriott)
2017-03-01 20:40:39 +01:00
Bram Moolenaar
59716a27bd patch 8.0.0396: 'balloonexpr' only works synchronously
Problem:    'balloonexpr' only works synchronously.
Solution:   Add balloon_show(). (Jusufadis Bakamovic, closes #1449)
2017-03-01 20:32:44 +01:00
Bram Moolenaar
f8ab1b14fd patch 8.0.0395: testing the + register fails with Motif
Problem:    Testing the + register fails with Motif.
Solution:   Also ignore the "failed to create input context" error in the
            second gvim.  Don't use msg() when it would result in a dialog.
2017-03-01 18:30:34 +01:00
Bram Moolenaar
abc39ab642 patch 8.0.0394: tabs are not aligned when scrolling horizontally
Problem:    Tabs are not aligned when scrolling horizontally and a Tab doesn't
            fit. (Axel Bender)
Solution:   Handle a Tab as a not fitting character. (Christian Brabandt)
            Also fix that ":redraw" does not scroll horizontally to show the
            cursor.  And fix the test that depended on the old behavior.
2017-03-01 18:04:05 +01:00
Bram Moolenaar
98e83b2956 patch 8.0.0393: order of duplicate tags is not preserved
Problem:    When the same tag appears more than once, the order is
            unpredictable. (Charles Campbell)
Solution:   Besides using a dict for finding duplicates, use a grow array for
            keeping the tags in sequence.
2017-03-01 15:45:05 +01:00
Bram Moolenaar
e0c31f6a30 patch 8.0.0392: GUI test fails with Athena and Motif
Problem:    GUI test fails with Athena and Motif.
Solution:   Add test_ignore_error().  Use it to ignore the "failed to create
            input context" error.
2017-03-01 15:07:05 +01:00
Bram Moolenaar
5f53dd3f74 patch 8.0.0391: arabic support is verbose and not well tested
Problem:    Arabic support is verbose and not well tested.
Solution:   Simplify the code.  Add more tests.
2017-03-01 14:02:30 +01:00
Bram Moolenaar
cb03642399 patch 8.0.0390: when the window scrolls the popup menu may be garbled
Problem:    When the window scrolls horizontally when the popup menu is
            displayed part of it may not be cleared. (Neovim issue #6184)
Solution:   Remove the menu when the windows scrolled. (closes #1524)
2017-03-01 12:29:10 +01:00
Bram Moolenaar
5342f00ff9 patch 8.0.0389: test for arabic does not check what is displayed
Problem:    Test for arabic does not check what is displayed.
Solution:   Improve what is asserted. (Dominique Pelle, closes #1523)
            Add a first shaping test.
2017-02-28 22:51:12 +01:00
Bram Moolenaar
1159b168dd patch 8.0.0388: filtering lines changes folds
Problem:    filtering lines through "cat", without changing the line count,
            changes manual folds.
Solution:   Change how marks and folds are adjusted. (Matthew Malcomson, from
            neovim #6194.
2017-02-28 21:53:56 +01:00
Bram Moolenaar
b113c3a618 patch 8.0.0387: compiler warnings
Problem:    compiler warnings
Solution:   Add type casts. (Christian Brabandt)
2017-02-28 21:26:17 +01:00
Bram Moolenaar
5b3af14b34 patch 8.0.0386: tiny build has a problem with generating the options test
Problem:    Tiny build has a problem with generating the options test.
Solution:   Change the "if" to skip over statements.
2017-02-27 22:59:40 +01:00
Bram Moolenaar
b5e8377364 patch 8.0.0385: no tests for arabic
Problem:    No tests for arabic.
Solution:   Add a first test for arabic. (Dominique Pelle, closes #1518)
2017-02-27 21:48:26 +01:00
Bram Moolenaar
d512e17ea4 patch 8.0.0384: timer test failed for no apparent reason
Problem:    Timer test failed for no apparent reason.
Solution:   Mark the test as flaky.
2017-02-27 21:35:53 +01:00
Bram Moolenaar
10a8da0594 patch 8.0.0383: misplaced #ifdef
Problem:    Misplaced #ifdef. (Christ van Willigen)
Solution:   Split assignment.
2017-02-27 21:11:35 +01:00
Bram Moolenaar
88e7688eda patch 8.0.0382: warning in tiny build for unused variable
Problem:    Warning in tiny build for unused variable. (Tony Mechelynck)
Solution:   Add #ifdefs.
2017-02-27 20:33:46 +01:00
Bram Moolenaar
aeb661e1f4 patch 8.0.0381: diff mode is not sufficiently tested
Problem:    Diff mode is not sufficiently tested.
Solution:   Add more diff mode tests. (Dominique Pelle, closes #1515)
2017-02-26 19:59:59 +01:00
Bram Moolenaar
38632faf63 patch 8.0.0380: with 'linebreak' double wide char wraps badly
Problem:    With 'linebreak' set and 'breakat' includes ">" a double-wide
            character results in "<<" displayed.
Solution:   Check for the character not to be replaced. (Ozaki Kiichi,
            closes #1456)
2017-02-26 19:40:59 +01:00
Bram Moolenaar
74a47162a0 patch 8.0.0379: CTRL-Z and mouse click use CTRL-O unnecessary
Problem:    CTRL-Z and mouse click use CTRL-O unnecessary.
Solution:   Remove stuffing CTRL-O. (James McCoy, closes #1453)
2017-02-26 19:09:05 +01:00
Bram Moolenaar
0c8485f0e4 patch 8.0.0378: possible overflow when reading corrupted undo file
Problem:    Another possible overflow when reading corrupted undo file.
Solution:   Check if allocated size is not too big. (King)
2017-02-26 18:17:10 +01:00
Bram Moolenaar
3eb1637b1b patch 8.0.0377: possible overflow when reading corrupted undo file
Problem:    Possible overflow when reading corrupted undo file.
Solution:   Check if allocated size is not too big. (King)
2017-02-26 18:11:36 +01:00
Bram Moolenaar
6d3c8586fc patch 8.0.0376: size computations in spell file reading are off
Problem:    Size computations in spell file reading are not exactly right.
Solution:   Make "len" a "long" and check with LONG_MAX.
2017-02-26 15:27:23 +01:00
Bram Moolenaar
5074a0e033 patch 8.0.0375: the "+ register is not tested
Problem:    The "+ register is not tested.
Solution:   Add a test using another Vim instance to change the "+ register.
            (Kazuki Kuriyama)
2017-02-26 15:08:21 +01:00
42 changed files with 1299 additions and 434 deletions

View File

@@ -1789,8 +1789,11 @@ v:progpath Contains the command with which Vim was invoked, including the
|--remote-expr|.
To get the full path use: >
echo exepath(v:progpath)
< NOTE: This does not work when the command is a relative path
and the current directory has changed.
< If the path is relative it will be expanded to the full path,
so that it still works after `:cd`. Thus starting "./vim"
results in "/home/user/path/to/vim/src/vim".
On MS-Windows the executable may be called "vim.exe", but the
".exe" is not added to v:progpath.
Read-only.
*v:register* *register-variable*
@@ -1981,19 +1984,20 @@ argidx() Number current index in the argument list
arglistid([{winnr} [, {tabnr}]]) Number argument list id
argv({nr}) String {nr} entry of the argument list
argv() List the argument list
assert_equal({exp}, {act} [, {msg}]) none assert {exp} is equal to {act}
assert_exception({error} [, {msg}]) none assert {error} is in v:exception
assert_fails({cmd} [, {error}]) none assert {cmd} fails
assert_false({actual} [, {msg}]) none assert {actual} is false
assert_equal({exp}, {act} [, {msg}]) none assert {exp} is equal to {act}
assert_exception({error} [, {msg}]) none assert {error} is in v:exception
assert_fails({cmd} [, {error}]) none assert {cmd} fails
assert_false({actual} [, {msg}]) none assert {actual} is false
assert_inrange({lower}, {upper}, {actual} [, {msg}])
none assert {actual} is inside the range
assert_match({pat}, {text} [, {msg}]) none assert {pat} matches {text}
assert_match({pat}, {text} [, {msg}]) none assert {pat} matches {text}
assert_notequal({exp}, {act} [, {msg}]) none assert {exp} is not equal {act}
assert_notmatch({pat}, {text} [, {msg}]) none assert {pat} not matches {text}
assert_true({actual} [, {msg}]) none assert {actual} is true
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
browse({save}, {title}, {initdir}, {default})
String put up a file requester
browsedir({title}, {initdir}) String put up a directory requester
@@ -2358,6 +2362,7 @@ test_alloc_fail({id}, {countdown}, {repeat})
test_autochdir() none enable 'autochdir' during startup
test_disable_char_avail({expr}) none test without typeahead
test_garbagecollect_now() none free memory right now for testing
test_ignore_error({expr}) none ignore a specific error
test_null_channel() Channel null value for testing
test_null_dict() Dict null value for testing
test_null_job() Job null value for testing
@@ -2618,6 +2623,25 @@ atan2({expr1}, {expr2}) *atan2()*
< 2.356194
{only available when compiled with the |+float| feature}
balloon_show({msg}) *balloon_show()*
Show {msg} inside the balloon.
Example: >
func GetBalloonContent()
" initiate getting the content
return ''
endfunc
set balloonexpr=GetBalloonContent()
func BalloonCallback(result)
call balloon_show(a:result)
endfunc
<
The intended use is that fetching the content of the balloon
is initiated from 'balloonexpr'. It will invoke an
asynchronous method, in which a callback invokes
balloon_show(). The 'balloonexpr' itself can return an
empty string or a placeholder.
{only available when compiled with the +beval feature}
*browse()*
browse({save}, {title}, {initdir}, {default})
@@ -7784,6 +7808,15 @@ test_garbagecollect_now() *test_garbagecollect_now()*
internally, and |v:testing| must have been set before calling
any function.
test_ignore_error({expr}) *test_ignore_error()*
Ignore any error containing {expr}. A normal message is given
instead.
This is only meant to be used in tests, where catching the
error with try/catch cannot be used (because it skips over
following code).
{expr} is used literally, not as a pattern.
There is currently no way to revert this.
test_null_channel() *test_null_channel()*
Return a Channel that is null. Only useful for testing.
{only available when compiled with the +channel feature}

View File

@@ -2092,6 +2092,7 @@ test1 \
# Run individual NEW style test, assuming that Vim was already compiled.
test_arglist \
test_arabic \
test_assert \
test_assign \
test_autochdir \

View File

@@ -200,126 +200,48 @@ A_is_f(int cur_c)
static int
chg_c_a2s(int cur_c)
{
int tempc;
switch (cur_c)
{
case a_HAMZA:
tempc = a_s_HAMZA;
break;
case a_ALEF_MADDA:
tempc = a_s_ALEF_MADDA;
break;
case a_ALEF_HAMZA_ABOVE:
tempc = a_s_ALEF_HAMZA_ABOVE;
break;
case a_WAW_HAMZA:
tempc = a_s_WAW_HAMZA;
break;
case a_ALEF_HAMZA_BELOW:
tempc = a_s_ALEF_HAMZA_BELOW;
break;
case a_YEH_HAMZA:
tempc = a_s_YEH_HAMZA;
break;
case a_ALEF:
tempc = a_s_ALEF;
break;
case a_TEH_MARBUTA:
tempc = a_s_TEH_MARBUTA;
break;
case a_DAL:
tempc = a_s_DAL;
break;
case a_THAL:
tempc = a_s_THAL;
break;
case a_REH:
tempc = a_s_REH;
break;
case a_ZAIN:
tempc = a_s_ZAIN;
break;
case a_TATWEEL: /* exceptions */
tempc = cur_c;
break;
case a_WAW:
tempc = a_s_WAW;
break;
case a_ALEF_MAKSURA:
tempc = a_s_ALEF_MAKSURA;
break;
case a_BEH:
tempc = a_s_BEH;
break;
case a_TEH:
tempc = a_s_TEH;
break;
case a_THEH:
tempc = a_s_THEH;
break;
case a_JEEM:
tempc = a_s_JEEM;
break;
case a_HAH:
tempc = a_s_HAH;
break;
case a_KHAH:
tempc = a_s_KHAH;
break;
case a_SEEN:
tempc = a_s_SEEN;
break;
case a_SHEEN:
tempc = a_s_SHEEN;
break;
case a_SAD:
tempc = a_s_SAD;
break;
case a_DAD:
tempc = a_s_DAD;
break;
case a_TAH:
tempc = a_s_TAH;
break;
case a_ZAH:
tempc = a_s_ZAH;
break;
case a_AIN:
tempc = a_s_AIN;
break;
case a_GHAIN:
tempc = a_s_GHAIN;
break;
case a_FEH:
tempc = a_s_FEH;
break;
case a_QAF:
tempc = a_s_QAF;
break;
case a_KAF:
tempc = a_s_KAF;
break;
case a_LAM:
tempc = a_s_LAM;
break;
case a_MEEM:
tempc = a_s_MEEM;
break;
case a_NOON:
tempc = a_s_NOON;
break;
case a_HEH:
tempc = a_s_HEH;
break;
case a_YEH:
tempc = a_s_YEH;
break;
default:
tempc = 0;
case a_HAMZA: return a_s_HAMZA;
case a_ALEF_MADDA: return a_s_ALEF_MADDA;
case a_ALEF_HAMZA_ABOVE: return a_s_ALEF_HAMZA_ABOVE;
case a_WAW_HAMZA: return a_s_WAW_HAMZA;
case a_ALEF_HAMZA_BELOW: return a_s_ALEF_HAMZA_BELOW;
case a_YEH_HAMZA: return a_s_YEH_HAMZA;
case a_ALEF: return a_s_ALEF;
case a_TEH_MARBUTA: return a_s_TEH_MARBUTA;
case a_DAL: return a_s_DAL;
case a_THAL: return a_s_THAL;
case a_REH: return a_s_REH;
case a_ZAIN: return a_s_ZAIN;
case a_TATWEEL: return cur_c; /* exceptions */
case a_WAW: return a_s_WAW;
case a_ALEF_MAKSURA: return a_s_ALEF_MAKSURA;
case a_BEH: return a_s_BEH;
case a_TEH: return a_s_TEH;
case a_THEH: return a_s_THEH;
case a_JEEM: return a_s_JEEM;
case a_HAH: return a_s_HAH;
case a_KHAH: return a_s_KHAH;
case a_SEEN: return a_s_SEEN;
case a_SHEEN: return a_s_SHEEN;
case a_SAD: return a_s_SAD;
case a_DAD: return a_s_DAD;
case a_TAH: return a_s_TAH;
case a_ZAH: return a_s_ZAH;
case a_AIN: return a_s_AIN;
case a_GHAIN: return a_s_GHAIN;
case a_FEH: return a_s_FEH;
case a_QAF: return a_s_QAF;
case a_KAF: return a_s_KAF;
case a_LAM: return a_s_LAM;
case a_MEEM: return a_s_MEEM;
case a_NOON: return a_s_NOON;
case a_HEH: return a_s_HEH;
case a_YEH: return a_s_YEH;
}
return tempc;
return 0;
}
@@ -329,126 +251,62 @@ chg_c_a2s(int cur_c)
static int
chg_c_a2i(int cur_c)
{
int tempc;
switch (cur_c)
{
case a_YEH_HAMZA:
tempc = a_i_YEH_HAMZA;
break;
case a_YEH_HAMZA: return a_i_YEH_HAMZA;
case a_HAMZA: /* exceptions */
tempc = a_s_HAMZA;
break;
return a_s_HAMZA;
case a_ALEF_MADDA: /* exceptions */
tempc = a_s_ALEF_MADDA;
break;
return a_s_ALEF_MADDA;
case a_ALEF_HAMZA_ABOVE: /* exceptions */
tempc = a_s_ALEF_HAMZA_ABOVE;
break;
return a_s_ALEF_HAMZA_ABOVE;
case a_WAW_HAMZA: /* exceptions */
tempc = a_s_WAW_HAMZA;
break;
return a_s_WAW_HAMZA;
case a_ALEF_HAMZA_BELOW: /* exceptions */
tempc = a_s_ALEF_HAMZA_BELOW;
break;
return a_s_ALEF_HAMZA_BELOW;
case a_ALEF: /* exceptions */
tempc = a_s_ALEF;
break;
return a_s_ALEF;
case a_TEH_MARBUTA: /* exceptions */
tempc = a_s_TEH_MARBUTA;
break;
return a_s_TEH_MARBUTA;
case a_DAL: /* exceptions */
tempc = a_s_DAL;
break;
return a_s_DAL;
case a_THAL: /* exceptions */
tempc = a_s_THAL;
break;
return a_s_THAL;
case a_REH: /* exceptions */
tempc = a_s_REH;
break;
return a_s_REH;
case a_ZAIN: /* exceptions */
tempc = a_s_ZAIN;
break;
return a_s_ZAIN;
case a_TATWEEL: /* exceptions */
tempc = cur_c;
break;
return cur_c;
case a_WAW: /* exceptions */
tempc = a_s_WAW;
break;
return a_s_WAW;
case a_ALEF_MAKSURA: /* exceptions */
tempc = a_s_ALEF_MAKSURA;
break;
case a_BEH:
tempc = a_i_BEH;
break;
case a_TEH:
tempc = a_i_TEH;
break;
case a_THEH:
tempc = a_i_THEH;
break;
case a_JEEM:
tempc = a_i_JEEM;
break;
case a_HAH:
tempc = a_i_HAH;
break;
case a_KHAH:
tempc = a_i_KHAH;
break;
case a_SEEN:
tempc = a_i_SEEN;
break;
case a_SHEEN:
tempc = a_i_SHEEN;
break;
case a_SAD:
tempc = a_i_SAD;
break;
case a_DAD:
tempc = a_i_DAD;
break;
case a_TAH:
tempc = a_i_TAH;
break;
case a_ZAH:
tempc = a_i_ZAH;
break;
case a_AIN:
tempc = a_i_AIN;
break;
case a_GHAIN:
tempc = a_i_GHAIN;
break;
case a_FEH:
tempc = a_i_FEH;
break;
case a_QAF:
tempc = a_i_QAF;
break;
case a_KAF:
tempc = a_i_KAF;
break;
case a_LAM:
tempc = a_i_LAM;
break;
case a_MEEM:
tempc = a_i_MEEM;
break;
case a_NOON:
tempc = a_i_NOON;
break;
case a_HEH:
tempc = a_i_HEH;
break;
case a_YEH:
tempc = a_i_YEH;
break;
default:
tempc = 0;
return a_s_ALEF_MAKSURA;
case a_BEH: return a_i_BEH;
case a_TEH: return a_i_TEH;
case a_THEH: return a_i_THEH;
case a_JEEM: return a_i_JEEM;
case a_HAH: return a_i_HAH;
case a_KHAH: return a_i_KHAH;
case a_SEEN: return a_i_SEEN;
case a_SHEEN: return a_i_SHEEN;
case a_SAD: return a_i_SAD;
case a_DAD: return a_i_DAD;
case a_TAH: return a_i_TAH;
case a_ZAH: return a_i_ZAH;
case a_AIN: return a_i_AIN;
case a_GHAIN: return a_i_GHAIN;
case a_FEH: return a_i_FEH;
case a_QAF: return a_i_QAF;
case a_KAF: return a_i_KAF;
case a_LAM: return a_i_LAM;
case a_MEEM: return a_i_MEEM;
case a_NOON: return a_i_NOON;
case a_HEH: return a_i_HEH;
case a_YEH: return a_i_YEH;
}
return tempc;
return 0;
}
@@ -458,126 +316,48 @@ chg_c_a2i(int cur_c)
static int
chg_c_a2m(int cur_c)
{
int tempc;
switch (cur_c)
{
case a_HAMZA: /* exception */
tempc = a_s_HAMZA;
break;
case a_ALEF_MADDA: /* exception */
tempc = a_f_ALEF_MADDA;
break;
case a_ALEF_HAMZA_ABOVE: /* exception */
tempc = a_f_ALEF_HAMZA_ABOVE;
break;
case a_WAW_HAMZA: /* exception */
tempc = a_f_WAW_HAMZA;
break;
case a_ALEF_HAMZA_BELOW: /* exception */
tempc = a_f_ALEF_HAMZA_BELOW;
break;
case a_YEH_HAMZA:
tempc = a_m_YEH_HAMZA;
break;
case a_ALEF: /* exception */
tempc = a_f_ALEF;
break;
case a_BEH:
tempc = a_m_BEH;
break;
case a_TEH_MARBUTA: /* exception */
tempc = a_f_TEH_MARBUTA;
break;
case a_TEH:
tempc = a_m_TEH;
break;
case a_THEH:
tempc = a_m_THEH;
break;
case a_JEEM:
tempc = a_m_JEEM;
break;
case a_HAH:
tempc = a_m_HAH;
break;
case a_KHAH:
tempc = a_m_KHAH;
break;
case a_DAL: /* exception */
tempc = a_f_DAL;
break;
case a_THAL: /* exception */
tempc = a_f_THAL;
break;
case a_REH: /* exception */
tempc = a_f_REH;
break;
case a_ZAIN: /* exception */
tempc = a_f_ZAIN;
break;
case a_SEEN:
tempc = a_m_SEEN;
break;
case a_SHEEN:
tempc = a_m_SHEEN;
break;
case a_SAD:
tempc = a_m_SAD;
break;
case a_DAD:
tempc = a_m_DAD;
break;
case a_TAH:
tempc = a_m_TAH;
break;
case a_ZAH:
tempc = a_m_ZAH;
break;
case a_AIN:
tempc = a_m_AIN;
break;
case a_GHAIN:
tempc = a_m_GHAIN;
break;
case a_TATWEEL: /* exception */
tempc = cur_c;
break;
case a_FEH:
tempc = a_m_FEH;
break;
case a_QAF:
tempc = a_m_QAF;
break;
case a_KAF:
tempc = a_m_KAF;
break;
case a_LAM:
tempc = a_m_LAM;
break;
case a_MEEM:
tempc = a_m_MEEM;
break;
case a_NOON:
tempc = a_m_NOON;
break;
case a_HEH:
tempc = a_m_HEH;
break;
case a_WAW: /* exception */
tempc = a_f_WAW;
break;
case a_ALEF_MAKSURA: /* exception */
tempc = a_f_ALEF_MAKSURA;
break;
case a_YEH:
tempc = a_m_YEH;
break;
default:
tempc = 0;
case a_HAMZA: return a_s_HAMZA; /* exception */
case a_ALEF_MADDA: return a_f_ALEF_MADDA; /* exception */
case a_ALEF_HAMZA_ABOVE: return a_f_ALEF_HAMZA_ABOVE; /* exception */
case a_WAW_HAMZA: return a_f_WAW_HAMZA; /* exception */
case a_ALEF_HAMZA_BELOW: return a_f_ALEF_HAMZA_BELOW; /* exception */
case a_YEH_HAMZA: return a_m_YEH_HAMZA;
case a_ALEF: return a_f_ALEF; /* exception */
case a_BEH: return a_m_BEH;
case a_TEH_MARBUTA: return a_f_TEH_MARBUTA; /* exception */
case a_TEH: return a_m_TEH;
case a_THEH: return a_m_THEH;
case a_JEEM: return a_m_JEEM;
case a_HAH: return a_m_HAH;
case a_KHAH: return a_m_KHAH;
case a_DAL: return a_f_DAL; /* exception */
case a_THAL: return a_f_THAL; /* exception */
case a_REH: return a_f_REH; /* exception */
case a_ZAIN: return a_f_ZAIN; /* exception */
case a_SEEN: return a_m_SEEN;
case a_SHEEN: return a_m_SHEEN;
case a_SAD: return a_m_SAD;
case a_DAD: return a_m_DAD;
case a_TAH: return a_m_TAH;
case a_ZAH: return a_m_ZAH;
case a_AIN: return a_m_AIN;
case a_GHAIN: return a_m_GHAIN;
case a_TATWEEL: return cur_c; /* exception */
case a_FEH: return a_m_FEH;
case a_QAF: return a_m_QAF;
case a_KAF: return a_m_KAF;
case a_LAM: return a_m_LAM;
case a_MEEM: return a_m_MEEM;
case a_NOON: return a_m_NOON;
case a_HEH: return a_m_HEH;
case a_WAW: return a_f_WAW; /* exception */
case a_ALEF_MAKSURA: return a_f_ALEF_MAKSURA; /* exception */
case a_YEH: return a_m_YEH;
}
return tempc;
return 0;
}

View File

@@ -1966,7 +1966,7 @@ channel_parse_json(channel_T *channel, ch_part_T part)
* more (but still incomplete): set a deadline of 100 msec. */
ch_logn(channel,
"Incomplete message (%d bytes) - wait 100 msec for more",
buflen);
(int)buflen);
reader.js_used = 0;
chanpart->ch_wait_len = buflen;
#ifdef WIN32
@@ -3299,6 +3299,7 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout)
channel_read(channel, part, "channel_read_block");
}
/* We have a complete message now. */
if (mode == MODE_RAW)
{
msg = channel_get_all(channel, part);

View File

@@ -186,7 +186,7 @@ static int ins_compl_pum_key(int c);
static int ins_compl_key2count(int c);
static int ins_compl_use_match(int c);
static int ins_complete(int c, int enable_pum);
static void show_pum(int save_w_wrow);
static void show_pum(int prev_w_wrow, int prev_w_leftcol);
static unsigned quote_meta(char_u *dest, char_u *str, int len);
#endif /* FEAT_INS_EXPAND */
@@ -1038,8 +1038,10 @@ doESCkey:
if (!p_im)
goto normalchar; /* insert CTRL-Z as normal char */
do_cmdline_cmd((char_u *)"stop");
c = Ctrl_O;
/*FALLTHROUGH*/
#ifdef CURSOR_SHAPE
ui_cursor_shape(); /* may need to update cursor shape */
#endif
continue;
case Ctrl_O: /* execute one command */
#ifdef FEAT_COMPL_FUNC
@@ -2816,6 +2818,7 @@ completeopt_was_set(void)
set_completion(colnr_T startcol, list_T *list)
{
int save_w_wrow = curwin->w_wrow;
int save_w_leftcol = curwin->w_leftcol;
/* If already doing completions stop it. */
if (ctrl_x_mode != 0)
@@ -2856,7 +2859,7 @@ set_completion(colnr_T startcol, list_T *list)
/* Lazily show the popup menu, unless we got interrupted. */
if (!compl_interrupted)
show_pum(save_w_wrow);
show_pum(save_w_wrow, save_w_leftcol);
out_flush();
}
@@ -5094,6 +5097,7 @@ ins_complete(int c, int enable_pum)
colnr_T curs_col; /* cursor column */
int n;
int save_w_wrow;
int save_w_leftcol;
int insert_match;
int save_did_ai = did_ai;
@@ -5537,6 +5541,7 @@ ins_complete(int c, int enable_pum)
* Find next match (and following matches).
*/
save_w_wrow = curwin->w_wrow;
save_w_leftcol = curwin->w_leftcol;
n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE);
/* may undisplay the popup menu */
@@ -5689,9 +5694,8 @@ ins_complete(int c, int enable_pum)
/* Show the popup menu, unless we got interrupted. */
if (enable_pum && !compl_interrupted)
{
show_pum(save_w_wrow);
}
show_pum(save_w_wrow, save_w_leftcol);
compl_was_interrupted = compl_interrupted;
compl_interrupted = FALSE;
@@ -5699,21 +5703,22 @@ ins_complete(int c, int enable_pum)
}
static void
show_pum(int save_w_wrow)
show_pum(int prev_w_wrow, int prev_w_leftcol)
{
/* RedrawingDisabled may be set when invoked through complete(). */
int n = RedrawingDisabled;
/* RedrawingDisabled may be set when invoked through complete(). */
int n = RedrawingDisabled;
RedrawingDisabled = 0;
RedrawingDisabled = 0;
/* If the cursor moved we need to remove the pum first. */
setcursor();
if (save_w_wrow != curwin->w_wrow)
ins_compl_del_pum();
/* If the cursor moved or the display scrolled we need to remove the pum
* first. */
setcursor();
if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol)
ins_compl_del_pum();
ins_compl_show_pum();
setcursor();
RedrawingDisabled = n;
ins_compl_show_pum();
setcursor();
RedrawingDisabled = n;
}
/*

View File

@@ -58,6 +58,9 @@ static void f_asin(typval_T *argvars, typval_T *rettv);
static void f_atan(typval_T *argvars, typval_T *rettv);
static void f_atan2(typval_T *argvars, typval_T *rettv);
#endif
#ifdef FEAT_BEVAL
static void f_balloon_show(typval_T *argvars, typval_T *rettv);
#endif
static void f_browse(typval_T *argvars, typval_T *rettv);
static void f_browsedir(typval_T *argvars, typval_T *rettv);
static void f_bufexists(typval_T *argvars, typval_T *rettv);
@@ -389,6 +392,7 @@ static void f_test_alloc_fail(typval_T *argvars, typval_T *rettv);
static void f_test_autochdir(typval_T *argvars, typval_T *rettv);
static void f_test_disable_char_avail(typval_T *argvars, typval_T *rettv);
static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv);
static void f_test_ignore_error(typval_T *argvars, typval_T *rettv);
#ifdef FEAT_JOB_CHANNEL
static void f_test_null_channel(typval_T *argvars, typval_T *rettv);
#endif
@@ -482,6 +486,9 @@ static struct fst
#ifdef FEAT_FLOAT
{"atan", 1, 1, f_atan},
{"atan2", 2, 2, f_atan2},
#endif
#ifdef FEAT_BEVAL
{"balloon_show", 1, 1, f_balloon_show},
#endif
{"browse", 4, 4, f_browse},
{"browsedir", 2, 2, f_browsedir},
@@ -823,6 +830,7 @@ static struct fst
{"test_autochdir", 0, 0, f_test_autochdir},
{"test_disable_char_avail", 1, 1, f_test_disable_char_avail},
{"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now},
{"test_ignore_error", 1, 1, f_test_ignore_error},
#ifdef FEAT_JOB_CHANNEL
{"test_null_channel", 0, 0, f_test_null_channel},
#endif
@@ -1360,6 +1368,18 @@ f_atan2(typval_T *argvars, typval_T *rettv)
}
#endif
/*
* "balloon_show()" function
*/
#ifdef FEAT_BEVAL
static void
f_balloon_show(typval_T *argvars, typval_T *rettv UNUSED)
{
if (balloonEval != NULL)
gui_mch_post_balloon(balloonEval, get_tv_string_chk(&argvars[0]));
}
#endif
/*
* "browse(save, title, initdir, default)" function
*/
@@ -12325,6 +12345,15 @@ f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
garbage_collect(TRUE);
}
/*
* "test_ignore_error()" function
*/
static void
f_test_ignore_error(typval_T *argvars, typval_T *rettv UNUSED)
{
ignore_error_for_testing(get_tv_string(&argvars[0]));
}
#ifdef FEAT_JOB_CHANNEL
static void
f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv)

View File

@@ -9812,6 +9812,7 @@ ex_redraw(exarg_T *eap)
RedrawingDisabled = 0;
p_lz = FALSE;
validate_cursor();
update_topline();
update_screen(eap->forceit ? CLEAR : VIsual_active ? INVERTED : 0);
#ifdef FEAT_TITLE

View File

@@ -1576,16 +1576,23 @@ foldMarkAdjustRecurse(
{
/* 5. fold is below line1 and contains line2; need to
* correct nested folds too */
foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top,
line2 - fp->fd_top, amount,
amount_after + (fp->fd_top - top));
if (amount == MAXLNUM)
{
foldMarkAdjustRecurse(&fp->fd_nested,
line1 - fp->fd_top,
line2 - fp->fd_top,
amount,
amount_after + (fp->fd_top - top));
fp->fd_len -= line2 - fp->fd_top + 1;
fp->fd_top = line1;
}
else
{
foldMarkAdjustRecurse(&fp->fd_nested,
line1 - fp->fd_top,
line2 - fp->fd_top,
amount,
amount_after - amount);
fp->fd_len += amount_after - amount;
fp->fd_top += amount;
}

View File

@@ -1,10 +1,10 @@
" Script to generate testdir/opt_test.vim from option.c
if 0
finish
endif
set cpo=&vim
" Only do this when build with the +eval feature.
if 1
set nomore
let script = [
@@ -130,7 +130,6 @@ let test_values = {
\ 'winaltkeys': [['menu', 'no'], ['', 'xxx']],
\
\ 'luadll': [[], []],
\ 'macatsui': [[], []],
\ 'perldll': [[], []],
\ 'pythondll': [[], []],
\ 'pythonthreedll': [[], []],
@@ -192,4 +191,6 @@ call add(script, 'let &lines = save_lines')
call writefile(script, 'testdir/opt_test.vim')
endif
qa!

View File

@@ -4216,6 +4216,11 @@ set_context_in_map_cmd(
arg = skipwhite(arg + 8);
continue;
}
if (STRNCMP(arg, "<special>", 9) == 0)
{
arg = skipwhite(arg + 9);
continue;
}
#ifdef FEAT_EVAL
if (STRNCMP(arg, "<script>", 8) == 0)
{
@@ -4267,7 +4272,7 @@ ExpandMappings(
{
count = 0;
for (i = 0; i < 6; ++i)
for (i = 0; i < 7; ++i)
{
if (i == 0)
p = (char_u *)"<silent>";
@@ -4285,6 +4290,8 @@ ExpandMappings(
#endif
else if (i == 5)
p = (char_u *)"<nowait>";
else if (i == 6)
p = (char_u *)"<special>";
else
continue;

View File

@@ -57,6 +57,9 @@ static void main_start_gui(void);
# if defined(HAS_SWAP_EXISTS_ACTION)
static void check_swap_exists_action(void);
# endif
# ifdef FEAT_EVAL
static void set_progpath(char_u *argv0);
# endif
# if defined(FEAT_CLIENTSERVER) || defined(PROTO)
static void exec_on_server(mparm_T *parmp);
static void prepare_server(mparm_T *parmp);
@@ -1694,7 +1697,7 @@ parse_command_name(mparm_T *parmp)
#ifdef FEAT_EVAL
set_vim_var_string(VV_PROGNAME, initstr, -1);
set_vim_var_string(VV_PROGPATH, (char_u *)parmp->argv[0], -1);
set_progpath((char_u *)parmp->argv[0]);
#endif
if (TOLOWER_ASC(initstr[0]) == 'r')
@@ -3417,7 +3420,7 @@ check_swap_exists_action(void)
}
#endif
#endif
#endif /* NO_VIM_MAIN */
#if defined(STARTUPTIME) || defined(PROTO)
static void time_diff(struct timeval *then, struct timeval *now);
@@ -3525,6 +3528,30 @@ time_msg(
#endif
#ifndef NO_VIM_MAIN
static void
set_progpath(char_u *argv0)
{
char_u *val = argv0;
char_u buf[MAXPATHL];
/* A relative path containing a "/" will become invalid when using ":cd",
* turn it into a full path.
* On MS-Windows "vim.exe" is found in the current directory, thus also do
* it when there is no path and the file exists. */
if ( !mch_isFullName(argv0)
# ifdef WIN32
&& mch_can_exe(argv0, NULL, TRUE)
# else
&& gettail(argv0) != argv0
# endif
&& vim_FullName(argv0, buf, MAXPATHL, TRUE) != FAIL)
val = buf;
set_vim_var_string(VV_PROGPATH, val, -1);
}
#endif /* NO_VIM_MAIN */
#if (defined(FEAT_CLIENTSERVER) && !defined(NO_VIM_MAIN)) || defined(PROTO)
/*

View File

@@ -1863,7 +1863,7 @@ recover_names(
else
{
#if defined(UNIX) || defined(WIN3264)
int len = STRLEN(dir_name);
int len = (int)STRLEN(dir_name);
p = dir_name + len;
if (after_pathsep(dir_name, p) && len > 1 && p[-1] == p[-2])
@@ -3924,7 +3924,7 @@ makeswapname(
#endif
#if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */
int len = STRLEN(dir_name);
int len = (int)STRLEN(dir_name);
s = dir_name + len;
if (after_pathsep(dir_name, s) && len > 1 && s[-1] == s[-2])

View File

@@ -539,6 +539,31 @@ emsg_not_now(void)
return FALSE;
}
#if defined(FEAT_EVAL) || defined(PROTO)
static garray_T ignore_error_list = GA_EMPTY;
void
ignore_error_for_testing(char_u *error)
{
if (ignore_error_list.ga_itemsize == 0)
ga_init2(&ignore_error_list, sizeof(char_u *), 1);
ga_add_string(&ignore_error_list, error);
}
static int
ignore_error(char_u *msg)
{
int i;
for (i = 0; i < ignore_error_list.ga_len; ++i)
if (strstr((char *)msg,
(char *)((char_u **)(ignore_error_list.ga_data))[i]) != NULL)
return TRUE;
return FALSE;
}
#endif
#if !defined(HAVE_STRERROR) || defined(PROTO)
/*
* Replacement for perror() that behaves more or less like emsg() was called.
@@ -577,6 +602,13 @@ emsg(char_u *s)
if (emsg_not_now())
return TRUE;
#ifdef FEAT_EVAL
/* When testing some errors are turned into a normal message. */
if (ignore_error(s))
/* don't call msg() if it results in a dialog */
return msg_use_printf() ? FALSE : msg(s);
#endif
called_emsg = TRUE;
/*

View File

@@ -2099,7 +2099,7 @@ ga_concat_strings(garray_T *gap, char *sep)
return s;
}
#if defined(FEAT_VIMINFO) || defined(PROTO)
#if defined(FEAT_VIMINFO) || defined(FEAT_EVAL) || defined(PROTO)
/*
* Make a copy of string "p" and add it to "gap".
* When out of memory nothing changes.

View File

@@ -2982,8 +2982,6 @@ do_mouse(
|| (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
&& bt_quickfix(curbuf))
{
if (State & INSERT)
stuffcharReadbuff(Ctrl_O);
if (curwin->w_llist_ref == NULL) /* quickfix window */
do_cmdline_cmd((char_u *)".cc");
else /* location list window */
@@ -6193,10 +6191,12 @@ nv_down(cmdarg_T *cap)
#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
/* In a quickfix window a <CR> jumps to the error under the cursor. */
if (bt_quickfix(curbuf) && cap->cmdchar == CAR)
{
if (curwin->w_llist_ref == NULL)
do_cmdline_cmd((char_u *)".cc"); /* quickfix window */
else
do_cmdline_cmd((char_u *)".ll"); /* location list window */
}
else
#endif
{

View File

@@ -467,6 +467,12 @@ mch_inchar(
if ((wait_time < 0 || wait_time > 100L) && channel_any_readahead())
wait_time = 10L;
#endif
#ifdef FEAT_BEVAL
if (p_beval && wait_time > 100L)
/* The 'balloonexpr' may indirectly invoke a callback while waiting
* for a character, need to check often. */
wait_time = 100L;
#endif
/*
* We want to be interrupted by the winch signal

View File

@@ -1467,6 +1467,12 @@ WaitForChar(long msec)
dwWaitTime = 10;
}
#endif
#ifdef FEAT_BEVAL
if (p_beval && dwWaitTime > 100)
/* The 'balloonexpr' may indirectly invoke a callback while
* waiting for a character, need to check often. */
dwWaitTime = 100;
#endif
#ifdef FEAT_MZSCHEME
if (mzthreads_allowed() && p_mzq > 0
&& (msec < 0 || (long)dwWaitTime > p_mzq))

View File

@@ -8,6 +8,7 @@ void trunc_string(char_u *s, char_u *buf, int room_in, int buflen);
void reset_last_sourcing(void);
void msg_source(int attr);
int emsg_not_now(void);
void ignore_error_for_testing(char_u *error);
void do_perror(char *msg);
int emsg(char_u *s);
int emsg2(char_u *s, char_u *a1);

View File

@@ -3429,10 +3429,13 @@ win_line(
#else
--ptr;
#endif
/* If the character fits on the screen, don't need to skip it.
* Except for a TAB. */
if ((
#ifdef FEAT_MBYTE
/* character fits on the screen, don't need to skip it */
if ((*mb_ptr2cells)(ptr) >= c && col == 0)
(*mb_ptr2cells)(ptr) >= c ||
#endif
*ptr == TAB) && col == 0)
n_skip = v - vcol;
}
@@ -4189,6 +4192,10 @@ win_line(
}
else
{
#ifdef FEAT_LINEBREAK
int c0;
#endif
if (p_extra_free != NULL)
{
vim_free(p_extra_free);
@@ -4198,6 +4205,9 @@ win_line(
* Get a character from the line itself.
*/
c = *ptr;
#ifdef FEAT_LINEBREAK
c0 = *ptr;
#endif
#ifdef FEAT_MBYTE
if (has_mbyte)
{
@@ -4214,7 +4224,12 @@ win_line(
/* Overlong encoded ASCII or ASCII with composing char
* is displayed normally, except a NUL. */
if (mb_c < 0x80)
{
c = mb_c;
# ifdef FEAT_LINEBREAK
c0 = mb_c;
# endif
}
mb_utf8 = TRUE;
/* At start of the line we can have a composing char.
@@ -4538,7 +4553,8 @@ win_line(
/*
* Found last space before word: check for line break.
*/
if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr))
if (wp->w_p_lbr && c0 == c
&& vim_isbreak(c) && !vim_isbreak(*ptr))
{
# ifdef FEAT_MBYTE
int mb_off = has_mbyte ? (*mb_head_off)(line, ptr - 1) : 0;

View File

@@ -1693,12 +1693,9 @@ searchc(cmdarg_T *cap, int t_cmd)
if (p[col] == c && stop)
break;
}
else
{
if (memcmp(p + col, lastc_bytes, lastc_bytelen) == 0
else if (STRNCMP(p + col, lastc_bytes, lastc_bytelen) == 0
&& stop)
break;
}
break;
stop = TRUE;
}
}

View File

@@ -1585,7 +1585,7 @@ spell_read_tree(
int prefixtree, /* TRUE for the prefix tree */
int prefixcnt) /* when "prefixtree" is TRUE: prefix count */
{
int len;
long len;
int idx;
char_u *bp;
idx_T *ip;
@@ -1595,7 +1595,7 @@ spell_read_tree(
len = get4c(fd);
if (len < 0)
return SP_TRUNCERROR;
if (len >= 0x3ffffff)
if (len >= LONG_MAX / (long)sizeof(int))
/* Invalid length, multiply with sizeof(int) would overflow. */
return SP_FORMERROR;
if (len > 0)

View File

@@ -35,9 +35,10 @@ typedef struct tag_pointers
} tagptrs_T;
/*
* The matching tags are first stored in one of the ht_match[] hash tables. In
* The matching tags are first stored in one of the hash tables. In
* which one depends on the priority of the match.
* At the end, all the matches from ht_match[] are concatenated, to make a list
* ht_match[] is used to find duplicates, ga_match[] to keep them in sequence.
* At the end, all the matches from ga_match[] are concatenated, to make a list
* sorted on priority.
*/
#define MT_ST_CUR 0 /* static match in current file */
@@ -1339,7 +1340,8 @@ find_tags(
#endif
char_u *mfp;
hashtab_T ht_match[MT_COUNT];
garray_T ga_match[MT_COUNT]; /* stores matches in sequence */
hashtab_T ht_match[MT_COUNT]; /* stores matches by key */
hash_T hash = 0;
int match_count = 0; /* number of matches found */
char_u **matches;
@@ -1405,7 +1407,10 @@ find_tags(
ebuf = alloc(LSIZE);
#endif
for (mtt = 0; mtt < MT_COUNT; ++mtt)
{
ga_init2(&ga_match[mtt], (int)sizeof(char_u *), 100);
hash_init(&ht_match[mtt]);
}
/* check for out of memory situation */
if (lbuf == NULL || tag_fname == NULL
@@ -2213,7 +2218,7 @@ parse_line:
}
/*
* If a match is found, add it to ht_match[].
* If a match is found, add it to ht_match[] and ga_match[].
*/
if (match)
{
@@ -2271,7 +2276,7 @@ parse_line:
}
/*
* Add the found match in ht_match[mtt].
* Add the found match in ht_match[mtt] and ga_match[mtt].
* Store the info we need later, which depends on the kind of
* tags we are dealing with.
*/
@@ -2423,7 +2428,8 @@ parse_line:
if (HASHITEM_EMPTY(hi))
{
if (hash_add_item(&ht_match[mtt], hi, mfp, hash)
== FAIL)
== FAIL
|| ga_grow(&ga_match[mtt], 1) != OK)
{
/* Out of memory! Just forget about the rest. */
retval = OK;
@@ -2431,7 +2437,11 @@ parse_line:
break;
}
else
{
((char_u **)(ga_match[mtt].ga_data))
[ga_match[mtt].ga_len++] = mfp;
++match_count;
}
}
else
/* duplicate tag, drop it */
@@ -2533,7 +2543,7 @@ findtag_end:
#endif
/*
* Move the matches from the ht_match[] arrays into one list of
* Move the matches from the ga_match[] arrays into one list of
* matches. When retval == FAIL, free the matches.
*/
if (retval == FAIL)
@@ -2547,34 +2557,28 @@ findtag_end:
match_count = 0;
for (mtt = 0; mtt < MT_COUNT; ++mtt)
{
hashitem_T *hi;
long_u todo;
todo = (long)ht_match[mtt].ht_used;
for (hi = ht_match[mtt].ht_array; todo > 0; ++hi)
for (i = 0; i < ga_match[mtt].ga_len; ++i)
{
if (!HASHITEM_EMPTY(hi))
mfp = ((char_u **)(ga_match[mtt].ga_data))[i];
if (matches == NULL)
vim_free(mfp);
else
{
mfp = hi->hi_key;
if (matches == NULL)
vim_free(mfp);
else
if (!name_only)
{
if (!name_only)
{
/* Change mtt back to zero-based. */
*mfp = *mfp - 1;
/* Change mtt back to zero-based. */
*mfp = *mfp - 1;
/* change the TAG_SEP back to NUL */
for (p = mfp + 1; *p != NUL; ++p)
if (*p == TAG_SEP)
*p = NUL;
}
matches[match_count++] = (char_u *)mfp;
/* change the TAG_SEP back to NUL */
for (p = mfp + 1; *p != NUL; ++p)
if (*p == TAG_SEP)
*p = NUL;
}
todo--;
matches[match_count++] = (char_u *)mfp;
}
}
ga_clear(&ga_match[mtt]);
hash_clear(&ht_match[mtt]);
}

View File

@@ -133,7 +133,8 @@ SCRIPTS_GUI =
# Tests using runtest.vim.vim.
# Keep test_alot*.res as the last one, sort the others.
NEW_TESTS = test_arglist.res \
NEW_TESTS = test_arabic.res \
test_arglist.res \
test_assert.res \
test_autochdir.res \
test_backspace_opt.res \

View File

@@ -165,6 +165,7 @@ let s:flaky = [
\ 'Test_collapse_buffers()',
\ 'Test_communicate()',
\ 'Test_nb_basic()',
\ 'Test_oneshot()',
\ 'Test_pipe_through_sort_all()',
\ 'Test_pipe_through_sort_some()',
\ 'Test_reltime()',

View File

@@ -27,3 +27,6 @@ endfunc
func GUITearDownCommon()
call delete('Xhome', 'rf')
endfunc
" Ignore the "failed to create input context" error.
call test_ignore_error('E285')

View File

@@ -192,6 +192,7 @@ func RunVimPiped(before, after, arguments, pipecmd)
if cmd !~ '-u NONE'
let cmd = cmd . ' -u NONE'
endif
let cmd .= ' --not-a-term'
" With pipecmd we can't set VIMRUNTIME.
if a:pipecmd != ''

472
src/testdir/test_arabic.vim Normal file
View File

@@ -0,0 +1,472 @@
" Simplistic testing of Arabic mode.
if !has('arabic') || !has('multi_byte')
finish
endif
source view_util.vim
" Return list of Unicode characters at line lnum.
" Combining characters are treated as a single item.
func s:get_chars(lnum)
call cursor(a:lnum, 1)
let chars = []
let numchars = strchars(getline('.'), 1)
for i in range(1, numchars)
exe 'norm ' i . '|'
let c=execute('ascii')
let c=substitute(c, '\n\?<.\{-}Hex\s*', 'U+', 'g')
let c=substitute(c, ',\s*Octal\s*\d*', '', 'g')
call add(chars, c)
endfor
return chars
endfunc
func Test_arabic_toggle()
set arabic
call assert_equal(1, &rightleft)
call assert_equal(1, &arabicshape)
call assert_equal('arabic', &keymap)
call assert_equal(1, &delcombine)
set iminsert=1 imsearch=1
set arabic&
call assert_equal(0, &rightleft)
call assert_equal(1, &arabicshape)
call assert_equal('arabic', &keymap)
call assert_equal(1, &delcombine)
call assert_equal(0, &iminsert)
call assert_equal(-1, &imsearch)
set arabicshape& keymap= delcombine&
endfunc
func Test_arabic_input()
new
set arabic
" Typing sghl in Arabic insert mode should show the
" Arabic word 'Salaam' i.e. 'peace', spelled:
" SEEN, LAM, ALEF, MEEM.
" See: https://www.mediawiki.org/wiki/VisualEditor/Typing/Right-to-left
call feedkeys('isghl!', 'tx')
call assert_match("^ *!\uFEE1\uFEFC\uFEB3$", ScreenLines(1, &columns)[0])
call assert_equal([
\ 'U+0633',
\ 'U+0644 U+0627',
\ 'U+0645',
\ 'U+21'], s:get_chars(1))
" Without shaping, it should give individual Arabic letters.
set noarabicshape
call assert_match("^ *!\u0645\u0627\u0644\u0633$", ScreenLines(1, &columns)[0])
call assert_equal([
\ 'U+0633',
\ 'U+0644',
\ 'U+0627',
\ 'U+0645',
\ 'U+21'], s:get_chars(1))
set arabic& arabicshape&
bwipe!
endfunc
func Test_arabic_toggle_keymap()
new
set arabic
call feedkeys("i12\<C-^>12\<C-^>12", 'tx')
call assert_match("^ *٢١21٢١$", ScreenLines(1, &columns)[0])
call assert_equal('١٢12١٢', getline('.'))
set arabic&
bwipe!
endfunc
func Test_delcombine()
new
set arabic
call feedkeys("isghl\<BS>\<BS>", 'tx')
call assert_match("^ *\uFEDE\uFEB3$", ScreenLines(1, &columns)[0])
call assert_equal(['U+0633', 'U+0644'], s:get_chars(1))
" Now the same with 'nodelcombine'
set nodelcombine
%d
call feedkeys("isghl\<BS>\<BS>", 'tx')
call assert_match("^ *\uFEB1$", ScreenLines(1, &columns)[0])
call assert_equal(['U+0633'], s:get_chars(1))
set arabic&
bwipe!
endfunc
" Values from src/arabic.h (not all used yet)
let s:a_COMMA = "\u060C"
let s:a_SEMICOLON = "\u061B"
let s:a_QUESTION = "\u061F"
let s:a_HAMZA = "\u0621"
let s:a_ALEF_MADDA = "\u0622"
let s:a_ALEF_HAMZA_ABOVE = "\u0623"
let s:a_WAW_HAMZA = "\u0624"
let s:a_ALEF_HAMZA_BELOW = "\u0625"
let s:a_YEH_HAMZA = "\u0626"
let s:a_ALEF = "\u0627"
let s:a_BEH = "\u0628"
let s:a_TEH_MARBUTA = "\u0629"
let s:a_TEH = "\u062a"
let s:a_THEH = "\u062b"
let s:a_JEEM = "\u062c"
let s:a_HAH = "\u062d"
let s:a_KHAH = "\u062e"
let s:a_DAL = "\u062f"
let s:a_THAL = "\u0630"
let s:a_REH = "\u0631"
let s:a_ZAIN = "\u0632"
let s:a_SEEN = "\u0633"
let s:a_SHEEN = "\u0634"
let s:a_SAD = "\u0635"
let s:a_DAD = "\u0636"
let s:a_TAH = "\u0637"
let s:a_ZAH = "\u0638"
let s:a_AIN = "\u0639"
let s:a_GHAIN = "\u063a"
let s:a_TATWEEL = "\u0640"
let s:a_FEH = "\u0641"
let s:a_QAF = "\u0642"
let s:a_KAF = "\u0643"
let s:a_LAM = "\u0644"
let s:a_MEEM = "\u0645"
let s:a_NOON = "\u0646"
let s:a_HEH = "\u0647"
let s:a_WAW = "\u0648"
let s:a_ALEF_MAKSURA = "\u0649"
let s:a_YEH = "\u064a"
let s:a_FATHATAN = "\u064b"
let s:a_DAMMATAN = "\u064c"
let s:a_KASRATAN = "\u064d"
let s:a_FATHA = "\u064e"
let s:a_DAMMA = "\u064f"
let s:a_KASRA = "\u0650"
let s:a_SHADDA = "\u0651"
let s:a_SUKUN = "\u0652"
let s:a_MADDA_ABOVE = "\u0653"
let s:a_HAMZA_ABOVE = "\u0654"
let s:a_HAMZA_BELOW = "\u0655"
let s:a_ZERO = "\u0660"
let s:a_ONE = "\u0661"
let s:a_TWO = "\u0662"
let s:a_THREE = "\u0663"
let s:a_FOUR = "\u0664"
let s:a_FIVE = "\u0665"
let s:a_SIX = "\u0666"
let s:a_SEVEN = "\u0667"
let s:a_EIGHT = "\u0668"
let s:a_NINE = "\u0669"
let s:a_PERCENT = "\u066a"
let s:a_DECIMAL = "\u066b"
let s:a_THOUSANDS = "\u066c"
let s:a_STAR = "\u066d"
let s:a_MINI_ALEF = "\u0670"
let s:a_s_FATHATAN = "\ufe70"
let s:a_m_TATWEEL_FATHATAN = "\ufe71"
let s:a_s_DAMMATAN = "\ufe72"
let s:a_s_KASRATAN = "\ufe74"
let s:a_s_FATHA = "\ufe76"
let s:a_m_FATHA = "\ufe77"
let s:a_s_DAMMA = "\ufe78"
let s:a_m_DAMMA = "\ufe79"
let s:a_s_KASRA = "\ufe7a"
let s:a_m_KASRA = "\ufe7b"
let s:a_s_SHADDA = "\ufe7c"
let s:a_m_SHADDA = "\ufe7d"
let s:a_s_SUKUN = "\ufe7e"
let s:a_m_SUKUN = "\ufe7f"
let s:a_s_HAMZA = "\ufe80"
let s:a_s_ALEF_MADDA = "\ufe81"
let s:a_f_ALEF_MADDA = "\ufe82"
let s:a_s_ALEF_HAMZA_ABOVE = "\ufe83"
let s:a_f_ALEF_HAMZA_ABOVE = "\ufe84"
let s:a_s_WAW_HAMZA = "\ufe85"
let s:a_f_WAW_HAMZA = "\ufe86"
let s:a_s_ALEF_HAMZA_BELOW = "\ufe87"
let s:a_f_ALEF_HAMZA_BELOW = "\ufe88"
let s:a_s_YEH_HAMZA = "\ufe89"
let s:a_f_YEH_HAMZA = "\ufe8a"
let s:a_i_YEH_HAMZA = "\ufe8b"
let s:a_m_YEH_HAMZA = "\ufe8c"
let s:a_s_ALEF = "\ufe8d"
let s:a_f_ALEF = "\ufe8e"
let s:a_s_BEH = "\ufe8f"
let s:a_f_BEH = "\ufe90"
let s:a_i_BEH = "\ufe91"
let s:a_m_BEH = "\ufe92"
let s:a_s_TEH_MARBUTA = "\ufe93"
let s:a_f_TEH_MARBUTA = "\ufe94"
let s:a_s_TEH = "\ufe95"
let s:a_f_TEH = "\ufe96"
let s:a_i_TEH = "\ufe97"
let s:a_m_TEH = "\ufe98"
let s:a_s_THEH = "\ufe99"
let s:a_f_THEH = "\ufe9a"
let s:a_i_THEH = "\ufe9b"
let s:a_m_THEH = "\ufe9c"
let s:a_s_JEEM = "\ufe9d"
let s:a_f_JEEM = "\ufe9e"
let s:a_i_JEEM = "\ufe9f"
let s:a_m_JEEM = "\ufea0"
let s:a_s_HAH = "\ufea1"
let s:a_f_HAH = "\ufea2"
let s:a_i_HAH = "\ufea3"
let s:a_m_HAH = "\ufea4"
let s:a_s_KHAH = "\ufea5"
let s:a_f_KHAH = "\ufea6"
let s:a_i_KHAH = "\ufea7"
let s:a_m_KHAH = "\ufea8"
let s:a_s_DAL = "\ufea9"
let s:a_f_DAL = "\ufeaa"
let s:a_s_THAL = "\ufeab"
let s:a_f_THAL = "\ufeac"
let s:a_s_REH = "\ufead"
let s:a_f_REH = "\ufeae"
let s:a_s_ZAIN = "\ufeaf"
let s:a_f_ZAIN = "\ufeb0"
let s:a_s_SEEN = "\ufeb1"
let s:a_f_SEEN = "\ufeb2"
let s:a_i_SEEN = "\ufeb3"
let s:a_m_SEEN = "\ufeb4"
let s:a_s_SHEEN = "\ufeb5"
let s:a_f_SHEEN = "\ufeb6"
let s:a_i_SHEEN = "\ufeb7"
let s:a_m_SHEEN = "\ufeb8"
let s:a_s_SAD = "\ufeb9"
let s:a_f_SAD = "\ufeba"
let s:a_i_SAD = "\ufebb"
let s:a_m_SAD = "\ufebc"
let s:a_s_DAD = "\ufebd"
let s:a_f_DAD = "\ufebe"
let s:a_i_DAD = "\ufebf"
let s:a_m_DAD = "\ufec0"
let s:a_s_TAH = "\ufec1"
let s:a_f_TAH = "\ufec2"
let s:a_i_TAH = "\ufec3"
let s:a_m_TAH = "\ufec4"
let s:a_s_ZAH = "\ufec5"
let s:a_f_ZAH = "\ufec6"
let s:a_i_ZAH = "\ufec7"
let s:a_m_ZAH = "\ufec8"
let s:a_s_AIN = "\ufec9"
let s:a_f_AIN = "\ufeca"
let s:a_i_AIN = "\ufecb"
let s:a_m_AIN = "\ufecc"
let s:a_s_GHAIN = "\ufecd"
let s:a_f_GHAIN = "\ufece"
let s:a_i_GHAIN = "\ufecf"
let s:a_m_GHAIN = "\ufed0"
let s:a_s_FEH = "\ufed1"
let s:a_f_FEH = "\ufed2"
let s:a_i_FEH = "\ufed3"
let s:a_m_FEH = "\ufed4"
let s:a_s_QAF = "\ufed5"
let s:a_f_QAF = "\ufed6"
let s:a_i_QAF = "\ufed7"
let s:a_m_QAF = "\ufed8"
let s:a_s_KAF = "\ufed9"
let s:a_f_KAF = "\ufeda"
let s:a_i_KAF = "\ufedb"
let s:a_m_KAF = "\ufedc"
let s:a_s_LAM = "\ufedd"
let s:a_f_LAM = "\ufede"
let s:a_i_LAM = "\ufedf"
let s:a_m_LAM = "\ufee0"
let s:a_s_MEEM = "\ufee1"
let s:a_f_MEEM = "\ufee2"
let s:a_i_MEEM = "\ufee3"
let s:a_m_MEEM = "\ufee4"
let s:a_s_NOON = "\ufee5"
let s:a_f_NOON = "\ufee6"
let s:a_i_NOON = "\ufee7"
let s:a_m_NOON = "\ufee8"
let s:a_s_HEH = "\ufee9"
let s:a_f_HEH = "\ufeea"
let s:a_i_HEH = "\ufeeb"
let s:a_m_HEH = "\ufeec"
let s:a_s_WAW = "\ufeed"
let s:a_f_WAW = "\ufeee"
let s:a_s_ALEF_MAKSURA = "\ufeef"
let s:a_f_ALEF_MAKSURA = "\ufef0"
let s:a_s_YEH = "\ufef1"
let s:a_f_YEH = "\ufef2"
let s:a_i_YEH = "\ufef3"
let s:a_m_YEH = "\ufef4"
let s:a_s_LAM_ALEF_MADDA_ABOVE = "\ufef5"
let s:a_f_LAM_ALEF_MADDA_ABOVE = "\ufef6"
let s:a_s_LAM_ALEF_HAMZA_ABOVE = "\ufef7"
let s:a_f_LAM_ALEF_HAMZA_ABOVE = "\ufef8"
let s:a_s_LAM_ALEF_HAMZA_BELOW = "\ufef9"
let s:a_f_LAM_ALEF_HAMZA_BELOW = "\ufefa"
let s:a_s_LAM_ALEF = "\ufefb"
let s:a_f_LAM_ALEF = "\ufefc"
let s:a_BYTE_ORDER_MARK = "\ufeff"
func Test_shape_initial()
new
set arabicshape
" Shaping arabic {testchar} non-arabic Tests chg_c_a2i().
" pair[0] = testchar, pair[1] = next-result, pair[2] = current-result
for pair in [[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_i_YEH_HAMZA],
\ [s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA],
\ [s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_s_ALEF_MADDA],
\ [s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_ABOVE],
\ [s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_s_WAW_HAMZA],
\ [s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_BELOW],
\ [s:a_ALEF, s:a_s_GHAIN, s:a_s_ALEF],
\ [s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_s_TEH_MARBUTA],
\ [s:a_DAL, s:a_s_GHAIN, s:a_s_DAL],
\ [s:a_THAL, s:a_s_GHAIN, s:a_s_THAL],
\ [s:a_REH, s:a_s_GHAIN, s:a_s_REH],
\ [s:a_ZAIN, s:a_s_GHAIN, s:a_s_ZAIN],
\ [s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL],
\ [s:a_WAW, s:a_s_GHAIN, s:a_s_WAW],
\ [s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_s_ALEF_MAKSURA],
\ [s:a_BEH, s:a_f_GHAIN, s:a_i_BEH],
\ [s:a_TEH, s:a_f_GHAIN, s:a_i_TEH],
\ [s:a_THEH, s:a_f_GHAIN, s:a_i_THEH],
\ [s:a_JEEM, s:a_f_GHAIN, s:a_i_JEEM],
\ [s:a_HAH, s:a_f_GHAIN, s:a_i_HAH],
\ [s:a_KHAH, s:a_f_GHAIN, s:a_i_KHAH],
\ [s:a_SEEN, s:a_f_GHAIN, s:a_i_SEEN],
\ [s:a_SHEEN, s:a_f_GHAIN, s:a_i_SHEEN],
\ [s:a_SAD, s:a_f_GHAIN, s:a_i_SAD],
\ [s:a_DAD, s:a_f_GHAIN, s:a_i_DAD],
\ [s:a_TAH, s:a_f_GHAIN, s:a_i_TAH],
\ [s:a_ZAH, s:a_f_GHAIN, s:a_i_ZAH],
\ [s:a_AIN, s:a_f_GHAIN, s:a_i_AIN],
\ [s:a_GHAIN, s:a_f_GHAIN, s:a_i_GHAIN],
\ [s:a_FEH, s:a_f_GHAIN, s:a_i_FEH],
\ [s:a_QAF, s:a_f_GHAIN, s:a_i_QAF],
\ [s:a_KAF, s:a_f_GHAIN, s:a_i_KAF],
\ [s:a_LAM, s:a_f_GHAIN, s:a_i_LAM],
\ [s:a_MEEM, s:a_f_GHAIN, s:a_i_MEEM],
\ [s:a_NOON, s:a_f_GHAIN, s:a_i_NOON],
\ [s:a_HEH, s:a_f_GHAIN, s:a_i_HEH],
\ [s:a_YEH, s:a_f_GHAIN, s:a_i_YEH],
\ ]
call setline(1, s:a_GHAIN . pair[0] . ' ')
call assert_equal([pair[1] . pair[2] . ' '], ScreenLines(1, 3))
endfor
set arabicshape&
bwipe!
endfunc
func Test_shape_isolated()
new
set arabicshape
" Shaping non-arabic {testchar} non-arabic Tests chg_c_a2s().
" pair[0] = testchar, pair[1] = current-result
for pair in [[s:a_HAMZA, s:a_s_HAMZA],
\ [s:a_ALEF_MADDA, s:a_s_ALEF_MADDA],
\ [s:a_ALEF_HAMZA_ABOVE, s:a_s_ALEF_HAMZA_ABOVE],
\ [s:a_WAW_HAMZA, s:a_s_WAW_HAMZA],
\ [s:a_ALEF_HAMZA_BELOW, s:a_s_ALEF_HAMZA_BELOW],
\ [s:a_YEH_HAMZA, s:a_s_YEH_HAMZA],
\ [s:a_ALEF, s:a_s_ALEF],
\ [s:a_TEH_MARBUTA, s:a_s_TEH_MARBUTA],
\ [s:a_DAL, s:a_s_DAL],
\ [s:a_THAL, s:a_s_THAL],
\ [s:a_REH, s:a_s_REH],
\ [s:a_ZAIN, s:a_s_ZAIN],
\ [s:a_TATWEEL, s:a_TATWEEL],
\ [s:a_WAW, s:a_s_WAW],
\ [s:a_ALEF_MAKSURA, s:a_s_ALEF_MAKSURA],
\ [s:a_BEH, s:a_s_BEH],
\ [s:a_TEH, s:a_s_TEH],
\ [s:a_THEH, s:a_s_THEH],
\ [s:a_JEEM, s:a_s_JEEM],
\ [s:a_HAH, s:a_s_HAH],
\ [s:a_KHAH, s:a_s_KHAH],
\ [s:a_SEEN, s:a_s_SEEN],
\ [s:a_SHEEN, s:a_s_SHEEN],
\ [s:a_SAD, s:a_s_SAD],
\ [s:a_DAD, s:a_s_DAD],
\ [s:a_TAH, s:a_s_TAH],
\ [s:a_ZAH, s:a_s_ZAH],
\ [s:a_AIN, s:a_s_AIN],
\ [s:a_GHAIN, s:a_s_GHAIN],
\ [s:a_FEH, s:a_s_FEH],
\ [s:a_QAF, s:a_s_QAF],
\ [s:a_KAF, s:a_s_KAF],
\ [s:a_LAM, s:a_s_LAM],
\ [s:a_MEEM, s:a_s_MEEM],
\ [s:a_NOON, s:a_s_NOON],
\ [s:a_HEH, s:a_s_HEH],
\ [s:a_YEH, s:a_s_YEH],
\ ]
call setline(1, ' ' . pair[0] . ' ')
call assert_equal([' ' . pair[1] . ' '], ScreenLines(1, 3))
endfor
set arabicshape&
bwipe!
endfunc
func Test_shape_medial()
new
set arabicshape
" Shaping arabic {testchar} arabic Tests chg_c_a2m().
" pair[0] = testchar, pair[1] = next-result, pair[2] = current-result,
" pair[3] = previous-result
for pair in [[s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA, s:a_s_BEH],
\[s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_f_ALEF_MADDA, s:a_i_BEH],
\[s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_ABOVE, s:a_i_BEH],
\[s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_f_WAW_HAMZA, s:a_i_BEH],
\[s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_BELOW, s:a_i_BEH],
\[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_m_YEH_HAMZA, s:a_i_BEH],
\[s:a_ALEF, s:a_s_GHAIN, s:a_f_ALEF, s:a_i_BEH],
\[s:a_BEH, s:a_f_GHAIN, s:a_m_BEH, s:a_i_BEH],
\[s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_f_TEH_MARBUTA, s:a_i_BEH],
\[s:a_TEH, s:a_f_GHAIN, s:a_m_TEH, s:a_i_BEH],
\[s:a_THEH, s:a_f_GHAIN, s:a_m_THEH, s:a_i_BEH],
\[s:a_JEEM, s:a_f_GHAIN, s:a_m_JEEM, s:a_i_BEH],
\[s:a_HAH, s:a_f_GHAIN, s:a_m_HAH, s:a_i_BEH],
\[s:a_KHAH, s:a_f_GHAIN, s:a_m_KHAH, s:a_i_BEH],
\[s:a_DAL, s:a_s_GHAIN, s:a_f_DAL, s:a_i_BEH],
\[s:a_THAL, s:a_s_GHAIN, s:a_f_THAL, s:a_i_BEH],
\[s:a_REH, s:a_s_GHAIN, s:a_f_REH, s:a_i_BEH],
\[s:a_ZAIN, s:a_s_GHAIN, s:a_f_ZAIN, s:a_i_BEH],
\[s:a_SEEN, s:a_f_GHAIN, s:a_m_SEEN, s:a_i_BEH],
\[s:a_SHEEN, s:a_f_GHAIN, s:a_m_SHEEN, s:a_i_BEH],
\[s:a_SAD, s:a_f_GHAIN, s:a_m_SAD, s:a_i_BEH],
\[s:a_DAD, s:a_f_GHAIN, s:a_m_DAD, s:a_i_BEH],
\[s:a_TAH, s:a_f_GHAIN, s:a_m_TAH, s:a_i_BEH],
\[s:a_ZAH, s:a_f_GHAIN, s:a_m_ZAH, s:a_i_BEH],
\[s:a_AIN, s:a_f_GHAIN, s:a_m_AIN, s:a_i_BEH],
\[s:a_GHAIN, s:a_f_GHAIN, s:a_m_GHAIN, s:a_i_BEH],
\[s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL, s:a_i_BEH],
\[s:a_FEH, s:a_f_GHAIN, s:a_m_FEH, s:a_i_BEH],
\[s:a_QAF, s:a_f_GHAIN, s:a_m_QAF, s:a_i_BEH],
\[s:a_KAF, s:a_f_GHAIN, s:a_m_KAF, s:a_i_BEH],
\[s:a_LAM, s:a_f_GHAIN, s:a_m_LAM, s:a_i_BEH],
\[s:a_MEEM, s:a_f_GHAIN, s:a_m_MEEM, s:a_i_BEH],
\[s:a_NOON, s:a_f_GHAIN, s:a_m_NOON, s:a_i_BEH],
\[s:a_HEH, s:a_f_GHAIN, s:a_m_HEH, s:a_i_BEH],
\[s:a_WAW, s:a_s_GHAIN, s:a_f_WAW, s:a_i_BEH],
\[s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_f_ALEF_MAKSURA, s:a_i_BEH],
\[s:a_YEH, s:a_f_GHAIN, s:a_m_YEH, s:a_i_BEH],
\ ]
call setline(1, s:a_GHAIN . pair[0] . s:a_BEH)
call assert_equal([pair[1] . pair[2] . pair[3]], ScreenLines(1, 3))
endfor
set arabicshape&
bwipe!
endfunc

View File

@@ -274,7 +274,6 @@ endfunction
function Test_breakindent16()
" Check that overlong lines are indented correctly.
" TODO: currently it does not fail even when the bug is not fixed.
let s:input=""
call s:test_windows('setl breakindent briopt=min:0 ts=4')
call setline(1, "\t".repeat("1234567890", 10))
@@ -283,16 +282,16 @@ function Test_breakindent16()
redraw!
let lines=s:screen_lines(1,10)
let expect=[
\ " 123456",
\ " 789012",
\ " 345678",
\ " 901234",
\ ]
call s:compare_lines(expect, lines)
let lines=s:screen_lines(4,10)
let expect=[
\ " 901234",
\ " 567890",
\ " 123456",
\ " 7890 ",
\ ]
call s:compare_lines(expect, lines)
call s:close_windows()

View File

@@ -25,6 +25,26 @@ func Test_complete_wildmenu()
set nowildmenu
endfunc
func Test_map_completion()
if !has('cmdline_compl')
return
endif
call feedkeys(":map <unique> <si\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"map <unique> <silent>', getreg(':'))
call feedkeys(":map <script> <un\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"map <script> <unique>', getreg(':'))
call feedkeys(":map <expr> <sc\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"map <expr> <script>', getreg(':'))
call feedkeys(":map <buffer> <e\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"map <buffer> <expr>', getreg(':'))
call feedkeys(":map <nowait> <b\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"map <nowait> <buffer>', getreg(':'))
call feedkeys(":map <special> <no\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"map <special> <nowait>', getreg(':'))
call feedkeys(":map <silent> <sp\<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"map <silent> <special>', getreg(':'))
endfunc
func Test_match_completion()
if !has('cmdline_compl')
return

View File

@@ -272,3 +272,78 @@ func Test_setting_cursor()
call delete('Xtest1')
call delete('Xtest2')
endfunc
func Test_diff_move_to()
new
call setline(1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
diffthis
vnew
call setline(1, [1, '2x', 3, 4, 4, 5, '6x', 7, '8x', 9, '10x'])
diffthis
norm ]c
call assert_equal(2, line('.'))
norm 3]c
call assert_equal(9, line('.'))
norm 10]c
call assert_equal(11, line('.'))
norm [c
call assert_equal(9, line('.'))
norm 2[c
call assert_equal(5, line('.'))
norm 10[c
call assert_equal(2, line('.'))
%bwipe!
endfunc
func Test_diffpatch()
" The patch program on MS-Windows may fail or hang.
if !executable('patch') || !has('unix')
return
endif
new
insert
***************
*** 1,3 ****
1
! 2
3
--- 1,4 ----
1
! 2x
3
+ 4
.
saveas Xpatch
bwipe!
new
call assert_fails('diffpatch Xpatch', 'E816:')
call setline(1, ['1', '2', '3'])
diffpatch Xpatch
call assert_equal(['1', '2x', '3', '4'], getline(1, '$'))
call delete('Xpatch')
bwipe!
endfunc
func Test_diff_too_many_buffers()
for i in range(1, 8)
exe "new Xtest" . i
diffthis
endfor
new Xtest9
call assert_fails('diffthis', 'E96:')
%bwipe!
endfunc
func Test_diff_nomodifiable()
new
call setline(1, [1, 2, 3, 4])
setl nomodifiable
diffthis
vnew
call setline(1, ['1x', 2, 3, 3, 4])
diffthis
call assert_fails('norm dp', 'E793:')
setl nomodifiable
call assert_fails('norm do', 'E21:')
%bwipe!
endfunc

View File

@@ -1,6 +1,6 @@
" Test for folding
function! Test_address_fold()
func! Test_address_fold()
new
call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
\ 'after fold 1', 'after fold 2', 'after fold 3'])
@@ -62,9 +62,9 @@ function! Test_address_fold()
call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
quit!
endfunction
endfunc
function! Test_indent_fold()
func! Test_indent_fold()
new
call setline(1, ['', 'a', ' b', ' c'])
setl fen fdm=indent
@@ -72,9 +72,9 @@ function! Test_indent_fold()
norm! >>
let a=map(range(1,4), 'foldclosed(v:val)')
call assert_equal([-1,-1,-1,-1], a)
endfu
endfunc
function! Test_indent_fold()
func! Test_indent_fold()
new
call setline(1, ['', 'a', ' b', ' c'])
setl fen fdm=indent
@@ -83,9 +83,9 @@ function! Test_indent_fold()
let a=map(range(1,4), 'foldclosed(v:val)')
call assert_equal([-1,-1,-1,-1], a)
bw!
endfu
endfunc
function! Test_indent_fold2()
func! Test_indent_fold2()
new
call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
setl fen fdm=marker
@@ -94,4 +94,21 @@ function! Test_indent_fold2()
let a=map(range(1,5), 'foldclosed(v:val)')
call assert_equal([-1,-1,-1,4,4], a)
bw!
endfu
endfunc
func Test_manual_fold_with_filter()
if !executable('cat')
return
endif
new
call setline(1, range(1, 20))
4,$fold
%foldopen
10,$fold
%foldopen
" This filter command should not have an effect
1,8! cat
call feedkeys('5ggzdzMGdd', 'xt')
call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
bwipe!
endfunc

View File

@@ -466,3 +466,10 @@ func Test_getbufvar()
set fileformats&
endfunc
func Test_balloon_show()
if has('balloon_eval')
" This won't do anything but must not crash either.
call balloon_show('hi!')
endif
endfunc

View File

@@ -72,6 +72,51 @@ func Test_getfontname_without_arg()
endif
endfunc
func Test_quoteplus()
let skipped = ''
if !g:x11_based_gui
let skipped = g:not_supported . 'quoteplus'
else
let quoteplus_saved = @+
let test_call = 'Can you hear me?'
let test_response = 'Yes, I can.'
let vim_exe = exepath(v:progpath)
let testee = 'VIMRUNTIME=' . $VIMRUNTIME . '; export VIMRUNTIME;'
\ . vim_exe
\ . ' -u NONE -U NONE --noplugin --not-a-term -c ''%s'''
" Ignore the "failed to create input context" error.
let cmd = 'call test_ignore_error("E285") | '
\ . 'gui -f | '
\ . 'call feedkeys("'
\ . '\"+p'
\ . ':s/' . test_call . '/' . test_response . '/\<CR>'
\ . '\"+yis'
\ . ':q!\<CR>", "tx")'
let run_vimtest = printf(testee, cmd)
" Set the quoteplus register to test_call, and another gvim will launched.
" Then, it first tries to paste the content of its own quotedplus register
" onto it. Second, it tries to substitute test_responce for the pasted
" sentence. If the sentence is identical to test_call, the substitution
" should succeed. Third, it tries to yank the result of the substitution
" to its own quoteplus register, and last it quits. When system()
" returns, the content of the quoteplus register should be identical to
" test_response if those quoteplus registers are synchronized properly
" with/through the X11 clipboard.
let @+ = test_call
call system(run_vimtest)
call assert_equal(test_response, @+)
let @+ = quoteplus_saved
endif
if !empty(skipped)
throw skipped
endif
endfunc
func Test_set_guifont()
let skipped = ''

View File

@@ -15,7 +15,10 @@ func TearDown()
call GUITearDownCommon()
endfunc
" Make sure that the tests will be done with the GUI activated.
" Ignore the "failed to create input context" error.
call test_ignore_error('E285')
" Start the GUI now, in the foreground.
gui -f
func Test_set_guiheadroom()

View File

@@ -217,3 +217,19 @@ func Test_list_with_listchars()
call s:compare_lines(expect, lines)
call s:close_windows()
endfunc
func Test_list_with_tab_and_skipping_first_chars()
call s:test_windows('setl list listchars=tab:>- ts=70 nowrap')
call setline(1, ["iiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa"])
call cursor(4,64)
norm! 2zl
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
\ "---------------aaaaa",
\ "---------------aaaaa",
\ "---------------aaaaa",
\ "iiiiiiiii>-----aaaaa",
\ ]
call s:compare_lines(expect, lines)
call s:close_windows()
endfu

View File

@@ -193,3 +193,64 @@ func Test_multibyte_sign_and_colorcolumn()
call s:compare_lines(expect, lines)
call s:close_windows()
endfunc
func Test_illegal_byte_and_breakat()
call s:test_windows("setl sbr= brk+=<")
vert resize 18
call setline(1, repeat("\x80", 6))
redraw!
let lines = s:screen_lines([1, 2], winwidth(0))
let expect = [
\ "<80><80><80><80><8",
\ "0><80> ",
\ ]
call s:compare_lines(expect, lines)
call s:close_windows('setl brk&vim')
endfunc
func Test_multibyte_wrap_and_breakat()
call s:test_windows("setl sbr= brk+=>")
call setline(1, repeat('a', 17) . repeat('あ', 2))
redraw!
let lines = s:screen_lines([1, 2], winwidth(0))
let expect = [
\ "aaaaaaaaaaaaaaaaaあ>",
\ "あ ",
\ ]
call s:compare_lines(expect, lines)
call s:close_windows('setl brk&vim')
endfunc
func Test_chinese_char_on_wrap_column()
call s:test_windows("setl nolbr wrap sbr=")
syntax off
call setline(1, [
\ 'aaaaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'aaaaaaaaaaaaaaaaa中'.
\ 'hello'])
call cursor(1,1)
norm! $
redraw!
let expect=[
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中aaaaaaaaaaaaaaaaa>',
\ '中hello ']
let lines = s:screen_lines([1, 10], winwidth(0))
call s:compare_lines(expect, lines)
call s:close_windows()
endfu

View File

@@ -128,6 +128,14 @@ func XlistTests(cchar)
let l = split(result, "\n")
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
" Test for '+'
redir => result
Xlist! +2
redir END
let l = split(result, "\n")
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
endfunc
func Test_clist()
@@ -925,6 +933,11 @@ func Test_efm2()
\ "(67,3) warning: 's' already defined"
\]
set efm=%+P[%f],(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%-Q
" To exercise the push/pop file functionality in quickfix, the test files
" need to be created.
call writefile(['Line1'], 'Xtestfile1')
call writefile(['Line2'], 'Xtestfile2')
call writefile(['Line3'], 'Xtestfile3')
cexpr ""
for l in lines
caddexpr l
@@ -935,6 +948,9 @@ func Test_efm2()
call assert_equal(2, l[2].col)
call assert_equal('w', l[2].type)
call assert_equal('e', l[3].type)
call delete('Xtestfile1')
call delete('Xtestfile2')
call delete('Xtestfile3')
" Tests for %E, %C and %Z format specifiers
let lines = ["Error 275",
@@ -1369,11 +1385,25 @@ func Test_switchbuf()
call assert_equal(2, winnr('$'))
call assert_equal(1, bufwinnr('Xqftestfile3'))
" If only quickfix window is open in the current tabpage, jumping to an
" entry with 'switchubf' set to 'usetab' should search in other tabpages.
enew | only
set switchbuf=usetab
tabedit Xqftestfile1
tabedit Xqftestfile2
tabedit Xqftestfile3
tabfirst
copen | only
clast
call assert_equal(4, tabpagenr())
tabfirst | tabonly | enew | only
call delete('Xqftestfile1')
call delete('Xqftestfile2')
call delete('Xqftestfile3')
set switchbuf&vim
enew | only
endfunc
func Xadjust_qflnum(cchar)
@@ -1691,3 +1721,56 @@ func Test_dirstack_cleanup()
caddbuffer
let &efm = save_efm
endfunc
" Tests for jumping to entries from the location list window and quickfix
" window
func Test_cwindow_jump()
set efm=%f%%%l%%%m
lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
lopen | only
lfirst
call assert_true(winnr('$') == 2)
call assert_true(winnr() == 1)
" Location list for the new window should be set
call assert_true(getloclist(0)[2].text == 'Line 30')
" Open a scratch buffer
" Open a new window and create a location list
" Open the location list window and close the other window
" Jump to an entry.
" Should create a new window and jump to the entry. The scrtach buffer
" should not be used.
enew | only
set buftype=nofile
below new
lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
lopen
2wincmd c
lnext
call assert_true(winnr('$') == 3)
call assert_true(winnr() == 2)
" Open two windows with two different location lists
" Open the location list window and close the previous window
" Jump to an entry in the location list window
" Should open the file in the first window and not set the location list.
enew | only
lgetexpr ["F1%5%Line 5"]
below new
lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
lopen
2wincmd c
lnext
call assert_true(winnr() == 1)
call assert_true(getloclist(0)[0].text == 'Line 5')
enew | only
cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
copen
cnext
call assert_true(winnr('$') == 2)
call assert_true(winnr() == 1)
enew | only
set efm&vim
endfunc

View File

@@ -294,3 +294,10 @@ func Test_searchpair()
q!
endfunc
func Test_searchc()
" These commands used to cause memory overflow in searchc().
new
norm ixx
exe "norm 0t\u93cf"
bw!
endfunc

View File

@@ -183,3 +183,17 @@ func Test_read_stdin()
endif
call delete('Xtestout')
endfunc
func Test_progpath()
" Tests normally run with "./vim" or "../vim", these must have been expanded
" to a full path.
if has('unix')
call assert_equal('/', v:progpath[0])
elseif has('win32')
call assert_equal(':', v:progpath[1])
call assert_match('[/\\]', v:progpath[2])
endif
" Only expect "vim" to appear in v:progname.
call assert_match('vim\c', v:progname)
endfunc

View File

@@ -35,10 +35,34 @@ func Test_static_tagjump()
tag one
call assert_equal(2, line('.'))
bwipe!
set tags&
call delete('Xtags')
call delete('Xfile1')
endfunc
func Test_duplicate_tagjump()
set tags=Xtags
call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
\ "thesame\tXfile1\t1;\"\td\tfile:",
\ "thesame\tXfile1\t2;\"\td\tfile:",
\ "thesame\tXfile1\t3;\"\td\tfile:",
\ ],
\ 'Xtags')
new Xfile1
call setline(1, ['thesame one', 'thesame two', 'thesame three'])
write
tag thesame
call assert_equal(1, line('.'))
tnext
call assert_equal(2, line('.'))
tnext
call assert_equal(3, line('.'))
bwipe!
set tags&
call delete('Xtags')
call delete('Xfile1')
endfunc
" Tests for [ CTRL-I and CTRL-W CTRL-I commands

View File

@@ -1385,7 +1385,7 @@ unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name)
{
int i;
u_entry_T *uep;
char_u **array;
char_u **array = NULL;
char_u *line;
int line_len;
@@ -1402,7 +1402,8 @@ unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name)
uep->ue_size = undo_read_4c(bi);
if (uep->ue_size > 0)
{
array = (char_u **)U_ALLOC_LINE(sizeof(char_u *) * uep->ue_size);
if (uep->ue_size < LONG_MAX / (int)sizeof(char_u *))
array = (char_u **)U_ALLOC_LINE(sizeof(char_u *) * uep->ue_size);
if (array == NULL)
{
*error = TRUE;
@@ -1410,8 +1411,6 @@ unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name)
}
vim_memset(array, 0, sizeof(char_u *) * uep->ue_size);
}
else
array = NULL;
uep->ue_array = array;
for (i = 0; i < uep->ue_size; ++i)
@@ -1787,7 +1786,7 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
linenr_T line_lnum;
colnr_T line_colnr;
linenr_T line_count;
int num_head = 0;
long num_head = 0;
long old_header_seq, new_header_seq, cur_header_seq;
long seq_last, seq_cur;
long last_save_nr = 0;
@@ -1974,7 +1973,8 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
* When there are no headers uhp_table is NULL. */
if (num_head > 0)
{
uhp_table = (u_header_T **)U_ALLOC_LINE(
if (num_head < LONG_MAX / (long)sizeof(u_header_T *))
uhp_table = (u_header_T **)U_ALLOC_LINE(
num_head * sizeof(u_header_T *));
if (uhp_table == NULL)
goto error;

View File

@@ -764,6 +764,68 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
405,
/**/
404,
/**/
403,
/**/
402,
/**/
401,
/**/
400,
/**/
399,
/**/
398,
/**/
397,
/**/
396,
/**/
395,
/**/
394,
/**/
393,
/**/
392,
/**/
391,
/**/
390,
/**/
389,
/**/
388,
/**/
387,
/**/
386,
/**/
385,
/**/
384,
/**/
383,
/**/
382,
/**/
381,
/**/
380,
/**/
379,
/**/
378,
/**/
377,
/**/
376,
/**/
375,
/**/
374,
/**/