Add Ctrl+space customization.
[platform/upstream/ibus.git] / src / ibuskeynames.c
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* GDK - The GIMP Drawing Kit
4  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /*
23  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
24  * file for a list of people on the GTK+ Team.  See the ChangeLog
25  * files for a list of changes.  These files are distributed with
26  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27  */
28
29 /* Key handling not part of the keymap */
30 #include <glib.h>
31 #include <glib/gprintf.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include "ibuskeysyms.h"
35 #include "keyname-table.h"
36
37 #define IBUS_NUM_KEYS G_N_ELEMENTS (gdk_keys_by_keyval)
38
39 static int
40 gdk_keys_keyval_compare (const void *pkey, const void *pbase)
41 {
42   return (*(int *) pkey) - ((gdk_key *) pbase)->keyval;
43 }
44
45 const gchar*
46 ibus_keyval_name (guint keyval)
47 {
48   static gchar buf[100];
49   gdk_key *found;
50
51   /* Check for directly encoded 24-bit UCS characters: */
52   if ((keyval & 0xff000000) == 0x01000000)
53     {
54       g_sprintf (buf, "U+%.04X", (keyval & 0x00ffffff));
55       return buf;
56     }
57
58   found = bsearch (&keyval, gdk_keys_by_keyval,
59                    IBUS_NUM_KEYS, sizeof (gdk_key),
60            gdk_keys_keyval_compare);
61
62   if (found != NULL)
63     {
64       while ((found > gdk_keys_by_keyval) &&
65              ((found - 1)->keyval == keyval))
66         found--;
67
68       return (gchar *) (keynames + found->offset);
69     }
70   else if (keyval != 0)
71     {
72       g_sprintf (buf, "%#x", keyval);
73       return buf;
74     }
75
76   return NULL;
77 }
78
79 static int
80 gdk_keys_name_compare (const void *pkey, const void *pbase)
81 {
82   return strcmp ((const char *) pkey,
83          (const char *) (keynames + ((const gdk_key *) pbase)->offset));
84 }
85
86 guint
87 ibus_keyval_from_name (const gchar *keyval_name)
88 {
89   gdk_key *found;
90
91   g_return_val_if_fail (keyval_name != NULL, 0);
92
93   found = bsearch (keyval_name, gdk_keys_by_name,
94            IBUS_NUM_KEYS, sizeof (gdk_key),
95            gdk_keys_name_compare);
96   if (found != NULL)
97     return found->keyval;
98   else
99     return IBUS_KEY_VoidSymbol;
100 }
101
102 static const gchar *
103 modifier_name[] = {
104     "Shift",       // 0
105     "Lock",        // 1
106     "Control",    // 2
107     "Alt",        // 3
108     "Mod2",        // 4
109     "Mod3",        // 5
110     "Mod4",        // 6
111     "Mod5",        // 7
112     "Button1",    // 8
113     "Button2",    // 9
114     "Button3",    // 10
115     "Button4",    // 11
116     "Button5",    // 12
117     NULL, NULL, NULL, NULL, NULL, // 13 - 17
118     NULL, NULL, NULL, NULL, NULL, // 18 - 22
119     NULL, NULL, NULL, // 23 - 25
120     "Super",    // 26
121     "Hyper",    // 27
122     "Meta",        // 28
123     NULL,        // 29
124     "Release",    // 30
125     NULL,        // 31
126 };
127
128 const gchar *
129 ibus_key_event_to_string (guint keyval,
130                           guint modifiers)
131 {
132     guint i;
133     GString *str;
134     const gchar *keyval_name;
135
136     g_return_val_if_fail (keyval != IBUS_KEY_VoidSymbol, NULL);
137
138     keyval_name = ibus_keyval_name (keyval);
139     g_return_val_if_fail (keyval_name != NULL, NULL);
140
141     str = g_string_new ("");
142
143     for (i = 0; i < 32; i++) {
144         guint mask = 1 << i;
145
146         if ((modifiers & mask) == 0)
147             continue;
148         if (modifier_name[i] == NULL)
149             continue;
150
151         g_string_append (str, modifier_name[i]);
152         g_string_append_c (str, '+');
153     }
154
155     g_string_append (str, keyval_name);
156
157     return g_string_free (str, FALSE);
158 }
159
160 gboolean
161 ibus_key_event_from_string (const gchar *string,
162                             guint       *keyval,
163                             guint       *modifiers)
164 {
165     g_return_val_if_fail (string != NULL, FALSE);
166     g_return_val_if_fail (keyval != NULL, FALSE);
167     g_return_val_if_fail (modifiers != NULL, FALSE);
168
169     gchar **tokens = NULL;
170     gchar **p;
171     gboolean retval = FALSE;
172
173     tokens = g_strsplit (string, "+", 0);
174     g_return_val_if_fail (tokens != NULL, FALSE);
175
176     *keyval = 0;
177     *modifiers = 0;
178
179     for (p = tokens; *(p + 1) != NULL; p++) {
180         gint i;
181         for (i = 0; i < 32; i++) {
182             if (g_strcmp0 (modifier_name[i], *p) != 0)
183                 continue;
184             *modifiers |= (1 << i);
185             break;
186         }
187         if (i == 32) {
188             goto _out;
189         }
190     }
191
192     *keyval = ibus_keyval_from_name (*p);
193     if (*keyval != IBUS_KEY_VoidSymbol)
194         retval = TRUE;
195 _out:
196     if (tokens)
197         g_strfreev (tokens);
198     return retval;
199 }
200