Kill some relocs
[vlc.git] / 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[20];
40     uint32_t i_key_code;
41 } key_descriptor_t;
42
43 static const struct key_descriptor_s vlc_keys[] =
44 {
45     { "Unset", KEY_UNSET },
46     { "Backspace", KEY_BACKSPACE },
47     { "Tab", KEY_TAB },
48     { "Enter", KEY_ENTER },
49     { "Esc", KEY_ESC },
50     { "Space", ' ' },
51     { "Left", KEY_LEFT },
52     { "Right", KEY_RIGHT },
53     { "Up", KEY_UP },
54     { "Down", KEY_DOWN },
55     { "F1", KEY_F1 },
56     { "F2", KEY_F2 },
57     { "F3", KEY_F3 },
58     { "F4", KEY_F4 },
59     { "F5", KEY_F5 },
60     { "F6", KEY_F6 },
61     { "F7", KEY_F7 },
62     { "F8", KEY_F8 },
63     { "F9", KEY_F9 },
64     { "F10", KEY_F10 },
65     { "F11", KEY_F11 },
66     { "F12", KEY_F12 },
67     { "Home", KEY_HOME },
68     { "End", KEY_END },
69     { "Insert", KEY_INSERT },
70     { "Delete", KEY_DELETE },
71     { "Menu", KEY_MENU },
72     { "Page Up", KEY_PAGEUP },
73     { "Page Down", KEY_PAGEDOWN },
74     { "Browser Back", KEY_BROWSER_BACK },
75     { "Browser Forward", KEY_BROWSER_FORWARD },
76     { "Browser Refresh", KEY_BROWSER_REFRESH },
77     { "Browser Stop", KEY_BROWSER_STOP },
78     { "Browser Search", KEY_BROWSER_SEARCH },
79     { "Browser Favorites", KEY_BROWSER_FAVORITES },
80     { "Browser Home", KEY_BROWSER_HOME },
81     { "Volume Mute", KEY_VOLUME_MUTE },
82     { "Volume Down", KEY_VOLUME_DOWN },
83     { "Volume Up", KEY_VOLUME_UP },
84     { "Media Next Track", KEY_MEDIA_NEXT_TRACK },
85     { "Media Prev Track", KEY_MEDIA_PREV_TRACK },
86     { "Media Stop", KEY_MEDIA_STOP },
87     { "Media Play Pause", KEY_MEDIA_PLAY_PAUSE },
88     { "Mouse Wheel Up", KEY_MOUSEWHEELUP },
89     { "Mouse Wheel Down", KEY_MOUSEWHEELDOWN },
90     { "Mouse Wheel Left", KEY_MOUSEWHEELLEFT },
91     { "Mouse Wheel Right", KEY_MOUSEWHEELRIGHT },
92 };
93 enum { vlc_num_keys=sizeof(vlc_keys)/sizeof(struct key_descriptor_s) };
94
95 static int cmpkey (const void *key, const void *elem)
96 {
97     return ((uintptr_t)key) - ((key_descriptor_t *)elem)->i_key_code;
98 }
99
100 /* Convert Unicode code point to UTF-8 */
101 static char *utf8_cp (uint_fast32_t cp, char *buf)
102 {
103     if (cp < (1 << 7))
104     {
105         buf[1] = 0;
106         buf[0] = cp;
107     }
108     else if (cp < (1 << 11))
109     {
110         buf[2] = 0;
111         buf[1] = 0x80 | (cp & 0x3F);
112         cp >>= 6;
113         buf[0] = 0xC0 | cp;
114     }
115     else if (cp < (1 << 16))
116     {
117         buf[3] = 0;
118         buf[2] = 0x80 | (cp & 0x3F);
119         cp >>= 6;
120         buf[1] = 0x80 | (cp & 0x3F);
121         cp >>= 6;
122         buf[0] = 0xE0 | cp;
123     }
124     else if (cp < (1 << 21))
125     {
126         buf[4] = 0;
127         buf[3] = 0x80 | (cp & 0x3F);
128         cp >>= 6;
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
136         return NULL;
137     return buf;
138 }
139
140 uint_fast32_t ConfigStringToKey (const char *name)
141 {
142     uint_fast32_t mods = 0;
143     uint32_t cp;
144
145     for (;;)
146     {
147         size_t len = strcspn (name, "-+");
148         if (name[len] == '\0')
149             break;
150
151         if (len == 4 && !strncasecmp (name, "Ctrl", 4))
152             mods |= KEY_MODIFIER_CTRL;
153         if (len == 3 && !strncasecmp (name, "Alt", 3))
154             mods |= KEY_MODIFIER_ALT;
155         if (len == 5 && !strncasecmp (name, "Shift", 5))
156             mods |= KEY_MODIFIER_SHIFT;
157         if (len == 4 && !strncasecmp (name, "Meta", 4))
158             mods |= KEY_MODIFIER_META;
159         if (len == 7 && !strncasecmp (name, "Command", 7))
160             mods |= KEY_MODIFIER_COMMAND;
161
162         name += len + 1;
163     }
164
165     for (size_t i = 0; i < vlc_num_keys; i++)
166         if (!strcasecmp( vlc_keys[i].psz_key_string, name))
167             return vlc_keys[i].i_key_code | mods;
168
169     return (vlc_towc (name, &cp) > 0) ? (mods | cp) : 0;
170 }
171
172 char *vlc_keycode2str (uint_fast32_t code)
173 {
174     char *str, buf[5];
175     uintptr_t key = code & ~KEY_MODIFIER;
176
177     key_descriptor_t *d = bsearch ((void *)key, vlc_keys, vlc_num_keys,
178                                    sizeof (vlc_keys[0]), cmpkey);
179     if (d == NULL && utf8_cp (key, buf) == NULL)
180         return NULL;
181
182     if (asprintf (&str, "%s%s%s%s%s%s",
183                   (code & KEY_MODIFIER_CTRL) ? "Ctrl+" : "",
184                   (code & KEY_MODIFIER_ALT) ? "Alt+" : "",
185                   (code & KEY_MODIFIER_SHIFT) ? "Shift+" : "",
186                   (code & KEY_MODIFIER_META) ? "Meta+" : "",
187                   (code & KEY_MODIFIER_COMMAND) ? "Command+" : "",
188                   (d != NULL) ? d->psz_key_string : buf) == -1)
189         return NULL;
190
191     return str;
192 }