Compare commits

...

8 Commits

Author SHA1 Message Date
Bram Moolenaar
97a80e440a patch 8.0.1015: missing update to terminal test
Problem:    Missing update to terminal test.
Solution:   Add the changes to the test.
2017-08-30 13:31:49 +02:00
Bram Moolenaar
b47a2597e6 patch 8.0.1014: old compiler doesn't know uint32_t
Problem:    Old compiler doesn't know uint32_t. Warning for using NULL instead
            of NUL.
Solution:   Use UINT32_T.  Use NUL instead of NULL.
2017-08-30 13:22:28 +02:00
Bram Moolenaar
e561a7e2fa patch 8.0.1013: terminal window behaves different from a buffer with changes
Problem:    A terminal window with a running job behaves different from a
            window containing a changed buffer.
Solution:   Do not set 'bufhidden' to "hide".  Fix that a buffer where a
            terminal used to run is listed as "[Scratch]".
2017-08-29 22:44:59 +02:00
Bram Moolenaar
48340b62e8 patch 8.0.1012: MS-Windows: problem with $HOME when is was set internally
Problem:    MS-Windows: Problem with $HOME when is was set internally.
Solution:   Only use the $HOME default internally. (Yasuhiro Matsumoto, closes
            #2013)
2017-08-29 22:08:53 +02:00
Bram Moolenaar
97f65fafdb patch 8.0.1011: terminal test fails with Athena and Motif
Problem:    Terminal test fails with Athena and Motif.
Solution:   Ignore the error for the input context. (Kazunobu Kuriyama)
2017-08-29 20:42:07 +02:00
Bram Moolenaar
3c37a8e660 patch 8.0.1010: build failure without termresponse feature
Problem:    Build failure without termresponse feature.
Solution:   Add #ifdef.
2017-08-28 23:00:55 +02:00
Bram Moolenaar
4db2554954 patch 8.0.1009: Xterm cursor blinking status may be inverted
Problem:    Xterm cursor blinking status may be inverted.
Solution:   Use another request to get the blink status and compare with the
            cursor style report
2017-08-28 22:43:05 +02:00
Bram Moolenaar
1dccf6351d patch 8.0.1008: slow updating of terminal window in Motif
Problem:    Slow updating of terminal window in Motif.
Solution:   Add a timeout to the wait-for-character loop.
2017-08-27 17:38:27 +02:00
16 changed files with 354 additions and 109 deletions

View File

@@ -1,4 +1,4 @@
*terminal.txt* For Vim version 8.0. Last change: 2017 Aug 26
*terminal.txt* For Vim version 8.0. Last change: 2017 Aug 29
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -140,11 +140,17 @@ Syntax ~
When the buffer associated with the terminal is unloaded or wiped out the job
is killed, similar to calling `job_stop(job, "kill")`
By default the 'bufhidden' option of the buffer will be set to "hide".
So long as the job is running: If the window is closed the buffer becomes
hidden. The command will not be stopped. The `:buffer` command can be used
to turn the current window into a terminal window. If there are unsaved
changes this fails, use ! to force, as usual.
So long as the job is running the window behaves like it contains a modified
buffer. Trying to close the window with `CTRL-W :close` or `CTRL-W :hide`
fails, unless "!" is added, in which case the job is ended. The text in the
window is lost. The buffer still exists, but getting it in a window with
`:buffer` will show an
empty buffer.
You can use `CTRL-W :hide` to close the terminal window and make the buffer
hidden, the job keeps running. The `:buffer` command can be used to turn the
current window into a terminal window. If there are unsaved changes this
fails, use ! to force, as usual.
To have a background job run without a window, and open the window when it's
done, use options like this: >

View File

@@ -2278,6 +2278,7 @@ test_arglist \
test_visual \
test_window_cmd \
test_window_id \
test_windows_home \
test_writefile \
test_alot_latin \
test_alot_utf8 \

View File

@@ -5825,8 +5825,8 @@ buf_spname(buf_T *buf)
if (buf->b_term != NULL)
return term_get_status_text(buf->b_term);
#endif
if (buf->b_sfname != NULL)
return buf->b_sfname;
if (buf->b_fname != NULL)
return buf->b_fname;
return (char_u *)_("[Scratch]");
}

View File

