xref: /AOO41X/main/vcl/unx/generic/app/keysymnames.cxx (revision c82f28778d59b20a7e6c0f9982d1bc73807a432a)
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_KP_Enter, "Entrée" },
171         { SunXK_Stop,  "Stop" },
172         { SunXK_Again, "Encore" },
173         { SunXK_Props, "Props" },
174         { SunXK_Undo,  "Annuler" },
175         { SunXK_Front, "Devant" },
176         { SunXK_Copy,  "Copy" },
177         { SunXK_Open,  "Ouvrir" },
178         { SunXK_Paste, "Coller" },
179         { SunXK_Find,  "Cher." },
180         { SunXK_Cut,   "Couper" },
181         { XK_minus, "-" },
182         { XK_plus, "+" }
183     };
184 
185     static const struct KeysymNameReplacement aImplReplacements_Italian[] =
186     {
187         { XK_Shift_L, "Maiusc" },
188         { XK_Shift_R, "Maiusc" },
189         { XK_Page_Up, "PgSu" },
190         { XK_Page_Down, "PgGiu" },
191         { XK_End, "Fine" },
192         { XK_Insert, "Ins" },
193         { XK_Delete, "Canc" },
194         { XK_Escape, "Esc" },
195         { XK_Right, "A destra" },
196         { XK_Left, "A sinistra" },
197         { XK_Up, "Sposta verso l'alto" },
198         { XK_Down, "Sposta verso il basso" },
199         { XK_BackSpace, "Backspace" },
200         { XK_Return, "Invio" },
201         { XK_space, "Spazio" },
202         { SunXK_Stop,  "Stop" },
203         { SunXK_Again, "Ancora" },
204         { SunXK_Props, "Proprietà" },
205         { SunXK_Undo,  "Annulla" },
206         { SunXK_Front, "Davanti" },
207         { SunXK_Copy,  "Copia" },
208         { SunXK_Open,  "Apri" },
209         { SunXK_Paste, "Incolla" },
210         { SunXK_Find,  "Trova" },
211         { SunXK_Cut,   "Taglia" },
212         { XK_minus, "-" },
213         { XK_plus, "+" }
214     };
215 
216     static const struct KeysymNameReplacement aImplReplacements_Dutch[] =
217     {
218         { XK_Page_Up, "PageUp" },
219         { XK_Page_Down, "PageDown" },
220         { XK_Escape, "Esc" },
221         { XK_Right, "Rechts" },
222         { XK_Left, "Links" },
223         { XK_Up, "Boven" },
224         { XK_Down, "Onder" },
225         { XK_BackSpace, "Backspace" },
226         { XK_Return, "Return" },
227         { XK_space, "Spatiebalk" },
228         { SunXK_Stop,  "Stop" },
229         { SunXK_Again, "Again" },
230         { SunXK_Props, "Props" },
231         { SunXK_Undo,  "Undo" },
232         { SunXK_Front, "Front" },
233         { SunXK_Copy,  "Copy" },
234         { SunXK_Open,  "Open" },
235         { SunXK_Paste, "Paste" },
236         { SunXK_Find,  "Find" },
237         { SunXK_Cut,   "Cut" },
238         { XK_minus, "-" },
239         { XK_plus, "+" }
240     };
241 
242     static const struct KeysymNameReplacement aImplReplacements_Norwegian[] =
243     {
244         { XK_Shift_L, "Skift" },
245         { XK_Shift_R, "Skift" },
246         { XK_Page_Up, "PageUp" },
247         { XK_Page_Down, "PageDown" },
248         { XK_Escape, "Esc" },
249         { XK_Right, "Hyre" },
250         { XK_Left, "Venstre" },
251         { XK_Up, "Opp" },
252         { XK_Down, "Ned" },
253         { XK_BackSpace, "Tilbake" },
254         { XK_Return, "Enter" },
255         { SunXK_Stop,  "Avbryt" },
256         { SunXK_Again, "Gjenta" },
257         { SunXK_Props, "Egenskaper" },
258         { SunXK_Undo,  "Angre" },
259         { SunXK_Front, "Front" },
260         { SunXK_Copy,  "Kopi" },
261         { SunXK_Open,  "Åpne" },
262         { SunXK_Paste, "Lim" },
263         { SunXK_Find,  "Søk" },
264         { SunXK_Cut,   "Klipp" },
265         { XK_minus, "-" },
266         { XK_plus, "+" }
267     };
268 
269     static const struct KeysymNameReplacement aImplReplacements_Swedish[] =
270     {
271         { XK_Shift_L, "Skift" },
272         { XK_Shift_R, "Skift" },
273         { XK_Page_Up, "PageUp" },
274         { XK_Page_Down, "PageDown" },
275         { XK_Escape, "Esc" },
276         { XK_Right, "Höger" },
277         { XK_Left, "Vänster" },
278         { XK_Up, "Up" },
279         { XK_Down, "Ned" },
280         { XK_BackSpace, "Backsteg" },
281         { XK_Return, "Retur" },
282         { XK_space, "Blank" },
283         { SunXK_Stop,  "Avbryt" },
284         { SunXK_Again, "Upprepa" },
285         { SunXK_Props, "Egenskaper" },
286         { SunXK_Undo,  "Ångra" },
287         { SunXK_Front, "Fram" },
288         { SunXK_Copy,  "Kopiera" },
289         { SunXK_Open,  "Öppna" },
290         { SunXK_Paste, "Klistra in" },
291         { SunXK_Find,  "Sök" },
292         { SunXK_Cut,   "Klipp ut" },
293         { XK_minus, "-" },
294         { XK_plus, "+" }
295     };
296 
297     static const struct KeysymNameReplacement aImplReplacements_Portuguese[] =
298     {
299         { XK_Page_Up, "PageUp" },
300         { XK_Page_Down, "PageDown" },
301         { XK_Escape, "Esc" },
302         { XK_Right, "Direita" },
303         { XK_Left, "Esquerda" },
304         { XK_Up, "Acima" },
305         { XK_Down, "Abaixo" },
306         { XK_BackSpace, "Backspace" },
307         { XK_Return, "Enter" },
308         { XK_slash, "Barra" },
309         { SunXK_Stop,  "Stop" },
310         { SunXK_Again, "Again" },
311         { SunXK_Props, "Props" },
312         { SunXK_Undo,  "Undo" },
313         { SunXK_Front, "Front" },
314         { SunXK_Copy,  "Copy" },
315         { SunXK_Open,  "Open" },
316         { SunXK_Paste, "Paste" },
317         { SunXK_Find,  "Find" },
318         { SunXK_Cut,   "Cut" },
319         { XK_minus, "-" },
320         { XK_plus, "+" }
321     };
322 
323     static const struct KeysymNameReplacement aImplReplacements_Spanish[] =
324     {
325         { XK_Shift_L, "Mayús" },
326         { XK_Shift_R, "Mayús" },
327         { XK_Page_Up, "RePág" },
328         { XK_Page_Down, "AvPág" },
329         { XK_End, "Fin" },
330         { XK_Home, "Inicio" },
331         { XK_Delete, "Supr" },
332         { XK_Escape, "Esc" },
333         { XK_Right, "Hacia la derecha" },
334         { XK_Left, "Hacia la izquierda" },
335         { XK_Up, "Hacia arriba" },
336         { XK_Down, "Hacia abajo" },
337         { XK_BackSpace, "Ret" },
338         { XK_Return, "Entrada" },
339         { XK_space, "Espacio" },
340         { XK_KP_Enter, "Intro" },
341         { SunXK_Stop,  "Stop" },
342         { SunXK_Again, "Repetir" },
343         { SunXK_Props, "Props" },
344         { SunXK_Undo,  "Anular" },
345         { SunXK_Front, "Delante" },
346         { SunXK_Copy,  "Copiar" },
347         { SunXK_Open,  "Abrir" },
348         { SunXK_Paste, "Pegar" },
349         { SunXK_Find,  "Buscar" },
350         { SunXK_Cut,   "Cortar" },
351         { XK_minus, "-" },
352         { XK_plus, "+" }
353     };
354 
355     static const struct KeyboardReplacements aKeyboards[] =
356     {
357 #ifdef SOLARIS
358         { "Germany5", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]) },
359         { "Germany4", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]) },
360         { "France5", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
361         { "France6", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
362         { "France_x86", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
363         { "Italy5", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
364         { "Italy5-Hobo", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
365         { "Italy4", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
366         { "Italy6", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
367         { "Italy_x86", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
368         { "Netherland4", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
369         { "Netherland5", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
370         { "Netherland5-Hobo", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
371         { "Netherland6", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
372         { "Netherland_x86", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
373         { "Norway5", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
374         { "Norway5-Hobo", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
375         { "Norway4", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
376         { "Norway6", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
377         { "Norway_x86", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
378         { "Portugal5", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
379         { "Portugal5-Hobo", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
380         { "Portugal4", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
381         { "Portugal6", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
382         { "Portugal_x86", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
383         { "Spain5", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
384         { "Spain5-Hobo", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
385         { "Spain4", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
386         { "Spain6", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
387         { "Spain_x86", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
388         { "Sweden5", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
389         { "Sweden5-Hobo", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
390         { "Sweden4", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
391         { "Sweden6", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
392         { "Sweden_x86", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
393 #endif
394         { "U.S. English", aImplReplacements_English, sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) },
395         { "United Kingdom", aImplReplacements_English, sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) },
396         // Germany, German
397         { "German", aImplReplacements_German, sizeof(aImplReplacements_German)/sizeof(aImplReplacements_German[0]) },
398         { "France", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
399         { "French", aImplReplacements_French, sizeof(aImplReplacements_French)/sizeof(aImplReplacements_French[0]) },
400         // Italy, Italian
401         { "Ital", aImplReplacements_Italian, sizeof(aImplReplacements_Italian)/sizeof(aImplReplacements_Italian[0]) },
402         // Norway, Norwegian
403         { "Norw", aImplReplacements_Norwegian, sizeof(aImplReplacements_Norwegian)/sizeof(aImplReplacements_Norwegian[0]) },
404         // Portugal, Portuguese
405         { "Portu", aImplReplacements_Portuguese, sizeof(aImplReplacements_Portuguese)/sizeof(aImplReplacements_Portuguese[0]) },
406         { "Spain", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
407         { "Spanish", aImplReplacements_Spanish, sizeof(aImplReplacements_Spanish)/sizeof(aImplReplacements_Spanish[0]) },
408         // Sweden, Swedish
409         { "Swed", aImplReplacements_Swedish, sizeof(aImplReplacements_Swedish)/sizeof(aImplReplacements_Swedish[0]) },
410         { "Netherland", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
411         { "Dutch", aImplReplacements_Dutch, sizeof(aImplReplacements_Dutch)/sizeof(aImplReplacements_Dutch[0]) },
412         // Turkish, Turkey
413         { "Turk", aImplReplacements_Turkish, sizeof(aImplReplacements_Turkish)/sizeof(aImplReplacements_Turkish[0]) },
414         // Russian, Russia
415         { "Russia", aImplReplacements_Russian, sizeof(aImplReplacements_Russian)/sizeof(aImplReplacements_Russian[0]) },
416         { "English", aImplReplacements_English, sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) }
417     };
418 
getKeysymReplacementName(const char * pKeyboard,KeySym nSymbol)419     String getKeysymReplacementName( const char* pKeyboard, KeySym nSymbol )
420     {
421         for( unsigned int n = 0; n < sizeof(aKeyboards)/sizeof(aKeyboards[0]); n++ )
422         {
423             if( ! strncasecmp( pKeyboard, aKeyboards[n].pKeyboardName, strlen( aKeyboards[n].pKeyboardName ) ) )
424             {
425                 const struct KeysymNameReplacement* pRepl = aKeyboards[n].pReplacements;
426                 for( int m = aKeyboards[n].nReplacements ; m ; )
427                 {
428                     if( nSymbol == pRepl[--m].aSymbol )
429                         return String( pRepl[m].pName, RTL_TEXTENCODING_UTF8 );
430                 }
431             }
432         }
433         // try english fallbacks
434         const struct KeysymNameReplacement* pRepl = aImplReplacements_English;
435         for( int m = sizeof(aImplReplacements_English)/sizeof(aImplReplacements_English[0]) ; m ; )
436         {
437             if( nSymbol == pRepl[--m].aSymbol )
438                 return String( pRepl[m].pName, RTL_TEXTENCODING_UTF8 );
439         }
440         return String();
441     }
442 
443 }
444 
445 #ifdef SOLARIS
446 typedef struct {
447     int         n_layout;
448     const char* p_description;
449 } keyboard_layout;
450 
451 static const keyboard_layout type0_layout[] =
452 {
453     { 0, "US4" },
454     { -1, NULL }
455 };
456 
457 static const keyboard_layout type3_layout[] =
458 {
459     { 0, "US3" },
460     { -1, NULL }
461 };
462 
463 static const keyboard_layout type4_layout[] =
464 {
465     { 0,  "US4" },
466     { 1,  "US4" },
467     { 2,  "FranceBelg4" },
468     { 3,  "Canada4" },
469     { 4,  "Denmark4" },
470     { 5,  "Germany4" },
471     { 6,  "Italy4" },
472     { 7,  "Netherland4" },
473     { 8,  "Norway4" },
474     { 9,  "Portugal4" },
475     { 10, "SpainLatAm4" },
476     { 11, "SwedenFin4" },
477     { 12, "Switzer_Fr4" },
478     { 13, "Switzer_Ge4" },
479     { 14, "UK4" },
480     { 16, "Korea4" },
481     { 17, "Taiwan4" },
482     { 19, "US101A_PC" },
483     { 19, "US101A_Sun" },
484     { 32, "Japan4" },
485     { 33, "US5" },
486     { 34, "US_UNIX5" },
487     { 35, "France5" },
488     { 36, "Denmark5" },
489     { 37, "Germany5" },
490     { 38, "Italy5" },
491     { 39, "Netherland5" },
492     { 40, "Norway5" },
493     { 41, "Portugal5" },
494     { 42, "Spain5" },
495     { 43, "Sweden5" },
496     { 44, "Switzer_Fr5" },
497     { 45, "Switzer_Ge5" },
498     { 46, "UK5" },
499     { 47, "Korea5" },
500     { 48, "Taiwan5" },
501     { 49, "Japan5" },
502     { 50, "Canada_Fr5" },
503     { 51, "Hungary5" },
504     { 52, "Poland5" },
505     { 53, "Czech5" },
506     { 54, "Russia5" },
507     { 55, "Latvia5" },
508     { 56, "Turkey5" },
509     { 57, "Greece5" },
510     { 58, "Estonia5" },
511     { 59, "Lithuania5" },
512     { 63, "Canada_Fr5_TBITS5" },
513     { 80, "US5_Hobo" },
514     { 81, "US_UNIX5_Hobo" },
515     { 82, "France5_Hobo" },
516     { 83, "Denmark5_Hobo" },
517     { 84, "Germany5_Hobo" },
518     { 85, "Italy5_Hobo" },
519     { 86, "Netherland5_Hobo" },
520     { 87, "Norway5_Hobo" },
521     { 88, "Portugal5_Hobo" },
522     { 89, "Spain5_Hobo" },
523     { 90, "Sweden5_Hobo" },
524     { 91, "Switzer_Fr5_Hobo" },
525     { 92, "Switzer_Ge5_Hobo" },
526     { 93, "UK5_Hobo" },
527     { 94, "Korea5_Hobo" },
528     { 95, "Taiwan5_Hobo" },
529     { 96, "Japan5_Hobo" },
530     { 97, "Canada_Fr5_Hobo" },
531     { -1, NULL }
532 };
533 
534 static const keyboard_layout type101_layout[] =
535 {
536     {  0, "US101A_x86" },
537     {  1, "US101A_x86" },
538     { 34, "J3100_x86" },
539     { 35, "France_x86" },
540     { 36, "Denmark_x86" },
541     { 37, "Germany_x86" },
542     { 38, "Italy_x86" },
543     { 39, "Netherland_x86" },
544     { 40, "Norway_x86" },
545     { 41, "Portugal_x86" },
546     { 42, "Spain_x86" },
547     { 43, "Sweden_x86" },
548     { 44, "Switzer_Fr_x86" },
549     { 45, "Switzer_Ge_x86" },
550     { 46, "UK_x86" },
551     { 47, "Korea_x86" },
552     { 48, "Taiwan_x86" },
553     { 49, "Japan_x86" },
554     { 50, "Canada_Fr2_x86" },
555     { 51, "Hungary_x86" },
556     { 52, "Poland_x86" },
557     { 53, "Czech_x86" },
558     { 54, "Russia_x86" },
559     { 55, "Latvia_x86" },
560     { 56, "Turkey_x86" },
561     { 57, "Greece_x86" },
562     { 59, "Lithuania_x86" },
563     { 1001, "MS_US101A_x86" },
564     { -1, NULL }
565 };
566 
567 static const keyboard_layout type6_layout[] =
568 {
569     { 0,  "US6" },
570     { 6,  "Denmark6" },
571     { 7,  "Finnish6" },
572     { 8,  "France6" },
573     { 9,  "Germany6" },
574     { 14, "Italy6" },
575     { 15, "Japan6" },
576     { 16, "Korea6" },
577     { 18, "Netherland6" },
578     { 19, "Norway6" },
579     { 22, "Portugal6" },
580     { 25, "Spain6" },
581     { 26, "Sweden6" },
582     { 27, "Switzer_Fr6" },
583     { 28, "Switzer_Ge6" },
584     { 30, "Taiwan6" },
585     { 32, "UK6" },
586     { 33, "US6" },
587     { -1, NULL }
588 };
589 #endif
590 
591 
592 #if OSL_DEBUG_LEVEL > 1
593 #include <stdio.h>
594 #endif
595 
GetKeyboardName(sal_Bool bRefresh)596 const char* SalDisplay::GetKeyboardName( sal_Bool bRefresh )
597 {
598     if( bRefresh || ! m_aKeyboardName.Len() )
599     {
600 #ifdef SOLARIS
601         if( IsLocal() )
602         {
603             int kbd = open( "/dev/kbd", O_RDONLY );
604             if( kbd >= 0 )
605             {
606                 int kbd_type = 0;
607                 if( ! ioctl( kbd, KIOCTYPE, &kbd_type ) )
608                 {
609                     int kbd_layout = 0;
610                     if( ! ioctl( kbd, KIOCLAYOUT, &kbd_layout ) )
611                     {
612                         const keyboard_layout *p_layout = NULL;
613                         switch( kbd_type )
614                         {
615                             case KB_KLUNK: p_layout = type0_layout;   break;
616                             case KB_SUN3:  p_layout = type3_layout;   break;
617                             case KB_SUN4:  p_layout = type4_layout;   break;
618                             case KB_USB:   p_layout = type6_layout;   break;
619                             case KB_PC:    p_layout = type101_layout; break;
620                         }
621 
622                         if( p_layout )
623                         {
624                             while( p_layout->n_layout != -1 )
625                             {
626                                 if ( p_layout->n_layout == kbd_layout )
627                                 {
628                                     m_aKeyboardName = p_layout->p_description;
629                                     break;
630                                 }
631                                 p_layout++;
632                             }
633                         }
634                     }
635                 }
636                 close(kbd);
637             }
638         }
639 #else
640         int opcode, event, error;
641         int major = XkbMajorVersion, minor = XkbMinorVersion;
642         if( XkbQueryExtension( GetDisplay(), &opcode, &event,&error, &major, &minor ) )
643         {
644             XkbDescPtr pXkbDesc = NULL;
645             // try X keyboard extension
646             if( (pXkbDesc = XkbGetKeyboard( GetDisplay(), XkbAllComponentsMask, XkbUseCoreKbd )) )
647             {
648                 const char* pAtom = NULL;
649                 if( pXkbDesc->names->groups[0] )
650                 {
651                     pAtom = XGetAtomName( GetDisplay(), pXkbDesc->names->groups[0] );
652                     m_aKeyboardName = pAtom;
653                     XFree( (void*)pAtom );
654                 }
655                 else
656                     m_aKeyboardName = "<unknown keyboard>";
657 #if OSL_DEBUG_LEVEL > 1
658 #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 ); }
659 
660                 PRINT_ATOM( keycodes );
661                 PRINT_ATOM( geometry );
662                 PRINT_ATOM( symbols );
663                 PRINT_ATOM( types );
664                 PRINT_ATOM( compat );
665                 PRINT_ATOM( phys_symbols );
666 
667 #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 ); }
668                 int i;
669                 for( i = 0; i < XkbNumVirtualMods; i++ )
670                     PRINT_ATOM_2( vmods );
671                 for( i = 0; i < XkbNumIndicators; i++ )
672                     PRINT_ATOM_2( indicators );
673                 for( i = 0; i < XkbNumKbdGroups; i++ )
674                     PRINT_ATOM_2( groups );
675 #endif
676                 XkbFreeKeyboard( pXkbDesc, XkbAllComponentsMask, True );
677             }
678         }
679 #endif
680         if( ! m_aKeyboardName.Len() )
681             m_aKeyboardName = "<unknown keyboard>";
682     }
683     return m_aKeyboardName.GetBuffer();
684 }
685