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