@@ -136,20 +136,11 @@ static guicolor_T prev_sp_color = INVALCOLOR;
static XButtonPressedEvent last_mouse_event;
#endif
static void gui_x11_timer_cb(XtPointer timed_out, XtIntervalId *interval_id);
static void gui_x11_visibility_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum);
static void gui_x11_expose_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum);
static void gui_x11_resize_window_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum);
static void gui_x11_focus_change_cb(Widget w, XtPointer data, XEvent *event, Boolean *dum);
static void gui_x11_enter_cb(Widget w, XtPointer data, XEvent *event, Boolean *dum);
static void gui_x11_leave_cb(Widget w, XtPointer data, XEvent *event, Boolean *dum);
static void gui_x11_mouse_cb(Widget w, XtPointer data, XEvent *event, Boolean *dum);
static void gui_x11_check_copy_area(void);
#ifdef FEAT_CLIENTSERVER
static void gui_x11_send_event_handler(Widget, XtPointer, XEvent *, Boolean *);
#endif
static void gui_x11_wm_protocol_handler(Widget, XtPointer, XEvent *, Boolean *);
static void gui_x11_blink_cb(XtPointer timed_out, XtIntervalId *interval_id);
static Cursor gui_x11_create_blank_mouse(void);
static void draw_curl(int row, int col, int cells);
@@ -574,6 +565,25 @@ gui_x11_timer_cb(
*((int *)timed_out) = TRUE;
}
#ifdef FEAT_JOB_CHANNEL
static void
channel_poll_cb(
XtPointer client_data,
XtIntervalId *interval_id UNUSED)
{
XtIntervalId *channel_timer = (XtIntervalId *)client_data;
/* Using an event handler for a channel that may be disconnected does
* not work, it hangs. Instead poll for messages. */
channel_handle_events(TRUE);
parse_queued_messages();
/* repeat */
*channel_timer = XtAppAddTimeOut(app_context, (long_u)20,
channel_poll_cb, client_data);
}
#endif
static void
gui_x11_visibility_cb(
Widget w UNUSED,
@@ -2698,12 +2708,22 @@ gui_mch_wait_for_chars(long wtime)
static int timed_out;
XtIntervalId timer = (XtIntervalId)0;
XtInputMask desired;
#ifdef FEAT_JOB_CHANNEL
XtIntervalId channel_timer = (XtIntervalId)0;
#endif
timed_out = FALSE;
if (wtime > 0)
timer = XtAppAddTimeOut(app_context, (long_u)wtime, gui_x11_timer_cb,
&timed_out);
#ifdef FEAT_JOB_CHANNEL
/* If there is a channel with the keep_open flag we need to poll for input
* on them. */
if (channel_any_keep_open())
channel_timer = XtAppAddTimeOut(app_context, (long_u)20,
channel_poll_cb, (XtPointer)&channel_timer);
#endif
focus = gui.in_focus;
#ifdef ALT_X_INPUT
@@ -2755,6 +2775,10 @@ gui_mch_wait_for_chars(long wtime)
if (timer != (XtIntervalId)0 && !timed_out)
XtRemoveTimeOut(timer);
#ifdef FEAT_JOB_CHANNEL
if (channel_timer != (XtIntervalId)0)
XtRemoveTimeOut(channel_timer);
#endif
return retval;
}
@@ -3087,25 +3111,6 @@ gui_mch_stop_blink(void)
blink_state = BLINK_NONE;
}
/*
* Start the cursor blinking. If it was already blinking, this restarts the
* waiting time and shows the cursor.
*/
void
gui_mch_start_blink(void)
{
if (blink_timer != (XtIntervalId)0)
XtRemoveTimeOut(blink_timer);
/* Only switch blinking on if none of the times is zero */
if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
{
blink_timer = XtAppAddTimeOut(app_context, blink_waittime,
gui_x11_blink_cb, NULL);
blink_state = BLINK_ON;
gui_update_cursor(TRUE, FALSE);
}
}
static void
gui_x11_blink_cb(
XtPointer timed_out UNUSED,
@@ -3127,6 +3132,25 @@ gui_x11_blink_cb(
}
}
/*
* Start the cursor blinking. If it was already blinking, this restarts the
* waiting time and shows the cursor.
*/
void
gui_mch_start_blink(void)
{
if (blink_timer != (XtIntervalId)0)
XtRemoveTimeOut(blink_timer);
/* Only switch blinking on if none of the times is zero */
if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
{
blink_timer = XtAppAddTimeOut(app_context, blink_waittime,
gui_x11_blink_cb, NULL);
blink_state = BLINK_ON;
gui_update_cursor(TRUE, FALSE);
}
}
/*
* Return the RGB value of a pixel as a long.
*/

