1d522f475Smrg#! /usr/bin/perl -w 204b94745Smrg# $XTermId: gen-pc-fkeys.pl,v 1.22 2007/11/30 23:03:55 tom Exp $ 320d2c4d2Smrg# ----------------------------------------------------------------------------- 420d2c4d2Smrg# this file is part of xterm 520d2c4d2Smrg# 620d2c4d2Smrg# Copyright 2004-2005,2007 by Thomas E. Dickey 720d2c4d2Smrg# 820d2c4d2Smrg# All Rights Reserved 920d2c4d2Smrg# 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: 1720d2c4d2Smrg# 1820d2c4d2Smrg# The above copyright notice and this permission notice shall be included 1920d2c4d2Smrg# in all copies or substantial portions of the Software. 2020d2c4d2Smrg# 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. 2820d2c4d2Smrg# 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# 35d522f475Smrg# Construct a list of function-key definitions corresponding to xterm's 36d522f475Smrg# Sun/PC keyboard. This uses ncurses' infocmp to obtain the strings (including 37d522f475Smrg# extensions) to modify (and verify). 38d522f475Smrguse strict; 39d522f475Smrg 40d522f475Smrgmy($max_modifier, $terminfo); 41d522f475Smrgmy(@old_fkeys, $opt_fkeys, $min_fkeys, $max_fkeys); 42d522f475Smrgmy(%old_ckeys, $opt_ckeys, $min_ckeys, $max_ckeys); 43d522f475Smrgmy(%old_ekeys, $opt_ekeys, $min_ekeys, $max_ekeys); 44d522f475Smrg 45d522f475Smrgmy(@ckey_names); 46d522f475Smrg@ckey_names = ( 47d522f475Smrg 'kcud1', 'kcub1', 'kcuf1', 'kcuu1', # 1 = no modifiers 48d522f475Smrg 'kDN', 'kLFT', 'kRIT', 'kUP', # 2 = shift 49d522f475Smrg # make_ckey_names() repeats this row, appending the modifier code 50d522f475Smrg ); 51d522f475Smrgmy %ckey_names; 52d522f475Smrgmy(@ckey_known); 53d522f475Smrg@ckey_known = ( 54d522f475Smrg 'kind', 'kLFT', 'kRIT', 'kri', # 2 = shift (standard) 55d522f475Smrg ); 56d522f475Smrg 57d522f475Smrgmy(@ekey_names); 58d522f475Smrg@ekey_names = ( 59d522f475Smrg 'khome', 'kend', 'knp', 'kpp', 'kdch1', 'kich1', # 1 = no modifiers 60d522f475Smrg 'kHOM', 'kEND', 'kNXT', 'kPRV', 'kDC', 'kIC', # 2 = shift 61d522f475Smrg # make_ekey_names() repeats this row, appending the modifier code 62d522f475Smrg); 63d522f475Smrgmy %ekey_names; 64d522f475Smrg 65d522f475Smrg$min_fkeys=12; # the number of "real" function keys on your keyboard 66d522f475Smrg$max_fkeys=64; # the number of function-keys terminfo can support 67d522f475Smrg$max_modifier=8; # modifier 1 + (1=shift, 2=alt, 4=control 8=meta) 68d522f475Smrg 69d522f475Smrg$min_ckeys=4; # the number of "real" cursor keys on your keyboard 70d522f475Smrg$max_ckeys=($min_ckeys * ($max_modifier - 1)); 71d522f475Smrg 72d522f475Smrg$min_ekeys=6; # the number of "real" editing keys on your keyboard 73d522f475Smrg$max_ekeys=($min_ekeys * ($max_modifier - 1)); 74d522f475Smrg 75d522f475Smrg$opt_ckeys=2; # xterm's modifyCursorKeys resource 76d522f475Smrg$opt_ekeys=2; # xterm's modifyCursorKeys resource 77d522f475Smrg$opt_fkeys=2; # xterm's modifyFunctionKeys resource 78d522f475Smrg$terminfo="xterm-new"; # the terminfo entry to use 79d522f475Smrg 80d522f475Smrg# apply the given modifier to the terminfo string, return the result 81d522f475Smrgsub modify_fkey($$$) { 82d522f475Smrg my $code = $_[0]; 83d522f475Smrg my $text = $_[1]; 84d522f475Smrg my $opts = $_[2]; 85d522f475Smrg if (not defined($text)) { 86d522f475Smrg $text = ""; 87d522f475Smrg } elsif ($code != 1) { 88d522f475Smrg $text =~ s/\\EO/\\E\[/ if ($opts >= 1); 89d522f475Smrg 90d522f475Smrg my $piece = substr $text, 0, length ($text) - 1; 91d522f475Smrg my $final = substr $text, length ($text) - 1; 92d522f475Smrg my $check = substr $piece, length ($piece) - 1; 93d522f475Smrg if ($check =~ /[0-9]/) { 94d522f475Smrg $code = ";" . $code; 95d522f475Smrg } elsif ( $check =~ /\[/ and $opts >= 2) { 96d522f475Smrg $code = "1;" . $code; 97d522f475Smrg } 98d522f475Smrg if ( $opts >= 3 ) { 99d522f475Smrg $code = ">" . $code; 100d522f475Smrg } 101d522f475Smrg $text = $piece . $code . $final; 102d522f475Smrg $text =~ s/([\d;]+)>/>$1/; 103d522f475Smrg } 104d522f475Smrg return $text; 105d522f475Smrg} 106d522f475Smrg 107d522f475Smrg# compute the next modifier value - 108d522f475Smrg# Cycling through the modifiers is not just like counting. Users prefer 109d522f475Smrg# pressing one modifier (even if using Emacs). So first we cycle through 110d522f475Smrg# the individual modifiers, then for completeness two, three, etc. 111d522f475Smrgsub next_modifier { 112d522f475Smrg my $code = $_[0]; 113d522f475Smrg my $mask = $code - 1; 114d522f475Smrg if ($mask == 0) { 115d522f475Smrg $mask = 1; # shift 116d522f475Smrg } elsif ($mask == 1) { 117d522f475Smrg $mask = 4; # control 118d522f475Smrg } elsif ($mask == 2) { 119d522f475Smrg $mask = 3; # shift+alt 120d522f475Smrg } elsif ($mask == 4) { 121d522f475Smrg $mask = 5; # shift+control 122d522f475Smrg } elsif ($mask == 5) { 123d522f475Smrg $mask = 2; # alt 124d522f475Smrg } 125d522f475Smrg # printf ("# next_modifier(%d) = %d\n", $code, $mask + 1); 126d522f475Smrg return $mask + 1; 127d522f475Smrg} 128d522f475Smrg 129d522f475Smrgsub make_ckey_names() { 130d522f475Smrg my ($j, $k); 131d522f475Smrg my $min = $min_ckeys * 2; 132d522f475Smrg my $max = $max_ckeys - 1; 133d522f475Smrg 134d522f475Smrg # printf "# make_ckey_names\n"; 135d522f475Smrg for $j ($min..$max) { 136d522f475Smrg $k = 1 + substr($j / $min_ckeys, 0, 1); 137d522f475Smrg $ckey_names[$j] = $ckey_names[$min_ckeys + ($j % $min_ckeys)] . $k; 138d522f475Smrg # printf "# make %d:%s\n", $j, $ckey_names[$j]; 139d522f475Smrg } 140d522f475Smrg for $j (0..$#ckey_names) { 141d522f475Smrg # printf "# %d:%s\n", $j, $ckey_names[$j]; 142d522f475Smrg $ckey_names{$ckey_names[$j]} = $j; 143d522f475Smrg } 144d522f475Smrg} 145d522f475Smrg 146d522f475Smrgsub make_ekey_names() { 147d522f475Smrg my ($j, $k); 148d522f475Smrg my $min = $min_ekeys * 2; 149d522f475Smrg my $max = $max_ekeys - 1; 150d522f475Smrg 151d522f475Smrg # printf "# make_ekey_names\n"; 152d522f475Smrg for $j ($min..$max) { 153d522f475Smrg $k = 1 + substr($j / $min_ekeys, 0, 1); 154d522f475Smrg $ekey_names[$j] = $ekey_names[$min_ekeys + ($j % $min_ekeys)] . $k; 155d522f475Smrg # printf "# make %d:%s\n", $j, $ekey_names[$j]; 156d522f475Smrg } 157d522f475Smrg for $j (0..$#ekey_names) { 158d522f475Smrg # printf "# %d:%s\n", $j, $ekey_names[$j]; 159d522f475Smrg $ekey_names{$ekey_names[$j]} = $j; 160d522f475Smrg } 161d522f475Smrg} 162d522f475Smrg 163d522f475Smrg# Read the terminfo entry's list of function keys $old_fkeys[]. 164d522f475Smrg# We could handle $old_fkeys[0], but choose to start numbering from 1. 165d522f475Smrgsub readterm($) { 166d522f475Smrg my $term = $_[0]; 167d522f475Smrg my($key, $n, $str); 168d522f475Smrg my(@list) = `infocmp -x -1 $term`; 169d522f475Smrg 170d522f475Smrg for $n (0..$#list) { 171d522f475Smrg chop $list[$n]; 172d522f475Smrg $list[$n] =~ s/^[[:space:]]//; 173d522f475Smrg 174d522f475Smrg $key = $list[$n]; 175d522f475Smrg $key =~ s/=.*//; 176d522f475Smrg 177d522f475Smrg $str = $list[$n]; 178d522f475Smrg $str =~ s/^[^=]+=//; 179d522f475Smrg $str =~ s/,$//; 180d522f475Smrg 181d522f475Smrg if ( $list[$n] =~ /^kf[[:digit:]]+=/ ) { 182d522f475Smrg $key =~ s/^kf//; 183d522f475Smrg # printf "# $n:%s(%d)(%s)\n", $list[$n], $key, $str; 184d522f475Smrg $old_fkeys[$key] = $str; 185d522f475Smrg } elsif ( $key =~ /^kc[[:alpha:]]+1/ 186d522f475Smrg or $key =~ /^k(LFT|RIT|UP|DN)\d?/) { 187d522f475Smrg # printf "# $n:%s(%d)(%s)\n", $list[$n], $key, $str; 188d522f475Smrg $old_ckeys{$key} = $str; 189d522f475Smrg } elsif ( defined $ekey_names{$key} ) { 190d522f475Smrg # printf "# $n:%s(%s)(%s)\n", $list[$n], $key, $str; 191d522f475Smrg $old_ekeys{$key} = $str; 192d522f475Smrg } 193d522f475Smrg } 194d522f475Smrg # printf ("last index:%d\n", $#old_fkeys); 195d522f475Smrg} 196d522f475Smrg 197d522f475Smrg# read the whole terminfo to ensure we get the non-modified stuff, then read 198d522f475Smrg# the part that contains modifiers. 199d522f475Smrgsub read_part($) { 200d522f475Smrg my $part = $_[0]; 201d522f475Smrg 202d522f475Smrg %old_ckeys = (); 203d522f475Smrg @old_fkeys = (); 204d522f475Smrg readterm($terminfo); 205d522f475Smrg readterm($part); 206d522f475Smrg} 207d522f475Smrg 208d522f475Smrgsub nameof_ckeys($) { 209d522f475Smrg my $opts = $_[0]; 210d522f475Smrg my $optname = "xterm+pcc" . ($opts >= 0 ? $opts : "n"); 211d522f475Smrg return $optname; 212d522f475Smrg} 213d522f475Smrg 214d522f475Smrgsub generate_ckeys($) { 215d522f475Smrg my $opts = $_[0]; 216d522f475Smrg my($modifier, $cur_ckey, $index); 217d522f475Smrg 218d522f475Smrg printf "%s|fragment with modifyCursorKeys:%s,\n", 219d522f475Smrg nameof_ckeys($opts), $opts; 220d522f475Smrg 221d522f475Smrg # show the standard cursor definitions 222d522f475Smrg $modifier = 1; 223d522f475Smrg for ($index = 0; $index < $min_ckeys; ++$index) { 224d522f475Smrg $cur_ckey = $index + ($modifier * $min_ckeys); 225d522f475Smrg my $name = $ckey_known[$index]; 226d522f475Smrg my $input = $old_ckeys{$ckey_names[$index]}; 227d522f475Smrg my $result = modify_fkey($modifier + 1, $input, $opts); 228d522f475Smrg printf "\t%s=%s,\n", $name, $result; 229d522f475Smrg if (defined $old_ckeys{$name}) { 230d522f475Smrg if ($old_ckeys{$name} ne $result) { 231d522f475Smrg printf "# found %s=%s\n", $name, $old_ckeys{$name}; 232d522f475Smrg } 233d522f475Smrg } 234d522f475Smrg } 235d522f475Smrg 236d522f475Smrg # show the extended cursor definitions 237d522f475Smrg for ($index = 0; $index < $min_ckeys; ++$index) { 238d522f475Smrg for ($modifier = 1; $modifier < $max_modifier; ++$modifier) { 239d522f475Smrg $cur_ckey = $index + ($modifier * $min_ckeys); 240d522f475Smrg if (defined $ckey_names[$cur_ckey] and 241d522f475Smrg $ckey_names[$cur_ckey] ne "kLFT" and 242d522f475Smrg $ckey_names[$cur_ckey] ne "kRIT" ) { 243d522f475Smrg my $name = $ckey_names[$cur_ckey]; 244d522f475Smrg my $input = $old_ckeys{$ckey_names[$index]}; 245d522f475Smrg my $result = modify_fkey($modifier + 1, $input, $opts); 246d522f475Smrg printf "\t%s=%s,\n", $name, $result; 247d522f475Smrg if (defined $old_ckeys{$name}) { 248d522f475Smrg if ($old_ckeys{$name} ne $result) { 249d522f475Smrg printf "# found %s=%s\n", $name, $old_ckeys{$name}; 250d522f475Smrg } 251d522f475Smrg } 252d522f475Smrg } 253d522f475Smrg } 254d522f475Smrg } 255d522f475Smrg} 256d522f475Smrg 257d522f475Smrgsub nameof_ekeys($) { 258d522f475Smrg my $opts = $_[0]; 259d522f475Smrg my $optname = "xterm+pce" . ($opts >= 0 ? $opts : "n"); 260d522f475Smrg return $optname; 261d522f475Smrg} 262d522f475Smrg 263d522f475Smrgsub generate_ekeys($) { 264d522f475Smrg my $opts = $_[0]; 265d522f475Smrg my($modifier, $cur_ekey, $index); 266d522f475Smrg 267d522f475Smrg printf "%s|fragment with modifyCursorKeys:%s,\n", 268d522f475Smrg nameof_ekeys($opts), $opts; 269d522f475Smrg 270d522f475Smrg for ($index = 0; $index < $min_ekeys; ++$index) { 271d522f475Smrg for ($modifier = 1; $modifier < $max_modifier; ++$modifier) { 272d522f475Smrg $cur_ekey = $index + ($modifier * $min_ekeys); 273d522f475Smrg if (defined $ekey_names[$cur_ekey] ) { 274d522f475Smrg my $name = $ekey_names[$cur_ekey]; 275d522f475Smrg my $input = $old_ekeys{$ekey_names[$index]}; 276d522f475Smrg my $result = modify_fkey($modifier + 1, $input, $opts); 277d522f475Smrg printf "\t%s=%s,\n", $name, $result; 278d522f475Smrg if (defined $old_ekeys{$name}) { 279d522f475Smrg if ($old_ekeys{$name} ne $result) { 280d522f475Smrg printf "# found %s=%s\n", $name, $old_ekeys{$name}; 281d522f475Smrg } 282d522f475Smrg } 283d522f475Smrg } 284d522f475Smrg } 285d522f475Smrg } 286d522f475Smrg} 287d522f475Smrg 288d522f475Smrgsub nameof_fkeys($) { 289d522f475Smrg my $opts = $_[0]; 290d522f475Smrg my $optname = "xterm+pcf" . ($opts >= 0 ? $opts : "n"); 291d522f475Smrg return $optname; 292d522f475Smrg} 293d522f475Smrg 294d522f475Smrgsub generate_fkeys($) { 295d522f475Smrg my $opts = $_[0]; 296d522f475Smrg my($modifier, $cur_fkey); 297d522f475Smrg 298d522f475Smrg printf "%s|fragment with modifyFunctionKeys:%s and ctrlFKeys:10,\n", 299d522f475Smrg nameof_fkeys($opts), $opts; 300d522f475Smrg 301d522f475Smrg for ($cur_fkey = 1, $modifier = 1; $cur_fkey < $max_fkeys; ++$cur_fkey) { 302d522f475Smrg my $index = (($cur_fkey - 1) % $min_fkeys); 303d522f475Smrg if ($index == 0 && $cur_fkey != 1) { 304d522f475Smrg $modifier = next_modifier($modifier); 305d522f475Smrg } 306d522f475Smrg if (defined $old_fkeys[$index + 1]) { 307d522f475Smrg my $input = $old_fkeys[$index + 1]; 308d522f475Smrg my $result = modify_fkey($modifier, $input, $opts); 309d522f475Smrg printf "\tkf%d=%s,\n", $cur_fkey, $result; 310d522f475Smrg if (defined $old_fkeys[$cur_fkey]) { 311d522f475Smrg if ($old_fkeys[$cur_fkey] ne $result) { 312d522f475Smrg printf "# found kf%d=%s\n", $cur_fkey, $old_fkeys[$cur_fkey]; 313d522f475Smrg } 314d522f475Smrg } 315d522f475Smrg } 316d522f475Smrg } 317d522f475Smrg} 318d522f475Smrg 319d522f475Smrgsub show_default() { 320d522f475Smrg readterm($terminfo); 321d522f475Smrg 322d522f475Smrg printf "xterm+pcfkeys|fragment for PC-style keys,\n"; 323d522f475Smrg printf "\tuse=%s,\n", nameof_ckeys($opt_ckeys); 324d522f475Smrg printf "\tuse=%s,\n", nameof_ekeys($opt_ekeys); 325d522f475Smrg printf "\tuse=%s,\n", nameof_fkeys($opt_fkeys); 326d522f475Smrg 327d522f475Smrg generate_ckeys($opt_ckeys); 328d522f475Smrg generate_ekeys($opt_ekeys); 329d522f475Smrg generate_fkeys($opt_fkeys); 330d522f475Smrg} 331d522f475Smrg 332d522f475Smrgsub show_nondefault() 333d522f475Smrg{ 334d522f475Smrg my $opts; 335d522f475Smrg 336d522f475Smrg for ($opts = 0; $opts <= 3; ++$opts) { 337d522f475Smrg if ($opts != $opt_ckeys) { 338d522f475Smrg read_part(nameof_ckeys($opts)); 339d522f475Smrg generate_ckeys($opts); 340d522f475Smrg } 341d522f475Smrg } 342d522f475Smrg 343d522f475Smrg for ($opts = 0; $opts <= 3; ++$opts) { 344d522f475Smrg if ($opts != $opt_ekeys) { 345d522f475Smrg read_part(nameof_ekeys($opts)); 346d522f475Smrg generate_ekeys($opts); 347d522f475Smrg } 348d522f475Smrg } 349d522f475Smrg 350d522f475Smrg for ($opts = 0; $opts <= 3; ++$opts) { 351d522f475Smrg if ($opts != $opt_fkeys) { 352d522f475Smrg read_part(nameof_fkeys($opts)); 353d522f475Smrg generate_fkeys($opts); 354d522f475Smrg } 355d522f475Smrg } 356d522f475Smrg} 357d522f475Smrg 358d522f475Smrgmake_ckey_names(); 359d522f475Smrgmake_ekey_names(); 360d522f475Smrg 361d522f475Smrgprintf "# gen-pc-fkeys.pl\n"; 362d522f475Smrgprintf "# %s:timode\n", "vile"; 363d522f475Smrgshow_default(); 364d522f475Smrgshow_nondefault(); 365