1f2e35a3aSmrg#!/usr/bin/env perl 204b94745Smrg# $XTermId: query-dynamic.pl,v 1.6 2019/05/19 08:56:11 tom Exp $ 3f2e35a3aSmrg# ----------------------------------------------------------------------------- 4f2e35a3aSmrg# this file is part of xterm 5f2e35a3aSmrg# 6f2e35a3aSmrg# Copyright 2019 by Thomas E. Dickey 7f2e35a3aSmrg# 8f2e35a3aSmrg# All Rights Reserved 9f2e35a3aSmrg# 10f2e35a3aSmrg# Permission is hereby granted, free of charge, to any person obtaining a 11f2e35a3aSmrg# copy of this software and associated documentation files (the 12f2e35a3aSmrg# "Software"), to deal in the Software without restriction, including 13f2e35a3aSmrg# without limitation the rights to use, copy, modify, merge, publish, 14f2e35a3aSmrg# distribute, sublicense, and/or sell copies of the Software, and to 15f2e35a3aSmrg# permit persons to whom the Software is furnished to do so, subject to 16f2e35a3aSmrg# the following conditions: 17f2e35a3aSmrg# 18f2e35a3aSmrg# The above copyright notice and this permission notice shall be included 19f2e35a3aSmrg# in all copies or substantial portions of the Software. 20f2e35a3aSmrg# 21f2e35a3aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22f2e35a3aSmrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23f2e35a3aSmrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24f2e35a3aSmrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 25f2e35a3aSmrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26f2e35a3aSmrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27f2e35a3aSmrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28f2e35a3aSmrg# 29f2e35a3aSmrg# Except as contained in this notice, the name(s) of the above copyright 30f2e35a3aSmrg# holders shall not be used in advertising or otherwise to promote the 31f2e35a3aSmrg# sale, use or other dealings in this Software without prior written 32f2e35a3aSmrg# authorization. 33f2e35a3aSmrg# ----------------------------------------------------------------------------- 34f2e35a3aSmrg# Test the color-query features of xterm for dynamic-colors 35f2e35a3aSmrg 36f2e35a3aSmrguse strict; 37f2e35a3aSmrguse warnings; 38f2e35a3aSmrg 39f2e35a3aSmrguse Getopt::Std; 40f2e35a3aSmrguse IO::Handle; 41f2e35a3aSmrg 42f2e35a3aSmrgour ( $opt_q, $opt_s, $opt_8 ); 43f2e35a3aSmrg 44f2e35a3aSmrgour @query_params; 45f2e35a3aSmrg 46f2e35a3aSmrgour @color_names = ( 47f2e35a3aSmrg "VT100 text foreground color", 48f2e35a3aSmrg "VT100 text background color", 49f2e35a3aSmrg "text cursor color", 50f2e35a3aSmrg "mouse foreground color", 51f2e35a3aSmrg "mouse background color", 52f2e35a3aSmrg "Tektronix foreground color", 53f2e35a3aSmrg "Tektronix background color", 54f2e35a3aSmrg "highlight background color", 55f2e35a3aSmrg "Tektronix cursor color", 56f2e35a3aSmrg "highlight foreground color" 57f2e35a3aSmrg); 58f2e35a3aSmrg 59f2e35a3aSmrg$Getopt::Std::STANDARD_HELP_VERSION = 1; 60f2e35a3aSmrg&getopts('qs8') || die( 61f2e35a3aSmrg "Usage: $0 [options]\n 62f2e35a3aSmrgOptions:\n 63f2e35a3aSmrg -q quicker results by merging queries 64f2e35a3aSmrg -s use ^G rather than ST 65f2e35a3aSmrg -8 use 8-bit controls 66f2e35a3aSmrg" 67f2e35a3aSmrg); 68f2e35a3aSmrg 69f2e35a3aSmrgour $OSC = "\x1b\]"; 70f2e35a3aSmrg$OSC = "\x9d" if ($opt_8); 71f2e35a3aSmrgour $ST = $opt_8 ? "\x9c" : ( $opt_s ? "\007" : "\x1b\\" ); 72f2e35a3aSmrg 73f2e35a3aSmrgsub get_reply($) { 74f2e35a3aSmrg open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n"); 75f2e35a3aSmrg autoflush TTY 1; 76f2e35a3aSmrg my $old = `stty -g`; 77f2e35a3aSmrg system "stty raw -echo min 0 time 5"; 78f2e35a3aSmrg 79f2e35a3aSmrg print TTY @_; 80f2e35a3aSmrg my $reply = <TTY>; 81f2e35a3aSmrg close TTY; 82f2e35a3aSmrg system "stty $old"; 83f2e35a3aSmrg if ( defined $reply ) { 84f2e35a3aSmrg die("^C received\n") if ( "$reply" eq "\003" ); 85f2e35a3aSmrg } 86f2e35a3aSmrg return $reply; 87f2e35a3aSmrg} 88f2e35a3aSmrg 89f2e35a3aSmrgsub visible($) { 90f2e35a3aSmrg my $reply = $_[0]; 91f2e35a3aSmrg my $n; 92f2e35a3aSmrg my $result = ""; 93f2e35a3aSmrg for ( $n = 0 ; $n < length($reply) ; ) { 94f2e35a3aSmrg my $c = substr( $reply, $n, 1 ); 95f2e35a3aSmrg if ( $c =~ /[[:print:]]/ ) { 96f2e35a3aSmrg $result .= $c; 97f2e35a3aSmrg } 98f2e35a3aSmrg else { 99f2e35a3aSmrg my $k = ord substr( $reply, $n, 1 ); 100f2e35a3aSmrg if ( ord $k == 0x1b ) { 101f2e35a3aSmrg $result .= "\\E"; 102f2e35a3aSmrg } 103f2e35a3aSmrg elsif ( $k == 0x7f ) { 104f2e35a3aSmrg $result .= "^?"; 105f2e35a3aSmrg } 106f2e35a3aSmrg elsif ( $k == 32 ) { 107f2e35a3aSmrg $result .= "\\s"; 108f2e35a3aSmrg } 109f2e35a3aSmrg elsif ( $k < 32 ) { 110f2e35a3aSmrg $result .= sprintf( "^%c", $k + 64 ); 111f2e35a3aSmrg } 112f2e35a3aSmrg elsif ( $k > 128 ) { 113f2e35a3aSmrg $result .= sprintf( "\\%03o", $k ); 114f2e35a3aSmrg } 115f2e35a3aSmrg else { 116f2e35a3aSmrg $result .= chr($k); 117f2e35a3aSmrg } 118f2e35a3aSmrg } 119f2e35a3aSmrg $n += 1; 120f2e35a3aSmrg } 121f2e35a3aSmrg 122f2e35a3aSmrg return $result; 123f2e35a3aSmrg} 124f2e35a3aSmrg 125f2e35a3aSmrgsub begin_query() { 126f2e35a3aSmrg @query_params = (); 127f2e35a3aSmrg} 128f2e35a3aSmrg 129f2e35a3aSmrgsub add_param($) { 130f2e35a3aSmrg $query_params[ $#query_params + 1 ] = $_[0]; 131f2e35a3aSmrg} 132f2e35a3aSmrg 133f2e35a3aSmrgsub show_reply($) { 134f2e35a3aSmrg my $reply = shift; 135f2e35a3aSmrg printf "data={%s}", &visible($reply); 136f2e35a3aSmrg} 137f2e35a3aSmrg 138f2e35a3aSmrgsub finish_query($) { 139f2e35a3aSmrg return unless (@query_params); 140f2e35a3aSmrg 141f2e35a3aSmrg my $reply; 142f2e35a3aSmrg my $n; 143f2e35a3aSmrg my $st = $opt_8 ? qr/\x9c/ : ( $opt_s ? qr/\007/ : qr/\x1b\\/ ); 144f2e35a3aSmrg my $osc = $opt_8 ? qr/\x9d/ : qr/\x1b]/; 145f2e35a3aSmrg my $match = qr/${osc}.*${st}/; 146f2e35a3aSmrg 147f2e35a3aSmrg my $params = join( ";", @query_params ); 148f2e35a3aSmrg $params =~ s/\d+/?/g; 149f2e35a3aSmrg $params = sprintf( "%d;%s", $query_params[0], $params ); 150f2e35a3aSmrg $reply = &get_reply( $OSC . $params . $ST ); 151f2e35a3aSmrg 152f2e35a3aSmrg printf "query{%s}", &visible($params); 153f2e35a3aSmrg 154f2e35a3aSmrg if ( defined $reply ) { 155f2e35a3aSmrg printf " len=%2d ", length($reply); 156f2e35a3aSmrg if ( $reply =~ /${match}/ ) { 157f2e35a3aSmrg my @chunks = split /${st}${osc}/, $reply; 158f2e35a3aSmrg printf "\n" if ( $#chunks > 0 ); 159f2e35a3aSmrg for my $c ( 0 .. $#chunks ) { 160f2e35a3aSmrg $chunks[$c] =~ s/^${osc}// if ( $c == 0 ); 161f2e35a3aSmrg $chunks[$c] =~ s/${st}$// if ( $c == $#chunks ); 162f2e35a3aSmrg my $param = $chunks[$c]; 163f2e35a3aSmrg $param =~ s/^(\d+);.*/$1/; 164f2e35a3aSmrg $param = -1 unless ( $param =~ /^\d+$/ ); 165f2e35a3aSmrg $chunks[$c] =~ s/^\d+;//; 166f2e35a3aSmrg printf "\t%d: ", $param if ( $#chunks > 0 ); 167f2e35a3aSmrg &show_reply( $chunks[$c] ); 168f2e35a3aSmrg printf " %s", $color_names[ $param - 10 ] 169f2e35a3aSmrg if ( ( $param >= 10 ) 170f2e35a3aSmrg and ( ( $param - 10 ) <= $#color_names ) ); 171f2e35a3aSmrg printf "\n" if ( $c < $#chunks ); 172f2e35a3aSmrg } 173f2e35a3aSmrg } 174f2e35a3aSmrg else { 175f2e35a3aSmrg printf "? "; 176f2e35a3aSmrg &show_reply($reply); 177f2e35a3aSmrg } 178f2e35a3aSmrg } 179f2e35a3aSmrg printf "\n"; 180f2e35a3aSmrg} 181f2e35a3aSmrg 182f2e35a3aSmrgsub query_color($) { 183f2e35a3aSmrg my $param = shift; 184f2e35a3aSmrg 185f2e35a3aSmrg &begin_query unless $opt_q; 186f2e35a3aSmrg if ( $#query_params >= 0 187f2e35a3aSmrg and ( $param != $query_params[$#query_params] + 1 ) ) 188f2e35a3aSmrg { 189f2e35a3aSmrg &finish_query; 190f2e35a3aSmrg &begin_query; 191f2e35a3aSmrg } 192f2e35a3aSmrg &add_param($param); 193f2e35a3aSmrg &finish_query unless $opt_q; 194f2e35a3aSmrg} 195f2e35a3aSmrg 196f2e35a3aSmrgsub query_colors($$) { 197f2e35a3aSmrg my $lo = shift; 198f2e35a3aSmrg my $hi = shift; 199f2e35a3aSmrg my $n; 200f2e35a3aSmrg for ( $n = $lo ; $n <= $hi ; ++$n ) { 201f2e35a3aSmrg &query_color($n); 202f2e35a3aSmrg } 203f2e35a3aSmrg} 204f2e35a3aSmrg 205f2e35a3aSmrgprintf "\x1b G" if ($opt_8); 206f2e35a3aSmrg 207f2e35a3aSmrg&begin_query if ($opt_q); 208f2e35a3aSmrg 209f2e35a3aSmrgif ( $#ARGV >= 0 ) { 210f2e35a3aSmrg while ( $#ARGV >= 0 ) { 211f2e35a3aSmrg if ( $ARGV[0] =~ /-/ ) { 212f2e35a3aSmrg my @args = split /-/, $ARGV[0]; 213f2e35a3aSmrg &query_colors( $args[0], $args[1] ); 214f2e35a3aSmrg } 215f2e35a3aSmrg else { 216f2e35a3aSmrg &query_colors( $ARGV[0], $ARGV[0] ); 217f2e35a3aSmrg } 218f2e35a3aSmrg shift @ARGV; 219f2e35a3aSmrg } 220f2e35a3aSmrg} 221f2e35a3aSmrgelse { 222f2e35a3aSmrg &query_colors( 10, 19 ); 223f2e35a3aSmrg} 224f2e35a3aSmrg 225f2e35a3aSmrg&finish_query if ($opt_q); 226f2e35a3aSmrg 227f2e35a3aSmrgprintf "\x1b F" if ($opt_8); 228f2e35a3aSmrg 229f2e35a3aSmrg1; 230