View File

@@ -1400,7 +1400,7 @@ static struct interval ambiguous[] =
* utf_char2cells() with different argument type for libvterm.
*/
int
utf_uint2cells(uint32_t c)
utf_uint2cells(UINT32_T c)
{
return utf_char2cells((int)c);
}
@@ -2312,7 +2312,7 @@ utf_char2bytes(int c, char_u *buf)
* utf_iscomposing() with different argument type for libvterm.
*/
int
utf_iscomposing_uint(uint32_t c)
utf_iscomposing_uint(UINT32_T c)
{
return utf_iscomposing((int)c);
}

View File

@@ -3750,10 +3750,33 @@ init_homedir(void)
var = mch_getenv((char_u *)"HOME");
#endif
if (var != NULL && *var == NUL) /* empty is same as not set */
var = NULL;
#ifdef WIN3264
/*
* Typically, $HOME is not defined on Windows, unless the user has
* specifically defined it for Vim's sake. However, on Windows NT
* platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
* each user. Try constructing $HOME from these.
*/
if (var == NULL || *var == NUL)
{
char_u *homedrive, *homepath;
homedrive = mch_getenv((char_u *)"HOMEDRIVE");
homepath = mch_getenv((char_u *)"HOMEPATH");
if (homepath == NULL || *homepath == NUL)
homepath = (char_u *)"\\";
if (homedrive != NULL
&& STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL)
{
sprintf((char *)NameBuff, "%s%s", homedrive, homepath);
if (NameBuff[0] != NUL)
var = NameBuff;
}
}
if (var == NULL)
var = mch_getenv((char_u *)"USERPROFILE");
/*
* Weird but true: $HOME may contain an indirect reference to another
* variable, esp. "%USERPROFILE%". Happens when $USERPROFILE isn't set
@@ -3774,40 +3797,14 @@ init_homedir(void)
{
vim_snprintf((char *)NameBuff, MAXPATHL, "%s%s", exp, p + 1);
var = NameBuff;
/* Also set $HOME, it's needed for _viminfo. */
vim_setenv((char_u *)"HOME", NameBuff);
}
}
}
/*
* Typically, $HOME is not defined on Windows, unless the user has
* specifically defined it for Vim's sake. However, on Windows NT
* platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
* each user. Try constructing $HOME from these.
*/
if (var == NULL)
{
char_u *homedrive, *homepath;
if (var != NULL && *var == NUL) /* empty is same as not set */
var = NULL;
homedrive = mch_getenv((char_u *)"HOMEDRIVE");
homepath = mch_getenv((char_u *)"HOMEPATH");
if (homepath == NULL || *homepath == NUL)
homepath = (char_u *)"\\";
if (homedrive != NULL
&& STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL)
{
sprintf((char *)NameBuff, "%s%s", homedrive, homepath);
if (NameBuff[0] != NUL)
{
var = NameBuff;
/* Also set $HOME, it's needed for _viminfo. */
vim_setenv((char_u *)"HOME", NameBuff);
}
}
}
# if defined(FEAT_MBYTE)
# ifdef FEAT_MBYTE
if (enc_utf8 && var != NULL)
{
int len;
@@ -3823,9 +3820,7 @@ init_homedir(void)
}
}
# endif
#endif
#if defined(MSWIN)
/*
* Default home dir is C:/
* Best assumption we can make in such a situation.
@@ -3833,6 +3828,7 @@ init_homedir(void)
if (var == NULL)
var = (char_u *)"C:/";
#endif
if (var != NULL)
{
#ifdef UNIX
@@ -4661,6 +4657,10 @@ home_replace(
homedir_env_orig = homedir_env = mch_getenv((char_u *)"SYS$LOGIN");
#else
homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME");
#endif
#ifdef WIN3264
if (homedir_env == NULL)
homedir_env_orig = homedir_env = mch_getenv((char_u *)"USERPROFILE");
#endif
/* Empty is the same as not set. */
if (homedir_env != NULL && *homedir_env == NUL)

View File

