- implemented load/save of joystick config
[supertux.git] / src / control / joystickkeyboardcontroller.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>,
5 //                2007 Ingo Ruhnke <grumbel@gmx.de>
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 #include <config.h>
22
23 #include <sstream>
24 #include "joystickkeyboardcontroller.hpp"
25 #include "log.hpp"
26 #include "gui/menu.hpp"
27 #include "gettext.hpp"
28 #include "lisp/lisp.hpp"
29 #include "lisp/list_iterator.hpp"
30 #include "game_session.hpp"
31 #include "console.hpp"
32 #include "gameconfig.hpp"
33
34 class JoystickKeyboardController::JoystickMenu : public Menu
35 {
36 public:
37   JoystickMenu(JoystickKeyboardController* controller);
38   virtual ~JoystickMenu();
39
40   void update();
41   std::string get_button_name(int button);
42   void update_menu_item(Control id);
43   virtual void menu_action(MenuItem* item);
44   JoystickKeyboardController* controller;
45 };
46
47 class JoystickKeyboardController::KeyboardMenu : public Menu
48 {
49 public:
50   KeyboardMenu(JoystickKeyboardController* controller);
51   ~KeyboardMenu();
52
53   void update();
54   std::string get_key_name(SDLKey key);
55   virtual void menu_action(MenuItem* item);
56   JoystickKeyboardController* controller;
57 };
58
59 JoystickKeyboardController::JoystickKeyboardController()
60   : wait_for_key(-1), wait_for_joystick(-1),
61     key_options_menu(0), joystick_options_menu(0)
62 {
63   // initialize default keyboard map
64   keymap.insert(std::make_pair(SDLK_LEFT,     LEFT));
65   keymap.insert(std::make_pair(SDLK_RIGHT,    RIGHT));
66   keymap.insert(std::make_pair(SDLK_UP,       UP));
67   keymap.insert(std::make_pair(SDLK_DOWN,     DOWN));
68   keymap.insert(std::make_pair(SDLK_SPACE,    JUMP));
69   keymap.insert(std::make_pair(SDLK_LCTRL,    ACTION));
70   keymap.insert(std::make_pair(SDLK_LALT,     ACTION));
71   keymap.insert(std::make_pair(SDLK_ESCAPE,   PAUSE_MENU));
72   keymap.insert(std::make_pair(SDLK_p,        PAUSE_MENU));
73   keymap.insert(std::make_pair(SDLK_PAUSE,    PAUSE_MENU));
74   keymap.insert(std::make_pair(SDLK_RETURN,   MENU_SELECT));
75   keymap.insert(std::make_pair(SDLK_KP_ENTER, MENU_SELECT));
76   keymap.insert(std::make_pair(SDLK_CARET,    CONSOLE));
77   keymap.insert(std::make_pair(SDLK_DELETE,   PEEK_LEFT));
78   keymap.insert(std::make_pair(SDLK_END,      PEEK_RIGHT));
79
80   int joystick_count = SDL_NumJoysticks();
81   min_joybuttons = -1;
82   max_joybuttons = -1;
83   max_joyaxis    = -1;
84   for(int i = 0; i < joystick_count; ++i) {
85     SDL_Joystick* joystick = SDL_JoystickOpen(i);
86     bool good = true;
87     if(SDL_JoystickNumButtons(joystick) < 2) {
88       log_info << "Joystick " << i << " has less than 2 buttons" << std::endl;
89       good = false;
90     }
91     if(SDL_JoystickNumAxes(joystick) < 2
92        && SDL_JoystickNumHats(joystick) == 0) {
93       log_info << "Joystick " << i << " has less than 2 axes and no hat" << std::endl;
94       good = false;
95     }
96     if(!good) {
97       SDL_JoystickClose(joystick);
98       continue;
99     }
100
101     if(min_joybuttons < 0 || SDL_JoystickNumButtons(joystick) < min_joybuttons)
102       min_joybuttons = SDL_JoystickNumButtons(joystick);
103
104     if(SDL_JoystickNumButtons(joystick) > max_joybuttons)
105       max_joybuttons = SDL_JoystickNumButtons(joystick);
106
107     if(SDL_JoystickNumAxes(joystick) > max_joyaxis)
108       max_joyaxis = SDL_JoystickNumAxes(joystick);
109
110     joysticks.push_back(joystick);
111   }
112
113   use_hat = true;
114   dead_zone = 1000;
115
116   // Default joystick button configuration
117   joy_button_map.insert(std::make_pair(0, JUMP));
118   joy_button_map.insert(std::make_pair(1, ACTION));
119   // 6 or more Buttons
120   if( min_joybuttons > 5 ){
121     joy_button_map.insert(std::make_pair( 4, PEEK_LEFT));
122     joy_button_map.insert(std::make_pair( 5, PEEK_RIGHT));
123     // 8 or more
124     if(min_joybuttons > 7)
125       joy_button_map.insert(std::make_pair(min_joybuttons-1, PAUSE_MENU));
126     // map all remaining joystick buttons to MENU_SELECT
127     for(int i = 2; i < max_joybuttons; ++i) {
128       if( i != min_joybuttons-1 && i !=4  && i!= 5 )
129         joy_button_map.insert(std::make_pair(i, MENU_SELECT));
130     }
131
132   } else {
133     // map the last 2 buttons to menu and pause
134     if(min_joybuttons > 2)
135       joy_button_map.insert(std::make_pair(min_joybuttons-1, PAUSE_MENU));
136     // map all remaining joystick buttons to MENU_SELECT
137     for(int i = 2; i < max_joybuttons; ++i) {
138       if(i != min_joybuttons-1)
139         joy_button_map.insert(std::make_pair(i, MENU_SELECT));
140     }
141   }
142
143   // Default joystick axis configuration
144   joy_axis_map.insert(std::make_pair(-1, LEFT));
145   joy_axis_map.insert(std::make_pair( 1, RIGHT));
146   joy_axis_map.insert(std::make_pair(-2, UP));
147   joy_axis_map.insert(std::make_pair( 2, DOWN));
148
149   // some joysticks or SDL seem to produce some bogus events after being opened
150   Uint32 ticks = SDL_GetTicks();
151   while(SDL_GetTicks() - ticks < 200) {
152     SDL_Event event;
153     SDL_PollEvent(&event);
154   }
155 }
156
157 JoystickKeyboardController::~JoystickKeyboardController()
158 {
159   for(std::vector<SDL_Joystick*>::iterator i = joysticks.begin();
160       i != joysticks.end(); ++i) {
161     if(*i != 0)
162       SDL_JoystickClose(*i);
163   }
164
165   delete key_options_menu;
166   delete joystick_options_menu;
167 }
168
169 void
170 JoystickKeyboardController::read(const lisp::Lisp& lisp)
171 {
172   const lisp::Lisp* keymap_lisp = lisp.get_lisp("keymap");
173   if(keymap_lisp) {
174     keymap.clear();
175     lisp::ListIterator iter(keymap_lisp);
176     while(iter.next()) {
177       if(iter.item() == "map") {
178         int key = -1;
179         std::string control;
180         const lisp::Lisp* map = iter.lisp();
181         map->get("key", key);
182         map->get("control", control);
183         if(key < SDLK_FIRST || key >= SDLK_LAST) {
184           log_info << "Invalid key '" << key << "' in keymap" << std::endl;
185           continue;
186         }
187
188         int i = 0;
189         for(i = 0; controlNames[i] != 0; ++i) {
190           if(control == controlNames[i])
191             break;
192         }
193         if(controlNames[i] == 0) {
194           log_info << "Invalid control '" << control << "' in keymap" << std::endl;
195           continue;
196         }
197         keymap.insert(std::make_pair((SDLKey) key, (Control) i));
198       } else {
199         log_info << "Invalid lisp element '" << iter.item() << "' in keymap" << std::endl;
200       }
201     }
202   }
203
204   const lisp::Lisp* joystick_lisp = lisp.get_lisp("joystick");
205   if(joystick_lisp) {
206     joystick_lisp->get("use_hat", use_hat);
207     joystick_lisp->get("dead_zone", dead_zone);
208     lisp::ListIterator iter(joystick_lisp);
209     while(iter.next()) {
210       if(iter.item() == "map") {
211         int button = -1;
212         int axis   = 0;
213         std::string control;
214         const lisp::Lisp* map = iter.lisp();
215
216         map->get("control", control);
217         int i = 0;
218         for(i = 0; controlNames[i] != 0; ++i) {
219           if(control == controlNames[i])
220             break;
221         }
222         if(controlNames[i] == 0) {
223           log_info << "Invalid control '" << control << "' in buttonmap" << std::endl;
224           continue;
225         }
226
227         if (map->get("button", button)) {
228           if(button < 0 || button >= max_joybuttons) {
229             log_info << "Invalid button '" << button << "' in buttonmap" << std::endl;
230             continue;
231           }
232           reset_joybutton(button, (Control) i);
233         }
234
235         if (map->get("axis",   axis)) {
236           if (axis == 0 || abs(axis) > max_joyaxis) {
237             log_info << "Invalid axis '" << axis << "' in axismap" << std::endl;
238             continue;
239           }
240           reset_joyaxis(axis, (Control) i);
241         }
242       }
243     }
244   }
245 }
246
247 void
248 JoystickKeyboardController::write(lisp::Writer& writer)
249 {
250   writer.start_list("keymap");
251   for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
252     writer.start_list("map");
253     writer.write_int("key", (int) i->first);
254     writer.write_string("control", controlNames[i->second]);
255     writer.end_list("map");
256   }
257   writer.end_list("keymap");
258
259   writer.start_list("joystick");
260   writer.write_bool("use_hat", use_hat);
261   writer.write_int("dead_zone", dead_zone);
262
263   for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end();
264       ++i) {
265     writer.start_list("map");
266     writer.write_int("button", i->first);
267     writer.write_string("control", controlNames[i->second]);
268     writer.end_list("map");
269   }
270
271   for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); ++i) {
272     writer.start_list("map");
273     writer.write_int("axis", i->first);
274     writer.write_string("control", controlNames[i->second]);
275     writer.end_list("map");
276   }
277
278   writer.end_list("joystick");
279 }
280
281 void
282 JoystickKeyboardController::reset()
283 {
284   Controller::reset();
285 }
286
287 void
288 JoystickKeyboardController::process_event(const SDL_Event& event)
289 {
290   switch(event.type) {
291     case SDL_KEYUP:
292     case SDL_KEYDOWN:
293       process_key_event(event);
294       break;
295
296     case SDL_JOYAXISMOTION:
297       if (wait_for_joystick >= 0)
298         {
299           if (abs(event.jaxis.value) > dead_zone)
300             {
301               if (event.jaxis.value < 0)
302                 reset_joyaxis(-(event.jaxis.axis + 1), Control(wait_for_joystick));
303               else
304                 reset_joyaxis(event.jaxis.axis + 1, Control(wait_for_joystick));
305
306               joystick_options_menu->update();
307               wait_for_joystick = -1;
308             }
309         }
310       else
311         {
312           // Split the axis into left and right, so that both can be
313           // mapped seperatly (needed for jump/down vs up/down)
314           int axis = event.jaxis.axis + 1;
315           
316           AxisMap::iterator left  = joy_axis_map.find(-axis);
317           AxisMap::iterator right = joy_axis_map.find(axis);
318
319           if(left == joy_axis_map.end()) {
320             std::cout << "Unmapped joyaxis " << (int)event.jaxis.axis << " moved" << std::endl;
321           } else {         
322             if (event.jaxis.value < -dead_zone)
323               controls[left->second]  = true;
324             else if (event.jaxis.value > dead_zone)
325               controls[left->second]  = false;
326             else
327               controls[left->second]  = false;
328           }
329
330           if(right == joy_axis_map.end()) {
331             std::cout << "Unmapped joyaxis " << (int)event.jaxis.axis << " moved" << std::endl;
332           } else {
333             if (event.jaxis.value < -dead_zone)
334               controls[right->second] = false;            
335             else if (event.jaxis.value > dead_zone)
336               controls[right->second] = true;              
337             else
338               controls[right->second] = false;
339           }
340         }
341       break;
342
343     case SDL_JOYHATMOTION:
344       if(!use_hat)
345         break;
346
347       if(event.jhat.value & SDL_HAT_UP) {
348         controls[UP]   = true;
349         controls[DOWN] = false;
350       }
351       if(event.jhat.value & SDL_HAT_DOWN) {
352         controls[UP]   = false;
353         controls[DOWN] = true;
354       }
355       if(event.jhat.value & SDL_HAT_LEFT) {
356         controls[LEFT]  = true;
357         controls[RIGHT] = false;
358       }
359       if(event.jhat.value & SDL_HAT_RIGHT) {
360         controls[LEFT]  = false;
361         controls[RIGHT] = true;
362       }
363       if(event.jhat.value == SDL_HAT_CENTERED) {
364         controls[UP]    = false;
365         controls[DOWN]  = false;
366         controls[LEFT]  = false;
367         controls[RIGHT] = false;
368       }
369       break;
370
371     case SDL_JOYBUTTONDOWN:
372     case SDL_JOYBUTTONUP:
373       {
374         if(wait_for_joystick >= 0) {
375           if(event.type == SDL_JOYBUTTONUP)
376             return;
377
378           Control c = (Control) wait_for_joystick;
379           reset_joybutton(event.jbutton.button, c);
380           reset();
381           joystick_options_menu->update();
382           wait_for_joystick = -1;
383           return;
384         }
385
386         ButtonMap::iterator i = joy_button_map.find(event.jbutton.button);
387         if(i == joy_button_map.end()) {
388           log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl;
389           return;
390         }
391
392         controls[i->second] = (event.type == SDL_JOYBUTTONDOWN);
393         break;
394       }
395
396     default:
397       break;
398   }
399 }
400
401 void
402 JoystickKeyboardController::process_key_event(const SDL_Event& event)
403 {
404   KeyMap::iterator key_mapping = keymap.find(event.key.keysym.sym);
405
406   // if console key was pressed: toggle console
407   if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) {
408     if (event.type != SDL_KEYDOWN) return;
409     Console::instance->toggle();
410     return;
411   }
412
413   // if console is open: send key there
414   if (Console::instance->hasFocus()) {
415     process_console_key_event(event);
416     return;
417   }
418
419   // if menu mode: send key there
420   if (Menu::current()) {
421     process_menu_key_event(event);
422     return;
423   }
424
425   // default action: update controls
426   if(key_mapping == keymap.end()) {
427     log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl;
428     return;
429   }
430   Control control = key_mapping->second;
431   controls[control] = (event.type == SDL_KEYDOWN);
432 }
433
434 void
435 JoystickKeyboardController::process_console_key_event(const SDL_Event& event)
436 {
437   if (event.type != SDL_KEYDOWN) return;
438
439   switch (event.key.keysym.sym) {
440     case SDLK_RETURN:
441       Console::instance->enter();
442       break;
443     case SDLK_BACKSPACE:
444       Console::instance->backspace();
445       break;
446     case SDLK_TAB:
447       Console::instance->autocomplete();
448       break;
449     case SDLK_PAGEUP:
450       Console::instance->scroll(-1);
451       break;
452     case SDLK_PAGEDOWN:
453       Console::instance->scroll(+1);
454       break;
455     case SDLK_HOME:
456       Console::instance->move_cursor(-65535);
457       break;
458     case SDLK_END:
459       Console::instance->move_cursor(+65535);
460       break;
461     case SDLK_UP:
462       Console::instance->show_history(-1);
463       break;
464     case SDLK_DOWN:
465       Console::instance->show_history(+1);
466       break;
467     case SDLK_LEFT:
468       Console::instance->move_cursor(-1);
469       break;
470     case SDLK_RIGHT:
471       Console::instance->move_cursor(+1);
472       break;
473     default:
474       int c = event.key.keysym.unicode;
475       if ((c >= 32) && (c <= 126)) {
476         Console::instance->input((char)c);
477       }
478       break;
479   }
480 }
481
482 void
483 JoystickKeyboardController::process_menu_key_event(const SDL_Event& event)
484 {
485   // wait for key mode?
486   if(wait_for_key >= 0) {
487     if(event.type == SDL_KEYUP)
488       return;
489
490     if(event.key.keysym.sym != SDLK_ESCAPE
491         && event.key.keysym.sym != SDLK_PAUSE) {
492       reset_key(event.key.keysym.sym, (Control) wait_for_key);
493     }
494     reset();
495     key_options_menu->update();
496     wait_for_key = -1;
497     return;
498   }
499   if(wait_for_joystick >= 0) {
500     if(event.key.keysym.sym == SDLK_ESCAPE) {
501       reset();
502       joystick_options_menu->update();
503       wait_for_joystick = -1;
504     }
505     return;
506   }
507
508   Control control;
509   /* we use default keys when the menu is open (to avoid problems when
510    * redefining keys to invalid settings
511    */
512   switch(event.key.keysym.sym) {
513     case SDLK_UP:
514       control = UP;
515       break;
516     case SDLK_DOWN:
517       control = DOWN;
518       break;
519     case SDLK_LEFT:
520       control = LEFT;
521       break;
522     case SDLK_RIGHT:
523       control = RIGHT;
524       break;
525     case SDLK_SPACE:
526     case SDLK_RETURN:
527     case SDLK_KP_ENTER:
528       control = MENU_SELECT;
529       break;
530     case SDLK_ESCAPE:
531     case SDLK_PAUSE:
532       control = PAUSE_MENU;
533       break;
534     default:
535       return;
536       break;
537   }
538
539   controls[control] = (event.type == SDL_KEYDOWN);
540 }
541
542 void
543 JoystickKeyboardController::reset_joyaxis(int axis, Control control)
544 {
545   // axis isn't the SDL axis number, but axisnumber + 1 with sign
546   // changed depending on if the positive or negative end is to be
547   // used (negative axis 0 becomes -1, positive axis 2 becomes +3,
548   // etc.)
549   
550   // remove all previous mappings for that control
551   for(AxisMap::iterator i = joy_axis_map.begin(); 
552       i != joy_axis_map.end(); /* no ++i */) {
553     if(i->second == control) {
554       AxisMap::iterator e = i;
555       ++i;
556       joy_axis_map.erase(e);
557     } else {
558       ++i;
559     }
560   }
561
562   // remove all previous mappings for that control
563   for(ButtonMap::iterator i = joy_button_map.begin();
564       i != joy_button_map.end(); /* no ++i */) {
565     if(i->second == control) {
566       ButtonMap::iterator e = i;
567       ++i;
568       joy_button_map.erase(e);
569     } else {
570       ++i;
571     }
572   }
573
574   // remove all previous and for that axis
575   AxisMap::iterator i = joy_axis_map.find(axis);
576   if(i != joy_axis_map.end())
577     joy_axis_map.erase(i);
578
579   // add new mapping
580   joy_axis_map.insert(std::make_pair(axis, control));
581 }
582
583 void
584 JoystickKeyboardController::reset_joybutton(int button, Control control)
585 {
586   // remove all previous mappings for that control
587   for(AxisMap::iterator i = joy_axis_map.begin(); 
588       i != joy_axis_map.end(); /* no ++i */) {
589     if(i->second == control) {
590       AxisMap::iterator e = i;
591       ++i;
592       joy_axis_map.erase(e);
593     } else {
594       ++i;
595     }
596   }
597
598   // remove all previous mappings for that control and for that key
599   for(ButtonMap::iterator i = joy_button_map.begin();
600       i != joy_button_map.end(); /* no ++i */) {
601     if(i->second == control) {
602       ButtonMap::iterator e = i;
603       ++i;
604       joy_button_map.erase(e);
605     } else {
606       ++i;
607     }
608   }
609   ButtonMap::iterator i = joy_button_map.find(button);
610   if(i != joy_button_map.end())
611     joy_button_map.erase(i);
612
613   // add new mapping
614   joy_button_map.insert(std::make_pair(button, control));
615
616   // map all unused buttons to MENU_SELECT
617   for(int b = 0; b < max_joybuttons; ++b) {
618     ButtonMap::iterator i = joy_button_map.find(b);
619     if(i != joy_button_map.end())
620       continue;
621
622     joy_button_map.insert(std::make_pair(b, MENU_SELECT));
623   }
624 }
625
626 void
627 JoystickKeyboardController::reset_key(SDLKey key, Control control)
628 {
629   // remove all previous mappings for that control and for that key
630   for(KeyMap::iterator i = keymap.begin();
631       i != keymap.end(); /* no ++i */) {
632     if(i->second == control) {
633       KeyMap::iterator e = i;
634       ++i;
635       keymap.erase(e);
636     } else {
637       ++i;
638     }
639   }
640   KeyMap::iterator i = keymap.find(key);
641   if(i != keymap.end())
642     keymap.erase(i);
643
644   // add new mapping
645   keymap.insert(std::make_pair(key, control));
646 }
647
648 SDLKey
649 JoystickKeyboardController::reversemap_key(Control c)
650 {
651   for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
652     if(i->second == c)
653       return i->first;
654   }
655
656   return SDLK_UNKNOWN;
657 }
658
659 int
660 JoystickKeyboardController::reversemap_joyaxis(Control c)
661 {
662   for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); ++i) {
663     if(i->second == c)
664       return i->first;
665   }
666   
667   return 0;
668 }
669
670 int
671 JoystickKeyboardController::reversemap_joybutton(Control c)
672 {
673   for(ButtonMap::iterator i = joy_button_map.begin();
674       i != joy_button_map.end(); ++i) {
675     if(i->second == c)
676       return i->first;
677   }
678
679   return -1;
680 }
681
682 Menu*
683 JoystickKeyboardController::get_key_options_menu()
684 {
685   if(key_options_menu == 0) {
686     key_options_menu = new KeyboardMenu(this);
687   }
688
689   return key_options_menu;
690 }
691
692 Menu*
693 JoystickKeyboardController::get_joystick_options_menu()
694 {
695   if(joystick_options_menu == 0) {
696     joystick_options_menu = new JoystickMenu(this);
697   }
698
699   return joystick_options_menu;
700 }
701
702 //----------------------------------------------------------------------------
703
704 JoystickKeyboardController::KeyboardMenu::KeyboardMenu(
705     JoystickKeyboardController* _controller)
706   : controller(_controller)
707 {
708     add_label(_("Setup Keyboard"));
709     add_hl();
710     add_controlfield(Controller::UP,         _("Up"));
711     add_controlfield(Controller::DOWN,       _("Down"));
712     add_controlfield(Controller::LEFT,       _("Left"));
713     add_controlfield(Controller::RIGHT,      _("Right"));
714     add_controlfield(Controller::JUMP,       _("Jump"));
715     add_controlfield(Controller::ACTION,     _("Action"));
716     add_controlfield(Controller::PEEK_LEFT,  _("Peek Left"));
717     add_controlfield(Controller::PEEK_RIGHT, _("Peek Right"));
718     if (config->console_enabled) {
719       add_controlfield(Controller::CONSOLE, _("Console"));
720     }
721     add_hl();
722     add_back(_("Back"));
723     update();
724 }
725
726 JoystickKeyboardController::KeyboardMenu::~KeyboardMenu()
727 {}
728
729 std::string
730 JoystickKeyboardController::KeyboardMenu::get_key_name(SDLKey key)
731 {
732   switch(key) {
733     case SDLK_UNKNOWN:
734       return _("None");
735     case SDLK_UP:
736       return _("Up cursor");
737     case SDLK_DOWN:
738       return _("Down cursor");
739     case SDLK_LEFT:
740       return _("Left cursor");
741     case SDLK_RIGHT:
742       return _("Right cursor");
743     case SDLK_RETURN:
744       return _("Return");
745     case SDLK_SPACE:
746       return _("Space");
747     case SDLK_RSHIFT:
748       return _("Right Shift");
749     case SDLK_LSHIFT:
750       return _("Left Shift");
751     case SDLK_RCTRL:
752       return _("Right Control");
753     case SDLK_LCTRL:
754       return _("Left Control");
755     case SDLK_RALT:
756       return _("Right Alt");
757     case SDLK_LALT:
758       return _("Left Alt");
759     default:
760       return SDL_GetKeyName((SDLKey) key);
761   }
762 }
763
764 void
765 JoystickKeyboardController::KeyboardMenu::menu_action(MenuItem* item)
766 {
767   assert(item->id >= 0 && item->id < Controller::CONTROLCOUNT);
768   item->change_input(_("Press Key"));
769   controller->wait_for_key = item->id;
770 }
771
772 void
773 JoystickKeyboardController::KeyboardMenu::update()
774 {
775   // update menu
776   get_item_by_id((int) Controller::UP).change_input(get_key_name(
777     controller->reversemap_key(Controller::UP)));
778   get_item_by_id((int) Controller::DOWN).change_input(get_key_name(
779     controller->reversemap_key(Controller::DOWN)));
780   get_item_by_id((int) Controller::LEFT).change_input(get_key_name(
781     controller->reversemap_key(Controller::LEFT)));
782   get_item_by_id((int) Controller::RIGHT).change_input(get_key_name(
783     controller->reversemap_key(Controller::RIGHT)));
784   get_item_by_id((int) Controller::JUMP).change_input(get_key_name(
785     controller->reversemap_key(Controller::JUMP)));
786   get_item_by_id((int) Controller::ACTION).change_input(get_key_name(
787     controller->reversemap_key(Controller::ACTION)));
788   get_item_by_id((int) Controller::PEEK_LEFT).change_input(get_key_name(
789     controller->reversemap_key(Controller::PEEK_LEFT)));
790   get_item_by_id((int) Controller::PEEK_RIGHT).change_input(get_key_name(
791     controller->reversemap_key(Controller::PEEK_RIGHT)));
792   if (config->console_enabled) {
793     get_item_by_id((int) Controller::CONSOLE).change_input(get_key_name(
794       controller->reversemap_key(Controller::CONSOLE)));
795   }
796 }
797
798 //---------------------------------------------------------------------------
799
800 JoystickKeyboardController::JoystickMenu::JoystickMenu(
801   JoystickKeyboardController* _controller)
802   : controller(_controller)
803 {
804   add_label(_("Setup Joystick"));
805   add_hl();
806   if(controller->joysticks.size() > 0) {
807     add_controlfield(Controller::UP,          _("Up"));
808     add_controlfield(Controller::DOWN,        _("Down"));
809     add_controlfield(Controller::LEFT,        _("Left"));
810     add_controlfield(Controller::RIGHT,       _("Right"));
811     add_controlfield(Controller::JUMP,        _("Jump"));
812     add_controlfield(Controller::ACTION,      _("Action"));
813     add_controlfield(Controller::PAUSE_MENU,  _("Pause/Menu"));
814     add_controlfield(Controller::PEEK_LEFT,   _("Peek Left"));
815     add_controlfield(Controller::PEEK_RIGHT,  _("Peek Right"));
816   } else {
817     add_deactive(-1, _("No Joysticks found"));
818   }
819   add_hl();
820   add_back(_("Back"));
821   update();
822 }
823
824 JoystickKeyboardController::JoystickMenu::~JoystickMenu()
825 {}
826
827 std::string
828 JoystickKeyboardController::JoystickMenu::get_button_name(int button)
829 {
830   if(button < 0)
831     return _("None");
832
833   std::ostringstream name;
834   name << "Button " << button;
835   return name.str();
836 }
837
838 void
839 JoystickKeyboardController::JoystickMenu::menu_action(MenuItem* item)
840 {
841   assert(item->id >= 0 && item->id < Controller::CONTROLCOUNT);
842   item->change_input(_("Press Button"));
843   controller->wait_for_joystick = item->id;
844 }
845
846 void
847 JoystickKeyboardController::JoystickMenu::update_menu_item(Control id)
848 {
849   int button = controller->reversemap_joybutton(id);
850   int axis   = controller->reversemap_joyaxis(id);
851   
852   if (button != -1) {
853     get_item_by_id((int)id).change_input(get_button_name(button));
854   } else if (axis != 0) {
855     std::ostringstream name;
856
857     name << "Axis ";
858
859     if (axis < 0)
860       name << "-";
861     else
862       name << "+";
863
864     if (abs(axis) == 1)
865       name << "X";
866     else if (abs(axis) == 2)
867       name << "Y";
868     else if (abs(axis) == 2)
869       name << "X2";
870     else if (abs(axis) == 3)
871       name << "Y2";
872     else 
873       name << abs(axis);
874
875     get_item_by_id((int)id).change_input(name.str());
876   } else {
877     get_item_by_id((int)id).change_input("None");
878   }
879 }
880
881 void
882 JoystickKeyboardController::JoystickMenu::update()
883 {
884   if(controller->joysticks.size() == 0)
885     return;
886
887   update_menu_item(Controller::UP);
888   update_menu_item(Controller::DOWN);
889   update_menu_item(Controller::LEFT);
890   update_menu_item(Controller::RIGHT);
891
892   update_menu_item(Controller::JUMP);
893   update_menu_item(Controller::ACTION);
894   update_menu_item(Controller::PAUSE_MENU);
895   update_menu_item(Controller::PEEK_LEFT);
896   update_menu_item(Controller::PEEK_RIGHT);
897 }