1913cc679Smrg#!/usr/bin/env perl 204b94745Smrg# $XTermId: query-status.pl,v 1.10 2021/11/11 21:31:48 tom Exp $ 3913cc679Smrg# ----------------------------------------------------------------------------- 4913cc679Smrg# this file is part of xterm 5913cc679Smrg# 6a5ae21e4Smrg# Copyright 2017-2019,2021 by Thomas E. Dickey 7913cc679Smrg# 8913cc679Smrg# All Rights Reserved 9913cc679Smrg# 10913cc679Smrg# Permission is hereby granted, free of charge, to any person obtaining a 11913cc679Smrg# copy of this software and associated documentation files (the 12913cc679Smrg# "Software"), to deal in the Software without restriction, including 13913cc679Smrg# without limitation the rights to use, copy, modify, merge, publish, 14913cc679Smrg# distribute, sublicense, and/or sell copies of the Software, and to 15913cc679Smrg# permit persons to whom the Software is furnished to do so, subject to 16913cc679Smrg# the following conditions: 17913cc679Smrg# 18913cc679Smrg# The above copyright notice and this permission notice shall be included 19913cc679Smrg# in all copies or substantial portions of the Software. 20913cc679Smrg# 21913cc679Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22913cc679Smrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23913cc679Smrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24913cc679Smrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 25913cc679Smrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26913cc679Smrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27913cc679Smrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28913cc679Smrg# 29913cc679Smrg# Except as contained in this notice, the name(s) of the above copyright 30913cc679Smrg# holders shall not be used in advertising or otherwise to promote the 31913cc679Smrg# sale, use or other dealings in this Software without prior written 32913cc679Smrg# authorization. 33913cc679Smrg# ----------------------------------------------------------------------------- 34913cc679Smrg# Test the status features of xterm using DECRQSS. 35913cc679Smrg# 36913cc679Smrg# TODO: use Term::ReadKey rather than system/stty 37913cc679Smrg 38913cc679Smrguse strict; 39913cc679Smrguse warnings; 40913cc679Smrg 41913cc679Smrguse Getopt::Std; 42913cc679Smrguse IO::Handle; 43913cc679Smrg 44a5ae21e4Smrgour ( $opt_a, $opt_c, $opt_d, $opt_8 ); 45f2e35a3aSmrg 46f2e35a3aSmrg$Getopt::Std::STANDARD_HELP_VERSION = 1; 47a5ae21e4Smrg&getopts('acd8') || die( 48a5ae21e4Smrg "Usage: $0 [options] [suffixes]\n 49913cc679SmrgOptions:\n 50a5ae21e4Smrg -a test ANSI colors with SGR controls 51a5ae21e4Smrg -c test cursor appearance with DECSCUSR controls 52a5ae21e4Smrg -d test direct colors with SGR controls 53913cc679Smrg -8 use 8-bit controls 54f2e35a3aSmrg 55f2e35a3aSmrgOptions which use C1 controls may not work with UTF-8. 56913cc679Smrg" 57913cc679Smrg); 58913cc679Smrg 59a5ae21e4Smrgour $ST = $opt_8 ? "\x9c" : "\x1b\\"; 60a5ae21e4Smrgour $CSI = $opt_8 ? "\x9a" : "\x1b["; 61913cc679Smrg 62913cc679Smrgour %suffixes; 63913cc679Smrg$suffixes{DECSCA} = '"q'; 64913cc679Smrg$suffixes{DECSCL} = '"p'; 65913cc679Smrg$suffixes{DECSTBM} = 'r'; 66913cc679Smrg$suffixes{DECSLRM} = 's'; 67913cc679Smrg$suffixes{SGR} = 'm'; 68913cc679Smrg$suffixes{DECSCUSR} = ' q'; 69913cc679Smrg 70913cc679Smrgsub get_reply($) { 71913cc679Smrg open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n"); 72913cc679Smrg autoflush TTY 1; 73913cc679Smrg my $old = `stty -g`; 74913cc679Smrg system "stty raw -echo min 0 time 5"; 75913cc679Smrg 76913cc679Smrg print TTY @_; 77913cc679Smrg my $reply = <TTY>; 78913cc679Smrg close TTY; 79913cc679Smrg system "stty $old"; 80913cc679Smrg if ( defined $reply ) { 81913cc679Smrg die("^C received\n") if ( "$reply" eq "\003" ); 82913cc679Smrg } 83913cc679Smrg return $reply; 84913cc679Smrg} 85913cc679Smrg 86913cc679Smrgsub visible($) { 87913cc679Smrg my $reply = $_[0]; 88913cc679Smrg my $n; 89913cc679Smrg my $result = ""; 90913cc679Smrg for ( $n = 0 ; $n < length($reply) ; ) { 91913cc679Smrg my $c = substr( $reply, $n, 1 ); 92913cc679Smrg if ( $c =~ /[[:print:]]/ ) { 93913cc679Smrg $result .= $c; 94913cc679Smrg } 95913cc679Smrg else { 96913cc679Smrg my $k = ord substr( $reply, $n, 1 ); 97913cc679Smrg if ( ord $k == 0x1b ) { 98913cc679Smrg $result .= "\\E"; 99913cc679Smrg } 100913cc679Smrg elsif ( $k == 0x7f ) { 101913cc679Smrg $result .= "^?"; 102913cc679Smrg } 103913cc679Smrg elsif ( $k == 32 ) { 104913cc679Smrg $result .= "\\s"; 105913cc679Smrg } 106913cc679Smrg elsif ( $k < 32 ) { 107913cc679Smrg $result .= sprintf( "^%c", $k + 64 ); 108913cc679Smrg } 109913cc679Smrg elsif ( $k > 128 ) { 110913cc679Smrg $result .= sprintf( "\\%03o", $k ); 111913cc679Smrg } 112913cc679Smrg else { 113913cc679Smrg $result .= chr($k); 114913cc679Smrg } 115913cc679Smrg } 116913cc679Smrg $n += 1; 117913cc679Smrg } 118913cc679Smrg 119913cc679Smrg return $result; 120913cc679Smrg} 121913cc679Smrg 122913cc679Smrgsub query_one($) { 123a5ae21e4Smrg my $name = shift; 124a5ae21e4Smrg 125a5ae21e4Smrg return unless $suffixes{$name}; 126a5ae21e4Smrg 127913cc679Smrg my $suffix = $suffixes{$name}; 128913cc679Smrg my $prefix = $opt_8 ? "\x90" : "\x1bP"; 129a5ae21e4Smrg my $st = $opt_8 ? "\x9c" : qr/\x1b\\/; 130a5ae21e4Smrg my $DCS = qr/${prefix}/; 131a5ae21e4Smrg my $match = qr/${DCS}.*${st}/; 132a5ae21e4Smrg my $reply = get_reply( $prefix . '$q' . $suffix . $ST ); 133913cc679Smrg 134913cc679Smrg printf "%-10s query{%s}%*s", $name, # 135913cc679Smrg &visible($suffix), # 136913cc679Smrg 4 - length($suffix), " "; 137913cc679Smrg 138913cc679Smrg if ( defined $reply ) { 139913cc679Smrg printf "%2d ", length($reply); 140913cc679Smrg if ( $reply =~ /${match}/ ) { 141913cc679Smrg 142913cc679Smrg $reply =~ s/^${DCS}//; 143913cc679Smrg $reply =~ s/^;//; 144913cc679Smrg $reply =~ s/${st}$//; 145913cc679Smrg } 146913cc679Smrg else { 147913cc679Smrg printf "? "; 148913cc679Smrg } 149913cc679Smrg 150913cc679Smrg printf "{%s}", visible($reply); 151913cc679Smrg } 152913cc679Smrg printf "\n"; 153913cc679Smrg} 154913cc679Smrg 155a5ae21e4Smrgsub ansi_color($) { 156a5ae21e4Smrg my $color = shift; 157a5ae21e4Smrg return $color; 158a5ae21e4Smrg} 159a5ae21e4Smrg 160a5ae21e4Smrgsub direct_color($) { 161a5ae21e4Smrg my $color = shift; 162a5ae21e4Smrg my $result = "8:2:"; 163a5ae21e4Smrg $result .= ( $color & 4 ) ? ":255" : ":0"; 164a5ae21e4Smrg $result .= ( $color & 2 ) ? ":255" : ":0"; 165a5ae21e4Smrg $result .= ( $color & 1 ) ? ":255" : ":0"; 166a5ae21e4Smrg return $result; 167a5ae21e4Smrg} 168a5ae21e4Smrg 169a5ae21e4Smrgsub default_colors() { 170a5ae21e4Smrg return "39;49"; 171a5ae21e4Smrg} 172a5ae21e4Smrg 173f2e35a3aSmrgprintf "\x1b G" if ($opt_8); 174f2e35a3aSmrg 175913cc679Smrgif ( $#ARGV >= 0 ) { 176913cc679Smrg while ( $#ARGV >= 0 ) { 177913cc679Smrg &query_one( shift @ARGV ); 178913cc679Smrg } 179913cc679Smrg} 180a5ae21e4Smrgelsif ($opt_a) { 181a5ae21e4Smrg for my $fg ( 0 .. 7 ) { 182a5ae21e4Smrg printf "%s3%sm", $CSI, &ansi_color($fg); 183a5ae21e4Smrg for my $bg ( 0 .. 7 ) { 184a5ae21e4Smrg printf "%s4%sm", $CSI, &ansi_color($bg); 185a5ae21e4Smrg &query_one("SGR"); 186a5ae21e4Smrg } 187a5ae21e4Smrg } 188a5ae21e4Smrg printf "%s%sm", $CSI, &default_colors; 189a5ae21e4Smrg} 190a5ae21e4Smrgelsif ($opt_c) { 191a5ae21e4Smrg for my $c ( 0 .. 6 ) { 192a5ae21e4Smrg printf "%s%d q", $CSI, $c; 193a5ae21e4Smrg &query_one("DECSCUSR"); 194a5ae21e4Smrg } 195a5ae21e4Smrg printf "%s q", $CSI; 196a5ae21e4Smrg} 197a5ae21e4Smrgelsif ($opt_d) { 198a5ae21e4Smrg for my $fg ( 0 .. 7 ) { 199a5ae21e4Smrg printf "%s3%sm", $CSI, &direct_color($fg); 200a5ae21e4Smrg for my $bg ( 0 .. 7 ) { 201a5ae21e4Smrg printf "%s4%sm", $CSI, &direct_color($bg); 202a5ae21e4Smrg &query_one("SGR"); 203a5ae21e4Smrg } 204a5ae21e4Smrg } 205a5ae21e4Smrg printf "%s39;49m", $CSI; 206a5ae21e4Smrg} 207913cc679Smrgelse { 208913cc679Smrg for my $key ( sort keys %suffixes ) { 209913cc679Smrg &query_one($key); 210913cc679Smrg } 211913cc679Smrg} 212f2e35a3aSmrg 213f2e35a3aSmrgprintf "\x1b F" if ($opt_8); 214