]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkkeyboard-fb.c
c5c8993ca691b959f3b17cd8cb0986489c4a71b3
[~andy/gtk] / gdk / linux-fb / gdkkeyboard-fb.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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 #include <gdk/gdk.h>
21 #include <gdk/gdkinternals.h>
22 #include "gdkkeysyms.h"
23 #include "gdkprivate-fb.h"
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <termios.h>
28 #include <sys/ioctl.h>
29 #include <sys/kd.h>
30 #include <sys/vt.h>
31
32 typedef struct _GdkFBKeyboard GdkFBKeyboard;
33 typedef struct _GdkFBKeyboardDevice GdkFBKeyboardDevice;
34
35 struct _GdkFBKeyboard {
36   gint fd;
37   GIOChannel *io;
38   gint io_tag;
39
40   guint modifier_state;
41   gboolean caps_lock : 1;
42
43   gint group;
44   gint level;
45   
46   GdkFBKeyboardDevice *dev;
47 };
48
49 struct _GdkFBKeyboardDevice {
50   char *name;
51   gboolean (*open)(GdkFBKeyboard *kb);
52   void (*close)(GdkFBKeyboard *kb);
53
54   guint    (*lookup_key)               (GdkFBKeyboard       *kb,
55                                         const GdkKeymapKey  *key);
56   gboolean (*translate_keyboard_state) (GdkFBKeyboard       *kb,
57                                         guint                hardware_keycode,
58                                         GdkModifierType      state,
59                                         gint                 group,
60                                         guint               *keyval,
61                                         gint                *effective_group,
62                                         gint                *level,
63                                         GdkModifierType     *unused_modifiers);
64   gboolean (*get_entries_for_keyval)   (GdkFBKeyboard       *kb,
65                                         guint                keyval,
66                                         GdkKeymapKey       **keys,
67                                         gint                *n_keys);
68   gboolean (*get_entries_for_keycode)  (GdkFBKeyboard       *kb,
69                                         guint                hardware_keycode,
70                                         GdkKeymapKey       **keys,
71                                         guint              **keyvals,
72                                         gint                *n_entries);
73
74   gpointer driver_data;
75 };
76
77 static GdkFBKeyboard *gdk_fb_keyboard = NULL;
78 static GdkKeymap *default_keymap = NULL;
79
80 static gboolean xlate_open            (GdkFBKeyboard       *kb);
81 static void     xlate_close           (GdkFBKeyboard       *kb);
82 static guint    xlate_lookup          (GdkFBKeyboard       *kb,
83                                        const GdkKeymapKey  *key);
84 static gboolean xlate_translate       (GdkFBKeyboard       *kb,
85                                        guint                hardware_keycode,
86                                        GdkModifierType      state,
87                                        gint                 group,
88                                        guint               *keyval,
89                                        gint                *effective_group,
90                                        gint                *level,
91                                        GdkModifierType     *unused_modifiers);
92 static gboolean xlate_get_for_keyval  (GdkFBKeyboard       *kb,
93                                        guint                keyval,
94                                        GdkKeymapKey       **keys,
95                                        gint                *n_keys);
96 static gboolean xlate_get_for_keycode (GdkFBKeyboard       *kb,
97                                        guint                hardware_keycode,
98                                        GdkKeymapKey       **keys,
99                                        guint              **keyvals,
100                                        gint                *n_entries);
101
102 static gboolean raw_open            (GdkFBKeyboard       *kb);
103 static void     raw_close           (GdkFBKeyboard       *kb);
104 static guint    raw_lookup          (GdkFBKeyboard       *kb,
105                                      const GdkKeymapKey  *key);
106 static gboolean raw_translate       (GdkFBKeyboard       *kb,
107                                      guint                hardware_keycode,
108                                      GdkModifierType      state,
109                                      gint                 group,
110                                      guint               *keyval,
111                                      gint                *effective_group,
112                                      gint                *level,
113                                      GdkModifierType     *unused_modifiers);
114 static gboolean raw_get_for_keyval  (GdkFBKeyboard       *kb,
115                                      guint                keyval,
116                                      GdkKeymapKey       **keys,
117                                      gint                *n_keys);
118 static gboolean raw_get_for_keycode (GdkFBKeyboard       *kb,
119                                      guint                hardware_keycode,
120                                      GdkKeymapKey       **keys,
121                                      guint              **keyvals,
122                                      gint                *n_entries);
123
124
125 static GdkFBKeyboardDevice keyb_devs[] =
126 {
127   {
128     "xlate",
129     xlate_open,
130     xlate_close,
131     xlate_lookup,
132     xlate_translate,
133     xlate_get_for_keyval,
134     xlate_get_for_keycode
135   },
136   {
137     "raw",
138     raw_open,
139     raw_close,
140     raw_lookup,
141     raw_translate,
142     raw_get_for_keyval,
143     raw_get_for_keycode
144   },
145 };
146
147 GdkKeymap*
148 gdk_keymap_get_default (void)
149 {
150   if (default_keymap == NULL)
151     default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
152
153   return default_keymap;
154 }
155
156 PangoDirection
157 gdk_keymap_get_direction (GdkKeymap *keymap)
158 {
159   /* FIXME: Only supports LTR keymaps at the moment */
160   return PANGO_DIRECTION_LTR;
161 }
162
163 guint
164 gdk_fb_keyboard_modifiers ()
165 {
166   return gdk_fb_keyboard->modifier_state;
167 }
168
169 gboolean
170 gdk_fb_keyboard_open (void)
171 {
172   GdkFBKeyboard *keyb;
173   GdkFBKeyboardDevice *device;
174   char *keyb_type;
175   int i;
176
177   keyb = g_new0 (GdkFBKeyboard, 1);
178   keyb->fd = -1;
179   
180   keyb_type = getenv ("GDK_KEYBOARD_TYPE");
181   if (!keyb_type)
182     keyb_type = "xlate";
183
184   for (i = 0; i < G_N_ELEMENTS(keyb_devs); i++)
185     {
186       if (g_strcasecmp(keyb_type, keyb_devs[i].name)==0)
187         break;
188     }
189   
190   if (i == G_N_ELEMENTS(keyb_devs))
191     {
192       g_warning ("No keyboard driver of type %s found", keyb_type);
193       return FALSE;
194     }
195
196   device = &keyb_devs[i];
197
198   keyb->dev = device;
199   
200   if (!device->open(keyb))
201     {
202       g_warning ("Keyboard driver open failed");
203       g_free (keyb);
204       return FALSE;
205     }
206
207   gdk_fb_keyboard = keyb;
208   
209   return TRUE;
210 }
211
212 void 
213 gdk_fb_keyboard_close (void)
214 {
215   gdk_fb_keyboard->dev->close(gdk_fb_keyboard);
216   g_free (gdk_fb_keyboard);
217 }
218
219
220 /**
221  * gdk_keymap_get_entries_for_keyval:
222  * @keymap: a #GdkKeymap, or %NULL to use the default keymap
223  * @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
224  * @keys: return location for an array of #GdkKeymapKey
225  * @n_keys: return location for number of elements in returned array
226  * 
227  * Obtains a list of keycode/group/level combinations that will
228  * generate @keyval. Groups and levels are two kinds of keyboard mode;
229  * in general, the level determines whether the top or bottom symbol
230  * on a key is used, and the group determines whether the left or
231  * right symbol is used. On US keyboards, the shift key changes the
232  * keyboard level, and there are no groups. A group switch key might
233  * convert a keyboard between Hebrew to English modes, for example.
234  * #GdkEventKey contains a %group field that indicates the active
235  * keyboard group. The level is computed from the modifier mask.
236  * The returned array should be freed
237  * with g_free().
238  *
239  * Return value: %TRUE if keys were found and returned
240  **/
241 gboolean
242 gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
243                                    guint          keyval,
244                                    GdkKeymapKey **keys,
245                                    gint          *n_keys)
246 {
247   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
248   g_return_val_if_fail (keys != NULL, FALSE);
249   g_return_val_if_fail (n_keys != NULL, FALSE);
250   g_return_val_if_fail (keyval != 0, FALSE);
251
252   return gdk_fb_keyboard->dev->get_entries_for_keyval (gdk_fb_keyboard,
253                                                        keyval,
254                                                        keys,
255                                                        n_keys);
256 }
257
258 /**
259  * gdk_keymap_get_entries_for_keycode:
260  * @keymap: a #GdkKeymap or %NULL to use the default keymap
261  * @hardware_keycode: a keycode
262  * @keys: return location for array of #GdkKeymapKey, or NULL
263  * @keyvals: return location for array of keyvals, or NULL
264  * @n_entries: length of @keys and @keyvals
265  *
266  * Returns the keyvals bound to @hardware_keycode.
267  * The Nth #GdkKeymapKey in @keys is bound to the Nth
268  * keyval in @keyvals. Free the returned arrays with g_free().
269  * When a keycode is pressed by the user, the keyval from
270  * this list of entries is selected by considering the effective
271  * keyboard group and level. See gdk_keymap_translate_keyboard_state().
272  *
273  * Returns: %TRUE if there were any entries
274  **/
275 gboolean
276 gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
277                                     guint          hardware_keycode,
278                                     GdkKeymapKey **keys,
279                                     guint        **keyvals,
280                                     gint          *n_entries)
281 {
282   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
283   g_return_val_if_fail (n_entries != NULL, FALSE);
284   
285   return gdk_fb_keyboard->dev->get_entries_for_keycode (gdk_fb_keyboard,
286                                                         hardware_keycode,
287                                                         keys,
288                                                         keyvals,
289                                                         n_entries);
290 }
291
292
293 /**
294  * gdk_keymap_lookup_key:
295  * @keymap: a #GdkKeymap or %NULL to use the default keymap
296  * @key: a #GdkKeymapKey with keycode, group, and level initialized
297  * 
298  * Looks up the keyval mapped to a keycode/group/level triplet.
299  * If no keyval is bound to @key, returns 0. For normal user input,
300  * you want to use gdk_keymap_translate_keyboard_state() instead of
301  * this function, since the effective group/level may not be
302  * the same as the current keyboard state.
303  * 
304  * Return value: a keyval, or 0 if none was mapped to the given @key
305  **/
306 guint
307 gdk_keymap_lookup_key (GdkKeymap          *keymap,
308                        const GdkKeymapKey *key)
309 {
310   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
311   g_return_val_if_fail (key != NULL, 0);
312   g_return_val_if_fail (key->group < 4, 0);
313
314   return gdk_fb_keyboard->dev->lookup_key (gdk_fb_keyboard,  key);
315 }
316
317
318 /**
319  * gdk_keymap_translate_keyboard_state:
320  * @keymap: a #GdkKeymap, or %NULL to use the default
321  * @hardware_keycode: a keycode
322  * @state: a modifier state 
323  * @group: active keyboard group
324  * @keyval: return location for keyval
325  * @effective_group: return location for effective group
326  * @level: return location for level
327  * @unused_modifiers: return location for modifiers that didn't affect the group or level
328  * 
329  *
330  * Translates the contents of a #GdkEventKey into a keyval, effective
331  * group, and level. Modifiers that didn't affect the translation and
332  * are thus available for application use are returned in
333  * @unused_modifiers.  See gdk_keyval_get_keys() for an explanation of
334  * groups and levels.  The @effective_group is the group that was
335  * actually used for the translation; some keys such as Enter are not
336  * affected by the active keyboard group. The @level is derived from
337  * @state. For convenience, #GdkEventKey already contains the translated
338  * keyval, so this function isn't as useful as you might think.
339  * 
340  * Return value: %TRUE if there was a keyval bound to the keycode/state/group
341  **/
342 gboolean
343 gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
344                                      guint            hardware_keycode,
345                                      GdkModifierType  state,
346                                      gint             group,
347                                      guint           *keyval,
348                                      gint            *effective_group,
349                                      gint            *level,
350                                      GdkModifierType *unused_modifiers)
351 {
352   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
353   g_return_val_if_fail (group < 4, FALSE);
354
355   return gdk_fb_keyboard->dev->translate_keyboard_state (gdk_fb_keyboard,
356                                                          hardware_keycode,
357                                                          state,
358                                                          group,
359                                                          keyval,
360                                                          effective_group,
361                                                          level,
362                                                          unused_modifiers);
363 }
364
365 static void
366 gdk_fb_handle_key (guint hw_keycode,
367                    guint keyval,
368                    guint modifier_state,
369                    guint8 group,
370                    gchar *string,
371                    gint string_length,
372                    gboolean key_up)
373 {
374   GdkWindow *win;
375   GdkEvent *event;
376
377   /* handle some magic keys */
378   if (key_up &&
379       (modifier_state & (GDK_CONTROL_MASK|GDK_MOD1_MASK)))
380     {
381       if (keyval == GDK_BackSpace)
382         {
383           ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
384           exit (1);
385         }
386           
387       if (keyval == GDK_Return)
388         gdk_fb_redraw_all ();
389     }
390
391   win = gdk_fb_keyboard_event_window (gdk_fb_window_find_focus (),
392                                       key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS);
393   if (win)
394     {
395       event = gdk_event_make (win,
396                               key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS,
397                               TRUE);
398     
399       event->key.state = modifier_state;
400       event->key.keyval = keyval;
401       event->key.string = string;
402       event->key.length = string_length;
403       event->key.hardware_keycode = hw_keycode;
404       event->key.group = group;
405     }
406   else
407     g_free (string);
408 }
409
410 /******************************************************
411  ********* Device specific keyboard code **************
412  ******************************************************/
413
414
415 /* XLATE keyboard driver */
416
417 struct {
418   char *str;
419   guint code;
420   guint modifier;
421 } xlate_codes[] =
422 {
423   {"\x5b\x41", GDK_F1},
424   {"\x5b\x42", GDK_F2},
425   {"\x5b\x43", GDK_F3},
426   {"\x5b\x44", GDK_F4},
427   {"\x5b\x45", GDK_F5},
428   {"\x31\x37\x7e", GDK_F6},
429   {"\x31\x38\x7e", GDK_F7},
430   {"\x31\x39\x7e", GDK_F8},
431   {"\x32\x30\x7e", GDK_F9},
432   {"\x32\x31\x7e", GDK_F10},
433   {"\x32\x33\x7e", GDK_F11},
434   {"\x32\x34\x7e", GDK_F12},
435   
436   {"\x32\x35\x7e", GDK_F1, GDK_SHIFT_MASK},
437   {"\x32\x36\x7e", GDK_F2, GDK_SHIFT_MASK},
438   {"\x32\x38\x7e", GDK_F3, GDK_SHIFT_MASK},
439   {"\x32\x39\x7e", GDK_F4, GDK_SHIFT_MASK},
440   {"\x33\x31\x7e", GDK_F5, GDK_SHIFT_MASK},
441   {"\x33\x32\x7e", GDK_F6, GDK_SHIFT_MASK},
442   {"\x33\x33\x7e", GDK_F7, GDK_SHIFT_MASK},
443   {"\x33\x34\x7e", GDK_F8, GDK_SHIFT_MASK},
444
445   {"\x31\x7e", GDK_Home},
446   {"\x35\x7e", GDK_Page_Up},
447   {"\x34\x7e", GDK_End},
448   {"\x36\x7e", GDK_Page_Down},
449   {"\x32\x7e", GDK_Insert},
450   {"\x33\x7e", GDK_Delete},
451
452   {"\x41", GDK_Up},
453   {"\x44", GDK_Left},
454   {"\x42", GDK_Down},
455   {"\x43", GDK_Right},
456   {"\x50", GDK_Break},
457 };
458
459 struct {
460   guint code;
461   guint modifier;
462 } xlate_chars[] =
463 {
464   /* 0x00 */
465   {'@', GDK_CONTROL_MASK},
466   {'a', GDK_CONTROL_MASK},
467   {'b', GDK_CONTROL_MASK},
468   {'c', GDK_CONTROL_MASK},
469   {'d', GDK_CONTROL_MASK},
470   {'e', GDK_CONTROL_MASK},
471   {'f', GDK_CONTROL_MASK},
472   {'g', GDK_CONTROL_MASK},
473   {'h', GDK_CONTROL_MASK},
474   {GDK_Tab, 0},
475   {'j', GDK_CONTROL_MASK},
476   {'k', GDK_CONTROL_MASK},
477   {'l', GDK_CONTROL_MASK},
478   {GDK_Return, 0},
479   {'n', GDK_CONTROL_MASK},
480   {'o', GDK_CONTROL_MASK},
481   /* 0x10 */
482   {'p', GDK_CONTROL_MASK},
483   {'q', GDK_CONTROL_MASK},
484   {'r', GDK_CONTROL_MASK},
485   {'s', GDK_CONTROL_MASK},
486   {'t', GDK_CONTROL_MASK},
487   {'u', GDK_CONTROL_MASK},
488   {'v', GDK_CONTROL_MASK},
489   {'w', GDK_CONTROL_MASK},
490   {'x', GDK_CONTROL_MASK},
491   {'y', GDK_CONTROL_MASK},
492   {'z', GDK_CONTROL_MASK},
493   {GDK_Escape, 0},
494   {'\\', GDK_CONTROL_MASK},
495   {']', GDK_CONTROL_MASK},
496   {'^', GDK_CONTROL_MASK},
497   {'_', GDK_CONTROL_MASK},
498   /* 0x20 */
499   {GDK_space, 0},
500   {'!', 0},
501   {'"', 0},
502   {'#', 0},
503   {'$', 0},
504   {'%', 0},
505   {'&', 0},
506   {'\'', 0},
507   {'(', 0},
508   {')', 0},
509   {'*', 0},
510   {'+', 0},
511   {',', 0},
512   {'-', 0},
513   {'.', 0},
514   {'/', 0},
515   /* 0x30 */
516   {'0', 0},
517   {'1', 0},
518   {'2', 0},
519   {'3', 0},
520   {'4', 0},
521   {'5', 0},
522   {'6', 0},
523   {'7', 0},
524   {'8', 0},
525   {'9', 0},
526   {':', 0},
527   {';', 0},
528   {'<', 0},
529   {'=', 0},
530   {'>', 0},
531   {'?', 0},
532   /* 0x40 */
533   {'@', 0},
534   {'A', 0},
535   {'B', 0},
536   {'C', 0},
537   {'D', 0},
538   {'E', 0},
539   {'F', 0},
540   {'G', 0},
541   {'H', 0},
542   {'I', 0},
543   {'J', 0},
544   {'K', 0},
545   {'L', 0},
546   {'M', 0},
547   {'N', 0},
548   {'O', 0},
549   /* 0x50 */
550   {'P', 0},
551   {'Q', 0},
552   {'R', 0},
553   {'S', 0},
554   {'T', 0},
555   {'U', 0},
556   {'V', 0},
557   {'W', 0},
558   {'X', 0},
559   {'Y', 0},
560   {'Z', 0},
561   {'[', 0},
562   {'\\', 0},
563   {']', 0},
564   {'^', 0},
565   {'_', 0},
566   /* 0x60 */
567   {'`', 0},
568   {'a', 0},
569   {'b', 0},
570   {'c', 0},
571   {'d', 0},
572   {'e', 0},
573   {'f', 0},
574   {'g', 0},
575   {'h', 0},
576   {'i', 0},
577   {'j', 0},
578   {'k', 0},
579   {'l', 0},
580   {'m', 0},
581   {'n', 0},
582   {'o', 0},
583   /* 0x70 */
584   {'p', 0},
585   {'q', 0},
586   {'r', 0},
587   {'s', 0},
588   {'t', 0},
589   {'u', 0},
590   {'v', 0},
591   {'w', 0},
592   {'x', 0},
593   {'y', 0},
594   {'z', 0},
595   {'{', 0},
596   {'|', 0},
597   {'}', 0},
598   {'~', 0},
599   {GDK_BackSpace, 0},
600   /* 0x80 */
601   {0, 0},
602   {0, 0},
603   {0, 0},
604   {0, 0},
605   {0, 0},
606   {0, 0},
607   {0, 0},
608   {0, 0},
609   {0, 0},
610   {0, 0},
611   {0, 0},
612   {0, 0},
613   {0, 0},
614   {0, 0},
615   {0, 0},
616   {0, 0},
617   /* 0x90 */
618   {0, 0},
619   {0, 0},
620   {0, 0},
621   {0, 0},
622   {0, 0},
623   {0, 0},
624   {0, 0},
625   {0, 0},
626   {0, 0},
627   {0, 0},
628   {0, 0},
629   {0, 0},
630   {0, 0},
631   {0, 0},
632   {0, 0},
633   {0, 0},
634   /* 0xA0 */
635   {0, 0},
636   {0, 0},
637   {0, 0},
638   {0, 0},
639   {0, 0},
640   {0, 0},
641   {0, 0},
642   {0, 0},
643   {0, 0},
644   {0, 0},
645   {0, 0},
646   {0, 0},
647   {0, 0},
648   {0, 0},
649   {0, 0},
650   {0, 0},
651   /* 0xB0 */
652   {0, 0},
653   {0, 0},
654   {0, 0},
655   {0, 0},
656   {0, 0},
657   {0, 0},
658   {0, 0},
659   {0, 0},
660   {0, 0},
661   {0, 0},
662   {0, 0},
663   {0, 0},
664   {0, 0},
665   {0, 0},
666   {0, 0},
667   {0, 0},
668   /* 0xC0 */
669   {0, 0},
670   {0, 0},
671   {0, 0},
672   {0, 0},
673   {0, 0},
674   {0, 0},
675   {0, 0},
676   {0, 0},
677   {0, 0},
678   {0, 0},
679   {0, 0},
680   {0, 0},
681   {0, 0},
682   {0, 0},
683   {0, 0},
684   {0, 0},
685   /* 0xD0 */
686   {0, 0},
687   {0, 0},
688   {0, 0},
689   {0, 0},
690   {0, 0},
691   {0, 0},
692   {0, 0},
693   {0, 0},
694   {0, 0},
695   {0, 0},
696   {0, 0},
697   {0, 0},
698   {0, 0},
699   {0, 0},
700   {0, 0},
701   {0, 0},
702   /* 0xE0 */
703   {0, 0},
704   {0, 0},
705   {0, 0},
706   {0, 0},
707   {0, 0},
708   {0, 0},
709   {0, 0},
710   {0, 0},
711   {0, 0},
712   {0, 0},
713   {0, 0},
714   {0, 0},
715   {0, 0},
716   {0, 0},
717   {0, 0},
718   {0, 0},
719   /* 0xF0 */
720   {0, 0},
721   {0, 0},
722   {0, 0},
723   {0, 0},
724   {0, 0},
725   {0, 0},
726   {0, 0},
727   {0, 0},
728   {0, 0},
729   {0, 0},
730   {0, 0},
731   {0, 0},
732   {0, 0},
733   {0, 0},
734   {0, 0},
735   {0, 0},
736 };
737
738 static gboolean
739 iscode (char *code, char *str, int str_max)
740 {
741   int i;
742
743   for (i = 0; code[i] && (i < str_max); i++)
744     {
745       if (code[i] != str[i])
746         return FALSE;
747     }
748   return (code[i] == 0);
749 }
750
751 static gboolean
752 xlate_io (GIOChannel *gioc,
753           GIOCondition cond,
754           gpointer data)
755 {
756   GdkFBKeyboard *keyb = (GdkFBKeyboard *)data;
757   guchar buf[128];
758   guint keycode;
759   guint modifier;
760   gboolean handled;
761   int i, n, j;
762   int left;
763   
764   n = read (keyb->fd, buf, sizeof(buf));
765   if (n <= 0)
766     g_error ("Nothing from keyboard!");
767
768   for (i = 0; i < n; i++)
769     {
770       handled = FALSE;
771       modifier = 0;
772       if ((buf[i] == 27) && (i+1 != n)) /* Escape */
773         {
774           /* Esc is not the last char in buffer, interpret as code sequence */
775           if (buf[i+1] == '[')
776             {
777               i += 2;
778               left = n-i;
779               if (left <= 0)
780                 return TRUE;
781
782               for (j=0;j<G_N_ELEMENTS (xlate_codes);j++)
783                 {
784                   if (iscode (xlate_codes[j].str, &buf[i], left))
785                     {
786                       /* Ctrl-Alt Return can't be pressed in the XLATE driver,
787                        * use Shift F1 instead */
788                       if ((xlate_codes[j].code == GDK_F1) &&
789                           (xlate_codes[j].modifier & GDK_SHIFT_MASK))
790                         gdk_fb_redraw_all ();
791
792                       if ((xlate_codes[j].code == GDK_F2) &&
793                           (xlate_codes[j].modifier & GDK_SHIFT_MASK))
794                         {
795                           static gint deg = 0;
796                           deg = (deg + 1) % 4;
797                             
798                           gdk_fb_set_rotation (deg);
799                         }
800
801                       
802                       gdk_fb_handle_key (xlate_codes[j].code,
803                                          xlate_codes[j].code,
804                                          xlate_codes[j].modifier,
805                                          0,
806                                          NULL,
807                                          0,
808                                          FALSE);
809                       gdk_fb_handle_key (xlate_codes[j].code,
810                                          xlate_codes[j].code,
811                                          xlate_codes[j].modifier,
812                                          0,
813                                          NULL,
814                                          0,
815                                          TRUE);
816                       i += strlen (xlate_codes[j].str);
817                       handled = TRUE;
818                       break;
819                     }
820                 }
821             }
822           else
823             {
824               /* Alt-key */
825               modifier |= GDK_MOD1_MASK;
826               i++;
827             }
828         }
829       if (!handled)
830         {
831           char dummy[2];
832           gint len;
833           
834           keycode = xlate_chars[buf[i]].code;
835           if (keycode == 0)
836             keycode = buf[i];
837           modifier |= xlate_chars[buf[i]].modifier;
838           
839           dummy[0] = keycode;
840           dummy[1] = 0;
841
842           len = ((keycode < 255) && isprint (keycode)) ? 1 : 0;
843           gdk_fb_handle_key (keycode,
844                              keycode,
845                              modifier,
846                              0,
847                              (len)?g_strdup(dummy) : NULL,
848                              len,
849                              FALSE);
850           gdk_fb_handle_key (keycode,
851                              keycode,
852                              modifier,
853                              0,
854                              (len)?g_strdup(dummy) : NULL,
855                              len,
856                              TRUE);
857           i++;
858         }
859     }
860   return TRUE;
861 }
862
863 static gboolean
864 xlate_open (GdkFBKeyboard *kb)
865 {
866   const char cursoroff_str[] = "\033[?1;0;0c";
867   struct termios ts;
868   
869   tcgetattr (gdk_display->tty_fd, &ts);
870   ts.c_cc[VTIME] = 0;
871   ts.c_cc[VMIN] = 1;
872   ts.c_lflag &= ~(ICANON|ECHO|ISIG);
873   ts.c_iflag = 0;
874   tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
875
876   tcsetpgrp (gdk_display->tty_fd, getpgrp());
877
878   write (gdk_display->tty_fd, cursoroff_str, strlen (cursoroff_str));
879   
880   ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
881
882   kb->fd = gdk_display->tty_fd;
883   kb->io = g_io_channel_unix_new (kb->fd);
884   kb->io_tag = g_io_add_watch (kb->io,
885                                G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
886                                xlate_io,
887                                kb);
888   
889   return TRUE;
890 }
891
892 static void
893 xlate_close (GdkFBKeyboard *kb)
894 {
895   struct termios ts;
896   const char cursoron_str[] = "\033c";
897
898   write (gdk_display->tty_fd, cursoron_str, strlen (cursoron_str));
899
900   tcgetattr (gdk_display->tty_fd, &ts);
901   ts.c_lflag |= (ICANON|ECHO|ISIG);
902   tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
903   
904   g_source_remove (kb->io_tag);
905   g_io_channel_unref (kb->io);
906   /* don't close kb->fd, it is the tty from gdk_display */
907 }
908
909 static guint
910 xlate_lookup (GdkFBKeyboard       *kb,
911               const GdkKeymapKey  *key)
912 {
913   g_warning ("xlate_lookup() NIY");
914   return FALSE;
915 }
916
917 static gboolean
918 xlate_translate (GdkFBKeyboard       *kb,
919                  guint                hardware_keycode,
920                  GdkModifierType      state,
921                  gint                 group,
922                  guint               *keyval,
923                  gint                *effective_group,
924                  gint                *level,
925                  GdkModifierType     *unused_modifiers)
926 {
927   g_warning ("xlate_translate() NIY");
928   return FALSE;
929 }
930
931 static gboolean
932 xlate_get_for_keyval (GdkFBKeyboard       *kb,
933                       guint                keyval,
934                       GdkKeymapKey       **keys,
935                       gint                *n_keys)
936 {
937   g_warning ("xlate_get_for_keyval() NIY");
938   return FALSE;
939 }
940
941 static gboolean
942 xlate_get_for_keycode (GdkFBKeyboard       *kb,
943                        guint                hardware_keycode,
944                        GdkKeymapKey       **keys,
945                        guint              **keyvals,
946                        gint                *n_entries)
947 {
948   g_warning ("xlate_get_for_keycode() NIY");
949   return FALSE;
950 }
951
952 /* Raw keyboard support */
953
954 static const guint trans_table[256][3] = {
955   /* 0x00 */
956   {0, 0, 0},
957   {GDK_Escape, 0, 0},
958   {'1', '!', 0},
959   {'2', '@', 0},
960   {'3', '#', 0},
961   {'4', '$', 0},
962   {'5', '%', 0},
963   {'6', '^', 0},
964   {'7', '&', 0},
965   {'8', '*', 0},
966   {'9', '(', 0},
967   {'0', ')', 0},
968   {'-', '_', 0},
969   {'=', '+', 0},
970   {GDK_BackSpace, 0, 0},
971   {GDK_Tab, 0, 0},
972
973   /* 0x10 */
974   {'q', 'Q', 0},
975   {'w', 'W', 0},
976   {'e', 'E', 0},
977   {'r', 'R', 0},
978   {'t', 'T', 0},
979   {'y', 'Y', 0},
980   {'u', 'U', 0},
981   {'i', 'I', 0},
982   {'o', 'O', 0},
983   {'p', 'P', 0},
984   {'[', '{', 0},
985   {']', '}', 0},
986   {GDK_Return, 0, 0},
987   {GDK_Control_L, 0, 0}, /* mod */
988   {'a', 'A', 0},
989   {'s', 'S', 0},
990
991         /* 0x20 */
992   {'d', 'D', 0},
993   {'f', 'F', 0},
994   {'g', 'G', 0},
995   {'h', 'H', 0},
996   {'j', 'J', 0},
997   {'k', 'K', 0},
998   {'l', 'L', 0},
999   {';', ':', 0},
1000   {'\'', '"', 0},
1001   {'`', '~', 0},
1002   {GDK_Shift_L, 0, 0}, /* mod */
1003   {'\\', 0, 0},
1004   {'z', 0, 0},
1005   {'x', 0, 0},
1006   {'c', 0, 0},
1007
1008   {'v', 'V', 0},
1009
1010         /* 0x30 */
1011   {'b', 'B', 0},
1012   {'n', 'N', 0},
1013   {'m', 'M', 0},
1014   {',', 0, 0},
1015   {'.', 0, 0},
1016   {'/', 0, 0},
1017   {GDK_Shift_R, 0, 0}, /* mod */
1018   {GDK_KP_Multiply, 0, 0},
1019   {0, 0, 0},
1020   {GDK_space, 0, 0},
1021   {0, 0, 0},
1022   {GDK_F1, 0, 0},
1023   {GDK_F2, 0, 0},
1024   {GDK_F3, 0, 0},
1025   {GDK_F4, 0, 0},
1026   {GDK_F5, 0, 0},
1027
1028         /* 0x40 */
1029   {GDK_F6, 0, 0},
1030   {GDK_F7, 0, 0},
1031   {GDK_F8, 0, 0},
1032   {GDK_F9, 0, 0},
1033   {GDK_F10, 0, 0},
1034   {0, 0, 0},
1035   {0, 0, 0},
1036   {'7', 0, 0},
1037   {'8', 0, 0},
1038   {'9', 0, 0},
1039   {'-', 0, 0},
1040   {'4', 0, 0},
1041   {'5', 0, 0},
1042   {'6', 0, 0},
1043   {'+', 0, 0},
1044   {'1', 0, 0},
1045
1046         /* 0x50 */
1047   {'2', 0, 0},
1048   {'3', 0, 0},
1049   {'0', 0, 0},
1050   {'.', 0, 0},
1051   {0, 0, 0},
1052   {0, 0, 0},
1053   {0, 0, 0},
1054   {GDK_F11, 0, 0},
1055   {GDK_F12, 0, 0},
1056   {0, 0, 0},
1057   {0, 0, 0},
1058   {0, 0, 0},
1059   {0, 0, 0},
1060   {0, 0, 0},
1061   {0, 0, 0},
1062   {0, 0, 0},
1063
1064         /* 0x60 */
1065   {GDK_Return, 0, 0},
1066   {0, 0, 0},
1067   {0, 0, 0},
1068   {0, 0, 0},
1069   {0, 0, 0},
1070   {0, 0, 0},
1071   {0, 0, 0},
1072   {0, 0, 0},
1073   {0, 0, 0},
1074   {0, 0, 0},
1075   {0, 0, 0},
1076   {0, 0, 0},
1077   {0, 0, 0},
1078   {0, 0, 0},
1079   {0, 0, 0},
1080   {0, 0, 0},
1081
1082         /* 0x70 */
1083   {0, 0, 0},
1084   {0, 0, 0},
1085   {0, 0, 0},
1086   {0, 0, 0},
1087   {0, 0, 0},
1088   {0, 0, 0},
1089   {0, 0, 0},
1090   {0, 0, 0},
1091   {0, 0, 0},
1092   {0, 0, 0},
1093   {0, 0, 0},
1094   {0, 0, 0},
1095   {0, 0, 0},
1096   {0, 0, 0},
1097   {0, 0, 0},
1098   {0, 0, 0},
1099
1100         /* 0x80 */
1101   {0, 0, 0},
1102   {0, 0, 0},
1103   {0, 0, 0},
1104   {0, 0, 0},
1105   {0, 0, 0},
1106   {0, 0, 0},
1107   {0, 0, 0},
1108   {0, 0, 0},
1109   {0, 0, 0},
1110   {0, 0, 0},
1111   {0, 0, 0},
1112   {0, 0, 0},
1113   {0, 0, 0},
1114   {0, 0, 0},
1115   {0, 0, 0},
1116   {0, 0, 0},
1117
1118         /* 0x90 */
1119   {0, 0, 0},
1120   {0, 0, 0},
1121   {0, 0, 0},
1122   {0, 0, 0},
1123   {0, 0, 0},
1124   {0, 0, 0},
1125   {0, 0, 0},
1126   {0, 0, 0},
1127   {0, 0, 0},
1128   {0, 0, 0},
1129   {0, 0, 0},
1130   {0, 0, 0},
1131   {0, 0, 0},
1132   {0, 0, 0},
1133   {0, 0, 0},
1134   {0, 0, 0},
1135
1136         /* 0xA0 */
1137   {0, 0, 0},
1138   {0, 0, 0},
1139   {0, 0, 0},
1140   {0, 0, 0},
1141   {0, 0, 0},
1142   {0, 0, 0},
1143   {0, 0, 0},
1144   {0, 0, 0},
1145   {0, 0, 0},
1146   {0, 0, 0},
1147   {0, 0, 0},
1148   {0, 0, 0},
1149   {0, 0, 0},
1150   {0, 0, 0},
1151   {0, 0, 0},
1152   {0, 0, 0},
1153
1154         /* 0xB0 */
1155   {0, 0, 0},
1156   {0, 0, 0},
1157   {0, 0, 0},
1158   {0, 0, 0},
1159   {0, 0, 0},
1160   {0, 0, 0},
1161   {0, 0, 0},
1162   {0, 0, 0},
1163   {0, 0, 0},
1164   {0, 0, 0},
1165   {0, 0, 0},
1166   {0, 0, 0},
1167   {0, 0, 0},
1168   {0, 0, 0},
1169   {0, 0, 0},
1170   {0, 0, 0},
1171
1172         /* 0xC0 */
1173   {0, 0, 0},
1174   {0, 0, 0},
1175   {0, 0, 0},
1176   {0, 0, 0},
1177   {0, 0, 0},
1178   {0, 0, 0},
1179   {0, 0, 0},
1180   {0, 0, 0},
1181   {GDK_Up, 0, 0},
1182   {0, 0, 0},
1183   {0, 0, 0},
1184   {GDK_Left, 0, 0},
1185   {0, 0, 0},
1186   {GDK_Right, 0, 0},
1187   {0, 0, 0},
1188   {0, 0, 0},
1189
1190         /* 0xD0 */
1191   {GDK_Down, 0, 0},
1192   {0, 0, 0},
1193   {0, 0, 0},
1194   {0, 0, 0},
1195   {0, 0, 0},
1196   {0, 0, 0},
1197   {0, 0, 0},
1198   {0, 0, 0},
1199   {0, 0, 0},
1200   {0, 0, 0},
1201   {0, 0, 0},
1202   {0, 0, 0},
1203   {0, 0, 0},
1204   {0, 0, 0},
1205   {0, 0, 0},
1206   {0, 0, 0},
1207
1208         /* 0xE0 */
1209   {0, 0, 0},
1210   {0, 0, 0},
1211   {0, 0, 0},
1212   {0, 0, 0},
1213   {0, 0, 0},
1214   {0, 0, 0},
1215   {0, 0, 0},
1216   {0, 0, 0},
1217   {0, 0, 0},
1218   {0, 0, 0},
1219   {0, 0, 0},
1220   {0, 0, 0},
1221   {0, 0, 0},
1222   {0, 0, 0},
1223   {0, 0, 0},
1224   {0, 0, 0},
1225
1226         /* 0xF0 */
1227   {0, 0, 0},
1228   {0, 0, 0},
1229   {0, 0, 0},
1230   {0, 0, 0},
1231   {0, 0, 0},
1232   {0, 0, 0},
1233   {0, 0, 0},
1234   {0, 0, 0},
1235   {0, 0, 0},
1236   {0, 0, 0},
1237   {0, 0, 0},
1238   {0, 0, 0},
1239   {0, 0, 0},
1240   {0, 0, 0},
1241   {0, 0, 0},
1242   {0, 0, 0},
1243 };
1244
1245 static gboolean
1246 raw_io (GIOChannel *gioc,
1247         GIOCondition cond,
1248         gpointer data)
1249 {
1250   GdkFBKeyboard *k = data;
1251   guchar buf[128];
1252   int i, n;
1253
1254   n = read (k->fd, buf, sizeof(buf));
1255   if (n <= 0)
1256     g_error("Nothing from keyboard!");
1257
1258   for (i = 0; i < n; i++)
1259     {
1260       guchar keycode;
1261       gboolean key_up;
1262       char dummy[2];
1263       int len;
1264       int mod;
1265       guint keyval;
1266
1267       keycode = buf[i] & 0x7F;
1268       key_up = buf[i] & 0x80;
1269
1270       if (keycode > G_N_ELEMENTS (trans_table))
1271         {
1272           g_warning ("Unknown keycode");
1273           continue;
1274         }
1275
1276       if ( (keycode == 0x1D) /* left Ctrl */
1277            || (keycode == 0x9D) /* right Ctrl */
1278            || (keycode == 0x38) /* left Alt */
1279            || (keycode == 0xB8) /* right Alt */
1280            || (keycode == 0x2A) /* left Shift */
1281            || (keycode == 0x36) /* right Shift */)
1282         {
1283           switch (keycode)
1284             {
1285             case 0x1D: /* Left Ctrl */
1286             case 0x9D: /* Right Ctrl */
1287               if (key_up)
1288                 k->modifier_state &= ~GDK_CONTROL_MASK;
1289               else
1290                 k->modifier_state |= GDK_CONTROL_MASK;
1291               break;
1292             case 0x38: /* Left Alt */
1293             case 0xB8: /* Right Alt */
1294               if (key_up)
1295                 k->modifier_state &= ~GDK_MOD1_MASK;
1296               else
1297                 k->modifier_state |= GDK_MOD1_MASK;
1298               break;
1299             case 0x2A: /* Left Shift */
1300             case 0x36: /* Right Shift */
1301               if (key_up)
1302                 k->modifier_state &= ~GDK_SHIFT_MASK;
1303               else
1304                 k->modifier_state |= GDK_SHIFT_MASK;
1305               break;
1306             }
1307           continue; /* Don't generate events for modifiers */
1308         }
1309
1310       if (keycode == 0x3A /* Caps lock */)
1311         {
1312           if (!key_up)
1313             k->caps_lock = !k->caps_lock;
1314           
1315           ioctl (k->fd, KDSETLED, k->caps_lock ? LED_CAP : 0);
1316           continue;
1317         }
1318
1319       if (trans_table[keycode][0] >= GDK_F1 &&
1320           trans_table[keycode][0] <= GDK_F35 &&
1321           (k->modifier_state & GDK_MOD1_MASK))
1322         {
1323           if (key_up) /* Only switch on release */
1324             {
1325               gint vtnum = trans_table[keycode][0] - GDK_F1 + 1;
1326
1327               /* Do the whole funky VT switch thing */
1328               ioctl (gdk_display->console_fd, VT_ACTIVATE, vtnum);
1329               ioctl (gdk_display->console_fd, VT_WAITACTIVE, gdk_display->vt);
1330               gdk_fb_redraw_all ();
1331             }
1332
1333           continue;
1334         }
1335
1336       keyval = 0;
1337       mod = 0;
1338       if (k->modifier_state & GDK_CONTROL_MASK)
1339         mod = 2;
1340       else if (k->modifier_state & GDK_SHIFT_MASK)
1341         mod = 1;
1342       do {
1343         keyval = trans_table[keycode][mod--];
1344       } while (!keyval && (mod >= 0));
1345
1346       if (k->caps_lock && (keyval >= 'a') && (keyval <= 'z'))
1347         keyval = toupper (keyval);
1348
1349       if (!keyval)
1350         continue;
1351
1352       len = isprint (keyval) ? 1 : 0;
1353       dummy[0] = keyval;
1354       dummy[1] = 0;
1355
1356       gdk_fb_handle_key (keycode,
1357                          keyval,
1358                          k->modifier_state,
1359                          0,
1360                          (len)?g_strdup(dummy):NULL,
1361                          len,
1362                          key_up);
1363     }
1364
1365   return TRUE;
1366 }
1367
1368 static gboolean
1369 raw_open (GdkFBKeyboard *kb)
1370 {
1371   const char cursoroff_str[] = "\033[?1;0;0c";
1372   struct termios ts;
1373   
1374   tcgetattr (gdk_display->tty_fd, &ts);
1375   ts.c_cc[VTIME] = 0;
1376   ts.c_cc[VMIN] = 1;
1377   ts.c_lflag &= ~(ICANON|ECHO|ISIG);
1378   ts.c_iflag = 0;
1379   tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
1380
1381   tcsetpgrp (gdk_display->tty_fd, getpgrp());
1382
1383   write (gdk_display->tty_fd, cursoroff_str, strlen (cursoroff_str));
1384   
1385   if (ioctl (gdk_display->tty_fd, KDSKBMODE, K_MEDIUMRAW) < 0)
1386     {
1387       g_warning ("setting tty to K_MEDIUMRAW failed");
1388       return FALSE;
1389     }
1390
1391   kb->fd = gdk_display->tty_fd;
1392   kb->io = g_io_channel_unix_new (kb->fd);
1393   kb->io_tag = g_io_add_watch (kb->io,
1394                                G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1395                                raw_io,
1396                                kb);
1397   
1398   return TRUE;
1399 }
1400
1401 static void
1402 raw_close (GdkFBKeyboard *kb)
1403 {
1404   struct termios ts;
1405   const char cursoron_str[] = "\033c";
1406
1407   write (gdk_display->tty_fd, cursoron_str, strlen (cursoron_str));
1408
1409   tcgetattr (gdk_display->tty_fd, &ts);
1410   ts.c_lflag |= (ICANON|ECHO|ISIG);
1411   tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
1412   
1413   ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
1414
1415   g_source_remove (kb->io_tag);
1416   g_io_channel_unref (kb->io);
1417   /* don't close kb->fd, it is the tty from gdk_display */
1418 }
1419
1420 static guint
1421 raw_lookup (GdkFBKeyboard       *kb,
1422               const GdkKeymapKey  *key)
1423 {
1424   g_warning ("raw_lookup() NIY");
1425   return FALSE;
1426 }
1427
1428 static gboolean
1429 raw_translate (GdkFBKeyboard       *kb,
1430                  guint                hardware_keycode,
1431                  GdkModifierType      state,
1432                  gint                 group,
1433                  guint               *keyval,
1434                  gint                *effective_group,
1435                  gint                *level,
1436                  GdkModifierType     *unused_modifiers)
1437 {
1438   g_warning ("raw_translate() NIY");
1439   return FALSE;
1440 }
1441
1442 static gboolean
1443 raw_get_for_keyval (GdkFBKeyboard       *kb,
1444                       guint                keyval,
1445                       GdkKeymapKey       **keys,
1446                       gint                *n_keys)
1447 {
1448   g_warning ("raw_get_for_keyval() NIY");
1449   return FALSE;
1450 }
1451
1452 static gboolean
1453 raw_get_for_keycode (GdkFBKeyboard       *kb,
1454                        guint                hardware_keycode,
1455                        GdkKeymapKey       **keys,
1456                        guint              **keyvals,
1457                        gint                *n_entries)
1458 {
1459   g_warning ("raw_get_for_keycode() NIY");
1460   return FALSE;
1461 }