@@ -3194,6 +3194,7 @@ static struct vimoption options[] =
p_term("t_nd", T_ND)
p_term("t_op", T_OP)
p_term("t_RB", T_RBG)
p_term("t_RC", T_CRC)
p_term("t_RI", T_CRI)
p_term("t_RS", T_CRS)
p_term("t_RV", T_CRV)

View File

@@ -10,7 +10,7 @@ int latin_char2len(int c);
int latin_char2bytes(int c, char_u *buf);
int latin_ptr2len(char_u *p);
int latin_ptr2len_len(char_u *p, int size);
int utf_uint2cells(uint32_t c);
int utf_uint2cells(UINT32_T c);
int utf_char2cells(int c);
int latin_ptr2cells(char_u *p);
int utf_ptr2cells(char_u *p);
@@ -38,7 +38,7 @@ int utfc_ptr2len(char_u *p);
int utfc_ptr2len_len(char_u *p, int size);
int utf_char2len(int c);
int utf_char2bytes(int c, char_u *buf);
int utf_iscomposing_uint(uint32_t c);
int utf_iscomposing_uint(UINT32_T c);
int utf_iscomposing(int c);
int utf_printable(int c);
int utf_class(int c);

View File

@@ -53,6 +53,7 @@ void cursor_on(void);
void cursor_off(void);
void term_cursor_mode(int forced);
void term_cursor_color(char_u *color);
int blink_state_is_inverted(void);
void term_cursor_shape(int shape, int blink);
void scroll_region_set(win_T *wp, int off);
void scroll_region_reset(void);

View File

