@@ -845,9 +845,11 @@ static struct builtin_term builtin_termcaps[] =
845845 ESC_STR "[8;%p1%d;%p2%dt" )},
846846 {(int )KS_CWP , IF_EB ("\033[3;%p1%d;%p2%dt" ,
847847 ESC_STR "[3;%p1%d;%p2%dt" )},
848+ {(int )KS_CGP , IF_EB ("\033[13t" , ESC_STR "[13t" )},
848849# else
849850 {(int )KS_CWS , IF_EB ("\033[8;%d;%dt" , ESC_STR "[8;%d;%dt" )},
850851 {(int )KS_CWP , IF_EB ("\033[3;%d;%dt" , ESC_STR "[3;%d;%dt" )},
852+ {(int )KS_CGP , IF_EB ("\033[13t" , ESC_STR "[13t" )},
851853# endif
852854 {(int )KS_CRV , IF_EB ("\033[>c" , ESC_STR "[>c" )},
853855 {(int )KS_RBG , IF_EB ("\033]11;?\007" , ESC_STR "]11;?\007" )},
@@ -2581,6 +2583,60 @@ term_set_winpos(int x, int y)
25812583 OUT_STR (tgoto ((char * )T_CWP , y , x ));
25822584}
25832585
2586+ # if defined(FEAT_TERMRESPONSE ) || defined(PROTO )
2587+ /*
2588+ * Return TRUE if we can request the terminal for a response.
2589+ */
2590+ static int
2591+ can_get_termresponse ()
2592+ {
2593+ return cur_tmode == TMODE_RAW
2594+ && termcap_active
2595+ # ifdef UNIX
2596+ & & (is_not_a_term () || (isatty (1 ) && isatty (read_cmd_fd )))
2597+ # endif
2598+ & & p_ek ;
2599+ }
2600+
2601+ static int winpos_x ;
2602+ static int winpos_y ;
2603+ static int waiting_for_winpos = FALSE;
2604+
2605+ /*
2606+ * Try getting the Vim window position from the terminal.
2607+ * Returns OK or FAIL.
2608+ */
2609+ int
2610+ term_get_winpos (int * x , int * y )
2611+ {
2612+ int count = 0 ;
2613+
2614+ if (* T_CGP == NUL || !can_get_termresponse ())
2615+ return FAIL ;
2616+ winpos_x = -1 ;
2617+ winpos_y = -1 ;
2618+ waiting_for_winpos = TRUE;
2619+ OUT_STR (T_CGP );
2620+ out_flush ();
2621+
2622+ /* Try reading the result for 100 msec. */
2623+ while (count ++ < 10 )
2624+ {
2625+ (void )vpeekc_nomap ();
2626+ if (winpos_x >= 0 && winpos_y >= 0 )
2627+ {
2628+ * x = winpos_x ;
2629+ * y = winpos_y ;
2630+ waiting_for_winpos = FALSE;
2631+ return OK ;
2632+ }
2633+ ui_delay (10 , FALSE);
2634+ }
2635+ waiting_for_winpos = FALSE;
2636+ return FALSE;
2637+ }
2638+ # endif
2639+
25842640 void
25852641term_set_winsize (int width , int height )
25862642{
@@ -3229,14 +3285,8 @@ stoptermcap(void)
32293285may_req_termresponse (void )
32303286{
32313287 if (crv_status == CRV_GET
3232- && cur_tmode == TMODE_RAW
3288+ && can_get_termresponse ()
32333289 && starting == 0
3234- && termcap_active
3235- && p_ek
3236- # ifdef UNIX
3237- && isatty (1 )
3238- && isatty (read_cmd_fd )
3239- # endif
32403290 && * T_CRV != NUL )
32413291 {
32423292 LOG_TR ("Sending CRV" );
@@ -3263,13 +3313,8 @@ may_req_termresponse(void)
32633313may_req_ambiguous_char_width (void )
32643314{
32653315 if (u7_status == U7_GET
3266- && cur_tmode == TMODE_RAW
3267- && termcap_active
3268- && p_ek
3269- # ifdef UNIX
3270- && isatty (1 )
3271- && isatty (read_cmd_fd )
3272- # endif
3316+ && can_get_termresponse ()
3317+ && starting == 0
32733318 && * T_U7 != NUL
32743319 && !option_was_set ((char_u * )"ambiwidth" ))
32753320 {
@@ -3295,7 +3340,6 @@ may_req_ambiguous_char_width(void)
32953340}
32963341# endif
32973342
3298- #if defined(FEAT_TERMRESPONSE ) || defined(PROTO )
32993343/*
33003344 * Similar to requesting the version string: Request the terminal background
33013345 * color when it is the right moment.
@@ -3304,13 +3348,8 @@ may_req_ambiguous_char_width(void)
33043348may_req_bg_color (void )
33053349{
33063350 if (rbg_status == RBG_GET
3307- && cur_tmode == TMODE_RAW
3308- && termcap_active
3309- && p_ek
3310- # ifdef UNIX
3311- && isatty (1 )
3312- && isatty (read_cmd_fd )
3313- # endif
3351+ && can_get_termresponse ()
3352+ && starting == 0
33143353 && * T_RBG != NUL
33153354 && !option_was_set ((char_u * )"bg" ))
33163355 {
@@ -3323,7 +3362,6 @@ may_req_bg_color(void)
33233362 (void )vpeekc_nomap ();
33243363 }
33253364}
3326- # endif
33273365
33283366# ifdef DEBUG_TERMRESPONSE
33293367 static void
@@ -4136,10 +4174,12 @@ check_termcode(
41364174 * - Cursor position report: <Esc>[{row};{col}R
41374175 * The final byte must be 'R'. It is used for checking the
41384176 * ambiguous-width character state.
4177+ *
4178+ * - window position reply: <Esc>[3;{x};{y}t
41394179 */
41404180 char_u * argp = tp [0 ] == ESC ? tp + 2 : tp + 1 ;
41414181
4142- if ((* T_CRV != NUL || * T_U7 != NUL )
4182+ if ((* T_CRV != NUL || * T_U7 != NUL || waiting_for_winpos )
41434183 && ((tp [0 ] == ESC && len >= 3 && tp [1 ] == '[' )
41444184 || (tp [0 ] == CSI && len >= 2 ))
41454185 && (VIM_ISDIGIT (* argp ) || * argp == '>' || * argp == '?' ))
@@ -4278,6 +4318,41 @@ check_termcode(
42784318 key_name [1 ] = (int )KE_IGNORE ;
42794319 slen = i + 1 ;
42804320 }
4321+
4322+ /*
4323+ * Check for a window position response from the terminal:
4324+ * {lead}3;{x}:{y}t
4325+ */
4326+ else if (waiting_for_winpos
4327+ && ((len >= 4 && tp [0 ] == ESC && tp [1 ] == '[' )
4328+ || (len >= 3 && tp [0 ] == CSI ))
4329+ && tp [(j = 1 + (tp [0 ] == ESC ))] == '3'
4330+ && tp [j + 1 ] == ';' )
4331+ {
4332+ j += 2 ;
4333+ for (i = j ; i < len && vim_isdigit (tp [i ]); ++ i )
4334+ ;
4335+ if (i < len && tp [i ] == ';' )
4336+ {
4337+ winpos_x = atoi ((char * )tp + j );
4338+ j = i + 1 ;
4339+ for (i = j ; i < len && vim_isdigit (tp [i ]); ++ i )
4340+ ;
4341+ if (i < len && tp [i ] == 't' )
4342+ {
4343+ winpos_y = atoi ((char * )tp + j );
4344+ /* got finished code: consume it */
4345+ key_name [0 ] = (int )KS_EXTRA ;
4346+ key_name [1 ] = (int )KE_IGNORE ;
4347+ slen = i + 1 ;
4348+ }
4349+ }
4350+ if (i == len )
4351+ {
4352+ LOG_TR ("not enough characters for winpos" );
4353+ return -1 ;
4354+ }
4355+ }
42814356 }
42824357
42834358 /* Check for background color response from the terminal:
0 commit comments