1 /*****************************************************************************
2 * keys.c: keys configuration
3 *****************************************************************************
4 * Copyright (C) 2003-2009 the VideoLAN team
6 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
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.
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.
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 *****************************************************************************/
29 * This file defines functions and structures for hotkey handling in vlc
32 #include <vlc_common.h>
34 #include "configuration.h"
36 typedef struct key_descriptor_s
38 const char *psz_key_string;
42 static const struct key_descriptor_s vlc_modifiers[] =
44 { "Alt", KEY_MODIFIER_ALT },
45 { "Shift", KEY_MODIFIER_SHIFT },
46 { "Ctrl", KEY_MODIFIER_CTRL },
47 { "Meta", KEY_MODIFIER_META },
48 { "Command", KEY_MODIFIER_COMMAND }
50 enum { vlc_num_modifiers=sizeof(vlc_modifiers)
51 /sizeof(struct key_descriptor_s) };
53 static const struct key_descriptor_s vlc_keys[] =
55 { "Unset", KEY_UNSET },
56 { "Backspace", KEY_BACKSPACE },
58 { "Enter", KEY_ENTER },
62 { "Right", KEY_RIGHT },
79 { "Insert", KEY_INSERT },
80 { "Delete", KEY_DELETE },
82 { "Page Up", KEY_PAGEUP },
83 { "Page Down", KEY_PAGEDOWN },
84 { "Browser Back", KEY_BROWSER_BACK },
85 { "Browser Forward", KEY_BROWSER_FORWARD },
86 { "Browser Refresh", KEY_BROWSER_REFRESH },
87 { "Browser Stop", KEY_BROWSER_STOP },
88 { "Browser Search", KEY_BROWSER_SEARCH },
89 { "Browser Favorites", KEY_BROWSER_FAVORITES },
90 { "Browser Home", KEY_BROWSER_HOME },
91 { "Volume Mute", KEY_VOLUME_MUTE },
92 { "Volume Down", KEY_VOLUME_DOWN },
93 { "Volume Up", KEY_VOLUME_UP },
94 { "Media Next Track", KEY_MEDIA_NEXT_TRACK },
95 { "Media Prev Track", KEY_MEDIA_PREV_TRACK },
96 { "Media Stop", KEY_MEDIA_STOP },
97 { "Media Play Pause", KEY_MEDIA_PLAY_PAUSE },
98 { "Mouse Wheel Up", KEY_MOUSEWHEELUP },
99 { "Mouse Wheel Down", KEY_MOUSEWHEELDOWN },
100 { "Mouse Wheel Left", KEY_MOUSEWHEELLEFT },
101 { "Mouse Wheel Right", KEY_MOUSEWHEELRIGHT },
103 enum { vlc_num_keys=sizeof(vlc_keys)/sizeof(struct key_descriptor_s) };
105 static int cmpkey (const void *key, const void *elem)
107 return ((uintptr_t)key) - ((key_descriptor_t *)elem)->i_key_code;
110 /* Convert Unicode code point to UTF-8 */
111 static char *utf8_cp (uint_fast32_t cp, char *buf)
118 else if (cp < (1 << 11))
121 buf[1] = 0x80 | (cp & 0x3F);
125 else if (cp < (1 << 16))
128 buf[2] = 0x80 | (cp & 0x3F);
130 buf[1] = 0x80 | (cp & 0x3F);
134 else if (cp < (1 << 21))
137 buf[3] = 0x80 | (cp & 0x3F);
139 buf[2] = 0x80 | (cp & 0x3F);
141 buf[1] = 0x80 | (cp & 0x3F);
150 /* Convert UTF-8 to Unicode code point */
151 static uint_fast32_t cp_utf8 (const char *utf8)
154 size_t l = strlen (utf8);
156 if (f < 0x80) /* ASCII (7 bits) */
158 if (f < 0xC0 || l < 2) /* bad */
160 if (f < 0xE0) /* two bytes (11 bits) */
161 return ((f & 0x1F) << 6) | (utf8[1] & 0x3F);
164 if (f < 0xF0) /* three bytes (16 bits) */
165 return ((f & 0x0F) << 12) | ((utf8[1] & 0x3F) << 6)
169 if (f < 0xF8) /* four bytes (21 bits) */
170 return ((f & 0x07) << 18) | ((utf8[1] & 0x3F) << 12)
171 | ((utf8[2] & 0x3F) << 6) | (utf8[3] & 0x3F);
175 char *KeyToString (uint_fast32_t sym)
179 d = bsearch ((void *)(uintptr_t)sym, vlc_keys, vlc_num_keys,
180 sizeof (vlc_keys[0]), cmpkey);
182 return strdup (d->psz_key_string);
185 if (utf8_cp (sym, buf))
191 uint_fast32_t StringToKey (char *name)
193 for (size_t i = 0; i < vlc_num_keys; i++)
194 if (!strcmp (vlc_keys[i].psz_key_string, name))
195 return vlc_keys[i].i_key_code;
197 return cp_utf8 (name);
200 uint_fast32_t ConfigStringToKey (const char *name)
202 uint_fast32_t mods = 0;
206 const char *psz_parser = strchr (name, '-');
207 if (psz_parser == NULL || psz_parser == name)
210 for (size_t i = 0; i < vlc_num_modifiers; i++)
212 if (!strncasecmp (vlc_modifiers[i].psz_key_string, name,
213 strlen (vlc_modifiers[i].psz_key_string)))
215 mods |= vlc_modifiers[i].i_key_code;
218 name = psz_parser + 1;
221 for (size_t i = 0; i < vlc_num_keys; i++)
222 if (!strcasecmp( vlc_keys[i].psz_key_string, name))
223 return vlc_keys[i].i_key_code | mods;
225 return cp_utf8 (name) | mods;
228 char *ConfigKeyToString (uint_fast32_t i_key)
230 // Worst case appears to be 45 characters:
231 // "Command-Meta-Ctrl-Shift-Alt-Browser Favorites"
232 char *psz_key = malloc (64);
236 char *p = psz_key, *psz_end = psz_key + 54;
239 for (size_t i = 0; i < vlc_num_modifiers; i++)
241 if (i_key & vlc_modifiers[i].i_key_code)
243 p += snprintf (p, psz_end - p, "%s-",
244 vlc_modifiers[i].psz_key_string);
251 i_key &= ~KEY_MODIFIER;
252 d = bsearch ((void *)(uintptr_t)i_key, vlc_keys, vlc_num_keys,
253 sizeof (vlc_keys[0]), cmpkey);
255 p += snprintf (p, psz_end - p, "%s", d->psz_key_string);
256 else if (utf8_cp (i_key, buf))
257 p += snprintf (p, psz_end - p, "%s", buf);