Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / keymaps / xkb.pl
1 #!/usr/bin/perl
2
3 #   FreeRDP: A Remote Desktop Protocol client.
4 #   XKB database conversion script
5
6 #   Copyright 2009 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7
8 #   Licensed under the Apache License, Version 2.0 (the "License");
9 #   you may not use this file except in compliance with the License.
10 #   You may obtain a copy of the License at
11
12 #       http://www.apache.org/licenses/LICENSE-2.0
13
14 #   Unless required by applicable law or agreed to in writing, software
15 #   distributed under the License is distributed on an "AS IS" BASIS,
16 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 #   See the License for the specific language governing permissions and
18 #   limitations under the License.
19
20
21 # Description:
22 # Script to export XKB configuration files to keycode -> virtual key code keymaps that are
23 # easy to use in FreeRDP. This makes keymap maintenance easier to make as all bugs can
24 # simply be reported to the XKB Configuration Database project, and then this script can
25 # be used to export newer (and fixed) version of the XKB Configuration Database.
26
27 use Cwd;
28
29 my %sym2virt = (
30         "AE00" => "VK_TILDE",
31         "AE01" => "VK_KEY_1",
32         "AE02" => "VK_KEY_2",
33         "AE03" => "VK_KEY_3",
34         "AE04" => "VK_KEY_4",
35         "AE05" => "VK_KEY_5",
36         "AE06" => "VK_KEY_6",
37         "AE07" => "VK_KEY_7",
38         "AE08" => "VK_KEY_8",
39         "AE09" => "VK_KEY_9",
40         "AE10" => "VK_KEY_0",
41         "AE11" => "VK_OEM_MINUS",
42         "AE12" => "VK_OEM_PLUS",
43
44         "AD01" => "VK_KEY_Q",
45         "AD02" => "VK_KEY_W",
46         "AD03" => "VK_KEY_E",
47         "AD04" => "VK_KEY_R",
48         "AD05" => "VK_KEY_T",
49         "AD06" => "VK_KEY_Y",
50         "AD07" => "VK_KEY_U",
51         "AD08" => "VK_KEY_I",
52         "AD09" => "VK_KEY_O",
53         "AD10" => "VK_KEY_P",
54         "AD11" => "VK_OEM_4",
55         "AD12" => "VK_OEM_6",
56
57         "AC01" => "VK_KEY_A",
58         "AC02" => "VK_KEY_S",
59         "AC03" => "VK_KEY_D",
60         "AC04" => "VK_KEY_F",
61         "AC05" => "VK_KEY_G",
62         "AC06" => "VK_KEY_H",
63         "AC07" => "VK_KEY_J",
64         "AC08" => "VK_KEY_K",
65         "AC09" => "VK_KEY_L",
66         "AC10" => "VK_OEM_1",
67         "AC11" => "VK_OEM_7",
68         "AC12" => "VK_OEM_5",
69
70         "AB00" => "VK_LSHIFT",
71         "AB01" => "VK_KEY_Z",
72         "AB02" => "VK_KEY_X",
73         "AB03" => "VK_KEY_C",
74         "AB04" => "VK_KEY_V",
75         "AB05" => "VK_KEY_B",
76         "AB06" => "VK_KEY_N",
77         "AB07" => "VK_KEY_M",
78         "AB08" => "VK_OEM_COMMA",
79         "AB09" => "VK_OEM_PERIOD",
80         "AB10" => "VK_OEM_2",
81         "AB11" => "VK_ABNT_C1",
82
83         "FK01" => "VK_F1",
84         "FK02" => "VK_F2",
85         "FK03" => "VK_F3",
86         "FK04" => "VK_F4",
87         "FK05" => "VK_F5",
88         "FK06" => "VK_F6",
89         "FK07" => "VK_F7",
90         "FK08" => "VK_F8",
91         "FK09" => "VK_F9",
92         "FK10" => "VK_F10",
93         "FK11" => "VK_F11",
94         "FK12" => "VK_F12",
95         "FK13" => "VK_F13",
96         "FK14" => "VK_F14",
97         "FK15" => "VK_F15",
98         "FK16" => "VK_F16",
99         "FK17" => "VK_F17",
100         "FK18" => "VK_F18",
101         "FK19" => "VK_F19",
102         "FK20" => "VK_F20",
103         "FK21" => "VK_F21",
104         "FK22" => "VK_F22",
105         "FK23" => "VK_F23",
106         "FK24" => "VK_F24",
107
108         "KP0" => "VK_NUMPAD0",
109         "KP1" => "VK_NUMPAD1",
110         "KP2" => "VK_NUMPAD2",
111         "KP3" => "VK_NUMPAD3",
112         "KP4" => "VK_NUMPAD4",
113         "KP5" => "VK_NUMPAD5",
114         "KP6" => "VK_NUMPAD6",
115         "KP7" => "VK_NUMPAD7",
116         "KP8" => "VK_NUMPAD8",
117         "KP9" => "VK_NUMPAD9",
118
119         "KPDV" => "VK_DIVIDE",
120         "KPMU" => "VK_MULTIPLY",
121         "KPSU" => "VK_SUBTRACT",
122         "KPAD" => "VK_ADD",
123         "KPDL" => "VK_DECIMAL",
124         "KPEN" => "VK_RETURN",
125
126         "RTRN" => "VK_RETURN",
127         "SPCE" => "VK_SPACE",
128         "BKSP" => "VK_BACK",
129         "BKSL" => "VK_OEM_5",
130         "LSGT" => "VK_OEM_102",
131         "ESC" => "VK_ESCAPE",
132         "TLDE" => "VK_OEM_3",
133         "CAPS" => "VK_CAPITAL",
134         "TAB" => "VK_TAB",
135         "LFSH" => "VK_LSHIFT",
136         "RTSH" => "VK_RSHIFT",
137         "LCTL" => "VK_LCONTROL",
138         "RCTL" => "VK_RCONTROL",
139         "LWIN" => "VK_LWIN",
140         "RWIN" => "VK_RWIN",
141         "LALT" => "VK_LMENU",
142         "RALT" => "VK_RMENU",
143         "COMP" => "VK_APPS",
144         "MENU" => "VK_APPS",
145         "UP" => "VK_UP",
146         "DOWN" => "VK_DOWN",
147         "LEFT" => "VK_LEFT",
148         "RGHT" => "VK_RIGHT",
149         "INS" => "VK_INSERT",
150         "DELE" => "VK_DELETE",
151         "PGUP" => "VK_PRIOR",
152         "PGDN" => "VK_NEXT",
153         "HOME" => "VK_HOME",
154         "END" => "VK_END",
155         "PAUS" => "VK_PAUSE",
156         "NMLK" => "VK_NUMLOCK",
157         "SCLK" => "VK_SCROLL",
158
159         # This page helps understanding the keys that follow:
160         # http://www.stanford.edu/class/cs140/projects/pintos/specs/kbd/scancodes-7.html
161  
162         "KANJ" => "VK_KANJI",
163         "HANJ" => "VK_HANJA",
164         "MUHE" => "VK_NONCONVERT",
165         "HIRA" => "VK_KANA",
166         "PRSC" => "VK_SNAPSHOT",
167
168         "KPF1" => "VK_NUMLOCK",
169         "KPF2" => "VK_DIVIDE",
170         "KPF3" => "VK_MULTIPLY",
171         "KPF4" => "VK_SUBTRACT",
172         "KPCO" => "VK_ADD",
173
174         "HELP" => "VK_HELP",
175         "SELE" => "VK_SELECT",
176
177         # We can ignore LDM (Lock Down Modifier)
178         # What are LCMP/RCMP?
179         # DO, FIND?
180
181 );
182
183 my $inDir;
184 my $outDir;
185
186 if(@ARGV < 1) {
187         $inDir = getcwd() . "/";
188         $outDir = $inDir;
189 } elsif(@ARGV == 1) {
190         $inDir = $ARGV[0];
191         $outDir = getcwd() . "/";
192 } elsif(@ARGV == 2) {
193         $inDir = $ARGV[0];
194         $outDir = $ARGV[1];
195 } else {
196         print   "Error: Too many arguments\n" .
197                 "Usage:\n" .
198                 "perl xkb.pl <XKB Directory>\n" .
199                 "perl xkb.pl <XKB Directory> <Output Directory>\n\n" .
200                 "In Linux, the XKB directory usually is /usr/share/X11/xkb/\n" .
201                 "The latest version of XKB can always be downloaded at:\n" .
202                 "http://freedesktop.org/wiki/Software/XKeyboardConfig\n";
203                 exit 0;
204 }
205
206
207
208 open("SPEC", $inDir . "xkeyboard-config.spec");
209
210 $xkbVersion = "";
211 while($line = <SPEC>) {
212         if($line =~ m/Version:\s+(.\..)/) {
213                 $xkbVersion = "version $1";
214         }
215 }
216
217 # Create directory if it does not exists
218 if(not -e $outDir) {
219         mkdir $outDir or die("Error: Can't create directory $outDir\n");
220 }
221
222 open("KCD", $inDir . "keycodes/keycodes.dir") or die("Error: Can't open $inDir" . "keycodes/keycodes.dir\n");
223
224 $previousFile = "";
225 while($line = <KCD>) {
226         if($line =~ m/........ -------- (.+)\((.+)\)/) {
227                 if($1 ne $previousFile) {
228                         push(@keymapFiles, $1);
229                         $previousFile = $1;
230                 }
231         }       
232 }
233 close("KCD");
234
235 foreach $keymapFile (@keymapFiles) {
236
237                 print "File $keymapFile:\n";
238
239                 @directories = split(/\//, $keymapFile);
240                 splice(@directories, @directories - 1, 1); 
241
242                 if(@directories > 0) {
243                         $directory = $outDir;           
244                         for($i = 0; $i < @directories; $i++) {
245                                 $directory .= $directories[$i] . "/";
246                                 if(not -e $directory) {
247                                         mkdir $directory or die("Can't create directory $directory\n");                         
248                                 }                       
249                         }
250                 }
251
252                 open("IN", $inDir . "keycodes/" . $keymapFile);
253                 open("OUT", ">" . "$outDir" . $keymapFile);
254
255                 print OUT "# This file was generated with xkb.pl\n";
256                 print OUT "# and is based on the X Keyboard Configuration Database $xkbVersion\n";
257                 print OUT "# Please use xkb.pl to re-export newer versions of XKB\n";
258                 print OUT "\n\n";
259
260                 while($line = <IN>) {
261                         if($line =~ m/xkb_keycodes \"(\w+)\"/) {
262
263                                 print "Exporting \"$1\"\n";
264                                 print OUT "keyboard \"$1\"";
265
266
267                                 while($line = <IN>) {
268                                         if($line =~ m/include\W+\"(.+)\"/) {
269                                                 print OUT "\n: extends \"$1\"";
270                                                 last;
271                                         } else {
272                                                 last;
273                                         }
274                                 }
275                                 print OUT "\n{\n";              
276
277                                 while($line = <IN>) {
278                                         if($line =~ m/<(\w{1,4})>\W+=\W+(\w+);/) {
279                                                 if($sym2virt{$1} ne undef) {
280                                                         $vkcode = $sym2virt{$1};
281                                                         print OUT "\t$vkcode";
282
283                                                         if(length($vkcode) < 8) {
284                                                                 print OUT "\t";
285                                                         }
286                                                         print OUT "\t<$2>\n";
287                                                 } else {
288                                                         # If undef, then this symbolic key code is
289                                                         # missing from the sym2virt hash table
290                                                         # print "\t$1\t$2\n";
291                                                 }
292                                         } elsif($line =~ m/};/) {
293                                                 print OUT "};\n\n";
294                                                 last;
295                                         }
296                                 }
297                         }
298                 }
299
300                 close("IN");
301                 close("OUT");
302 }
303