@@ -128,8 +128,11 @@ static int u7_status = STATUS_GET;
/* Request background color report: */
static int rbg_status = STATUS_GET;
/* Request cursor mode report: */
static int rcm_status = STATUS_GET;
/* Request cursor blinking mode report: */
static int rbm_status = STATUS_GET;
/* Request cursor style report: */
static int rcs_status = STATUS_GET;
# endif
/*
@@ -163,9 +166,14 @@ static int detected_8bit = FALSE; /* detected 8-bit terminal */
#ifdef FEAT_TERMRESPONSE
/* When the cursor shape was detected these values are used:
* 1: block, 2: underline, 3: vertical bar
* initial_cursor_blink is only valid when initial_cursor_shape is not zero. */
* 1: block, 2: underline, 3: vertical bar */
static int initial_cursor_shape = 0;
/* The blink flag from the style response may be inverted from the actual
* blinking state, xterm XORs the flags. */
static int initial_cursor_shape_blink = FALSE;
/* The blink flag from the blinking-cursor mode response */
static int initial_cursor_blink = FALSE;
#endif
@@ -835,6 +843,7 @@ static struct builtin_term builtin_termcaps[] =
# else
{(int)KS_CSH, IF_EB("\033[%d q", ESC_STR "[%d q")},
# endif
{(int)KS_CRC, IF_EB("\033[?12$p", ESC_STR "[?12$p")},
{(int)KS_CRS, IF_EB("\033P$q q\033\\", ESC_STR "P$q q" ESC_STR "\\")},
# ifdef TERMINFO
{(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
@@ -3316,7 +3325,8 @@ settmode(int tmode)
if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
|| u7_status == STATUS_SENT
|| rbg_status == STATUS_SENT
|| rcm_status == STATUS_SENT))
|| rbm_status == STATUS_SENT
|| rcs_status == STATUS_SENT))
(void)vpeekc_nomap();
check_for_codes_from_term();
}
@@ -3386,7 +3396,8 @@ stoptermcap(void)
if (crv_status == STATUS_SENT
|| u7_status == STATUS_SENT
|| rbg_status == STATUS_SENT
|| rcm_status == STATUS_SENT)
|| rbm_status == STATUS_SENT
|| rcs_status == STATUS_SENT)
{
# ifdef UNIX
/* Give the terminal a chance to respond. */
@@ -3500,6 +3511,8 @@ may_req_ambiguous_char_width(void)
void
may_req_bg_color(void)
{
int did_one = FALSE;
if (can_get_termresponse() && starting == 0)
{
/* Only request background if t_RB is set and 'background' wasn't
@@ -3511,7 +3524,20 @@ may_req_bg_color(void)
LOG_TR("Sending BG request");
out_str(T_RBG);
rbg_status = STATUS_SENT;
did_one = TRUE;
}
/* Only request cursor blinking mode if t_RC is set. */
if (rbm_status == STATUS_GET && *T_CRC != NUL)
{
LOG_TR("Sending BC request");
out_str(T_CRC);
rbm_status = STATUS_SENT;
did_one = TRUE;
}
if (did_one)
{
/* check for the characters now, otherwise they might be eaten by
* get_keystroke() */
out_flush();
@@ -3751,6 +3777,17 @@ term_cursor_color(char_u *color)
}
# endif
int
blink_state_is_inverted()
{
#ifdef FEAT_TERMRESPONSE
return rbm_status == STATUS_GOT && rcs_status == STATUS_GOT
&& initial_cursor_blink != initial_cursor_shape_blink;
#else
return FALSE;
#endif
}
/*
* "shape": 1 = block, 2 = underline, 3 = vertical bar
*/
@@ -3762,16 +3799,26 @@ term_cursor_shape(int shape, int blink)
OUT_STR(tgoto((char *)T_CSH, 0, shape * 2 - blink));
out_flush();
}
/* When t_SH is not set try setting just the blink state. */
else if (blink && *T_VS != NUL)
else
{
out_str(T_VS);
out_flush();
}
else if (!blink && *T_CVS != NUL)
{
out_str(T_CVS);
out_flush();
int do_blink = blink;
/* t_SH is empty: try setting just the blink state.
* The blink flags are XORed together, if the initial blinking from
* style and shape differs, we need to invert the flag here. */
if (blink_state_is_inverted())
do_blink = !blink;
if (do_blink && *T_VS != NUL)
{
out_str(T_VS);
out_flush();
}
else if (!do_blink && *T_CVS != NUL)
{
out_str(T_CVS);
out_flush();
}
}
}
#endif
@@ -4533,7 +4580,7 @@ check_termcode(
/* Only request the cursor style if t_SH and t_RS are
* set. Not for Terminal.app, it can't handle t_RS, it
* echoes the characters to the screen. */
if (rcm_status == STATUS_GET
if (rcs_status == STATUS_GET
# ifdef MACOS
&& !is_terminal_app
# endif
@@ -4542,7 +4589,7 @@ check_termcode(
{
LOG_TR("Sending cursor style request");
out_str(T_CRS);
rcm_status = STATUS_SENT;
rcs_status = STATUS_SENT;
out_flush();
}
}
@@ -4558,6 +4605,29 @@ check_termcode(
slen = i + 1;
}
/* Check blinking cursor from xterm:
* {lead}?12;1$y set
* {lead}?12;2$y not set
*
* {lead} can be <Esc>[ or CSI
*/
else if (rbm_status == STATUS_SENT
&& tp[(j = 1 + (tp[0] == ESC))] == '?'
&& i == j + 6
&& tp[j + 1] == '1'
&& tp[j + 2] == '2'
&& tp[j + 3] == ';'
&& tp[i - 1] == '$'
&& tp[i] == 'y')
{
initial_cursor_blink = (tp[j + 4] == '1');
rbm_status = STATUS_GOT;
LOG_TR("Received cursor blinking mode response");
key_name[0] = (int)KS_EXTRA;
key_name[1] = (int)KE_IGNORE;
slen = i + 1;
}
/*
* Check for a window position response from the terminal:
* {lead}3;{x}:{y}t
@@ -4668,7 +4738,7 @@ check_termcode(
*
* Consume any code that starts with "{lead}.+r" or "{lead}.$r".
*/
else if ((check_for_codes || rcm_status == STATUS_SENT)
else if ((check_for_codes || rcs_status == STATUS_SENT)
&& ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
|| tp[0] == DCS))
{
@@ -4710,8 +4780,9 @@ check_termcode(
initial_cursor_shape = (number + 1) / 2;
/* The blink flag is actually inverted, compared to
* the value set with T_SH. */
initial_cursor_blink = (number & 1) ? FALSE : TRUE;
rcm_status = STATUS_GOT;
initial_cursor_shape_blink =
(number & 1) ? FALSE : TRUE;
rcs_status = STATUS_GOT;
LOG_TR("Received cursor shape response");
key_name[0] = (int)KS_EXTRA;

View File

@@ -42,7 +42,8 @@ enum SpecialKey
KS_VS, /* cursor very visible (blink) */
KS_CVS, /* cursor normally visible (no blink) */
KS_CSH, /* cursor shape */
KS_CRS, /* request cursor shape */
KS_CRC, /* request cursor blinking */
KS_CRS, /* request cursor style */
KS_ME, /* normal mode */
KS_MR, /* reverse mode */
KS_MD, /* bold mode */
@@ -135,7 +136,8 @@ extern char_u *(term_strings[]); /* current terminal strings */
#define T_VS (TERM_STR(KS_VS)) /* cursor very visible (blink) */
#define T_CVS (TERM_STR(KS_CVS)) /* cursor normally visible (no blink) */
#define T_CSH (TERM_STR(KS_CSH)) /* cursor shape */
#define T_CRS (TERM_STR(KS_CRS)) /* request cursor shape */
#define T_CRC (TERM_STR(KS_CRC)) /* request cursor blinking */
#define T_CRS (TERM_STR(KS_CRS)) /* request cursor style */
#define T_ME (TERM_STR(KS_ME)) /* normal mode */
#define T_MR (TERM_STR(KS_MR)) /* reverse mode */
#define T_MD (TERM_STR(KS_MD)) /* bold mode */

View File

@@ -39,16 +39,12 @@
*
* TODO:
* - ":term NONE" does not work in MS-Windows.
* - better check for blinking - reply from Thomas Dickey Aug 22
* - test for writing lines to terminal job does not work on MS-Windows
* - implement term_setsize()
* - add test for giving error for invalid 'termsize' value.
* - support minimal size when 'termsize' is "rows*cols".
* - support minimal size when 'termsize' is empty?
* - do not set bufhidden to "hide"? works like a buffer with changes.
* document that CTRL-W :hide can be used.
* - GUI: when using tabs, focus in terminal, click on tab does not work.
* - When $HOME was set by Vim (MS-Windows), do not pass it to the job.
* - GUI: when 'confirm' is set and trying to exit Vim, dialog offers to save
* changes to "!shell".
* (justrajdeep, 2017 Aug 22)
@@ -400,10 +396,6 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
* the job finished. */
curbuf->b_p_ma = FALSE;
/* Set 'bufhidden' to "hide": allow closing the window. */
set_string_option_direct((char_u *)"bufhidden", -1,
(char_u *)"hide", OPT_FREE|OPT_LOCAL, 0);
set_term_and_win_size(term);
setup_job_options(opt, term->tl_rows, term->tl_cols);
@@ -2482,7 +2474,8 @@ f_term_getcursor(typval_T *argvars, typval_T *rettv)
if (d != NULL)
{
dict_add_nr_str(d, "visible", term->tl_cursor_visible, NULL);
dict_add_nr_str(d, "blink", term->tl_cursor_blink, NULL);
dict_add_nr_str(d, "blink", blink_state_is_inverted()
? !term->tl_cursor_blink : term->tl_cursor_blink, NULL);
dict_add_nr_str(d, "shape", term->tl_cursor_shape, NULL);
dict_add_nr_str(d, "color", 0L, term->tl_cursor_color == NULL
? (char_u *)"" : term->tl_cursor_color);

View File

@@ -205,7 +205,8 @@ NEW_TESTS = test_arabic.res \
test_writefile.res \
test_alot_latin.res \
test_alot_utf8.res \
test_alot.res
test_alot.res \
test_windows_home.res
# Explicit dependencies.

View File

@@ -84,6 +84,7 @@ endfunc
func Test_terminal_hide_buffer()
let buf = Run_shell_in_terminal({})
setlocal bufhidden=hide
quit
for nr in range(1, winnr('$'))
call assert_notequal(winbufnr(nr), buf)
@@ -356,13 +357,13 @@ func Test_finish_open_close()
call assert_equal(1, winnr('$'))
exe 'terminal ++open ' . cmd
close
close!
call WaitFor("winnr('$') == 2", waittime)
call assert_equal(2, winnr('$'))
bwipe
call term_start(cmd, {'term_finish': 'open'})
close
close!
call WaitFor("winnr('$') == 2", waittime)
call assert_equal(2, winnr('$'))
bwipe
@@ -385,7 +386,7 @@ func Test_finish_open_close()
call assert_fails("call term_start(cmd, {'term_opencmd': 'split % and %d'})", 'E475:')
call term_start(cmd, {'term_finish': 'open', 'term_opencmd': '4split | buffer %d'})
close
close!
call WaitFor("winnr('$') == 2", waittime)
call assert_equal(2, winnr('$'))
call assert_equal(4, winheight(0))
@@ -429,6 +430,10 @@ func Test_zz_terminal_in_gui()
if !CanRunGui()
return
endif
" Ignore the "failed to create input context" error.
call test_ignore_error('E285:')
gui -f
call assert_equal(1, winnr('$'))

View File

@@ -0,0 +1,124 @@
" Test for $HOME on Windows.
if !has('win32')
finish
endif
let s:env = {}
func s:restore_env()
for i in keys(s:env)
exe 'let ' . i . '=s:env["' . i . '"]'
endfor
endfunc
func s:save_env(...)
for i in a:000
exe 'let s:env["' . i . '"]=' . i
endfor
endfunc
func s:unlet_env(...)
for i in a:000
exe 'let ' . i . '=""'
endfor
endfunc
func CheckHomeIsMissingFromSubprocessEnvironment()
silent! let out = system('set')
let env = filter(split(out, "\n"), 'v:val=~"^HOME="')
call assert_equal(0, len(env))
endfunc
func CheckHomeIsInSubprocessEnvironment(exp)
silent! let out = system('set')
let env = filter(split(out, "\n"), 'v:val=~"^HOME="')
let home = len(env) == 0 ? "" : substitute(env[0], '[^=]\+=', '', '')
call assert_equal(a:exp, home)
endfunc
func CheckHome(exp, ...)
"call assert_equal(a:exp, $HOME)
"call assert_equal(a:exp, expand('~', ':p'))
if !a:0
call CheckHomeIsMissingFromSubprocessEnvironment()
else
call CheckHomeIsInSubprocessEnvironment(a:exp)
endif
endfunc
func TestWindowsHome()
command! -nargs=* SaveEnv call <SID>save_env(<f-args>)
command! -nargs=* RestoreEnv call <SID>restore_env()
command! -nargs=* UnletEnv call <SID>unlet_env(<f-args>)
SaveEnv $HOME $USERPROFILE $HOMEDRIVE $HOMEPATH
try
RestoreEnv
UnletEnv $HOME $USERPROFILE $HOMEPATH
let $HOMEDRIVE = 'C:'
call CheckHome('C:\')
RestoreEnv
UnletEnv $HOME $USERPROFILE
let $HOMEDRIVE = 'C:'
let $HOMEPATH = '\foobar'
call CheckHome('C:\foobar')
RestoreEnv
UnletEnv $HOME $HOMEDRIVE $HOMEPATH
let $USERPROFILE = 'C:\foo'
call CheckHome('C:\foo')
RestoreEnv
UnletEnv $HOME
let $USERPROFILE = 'C:\foo'
let $HOMEDRIVE = 'C:'
let $HOMEPATH = '\baz'
call CheckHome('C:\foo')
RestoreEnv
let $HOME = 'C:\bar'
let $USERPROFILE = 'C:\foo'
let $HOMEDRIVE = 'C:'
let $HOMEPATH = '\baz'
call CheckHome('C:\bar', 1)
RestoreEnv
let $HOME = '%USERPROFILE%\bar'
let $USERPROFILE = 'C:\foo'
let $HOMEDRIVE = 'C:'
let $HOMEPATH = '\baz'
call CheckHome('%USERPROFILE%\bar', 1)
RestoreEnv
let $HOME = '%USERPROFILE'
let $USERPROFILE = 'C:\foo'
let $HOMEDRIVE = 'C:'
let $HOMEPATH = '\baz'
call CheckHome('%USERPROFILE', 1)
RestoreEnv
let $HOME = 'C:\%USERPROFILE%'
let $USERPROFILE = 'C:\foo'
let $HOMEDRIVE = 'C:'
let $HOMEPATH = '\baz'
call CheckHome('C:\%USERPROFILE%', 1)
if has('channel')
RestoreEnv
UnletEnv $HOME
let env = ''
let job = job_start('cmd /c set', {'out_cb': {ch,x->[env,execute('let env=x')]}})
sleep 1
let env = filter(split(env, "\n"), 'v:val=="HOME"')
let home = len(env) == 0 ? "" : env[0]
call assert_equal('', home)
endif
finally
RestoreEnv
delcommand SaveEnv
delcommand RestoreEnv
delcommand UnletEnv
endtry
endfunc

View File

@@ -769,6 +769,22 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1015,
/**/
1014,
/**/
1013,
/**/
1012,
/**/
1011,
/**/
1010,
/**/
1009,
/**/
1008,
/**/
1007,
/**/