rnd-20030126-1-src
[rocksndiamonds.git] / src / events.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * events.c                                                 *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "events.h"
17 #include "init.h"
18 #include "screens.h"
19 #include "tools.h"
20 #include "game.h"
21 #include "editor.h"
22 #include "files.h"
23 #include "tape.h"
24 #include "network.h"
25
26 /* values for key_status */
27 #define KEY_NOT_PRESSED         FALSE
28 #define KEY_RELEASED            FALSE
29 #define KEY_PRESSED             TRUE
30
31
32 /* event filter especially needed for SDL event filtering due to
33    delay problems with lots of mouse motion events when mouse
34    button not pressed */
35
36 int FilterMouseMotionEvents(const Event *event)
37 {
38   if (event->type != EVENT_MOTIONNOTIFY)
39     return 1;
40
41   /* get mouse motion events without pressed button only in level editor */
42   if (button_status == MB_RELEASED && game_status != LEVELED)
43     return 0;
44   else
45     return 1;
46 }
47
48 /* this is only really needed for non-SDL targets to filter unwanted events;
49    when using SDL with properly installed event filter, this function can be
50    replaced with a simple "NextEvent()" call, but it doesn't hurt either */
51
52 static boolean NextValidEvent(Event *event)
53 {
54   while (PendingEvent())
55   {
56     NextEvent(event);
57
58     if (FilterMouseMotionEvents(event))
59       return TRUE;
60   }
61
62   return FALSE;
63 }
64
65 void EventLoop(void)
66 {
67   while(1)
68   {
69     if (PendingEvent())         /* got event */
70     {
71       Event event;
72
73       if (NextValidEvent(&event))
74       {
75         switch(event.type)
76         {
77           case EVENT_BUTTONPRESS:
78           case EVENT_BUTTONRELEASE:
79             HandleButtonEvent((ButtonEvent *) &event);
80             break;
81   
82           case EVENT_MOTIONNOTIFY:
83             HandleMotionEvent((MotionEvent *) &event);
84             break;
85   
86           case EVENT_KEYPRESS:
87           case EVENT_KEYRELEASE:
88             HandleKeyEvent((KeyEvent *) &event);
89             break;
90   
91           default:
92             HandleOtherEvents(&event);
93             break;
94         }
95       }
96     }
97     else
98       HandleNoEvent();
99
100     /* don't use all CPU time when idle; the main loop while playing
101        has its own synchronization and is CPU friendly, too */
102
103     if (game_status == PLAYING)
104       HandleGameActions();
105     else
106     {
107       SyncDisplay();
108       if (!PendingEvent())      /* delay only if no pending events */
109         Delay(10);
110     }
111
112     /* refresh window contents from drawing buffer, if needed */
113     BackToFront();
114
115     if (game_status == EXITGAME)
116       return;
117   }
118 }
119
120 void HandleOtherEvents(Event *event)
121 {
122   switch(event->type)
123   {
124     case EVENT_EXPOSE:
125       HandleExposeEvent((ExposeEvent *) event);
126       break;
127
128     case EVENT_UNMAPNOTIFY:
129 #if 0
130       /* This causes the game to stop not only when iconified, but also
131          when on another virtual desktop, which might be not desired. */
132       SleepWhileUnmapped();
133 #endif
134       break;
135
136     case EVENT_FOCUSIN:
137     case EVENT_FOCUSOUT:
138       HandleFocusEvent((FocusChangeEvent *) event);
139       break;
140
141     case EVENT_CLIENTMESSAGE:
142       HandleClientMessageEvent((ClientMessageEvent *) event);
143       break;
144
145 #if defined(TARGET_SDL)
146     case SDL_JOYAXISMOTION:
147     case SDL_JOYBUTTONDOWN:
148     case SDL_JOYBUTTONUP:
149       HandleJoystickEvent(event);
150       break;
151 #endif
152
153     default:
154       break;
155   }
156 }
157
158 void ClearEventQueue()
159 {
160   while (PendingEvent())
161   {
162     Event event;
163
164     NextEvent(&event);
165
166     switch(event.type)
167     {
168       case EVENT_BUTTONRELEASE:
169         button_status = MB_RELEASED;
170         break;
171
172       case EVENT_KEYRELEASE:
173         key_joystick_mapping = 0;
174         break;
175
176       default:
177         HandleOtherEvents(&event);
178         break;
179     }
180   }
181 }
182
183 void ClearPlayerAction()
184 {
185   int i;
186
187   /* simulate key release events for still pressed keys */
188   key_joystick_mapping = 0;
189   for (i=0; i<MAX_PLAYERS; i++)
190     stored_player[i].action = 0;
191 }
192
193 void SleepWhileUnmapped()
194 {
195   boolean window_unmapped = TRUE;
196
197   KeyboardAutoRepeatOn();
198
199   while(window_unmapped)
200   {
201     Event event;
202
203     NextEvent(&event);
204
205     switch(event.type)
206     {
207       case EVENT_BUTTONRELEASE:
208         button_status = MB_RELEASED;
209         break;
210
211       case EVENT_KEYRELEASE:
212         key_joystick_mapping = 0;
213         break;
214
215       case EVENT_MAPNOTIFY:
216         window_unmapped = FALSE;
217         break;
218
219       case EVENT_UNMAPNOTIFY:
220         /* this is only to surely prevent the 'should not happen' case
221          * of recursively looping between 'SleepWhileUnmapped()' and
222          * 'HandleOtherEvents()' which usually calls this funtion.
223          */
224         break;
225
226       default:
227         HandleOtherEvents(&event);
228         break;
229     }
230   }
231
232   if (game_status == PLAYING)
233     KeyboardAutoRepeatOff();
234 }
235
236 void HandleExposeEvent(ExposeEvent *event)
237 {
238 #ifndef TARGET_SDL
239   RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
240   FlushDisplay();
241 #endif
242 }
243
244 void HandleButtonEvent(ButtonEvent *event)
245 {
246   motion_status = FALSE;
247
248   if (event->type == EVENT_BUTTONPRESS)
249     button_status = event->button;
250   else
251     button_status = MB_RELEASED;
252
253   HandleButton(event->x, event->y, button_status);
254 }
255
256 void HandleMotionEvent(MotionEvent *event)
257 {
258   if (!PointerInWindow(window))
259     return;     /* window and pointer are on different screens */
260
261 #if 1
262   if (button_status == MB_RELEASED && game_status != LEVELED)
263     return;
264 #endif
265
266   motion_status = TRUE;
267
268   HandleButton(event->x, event->y, button_status);
269 }
270
271 void HandleKeyEvent(KeyEvent *event)
272 {
273   int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
274   boolean with_modifiers = (game_status == PLAYING ? FALSE : TRUE);
275   Key key = GetEventKey(event, with_modifiers);
276
277   HandleKey(key, key_status);
278 }
279
280 void HandleFocusEvent(FocusChangeEvent *event)
281 {
282   static int old_joystick_status = -1;
283
284   if (event->type == EVENT_FOCUSOUT)
285   {
286     KeyboardAutoRepeatOn();
287     old_joystick_status = joystick.status;
288     joystick.status = JOYSTICK_NOT_AVAILABLE;
289
290     ClearPlayerAction();
291   }
292   else if (event->type == EVENT_FOCUSIN)
293   {
294     /* When there are two Rocks'n'Diamonds windows which overlap and
295        the player moves the pointer from one game window to the other,
296        a 'FocusOut' event is generated for the window the pointer is
297        leaving and a 'FocusIn' event is generated for the window the
298        pointer is entering. In some cases, it can happen that the
299        'FocusIn' event is handled by the one game process before the
300        'FocusOut' event by the other game process. In this case the
301        X11 environment would end up with activated keyboard auto repeat,
302        because unfortunately this is a global setting and not (which
303        would be far better) set for each X11 window individually.
304        The effect would be keyboard auto repeat while playing the game
305        (game_status == PLAYING), which is not desired.
306        To avoid this special case, we just wait 1/10 second before
307        processing the 'FocusIn' event.
308     */
309
310     if (game_status == PLAYING)
311     {
312       Delay(100);
313       KeyboardAutoRepeatOff();
314     }
315     if (old_joystick_status != -1)
316       joystick.status = old_joystick_status;
317   }
318 }
319
320 void HandleClientMessageEvent(ClientMessageEvent *event)
321 {
322   if (CheckCloseWindowEvent(event))
323     CloseAllAndExit(0);
324 }
325
326 void HandleButton(int mx, int my, int button)
327 {
328   static int old_mx = 0, old_my = 0;
329
330   if (button < 0)
331   {
332     mx = old_mx;
333     my = old_my;
334     button = -button;
335   }
336   else
337   {
338     old_mx = mx;
339     old_my = my;
340   }
341
342   HandleGadgets(mx, my, button);
343
344   switch(game_status)
345   {
346     case MAINMENU:
347       HandleMainMenu(mx,my, 0,0, button);
348       break;
349
350     case TYPENAME:
351       HandleTypeName(0, KSYM_Return);
352       break;
353
354     case CHOOSELEVEL:
355       HandleChooseLevel(mx,my, 0,0, button);
356       break;
357
358     case HALLOFFAME:
359       HandleHallOfFame(0,0, 0,0, button);
360       break;
361
362     case LEVELED:
363       break;
364
365     case HELPSCREEN:
366       HandleHelpScreen(button);
367       break;
368
369     case SETUP:
370       HandleSetupScreen(mx,my, 0,0, button);
371       break;
372
373     case PLAYING:
374 #ifdef DEBUG
375       if (button == MB_RELEASED)
376       {
377         int sx = (mx - SX) / TILEX;
378         int sy = (my - SY) / TILEY;
379
380         if (IN_VIS_FIELD(sx,sy))
381         {
382           int x = LEVELX(sx);
383           int y = LEVELY(sy);
384
385           printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
386
387           if (!IN_LEV_FIELD(x, y))
388             break;
389
390           printf("      Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
391           printf("      Store[%d][%d] == %d\n", x,y, Store[x][y]);
392           printf("      Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
393           printf("      StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
394           printf("      MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
395           printf("      MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
396           printf("      MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
397           printf("\n");
398         }
399       }
400 #endif
401       break;
402
403     default:
404       break;
405   }
406 }
407
408 void HandleKey(Key key, int key_status)
409 {
410   int joy = 0;
411   boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
412   static struct SetupKeyboardInfo custom_key;
413   static struct
414   {
415     Key *key_custom;
416     Key key_default;
417     byte action;
418   } key_info[] =
419   {
420     { &custom_key.left,  DEFAULT_KEY_LEFT,  JOY_LEFT     },
421     { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT    },
422     { &custom_key.up,    DEFAULT_KEY_UP,    JOY_UP       },
423     { &custom_key.down,  DEFAULT_KEY_DOWN,  JOY_DOWN     },
424     { &custom_key.snap,  DEFAULT_KEY_SNAP,  JOY_BUTTON_1 },
425     { &custom_key.bomb,  DEFAULT_KEY_BOMB,  JOY_BUTTON_2 }
426   };
427
428   if (game_status == PLAYING)
429   {
430     /* only needed for single-step tape recording mode */
431     static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
432     static boolean bomb_placed[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
433     int pnr;
434
435     for (pnr=0; pnr<MAX_PLAYERS; pnr++)
436     {
437       int i;
438       byte key_action = 0;
439
440       if (setup.input[pnr].use_joystick)
441         continue;
442
443       custom_key = setup.input[pnr].key;
444
445       for (i=0; i<6; i++)
446         if (key == *key_info[i].key_custom)
447           key_action |= key_info[i].action;
448
449       if (tape.single_step && clear_button_2[pnr])
450       {
451         stored_player[pnr].action &= ~KEY_BUTTON_2;
452         clear_button_2[pnr] = FALSE;
453       }
454
455       if (key_status == KEY_PRESSED)
456         stored_player[pnr].action |= key_action;
457       else
458         stored_player[pnr].action &= ~key_action;
459
460       if (tape.single_step && tape.recording && tape.pausing)
461       {
462         if (key_status == KEY_PRESSED &&
463             (key_action & (KEY_MOTION | KEY_BUTTON_1)))
464         {
465           TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
466
467           if (key_action & KEY_MOTION)
468           {
469             if (stored_player[pnr].action & KEY_BUTTON_2)
470               bomb_placed[pnr] = TRUE;
471           }
472         }
473         else if (key_status == KEY_RELEASED &&
474                  (key_action & KEY_BUTTON_2))
475         {
476           if (!bomb_placed[pnr])
477           {
478             TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
479
480             stored_player[pnr].action |= KEY_BUTTON_2;
481             clear_button_2[pnr] = TRUE;
482           }
483
484           bomb_placed[pnr] = FALSE;
485         }
486       }
487       else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
488         TapeTogglePause(TAPE_TOGGLE_MANUAL);
489     }
490   }
491   else
492   {
493     int i;
494
495     for (i=0; i<6; i++)
496       if (key == key_info[i].key_default)
497         joy |= key_info[i].action;
498   }
499
500   if (joy)
501   {
502     if (key_status == KEY_PRESSED)
503       key_joystick_mapping |= joy;
504     else
505       key_joystick_mapping &= ~joy;
506
507     HandleJoystick();
508   }
509
510   if (game_status != PLAYING)
511     key_joystick_mapping = 0;
512
513   if (key_status == KEY_RELEASED)
514     return;
515
516   if ((key == KSYM_Return || key == setup.shortcut.toggle_pause) &&
517       game_status == PLAYING && AllPlayersGone)
518   {
519     CloseDoor(DOOR_CLOSE_1);
520     game_status = MAINMENU;
521     DrawMainMenu();
522     return;
523   }
524
525   /* allow quick escape to the main menu with the Escape key */
526   if (key == KSYM_Escape &&
527       game_status != MAINMENU &&
528       game_status != PLAYING &&
529       game_status != LEVELED &&
530       game_status != CHOOSELEVEL &&
531       game_status != SETUP)
532   {
533     game_status = MAINMENU;
534     DrawMainMenu();
535     return;
536   }
537
538   /* special key shortcuts */
539   if (game_status == MAINMENU || game_status == PLAYING)
540   {
541     if (key == setup.shortcut.save_game)
542       TapeQuickSave();
543     else if (key == setup.shortcut.load_game)
544       TapeQuickLoad();
545     else if (key == setup.shortcut.toggle_pause)
546       TapeTogglePause(TAPE_TOGGLE_MANUAL);
547   }
548
549 #if 0
550 #ifndef DEBUG
551
552   if (game_status == PLAYING && (tape.playing || tape.pausing))
553     return;
554
555 #endif
556 #endif
557
558
559   HandleGadgetsKeyInput(key);
560
561   switch(game_status)
562   {
563     case TYPENAME:
564       HandleTypeName(0, key);
565       break;
566
567     case MAINMENU:
568     case CHOOSELEVEL:
569     case SETUP:
570       switch(key)
571       {
572         case KSYM_Return:
573           if (game_status == MAINMENU)
574             HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
575           else if (game_status == CHOOSELEVEL)
576             HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
577           else if (game_status == SETUP)
578             HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
579           break;
580
581         case KSYM_Escape:
582           if (game_status == CHOOSELEVEL)
583             HandleChooseLevel(0,0, 0,0, MB_MENU_LEAVE);
584           else if (game_status == SETUP)
585             HandleSetupScreen(0,0, 0,0, MB_MENU_LEAVE);
586           break;
587
588         case KSYM_Page_Up:
589           if (game_status == CHOOSELEVEL)
590             HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
591           else if (game_status == SETUP)
592             HandleSetupScreen(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
593           break;
594
595         case KSYM_Page_Down:
596           if (game_status == CHOOSELEVEL)
597             HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
598           else if (game_status == SETUP)
599             HandleSetupScreen(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
600           break;
601
602 #ifdef DEBUG
603         case KSYM_t:
604           DumpTape(&tape);
605           break;
606 #endif
607
608         default:
609           break;
610       }
611       break;
612
613     case HELPSCREEN:
614       HandleHelpScreen(MB_RELEASED);
615       break;
616
617     case HALLOFFAME:
618       switch(key)
619       {
620         case KSYM_Return:
621           game_status = MAINMENU;
622           DrawMainMenu();
623           BackToFront();
624           break;
625
626         case KSYM_Page_Up:
627           HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
628           break;
629
630         case KSYM_Page_Down:
631           HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
632           break;
633
634         default:
635           break;
636       }
637       break;
638
639     case LEVELED:
640       if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
641         HandleLevelEditorKeyInput(key);
642       break;
643
644     case PLAYING:
645     {
646       switch(key)
647       {
648         case KSYM_Escape:
649           RequestQuitGame(setup.ask_on_escape);
650           break;
651
652 #ifdef DEBUG
653         case KSYM_0:
654         case KSYM_1:
655         case KSYM_2:
656         case KSYM_3:
657         case KSYM_4:
658         case KSYM_5:
659         case KSYM_6:
660         case KSYM_7:
661         case KSYM_8:
662         case KSYM_9:
663           if (key == KSYM_0)
664           {
665             if (GameFrameDelay == 500)
666               GameFrameDelay = GAME_FRAME_DELAY;
667             else
668               GameFrameDelay = 500;
669           }
670           else
671             GameFrameDelay = (key - KSYM_0) * 10;
672           printf("Game speed == %d%% (%d ms delay between two frames)\n",
673                  GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
674           break;
675
676         case KSYM_d:
677           if (options.debug)
678           {
679             options.debug = FALSE;
680             printf("debug mode disabled\n");
681           }
682           else
683           {
684             options.debug = TRUE;
685             printf("debug mode enabled\n");
686           }
687           break;
688
689         case KSYM_s:
690           if (!global.fps_slowdown)
691           {
692             global.fps_slowdown = TRUE;
693             global.fps_slowdown_factor = 2;
694             printf("fps slowdown enabled -- display only every 2nd frame\n");
695           }
696           else if (global.fps_slowdown_factor == 2)
697           {
698             global.fps_slowdown_factor = 4;
699             printf("fps slowdown enabled -- display only every 4th frame\n");
700           }
701           else
702           {
703             global.fps_slowdown = FALSE;
704             global.fps_slowdown_factor = 1;
705             printf("fps slowdown disabled\n");
706           }
707           break;
708
709 #if 0
710         case KSYM_a:
711           if (ScrollStepSize == TILEX/8)
712             ScrollStepSize = TILEX/4;
713           else
714             ScrollStepSize = TILEX/8;
715           printf("ScrollStepSize == %d\n", ScrollStepSize);
716           break;
717 #endif
718
719 #if 0
720         case KSYM_m:
721           if (MoveSpeed == 8)
722           {
723             MoveSpeed = 4;
724             ScrollStepSize = TILEX/4;
725           }
726           else
727           {
728             MoveSpeed = 8;
729             ScrollStepSize = TILEX/8;
730           }
731           printf("MoveSpeed == %d\n", MoveSpeed);
732           break;
733 #endif
734
735         case KSYM_f:
736           ScrollStepSize = TILEX/8;
737           printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
738           break;
739
740         case KSYM_g:
741           ScrollStepSize = TILEX/4;
742           printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
743           break;
744
745         case KSYM_h:
746           ScrollStepSize = TILEX/2;
747           printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
748           break;
749
750         case KSYM_l:
751           ScrollStepSize = TILEX;
752           printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
753           break;
754
755         case KSYM_Q:
756         case KSYM_q:
757           local_player->dynamite = 1000;
758           break;
759
760
761
762 #if 0
763
764         case KSYM_z:
765           {
766             int i;
767
768             for(i=0; i<MAX_PLAYERS; i++)
769             {
770               printf("Player %d:\n", i);
771               printf("  jx == %d, jy == %d\n",
772                      stored_player[i].jx, stored_player[i].jy);
773               printf("  last_jx == %d, last_jy == %d\n",
774                      stored_player[i].last_jx, stored_player[i].last_jy);
775             }
776             printf("\n");
777           }
778
779           break;
780 #endif
781 #endif
782
783         default:
784           break;
785       }
786       break;
787     }
788     default:
789       break;
790   }
791 }
792
793 void HandleNoEvent()
794 {
795   if (button_status && game_status != PLAYING)
796   {
797     HandleButton(0, 0, -button_status);
798     return;
799   }
800
801 #if defined(PLATFORM_UNIX)
802   if (options.network)
803     HandleNetworking();
804 #endif
805
806   HandleJoystick();
807 }
808
809 static int HandleJoystickForAllPlayers()
810 {
811   int i;
812   int result = 0;
813
814   for (i=0; i<MAX_PLAYERS; i++)
815   {
816     byte joy_action = 0;
817
818     /*
819     if (!setup.input[i].use_joystick)
820       continue;
821       */
822
823     joy_action = Joystick(i);
824     result |= joy_action;
825
826     if (!setup.input[i].use_joystick)
827       continue;
828
829     stored_player[i].action = joy_action;
830   }
831
832   return result;
833 }
834
835 void HandleJoystick()
836 {
837   int joystick  = HandleJoystickForAllPlayers();
838   int keyboard  = key_joystick_mapping;
839   int joy       = (joystick | keyboard);
840   int left      = joy & JOY_LEFT;
841   int right     = joy & JOY_RIGHT;
842   int up        = joy & JOY_UP;
843   int down      = joy & JOY_DOWN;
844   int button    = joy & JOY_BUTTON;
845   int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
846   int dx        = (left ? -1    : right ? 1     : 0);
847   int dy        = (up   ? -1    : down  ? 1     : 0);
848
849   switch(game_status)
850   {
851     case MAINMENU:
852     case CHOOSELEVEL:
853     case SETUP:
854     {
855       static unsigned long joystickmove_delay = 0;
856
857       if (joystick && !button &&
858           !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
859         newbutton = dx = dy = 0;
860
861       if (game_status == MAINMENU)
862         HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
863       else if (game_status == CHOOSELEVEL)
864         HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
865       else if (game_status == SETUP)
866         HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
867       break;
868     }
869
870     case HALLOFFAME:
871       HandleHallOfFame(0,0, dx,dy, !newbutton);
872       break;
873
874     case HELPSCREEN:
875       HandleHelpScreen(!newbutton);
876       break;
877
878     case LEVELED:
879       HandleLevelEditorIdle();
880       break;
881
882     case PLAYING:
883       if (tape.playing || keyboard)
884         newbutton = ((joy & JOY_BUTTON) != 0);
885
886       if (AllPlayersGone && newbutton)
887       {
888         CloseDoor(DOOR_CLOSE_1);
889         game_status = MAINMENU;
890         DrawMainMenu();
891         return;
892       }
893
894       break;
895
896     default:
897       break;
898   }
899 }