]> git.sesse.net Git - vlc/blob - src/config/keys.c
Unduplicate code
[vlc] / src / config / keys.c
1 /*****************************************************************************
2  * keys.c: keys configuration
3  *****************************************************************************
4  * Copyright (C) 2003-2009 the VideoLAN team
5  *
6  * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 /**
28  * \file
29  * This file defines functions and structures for hotkey handling in vlc
30  */
31
32 #include <vlc_common.h>
33 #include <vlc_keys.h>
34 #include "configuration.h"
35 #include "libvlc.h"
36
37 typedef struct key_descriptor_s
38 {
39     const char *psz_key_string;
40     uint32_t i_key_code;
41 } key_descriptor_t;
42
43 static const struct key_descriptor_s vlc_modifiers[] =
44 {
45     { "Alt", KEY_MODIFIER_ALT },
46     { "Shift", KEY_MODIFIER_SHIFT },
47     { "Ctrl", KEY_MODIFIER_CTRL },
48     { "Meta", KEY_MODIFIER_META },
49     { "Command", KEY_MODIFIER_COMMAND }
50 };
51 enum { vlc_num_modifiers=sizeof(vlc_modifiers)
52                         /sizeof(struct key_descriptor_s) };
53
54 static const struct key_descriptor_s vlc_keys[] =
55 {
56     { "Unset", KEY_UNSET },
57     { "Backspace", KEY_BACKSPACE },
58     { "Tab", KEY_TAB },
59     { "Enter", KEY_ENTER },
60     { "Esc", KEY_ESC },
61     { "Space", ' ' },
62     { "Left", KEY_LEFT },
63     { "Right", KEY_RIGHT },
64     { "Up", KEY_UP },
65     { "Down", KEY_DOWN },
66     { "F1", KEY_F1 },
67     { "F2", KEY_F2 },
68     { "F3", KEY_F3 },
69     { "F4", KEY_F4 },
70     { "F5", KEY_F5 },
71     { "F6", KEY_F6 },
72     { "F7", KEY_F7 },
73     { "F8", KEY_F8 },
74     { "F9", KEY_F9 },
75     { "F10", KEY_F10 },
76     { "F11", KEY_F11 },
77     { "F12", KEY_F12 },
78     { "Home", KEY_HOME },
79     { "End", KEY_END },
80     { "Insert", KEY_INSERT },
81     { "Delete", KEY_DELETE },
82     { "Menu", KEY_MENU },
83     { "Page Up", KEY_PAGEUP },
84     { "Page Down", KEY_PAGEDOWN },
85     { "Browser Back", KEY_BROWSER_BACK },
86     { "Browser Forward", KEY_BROWSER_FORWARD },
87     { "Browser Refresh", KEY_BROWSER_REFRESH },
88     { "Browser Stop", KEY_BROWSER_STOP },
89     { "Browser Search", KEY_BROWSER_SEARCH },
90     { "Browser Favorites", KEY_BROWSER_FAVORITES },
91     { "Browser Home", KEY_BROWSER_HOME },
92     { "Volume Mute", KEY_VOLUME_MUTE },
93     { "Volume Down", KEY_VOLUME_DOWN },
94     { "Volume Up", KEY_VOLUME_UP },
95     { "Media Next Track", KEY_MEDIA_NEXT_TRACK },
96     { "Media Prev Track", KEY_MEDIA_PREV_TRACK },
97     { "Media Stop", KEY_MEDIA_STOP },
98     { "Media Play Pause", KEY_MEDIA_PLAY_PAUSE },
99     { "Mouse Wheel Up", KEY_MOUSEWHEELUP },
100     { "Mouse Wheel Down", KEY_MOUSEWHEELDOWN },
101     { "Mouse Wheel Left", KEY_MOUSEWHEELLEFT },
102     { "Mouse Wheel Right", KEY_MOUSEWHEELRIGHT },
103 };
104 enum { vlc_num_keys=sizeof(vlc_keys)/sizeof(struct key_descriptor_s) };
105
106 static int cmpkey (const void *key, const void *elem)
107 {
108     return ((uintptr_t)key) - ((key_descriptor_t *)elem)->i_key_code;
109 }
110
111 /* Convert Unicode code point to UTF-8 */
112 static char *utf8_cp (uint_fast32_t cp, char *buf)
113 {
114     if (cp < (1 << 7))
115     {
116         buf[1] = 0;
117         buf[0] = cp;
118     }
119     else if (cp < (1 << 11))
120     {
121         buf[2] = 0;
122         buf[1] = 0x80 | (cp & 0x3F);
123         cp >>= 6;
124         buf[0] = 0xC0 | cp;
125     }
126     else if (cp < (1 << 16))
127     {
128         buf[3] = 0;
129         buf[2] = 0x80 | (cp & 0x3F);
130         cp >>= 6;
131         buf[1] = 0x80 | (cp & 0x3F);
132         cp >>= 6;
133         buf[0] = 0xE0 | cp;
134     }
135     else if (cp < (1 << 21))
136     {
137         buf[4] = 0;
138         buf[3] = 0x80 | (cp & 0x3F);
139         cp >>= 6;
140         buf[2] = 0x80 | (cp & 0x3F);
141         cp >>= 6;
142         buf[1] = 0x80 | (cp & 0x3F);
143         cp >>= 6;
144         buf[0] = 0xE0 | cp;
145     }
146     else
147         return NULL;
148     return buf;
149 }
150
151 char *KeyToString (uint_fast32_t sym)
152 {
153     key_descriptor_t *d;
154
155     d = bsearch ((void *)(uintptr_t)sym, vlc_keys, vlc_num_keys,
156                  sizeof (vlc_keys[0]), cmpkey);
157     if (d)
158         return strdup (d->psz_key_string);
159
160     char buf[5];
161     if (utf8_cp (sym, buf))
162         return strdup (buf);
163
164     return NULL;
165 }
166
167 uint_fast32_t ConfigStringToKey (const char *name)
168 {
169     uint_fast32_t mods = 0;
170     uint32_t cp;
171
172     for (;;)
173     {
174         const char *psz_parser = strchr (name, '-');
175         if (psz_parser == NULL || psz_parser == name)
176             break;
177
178         for (size_t i = 0; i < vlc_num_modifiers; i++)
179         {
180             if (!strncasecmp (vlc_modifiers[i].psz_key_string, name,
181                               strlen (vlc_modifiers[i].psz_key_string)))
182             {
183                 mods |= vlc_modifiers[i].i_key_code;
184             }
185         }
186         name = psz_parser + 1;
187     }
188
189     for (size_t i = 0; i < vlc_num_keys; i++)
190         if (!strcasecmp( vlc_keys[i].psz_key_string, name))
191             return vlc_keys[i].i_key_code | mods;
192
193     return (vlc_towc (name, &cp) > 0) ? (mods | cp) : 0;
194 }
195
196 char *ConfigKeyToString (uint_fast32_t i_key)
197 {
198     // Worst case appears to be 45 characters:
199     // "Command-Meta-Ctrl-Shift-Alt-Browser Favorites"
200     char *psz_key = malloc (64);
201     if (!psz_key)
202         return NULL;
203
204     char *p = psz_key, *psz_end = psz_key + 54;
205     *p = '\0';
206
207     for (size_t i = 0; i < vlc_num_modifiers; i++)
208     {
209         if (i_key & vlc_modifiers[i].i_key_code)
210         {
211             p += snprintf (p, psz_end - p, "%s-",
212                            vlc_modifiers[i].psz_key_string);
213         }
214     }
215
216     key_descriptor_t *d;
217     char buf[5];
218
219     i_key &= ~KEY_MODIFIER;
220     d = bsearch ((void *)(uintptr_t)i_key, vlc_keys, vlc_num_keys,
221                  sizeof (vlc_keys[0]), cmpkey);
222     if (d)
223         p += snprintf (p, psz_end - p, "%s", d->psz_key_string);
224     else if (utf8_cp (i_key, buf))
225         p += snprintf (p, psz_end - p, "%s", buf);
226     else
227         return NULL;
228
229     return psz_key;
230 }