summaryrefslogtreecommitdiff
path: root/src/term.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/term.c')
-rw-r--r--src/term.c222
1 files changed, 132 insertions, 90 deletions
diff --git a/src/term.c b/src/term.c
index 462fe6f98..29d402505 100644
--- a/src/term.c
+++ b/src/term.c
@@ -110,19 +110,29 @@ static void log_tr(const char *fmt, ...);
# define LOG_TR(msg) do { /**/ } while (0)
# endif
-# define STATUS_GET 1 /* send request when switching to RAW mode */
-# define STATUS_SENT 2 /* did send request, waiting for response */
-# define STATUS_GOT 3 /* received response */
+typedef enum {
+ STATUS_GET, // send request when switching to RAW mode
+ STATUS_SENT, // did send request, checking for response
+ STATUS_GOT, // received response
+ STATUS_FAIL // timed out
+} request_progress_T;
-/* Request Terminal Version status: */
-static int crv_status = STATUS_GET;
+typedef struct {
+ request_progress_T tr_progress;
+ time_t tr_start; // when request was sent, -1 for never
+} termrequest_T;
-/* Request Cursor position report: */
-static int u7_status = STATUS_GET;
+# define TERMREQUEST_INIT {STATUS_GET, -1}
+
+// Request Terminal Version status:
+static termrequest_T crv_status = TERMREQUEST_INIT;
+
+// Request Cursor position report:
+static termrequest_T u7_status = TERMREQUEST_INIT;
# ifdef FEAT_TERMINAL
-/* Request foreground color report: */
-static int rfg_status = STATUS_GET;
+// Request foreground color report:
+static termrequest_T rfg_status = TERMREQUEST_INIT;
static int fg_r = 0;
static int fg_g = 0;
static int fg_b = 0;
@@ -132,16 +142,29 @@ static int bg_b = 255;
# endif
/* Request background color report: */
-static int rbg_status = STATUS_GET;
+static termrequest_T rbg_status = TERMREQUEST_INIT;
/* Request cursor blinking mode report: */
-static int rbm_status = STATUS_GET;
+static termrequest_T rbm_status = TERMREQUEST_INIT;
/* Request cursor style report: */
-static int rcs_status = STATUS_GET;
+static termrequest_T rcs_status = TERMREQUEST_INIT;
/* Request windos position report: */
-static int winpos_status = STATUS_GET;
+static termrequest_T winpos_status = TERMREQUEST_INIT;
+
+static termrequest_T *all_termrequests[] = {
+ &crv_status,
+ &u7_status,
+# ifdef FEAT_TERMINAL
+ &rfg_status,
+# endif
+ &rbg_status,
+ &rbm_status,
+ &rcs_status,
+ &winpos_status,
+ NULL
+};
# endif
/*
@@ -2011,7 +2034,7 @@ set_termname(char_u *term)
set_term_defaults(); /* use current values as defaults */
#ifdef FEAT_TERMRESPONSE
LOG_TR(("setting crv_status to STATUS_GET"));
- crv_status = STATUS_GET; /* Get terminal version later */
+ crv_status.tr_progress = STATUS_GET; // Get terminal version later
#endif
/*
@@ -2833,12 +2856,47 @@ can_get_termresponse()
{
return cur_tmode == TMODE_RAW
&& termcap_active
-# ifdef UNIX
+# ifdef UNIX
&& (is_not_a_term() || (isatty(1) && isatty(read_cmd_fd)))
-# endif
+# endif
&& p_ek;
}
+/*
+ * Set "status" to STATUS_SENT.
+ */
+ static void
+termrequest_sent(termrequest_T *status)
+{
+ status->tr_progress = STATUS_SENT;
+ status->tr_start = time(NULL);
+}
+
+/*
+ * Return TRUE if any of the requests are in STATUS_SENT.
+ */
+ static int
+termrequest_any_pending()
+{
+ int i;
+ time_t now = time(NULL);
+
+ for (i = 0; all_termrequests[i] != NULL; ++i)
+ {
+ if (all_termrequests[i]->tr_progress == STATUS_SENT)
+ {
+ if (all_termrequests[i]->tr_start > 0 && now > 0
+ && all_termrequests[i]->tr_start + 2 < now)
+ // Sent the request more than 2 seconds ago and didn't get a
+ // response, assume it failed.
+ all_termrequests[i]->tr_progress = STATUS_FAIL;
+ else
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
static int winpos_x = -1;
static int winpos_y = -1;
static int did_request_winpos = 0;
@@ -2860,7 +2918,7 @@ term_get_winpos(int *x, int *y, varnumber_T timeout)
winpos_x = -1;
winpos_y = -1;
++did_request_winpos;
- winpos_status = STATUS_SENT;
+ termrequest_sent(&winpos_status);
OUT_STR(T_CGP);
out_flush();
@@ -3478,18 +3536,10 @@ settmode(int tmode)
if (!gui.in_use && !gui.starting)
# endif
{
- /* May need to check for T_CRV response and termcodes, it
- * doesn't work in Cooked mode, an external program may get
- * them. */
- if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
- || u7_status == STATUS_SENT
-#ifdef FEAT_TERMINAL
- || rfg_status == STATUS_SENT
-#endif
- || rbg_status == STATUS_SENT
- || rbm_status == STATUS_SENT
- || rcs_status == STATUS_SENT
- || winpos_status == STATUS_SENT))
+ // May need to check for T_CRV response and termcodes, it
+ // doesn't work in Cooked mode, an external program may get
+ // them.
+ if (tmode != TMODE_RAW && termrequest_any_pending())
(void)vpeekc_nomap();
check_for_codes_from_term();
}
@@ -3540,7 +3590,7 @@ starttermcap(void)
may_req_termresponse();
/* Immediately check for a response. If t_Co changes, we don't
* want to redraw with wrong colors first. */
- if (crv_status == STATUS_SENT)
+ if (crv_status.tr_progress == STATUS_SENT)
check_for_codes_from_term();
}
#endif
@@ -3559,23 +3609,15 @@ stoptermcap(void)
if (!gui.in_use && !gui.starting)
# endif
{
- /* May need to discard T_CRV, T_U7 or T_RBG response. */
- if (crv_status == STATUS_SENT
- || u7_status == STATUS_SENT
-# ifdef FEAT_TERMINAL
- || rfg_status == STATUS_SENT
-# endif
- || rbg_status == STATUS_SENT
- || rbm_status == STATUS_SENT
- || rcs_status == STATUS_SENT
- || winpos_status == STATUS_SENT)
+ // May need to discard T_CRV, T_U7 or T_RBG response.
+ if (termrequest_any_pending())
{
# ifdef UNIX
- /* Give the terminal a chance to respond. */
+ // Give the terminal a chance to respond.
mch_delay(100L, FALSE);
# endif
# ifdef TCIFLUSH
- /* Discard data received but not read. */
+ // Discard data received but not read.
if (exiting)
tcflush(fileno(stdin), TCIFLUSH);
# endif
@@ -3614,14 +3656,14 @@ stoptermcap(void)
void
may_req_termresponse(void)
{
- if (crv_status == STATUS_GET
+ if (crv_status.tr_progress == STATUS_GET
&& can_get_termresponse()
&& starting == 0
&& *T_CRV != NUL)
{
LOG_TR(("Sending CRV request"));
out_str(T_CRV);
- crv_status = STATUS_SENT;
+ termrequest_sent(&crv_status);
/* check for the characters now, otherwise they might be eaten by
* get_keystroke() */
out_flush();
@@ -3641,37 +3683,37 @@ may_req_termresponse(void)
void
may_req_ambiguous_char_width(void)
{
- if (u7_status == STATUS_GET
+ if (u7_status.tr_progress == STATUS_GET
&& can_get_termresponse()
&& starting == 0
&& *T_U7 != NUL
&& !option_was_set((char_u *)"ambiwidth"))
{
- char_u buf[16];
-
- LOG_TR(("Sending U7 request"));
- /* Do this in the second row. In the first row the returned sequence
- * may be CSI 1;2R, which is the same as <S-F3>. */
- term_windgoto(1, 0);
- buf[mb_char2bytes(0x25bd, buf)] = 0;
- out_str(buf);
- out_str(T_U7);
- u7_status = STATUS_SENT;
- out_flush();
-
- /* This overwrites a few characters on the screen, a redraw is needed
- * after this. Clear them out for now. */
- term_windgoto(1, 0);
- out_str((char_u *)" ");
- term_windgoto(0, 0);
-
- /* Need to reset the known cursor position. */
- screen_start();
-
- /* check for the characters now, otherwise they might be eaten by
- * get_keystroke() */
- out_flush();
- (void)vpeekc_nomap();
+ char_u buf[16];
+
+ LOG_TR(("Sending U7 request"));
+ /* Do this in the second row. In the first row the returned sequence
+ * may be CSI 1;2R, which is the same as <S-F3>. */
+ term_windgoto(1, 0);
+ buf[mb_char2bytes(0x25bd, buf)] = 0;
+ out_str(buf);
+ out_str(T_U7);
+ termrequest_sent(&u7_status);
+ out_flush();
+
+ /* This overwrites a few characters on the screen, a redraw is needed
+ * after this. Clear them out for now. */
+ term_windgoto(1, 0);
+ out_str((char_u *)" ");
+ term_windgoto(0, 0);
+
+ /* Need to reset the known cursor position. */
+ screen_start();
+
+ /* check for the characters now, otherwise they might be eaten by
+ * get_keystroke() */
+ out_flush();
+ (void)vpeekc_nomap();
}
}
@@ -3688,21 +3730,21 @@ may_req_bg_color(void)
# ifdef FEAT_TERMINAL
/* Only request foreground if t_RF is set. */
- if (rfg_status == STATUS_GET && *T_RFG != NUL)
+ if (rfg_status.tr_progress == STATUS_GET && *T_RFG != NUL)
{
LOG_TR(("Sending FG request"));
out_str(T_RFG);
- rfg_status = STATUS_SENT;
+ termrequest_sent(&rfg_status);
didit = TRUE;
}
# endif
/* Only request background if t_RB is set. */
- if (rbg_status == STATUS_GET && *T_RBG != NUL)
+ if (rbg_status.tr_progress == STATUS_GET && *T_RBG != NUL)
{
LOG_TR(("Sending BG request"));
out_str(T_RBG);
- rbg_status = STATUS_SENT;
+ termrequest_sent(&rbg_status);
didit = TRUE;
}
@@ -3962,7 +4004,7 @@ term_cursor_color(char_u *color)
blink_state_is_inverted()
{
#ifdef FEAT_TERMRESPONSE
- return rbm_status == STATUS_GOT && rcs_status == STATUS_GOT
+ return rbm_status.tr_progress == STATUS_GOT && rcs_status.tr_progress == STATUS_GOT
&& initial_cursor_blink != initial_cursor_shape_blink;
#else
return FALSE;
@@ -4651,7 +4693,7 @@ check_termcode(
char *aw = NULL;
LOG_TR(("Received U7 status: %s", tp));
- u7_status = STATUS_GOT;
+ u7_status.tr_progress = STATUS_GOT;
did_cursorhold = TRUE;
if (col == 2)
aw = "single";
@@ -4689,7 +4731,7 @@ check_termcode(
int version = col;
LOG_TR(("Received CRV response: %s", tp));
- crv_status = STATUS_GOT;
+ crv_status.tr_progress = STATUS_GOT;
did_cursorhold = TRUE;
/* If this code starts with CSI, you can bet that the
@@ -4804,7 +4846,7 @@ check_termcode(
* 279 (otherwise it returns 0x18).
* Not for Terminal.app, it can't handle t_RS, it
* echoes the characters to the screen. */
- if (rcs_status == STATUS_GET
+ if (rcs_status.tr_progress == STATUS_GET
&& version >= 279
&& !is_not_xterm
&& *T_CSH != NUL
@@ -4812,20 +4854,20 @@ check_termcode(
{
LOG_TR(("Sending cursor style request"));
out_str(T_CRS);
- rcs_status = STATUS_SENT;
+ termrequest_sent(&rcs_status);
need_flush = TRUE;
}
/* Only request the cursor blink mode if t_RC set. Not
* for Gnome terminal, it can't handle t_RC, it
* echoes the characters to the screen. */
- if (rbm_status == STATUS_GET
+ if (rbm_status.tr_progress == STATUS_GET
&& !is_not_xterm
&& *T_CRC != NUL)
{
LOG_TR(("Sending cursor blink mode request"));
out_str(T_CRC);
- rbm_status = STATUS_SENT;
+ termrequest_sent(&rbm_status);
need_flush = TRUE;
}
@@ -4848,7 +4890,7 @@ check_termcode(
*
* {lead} can be <Esc>[ or CSI
*/
- else if (rbm_status == STATUS_SENT
+ else if (rbm_status.tr_progress == STATUS_SENT
&& tp[(j = 1 + (tp[0] == ESC))] == '?'
&& i == j + 6
&& tp[j + 1] == '1'
@@ -4858,7 +4900,7 @@ check_termcode(
&& tp[i] == 'y')
{
initial_cursor_blink = (tp[j + 4] == '1');
- rbm_status = STATUS_GOT;
+ rbm_status.tr_progress = STATUS_GOT;
LOG_TR(("Received cursor blinking mode response: %s", tp));
key_name[0] = (int)KS_EXTRA;
key_name[1] = (int)KE_IGNORE;
@@ -4896,7 +4938,7 @@ check_termcode(
slen = i + 1;
if (--did_request_winpos <= 0)
- winpos_status = STATUS_GOT;
+ winpos_status.tr_progress = STATUS_GOT;
}
}
if (i == len)
@@ -4948,7 +4990,7 @@ check_termcode(
+ tp[j+17]) ? "light" : "dark";
LOG_TR(("Received RBG response: %s", tp));
- rbg_status = STATUS_GOT;
+ rbg_status.tr_progress = STATUS_GOT;
# ifdef FEAT_TERMINAL
bg_r = rval;
bg_g = gval;
@@ -4968,7 +5010,7 @@ check_termcode(
else
{
LOG_TR(("Received RFG response: %s", tp));
- rfg_status = STATUS_GOT;
+ rfg_status.tr_progress = STATUS_GOT;
fg_r = rval;
fg_g = gval;
fg_b = bval;
@@ -5008,7 +5050,7 @@ check_termcode(
*
* Consume any code that starts with "{lead}.+r" or "{lead}.$r".
*/
- else if ((check_for_codes || rcs_status == STATUS_SENT)
+ else if ((check_for_codes || rcs_status.tr_progress == STATUS_SENT)
&& ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
|| tp[0] == DCS))
{
@@ -5061,7 +5103,7 @@ check_termcode(
* the value set with T_SH. */
initial_cursor_shape_blink =
(number & 1) ? FALSE : TRUE;
- rcs_status = STATUS_GOT;
+ rcs_status.tr_progress = STATUS_GOT;
LOG_TR(("Received cursor shape response: %s", tp));
key_name[0] = (int)KS_EXTRA;
@@ -6045,7 +6087,7 @@ check_termcode(
void
term_get_fg_color(char_u *r, char_u *g, char_u *b)
{
- if (rfg_status == STATUS_GOT)
+ if (rfg_status.tr_progress == STATUS_GOT)
{
*r = fg_r;
*g = fg_g;
@@ -6059,7 +6101,7 @@ term_get_fg_color(char_u *r, char_u *g, char_u *b)
void
term_get_bg_color(char_u *r, char_u *g, char_u *b)
{
- if (rbg_status == STATUS_GOT)
+ if (rbg_status.tr_progress == STATUS_GOT)
{
*r = bg_r;
*g = bg_g;