diff options
Diffstat (limited to 'perl-install/keyboard.pm')
-rw-r--r-- | perl-install/keyboard.pm | 351 |
1 files changed, 263 insertions, 88 deletions
diff --git a/perl-install/keyboard.pm b/perl-install/keyboard.pm index 233aafda1..8f8fef04e 100644 --- a/perl-install/keyboard.pm +++ b/perl-install/keyboard.pm @@ -1,34 +1,235 @@ -package keyboard; + +package keyboard; # $Id$ use diagnostics; use strict; -use vars qw($KMAP_MAGIC %defaultKeyboards %loadKeymap); -use common qw(:system :file); +#-###################################################################################### +#- misc imports +#-###################################################################################### +use common qw(:common :system :file); +use run_program; +use commands; use log; +use c; -$KMAP_MAGIC = 0x8B39C07F; +#-###################################################################################### +#- Globals +#-###################################################################################### +my $KMAP_MAGIC = 0x8B39C07F; -%defaultKeyboards = ( - "de" => "de-latin1", - "fi" => "fi-latin1", - "se" => "se-latin1", - "no" => "no-latin1", - "cs" => "cz-lat2", - "tr" => "trq", +#- a best guess of the keyboard layout, based on the choosen locale +my %lang2keyboard = +( + 'af' => 'us_intl', + 'az' => 'az', + 'be' => 'by', + 'be_BY.CP1251' => 'by', + 'bg' => 'bg', +'bg_BG'=> 'bg', + 'br' => 'fr', + 'ca' => 'es', + 'cs' => 'cz_qwerty', + 'cy' => 'uk', + 'da' => 'dk', + 'de' => 'de', +'de_AT'=> 'de', +'de_CH'=> 'ch_de', +'de_DE'=> 'de', + 'el' => 'gr', + 'en' => 'us', +'en_US'=> 'us', +'en_GB'=> 'uk', + 'eo' => 'us_intl', + 'es' => 'es', + 'es@tradicional' => 'es', +'es_AR'=> 'la', +'es_ES'=> 'es', +'es_MX'=> 'la', + 'et' => 'ee', + 'eu' => 'es', + 'fa' => 'ir', + 'fi' => 'fi', + 'fr' => 'fr', +'fr_BE'=> 'be', +'fr_CA'=> 'qc', +'fr_CH'=> 'ch_fr', +'fr_FR'=> 'fr', + 'ga' => 'uk', + 'gl' => 'es', + 'he' => 'il', + 'hr' => 'hr', + 'hu' => 'hu', + 'hy' => 'am', + 'is' => 'is', + 'it' => 'it', + 'ja' => 'jp', + 'ka' => 'ge_la', + 'lt' => 'lt', + 'mk' => 'mk', + 'nb' => 'no', + 'nl' => 'nl', +'nl_BE'=> 'be', +'nl_NL'=> 'nl', + 'no' => 'no', + 'no@nynorsk' => 'no', + 'ny' => 'no', + 'oc' => 'fr', + 'pl' => 'pl', + 'pt' => 'pt', +'pt_BR'=> 'br', +'pt_PT'=> 'pt', + 'ru' => 'ru', + 'ru_RU.KOI8-R' => 'ru', + 'sk' => 'sk_qwerty', + 'sl' => 'si', + 'sr' => 'yu', + 'sv' => 'se', + 'sv@ny' => 'se', + 'sv@traditionell' => 'se', + 'th' => 'th', + 'tr' => 'tr_q', + 'uk' => 'ua', +'uk_UA' => 'ua', + 'vi' => 'vn', +'vi_VN.tcvn' => 'vn', +'vi_VN.viscii' => 'vn', + 'wa' => 'be', ); -1; +#- key = extension for Xmodmap file, [0] = description of the keyboard, +#- [1] = name for loadkeys, [2] = name for XKB +my %keyboards = ( +arch() =~ /^sparc/ ? ( + "cs" => [ __("Czech (QWERTZ)"), "sunt5-cz-us", "czsk(cz_us_qwertz)" ], + "de" => [ __("German"), "sunt5-de-latin1", "de" ], + "dvorak" => [ __("Dvorak"), "sundvorak", "dvorak" ], + "es" => [ __("Spanish"), "sunt5-es", "es" ], + "fi" => [ __("Finnish"), "sunt5-fi-latin1", "fi" ], + "fr" => [ __("French"), "sunt5-fr-latin1", "fr" ], + "no" => [ __("Norwegian"), "sunt4-no-latin1", "no" ], + "pl" => [ __("Polish"), "sun-pl-altgraph", "pl" ], + "ru" => [ __("Russian"), "sunt5-ru", "ru" ], + "uk" => [ __("UK keyboard"), "sunt5-uk", "gb" ], + "us" => [ __("US keyboard"), "sunkeymap", "us" ], +) : ( +arch() eq "ppc" ? ( + "us" => [ __("US keyboard"), "mac-us-ext", "us" ], + "de_nodeadkeys" => [ __("German"), "mac-de-latin1-nodeadkeys", "de(nodeadkeys)" ], + "fr" => [ __("French"), "mac-fr2-ext", "fr" ], +) : ( + "am_old" => [ __("Armenian (old)"), "am_old", "am(old)" ], + "am" => [ __("Armenian (typewriter)"), "am-armscii8", "am" ], + "am_phonetic" => [ __("Armenian (phonetic)"), "am_phonetic", "am(phonetic)" ], +#- only xmodmap is currently available +#-"ar" => [ __("Arabic"), "ar-8859_6", "ar" ], + "az" => [ __("Azerbaidjani (latin)"), "az", "az" ], + "a3" => [ __("Azerbaidjani (cyrillic)"), "az-koi8c","az(cyrillic)" ], + "be" => [ __("Belgian"), "be-latin1", "be" ], + "bg" => [ __("Bulgarian"), "bg", "bg" ], + "br" => [ __("Brazilian (ABNT-2)"), "br-abnt2", "br" ], + "by" => [ __("Belarusian"), "by-cp1251", "byru" ], + "ch_de" => [ __("Swiss (German layout)"), "sg-latin1", "de_CH" ], + "ch_fr" => [ __("Swiss (French layout)"), "fr_CH-latin1", "fr_CH" ], + "cz" => [ __("Czech (QWERTZ)"), "cz-latin2", "czsk(cz_us_qwertz)" ], + "cz_qwerty" => [ __("Czech (QWERTY)"), "cz-lat2", "czsk(cz_us_qwerty)" ], + "cz_prog" => [ __("Czech (Programmers)"), "cz-lat2-prog", "czsk(us_cz_prog)" ], + "de" => [ __("German"), "de-latin1", "de" ], + "de_nodeadkeys" => [ __("German (no dead keys)"), "de-latin1-nodeadkeys", "de(nodeadkeys)" ], + "dk" => [ __("Danish"), "dk-latin1", "dk" ], + "dvorak" => [ __("Dvorak (US)"), "pc-dvorak-latin1", "dvorak" ], + "dvorak_no" => [ __("Dvorak (Norwegian)"), "no-dvorak", "dvorak(no)" ], + "ee" => [ __("Estonian"), "ee-latin9", "ee" ], + "es" => [ __("Spanish"), "es-latin1", "es" ], + "fi" => [ __("Finnish"), "fi-latin1", "fi" ], + "fr" => [ __("French"), "fr-latin1", "fr" ], + "ge_ru"=>[__("Georgian (\"Russian\" layout)"),"ge_ru-georgian_academy","ge_ru"], + "ge_la"=>[__("Georgian (\"Latin\" layout)"),"ge_la-georgian_academy","ge_la"], + "gr" => [ __("Greek"), "gr-8859_7", "gr" ], + "hu" => [ __("Hungarian"), "hu-latin2", "hu" ], + "hr" => [ __("Croatian"), "croat", "yu" ], + "il" => [ __("Israeli"), "il-8859_8", "il" ], + "il_phonetic" => [ __("Israeli (Phonetic)"),"hebrew", "il_phonetic" ], + "ir" => [ __("Iranian"), "ir-isiri3342","ir" ], + "is" => [ __("Icelandic"), "is-latin1", "is" ], + "it" => [ __("Italian"), "it-latin1", "it" ], + "jp" => [ __("Japanese 106 keys"), "jp106", "jp" ], + "la" => [ __("Latin American"), "la-latin1", "la" ], +#-"mk" => [ __("Macedonian"), "mk", "mk" ], + "nl" => [ __("Dutch"), "nl-latin1", "nl" ], + "lt" => [ __("Lithuanian AZERTY (old)"), "lt-latin7","lt" ], +#- TODO: write a console kbd map for lt_new + "lt_new" => [ __("Lithuanian AZERTY (new)"), "lt-latin7","lt_new" ], + "lt_b" => [ __("Lithuanian \"number row\" QWERTY"), "ltb-latin7", "lt_b" ], + "lt_p" => [ __("Lithuanian \"phonetic\" QWERTY"), "ltp-latin7", "lt_p" ], + "no" => [ __("Norwegian"), "no-latin1", "no" ], + "pl" => [ __("Polish (qwerty layout)"), "pl", "pl" ], + "pl2" => [ __("Polish (qwertz layout)"), "pl-latin2", "pl2" ], + "pt" => [ __("Portuguese"), "pt-latin1", "pt" ], + "qc" => [ __("Canadian (Quebec)"), "qc-latin1","ca_enhanced" ], + "ru" => [ __("Russian"), "ru4", "ru(winkeys)" ], + "ru_yawerty" => [ __("Russian (Yawerty)"),"ru-yawerty","ru_yawerty" ], + "se" => [ __("Swedish"), "se-latin1", "se" ], + "si" => [ __("Slovenian"), "slovene", "si" ], + "sk" => [ __("Slovakian (QWERTZ)"), "sk-qwertz", "czsk(sk_us_qwertz)" ], + "sk_qwerty" => [ __("Slovakian (QWERTY)"), "sk-qwerty", "czsk(sk_us_qwerty)" ], + "sk_prog" => [ __("Slovakian (Programmers)"), "sk-prog", "czsk(us_sk_prog" ], + "th" => [ __("Thai keyboard"), "th", "th" ], + "tr_f" => [ __("Turkish (traditional \"F\" model)"), "trf", "tr_f" ], + "tr_q" => [ __("Turkish (modern \"Q\" model)"), "tr_q-latin5", "tr_q" ], + "ua" => [ __("Ukrainian"), "ua", "ua" ], + "uk" => [ __("UK keyboard"), "uk", "gb" ], + "us" => [ __("US keyboard"), "us", "us" ], + "us_intl" => [ __("US keyboard (international)"), "us-latin1", "us_intl" ], + "vn" => [ __("Vietnamese \"numeric row\" QWERTY"),"vn-tcvn", "vn" ], + "yu" => [ __("Yugoslavian (latin layout)"), "sr", "yu" ], +)), +); + + +#-###################################################################################### +#- Functions +#-###################################################################################### +sub xmodmaps { keys %keyboards } +sub keyboard2text { $keyboards{$_[0]} && $keyboards{$_[0]}[0] } +sub keyboard2kmap { $keyboards{$_[0]} && $keyboards{$_[0]}[1] } +sub keyboard2xkb { $keyboards{$_[0]} && $keyboards{$_[0]}[2] } + +sub loadkeys_files { + my $archkbd = arch() =~ /^sparc/ ? "sun" : arch() =~ /i.86/ ? "i386" : arch(); + my $p = "/usr/lib/kbd/keymaps/$archkbd"; + my $post = ".kmap.gz"; + my %trans = ("cz-latin2" => "cz-lat2"); + my (@l, %l); + foreach (values %keyboards) { + local $_ = $trans{$_->[1]} || $_->[1]; + my ($l) = grep { -e $_ } ("$p/$_$post"); + $l or /(..)/ and ($l) = grep { -e $_ } ("$p/$1$post"); + print STDERR "unknown $_\n" if $_[0] && !$l; $l or next; + push @l, $l; + foreach (`zgrep include $l | grep "^include"`) { + /include\s+"(.*)"/ or die "bad line $_"; + @l{grep { -e $_ } ("$p/$1.inc.gz")} = (); + } + } + @l, keys %l, grep { -e $_ } map { "$p/$_.inc.gz" } qw(compose euro windowkeys linux-keys-bare); +} +sub lang2keyboard { + my ($l) = @_; + my $kb = $lang2keyboard{$l} || $keyboards{$l} && $l || "us"; + $keyboards{$kb} ? $kb : "us"; #- handle incorrect keyboad mapping to us. +} -sub load($) { - my ($keymap_raw) = @_; +sub load { + my ($keymap) = @_; + return if $::testing; - my ($magic, @keymaps) = unpack "i i" . c::MAX_NR_KEYMAPS() . "a*", $keymap_raw; - $keymap_raw = pop @keymaps; + my ($magic, @keymaps) = unpack "I i" . c::MAX_NR_KEYMAPS() . "a*", $keymap; + $keymap = pop @keymaps; - $magic != $KMAP_MAGIC and die "failed to read kmap magic: $!"; + $magic != $KMAP_MAGIC and die "failed to read kmap magic"; local *F; sysopen F, "/dev/console", 2 or die "failed to open /dev/console: $!"; @@ -37,92 +238,66 @@ sub load($) { foreach (0 .. c::MAX_NR_KEYMAPS() - 1) { $keymaps[$_] or next; - my @keymap = unpack "s" . c::NR_KEYS() . "a*", $keymap_raw; - $keymap_raw = pop @keymap; + my @keymap = unpack "s" . c::NR_KEYS() . "a*", $keymap; + $keymap = pop @keymap; - my $key = 0; + my $key = -1; foreach my $value (@keymap) { - c::KTYP($value) != c::KT_SPEC() or next; - ioctl(F, c::KDSKBENT(), pack("CCS", $_, $key++, $value)) or log::l("keymap ioctl failed: $!"); $key++; + c::KTYP($value) != c::KT_SPEC() or next; + ioctl(F, c::KDSKBENT(), pack("CCS", $_, $key, $value)) or die "keymap ioctl failed ($_ $key $value): $!"; } $count++; } - log::l("loaded $count keymap tables"); - 1; + #- log::l("loaded $count keymap tables"); } -sub setup($) { - my ($defkbd) = @_; - my $t; - - #$::testing and return 1; - - $defkbd ||= $defaultKeyboards{$ENV{LANG}} || "us"; - - local *F; - open F, "/etc/keymaps" or die "cannot open /etc/keymaps: $!"; - - my $format = "i2"; - read F, $t, psizeof($format) or die "failed to read keymaps header: $!"; - my ($magic, $numEntries) = unpack $format, $t; - - log::l("%d keymaps are available", $numEntries); - - my @infoTable; - my $format2 = "i Z40"; - foreach (1..$numEntries) { - read F, $t, psizeof($format2) or die "failed to read keymap information: $!"; - push @infoTable, [ unpack $format2, $t ]; +sub xmodmap_file { + my ($keyboard) = @_; + my $f = "$ENV{SHARE_PATH}/xmodmap/xmodmap.$keyboard"; + if (! -e $f) { + run_program::run("packdrake", "-x", "$ENV{SHARE_PATH}/xmodmap.cz2", '/tmp', "xmodmap.$keyboard"); + $f = "/tmp/xmodmap.$keyboard"; } + -e $f && $f; +} - foreach (@infoTable) { - read F, $t, $_->[0] or log::l("error reading $_->[0] bytes from file: $!"), return; +sub setup { + return if arch() =~ /^sparc/; + my ($keyboard) = @_; + my $o = $keyboards{$keyboard} or return; - if ($defkbd eq $_->[1]) { - log::l("using keymap $_->[1]"); - load($t) or return; - &write("/tmp", $_->[1]) or log::l("write keyboard config failed"); - return $_->[1]; - } + log::l("loading keymap $o->[1]"); + if (-e (my $f = "$ENV{SHARE_PATH}/keymaps/$o->[1].bkmap")) { + load(scalar cat_($f)); + } else { + local *F; + open F, "packdrake -x $ENV{SHARE_PATH}/keymaps.cz2 '' $o->[1].bkmap |"; + local $/ = undef; + eval { load(join('', <F>)) }; } - undef; + my $f = xmodmap_file($keyboard); + eval { run_program::run('xmodmap', $f) } unless $::testing || !$f; } -sub write($$) { - my ($prefix, $keymap) = @_; - - $keymap or return 1; - $::testing and return 1; +sub write { + my ($prefix, $keyboard, $charset, $isNotDelete) = @_; - local *F; - open F, ">$prefix/etc/sysconfig/keyboard" or die "failed to create keyboard configuration: $!"; - print F "KEYTABLE=$keymap\n" or die "failed to write keyboard configuration: $!"; - - # write default keymap - if (fork) { - wait; - $? == 0 or log::l('dumpkeys failed'); - } else { - chroot $prefix; - CORE::system("/usr/bin/dumpkeys > /etc/sysconfig/console/default.kmap 2>/dev/null"); - exit($?); - } + setVarsInSh("$prefix/etc/sysconfig/keyboard", { KEYTABLE => keyboard2kmap($keyboard), + KBCHARSET => $charset, + BACKSPACE => $isNotDelete ? "BackSpace" : "Delete" }); + run_program::rooted($prefix, "dumpkeys > /etc/sysconfig/console/default.kmap") or log::l("dumpkeys failed"); } -sub read($) { - my ($file) = @_; - - local *F; - open F, "$file" or # fail silently -- old bootdisks won't create this - log::l("failed to read keyboard configuration (probably ok)"), return; - - foreach (<F>) { - ($_) = /^KEYTABLE=(.*)/ or die "unrecognized entry in keyboard configuration file"; - s/\"//g; - s/\.[^.]*//; # remove extension - return basename($_); - } - log::l("empty keyboard configuration file"); - undef; +sub read { + my ($prefix) = @_; + my %keyf = getVarsFromSh("$prefix/etc/sysconfig/keyboard"); + my $keytable = $keyf{KEYTABLE}; + keyboard2kmap($_) eq $keytable and return $_ foreach keys %keyboards; + $keyboards{$keytable} ? $keytable : 'us_intl'; } + +#-###################################################################################### +#- Wonderful perl :( +#-###################################################################################### +1; |