1e0a2b6dfSmrg#!/usr/bin/env perl
204b94745Smrg# $XTermId: tcapquery.pl,v 1.29 2019/04/29 23:27:57 tom Exp $
320d2c4d2Smrg# -----------------------------------------------------------------------------
420d2c4d2Smrg# this file is part of xterm
5d522f475Smrg#
6f2e35a3aSmrg# Copyright 2004-2018,2019 by Thomas E. Dickey
7913cc679Smrg#
820d2c4d2Smrg#                         All Rights Reserved
9913cc679Smrg#
1020d2c4d2Smrg# Permission is hereby granted, free of charge, to any person obtaining a
1120d2c4d2Smrg# copy of this software and associated documentation files (the
1220d2c4d2Smrg# "Software"), to deal in the Software without restriction, including
1320d2c4d2Smrg# without limitation the rights to use, copy, modify, merge, publish,
1420d2c4d2Smrg# distribute, sublicense, and/or sell copies of the Software, and to
1520d2c4d2Smrg# permit persons to whom the Software is furnished to do so, subject to
1620d2c4d2Smrg# the following conditions:
17913cc679Smrg#
1820d2c4d2Smrg# The above copyright notice and this permission notice shall be included
1920d2c4d2Smrg# in all copies or substantial portions of the Software.
20913cc679Smrg#
2120d2c4d2Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2220d2c4d2Smrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2320d2c4d2Smrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2420d2c4d2Smrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
2520d2c4d2Smrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2620d2c4d2Smrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2720d2c4d2Smrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28913cc679Smrg#
2920d2c4d2Smrg# Except as contained in this notice, the name(s) of the above copyright
3020d2c4d2Smrg# holders shall not be used in advertising or otherwise to promote the
3120d2c4d2Smrg# sale, use or other dealings in this Software without prior written
3220d2c4d2Smrg# authorization.
3320d2c4d2Smrg# -----------------------------------------------------------------------------
34d522f475Smrg# Test the tcap-query option of xterm.
35d522f475Smrg
36d522f475Smrguse strict;
37e0a2b6dfSmrguse warnings;
38d522f475Smrg
39d522f475Smrguse Getopt::Std;
40d522f475Smrguse IO::Handle;
41d522f475Smrg
42913cc679Smrgour (
43913cc679Smrg    $opt_a, $opt_b, $opt_c, $opt_e, $opt_f, $opt_i,
44f2e35a3aSmrg    $opt_k, $opt_m, $opt_q, $opt_t, $opt_x, $opt_X
45913cc679Smrg);
46f2e35a3aSmrg
47f2e35a3aSmrgour @query_params;
48f2e35a3aSmrgour @query_result;
49f2e35a3aSmrg
50f2e35a3aSmrg$Getopt::Std::STANDARD_HELP_VERSION = 1;
51f2e35a3aSmrg&getopts('abcefikmqt:x:X') || die(
52913cc679Smrg    "Usage: $0 [options]\n
53d522f475SmrgOptions:\n
5420d2c4d2Smrg  -a      (same as -c -e -f -k -m)
5520d2c4d2Smrg  -b      use both terminfo and termcap (default is termcap)
5620d2c4d2Smrg  -c      cursor-keys
5720d2c4d2Smrg  -e      editing keypad-keys
5820d2c4d2Smrg  -f      function-keys
5920d2c4d2Smrg  -i      use terminfo rather than termcap names
6020d2c4d2Smrg  -k      numeric keypad-keys
6120d2c4d2Smrg  -m      miscellaneous (none of -c, -e, -f, -k)
62f2e35a3aSmrg  -q      quicker results by merging queries
6320d2c4d2Smrg  -t NAME use given NAME for \$TERM, set that in xterm's tcap keyboard
6420d2c4d2Smrg  -x KEY  extended cursor/editing key (terminfo only)
6520d2c4d2Smrg  -X      test all extended cursor- and/or editing-keys (terminfo)
66913cc679Smrg"
67913cc679Smrg);
68913cc679Smrg
69913cc679Smrgif (
70913cc679Smrg    not(   defined($opt_c)
71913cc679Smrg        or defined($opt_e)
72913cc679Smrg        or defined($opt_f)
73913cc679Smrg        or defined($opt_k)
74913cc679Smrg        or defined($opt_m)
75913cc679Smrg        or defined($opt_x) )
76913cc679Smrg  )
77913cc679Smrg{
78913cc679Smrg    $opt_a = 1;
79d522f475Smrg}
80d522f475Smrg
8120d2c4d2Smrgsub no_reply($) {
82913cc679Smrg    open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n");
83913cc679Smrg    autoflush TTY 1;
84913cc679Smrg    my $old = `stty -g`;
85913cc679Smrg    system "stty raw -echo min 0 time 5";
86913cc679Smrg
87913cc679Smrg    print TTY @_;
88913cc679Smrg    close TTY;
89913cc679Smrg    system "stty $old";
9020d2c4d2Smrg}
9120d2c4d2Smrg
92d522f475Smrgsub get_reply($) {
93913cc679Smrg    open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n");
94913cc679Smrg    autoflush TTY 1;
95913cc679Smrg    my $old = `stty -g`;
96913cc679Smrg    system "stty raw -echo min 0 time 5";
97913cc679Smrg
98913cc679Smrg    print TTY @_;
99913cc679Smrg    my $reply = <TTY>;
100913cc679Smrg    close TTY;
101913cc679Smrg    system "stty $old";
102913cc679Smrg    if ( defined $reply ) {
103913cc679Smrg        die("^C received\n") if ( "$reply" eq "\003" );
104913cc679Smrg    }
105913cc679Smrg    return $reply;
106d522f475Smrg}
107d522f475Smrg
108d522f475Smrgsub hexified($) {
109913cc679Smrg    my $value  = $_[0];
110913cc679Smrg    my $result = "";
111913cc679Smrg    my $n;
112913cc679Smrg
113913cc679Smrg    for ( $n = 0 ; $n < length($value) ; ++$n ) {
114913cc679Smrg        $result .= sprintf( "%02X", ord substr( $value, $n, 1 ) );
115913cc679Smrg    }
116913cc679Smrg    return $result;
117d522f475Smrg}
118d522f475Smrg
11920d2c4d2Smrgsub modify_tcap($) {
120913cc679Smrg    my $name  = $_[0];
121f2e35a3aSmrg    my $param = &hexified($name);
122f2e35a3aSmrg    &no_reply( "\x1bP+p" . $param . "\x1b\\" );
12320d2c4d2Smrg}
12420d2c4d2Smrg
125f2e35a3aSmrgsub begin_query() {
126f2e35a3aSmrg    @query_params = ();
127f2e35a3aSmrg}
128f2e35a3aSmrg
129f2e35a3aSmrgsub add_param($) {
130f2e35a3aSmrg    $query_params[ $#query_params + 1 ] = &hexified( $_[0] );
131f2e35a3aSmrg}
132f2e35a3aSmrg
133f2e35a3aSmrgsub finish_query() {
134f2e35a3aSmrg    my $reply = &get_reply( "\x1bP+q" . join( ';', @query_params ) . "\x1b\\" );
135913cc679Smrg
136913cc679Smrg    return unless defined $reply;
137913cc679Smrg    if ( $reply =~ /\x1bP1\+r[[:xdigit:]]+=[[:xdigit:]]*.*/ ) {
138913cc679Smrg        my $n;
139913cc679Smrg
140f2e35a3aSmrg        $reply =~ s/^\x1bP1\+r//;
141f2e35a3aSmrg        $reply =~ s/\x1b\\//;
142913cc679Smrg
143913cc679Smrg        my $result = "";
144f2e35a3aSmrg        my $count  = 0;
145f2e35a3aSmrg        my $state  = 0;
146f2e35a3aSmrg        my $error  = "?";
147f2e35a3aSmrg        for ( $n = 0 ; $n < length($reply) ; ) {
148f2e35a3aSmrg            my $c = substr( $reply, $n, 1 );
149913cc679Smrg
150f2e35a3aSmrg            if ( $c eq ';' ) {
151f2e35a3aSmrg                $n += 1;
152f2e35a3aSmrg                printf "%d%s\t%s\n", $count, $error, $result
153f2e35a3aSmrg                  if ( $result ne "" );
154f2e35a3aSmrg                $result = "";
155f2e35a3aSmrg                $state  = 0;
156f2e35a3aSmrg                $error  = "?";
157f2e35a3aSmrg                $count++;
158f2e35a3aSmrg            }
159f2e35a3aSmrg            elsif ( $c eq '=' ) {
160f2e35a3aSmrg                $error = ""
161f2e35a3aSmrg                  if (  $count <= $#query_params
162f2e35a3aSmrg                    and &hexified($result) eq $query_params[$count] );
163f2e35a3aSmrg                $n += 1;
164f2e35a3aSmrg                $result .= $c;
165f2e35a3aSmrg                $state = 1;
166f2e35a3aSmrg            }
167f2e35a3aSmrg            elsif ( $c =~ /[[:punct:]]/ ) {
168913cc679Smrg                $n += 1;
169913cc679Smrg                $result .= $c;
170913cc679Smrg            }
171913cc679Smrg            else {
172f2e35a3aSmrg                my $k = hex substr( $reply, $n, 2 );
173913cc679Smrg                if ( $k == 0x1b ) {
174913cc679Smrg                    $result .= "\\E";
175913cc679Smrg                }
176913cc679Smrg                elsif ( $k == 0x7f ) {
177913cc679Smrg                    $result .= "^?";
178913cc679Smrg                }
179913cc679Smrg                elsif ( $k == 32 ) {
180913cc679Smrg                    $result .= "\\s";
181913cc679Smrg                }
182913cc679Smrg                elsif ( $k < 32 ) {
183913cc679Smrg                    $result .= sprintf( "^%c", $k + 64 );
184913cc679Smrg                }
185913cc679Smrg                elsif ( $k > 128 ) {
186913cc679Smrg                    $result .= sprintf( "\\%03o", $k );
187913cc679Smrg                }
188913cc679Smrg                else {
189913cc679Smrg                    $result .= chr($k);
190913cc679Smrg                }
191913cc679Smrg                $n += 2;
192913cc679Smrg            }
193913cc679Smrg        }
194f2e35a3aSmrg        printf "%d%s\t%s\n", $count, $error, $result if ( $result ne "" );
195913cc679Smrg    }
196d522f475Smrg}
197d522f475Smrg
198f2e35a3aSmrgsub query_tcap($$) {
199f2e35a3aSmrg    my $tcap  = shift;
200f2e35a3aSmrg    my $tinfo = shift;
201f2e35a3aSmrg
202f2e35a3aSmrg    &begin_query unless ($opt_q);
203f2e35a3aSmrg    &add_param($tcap)  if ( $opt_b or not $opt_i );
204f2e35a3aSmrg    &add_param($tinfo) if ( $opt_b or $opt_i );
205f2e35a3aSmrg    &finish_query unless ($opt_q);
206f2e35a3aSmrg}
207f2e35a3aSmrg
20820d2c4d2Smrg# extended-keys are a feature of ncurses 5.0 and later
209d522f475Smrgsub query_extended($) {
210913cc679Smrg    my $name = $_[0];
211913cc679Smrg    my $n;
212d522f475Smrg
213913cc679Smrg    $name = "k" . $name if ( $name !~ /^k/ );
214d522f475Smrg
215913cc679Smrg    for ( $n = 2 ; $n <= 7 ; ++$n ) {
216913cc679Smrg        my $test = $name;
217913cc679Smrg        $test = $test . $n if ( $n > 2 );
218f2e35a3aSmrg        &query_tcap( $name, $test );
219913cc679Smrg    }
220d522f475Smrg}
221d522f475Smrg
222f2e35a3aSmrg&begin_query if ($opt_q);
223f2e35a3aSmrg
224f2e35a3aSmrg&query_tcap( "TN", "name" );
22520d2c4d2Smrgif ( defined($opt_t) ) {
226913cc679Smrg    printf "Setting TERM=%s\n", $opt_t;
227f2e35a3aSmrg    &modify_tcap($opt_t);
22820d2c4d2Smrg}
22920d2c4d2Smrg
230d522f475Smrg# See xtermcapKeycode()
231d522f475Smrgif ( defined($opt_a) || defined($opt_c) ) {
232f2e35a3aSmrg    &query_tcap( "ku", "kcuu1" );
233f2e35a3aSmrg    &query_tcap( "kd", "kcud1" );
234f2e35a3aSmrg    &query_tcap( "kr", "kcuf1" );
235f2e35a3aSmrg    &query_tcap( "kl", "kcub1" );
236f2e35a3aSmrg
237f2e35a3aSmrg    &query_tcap( "kF", "kind" );
238f2e35a3aSmrg    &query_tcap( "kR", "kri" );
239f2e35a3aSmrg    &query_tcap( "%i", "kRIT" );
240f2e35a3aSmrg    &query_tcap( "#4", "kLFT" );
241d522f475Smrg}
242d522f475Smrg
243d522f475Smrgif ( defined($opt_a) || defined($opt_e) ) {
244f2e35a3aSmrg    &query_tcap( "kD", "kdch1" );
245f2e35a3aSmrg    &query_tcap( "kI", "kich1" );
246d522f475Smrg
247f2e35a3aSmrg    &query_tcap( "kh",  "khome" );
248f2e35a3aSmrg    &query_tcap( "\@7", "kend" );
249f2e35a3aSmrg    &query_tcap( "#2",  "kHOM" );
250f2e35a3aSmrg    &query_tcap( "*7",  "kEND" );
251d522f475Smrg
252f2e35a3aSmrg    &query_tcap( "*6",  "kslt" );
253f2e35a3aSmrg    &query_tcap( "#6",  "kSLT" );
254f2e35a3aSmrg    &query_tcap( "\@0", "kfnd" );
255f2e35a3aSmrg    &query_tcap( "*0",  "kFND" );
256d522f475Smrg
257f2e35a3aSmrg    &query_tcap( "kN", "knp" );
258f2e35a3aSmrg    &query_tcap( "kP", "kpp" );
25920d2c4d2Smrg
260f2e35a3aSmrg    &query_tcap( "%c", "kNXT" );
261f2e35a3aSmrg    &query_tcap( "%e", "kPRV" );
262d522f475Smrg}
263d522f475Smrg
264d522f475Smrgif ( defined($opt_a) || defined($opt_f) ) {
265f2e35a3aSmrg    &query_tcap( "k1", "kf1" );
266f2e35a3aSmrg    &query_tcap( "k2", "kf2" );
267f2e35a3aSmrg    &query_tcap( "k3", "kf3" );
268f2e35a3aSmrg    &query_tcap( "k4", "kf4" );
269f2e35a3aSmrg    &query_tcap( "k5", "kf5" );
270f2e35a3aSmrg    &query_tcap( "k6", "kf6" );
271f2e35a3aSmrg    &query_tcap( "k7", "kf7" );
272f2e35a3aSmrg    &query_tcap( "k8", "kf8" );
273f2e35a3aSmrg    &query_tcap( "k9", "kf9" );
274f2e35a3aSmrg    &query_tcap( "k;", "kf10" );
275f2e35a3aSmrg    &query_tcap( "F1", "kf11" );
276f2e35a3aSmrg    &query_tcap( "F2", "kf12" );
277f2e35a3aSmrg    &query_tcap( "F3", "kf13" );
278f2e35a3aSmrg    &query_tcap( "F4", "kf14" );
279f2e35a3aSmrg    &query_tcap( "F5", "kf15" );
280f2e35a3aSmrg    &query_tcap( "F6", "kf16" );
281f2e35a3aSmrg    &query_tcap( "F7", "kf17" );
282f2e35a3aSmrg    &query_tcap( "F8", "kf18" );
283f2e35a3aSmrg    &query_tcap( "F9", "kf19" );
284f2e35a3aSmrg    &query_tcap( "FA", "kf20" );
285f2e35a3aSmrg    &query_tcap( "FB", "kf21" );
286f2e35a3aSmrg    &query_tcap( "FC", "kf22" );
287f2e35a3aSmrg    &query_tcap( "FD", "kf23" );
288f2e35a3aSmrg    &query_tcap( "FE", "kf24" );
289f2e35a3aSmrg    &query_tcap( "FF", "kf25" );
290f2e35a3aSmrg    &query_tcap( "FG", "kf26" );
291f2e35a3aSmrg    &query_tcap( "FH", "kf27" );
292f2e35a3aSmrg    &query_tcap( "FI", "kf28" );
293f2e35a3aSmrg    &query_tcap( "FJ", "kf29" );
294f2e35a3aSmrg    &query_tcap( "FK", "kf30" );
295f2e35a3aSmrg    &query_tcap( "FL", "kf31" );
296f2e35a3aSmrg    &query_tcap( "FM", "kf32" );
297f2e35a3aSmrg    &query_tcap( "FN", "kf33" );
298f2e35a3aSmrg    &query_tcap( "FO", "kf34" );
299f2e35a3aSmrg    &query_tcap( "FP", "kf35" );
300f2e35a3aSmrg    &query_tcap( "FQ", "kf36" );
301f2e35a3aSmrg    &query_tcap( "FR", "kf37" );
302f2e35a3aSmrg    &query_tcap( "FS", "kf38" );
303f2e35a3aSmrg    &query_tcap( "FT", "kf39" );
304f2e35a3aSmrg    &query_tcap( "FU", "kf40" );
305f2e35a3aSmrg    &query_tcap( "FV", "kf41" );
306f2e35a3aSmrg    &query_tcap( "FW", "kf42" );
307f2e35a3aSmrg    &query_tcap( "FX", "kf43" );
308f2e35a3aSmrg    &query_tcap( "FY", "kf44" );
309f2e35a3aSmrg    &query_tcap( "FZ", "kf45" );
310f2e35a3aSmrg    &query_tcap( "Fa", "kf46" );
311f2e35a3aSmrg    &query_tcap( "Fb", "kf47" );
312f2e35a3aSmrg    &query_tcap( "Fc", "kf48" );
313f2e35a3aSmrg    &query_tcap( "Fd", "kf49" );
314f2e35a3aSmrg    &query_tcap( "Fe", "kf50" );
315f2e35a3aSmrg    &query_tcap( "Ff", "kf51" );
316f2e35a3aSmrg    &query_tcap( "Fg", "kf52" );
317f2e35a3aSmrg    &query_tcap( "Fh", "kf53" );
318f2e35a3aSmrg    &query_tcap( "Fi", "kf54" );
319f2e35a3aSmrg    &query_tcap( "Fj", "kf55" );
320f2e35a3aSmrg    &query_tcap( "Fk", "kf56" );
321f2e35a3aSmrg    &query_tcap( "Fl", "kf57" );
322f2e35a3aSmrg    &query_tcap( "Fm", "kf58" );
323f2e35a3aSmrg    &query_tcap( "Fn", "kf59" );
324f2e35a3aSmrg    &query_tcap( "Fo", "kf60" );
325f2e35a3aSmrg    &query_tcap( "Fp", "kf61" );
326f2e35a3aSmrg    &query_tcap( "Fq", "kf62" );
327f2e35a3aSmrg    &query_tcap( "Fr", "kf63" );
328d522f475Smrg}
329d522f475Smrg
330d522f475Smrgif ( defined($opt_a) || defined($opt_k) ) {
331f2e35a3aSmrg    &query_tcap( "K1", "ka1" );
332f2e35a3aSmrg    &query_tcap( "K3", "ka3" );
333f2e35a3aSmrg    &query_tcap( "K4", "kc1" );
334f2e35a3aSmrg    &query_tcap( "K5", "kc3" );
335d522f475Smrg}
336d522f475Smrg
337d522f475Smrgif ( defined($opt_a) || defined($opt_m) ) {
338f2e35a3aSmrg    &query_tcap( "kB", "kcbt" );
339f2e35a3aSmrg    &query_tcap( "kC", "kclr" );
340f2e35a3aSmrg    &query_tcap( "&8", "kund" );
341d522f475Smrg
342f2e35a3aSmrg    &query_tcap( "kb", "kbs" );
343d522f475Smrg
344f2e35a3aSmrg    &query_tcap( "%1", "khlp" );
345f2e35a3aSmrg    &query_tcap( "#1", "kHLP" );
346d522f475Smrg
347f2e35a3aSmrg    &query_tcap( "Co", "colors" );
348f2e35a3aSmrg    &query_tcap( "Co", "RGB" ) if ($opt_i);
349d522f475Smrg}
350d522f475Smrg
351913cc679Smrgif ( defined($opt_x) ) {
352f2e35a3aSmrg    &query_extended($opt_x);
353d522f475Smrg}
35420d2c4d2Smrg
355913cc679Smrgif ( defined($opt_X) ) {
356913cc679Smrg    if ( defined($opt_c) ) {
357f2e35a3aSmrg        &query_extended("DN");
358f2e35a3aSmrg        &query_extended("UP");
359f2e35a3aSmrg        &query_extended("LFT");
360f2e35a3aSmrg        &query_extended("RIT");
361913cc679Smrg    }
362913cc679Smrg    if ( defined($opt_e) ) {
363f2e35a3aSmrg        &query_extended("DC");
364f2e35a3aSmrg        &query_extended("END");
365f2e35a3aSmrg        &query_extended("HOM");
366f2e35a3aSmrg        &query_extended("IC");
367f2e35a3aSmrg        &query_extended("NXT");
368f2e35a3aSmrg        &query_extended("PRV");
369913cc679Smrg    }
37020d2c4d2Smrg}
371f2e35a3aSmrg
372f2e35a3aSmrg&finish_query if ($opt_q);
373f2e35a3aSmrg
374f2e35a3aSmrg1;
375