1f2e35a3aSmrg#!/usr/bin/env perl
2f2e35a3aSmrg# $XTermId: mouse-codes,v 1.7 2020/12/13 15:07:02 tom Exp $
3f2e35a3aSmrg# -----------------------------------------------------------------------------
4f2e35a3aSmrg# this file is part of xterm
5f2e35a3aSmrg#
6f2e35a3aSmrg# Copyright 2018-2019,2020 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# Imitate xterm's BtnCode() function, to enumerate the possible inputs (button,
35f2e35a3aSmrg# event state) versus output (xterm mouse-code).
36f2e35a3aSmrguse strict;
37f2e35a3aSmrguse warnings;
38f2e35a3aSmrg
39f2e35a3aSmrguse Getopt::Std;
40f2e35a3aSmrg
41f2e35a3aSmrgour ( $opt_b, $opt_i, $opt_x );
42f2e35a3aSmrg
43f2e35a3aSmrg# Typically,
44f2e35a3aSmrg# -	Buttons 1, 2, and 3 are left-to-right assignments on a 3-button mouse.
45f2e35a3aSmrg# -	Buttons 4 and 5 are (by convention) assigned to a wheel mouse's
46f2e35a3aSmrg#	up/down events.
47f2e35a3aSmrg# -	Buttons 6 and 7 may happen to work, e.g., as left/right events from a
48f2e35a3aSmrg#	tiltable wheel mouse.  There is no explicit support for these (there
49f2e35a3aSmrg#	are no related symbols in Xt), so it is not possible to use them in the
50f2e35a3aSmrg#	translations resource.
51f2e35a3aSmrgour $maxbutton = 7;
52f2e35a3aSmrg
53f2e35a3aSmrg# xterm uses code 3 internally for release-events.
54f2e35a3aSmrgsub ButtonName($) {
55f2e35a3aSmrg    my $code   = shift;
56f2e35a3aSmrg    my $result = "";
57f2e35a3aSmrg    if ( $code < 0 ) {
58f2e35a3aSmrg        $result = "release";
59f2e35a3aSmrg    }
60f2e35a3aSmrg    else {
61f2e35a3aSmrg        $result = sprintf "Button%d", ( $code > 3 ) ? $code : ( $code + 1 );
62f2e35a3aSmrg    }
63f2e35a3aSmrg    return $result;
64f2e35a3aSmrg}
65f2e35a3aSmrg
66f2e35a3aSmrg# Combine the modifier state as bits:
67f2e35a3aSmrg#  shift key   -> 1
68f2e35a3aSmrg#  meta key    -> 2 (Mod1 came from X11R1, but was adapted from X10)
69f2e35a3aSmrg#  control key -> 4
70f2e35a3aSmrgour $maxstates = 7;
71f2e35a3aSmrg
72f2e35a3aSmrgsub KeyState($) {
73f2e35a3aSmrg    my $mask   = shift;
74f2e35a3aSmrg    my $result = "";
75f2e35a3aSmrg    $result .= " + shift"   if ( ( $mask & 1 ) != 0 );
76f2e35a3aSmrg    $result .= " + meta"    if ( ( $mask & 2 ) != 0 );
77f2e35a3aSmrg    $result .= " + control" if ( ( $mask & 4 ) != 0 );
78f2e35a3aSmrg    return $result;
79f2e35a3aSmrg}
80f2e35a3aSmrg
81f2e35a3aSmrgsub Motion($) {
82f2e35a3aSmrg    my $code   = shift;
83f2e35a3aSmrg    my $result = "";
84f2e35a3aSmrg    $result = " + motion" if ( $code != 0 );
85f2e35a3aSmrg    return $result;
86f2e35a3aSmrg}
87f2e35a3aSmrg
88f2e35a3aSmrgsub report() {
89f2e35a3aSmrg    my $button;
90f2e35a3aSmrg    my $states;
91f2e35a3aSmrg    my $motion;
92f2e35a3aSmrg    my %encoded;
93f2e35a3aSmrg    my %reports;
94f2e35a3aSmrg    for $states ( 0 .. $maxstates ) {
95f2e35a3aSmrg        for $motion ( 0 .. 1 ) {
96f2e35a3aSmrg            for $button ( -1 .. $maxbutton ) {
97f2e35a3aSmrg                next if ( $button == 3 );
98f2e35a3aSmrg                my $result = ( 32 + ( $states << 2 ) );
99f2e35a3aSmrg                $result += 32 if ( $motion != 0 );
100f2e35a3aSmrg                if ( $button < 0 ) {
101f2e35a3aSmrg                    $result += 3;
102f2e35a3aSmrg                }
103f2e35a3aSmrg                else {
104f2e35a3aSmrg                    $result += $button & 3;
105f2e35a3aSmrg                    if ( $button & 4 ) {
106f2e35a3aSmrg                        $result += 64;
107f2e35a3aSmrg                    }
108f2e35a3aSmrg                    if ( $button & 8 ) {
109f2e35a3aSmrg                        $result += 128;
110f2e35a3aSmrg                    }
111f2e35a3aSmrg                }
112f2e35a3aSmrg                my $code   = sprintf "%3d",    $result;
113f2e35a3aSmrg                my $report = sprintf "%s%s%s", &ButtonName($button),
114f2e35a3aSmrg                  &KeyState($states), &Motion($motion);
115f2e35a3aSmrg                if ( defined $encoded{$code} ) {
116f2e35a3aSmrg                    printf "OOPS %s ->%s versus %s\n", $code, $report,
117f2e35a3aSmrg                      $encoded{$code};
118f2e35a3aSmrg                }
119f2e35a3aSmrg                elsif ( $result > 255 and not defined $opt_x ) {
120f2e35a3aSmrg                    printf "OOPS %s ->%s\n", $code, $report;
121f2e35a3aSmrg                }
122f2e35a3aSmrg                $encoded{$code}   = $report;
123f2e35a3aSmrg                $reports{$report} = $result;
124f2e35a3aSmrg            }
125f2e35a3aSmrg        }
126f2e35a3aSmrg    }
127f2e35a3aSmrg    if ($opt_i) {
128f2e35a3aSmrg        foreach my $report ( sort keys %reports ) {
129f2e35a3aSmrg            printf "%s = %s\n", $report, $reports{$report};
130f2e35a3aSmrg        }
131f2e35a3aSmrg    }
132f2e35a3aSmrg    else {
133f2e35a3aSmrg        foreach my $code ( sort keys %encoded ) {
134f2e35a3aSmrg            printf "%s = %s\n", $code, $encoded{$code};
135f2e35a3aSmrg        }
136f2e35a3aSmrg    }
137f2e35a3aSmrg}
138f2e35a3aSmrg
139f2e35a3aSmrgsub main::HELP_MESSAGE() {
140f2e35a3aSmrg    printf STDERR <<EOF
141f2e35a3aSmrgUsage: $0 [options]
142f2e35a3aSmrg
143f2e35a3aSmrgOptions:
144f2e35a3aSmrg	-b NUM	set the number of buttons (default: 7)
145f2e35a3aSmrg	-i	invert the report to show code for each combination
146f2e35a3aSmrg	-x	eliminate 1-byte limit for codes
147f2e35a3aSmrgEOF
148f2e35a3aSmrg      ;
149f2e35a3aSmrg    exit 1;
150f2e35a3aSmrg}
151f2e35a3aSmrg$Getopt::Std::STANDARD_HELP_VERSION = 1;
152f2e35a3aSmrg&getopts('b:ix') || &main::HELP_MESSAGE;
153f2e35a3aSmrg$maxbutton = $opt_b if ( defined $opt_b );
154f2e35a3aSmrg&main::HELP_MESSAGE if ( $maxbutton !~ /^\d+$/ );
155f2e35a3aSmrg$#ARGV < 0 || &main::HELP_MESSAGE;
156f2e35a3aSmrg
157f2e35a3aSmrg&report;
158f2e35a3aSmrg
159f2e35a3aSmrg1;
160