1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #ifndef SOLARIS
28 #include <tools/prex.h>
29 #include <X11/XKBlib.h>
30 #include <tools/postx.h>
31 #endif
32
33 #include <unx/saldisp.hxx>
34 #include <X11/keysym.h>
35
36 #if !defined (SunXK_Undo)
37 #define SunXK_Undo 0x0000FF65 // XK_Undo
38 #define SunXK_Again 0x0000FF66 // XK_Redo
39 #define SunXK_Find 0x0000FF68 // XK_Find
40 #define SunXK_Stop 0x0000FF69 // XK_Cancel
41 #define SunXK_Props 0x1005FF70
42 #define SunXK_Front 0x1005FF71
43 #define SunXK_Copy 0x1005FF72
44 #define SunXK_Open 0x1005FF73
45 #define SunXK_Paste 0x1005FF74
46 #define SunXK_Cut 0x1005FF75
47 #endif
48
49 #ifdef SOLARIS
50 #include <sys/types.h>
51 #include <sys/ioctl.h>
52 #include <sys/kbio.h>
53 #include <sys/kbd.h>
54 #include <stdio.h>
55 #include <fcntl.h>
56 #include <deflt.h>
57 #include <unistd.h>
58 #include <stdlib.h>
59 #endif
60
61 #include <string.h>
62
63 namespace vcl_sal {
64
65 struct KeysymNameReplacement
66 {
67 KeySym aSymbol;
68 const char* pName;
69 };
70
71 struct KeyboardReplacements
72 {
73 const char* pKeyboardName;
74 const KeysymNameReplacement* pReplacements;
75 int nReplacements;
76 };
77
78 // ====================================================================
79 //
80 // CAUTION CAUTION CAUTION
81 // every string value in the replacements tables must be in UTF8
82 // be careful with your editor !
83 //
84 // ====================================================================
85
86 static const struct KeysymNameReplacement aImplReplacements_English[] =
87 {
88 { XK_Control_L, "Ctrl" },
89 { XK_Control_R, "Ctrl" },
90 { XK_Escape, "Esc" },
91 { XK_space, "Space" },
92 { XK_minus, "-" },
93 { XK_plus, "+" }
94 };
95
96 static const struct KeysymNameReplacement aImplReplacements_Turkish[] =
97 {
98 { XK_Control_L, "Ctrl" },
99 { XK_Control_R, "Ctrl" },
100 { XK_Right, "Sağ" },
101 { XK_Left, "Sol" },
102 { XK_Up, "Yukarı" },
103 { XK_Down, "Aşağı" },
104 { XK_space, "Boşluk" }
105 };
106
107 static const struct KeysymNameReplacement aImplReplacements_Russian[] =
108 {
109 { XK_Right, "Вправо" },
110 { XK_Left, "Влево" },
111 { XK_Up, "Вверх" },
112 { XK_Down, "Вниз" },
113 { XK_space, "Пробел" }
114 };
115
116 static const struct KeysymNameReplacement aImplReplacements_German[] =
117 {
118 { XK_Control_L, "Strg" },
119 { XK_Control_R, "Strg" },
120 { XK_Shift_L, "Umschalt" },
121 { XK_Shift_R, "Umschalt" },
122 { XK_Alt_L, "Alt" },
123 { XK_Alt_R, "Alt Gr" },
124 { XK_Page_Up, "Bild auf" },
125 { XK_Page_Down, "Bild ab" },
126 { XK_End, "Ende" },
127 { XK_Home, "Pos 1" },
128 { XK_Insert, "Einfg" },
129 { XK_Delete, "Entf" },
130 { XK_Escape, "Esc" },
131 { XK_Right, "Rechts" },
132 { XK_Left, "Links" },
133 { XK_Up, "Oben" },
134 { XK_Down, "Unten" },
135 { XK_BackSpace, "Rückschritt" },
136 { XK_Return, "Eingabe" },
137 { XK_slash, "Schrägstrich" },
138 { XK_space, "Leertaste" },
139 { SunXK_Stop, "Stop" },
140 { SunXK_Again, "Wiederholen" },
141 { SunXK_Props, "Eigenschaften" },
142 { SunXK_Undo, "Zurücknehmen" },
143 { SunXK_Front, "Vordergrund" },
144 { SunXK_Copy, "Kopieren" },
145 { SunXK_Open, "Öffnen" },
146 { SunXK_Paste, "Einsetzen" },
147 { SunXK_Find, "Suchen" },
148 { SunXK_Cut, "Ausschneiden" },
149 { XK_minus, "-" },
150 { XK_plus, "+" }
151 };
152
153 static const struct KeysymNameReplacement aImplReplacements_French[] =
154 {
155 { XK_Shift_L, "Maj" },
156 { XK_Shift_R, "Maj" },
157 { XK_Page_Up, "Pg. Préc" },
158 { XK_Page_Down, "Pg. Suiv" },
159 { XK_End, "Fin" },
160 { XK_Home, "Origine" },
161 { XK_Insert, "Insérer" },
162 { XK_Delete, "Suppr" },
163 { XK_Escape, "Esc" },
164 { XK_Right, "Droite" },
165 { XK_Left, "Gauche" },
166 { XK_Up, "Haut" },
167 { XK_Down, "Bas" },
168 { XK_BackSpace, "Ret. Arr" },
169 { XK_Return, "Retour" },
170 { XK_space, "Espace" },
171 { XK_KP_Enter, "Entrée" },
172 { SunXK_Stop, "Stop" },
173 { SunXK_Again, "Encore" },
174 { SunXK_Props, "Props" },
175 { SunXK_Undo, "Annuler" },
176 { SunXK_Front, "Devant" },
177 { SunXK_Copy, "Copy" },
178 { SunXK_Open, "Ouvrir" },
179 { SunXK_Paste, "Coller" },
180 { SunXK_Find, "Cher." },
181 { SunXK_Cut, "Couper" },
182 { XK_minus, "-" },
183 { XK_plus, "+" }
184 };
185
186 static const struct KeysymNameReplacement aImplReplacements_Italian[] =
187 {
188 { XK_Shift_L, "Maiusc" },
189 { XK_Shift_R, "Maiusc" },
190 { XK_Page_Up, "PgSu" },
191 { XK_Page_Down, "PgGiu" },
192 { XK_End, "Fine" },
193 { XK_Insert, "Ins" },
194 { XK_Delete, "Canc" },
195 { XK_Escape, "Esc" },
196 { XK_Right, "A destra" },
197 { XK_Left, "A sinistra" },
198 { XK_Up, "Sposta verso l'alto" },
199 { XK_Down, "Sposta verso il basso" },
200 { XK_BackSpace, "Backspace" },
201 { XK_Return, "Invio" },
202 { XK_space, "Spazio" },
203 { SunXK_Stop, "Stop" },
204 { SunXK_Again, "Ancora" },
205 { SunXK_Props, "Proprietà" },
206 { SunXK_Undo, "Annulla" },
207 { SunXK_Front, "Davanti" },
208 { SunXK_Copy, "Copia" },
209 { SunXK_Open, "Apri" },
210 { SunXK_Paste, "Incolla" },
211 { SunXK_Find, "Trova" },
212 { SunXK_Cut, "Taglia" },
213 { XK_minus, "-" },
214 { XK_plus, "+" }
215 };
216
217 static const struct KeysymNameReplacement aImplReplacements_Dutch[] =
218 {
219 { XK_Page_Up, "PageUp" },
220 { XK_Page_Down, "PageDown" },
221 { XK_Escape, "Esc" },
222 { XK_Right, "Rechts" },
223 { XK_Left, "Links" },
224 { XK_Up, "Boven" },
225 { XK_Down, "Onder" },
226 { XK_BackSpace, "Backspace" },
227 { XK_Return, "Return" },
228 { XK_space, "Spatiebalk" },
229 { SunXK_Stop, "Stop" },
230 { SunXK_Again, "Again" },
231 { SunXK_Props, "Props" },
232 { SunXK_Undo, "Undo" },
233 { SunXK_Front, "Front" },
234 { SunXK_Copy, "Copy" },
235 { SunXK_Open, "Open" },
236 { SunXK_Paste, "Paste" },
237 { SunXK_Find, "Find" },
238 { SunXK_Cut, "Cut" },
239 { XK_minus, "-" },
240 { XK_plus, "+" }
241 };
242
243 static const struct KeysymNameReplacement aImplReplacements_Norwegian[] =
244 {
245 { XK_Shift_L, "Skift" },
246 { XK_Shift_R, "Skift" },
247 { XK_Page_Up, "PageUp" },
248 { XK_Page_Down, "PageDown" },
249 { XK_Escape, "Esc" },
250 { XK_Right, "Hyre" },
251 { XK_Left, "Venstre" },
252 { XK_Up, "Opp" },
253 { XK_Down, "Ned" },
254 { XK_BackSpace, "Tilbake" },
255 { XK_Return, "Enter" },
256 { SunXK_Stop, "Avbryt" },
257 { SunXK_Again, "Gjenta" },
258 { SunXK_Props, "Egenskaper" },
259 { SunXK_Undo, "Angre" },
260 { SunXK_Front, "Front" },
261 { SunXK_Copy, "Kopi" },
262 { SunXK_Open, "Åpne" },
263 { SunXK_Paste, "Lim" },
264 { SunXK_Find, "Søk" },
265 { SunXK_Cut, "Klipp" },
266 { XK_minus, "-" },
267 { XK_plus, "+" }
268 };
269
270 static const struct KeysymNameReplacement aImplReplacements_Swedish[] =
271 {
272 { XK_Shift_L, "Skift" },
273 { XK_Shift_R, "Skift" },
274 { XK_Page_Up, "PageUp" },
275 { XK_Page_Down, "PageDown" },
276 { XK_Escape, "Esc" },
277 { XK_Right, "Höger" },
278 { XK_Left, "Vänster" },
279 { XK_Up, "Up" },
280 { XK_Down, "Ned" },
281 { XK_BackSpace, "Backsteg" },
282 { XK_Return, "Retur" },
283 { XK_space, "Blank" },
284 { SunXK_Stop, "Avbryt" },
285 { SunXK_Again, "Upprepa" },
286 { SunXK_Props, "Egenskaper" },
287 { SunXK_Undo, "Ångra" },
288 { SunXK_Front, "Fram" },
289 { SunXK_Copy, "Kopiera" },
290 { SunXK_Open, "Öppna" },
291 { SunXK_Paste, "Klistra in" },
292 { SunXK_Find, "Sök" },
293 { SunXK_Cut, "Klipp ut" },
294 { XK_minus, "-" },
295 { XK_plus, "+" }
296 };
297
298 static const struct KeysymNameReplacement aImplReplacements_Portuguese[] =
299 {
300 { XK_Page_Up, "PageUp" },
301 { XK_Page_Down, "PageDown" },
302 { XK_Escape, "Esc" },
303 { XK_Right, "Direita" },
304 { XK_Left, "Esquerda" },
305 { XK_Up, "Acima" },
306 { XK_Down, "Abaixo" },
307 { XK_BackSpace, "Backspace" },
308 { XK_Return, "Enter" },
309 { XK_slash, "Barra" },
310 { SunXK_Stop, "Stop" },
311 { SunXK_Again, "Again" },
312 { SunXK_Props, "Props" },
313 { SunXK_Undo, "Undo" },
314 { SunXK_Front, "Front" },
315 { SunXK_Copy, "Copy" },
316 { SunXK_Open, "Open" },
317 { SunXK_Paste, "Paste" },
318 { SunXK_Find, "Find" },
319 { SunXK_Cut, "Cut" },
320 { XK_minus, "-" },
321 { XK_plus, "+" }
322 };
323
324 static const struct KeysymNameReplacement aImplReplacements_Spanish[] =
325 {
326 { XK_Shift_L, "Mayús" },
327 { XK_Shift_R, "Mayús" },
328 { XK_Page_Up, "RePág" },
329 { XK_Page_Down, "AvPág" },
330 { XK_End, "Fin" },
331 { XK_Home, "Inicio" },
332 { XK_Delete, "Supr" },
333 { XK_Escape, "Esc" },
334 { XK_Right, "Hacia la derecha" },
335 { XK_Left, "Hacia la izquierda" },
336 { XK_Up, "Hacia arriba" },
337 { XK_Down, "Hacia abajo" },
338 { XK_BackSpace, "Ret" },
339 { XK_Return, "Entrada" },
340 { XK_space, "Espacio" },
341 { XK_KP_Enter, "Intro" },
342 { SunXK_Stop, "Stop" },
343 { SunXK_Again, "Repetir" },
344 { SunXK_Props, "Props" },
345 { SunXK_Undo, "Anular" },
346 { SunXK_Front, "Delante" },
347 { SunXK_Copy, "Copiar" },
348 { SunXK_Open, "Abrir" },
349 { SunXK_Paste, "Pegar" },
350 { SunXK_Find, "Buscar" },
351 { SunXK_Cut, "Cortar" },
352 { XK_minus, "-" },
353 { XK_plus, "+" }
354 };
355
356 static const struct KeyboardReplacements aKeyboards[] =
357 {
358 #ifdef SOLARIS
359 { "Germany5", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]) },
360 { "Germany4", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]) },
361 { "France5", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
362 { "France6", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
363 { "France_x86", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
364 { "Italy5", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
365 { "Italy5-Hobo", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
366 { "Italy4", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
367 { "Italy6", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
368 { "Italy_x86", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
369 { "Netherland4", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
370 { "Netherland5", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
371 { "Netherland5-Hobo", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
372 { "Netherland6", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
373 { "Netherland_x86", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
374 { "Norway5", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
375 { "Norway5-Hobo", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
376 { "Norway4", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
377 { "Norway6", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
378 { "Norway_x86", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
379 { "Portugal5", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
380 { "Portugal5-Hobo", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
381 { "Portugal4", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
382 { "Portugal6", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
383 { "Portugal_x86", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
384 { "Spain5", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
385 { "Spain5-Hobo", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
386 { "Spain4", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
387 { "Spain6", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
388 { "Spain_x86", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
389 { "Sweden5", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
390 { "Sweden5-Hobo", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
391 { "Sweden4", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
392 { "Sweden6", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
393 { "Sweden_x86", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
394 #endif
395 { "U.S. English", aImplReplacements_English, sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) },
396 { "United Kingdom", aImplReplacements_English, sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) },
397 // Germany, German
398 { "German", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]) },
399 { "France", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
400 { "French", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
401 // Italy, Italian
402 { "Ital", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
403 // Norway, Norwegian
404 { "Norw", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
405 // Portugal, Portuguese
406 { "Portu", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
407 { "Spain", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
408 { "Spanish", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
409 // Sweden, Swedish
410 { "Swed", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
411 { "Netherland", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
412 { "Dutch", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
413 // Turkish, Turkey
414 { "Turk", aImplReplacements_Turkish, sizeof(aImplReplacements_Turkish)/sizeof(aImplReplacements_Turkish[0]) },
415 // Russian, Russia
416 { "Russia", aImplReplacements_Russian, sizeof(aImplReplacements_Russian)/sizeof(aImplReplacements_Russian[0]) },
417 { "English", aImplReplacements_English, sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) }
418 };
419
getKeysymReplacementName(const char * pKeyboard,KeySym nSymbol)420 String getKeysymReplacementName( const char* pKeyboard, KeySym nSymbol )
421 {
422 for( unsigned int n = 0; n < sizeof(aKeyboards)/sizeof(aKeyboards[0]); n++ )
423 {
424 if( ! strncasecmp( pKeyboard, aKeyboards[n].pKeyboardName, strlen( aKeyboards[n].pKeyboardName ) ) )
425 {
426 const struct KeysymNameReplacement* pRepl = aKeyboards[n].pReplacements;
427 for( int m = aKeyboards[n].nReplacements ; m ; )
428 {
429 if( nSymbol == pRepl[--m].aSymbol )
430 return String( pRepl[m].pName, RTL_TEXTENCODING_UTF8 );
431 }
432 }
433 }
434 // try english fallbacks
435 const struct KeysymNameReplacement* pRepl = aImplReplacements_English;
436 for( int m = sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) ; m ; )
437 {
438 if( nSymbol == pRepl[--m].aSymbol )
439 return String( pRepl[m].pName, RTL_TEXTENCODING_UTF8 );
440 }
441 return String();
442 }
443
444 }
445
446 #ifdef SOLARIS
447 typedef struct {
448 int n_layout;
449 const char* p_description;
450 } keyboard_layout;
451
452 static const keyboard_layout type0_layout[] =
453 {
454 { 0, "US4" },
455 { -1, NULL }
456 };
457
458 static const keyboard_layout type3_layout[] =
459 {
460 { 0, "US3" },
461 { -1, NULL }
462 };
463
464 static const keyboard_layout type4_layout[] =
465 {
466 { 0, "US4" },
467 { 1, "US4" },
468 { 2, "FranceBelg4" },
469 { 3, "Canada4" },
470 { 4, "Denmark4" },
471 { 5, "Germany4" },
472 { 6, "Italy4" },
473 { 7, "Netherland4" },
474 { 8, "Norway4" },
475 { 9, "Portugal4" },
476 { 10, "SpainLatAm4" },
477 { 11, "SwedenFin4" },
478 { 12, "Switzer_Fr4" },
479 { 13, "Switzer_Ge4" },
480 { 14, "UK4" },
481 { 16, "Korea4" },
482 { 17, "Taiwan4" },
483 { 19, "US101A_PC" },
484 { 19, "US101A_Sun" },
485 { 32, "Japan4" },
486 { 33, "US5" },
487 { 34, "US_UNIX5" },
488 { 35, "France5" },
489 { 36, "Denmark5" },
490 { 37, "Germany5" },
491 { 38, "Italy5" },
492 { 39, "Netherland5" },
493 { 40, "Norway5" },
494 { 41, "Portugal5" },
495 { 42, "Spain5" },
496 { 43, "Sweden5" },
497 { 44, "Switzer_Fr5" },
498 { 45, "Switzer_Ge5" },
499 { 46, "UK5" },
500 { 47, "Korea5" },
501 { 48, "Taiwan5" },
502 { 49, "Japan5" },
503 { 50, "Canada_Fr5" },
504 { 51, "Hungary5" },
505 { 52, "Poland5" },
506 { 53, "Czech5" },
507 { 54, "Russia5" },
508 { 55, "Latvia5" },
509 { 56, "Turkey5" },
510 { 57, "Greece5" },
511 { 58, "Estonia5" },
512 { 59, "Lithuania5" },
513 { 63, "Canada_Fr5_TBITS5" },
514 { 80, "US5_Hobo" },
515 { 81, "US_UNIX5_Hobo" },
516 { 82, "France5_Hobo" },
517 { 83, "Denmark5_Hobo" },
518 { 84, "Germany5_Hobo" },
519 { 85, "Italy5_Hobo" },
520 { 86, "Netherland5_Hobo" },
521 { 87, "Norway5_Hobo" },
522 { 88, "Portugal5_Hobo" },
523 { 89, "Spain5_Hobo" },
524 { 90, "Sweden5_Hobo" },
525 { 91, "Switzer_Fr5_Hobo" },
526 { 92, "Switzer_Ge5_Hobo" },
527 { 93, "UK5_Hobo" },
528 { 94, "Korea5_Hobo" },
529 { 95, "Taiwan5_Hobo" },
530 { 96, "Japan5_Hobo" },
531 { 97, "Canada_Fr5_Hobo" },
532 { -1, NULL }
533 };
534
535 static const keyboard_layout type101_layout[] =
536 {
537 { 0, "US101A_x86" },
538 { 1, "US101A_x86" },
539 { 34, "J3100_x86" },
540 { 35, "France_x86" },
541 { 36, "Denmark_x86" },
542 { 37, "Germany_x86" },
543 { 38, "Italy_x86" },
544 { 39, "Netherland_x86" },
545 { 40, "Norway_x86" },
546 { 41, "Portugal_x86" },
547 { 42, "Spain_x86" },
548 { 43, "Sweden_x86" },
549 { 44, "Switzer_Fr_x86" },
550 { 45, "Switzer_Ge_x86" },
551 { 46, "UK_x86" },
552 { 47, "Korea_x86" },
553 { 48, "Taiwan_x86" },
554 { 49, "Japan_x86" },
555 { 50, "Canada_Fr2_x86" },
556 { 51, "Hungary_x86" },
557 { 52, "Poland_x86" },
558 { 53, "Czech_x86" },
559 { 54, "Russia_x86" },
560 { 55, "Latvia_x86" },
561 { 56, "Turkey_x86" },
562 { 57, "Greece_x86" },
563 { 59, "Lithuania_x86" },
564 { 1001, "MS_US101A_x86" },
565 { -1, NULL }
566 };
567
568 static const keyboard_layout type6_layout[] =
569 {
570 { 0, "US6" },
571 { 6, "Denmark6" },
572 { 7, "Finnish6" },
573 { 8, "France6" },
574 { 9, "Germany6" },
575 { 14, "Italy6" },
576 { 15, "Japan6" },
577 { 16, "Korea6" },
578 { 18, "Netherland6" },
579 { 19, "Norway6" },
580 { 22, "Portugal6" },
581 { 25, "Spain6" },
582 { 26, "Sweden6" },
583 { 27, "Switzer_Fr6" },
584 { 28, "Switzer_Ge6" },
585 { 30, "Taiwan6" },
586 { 32, "UK6" },
587 { 33, "US6" },
588 { -1, NULL }
589 };
590 #endif
591
592
593 #if OSL_DEBUG_LEVEL > 1
594 #include <stdio.h>
595 #endif
596
GetKeyboardName(sal_Bool bRefresh)597 const char* SalDisplay::GetKeyboardName( sal_Bool bRefresh )
598 {
599 if( bRefresh || ! m_aKeyboardName.Len() )
600 {
601 #ifdef SOLARIS
602 if( IsLocal() )
603 {
604 int kbd = open( "/dev/kbd", O_RDONLY );
605 if( kbd >= 0 )
606 {
607 int kbd_type = 0;
608 if( ! ioctl( kbd, KIOCTYPE, &kbd_type ) )
609 {
610 int kbd_layout = 0;
611 if( ! ioctl( kbd, KIOCLAYOUT, &kbd_layout ) )
612 {
613 const keyboard_layout *p_layout = NULL;
614 switch( kbd_type )
615 {
616 case KB_KLUNK: p_layout = type0_layout; break;
617 case KB_SUN3: p_layout = type3_layout; break;
618 case KB_SUN4: p_layout = type4_layout; break;
619 case KB_USB: p_layout = type6_layout; break;
620 case KB_PC: p_layout = type101_layout; break;
621 }
622
623 if( p_layout )
624 {
625 while( p_layout->n_layout != -1 )
626 {
627 if ( p_layout->n_layout == kbd_layout )
628 {
629 m_aKeyboardName = p_layout->p_description;
630 break;
631 }
632 p_layout++;
633 }
634 }
635 }
636 }
637 close(kbd);
638 }
639 }
640 #else
641 int opcode, event, error;
642 int major = XkbMajorVersion, minor = XkbMinorVersion;
643 if( XkbQueryExtension( GetDisplay(), &opcode, &event,&error, &major, &minor ) )
644 {
645 XkbDescPtr pXkbDesc = NULL;
646 // try X keyboard extension
647 if( (pXkbDesc = XkbGetKeyboard( GetDisplay(), XkbAllComponentsMask, XkbUseCoreKbd )) )
648 {
649 const char* pAtom = NULL;
650 if( pXkbDesc->names->groups[0] )
651 {
652 pAtom = XGetAtomName( GetDisplay(), pXkbDesc->names->groups[0] );
653 m_aKeyboardName = pAtom;
654 XFree( (void*)pAtom );
655 }
656 else
657 m_aKeyboardName = "<unknown keyboard>";
658 #if OSL_DEBUG_LEVEL > 1
659 #define PRINT_ATOM( x ) { if( pXkbDesc->names->x ) { pAtom = XGetAtomName( GetDisplay(), pXkbDesc->names->x ); fprintf( stderr, "%s: %s\n", #x, pAtom ); XFree( (void*)pAtom ); } else fprintf( stderr, "%s: <nil>\n", #x ); }
660
661 PRINT_ATOM( keycodes );
662 PRINT_ATOM( geometry );
663 PRINT_ATOM( symbols );
664 PRINT_ATOM( types );
665 PRINT_ATOM( compat );
666 PRINT_ATOM( phys_symbols );
667
668 #define PRINT_ATOM_2( x ) { if( pXkbDesc->names->x[i] ) { pAtom = XGetAtomName( GetDisplay(), pXkbDesc->names->x[i] ); fprintf( stderr, "%s[%d]: %s\n", #x, i, pAtom ); XFree( (void*)pAtom ); } else fprintf( stderr, "%s[%d]: <nil>\n", #x, i ); }
669 int i;
670 for( i = 0; i < XkbNumVirtualMods; i++ )
671 PRINT_ATOM_2( vmods );
672 for( i = 0; i < XkbNumIndicators; i++ )
673 PRINT_ATOM_2( indicators );
674 for( i = 0; i < XkbNumKbdGroups; i++ )
675 PRINT_ATOM_2( groups );
676 #endif
677 XkbFreeKeyboard( pXkbDesc, XkbAllComponentsMask, True );
678 }
679 }
680 #endif
681 if( ! m_aKeyboardName.Len() )
682 m_aKeyboardName = "<unknown keyboard>";
683 }
684 return m_aKeyboardName.GetBuffer();
685 }
686