diff options
Diffstat (limited to 'scripts/xkb.pl')
-rwxr-xr-x | scripts/xkb.pl | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/scripts/xkb.pl b/scripts/xkb.pl new file mode 100755 index 0000000..976ee3b --- /dev/null +++ b/scripts/xkb.pl @@ -0,0 +1,303 @@ +#!/usr/bin/perl + +# FreeRDP: A Remote Desktop Protocol Implementation +# XKB database conversion script + +# Copyright 2009 Marc-Andre Moreau <marcandre.moreau@gmail.com> + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Description: +# Script to export XKB configuration files to keycode -> virtual key code keymaps that are +# easy to use in FreeRDP. This makes keymap maintenance easier to make as all bugs can +# simply be reported to the XKB Configuration Database project, and then this script can +# be used to export newer (and fixed) version of the XKB Configuration Database. + +use Cwd; + +my %sym2virt = ( + "AE00" => "VK_TILDE", + "AE01" => "VK_KEY_1", + "AE02" => "VK_KEY_2", + "AE03" => "VK_KEY_3", + "AE04" => "VK_KEY_4", + "AE05" => "VK_KEY_5", + "AE06" => "VK_KEY_6", + "AE07" => "VK_KEY_7", + "AE08" => "VK_KEY_8", + "AE09" => "VK_KEY_9", + "AE10" => "VK_KEY_0", + "AE11" => "VK_OEM_MINUS", + "AE12" => "VK_OEM_PLUS", + + "AD01" => "VK_KEY_Q", + "AD02" => "VK_KEY_W", + "AD03" => "VK_KEY_E", + "AD04" => "VK_KEY_R", + "AD05" => "VK_KEY_T", + "AD06" => "VK_KEY_Y", + "AD07" => "VK_KEY_U", + "AD08" => "VK_KEY_I", + "AD09" => "VK_KEY_O", + "AD10" => "VK_KEY_P", + "AD11" => "VK_OEM_4", + "AD12" => "VK_OEM_6", + + "AC01" => "VK_KEY_A", + "AC02" => "VK_KEY_S", + "AC03" => "VK_KEY_D", + "AC04" => "VK_KEY_F", + "AC05" => "VK_KEY_G", + "AC06" => "VK_KEY_H", + "AC07" => "VK_KEY_J", + "AC08" => "VK_KEY_K", + "AC09" => "VK_KEY_L", + "AC10" => "VK_OEM_1", + "AC11" => "VK_OEM_7", + "AC12" => "VK_OEM_5", + + "AB00" => "VK_LSHIFT", + "AB01" => "VK_KEY_Z", + "AB02" => "VK_KEY_X", + "AB03" => "VK_KEY_C", + "AB04" => "VK_KEY_V", + "AB05" => "VK_KEY_B", + "AB06" => "VK_KEY_N", + "AB07" => "VK_KEY_M", + "AB08" => "VK_OEM_COMMA", + "AB09" => "VK_OEM_PERIOD", + "AB10" => "VK_OEM_2", + "AB11" => "VK_ABNT_C1", + + "FK01" => "VK_F1", + "FK02" => "VK_F2", + "FK03" => "VK_F3", + "FK04" => "VK_F4", + "FK05" => "VK_F5", + "FK06" => "VK_F6", + "FK07" => "VK_F7", + "FK08" => "VK_F8", + "FK09" => "VK_F9", + "FK10" => "VK_F10", + "FK11" => "VK_F11", + "FK12" => "VK_F12", + "FK13" => "VK_F13", + "FK14" => "VK_F14", + "FK15" => "VK_F15", + "FK16" => "VK_F16", + "FK17" => "VK_F17", + "FK18" => "VK_F18", + "FK19" => "VK_F19", + "FK20" => "VK_F20", + "FK21" => "VK_F21", + "FK22" => "VK_F22", + "FK23" => "VK_F23", + "FK24" => "VK_F24", + + "KP0" => "VK_NUMPAD0", + "KP1" => "VK_NUMPAD1", + "KP2" => "VK_NUMPAD2", + "KP3" => "VK_NUMPAD3", + "KP4" => "VK_NUMPAD4", + "KP5" => "VK_NUMPAD5", + "KP6" => "VK_NUMPAD6", + "KP7" => "VK_NUMPAD7", + "KP8" => "VK_NUMPAD8", + "KP9" => "VK_NUMPAD9", + + "KPDV" => "VK_DIVIDE", + "KPMU" => "VK_MULTIPLY", + "KPSU" => "VK_SUBTRACT", + "KPAD" => "VK_ADD", + "KPDL" => "VK_DECIMAL", + "KPEN" => "VK_RETURN", + + "RTRN" => "VK_RETURN", + "SPCE" => "VK_SPACE", + "BKSP" => "VK_BACK", + "BKSL" => "VK_OEM_5", + "LSGT" => "VK_OEM_102", + "ESC" => "VK_ESCAPE", + "TLDE" => "VK_OEM_3", + "CAPS" => "VK_CAPITAL", + "TAB" => "VK_TAB", + "LFSH" => "VK_LSHIFT", + "RTSH" => "VK_RSHIFT", + "LCTL" => "VK_LCONTROL", + "RCTL" => "VK_RCONTROL", + "LWIN" => "VK_LWIN", + "RWIN" => "VK_RWIN", + "LALT" => "VK_LMENU", + "RALT" => "VK_RMENU", + "COMP" => "VK_APPS", + "MENU" => "VK_APPS", + "UP" => "VK_UP", + "DOWN" => "VK_DOWN", + "LEFT" => "VK_LEFT", + "RGHT" => "VK_RIGHT", + "INS" => "VK_INSERT", + "DELE" => "VK_DELETE", + "PGUP" => "VK_PRIOR", + "PGDN" => "VK_NEXT", + "HOME" => "VK_HOME", + "END" => "VK_END", + "PAUS" => "VK_PAUSE", + "NMLK" => "VK_NUMLOCK", + "SCLK" => "VK_SCROLL", + + # This page helps understanding the keys that follow: + # http://www.stanford.edu/class/cs140/projects/pintos/specs/kbd/scancodes-7.html + + "KANJ" => "VK_KANJI", + "HANJ" => "VK_HANJA", + "MUHE" => "VK_NONCONVERT", + "HIRA" => "VK_KANA", + "PRSC" => "VK_SNAPSHOT", + + "KPF1" => "VK_NUMLOCK", + "KPF2" => "VK_DIVIDE", + "KPF3" => "VK_MULTIPLY", + "KPF4" => "VK_SUBTRACT", + "KPCO" => "VK_ADD", + + "HELP" => "VK_HELP", + "SELE" => "VK_SELECT", + + # We can ignore LDM (Lock Down Modifier) + # What are LCMP/RCMP? + # DO, FIND? + +); + +my $inDir; +my $outDir; + +if(@ARGV < 1) { + $inDir = getcwd() . "/"; + $outDir = $inDir; +} elsif(@ARGV == 1) { + $inDir = $ARGV[0]; + $outDir = getcwd() . "/"; +} elsif(@ARGV == 2) { + $inDir = $ARGV[0]; + $outDir = $ARGV[1]; +} else { + print "Error: Too many arguments\n" . + "Usage:\n" . + "perl xkb.pl <XKB Directory>\n" . + "perl xkb.pl <XKB Directory> <Output Directory>\n\n" . + "In Linux, the XKB directory usually is /usr/share/X11/xkb/\n" . + "The latest version of XKB can always be downloaded at:\n" . + "http://freedesktop.org/wiki/Software/XKeyboardConfig\n"; + exit 0; +} + + + +open("SPEC", $inDir . "xkeyboard-config.spec"); + +$xkbVersion = ""; +while($line = <SPEC>) { + if($line =~ m/Version:\s+(.\..)/) { + $xkbVersion = "version $1"; + } +} + +# Create directory if it does not exists +if(not -e $outDir) { + mkdir $outDir or die("Error: Can't create directory $outDir\n"); +} + +open("KCD", $inDir . "keycodes/keycodes.dir") or die("Error: Can't open $inDir" . "keycodes/keycodes.dir\n"); + +$previousFile = ""; +while($line = <KCD>) { + if($line =~ m/........ -------- (.+)\((.+)\)/) { + if($1 ne $previousFile) { + push(@keymapFiles, $1); + $previousFile = $1; + } + } +} +close("KCD"); + +foreach $keymapFile (@keymapFiles) { + + print "File $keymapFile:\n"; + + @directories = split(/\//, $keymapFile); + splice(@directories, @directories - 1, 1); + + if(@directories > 0) { + $directory = $outDir; + for($i = 0; $i < @directories; $i++) { + $directory .= $directories[$i] . "/"; + if(not -e $directory) { + mkdir $directory or die("Can't create directory $directory\n"); + } + } + } + + open("IN", $inDir . "keycodes/" . $keymapFile); + open("OUT", ">" . "$outDir" . $keymapFile); + + print OUT "# This file was generated with xkb.pl\n"; + print OUT "# and is based on the X Keyboard Configuration Database $xkbVersion\n"; + print OUT "# Please use xkb.pl to re-export newer versions of XKB\n"; + print OUT "\n\n"; + + while($line = <IN>) { + if($line =~ m/xkb_keycodes \"(\w+)\"/) { + + print "Exporting \"$1\"\n"; + print OUT "keyboard \"$1\""; + + + while($line = <IN>) { + if($line =~ m/include\W+\"(.+)\"/) { + print OUT "\n: extends \"$1\""; + last; + } else { + last; + } + } + print OUT "\n{\n"; + + while($line = <IN>) { + if($line =~ m/<(\w{1,4})>\W+=\W+(\w+);/) { + if($sym2virt{$1} ne undef) { + $vkcode = $sym2virt{$1}; + print OUT "\t$vkcode"; + + if(length($vkcode) < 8) { + print OUT "\t"; + } + print OUT "\t<$2>\n"; + } else { + # If undef, then this symbolic key code is + # missing from the sym2virt hash table + # print "\t$1\t$2\n"; + } + } elsif($line =~ m/};/) { + print OUT "};\n\n"; + last; + } + } + } + } + + close("IN"); + close("OUT"); +} + |