• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 #include "android/skin/keyset.h"
13 #include "android/utils/debug.h"
14 #include "android/utils/bufprint.h"
15 #include "android/android.h"
16 #include <SDL.h>
17 
18 #define  DEBUG  1
19 
20 #if 1
21 #  define  D_ACTIVE  VERBOSE_CHECK(keys)
22 #else
23 #  define  D_ACTIVE  DEBUG
24 #endif
25 
26 #if DEBUG
27 #  define  D(...)   VERBOSE_PRINT(keys,__VA_ARGS__)
28 #else
29 #  define  D(...)   ((void)0)
30 #endif
31 
32 #define _SKIN_KEY_COMMAND(x,y)    #x ,
33 static const char* const command_strings[ SKIN_KEY_COMMAND_MAX ] = {
34     SKIN_KEY_COMMAND_LIST
35 };
36 #undef _SKIN_KEY_COMMAND
37 
38 const char*
skin_key_command_to_str(SkinKeyCommand cmd)39 skin_key_command_to_str( SkinKeyCommand  cmd )
40 {
41     if (cmd > SKIN_KEY_COMMAND_NONE && cmd < SKIN_KEY_COMMAND_MAX)
42         return  command_strings[cmd];
43 
44     return NULL;
45 }
46 
47 SkinKeyCommand
skin_key_command_from_str(const char * str,int len)48 skin_key_command_from_str( const char*  str, int  len )
49 {
50     int  nn;
51     if (len < 0)
52         len = strlen(str);
53     for (nn = 0; nn < SKIN_KEY_COMMAND_MAX; nn++) {
54         const char*  cmd = command_strings[nn];
55 
56         if ( !memcmp( cmd, str, len ) && cmd[len] == 0 )
57             return (SkinKeyCommand) nn;
58     }
59     return SKIN_KEY_COMMAND_NONE;
60 }
61 
62 
63 #define _SKIN_KEY_COMMAND(x,y)    y ,
64 static const char* const command_descriptions[ SKIN_KEY_COMMAND_MAX ] = {
65     SKIN_KEY_COMMAND_LIST
66 };
67 #undef _SKIN_KEY_COMMAND
68 
69 const char*
skin_key_command_description(SkinKeyCommand cmd)70 skin_key_command_description( SkinKeyCommand  cmd )
71 {
72     if (cmd > SKIN_KEY_COMMAND_NONE && cmd < SKIN_KEY_COMMAND_MAX)
73         return command_descriptions[cmd];
74 
75     return NULL;
76 }
77 
78 #define  _KEYSYM1_(x)  _KEYSYM_(x,x)
79 
80 #define _KEYSYM_LIST  \
81     _KEYSYM1_(BACKSPACE)   \
82     _KEYSYM1_(TAB)         \
83     _KEYSYM1_(CLEAR)       \
84     _KEYSYM_(RETURN,ENTER) \
85     _KEYSYM1_(PAUSE)       \
86     _KEYSYM1_(ESCAPE)      \
87     _KEYSYM1_(SPACE)       \
88     _KEYSYM_(EXCLAIM,EXCLAM)    \
89     _KEYSYM_(QUOTEDBL,DOUBLEQUOTE)   \
90     _KEYSYM_(HASH,HASH)    \
91     _KEYSYM1_(DOLLAR)      \
92     _KEYSYM1_(AMPERSAND)   \
93     _KEYSYM1_(QUOTE)       \
94     _KEYSYM_(LEFTPAREN,LPAREN)  \
95     _KEYSYM_(RIGHTPAREN,RPAREN) \
96     _KEYSYM1_(ASTERISK) \
97     _KEYSYM1_(PLUS) \
98     _KEYSYM1_(COMMA) \
99     _KEYSYM1_(MINUS) \
100     _KEYSYM1_(PERIOD) \
101     _KEYSYM1_(SLASH) \
102     _KEYSYM1_(0) \
103     _KEYSYM1_(1) \
104     _KEYSYM1_(2) \
105     _KEYSYM1_(3) \
106     _KEYSYM1_(4) \
107     _KEYSYM1_(5) \
108     _KEYSYM1_(6) \
109     _KEYSYM1_(7) \
110     _KEYSYM1_(8) \
111     _KEYSYM1_(9) \
112     _KEYSYM1_(COLON) \
113     _KEYSYM1_(SEMICOLON) \
114     _KEYSYM1_(LESS) \
115     _KEYSYM_(EQUALS,EQUAL) \
116     _KEYSYM1_(GREATER) \
117     _KEYSYM1_(QUESTION) \
118     _KEYSYM1_(AT) \
119     _KEYSYM1_(LEFTBRACKET) \
120     _KEYSYM1_(BACKSLASH) \
121     _KEYSYM1_(RIGHTBRACKET) \
122     _KEYSYM1_(CARET) \
123     _KEYSYM1_(UNDERSCORE) \
124     _KEYSYM1_(BACKQUOTE) \
125     _KEYSYM_(a,A) \
126     _KEYSYM_(b,B) \
127     _KEYSYM_(c,C) \
128     _KEYSYM_(d,D) \
129     _KEYSYM_(e,E) \
130     _KEYSYM_(f,F) \
131     _KEYSYM_(g,G) \
132     _KEYSYM_(h,H) \
133     _KEYSYM_(i,I) \
134     _KEYSYM_(j,J) \
135     _KEYSYM_(k,K) \
136     _KEYSYM_(l,L) \
137     _KEYSYM_(m,M) \
138     _KEYSYM_(n,N) \
139     _KEYSYM_(o,O) \
140     _KEYSYM_(p,P) \
141     _KEYSYM_(q,Q) \
142     _KEYSYM_(r,R) \
143     _KEYSYM_(s,S) \
144     _KEYSYM_(t,T) \
145     _KEYSYM_(u,U) \
146     _KEYSYM_(v,V) \
147     _KEYSYM_(w,W) \
148     _KEYSYM_(x,X) \
149     _KEYSYM_(y,Y) \
150     _KEYSYM_(z,Z) \
151     _KEYSYM1_(DELETE) \
152     _KEYSYM_(KP_PLUS,KEYPAD_PLUS)     \
153     _KEYSYM_(KP_MINUS,KEYPAD_MINUS)    \
154     _KEYSYM_(KP_MULTIPLY,KEYPAD_MULTIPLY) \
155     _KEYSYM_(KP_DIVIDE,KEYPAD_DIVIDE)   \
156     _KEYSYM_(KP_ENTER,KEYPAD_ENTER)    \
157     _KEYSYM_(KP_PERIOD,KEYPAD_PERIOD)   \
158     _KEYSYM_(KP_EQUALS,KEYPAD_EQUALS)   \
159     _KEYSYM_(KP1,KEYPAD_1)         \
160     _KEYSYM_(KP2,KEYPAD_2)         \
161     _KEYSYM_(KP3,KEYPAD_3)         \
162     _KEYSYM_(KP4,KEYPAD_4)         \
163     _KEYSYM_(KP5,KEYPAD_5)         \
164     _KEYSYM_(KP6,KEYPAD_6)         \
165     _KEYSYM_(KP7,KEYPAD_7)         \
166     _KEYSYM_(KP8,KEYPAD_8)         \
167     _KEYSYM_(KP9,KEYPAD_9)         \
168     _KEYSYM_(KP0,KEYPAD_0)         \
169     _KEYSYM1_(UP)  \
170     _KEYSYM1_(DOWN) \
171     _KEYSYM1_(RIGHT) \
172     _KEYSYM1_(LEFT) \
173     _KEYSYM1_(INSERT) \
174     _KEYSYM1_(HOME) \
175     _KEYSYM1_(END) \
176     _KEYSYM1_(PAGEUP) \
177     _KEYSYM1_(PAGEDOWN) \
178     _KEYSYM1_(F1) \
179     _KEYSYM1_(F2) \
180     _KEYSYM1_(F3) \
181     _KEYSYM1_(F4) \
182     _KEYSYM1_(F5) \
183     _KEYSYM1_(F6) \
184     _KEYSYM1_(F7) \
185     _KEYSYM1_(F8) \
186     _KEYSYM1_(F9) \
187     _KEYSYM1_(F10) \
188     _KEYSYM1_(F11) \
189     _KEYSYM1_(F12) \
190     _KEYSYM1_(F13) \
191     _KEYSYM1_(F14) \
192     _KEYSYM1_(F15) \
193     _KEYSYM1_(SCROLLOCK) \
194     _KEYSYM1_(SYSREQ) \
195     _KEYSYM1_(PRINT) \
196     _KEYSYM1_(BREAK) \
197 
198 #define _KEYSYM_(x,y)   { SDLK_##x, #y },
199 static const struct { int  _sym; const char*  _str; }  keysym_names[] =
200 {
201     _KEYSYM_LIST
202     { 0, NULL }
203 };
204 #undef _KEYSYM_
205 
206 int
skin_keysym_str_count(void)207 skin_keysym_str_count( void )
208 {
209     return sizeof(keysym_names)/sizeof(keysym_names[0])-1;
210 }
211 
212 const char*
skin_keysym_str(int index)213 skin_keysym_str( int  index )
214 {
215     if (index >= 0 && index < skin_keysym_str_count())
216         return keysym_names[index]._str;
217 
218     return NULL;
219 }
220 
221 const char*
skin_key_symmod_to_str(int sym,int mod)222 skin_key_symmod_to_str( int  sym, int  mod )
223 {
224     static char  temp[32];
225     char*        p = temp;
226     char*        end = p + sizeof(temp);
227     int          nn;
228 
229     if ((mod & KMOD_LCTRL) != 0) {
230         p = bufprint(p, end, "Ctrl-");
231     }
232     if ((mod & KMOD_RCTRL) != 0) {
233         p = bufprint(p, end, "RCtrl-");
234     }
235     if ((mod & KMOD_LSHIFT) != 0) {
236         p = bufprint(p, end, "Shift-");
237     }
238     if ((mod & KMOD_RSHIFT) != 0) {
239         p = bufprint(p, end, "RShift-");
240     }
241     if ((mod & KMOD_LALT) != 0) {
242         p = bufprint(p, end, "Alt-");
243     }
244     if ((mod & KMOD_RALT) != 0) {
245         p = bufprint(p, end, "RAlt-");
246     }
247     for (nn = 0; keysym_names[nn]._sym != 0; nn++) {
248         if (keysym_names[nn]._sym == sym) {
249             p = bufprint(p, end, "%s", keysym_names[nn]._str);
250             return temp;;
251         }
252     }
253 
254     if (sym >= 32 && sym <= 127) {
255         p = bufprint(p, end, "%c", sym);
256         return temp;
257     }
258 
259     return NULL;
260 }
261 
262 
263 int
skin_key_symmod_from_str(const char * str,int * psym,int * pmod)264 skin_key_symmod_from_str( const char*  str, int  *psym, int  *pmod )
265 {
266     int          mod = 0;
267     int          match = 1;
268     int          nn;
269     const char*  s0 = str;
270     static const struct { const char*  prefix; int  mod; }  mods[] =
271     {
272         { "^",      KMOD_LCTRL },
273         { "Ctrl",   KMOD_LCTRL },
274         { "ctrl",   KMOD_LCTRL },
275         { "RCtrl",  KMOD_RCTRL },
276         { "rctrl",  KMOD_RCTRL },
277         { "Alt",    KMOD_LALT },
278         { "alt",    KMOD_LALT },
279         { "RAlt",   KMOD_RALT },
280         { "ralt",   KMOD_RALT },
281         { "Shift",  KMOD_LSHIFT },
282         { "shift",  KMOD_LSHIFT },
283         { "RShift", KMOD_RSHIFT },
284         { "rshift", KMOD_RSHIFT },
285         { NULL, 0 }
286     };
287 
288     while (match) {
289         match = 0;
290         for (nn = 0; mods[nn].prefix != NULL; nn++) {
291             const char*  prefix = mods[nn].prefix;
292             int          len    = strlen(prefix);
293 
294             if ( !memcmp(str, prefix, len) ) {
295                 str  += len;
296                 match = 1;
297                 mod  |= mods[nn].mod;
298                 if (str[0] == '-' && str[1] != 0)
299                     str++;
300                 break;
301             }
302         }
303     }
304 
305     for (nn = 0; keysym_names[nn]._sym; nn++) {
306 #ifdef _WIN32
307         if ( !stricmp(str, keysym_names[nn]._str) )
308 #else
309         if ( !strcasecmp(str, keysym_names[nn]._str) )
310 #endif
311         {
312             *psym = keysym_names[nn]._sym;
313             *pmod = mod;
314             return 0;
315         }
316     }
317 
318     D("%s: can't find sym value for '%s' (mod=%d, str=%s)", __FUNCTION__, s0, mod, str);
319     return -1;
320 }
321 
322 
323 typedef struct {
324     int             sym;
325     int             mod;
326     SkinKeyCommand  command;
327 } SkinKeyItem;
328 
329 
330 struct SkinKeyset {
331     int           num_items;
332     int           max_items;
333     SkinKeyItem*  items;
334 };
335 
336 
337 static int
skin_keyset_add(SkinKeyset * kset,int sym,int mod,SkinKeyCommand command)338 skin_keyset_add( SkinKeyset*  kset, int  sym, int  mod, SkinKeyCommand  command )
339 {
340     SkinKeyItem*  item = kset->items;
341     SkinKeyItem*  end  = item + kset->num_items;
342     SkinKeyItem*  first = NULL;
343     int           count = 0;
344 
345     D( "adding binding %s to %s", skin_key_command_to_str(command), skin_key_symmod_to_str(sym,mod));
346     for ( ; item < end; item++) {
347         if (item->command == command) {
348             if (!first)
349                 first = item;
350             if (++count == SKIN_KEY_COMMAND_MAX_BINDINGS) {
351                 /* replace the first (oldest) one in the list */
352                 first->sym = sym;
353                 first->mod = mod;
354                 return 0;
355             }
356             continue;
357         }
358         if (item->sym == sym && item->mod == mod) {
359             /* replace a (sym,mod) binding */
360             item->command = command;
361             return 0;
362         }
363     }
364     if (kset->num_items >= kset->max_items) {
365         int           old_size  = kset->max_items;
366         int           new_size  = old_size + (old_size >> 1) + 4;
367         SkinKeyItem*  new_items = realloc( kset->items, new_size*sizeof(SkinKeyItem) );
368         if (new_items == NULL) {
369             return -1;
370         }
371         kset->items     = new_items;
372         kset->max_items = new_size;
373     }
374     item = kset->items + kset->num_items++;
375     item->command = command;
376     item->sym     = sym;
377     item->mod     = mod;
378     return 1;
379 }
380 
381 
382 SkinKeyset*
skin_keyset_new(AConfig * root)383 skin_keyset_new ( AConfig*  root )
384 {
385     SkinKeyset*  kset = calloc(1, sizeof(*kset));
386     AConfig*     node = root->first_child;;
387 
388     if (kset == NULL)
389         return NULL;
390 
391     for ( ; node != NULL; node = node->next )
392     {
393         SkinKeyCommand  command;
394         int             sym, mod;
395         char*           p;
396 
397         command = skin_key_command_from_str( node->name, -1 );
398         if (command == SKIN_KEY_COMMAND_NONE) {
399             D( "ignoring unknown keyset command '%s'", node->name );
400             continue;
401         }
402         p = (char*)node->value;
403         while (*p) {
404             char*  q = strpbrk( p, " \t,:" );
405             if (q == NULL)
406                 q = p + strlen(p);
407 
408             if (q > p) {
409                 int   len = q - p;
410                 char  keys[24];
411                 if (len+1 >= (int)sizeof(keys)) {
412                     D("key binding too long: '%s'", p);
413                 }
414                 else {
415                     memcpy( keys, p, len );
416                     keys[len] = 0;
417                     if ( skin_key_symmod_from_str( keys, &sym, &mod ) < 0 ) {
418                         D( "ignoring unknown keys '%s' for command '%s'",
419                                 keys, node->name );
420                     } else {
421                         skin_keyset_add( kset, sym, mod, command );
422                     }
423                 }
424             } else if (*q)
425                 q += 1;
426 
427             p = q;
428         }
429     }
430     return  kset;
431 }
432 
433 
434 SkinKeyset*
skin_keyset_new_from_text(const char * text)435 skin_keyset_new_from_text( const char*  text )
436 {
437     AConfig*     root = aconfig_node("","");
438     char*        str = strdup(text);
439     SkinKeyset*  result;
440 
441     D("kset new from:\n%s", text);
442     aconfig_load( root, str );
443     result = skin_keyset_new( root );
444     free(str);
445     D("kset done result=%p", result);
446     return result;
447 }
448 
449 
450 void
skin_keyset_free(SkinKeyset * kset)451 skin_keyset_free( SkinKeyset*  kset )
452 {
453     if (kset) {
454         free(kset->items);
455         kset->items     = NULL;
456         kset->num_items = 0;
457         kset->max_items = 0;
458         free(kset);
459     }
460 }
461 
462 
463 extern int
skin_keyset_get_bindings(SkinKeyset * kset,SkinKeyCommand command,SkinKeyBinding * bindings)464 skin_keyset_get_bindings( SkinKeyset*      kset,
465                           SkinKeyCommand   command,
466                           SkinKeyBinding*  bindings )
467 {
468     if (kset) {
469         int     count = 0;
470         SkinKeyItem*  item = kset->items;
471         SkinKeyItem*  end  = item + kset->num_items;
472 
473         for ( ; item < end; item++ ) {
474             if (item->command == command) {
475                 bindings->sym = item->sym;
476                 bindings->mod = item->mod;
477                 bindings ++;
478                 if ( ++count >= SKIN_KEY_COMMAND_MAX_BINDINGS ) {
479                     /* shouldn't happen, but be safe */
480                     break;
481                 }
482             }
483         }
484         return count;
485     }
486     return -1;
487 }
488 
489 
490 /* retrieve the command corresponding to a given (sym,mod) pair. returns SKIN_KEY_COMMAND_NONE if not found */
491 SkinKeyCommand
skin_keyset_get_command(SkinKeyset * kset,int sym,int mod)492 skin_keyset_get_command( SkinKeyset*  kset, int  sym, int mod )
493 {
494     if (kset) {
495         SkinKeyItem*  item = kset->items;
496         SkinKeyItem*  end  = item + kset->num_items;
497 
498         for ( ; item < end; item++ ) {
499             if (item->sym == sym && item->mod == mod) {
500                 return item->command;
501             }
502         }
503     }
504     return SKIN_KEY_COMMAND_NONE;
505 }
506 
507 
508 const char*
skin_keyset_get_default(void)509 skin_keyset_get_default( void )
510 {
511     return
512     "BUTTON_CALL         F3\n"
513     "BUTTON_HANGUP       F4\n"
514     "BUTTON_HOME         Home\n"
515     "BUTTON_BACK         Escape\n"
516     "BUTTON_MENU         F2, PageUp\n"
517     "BUTTON_STAR         Shift-F2, PageDown\n"
518     "BUTTON_POWER        F7\n"
519     "BUTTON_SEARCH       F5\n"
520     "BUTTON_CAMERA       Ctrl-Keypad_5, Ctrl-F3\n"
521     "BUTTON_VOLUME_UP    Keypad_Plus, Ctrl-F5\n"
522     "BUTTON_VOLUME_DOWN  Keypad_Minus, Ctrl-F6\n"
523 
524     "TOGGLE_NETWORK      F8\n"
525     "TOGGLE_TRACING      F9\n"
526     "TOGGLE_FULLSCREEN   Alt-Enter\n"
527 
528     "BUTTON_DPAD_CENTER  Keypad_5\n"
529     "BUTTON_DPAD_UP      Keypad_8\n"
530     "BUTTON_DPAD_LEFT    Keypad_4\n"
531     "BUTTON_DPAD_RIGHT   Keypad_6\n"
532     "BUTTON_DPAD_DOWN    Keypad_2\n"
533 
534     "TOGGLE_TRACKBALL    F6\n"
535     "SHOW_TRACKBALL      Delete\n"
536 
537     "CHANGE_LAYOUT_PREV  Keypad_7, Ctrl-F11\n"
538     "CHANGE_LAYOUT_NEXT  Keypad_9, Ctrl-F12\n"
539     "ONION_ALPHA_UP      Keypad_Multiply\n"
540     "ONION_ALPHA_DOWN    Keypad_Divide\n"
541     ;
542 }
543