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 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 When the buffer associated with the terminal is unloaded or wiped out the job
is killed, similar to calling `job_stop(job, "kill")` 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 the window behaves like it contains a modified
So long as the job is running: If the window is closed the buffer becomes buffer. Trying to close the window with `CTRL-W :close` or `CTRL-W :hide`
hidden. The command will not be stopped. The `:buffer` command can be used fails, unless "!" is added, in which case the job is ended. The text in the
to turn the current window into a terminal window. If there are unsaved window is lost. The buffer still exists, but getting it in a window with
changes this fails, use ! to force, as usual. `: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 To have a background job run without a window, and open the window when it's
done, use options like this: > done, use options like this: >

View File

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

View File

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

View File

@@ -136,20 +136,11 @@ static guicolor_T prev_sp_color = INVALCOLOR;
static XButtonPressedEvent last_mouse_event; static XButtonPressedEvent last_mouse_event;
#endif #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); static void gui_x11_check_copy_area(void);
#ifdef FEAT_CLIENTSERVER #ifdef FEAT_CLIENTSERVER
static void gui_x11_send_event_handler(Widget, XtPointer, XEvent *, Boolean *); static void gui_x11_send_event_handler(Widget, XtPointer, XEvent *, Boolean *);
#endif #endif
static void gui_x11_wm_protocol_handler(Widget, XtPointer, XEvent *, Boolean *); 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 Cursor gui_x11_create_blank_mouse(void);
static void draw_curl(int row, int col, int cells); static void draw_curl(int row, int col, int cells);
@@ -574,6 +565,25 @@ gui_x11_timer_cb(
*((int *)timed_out) = TRUE; *((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 static void
gui_x11_visibility_cb( gui_x11_visibility_cb(
Widget w UNUSED, Widget w UNUSED,
@@ -2698,12 +2708,22 @@ gui_mch_wait_for_chars(long wtime)
static int timed_out; static int timed_out;
XtIntervalId timer = (XtIntervalId)0; XtIntervalId timer = (XtIntervalId)0;
XtInputMask desired; XtInputMask desired;
#ifdef FEAT_JOB_CHANNEL
XtIntervalId channel_timer = (XtIntervalId)0;
#endif
timed_out = FALSE; timed_out = FALSE;
if (wtime > 0) if (wtime > 0)
timer = XtAppAddTimeOut(app_context, (long_u)wtime, gui_x11_timer_cb, timer = XtAppAddTimeOut(app_context, (long_u)wtime, gui_x11_timer_cb,
&timed_out); &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; focus = gui.in_focus;
#ifdef ALT_X_INPUT #ifdef ALT_X_INPUT
@@ -2755,6 +2775,10 @@ gui_mch_wait_for_chars(long wtime)
if (timer != (XtIntervalId)0 && !timed_out) if (timer != (XtIntervalId)0 && !timed_out)
XtRemoveTimeOut(timer); XtRemoveTimeOut(timer);
#ifdef FEAT_JOB_CHANNEL
if (channel_timer != (XtIntervalId)0)
XtRemoveTimeOut(channel_timer);
#endif
return retval; return retval;
} }
@@ -3087,25 +3111,6 @@ gui_mch_stop_blink(void)
blink_state = BLINK_NONE; 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 static void
gui_x11_blink_cb( gui_x11_blink_cb(
XtPointer timed_out UNUSED, 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. * 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. * utf_char2cells() with different argument type for libvterm.
*/ */
int int
utf_uint2cells(uint32_t c) utf_uint2cells(UINT32_T c)
{ {
return utf_char2cells((int)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. * utf_iscomposing() with different argument type for libvterm.
*/ */
int int
utf_iscomposing_uint(uint32_t c) utf_iscomposing_uint(UINT32_T c)
{ {
return utf_iscomposing((int)c); return utf_iscomposing((int)c);
} }

View File

@@ -3750,10 +3750,33 @@ init_homedir(void)
var = mch_getenv((char_u *)"HOME"); var = mch_getenv((char_u *)"HOME");
#endif #endif
if (var != NULL && *var == NUL) /* empty is same as not set */
var = NULL;
#ifdef WIN3264 #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 * Weird but true: $HOME may contain an indirect reference to another
* variable, esp. "%USERPROFILE%". Happens when $USERPROFILE isn't set * 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); vim_snprintf((char *)NameBuff, MAXPATHL, "%s%s", exp, p + 1);
var = NameBuff; var = NameBuff;
/* Also set $HOME, it's needed for _viminfo. */
vim_setenv((char_u *)"HOME", NameBuff);
} }
} }
} }
/* if (var != NULL && *var == NUL) /* empty is same as not set */
* Typically, $HOME is not defined on Windows, unless the user has var = NULL;
* 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;
homedrive = mch_getenv((char_u *)"HOMEDRIVE"); # ifdef FEAT_MBYTE
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)
if (enc_utf8 && var != NULL) if (enc_utf8 && var != NULL)
{ {
int len; int len;
@@ -3823,9 +3820,7 @@ init_homedir(void)
} }
} }
# endif # endif
#endif
#if defined(MSWIN)
/* /*
* Default home dir is C:/ * Default home dir is C:/
* Best assumption we can make in such a situation. * Best assumption we can make in such a situation.
@@ -3833,6 +3828,7 @@ init_homedir(void)
if (var == NULL) if (var == NULL)
var = (char_u *)"C:/"; var = (char_u *)"C:/";
#endif #endif
if (var != NULL) if (var != NULL)
{ {
#ifdef UNIX #ifdef UNIX
@@ -4661,6 +4657,10 @@ home_replace(
homedir_env_orig = homedir_env = mch_getenv((char_u *)"SYS$LOGIN"); homedir_env_orig = homedir_env = mch_getenv((char_u *)"SYS$LOGIN");
#else #else
homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME"); 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 #endif
/* Empty is the same as not set. */ /* Empty is the same as not set. */
if (homedir_env != NULL && *homedir_env == NUL) 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_nd", T_ND)
p_term("t_op", T_OP) p_term("t_op", T_OP)
p_term("t_RB", T_RBG) p_term("t_RB", T_RBG)
p_term("t_RC", T_CRC)
p_term("t_RI", T_CRI) p_term("t_RI", T_CRI)
p_term("t_RS", T_CRS) p_term("t_RS", T_CRS)
p_term("t_RV", T_CRV) 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_char2bytes(int c, char_u *buf);
int latin_ptr2len(char_u *p); int latin_ptr2len(char_u *p);
int latin_ptr2len_len(char_u *p, int size); 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 utf_char2cells(int c);
int latin_ptr2cells(char_u *p); int latin_ptr2cells(char_u *p);
int utf_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 utfc_ptr2len_len(char_u *p, int size);
int utf_char2len(int c); int utf_char2len(int c);
int utf_char2bytes(int c, char_u *buf); 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_iscomposing(int c);
int utf_printable(int c); int utf_printable(int c);
int utf_class(int c); int utf_class(int c);

View File

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

View File

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

View File

@@ -42,7 +42,8 @@ enum SpecialKey
KS_VS, /* cursor very visible (blink) */ KS_VS, /* cursor very visible (blink) */
KS_CVS, /* cursor normally visible (no blink) */ KS_CVS, /* cursor normally visible (no blink) */
KS_CSH, /* cursor shape */ KS_CSH, /* cursor shape */
KS_CRS, /* request cursor shape */ KS_CRC, /* request cursor blinking */
KS_CRS, /* request cursor style */
KS_ME, /* normal mode */ KS_ME, /* normal mode */
KS_MR, /* reverse mode */ KS_MR, /* reverse mode */
KS_MD, /* bold 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_VS (TERM_STR(KS_VS)) /* cursor very visible (blink) */
#define T_CVS (TERM_STR(KS_CVS)) /* cursor normally visible (no blink) */ #define T_CVS (TERM_STR(KS_CVS)) /* cursor normally visible (no blink) */
#define T_CSH (TERM_STR(KS_CSH)) /* cursor shape */ #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_ME (TERM_STR(KS_ME)) /* normal mode */
#define T_MR (TERM_STR(KS_MR)) /* reverse mode */ #define T_MR (TERM_STR(KS_MR)) /* reverse mode */
#define T_MD (TERM_STR(KS_MD)) /* bold mode */ #define T_MD (TERM_STR(KS_MD)) /* bold mode */

View File

@@ -39,16 +39,12 @@
* *
* TODO: * TODO:
* - ":term NONE" does not work in MS-Windows. * - ":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 * - test for writing lines to terminal job does not work on MS-Windows
* - implement term_setsize() * - implement term_setsize()
* - add test for giving error for invalid 'termsize' value. * - add test for giving error for invalid 'termsize' value.
* - support minimal size when 'termsize' is "rows*cols". * - support minimal size when 'termsize' is "rows*cols".
* - support minimal size when 'termsize' is empty? * - 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. * - 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 * - GUI: when 'confirm' is set and trying to exit Vim, dialog offers to save
* changes to "!shell". * changes to "!shell".
* (justrajdeep, 2017 Aug 22) * (justrajdeep, 2017 Aug 22)
@@ -400,10 +396,6 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
* the job finished. */ * the job finished. */
curbuf->b_p_ma = FALSE; 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); set_term_and_win_size(term);
setup_job_options(opt, term->tl_rows, term->tl_cols); 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) if (d != NULL)
{ {
dict_add_nr_str(d, "visible", term->tl_cursor_visible, 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, "shape", term->tl_cursor_shape, NULL);
dict_add_nr_str(d, "color", 0L, term->tl_cursor_color == NULL dict_add_nr_str(d, "color", 0L, term->tl_cursor_color == NULL
? (char_u *)"" : term->tl_cursor_color); ? (char_u *)"" : term->tl_cursor_color);

View File

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

View File

@@ -84,6 +84,7 @@ endfunc
func Test_terminal_hide_buffer() func Test_terminal_hide_buffer()
let buf = Run_shell_in_terminal({}) let buf = Run_shell_in_terminal({})
setlocal bufhidden=hide
quit quit
for nr in range(1, winnr('$')) for nr in range(1, winnr('$'))
call assert_notequal(winbufnr(nr), buf) call assert_notequal(winbufnr(nr), buf)
@@ -356,13 +357,13 @@ func Test_finish_open_close()
call assert_equal(1, winnr('$')) call assert_equal(1, winnr('$'))
exe 'terminal ++open ' . cmd exe 'terminal ++open ' . cmd
close close!
call WaitFor("winnr('$') == 2", waittime) call WaitFor("winnr('$') == 2", waittime)
call assert_equal(2, winnr('$')) call assert_equal(2, winnr('$'))
bwipe bwipe
call term_start(cmd, {'term_finish': 'open'}) call term_start(cmd, {'term_finish': 'open'})
close close!
call WaitFor("winnr('$') == 2", waittime) call WaitFor("winnr('$') == 2", waittime)
call assert_equal(2, winnr('$')) call assert_equal(2, winnr('$'))
bwipe bwipe
@@ -385,7 +386,7 @@ func Test_finish_open_close()
call assert_fails("call term_start(cmd, {'term_opencmd': 'split % and %d'})", 'E475:') 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'}) call term_start(cmd, {'term_finish': 'open', 'term_opencmd': '4split | buffer %d'})
close close!
call WaitFor("winnr('$') == 2", waittime) call WaitFor("winnr('$') == 2", waittime)
call assert_equal(2, winnr('$')) call assert_equal(2, winnr('$'))
call assert_equal(4, winheight(0)) call assert_equal(4, winheight(0))
@@ -429,6 +430,10 @@ func Test_zz_terminal_in_gui()
if !CanRunGui() if !CanRunGui()
return return
endif endif
" Ignore the "failed to create input context" error.
call test_ignore_error('E285:')
gui -f gui -f
call assert_equal(1, winnr('$')) 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[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1015,
/**/
1014,
/**/
1013,
/**/
1012,
/**/
1011,
/**/
1010,
/**/
1009,
/**/
1008,
/**/ /**/
1007, 1007,
/**/ /**/