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