xref: /trunk/main/vcl/unx/generic/app/keysymnames.cxx (revision fe912e68)
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