rnd-20020402-1-src
[rocksndiamonds.git] / src / screens.c
index 0f313c856d73405485b5417b9b9c4ecccc14accb..d1d8e1192a515c2a5448c2ca3109e8c80ca8d121 100644 (file)
 /* screens in the setup menu */
 #define SETUP_MODE_MAIN                        0
 #define SETUP_MODE_INPUT               1
-#define SETUP_MODE_GRAPHICS            2
-#define SETUP_MODE_SOUND               3
+#define SETUP_MODE_SHORTCUT            2
+#define SETUP_MODE_GRAPHICS            3
+#define SETUP_MODE_SOUND               4
 
-#define MAX_SETUP_MODES                        4
+#define MAX_SETUP_MODES                        5
 
-/* for HandleSetupInputScreen() */
+/* for input setup functions */
 #define SETUPINPUT_SCREEN_POS_START    0
 #define SETUPINPUT_SCREEN_POS_END      (SCR_FIELDY - 4)
 #define SETUPINPUT_SCREEN_POS_EMPTY1   (SETUPINPUT_SCREEN_POS_START + 3)
 #define SETUPINPUT_SCREEN_POS_EMPTY2   (SETUPINPUT_SCREEN_POS_END - 1)
 
-/* for HandleChooseLevel() */
+/* for various menu stuff  */
 #define MAX_MENU_ENTRIES_ON_SCREEN     (SCR_FIELDY - 2)
 #define MENU_SCREEN_START_YPOS         2
 #define MENU_SCREEN_VALUE_XPOS         14
 #define NUM_SCREEN_SCROLLBARS          1
 #define NUM_SCREEN_GADGETS             3
 
-/* forward declaration for internal use */
+/* forward declarations of internal functions */
 static void HandleScreenGadgets(struct GadgetInfo *);
+static void HandleSetupScreen_Generic(int, int, int, int, int);
+static void HandleSetupScreen_Input(int, int, int, int, int);
+static void CustomizeKeyboard(int);
+static void CalibrateJoystick(int);
 
 static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
 
