]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkkeys-win32.c
[gdk] Add gdk_keymap_get_num_lock_state
[~andy/gtk] / gdk / win32 / gdkkeys-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25  */
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <limits.h>
31 #include <errno.h>
32
33 #include "gdk.h"
34
35 #include "gdkprivate-win32.h"
36 #include "gdkinternals.h"
37 #include "gdkkeysyms.h"
38
39 #include "config.h"
40
41 guint _gdk_keymap_serial = 0;
42 gboolean _gdk_keyboard_has_altgr = FALSE;
43 guint _scancode_rshift = 0;
44
45 static GdkModifierType gdk_shift_modifiers = GDK_SHIFT_MASK;
46
47 static GdkKeymap *default_keymap = NULL;
48
49 static guint *keysym_tab = NULL;
50
51 #ifdef G_ENABLE_DEBUG
52 static void
53 print_keysym_tab (void)
54 {
55   gint vk;
56   
57   g_print ("keymap:%s%s\n",
58            _gdk_keyboard_has_altgr ? " (uses AltGr)" : "",
59            (gdk_shift_modifiers & GDK_LOCK_MASK) ? " (has ShiftLock)" : "");
60   for (vk = 0; vk < 256; vk++)
61     {
62       gint state;
63       
64       g_print ("%#.02x: ", vk);
65       for (state = 0; state < 4; state++)
66         {
67           gchar *name = gdk_keyval_name (keysym_tab[vk*4 + state]);
68           if (name == NULL)
69             name = "(none)";
70           g_print ("%s ", name);
71         }
72       g_print ("\n");
73     }
74 }
75 #endif
76
77 static void
78 handle_special (guint  vk,
79                 guint *ksymp,
80                 gint   shift)
81
82 {
83   switch (vk)
84     {
85     case VK_CANCEL:
86       *ksymp = GDK_Cancel; break;
87     case VK_BACK:
88       *ksymp = GDK_BackSpace; break;
89     case VK_TAB:
90       if (shift & 0x1)
91         *ksymp = GDK_ISO_Left_Tab;
92       else
93         *ksymp = GDK_Tab;
94       break;
95     case VK_CLEAR:
96       *ksymp = GDK_Clear; break;
97     case VK_RETURN:
98       *ksymp = GDK_Return; break;
99     case VK_SHIFT:
100     case VK_LSHIFT:
101       *ksymp = GDK_Shift_L; break;
102     case VK_CONTROL:
103     case VK_LCONTROL:
104       *ksymp = GDK_Control_L; break;
105     case VK_MENU:
106     case VK_LMENU:
107       *ksymp = GDK_Alt_L; break;
108     case VK_PAUSE:
109       *ksymp = GDK_Pause; break;
110     case VK_ESCAPE:
111       *ksymp = GDK_Escape; break;
112     case VK_PRIOR:
113       *ksymp = GDK_Prior; break;
114     case VK_NEXT:
115       *ksymp = GDK_Next; break;
116     case VK_END:
117       *ksymp = GDK_End; break;
118     case VK_HOME:
119       *ksymp = GDK_Home; break;
120     case VK_LEFT:
121       *ksymp = GDK_Left; break;
122     case VK_UP:
123       *ksymp = GDK_Up; break;
124     case VK_RIGHT:
125       *ksymp = GDK_Right; break;
126     case VK_DOWN:
127       *ksymp = GDK_Down; break;
128     case VK_SELECT:
129       *ksymp = GDK_Select; break;
130     case VK_PRINT:
131       *ksymp = GDK_Print; break;
132     case VK_EXECUTE:
133       *ksymp = GDK_Execute; break;
134     case VK_INSERT:
135       *ksymp = GDK_Insert; break;
136     case VK_DELETE:
137       *ksymp = GDK_Delete; break;
138     case VK_HELP:
139       *ksymp = GDK_Help; break;
140     case VK_LWIN:
141       *ksymp = GDK_Meta_L; break;
142     case VK_RWIN:
143       *ksymp = GDK_Meta_R; break;
144     case VK_APPS:
145       *ksymp = GDK_Menu; break;
146     case VK_MULTIPLY:
147       *ksymp = GDK_KP_Multiply; break;
148     case VK_ADD:
149       *ksymp = GDK_KP_Add; break;
150     case VK_SEPARATOR:
151       *ksymp = GDK_KP_Separator; break;
152     case VK_SUBTRACT:
153       *ksymp = GDK_KP_Subtract; break;
154     case VK_DIVIDE:
155       *ksymp = GDK_KP_Divide; break;
156     case VK_NUMPAD0:
157       *ksymp = GDK_KP_0; break;
158     case VK_NUMPAD1:
159       *ksymp = GDK_KP_1; break;
160     case VK_NUMPAD2:
161       *ksymp = GDK_KP_2; break;
162     case VK_NUMPAD3:
163       *ksymp = GDK_KP_3; break;
164     case VK_NUMPAD4:
165       *ksymp = GDK_KP_4; break;
166     case VK_NUMPAD5:
167       *ksymp = GDK_KP_5; break;
168     case VK_NUMPAD6:
169       *ksymp = GDK_KP_6; break;
170     case VK_NUMPAD7:
171       *ksymp = GDK_KP_7; break;
172     case VK_NUMPAD8:
173       *ksymp = GDK_KP_8; break;
174     case VK_NUMPAD9:
175       *ksymp = GDK_KP_9; break;
176     case VK_F1:
177       *ksymp = GDK_F1; break;
178     case VK_F2:
179       *ksymp = GDK_F2; break;
180     case VK_F3:
181       *ksymp = GDK_F3; break;
182     case VK_F4:
183       *ksymp = GDK_F4; break;
184     case VK_F5:
185       *ksymp = GDK_F5; break;
186     case VK_F6:
187       *ksymp = GDK_F6; break;
188     case VK_F7:
189       *ksymp = GDK_F7; break;
190     case VK_F8:
191       *ksymp = GDK_F8; break;
192     case VK_F9:
193       *ksymp = GDK_F9; break;
194     case VK_F10:
195       *ksymp = GDK_F10; break;
196     case VK_F11:
197       *ksymp = GDK_F11; break;
198     case VK_F12:
199       *ksymp = GDK_F12; break;
200     case VK_F13:
201       *ksymp = GDK_F13; break;
202     case VK_F14:
203       *ksymp = GDK_F14; break;
204     case VK_F15:
205       *ksymp = GDK_F15; break;
206     case VK_F16:
207       *ksymp = GDK_F16; break;
208     case VK_F17:
209       *ksymp = GDK_F17; break;
210     case VK_F18:
211       *ksymp = GDK_F18; break;
212     case VK_F19:
213       *ksymp = GDK_F19; break;
214     case VK_F20:
215       *ksymp = GDK_F20; break;
216     case VK_F21:
217       *ksymp = GDK_F21; break;
218     case VK_F22:
219       *ksymp = GDK_F22; break;
220     case VK_F23:
221       *ksymp = GDK_F23; break;
222     case VK_F24:
223       *ksymp = GDK_F24; break;
224     case VK_NUMLOCK:
225       *ksymp = GDK_Num_Lock; break;
226     case VK_SCROLL:
227       *ksymp = GDK_Scroll_Lock; break;
228     case VK_RSHIFT:
229       *ksymp = GDK_Shift_R; break;
230     case VK_RCONTROL:
231       *ksymp = GDK_Control_R; break;
232     case VK_RMENU:
233       *ksymp = GDK_Alt_R; break;
234     }
235 }
236
237 static void
238 set_shift_vks (guchar *key_state,
239                gint    shift)
240 {
241   switch (shift)
242     {
243     case 0:
244       key_state[VK_SHIFT] = 0;
245       key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
246       break;
247     case 1:
248       key_state[VK_SHIFT] = 0x80;
249       key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
250       break;
251     case 2:
252       key_state[VK_SHIFT] = 0;
253       key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80;
254       break;
255     case 3:
256       key_state[VK_SHIFT] = 0x80;
257       key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80;
258       break;
259     }
260 }
261
262 static void
263 reset_after_dead (guchar key_state[256])
264 {
265   guchar temp_key_state[256];
266   wchar_t wcs[2];
267
268   memmove (temp_key_state, key_state, sizeof (key_state));
269
270   temp_key_state[VK_SHIFT] =
271     temp_key_state[VK_CONTROL] =
272     temp_key_state[VK_MENU] = 0;
273
274   ToUnicodeEx (VK_SPACE, MapVirtualKey (VK_SPACE, 0),
275                temp_key_state, wcs, G_N_ELEMENTS (wcs),
276                0, _gdk_input_locale);
277 }
278
279 static void
280 handle_dead (guint  keysym,
281              guint *ksymp)
282 {
283   switch (keysym)
284     {
285     case '"': /* 0x022 */
286       *ksymp = GDK_dead_diaeresis; break;
287     case '\'': /* 0x027 */
288       *ksymp = GDK_dead_acute; break;
289     case GDK_asciicircum: /* 0x05e */
290       *ksymp = GDK_dead_circumflex; break;
291     case GDK_grave:     /* 0x060 */
292       *ksymp = GDK_dead_grave; break;
293     case GDK_asciitilde: /* 0x07e */
294       *ksymp = GDK_dead_tilde; break;
295     case GDK_diaeresis: /* 0x0a8 */
296       *ksymp = GDK_dead_diaeresis; break;
297     case GDK_degree: /* 0x0b0 */
298       *ksymp = GDK_dead_abovering; break;
299     case GDK_acute:     /* 0x0b4 */
300       *ksymp = GDK_dead_acute; break;
301     case GDK_periodcentered: /* 0x0b7 */
302       *ksymp = GDK_dead_abovedot; break;
303     case GDK_cedilla: /* 0x0b8 */
304       *ksymp = GDK_dead_cedilla; break;
305     case GDK_breve:     /* 0x1a2 */
306       *ksymp = GDK_dead_breve; break;
307     case GDK_ogonek: /* 0x1b2 */
308       *ksymp = GDK_dead_ogonek; break;
309     case GDK_caron:     /* 0x1b7 */
310       *ksymp = GDK_dead_caron; break;
311     case GDK_doubleacute: /* 0x1bd */
312       *ksymp = GDK_dead_doubleacute; break;
313     case GDK_abovedot: /* 0x1ff */
314       *ksymp = GDK_dead_abovedot; break;
315     case 0x1000384: /* Greek tonos */
316       *ksymp = GDK_dead_acute; break;
317     case GDK_Greek_accentdieresis: /* 0x7ae */
318       *ksymp = GDK_Greek_accentdieresis; break;
319     default:
320       /* By default use the keysym as such. This takes care of for
321        * instance the dead U+09CD (BENGALI VIRAMA) on the ekushey
322        * Bengali layout.
323        */
324       *ksymp = keysym; break;
325     }
326 }
327
328 static void
329 update_keymap (void)
330 {
331   static guint current_serial = 0;
332   guchar key_state[256];
333   guint scancode;
334   guint vk;
335   gboolean capslock_tested = FALSE;
336
337   if (keysym_tab != NULL && current_serial == _gdk_keymap_serial)
338     return;
339
340   current_serial = _gdk_keymap_serial;
341
342   if (keysym_tab == NULL)
343     keysym_tab = g_new (guint, 4*256);
344
345   memset (key_state, 0, sizeof (key_state));
346
347   _gdk_keyboard_has_altgr = FALSE;
348   gdk_shift_modifiers = GDK_SHIFT_MASK;
349
350   for (vk = 0; vk < 256; vk++)
351     {
352       if ((scancode = MapVirtualKey (vk, 0)) == 0 &&
353           vk != VK_DIVIDE)
354         keysym_tab[vk*4+0] =
355           keysym_tab[vk*4+1] =
356           keysym_tab[vk*4+2] =
357           keysym_tab[vk*4+3] = GDK_VoidSymbol;
358       else
359         {
360           gint shift;
361
362           if (vk == VK_RSHIFT)
363             _scancode_rshift = scancode;
364
365           key_state[vk] = 0x80;
366           for (shift = 0; shift < 4; shift++)
367             {
368               guint *ksymp = keysym_tab + vk*4 + shift;
369               
370               set_shift_vks (key_state, shift);
371
372               *ksymp = 0;
373
374               /* First, handle those virtual keys that we always want
375                * as special GDK_* keysyms, even if ToAsciiEx might
376                * turn some them into a ASCII character (like TAB and
377                * ESC).
378                */
379               handle_special (vk, ksymp, shift);
380
381               if (*ksymp == 0)
382                 {
383                   wchar_t wcs[10];
384                   gint k;
385
386                   wcs[0] = wcs[1] = 0;
387                   k = ToUnicodeEx (vk, scancode, key_state,
388                                    wcs, G_N_ELEMENTS (wcs),
389                                    0, _gdk_input_locale);
390 #if 0
391                   g_print ("ToUnicodeEx(%#02x, %d: %d): %d, %04x %04x\n",
392                            vk, scancode, shift, k,
393                            wcs[0], wcs[1]);
394 #endif
395                   if (k == 1)
396                     *ksymp = gdk_unicode_to_keyval (wcs[0]);
397                   else if (k == -1)
398                     {
399                       guint keysym = gdk_unicode_to_keyval (wcs[0]);
400
401                       /* It is a dead key, and it's has been stored in
402                        * the keyboard layout's state by
403                        * ToAsciiEx()/ToUnicodeEx(). Yes, this is an
404                        * incredibly silly API! Make the keyboard
405                        * layout forget it by calling
406                        * ToAsciiEx()/ToUnicodeEx() once more, with the
407                        * virtual key code and scancode for the
408                        * spacebar, without shift or AltGr. Otherwise
409                        * the next call to ToAsciiEx() with a different
410                        * key would try to combine with the dead key.
411                        */
412                       reset_after_dead (key_state);
413
414                       /* Use dead keysyms instead of "undead" ones */
415                       handle_dead (keysym, ksymp);
416                     }
417                   else if (k == 0)
418                     {
419                       /* Seems to be necessary to "reset" the keyboard layout
420                        * in this case, too. Otherwise problems on NT4.
421                        */
422                       reset_after_dead (key_state);
423                     }
424                   else
425                     {
426 #if 0
427                       GDK_NOTE (EVENTS,
428                                 g_print ("ToUnicodeEx returns %d "
429                                          "for vk:%02x, sc:%02x%s%s\n",
430                                          k, vk, scancode,
431                                          (shift&0x1 ? " shift" : ""),
432                                          (shift&0x2 ? " altgr" : "")));
433 #endif
434                     }
435                 }
436               if (*ksymp == 0)
437                 *ksymp = GDK_VoidSymbol;
438             }
439           key_state[vk] = 0;
440
441           /* Check if keyboard has an AltGr key by checking if
442            * the mapping with Control+Alt is different.
443            */
444           if (!_gdk_keyboard_has_altgr)
445             if ((keysym_tab[vk*4 + 2] != GDK_VoidSymbol &&
446                  keysym_tab[vk*4] != keysym_tab[vk*4 + 2]) ||
447                 (keysym_tab[vk*4 + 3] != GDK_VoidSymbol &&
448                  keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 3]))
449               _gdk_keyboard_has_altgr = TRUE;
450           
451           if (!capslock_tested)
452             {
453               /* Can we use this virtual key to determine the CapsLock
454                * key behaviour: CapsLock or ShiftLock? If it generates
455                * keysyms for printable characters and has a shifted
456                * keysym that isn't just the upperacase of the
457                * unshifted keysym, check the behaviour of VK_CAPITAL.
458                */
459               if (g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 0])) &&
460                   keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 0] &&
461                   g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 1])) &&
462                   keysym_tab[vk*4 + 1] != gdk_keyval_to_upper (keysym_tab[vk*4 + 0]))
463                 {
464                   guchar chars[2];
465                   
466                   capslock_tested = TRUE;
467                   
468                   key_state[VK_SHIFT] = 0;
469                   key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
470                   key_state[VK_CAPITAL] = 1;
471
472                   if (ToAsciiEx (vk, scancode, key_state,
473                                  (LPWORD) chars, 0, _gdk_input_locale) == 1)
474                     {
475                       if (chars[0] >= GDK_space &&
476                           chars[0] <= GDK_asciitilde &&
477                           chars[0] == keysym_tab[vk*4 + 1])
478                         {
479                           /* CapsLock acts as ShiftLock */
480                           gdk_shift_modifiers |= GDK_LOCK_MASK;
481                         }
482                     }
483                   key_state[VK_CAPITAL] = 0;
484                 }    
485             }
486         }
487     }
488   GDK_NOTE (EVENTS, print_keysym_tab ());
489
490
491 GdkKeymap*
492 gdk_keymap_get_for_display (GdkDisplay *display)
493 {
494   g_return_val_if_fail (display == gdk_display_get_default (), NULL);
495
496   if (default_keymap == NULL)
497     default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
498
499   return default_keymap;
500 }
501
502 PangoDirection
503 gdk_keymap_get_direction (GdkKeymap *keymap)
504 {
505   update_keymap ();
506
507   switch (PRIMARYLANGID (LOWORD ((DWORD) (gintptr) _gdk_input_locale)))
508     {
509     case LANG_HEBREW:
510     case LANG_ARABIC:
511 #ifdef LANG_URDU
512     case LANG_URDU:
513 #endif
514     case LANG_FARSI:
515       /* Others? */
516       return PANGO_DIRECTION_RTL;
517
518     default:
519       return PANGO_DIRECTION_LTR;
520     }
521 }
522
523 gboolean
524 gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
525 {
526   /* Should we check if the kayboard layouts switchable at the moment
527    * cover both directionalities? What does the doc comment in
528    * ../x11/gdkkeys-x11.c exactly mean?
529    */
530   return FALSE;
531 }
532
533 gboolean
534 gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
535 {
536   return ((GetKeyState (VK_CAPITAL) & 1) != 0);
537 }
538
539 gboolean
540 gdk_keymap_get_num_lock_state (GdkKeymap *keymap)
541 {
542   return ((GetKeyState (VK_NUMLOCK) & 1) != 0);
543 }
544
545 gboolean
546 gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
547                                    guint          keyval,
548                                    GdkKeymapKey **keys,
549                                    gint          *n_keys)
550 {
551   GArray *retval;
552
553   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
554   g_return_val_if_fail (keys != NULL, FALSE);
555   g_return_val_if_fail (n_keys != NULL, FALSE);
556   g_return_val_if_fail (keyval != 0, FALSE);
557   
558   retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
559
560   /* Accept only the default keymap */
561   if (keymap == NULL || keymap == gdk_keymap_get_default ())
562     {
563       gint vk;
564       
565       update_keymap ();
566
567       for (vk = 0; vk < 256; vk++)
568         {
569           gint i;
570
571           for (i = 0; i < 4; i++)
572             {
573               if (keysym_tab[vk*4+i] == keyval)
574                 {
575                   GdkKeymapKey key;
576                   
577                   key.keycode = vk;
578                   
579                   /* 2 levels (normal, shift), two groups (normal, AltGr) */
580                   key.group = i / 2;
581                   key.level = i % 2;
582                   
583                   g_array_append_val (retval, key);
584                 }
585             }
586         }
587     }
588
589 #ifdef G_ENABLE_DEBUG
590   if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
591     {
592       gint i;
593
594       g_print ("gdk_keymap_get_entries_for_keyval: %#.04x (%s):",
595                keyval, gdk_keyval_name (keyval));
596       for (i = 0; i < retval->len; i++)
597         {
598           GdkKeymapKey *entry = (GdkKeymapKey *) retval->data + i;
599           g_print ("  %#.02x %d %d", entry->keycode, entry->group, entry->level);
600         }
601       g_print ("\n");
602     }
603 #endif
604
605   if (retval->len > 0)
606     {
607       *keys = (GdkKeymapKey*) retval->data;
608       *n_keys = retval->len;
609     }
610   else
611     {
612       *keys = NULL;
613       *n_keys = 0;
614     }
615       
616   g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
617
618   return *n_keys > 0;
619 }
620
621 gboolean
622 gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
623                                     guint          hardware_keycode,
624                                     GdkKeymapKey **keys,
625                                     guint        **keyvals,
626                                     gint          *n_entries)
627 {
628   GArray *key_array;
629   GArray *keyval_array;
630
631   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
632   g_return_val_if_fail (n_entries != NULL, FALSE);
633
634   if (hardware_keycode <= 0 ||
635       hardware_keycode >= 256)
636     {
637       if (keys)
638         *keys = NULL;
639       if (keyvals)
640         *keyvals = NULL;
641
642       *n_entries = 0;
643       return FALSE;
644     }
645   
646   if (keys)
647     key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
648   else
649     key_array = NULL;
650   
651   if (keyvals)
652     keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
653   else
654     keyval_array = NULL;
655   
656   /* Accept only the default keymap */
657   if (keymap == NULL || keymap == gdk_keymap_get_default ())
658     {
659       gint i;
660
661       update_keymap ();
662
663       for (i = 0; i < 4; i++)
664         {
665           if (key_array)
666             {
667               GdkKeymapKey key;
668               
669               key.keycode = hardware_keycode;
670               
671               key.group = i / 2;
672               key.level = i % 2;
673               
674               g_array_append_val (key_array, key);
675             }
676
677           if (keyval_array)
678             g_array_append_val (keyval_array, keysym_tab[hardware_keycode*4+i]);
679         }
680     }
681
682   if ((key_array && key_array->len > 0) ||
683       (keyval_array && keyval_array->len > 0))
684     {
685       if (keys)
686         *keys = (GdkKeymapKey*) key_array->data;
687
688       if (keyvals)
689         *keyvals = (guint*) keyval_array->data;
690
691       if (key_array)
692         *n_entries = key_array->len;
693       else
694         *n_entries = keyval_array->len;
695     }
696   else
697     {
698       if (keys)
699         *keys = NULL;
700
701       if (keyvals)
702         *keyvals = NULL;
703       
704       *n_entries = 0;
705     }
706
707   if (key_array)
708     g_array_free (key_array, key_array->len > 0 ? FALSE : TRUE);
709   if (keyval_array)
710     g_array_free (keyval_array, keyval_array->len > 0 ? FALSE : TRUE);
711
712   return *n_entries > 0;
713 }
714
715 guint
716 gdk_keymap_lookup_key (GdkKeymap          *keymap,
717                        const GdkKeymapKey *key)
718 {
719   guint sym;
720
721   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
722   g_return_val_if_fail (key != NULL, 0);
723   g_return_val_if_fail (key->group < 4, 0);
724   
725   /* Accept only the default keymap */
726   if (keymap != NULL && keymap != gdk_keymap_get_default ())
727     return 0;
728
729   update_keymap ();
730   
731   if (key->keycode >= 256 ||
732       key->group < 0 || key->group >= 2 ||
733       key->level < 0 || key->level >= 2)
734     return 0;
735   
736   sym = keysym_tab[key->keycode*4 + key->group*2 + key->level];
737   
738   if (sym == GDK_VoidSymbol)
739     return 0;
740   else
741     return sym;
742 }
743
744 gboolean
745 gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
746                                      guint            hardware_keycode,
747                                      GdkModifierType  state,
748                                      gint             group,
749                                      guint           *keyval,
750                                      gint            *effective_group,
751                                      gint            *level,
752                                      GdkModifierType *consumed_modifiers)
753 {
754   guint tmp_keyval;
755   guint *keyvals;
756   gint shift_level;
757   gboolean ignore_shift = FALSE;
758   gboolean ignore_group = FALSE;
759       
760   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
761   g_return_val_if_fail (group < 4, FALSE);
762   
763 #if 0
764   GDK_NOTE (EVENTS, g_print ("gdk_keymap_translate_keyboard_state: keycode=%#x state=%#x group=%d\n",
765                              hardware_keycode, state, group));
766 #endif
767   if (keyval)
768     *keyval = 0;
769   if (effective_group)
770     *effective_group = 0;
771   if (level)
772     *level = 0;
773   if (consumed_modifiers)
774     *consumed_modifiers = 0;
775
776   /* Accept only the default keymap */
777   if (keymap != NULL && keymap != gdk_keymap_get_default ())
778     return FALSE;
779
780   if (hardware_keycode >= 256)
781     return FALSE;
782
783   if (group < 0 || group >= 2)
784     return FALSE;
785
786   update_keymap ();
787
788   keyvals = keysym_tab + hardware_keycode*4;
789
790   if ((state & GDK_LOCK_MASK) &&
791       (state & GDK_SHIFT_MASK) &&
792       ((gdk_shift_modifiers & GDK_LOCK_MASK) ||
793        (keyvals[group*2 + 1] == gdk_keyval_to_upper (keyvals[group*2 + 0]))))
794     /* Shift always disables ShiftLock. Shift disables CapsLock for
795      * keys with lowercase/uppercase letter pairs.
796      */
797     shift_level = 0;
798   else if (state & gdk_shift_modifiers)
799     shift_level = 1;
800   else
801     shift_level = 0;
802
803   /* Drop group and shift if there are no keysymbols on
804    * the key for those.
805    */
806   if (shift_level == 1 &&
807       keyvals[group*2 + 1] == GDK_VoidSymbol &&
808       keyvals[group*2] != GDK_VoidSymbol)
809     {
810       shift_level = 0;
811       ignore_shift = TRUE;
812     }
813
814   if (group == 1 &&
815       keyvals[2 + shift_level] == GDK_VoidSymbol &&
816       keyvals[0 + shift_level] != GDK_VoidSymbol)
817     {
818       group = 0;
819       ignore_group = TRUE;
820     }
821
822   if (keyvals[group *2 + shift_level] == GDK_VoidSymbol &&
823       keyvals[0 + 0] != GDK_VoidSymbol)
824     {
825       shift_level = 0;
826       group = 0;
827       ignore_group = TRUE;
828       ignore_shift = TRUE;
829     }
830
831   /* See whether the group and shift level actually mattered
832    * to know what to put in consumed_modifiers
833    */
834   if (keyvals[group*2 + 1] == GDK_VoidSymbol ||
835       keyvals[group*2 + 0] == keyvals[group*2 + 1])
836     ignore_shift = TRUE;
837
838   if (keyvals[2 + shift_level] == GDK_VoidSymbol ||
839       keyvals[0 + shift_level] == keyvals[2 + shift_level])
840     ignore_group = TRUE;
841
842   tmp_keyval = keyvals[group*2 + shift_level];
843
844   /* If a true CapsLock is toggled, and Shift is not down,
845    * and the shifted keysym is the uppercase of the unshifted,
846    * use it.
847    */
848   if (!(gdk_shift_modifiers & GDK_LOCK_MASK) &&
849       !(state & GDK_SHIFT_MASK) &&
850       (state & GDK_LOCK_MASK))
851     {
852       guint upper = gdk_keyval_to_upper (tmp_keyval);
853       if (upper == keyvals[group*2 + 1])
854         tmp_keyval = upper;
855     }
856
857   if (keyval)
858     *keyval = tmp_keyval;
859
860   if (effective_group)
861     *effective_group = group;
862
863   if (level)
864     *level = shift_level;
865
866   if (consumed_modifiers)
867     {
868       *consumed_modifiers =
869         (ignore_group ? 0 : GDK_MOD2_MASK) |
870         (ignore_shift ? 0 : (GDK_SHIFT_MASK|GDK_LOCK_MASK));
871     }
872                                 
873 #if 0
874   GDK_NOTE (EVENTS, g_print ("... group=%d level=%d cmods=%#x keyval=%s\n",
875                              group, shift_level, tmp_modifiers, gdk_keyval_name (tmp_keyval)));
876 #endif
877
878   return tmp_keyval != GDK_VoidSymbol;
879 }
880
881 void
882 gdk_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
883                                   GdkModifierType *state)
884 {
885 }
886
887 gboolean
888 gdk_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
889                                   GdkModifierType *state)
890 {
891   /* FIXME: Is this the right thing to do? */
892   return TRUE;
893 }