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