@@ -117,7 +122,7 @@ static void ToggleFullscreenIfNeeded()
 
 void DrawMainMenu()
 {
-  static struct LevelDirInfo *leveldir_last_valid = NULL;
+  static LevelDirTree *leveldir_last_valid = NULL;
   int i;
   char *name_text = (!options.network && setup.team_mode ? "Team:" : "Name:");
 
@@ -125,6 +130,7 @@ void DrawMainMenu()
   FadeSounds();
   KeyboardAutoRepeatOn();
   ActivateJoystickIfAvailable();
+  SetDrawDeactivationMask(REDRAW_NONE);
 
   /* needed if last screen was the playing screen, invoked from level editor */
   if (level_editor_test_game)
@@ -230,8 +236,8 @@ static void gotoTopLevelDir()
     /* write a "path" into level tree for easy navigation to last level */
     if (leveldir_current->node_parent->node_group->cl_first == -1)
     {
-      int num_leveldirs = numLevelDirInfoInGroup(leveldir_current);
-      int leveldir_pos = posLevelDirInfo(leveldir_current);
+      int num_leveldirs = numTreeInfoInGroup(leveldir_current);
+      int leveldir_pos = posTreeInfo(leveldir_current);
       int num_page_entries;
       int cl_first, cl_cursor;
 
@@ -929,7 +935,7 @@ static void AdjustChooseLevelScrollbar(int id, int first_entry)
   struct GadgetInfo *gi = screen_gadget[id];
   int items_max, items_visible, item_position;
 
-  items_max = numLevelDirInfoInGroup(leveldir_current);
+  items_max = numTreeInfoInGroup(leveldir_current);
   items_visible = MAX_MENU_ENTRIES_ON_SCREEN - 1;
   item_position = first_entry;
 
@@ -945,7 +951,7 @@ static void drawChooseLevelList(int first_entry, int num_page_entries)
   int i;
   char buffer[SCR_FIELDX * 2];
   int max_buffer_len = (SCR_FIELDX - 2) * 2;
-  int num_leveldirs = numLevelDirInfoInGroup(leveldir_current);
+  int num_leveldirs = numTreeInfoInGroup(leveldir_current);
 
   ClearRectangle(backbuffer, SX, SY, SXSIZE - 32, SYSIZE);
   redraw_mask |= REDRAW_FIELD;
@@ -954,12 +960,12 @@ static void drawChooseLevelList(int first_entry, int num_page_entries)
 
   for(i=0; i<num_page_entries; i++)
   {
-    struct LevelDirInfo *node, *node_first;
+    LevelDirTree *node, *node_first;
     int leveldir_pos = first_entry + i;
     int ypos = MENU_SCREEN_START_YPOS + i;
 
-    node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
-    node = getLevelDirInfoFromPos(node_first, leveldir_pos);
+    node_first = getTreeInfoFirstGroupEntry(leveldir_current);
+    node = getTreeInfoFromPos(node_first, leveldir_pos);
 
     strncpy(buffer, node->name , max_buffer_len);
     buffer[max_buffer_len] = '\0';
@@ -983,11 +989,11 @@ static void drawChooseLevelList(int first_entry, int num_page_entries)
 
 static void drawChooseLevelInfo(int leveldir_pos)
 {
-  struct LevelDirInfo *node, *node_first;
+  LevelDirTree *node, *node_first;
   int x, last_redraw_mask = redraw_mask;
 
-  node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
-  node = getLevelDirInfoFromPos(node_first, leveldir_pos);
+  node_first = getTreeInfoFirstGroupEntry(leveldir_current);
+  node = getTreeInfoFromPos(node_first, leveldir_pos);
 
   ClearRectangle(drawto, SX + 32, SY + 32, SXSIZE - 64, 32);
 
@@ -1011,7 +1017,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
   int x = 0;
   int y = leveldir_current->cl_cursor;
   int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
-  int num_leveldirs = numLevelDirInfoInGroup(leveldir_current);
+  int num_leveldirs = numTreeInfoInGroup(leveldir_current);
   int num_page_entries;
 
   if (num_leveldirs <= MAX_MENU_ENTRIES_ON_SCREEN)
@@ -1021,7 +1027,7 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
 
   if (button == MB_MENU_INITIALIZE)
   {
-    int leveldir_pos = posLevelDirInfo(leveldir_current);
+    int leveldir_pos = posTreeInfo(leveldir_current);
 
     if (leveldir_current->cl_first == -1)
     {
@@ -1114,11 +1120,11 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
 
   if (dx == 1)
   {
-    struct LevelDirInfo *node_first, *node_cursor;
+    LevelDirTree *node_first, *node_cursor;
     int leveldir_pos = leveldir_current->cl_first + y;
 
-    node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
-    node_cursor = getLevelDirInfoFromPos(node_first, leveldir_pos);
+    node_first = getTreeInfoFirstGroupEntry(leveldir_current);
+    node_cursor = getTreeInfoFromPos(node_first, leveldir_pos);
 
     if (node_cursor->node_group)
     {
@@ -1150,11 +1156,11 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
     }
     else
     {
-      struct LevelDirInfo *node_first, *node_cursor;
+      LevelDirTree *node_first, *node_cursor;
       int leveldir_pos = leveldir_current->cl_first + y;
 
-      node_first = getLevelDirInfoFirstGroupEntry(leveldir_current);
-      node_cursor = getLevelDirInfoFromPos(node_first, leveldir_pos);
+      node_first = getTreeInfoFirstGroupEntry(leveldir_current);
+      node_cursor = getTreeInfoFromPos(node_first, leveldir_pos);
 
       if (node_cursor->node_group)
       {
@@ -1322,6 +1328,12 @@ static void execSetupInput()
   DrawSetupScreen();
 }
 
+static void execSetupShortcut()
+{
+  setup_mode = SETUP_MODE_SHORTCUT;
+  DrawSetupScreen();
+}
+
 static void execExitSetup()
 {
   game_status = MAINMENU;
@@ -1338,8 +1350,9 @@ static struct TokenInfo setup_info_main[] =
 {
   { TYPE_ENTER_MENU,   execSetupSound,         "Sound Setup"   },
   { TYPE_ENTER_MENU,   execSetupInput,         "Input Devices" },
-  { TYPE_EMPTY,                NULL,                   ""              },
+  { TYPE_ENTER_MENU,   execSetupShortcut,      "Key Shortcuts" },
 #if 0
+  { TYPE_EMPTY,                NULL,                   ""              },
   { TYPE_SWITCH,       &setup.sound,           "Sound:",       },
   { TYPE_SWITCH,       &setup.sound_loops,     " Sound Loops:" },
   { TYPE_SWITCH,       &setup.sound_music,     " Game Music:"  },
@@ -1377,6 +1390,64 @@ static struct TokenInfo setup_info_sound[] =
   { 0,                 NULL,                   NULL            }
 };
 
+static struct TokenInfo setup_info_shortcut[] =
+{
+  { TYPE_KEYTEXT,      NULL,                   "Quick Save Game:",     },
+  { TYPE_KEY,          &setup.shortcut.save_game,      ""              },
+  { TYPE_KEYTEXT,      NULL,                   "Quick Load Game:",     },
+  { TYPE_KEY,          &setup.shortcut.load_game,      ""              },
+  { TYPE_EMPTY,                NULL,                   ""                      },
+  { TYPE_LEAVE_MENU,   execSetupMain,          "Exit"                  },
+  { 0,                 NULL,                   NULL                    }
+};
+
+static Key getSetupKey()
+{
+  Key key = KSYM_UNDEFINED;
+  boolean got_key_event = FALSE;
+
+  while (!got_key_event)
+  {
+    if (PendingEvent())                /* got event */
+    {
+      Event event;
+
+      NextEvent(&event);
+
+      switch(event.type)
+      {
+        case EVENT_KEYPRESS:
+         {
+           key = GetEventKey((KeyEvent *)&event, TRUE);
+
+           /* press 'Escape' or 'Enter' to keep the existing key binding */
+           if (key == KSYM_Escape || key == KSYM_Return)
+             key = KSYM_UNDEFINED;     /* keep old value */
+
+           got_key_event = TRUE;
+         }
+         break;
+
+        case EVENT_KEYRELEASE:
+         key_joystick_mapping = 0;
+         break;
+
+        default:
+         HandleOtherEvents(&event);
+         break;
+      }
+    }
+
+    BackToFront();
+    DoAnimation();
+
+    /* don't eat all CPU time */
+    Delay(10);
+  }
+
+  return key;
+}
+
 static void drawSetupValue(int pos)
 {
   int xpos = MENU_SCREEN_VALUE_XPOS;
@@ -1385,23 +1456,49 @@ static void drawSetupValue(int pos)
   char *value_string = getSetupValue(setup_info[pos].type & ~TYPE_GHOSTED,
                                     setup_info[pos].value);
 
-  if (setup_info[pos].type & TYPE_SWITCH ||
-      setup_info[pos].type & TYPE_YES_NO)
+  if (setup_info[pos].type & TYPE_KEY)
   {
-    boolean value = *(boolean *)(setup_info[pos].value);
-    int value_length = 3;
-
-    if (!value)
-      value_color = FC_BLUE;
+    xpos = 3;
 
-    if (strlen(value_string) < value_length)
-      strcat(value_string, " ");
+    if (setup_info[pos].type & TYPE_QUERY)
+    {
+      value_string = "<press key>";
+      value_color = FC_RED;
+    }
   }
 
+  if (setup_info[pos].type & TYPE_BOOLEAN_STYLE &&
+      !*(boolean *)(setup_info[pos].value))
+    value_color = FC_BLUE;
+
+  DrawText(SX + xpos * 32, SY + ypos * 32,
+          (xpos == 3 ? "              " : "   "), FS_BIG, FC_YELLOW);
   DrawText(SX + xpos * 32, SY + ypos * 32, value_string, FS_BIG, value_color);
 }
 
-static void DrawGenericSetupScreen()
+static void changeSetupValue(int pos)
+{
+  if (setup_info[pos].type & TYPE_BOOLEAN_STYLE)
+  {
+    *(boolean *)setup_info[pos].value ^= TRUE;
+  }
+  else if (setup_info[pos].type & TYPE_KEY)
+  {
+    Key key;
+
+    setup_info[pos].type |= TYPE_QUERY;
+    drawSetupValue(pos);
+    setup_info[pos].type &= ~TYPE_QUERY;
+
+    key = getSetupKey();
+    if (key != KSYM_UNDEFINED)
+      *(Key *)setup_info[pos].value = key;
+  }
+
+  drawSetupValue(pos);
+}
+
+static void DrawSetupScreen_Generic()
 {
   char *title_string = NULL;
   int i;
@@ -1418,7 +1515,12 @@ static void DrawGenericSetupScreen()
   else if (setup_mode == SETUP_MODE_SOUND)
   {
     setup_info = setup_info_sound;
-    title_string = "Sound Setup";
+    title_string = "Setup Sound";
+  }
+  else if (setup_mode == SETUP_MODE_SHORTCUT)
+  {
+    setup_info = setup_info_shortcut;
+    title_string = "Setup Shortcuts";
   }
 
   DrawText(SX + 16, SY + 16, title_string, FS_BIG, FC_YELLOW);
@@ -1443,10 +1545,10 @@ static void DrawGenericSetupScreen()
       initCursor(i, GFX_ARROW_BLUE_RIGHT);
     else if (setup_info[i].type & TYPE_LEAVE_MENU)
       initCursor(i, GFX_ARROW_BLUE_LEFT);
-    else if (setup_info[i].type != TYPE_EMPTY)
+    else if (setup_info[i].type & ~TYPE_SKIP_ENTRY)
       initCursor(i, GFX_KUGEL_BLAU);
 
-    if (setup_info[i].type & TYPE_BOOLEAN_STYLE)
+    if (setup_info[i].type & TYPE_VALUE)
       drawSetupValue(i);
 
     num_setup_info++;
@@ -1454,10 +1556,10 @@ static void DrawGenericSetupScreen()
 
   FadeToFront();
   InitAnimation();
-  HandleSetupScreen(0,0,0,0,MB_MENU_INITIALIZE);
+  HandleSetupScreen_Generic(0,0,0,0,MB_MENU_INITIALIZE);
 }
 
-void HandleGenericSetupScreen(int mx, int my, int dx, int dy, int button)
+void HandleSetupScreen_Generic(int mx, int my, int dx, int dy, int button)
 {
   static int choice_store[MAX_SETUP_MODES];
   int choice = choice_store[setup_mode];
@@ -1478,7 +1580,7 @@ void HandleGenericSetupScreen(int mx, int my, int dx, int dy, int button)
        void (*menu_callback_function)(void) = setup_info[y].value;
 
        menu_callback_function();
-       break;  /* absolutely needed because 'setup_info' has changed! */
+       break;  /* absolutely needed because function changes 'setup_info'! */
       }
     }
 
@@ -1494,10 +1596,10 @@ void HandleGenericSetupScreen(int mx, int my, int dx, int dy, int button)
   {
     if (dx)
     {
-      int type = (dx < 0 ? TYPE_LEAVE_MENU : TYPE_ENTER_MENU);
+      int menu_navigation_type = (dx < 0 ? TYPE_LEAVE_MENU : TYPE_ENTER_MENU);
 
-      if (!(setup_info[choice].type & TYPE_ENTER_OR_LEAVE_MENU) ||
-         setup_info[choice].type == type)
+      if ((setup_info[choice].type & menu_navigation_type) ||
+         (setup_info[choice].type & TYPE_BOOLEAN_STYLE))
        button = MB_MENU_CHOICE;
     }
     else if (dy)
@@ -1505,12 +1607,12 @@ void HandleGenericSetupScreen(int mx, int my, int dx, int dy, int button)
 
     /* jump to next non-empty menu entry (up or down) */
     while (y > 0 && y < num_setup_info - 1 &&
-          setup_info[y].type == TYPE_EMPTY)
+          (setup_info[y].type & TYPE_SKIP_ENTRY))
       y += dy;
   }
 
   if (x == 0 && y >= 0 && y < num_setup_info &&
-      setup_info[y].type != TYPE_EMPTY)
+      (setup_info[y].type & ~TYPE_SKIP_ENTRY))
   {
     if (button)
     {
@@ -1523,6 +1625,7 @@ void HandleGenericSetupScreen(int mx, int my, int dx, int dy, int button)
     }
     else if (!(setup_info[y].type & TYPE_GHOSTED))
     {
+#if 0
       if (setup_info[y].type & TYPE_BOOLEAN_STYLE)
       {
        boolean new_value = !*(boolean *)(setup_info[y].value);
@@ -1530,12 +1633,34 @@ void HandleGenericSetupScreen(int mx, int my, int dx, int dy, int button)
        *(boolean *)setup_info[y].value = new_value;
        drawSetupValue(y);
       }
+      else if (setup_info[y].type == TYPE_KEYTEXT &&
+              setup_info[y + 1].type == TYPE_KEY)
+      {
+       changeSetupValue(y + 1);
+      }
       else if (setup_info[y].type & TYPE_ENTER_OR_LEAVE_MENU)
       {
        void (*menu_callback_function)(void) = setup_info[choice].value;
 
        menu_callback_function();
       }
+#else
+      if (setup_info[y].type & TYPE_ENTER_OR_LEAVE_MENU)
+      {
+       void (*menu_callback_function)(void) = setup_info[choice].value;
+
+       menu_callback_function();
+      }
+      else
+      {
+       if ((setup_info[y].type & TYPE_KEYTEXT) &&
+           (setup_info[y + 1].type & TYPE_KEY))
+         y++;
+
+       if (setup_info[y].type & TYPE_VALUE)
+         changeSetupValue(y);
+      }
+#endif
     }
   }
 
@@ -1545,10 +1670,10 @@ void HandleGenericSetupScreen(int mx, int my, int dx, int dy, int button)
     DoAnimation();
 }
 
-void DrawSetupInputScreen()
+void DrawSetupScreen_Input()
 {
   ClearWindow();
-  DrawText(SX+16, SY+16, "SETUP INPUT", FS_BIG, FC_YELLOW);
+  DrawText(SX+16, SY+16, "Setup Input", FS_BIG, FC_YELLOW);
 
   initCursor(0, GFX_KUGEL_BLAU);
   initCursor(1, GFX_KUGEL_BLAU);
@@ -1566,7 +1691,7 @@ void DrawSetupInputScreen()
   DrawTextFCentered(SYSIZE - 20, FC_BLUE,
                    "Joysticks deactivated on this screen");
 
-  HandleSetupInputScreen(0,0, 0,0, MB_MENU_INITIALIZE);
+  HandleSetupScreen_Input(0,0, 0,0, MB_MENU_INITIALIZE);
   FadeToFront();
   InitAnimation();
 }
@@ -1663,7 +1788,7 @@ static void drawPlayerSetupInputInfo(int player_nr)
   }
 }
 
-void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
+void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
 {
   static int choice = 0;
   static int player_nr = 0;
@@ -1784,22 +1909,6 @@ void HandleSetupInputScreen(int mx, int my, int dx, int dy, int button)
     DoAnimation();
 }
 
-void DrawSetupScreen()
-{
-  if (setup_mode == SETUP_MODE_INPUT)
-    DrawSetupInputScreen();
-  else
-    DrawGenericSetupScreen();
-}
-
-void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
-{
-  if (setup_mode == SETUP_MODE_INPUT)
-    HandleSetupInputScreen(mx, my, dx, dy, button);
-  else
-    HandleGenericSetupScreen(mx, my, dx, dy, button);
-}
-
 void CustomizeKeyboard(int player_nr)
 {
   int i;
@@ -1927,7 +2036,7 @@ void CustomizeKeyboard(int player_nr)
   setup.input[player_nr].key = custom_key;
 
   StopAnimation();
-  DrawSetupInputScreen();
+  DrawSetupScreen_Input();
 }
 
 static boolean CalibrateJoystickMain(int player_nr)
@@ -2095,7 +2204,7 @@ static boolean CalibrateJoystickMain(int player_nr)
 
   StopAnimation();
 
-  DrawSetupInputScreen();
+  DrawSetupScreen_Input();
 
   /* wait until the last pressed button was released */
   while (Joystick(player_nr) & JOY_BUTTON)
@@ -2127,6 +2236,22 @@ void CalibrateJoystick(int player_nr)
   }
 }
 
+void DrawSetupScreen()
+{
+  if (setup_mode == SETUP_MODE_INPUT)
+    DrawSetupScreen_Input();
+  else
+    DrawSetupScreen_Generic();
+}
+
+void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
+{
+  if (setup_mode == SETUP_MODE_INPUT)
+    HandleSetupScreen_Input(mx, my, dx, dy, button);
+  else
+    HandleSetupScreen_Generic(mx, my, dx, dy, button);
+}
+
 void HandleGameActions()
 {
   if (game_status != PLAYING)
@@ -2326,7 +2451,7 @@ void CreateScreenGadgets()
 
 void MapChooseLevelGadgets()
 {
-  int num_leveldirs = numLevelDirInfoInGroup(leveldir_current);
+  int num_leveldirs = numTreeInfoInGroup(leveldir_current);
   int i;
 
   if (num_leveldirs <= MAX_MENU_ENTRIES_ON_SCREEN)