small code cleanup
[rocksndiamonds.git] / src / screens.c
index 339681299899fea6e6c3b028ff4011fa75a478ab..127333bcb1408058c3793f57886a78bb8d4e75e7 100644 (file)
 #define SETUP_MODE_CHOOSE_WINDOW_SIZE  19
 #define SETUP_MODE_CHOOSE_SCALING_TYPE 20
 #define SETUP_MODE_CHOOSE_RENDERING    21
-#define SETUP_MODE_CHOOSE_GRAPHICS     22
-#define SETUP_MODE_CHOOSE_SOUNDS       23
-#define SETUP_MODE_CHOOSE_MUSIC                24
-#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE        25
-#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 26
-#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 27
-#define SETUP_MODE_CHOOSE_TOUCH_CONTROL        28
-#define SETUP_MODE_CHOOSE_MOVE_DISTANCE        29
-#define SETUP_MODE_CHOOSE_DROP_DISTANCE        30
-#define SETUP_MODE_CHOOSE_TRANSPARENCY 31
-#define SETUP_MODE_CHOOSE_GRID_XSIZE_0 32
-#define SETUP_MODE_CHOOSE_GRID_YSIZE_0 33
-#define SETUP_MODE_CHOOSE_GRID_XSIZE_1 34
-#define SETUP_MODE_CHOOSE_GRID_YSIZE_1 35
-#define SETUP_MODE_CONFIG_VIRT_BUTTONS 36
-
-#define MAX_SETUP_MODES                        37
+#define SETUP_MODE_CHOOSE_VSYNC                22
+#define SETUP_MODE_CHOOSE_GRAPHICS     23
+#define SETUP_MODE_CHOOSE_SOUNDS       24
+#define SETUP_MODE_CHOOSE_MUSIC                25
+#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE        26
+#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 27
+#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 28
+#define SETUP_MODE_CHOOSE_TOUCH_CONTROL        29
+#define SETUP_MODE_CHOOSE_MOVE_DISTANCE        30
+#define SETUP_MODE_CHOOSE_DROP_DISTANCE        31
+#define SETUP_MODE_CHOOSE_TRANSPARENCY 32
+#define SETUP_MODE_CHOOSE_GRID_XSIZE_0 33
+#define SETUP_MODE_CHOOSE_GRID_YSIZE_0 34
+#define SETUP_MODE_CHOOSE_GRID_XSIZE_1 35
+#define SETUP_MODE_CHOOSE_GRID_YSIZE_1 36
+#define SETUP_MODE_CONFIG_VIRT_BUTTONS 37
+
+#define MAX_SETUP_MODES                        38
 
 #define MAX_MENU_MODES                 MAX(MAX_INFO_MODES, MAX_SETUP_MODES)
 
 #define STR_SETUP_CHOOSE_WINDOW_SIZE   "Window Scaling"
 #define STR_SETUP_CHOOSE_SCALING_TYPE  "Anti-Aliasing"
 #define STR_SETUP_CHOOSE_RENDERING     "Rendering Mode"
+#define STR_SETUP_CHOOSE_VSYNC         "VSync Mode"
 #define STR_SETUP_CHOOSE_VOLUME_SIMPLE "Sound Volume"
 #define STR_SETUP_CHOOSE_VOLUME_LOOPS  "Loops Volume"
 #define STR_SETUP_CHOOSE_VOLUME_MUSIC  "Music Volume"
 #define MENU_SETUP_FONT_TITLE          FONT_TEXT_1
 #define MENU_SETUP_FONT_TEXT           FONT_TITLE_2
 
+#define MAX_SETUP_TEXT_INPUT_LEN       28
+
 /* for various menu stuff  */
 #define MENU_SCREEN_START_XPOS         1
 #define MENU_SCREEN_START_YPOS         2
 #define MAX_MENU_TEXT_LENGTH_BIG       13
 #define MAX_MENU_TEXT_LENGTH_MEDIUM    (MAX_MENU_TEXT_LENGTH_BIG * 2)
 
-/* buttons and scrollbars identifiers */
+/* screen gadget identifiers */
 #define SCREEN_CTRL_ID_PREV_LEVEL      0
 #define SCREEN_CTRL_ID_NEXT_LEVEL      1
 #define SCREEN_CTRL_ID_PREV_PLAYER     2
 #define SCREEN_CTRL_ID_SCROLL_UP       6
 #define SCREEN_CTRL_ID_SCROLL_DOWN     7
 #define SCREEN_CTRL_ID_SCROLL_VERTICAL 8
+#define SCREEN_CTRL_ID_NETWORK_SERVER  9
 
-#define NUM_SCREEN_GADGETS             9
+#define NUM_SCREEN_GADGETS             10
 
 #define NUM_SCREEN_MENUBUTTONS         6
 #define NUM_SCREEN_SCROLLBUTTONS       2
 #define NUM_SCREEN_SCROLLBARS          1
+#define NUM_SCREEN_TEXTINPUT           1
 
 #define SCREEN_MASK_MAIN               (1 << 0)
 #define SCREEN_MASK_MAIN_HAS_SOLUTION  (1 << 1)
@@ -265,6 +271,9 @@ static TreeInfo *scaling_type_current = NULL;
 static TreeInfo *rendering_modes = NULL;
 static TreeInfo *rendering_mode_current = NULL;
 
+static TreeInfo *vsync_modes = NULL;
+static TreeInfo *vsync_mode_current = NULL;
+
 static TreeInfo *scroll_delays = NULL;
 static TreeInfo *scroll_delay_current = NULL;
 
@@ -353,6 +362,19 @@ static struct
   {    NULL,                            NULL                            },
 };
 
+static struct
+{
+  char *value;
+  char *text;
+} vsync_modes_list[] =
+{
+  {    STR_VSYNC_MODE_OFF,             "Off"           },
+  {    STR_VSYNC_MODE_NORMAL,          "Normal"        },
+  {    STR_VSYNC_MODE_ADAPTIVE,        "Adaptive"      },
+
+  {    NULL,                            NULL           },
+};
+
 static struct
 {
   int value;
@@ -652,6 +674,8 @@ static char str_main_text_first_level[10];
 static char str_main_text_last_level[10];
 static char str_main_text_level_number[10];
 
+static char network_server_hostname[MAX_SETUP_TEXT_INPUT_LEN + 1];
+
 static char *main_text_name                    = str_main_text_name;
 static char *main_text_first_level             = str_main_text_first_level;
 static char *main_text_last_level              = str_main_text_last_level;
@@ -2218,7 +2242,8 @@ static int getMenuTextFont(int type)
              TYPE_PLAYER       |
              TYPE_ECS_AGA      |
              TYPE_KEYTEXT      |
-             TYPE_ENTER_LIST))
+             TYPE_ENTER_LIST   |
+             TYPE_TEXT_INPUT))
     return FONT_MENU_2;
   else
     return FONT_MENU_1;
@@ -2265,6 +2290,7 @@ static void DrawCursorAndText_Setup(int screen_pos, int menu_info_pos_raw,
 
 static char *window_size_text;
 static char *scaling_type_text;
+static char *network_server_text;
 
 static void drawSetupValue(int, int);
 
@@ -2302,6 +2328,25 @@ static void drawMenuInfoList(int first_entry, int num_page_entries,
 
     DrawCursorAndText_Menu(i, menu_info_pos, FALSE);
 
+    if (si->type & TYPE_STRING)
+    {
+      int gadget_id = -1;
+
+      if (value_ptr == &network_server_text)
+       gadget_id = SCREEN_CTRL_ID_NETWORK_SERVER;
+
+      if (gadget_id != -1)
+      {
+       struct GadgetInfo *gi = screen_gadget[gadget_id];
+       int xpos = MENU_SCREEN_START_XPOS;
+       int ypos = MENU_SCREEN_START_YPOS + i;
+       int x = mSX + xpos * 32;
+       int y = mSY + ypos * 32;
+
+       ModifyGadget(gi, GDI_X, x, GDI_Y, y, GDI_END);
+      }
+    }
+
     if (si->type & TYPE_VALUE &&
        menu_info == setup_info)
       drawSetupValue(i, menu_info_pos);
@@ -2647,6 +2692,11 @@ static void HandleMenuScreen(int mx, int my, int dx, int dy, int button,
          menu_info[first_entry + y - 1].type & TYPE_ENTER_LIST)
        y--;
 
+      /* when selecting string value, execute function for text input gadget */
+      if (menu_info[first_entry + y].type & TYPE_STRING && y > 0 &&
+         menu_info[first_entry + y - 1].type & TYPE_TEXT_INPUT)
+       y--;
+
       if (menu_info[first_entry + y].type & TYPE_ENTER_OR_LEAVE)
       {
        void (*menu_callback_function)(void) =
@@ -2656,6 +2706,13 @@ static void HandleMenuScreen(int mx, int my, int dx, int dy, int button,
 
        menu_callback_function();
       }
+      else if (menu_info[first_entry + y].type & TYPE_TEXT_INPUT)
+      {
+       void (*gadget_callback_function)(void) =
+         menu_info[first_entry + y].value;
+
+       gadget_callback_function();
+      }
       else if (menu_info[first_entry + y].type & TYPE_VALUE &&
               menu_info == setup_info)
       {
@@ -4168,7 +4225,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
        execSetupGame();
       else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
               setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
-              setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+              setup_mode == SETUP_MODE_CHOOSE_RENDERING ||
+              setup_mode == SETUP_MODE_CHOOSE_VSYNC)
        execSetupGraphics();
       else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
               setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
@@ -4325,7 +4383,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
            execSetupGame();
          else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
                   setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
-                  setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+                  setup_mode == SETUP_MODE_CHOOSE_RENDERING ||
+                  setup_mode == SETUP_MODE_CHOOSE_VSYNC)
            execSetupGraphics();
          else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
                   setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
@@ -4396,7 +4455,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
            execSetupGame();
          else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE ||
                   setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE ||
-                  setup_mode == SETUP_MODE_CHOOSE_RENDERING)
+                  setup_mode == SETUP_MODE_CHOOSE_RENDERING ||
+                  setup_mode == SETUP_MODE_CHOOSE_VSYNC)
            execSetupGraphics();
          else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE ||
                   setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS ||
@@ -4667,9 +4727,11 @@ static int max_setup_info;       /* total number of setup entries in list */
 static char *window_size_text;
 static char *scaling_type_text;
 static char *rendering_mode_text;
+static char *vsync_mode_text;
 static char *scroll_delay_text;
 static char *snapshot_mode_text;
 static char *game_speed_text;
+static char *network_server_text;
 static char *graphics_set_name;
 static char *sounds_set_name;
 static char *music_set_name;
@@ -4839,12 +4901,31 @@ static void execSetupGame_setSnapshotModes(void)
   snapshot_mode_text = snapshot_mode_current->name;
 }
 
+static void execSetupGame_setNetworkServerText(void)
+{
+  if (strEqual(setup.network_server_hostname, STR_NETWORK_AUTO_DETECT))
+  {
+    strcpy(network_server_hostname, STR_NETWORK_AUTO_DETECT_SETUP);
+  }
+  else
+  {
+    strncpy(network_server_hostname, setup.network_server_hostname,
+           MAX_SETUP_TEXT_INPUT_LEN);
+    network_server_hostname[MAX_SETUP_TEXT_INPUT_LEN] = '\0';
+  }
+
+  /* needed for displaying network server text instead of identifier */
+  network_server_text = network_server_hostname;
+}
+
 static void execSetupGame(void)
 {
   execSetupGame_setGameSpeeds();
   execSetupGame_setScrollDelays();
   execSetupGame_setSnapshotModes();
 
+  execSetupGame_setNetworkServerText();
+
   setup_mode = SETUP_MODE_GAME;
 
   DrawSetupScreen();
@@ -5064,6 +5145,56 @@ static void execSetupGraphics_setRenderingModes(void)
   rendering_mode_text = rendering_mode_current->name;
 }
 
+static void execSetupGraphics_setVsyncModes(void)
+{
+  if (vsync_modes == NULL)
+  {
+    int i;
+
+    for (i = 0; vsync_modes_list[i].value != NULL; i++)
+    {
+      TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED);
+      char identifier[32], name[32];
+      char *value = vsync_modes_list[i].value;
+      char *text = vsync_modes_list[i].text;
+
+      ti->node_top = &vsync_modes;
+      ti->sort_priority = i;
+
+      sprintf(identifier, "%s", value);
+      sprintf(name, "%s", text);
+
+      setString(&ti->identifier, identifier);
+      setString(&ti->name, name);
+      setString(&ti->name_sorting, name);
+      setString(&ti->infotext, STR_SETUP_CHOOSE_VSYNC);
+
+      pushTreeInfo(&vsync_modes, ti);
+    }
+
+    /* sort vsync mode values to start with lowest vsync mode value */
+    sortTreeInfo(&vsync_modes);
+
+    /* set current vsync mode value to configured vsync mode value */
+    vsync_mode_current =
+      getTreeInfoFromIdentifier(vsync_modes, setup.vsync_mode);
+
+    /* if that fails, set current vsync mode to reliable default value */
+    if (vsync_mode_current == NULL)
+      vsync_mode_current =
+       getTreeInfoFromIdentifier(vsync_modes, STR_VSYNC_MODE_DEFAULT);
+
+    /* if that also fails, set current vsync mode to first available one */
+    if (vsync_mode_current == NULL)
+      vsync_mode_current = vsync_modes;
+  }
+
+  setup.vsync_mode = vsync_mode_current->identifier;
+
+  /* needed for displaying vsync mode text instead of identifier */
+  vsync_mode_text = vsync_mode_current->name;
+}
+
 static void execSetupGraphics(void)
 {
   // update "setup.window_scaling_percent" from list selection
@@ -5077,6 +5208,7 @@ static void execSetupGraphics(void)
 
   execSetupGraphics_setScalingTypes();
   execSetupGraphics_setRenderingModes();
+  execSetupGraphics_setVsyncModes();
 
   setup_mode = SETUP_MODE_GRAPHICS;
 
@@ -5092,6 +5224,9 @@ static void execSetupGraphics(void)
 
   // screen rendering mode may have changed at this point
   SDLSetScreenRenderingMode(setup.screen_rendering_mode);
+
+  // screen vsync mode may have changed at this point
+  SDLSetScreenVsyncMode(setup.vsync_mode);
 #endif
 }
 
@@ -5116,6 +5251,13 @@ static void execSetupChooseRenderingMode(void)
   DrawSetupScreen();
 }
 
+static void execSetupChooseVsyncMode(void)
+{
+  setup_mode = SETUP_MODE_CHOOSE_VSYNC;
+
+  DrawSetupScreen();
+}
+
 static void execSetupChooseVolumeSimple(void)
 {
   setup_mode = SETUP_MODE_CHOOSE_VOLUME_SIMPLE;
@@ -5794,6 +5936,55 @@ static void execSaveAndExitSetup(void)
   execExitSetup();
 }
 
+static void execGadgetNetworkServer(void)
+{
+  int gadget_id = SCREEN_CTRL_ID_NETWORK_SERVER;
+  struct GadgetInfo *gi = screen_gadget[gadget_id];
+
+  if (strEqual(setup.network_server_hostname, STR_NETWORK_AUTO_DETECT))
+    network_server_hostname[0] = '\0';
+
+  ModifyGadget(gi, GDI_TEXT_VALUE, network_server_hostname, GDI_END);
+
+  MapGadget(gi);
+
+  ClickOnGadget(gi, MB_LEFTBUTTON);
+}
+
+static void ToggleNetworkModeIfNeeded(void)
+{
+  int font_title = FONT_TITLE_1;
+  int font_foot = FC_BLUE;
+  int ystart  = mSY - SY + 16;
+  int ybottom = mSY - SY + SYSIZE - 20;
+  char *text = (setup.network_mode ? "Start Network" : "Stop Network");
+
+  if (setup.network_mode == network.enabled)
+    return;
+
+  network.enabled = setup.network_mode;
+
+  FadeOut(REDRAW_ALL);
+
+  ClearField();
+
+  DrawTextSCentered(ystart, font_title, text);
+
+  FadeIn(REDRAW_ALL);
+
+  if (network.enabled)
+    InitNetworkServer();
+  else
+    DisconnectFromNetworkServer();
+
+  DrawTextSCentered(ybottom, font_foot,
+                   "Press any key or button for setup menu");
+
+  WaitForEventToContinue();
+
+  DrawSetupScreen();
+}
+
 static struct
 {
   void *value;
@@ -5818,6 +6009,9 @@ static struct
   { &setup.screen_rendering_mode,      execSetupChooseRenderingMode    },
   { &setup.screen_rendering_mode,      &rendering_mode_text            },
 
+  { &setup.vsync_mode,                 execSetupChooseVsyncMode        },
+  { &setup.vsync_mode,                 &vsync_mode_text                },
+
   { &setup.graphics_set,               execSetupChooseGraphics         },
   { &setup.graphics_set,               &graphics_set_name              },
 
@@ -5894,6 +6088,8 @@ static struct TokenInfo setup_info_game[] =
   { TYPE_SWITCH,       &setup.team_mode,       "Team-Mode (Multi-Player):" },
   { TYPE_SWITCH,       &setup.network_mode,    "Network Multi-Player Mode:" },
   { TYPE_PLAYER,       &setup.network_player_nr,"Preferred Network Player:" },
+  { TYPE_TEXT_INPUT,   execGadgetNetworkServer, "Network Server Hostname:" },
+  { TYPE_STRING,       &network_server_text,   ""                      },
   { TYPE_YES_NO,       &setup.input_on_focus,  "Only Move Focussed Player:" },
   { TYPE_SWITCH,       &setup.time_limit,      "Time Limit:"           },
   { TYPE_SWITCH,       &setup.handicap,        "Handicap:"             },
@@ -5966,6 +6162,8 @@ static struct TokenInfo setup_info_graphics[] =
   { TYPE_ENTER_LIST,   execSetupChooseScrollDelay, "Scroll Delay:"     },
   { TYPE_STRING,       &scroll_delay_text,     ""                      },
 #endif
+  { TYPE_ENTER_LIST,   execSetupChooseVsyncMode, "Vertical Sync (VSync):" },
+  { TYPE_STRING,       &vsync_mode_text,       ""                      },
   { TYPE_SWITCH,       &setup.fade_screens,    "Fade Screens:"         },
   { TYPE_SWITCH,       &setup.quick_switch,    "Quick Player Focus Switch:" },
   { TYPE_SWITCH,       &setup.quick_doors,     "Quick Menu Doors:"     },
@@ -6291,10 +6489,12 @@ static void drawSetupValue(int screen_pos, int setup_info_pos_raw)
   int ypos = MENU_SCREEN_START_YPOS + screen_pos;
   int startx = mSX + xpos * 32;
   int starty = mSY + ypos * 32;
-  int font_nr, font_nr_default, font_width_default;
   int type = si->type;
   void *value = si->value;
   char *value_string = getSetupValue(type, value);
+  int font_nr_default = getSetupValueFont(type, value);
+  int font_width_default = getFontWidth(font_nr_default);
+  int font_nr = font_nr_default;
   int i;
 
   if (value_string == NULL)
@@ -6329,10 +6529,6 @@ static void drawSetupValue(int screen_pos, int setup_info_pos_raw)
 
   startx = mSX + xpos * 32;
   starty = mSY + ypos * 32;
-  font_nr_default = getSetupValueFont(type, value);
-  font_width_default = getFontWidth(font_nr_default);
-
-  font_nr = font_nr_default;
 
   // special check if right-side setup values moved left due to scrollbar
   if (scrollbar_needed && xpos > MENU_SCREEN_START_XPOS)
@@ -6398,10 +6594,17 @@ static void drawSetupValue(int screen_pos, int setup_info_pos_raw)
 
   if (type & TYPE_PLAYER)
   {
+    struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
     int player_nr = *(int *)value;
-    int xoff = getFontWidth(font_nr);
+    int xoff = font->draw_xoffset + getFontWidth(font_nr);
+    int yoff = font->draw_yoffset + (getFontHeight(font_nr) - TILEY) / 2;
+    int startx2 = startx + xoff;
+    int starty2 = starty + yoff;
+
+    if (DrawingOnBackground(startx2, starty2))
+      ClearRectangleOnBackground(drawto, startx2, starty2, TILEX, TILEY);
 
-    DrawFixedGraphicThruMaskExt(drawto, startx + xoff, starty,
+    DrawFixedGraphicThruMaskExt(drawto, startx2, starty2,
                                PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0);
   }
 
@@ -6457,24 +6660,9 @@ static void changeSetupValue(int screen_pos, int setup_info_pos_raw, int dx)
   if (si->value == &setup.fullscreen)
     ToggleFullscreenOrChangeWindowScalingIfNeeded();
 
-  if (si->value == &setup.network_mode &&
-      setup.network_mode != network.enabled)
-  {
-    network.enabled = setup.network_mode;
-
-    FadeOut(REDRAW_ALL);
-
-    ClearField();
-
-    FadeIn(REDRAW_ALL);
-
-    if (network.enabled)
-      InitNetworkServer();
-    else
-      DisconnectFromNetworkServer();
-
-    DrawSetupScreen();
-  }
+  // network mode may have changed at this point
+  if (si->value == &setup.network_mode)
+    ToggleNetworkModeIfNeeded();
 }
 
 static struct TokenInfo *getSetupInfoFinal(struct TokenInfo *setup_info_orig)
@@ -7833,6 +8021,8 @@ void DrawSetupScreen(void)
     DrawChooseTree(&scaling_type_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING)
     DrawChooseTree(&rendering_mode_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VSYNC)
+    DrawChooseTree(&vsync_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS)
     DrawChooseTree(&artwork.gfx_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS)
@@ -7913,6 +8103,8 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     HandleChooseTree(mx, my, dx, dy, button, &scaling_type_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING)
     HandleChooseTree(mx, my, dx, dy, button, &rendering_mode_current);
+  else if (setup_mode == SETUP_MODE_CHOOSE_VSYNC)
+    HandleChooseTree(mx, my, dx, dy, button, &vsync_mode_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS)
     HandleChooseTree(mx, my, dx, dy, button, &artwork.gfx_current);
   else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS)
@@ -8096,6 +8288,26 @@ static struct
   }
 };
 
+static struct
+{
+  int graphic;
+  int gadget_id;
+  int x, y;
+  int size;
+  char *value;
+  char *infotext;
+} textinput_info[NUM_SCREEN_TEXTINPUT] =
+{
+  {
+    IMG_SETUP_INPUT_TEXT,
+    SCREEN_CTRL_ID_NETWORK_SERVER,
+    -1, -1,    /* these values are not constant, but can change at runtime */
+    MAX_SETUP_TEXT_INPUT_LEN,
+    network_server_hostname,
+    "Network Server Hostname / IP"
+  },
+};
+
 static void CreateScreenMenubuttons(void)
 {
   struct GadgetInfo *gi;
@@ -8310,12 +8522,60 @@ static void CreateScreenScrollbars(void)
   }
 }
 
+static void CreateScreenTextInputGadgets(void)
+{
+  int i;
+
+  for (i = 0; i < NUM_SCREEN_TEXTINPUT; i++)
+  {
+    int graphic = textinput_info[i].graphic;
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->active_xoffset;
+    int gd_y2 = gd->src_y + gd->active_yoffset;
+    struct GadgetInfo *gi;
+    unsigned int event_mask;
+    int id = textinput_info[i].gadget_id;
+    int x = textinput_info[i].x;
+    int y = textinput_info[i].y;
+
+    event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
+
+    gi = CreateGadget(GDI_CUSTOM_ID, id,
+                     GDI_CUSTOM_TYPE_ID, i,
+                     GDI_INFO_TEXT, textinput_info[i].infotext,
+                     GDI_X, SX + x,
+                     GDI_Y, SY + y,
+                     GDI_TYPE, GD_TYPE_TEXT_INPUT_ALPHANUMERIC,
+                     GDI_TEXT_VALUE, textinput_info[i].value,
+                     GDI_TEXT_SIZE, textinput_info[i].size,
+                     GDI_TEXT_FONT, getSetupValueFont(TYPE_STRING, NULL),
+                     GDI_TEXT_FONT_ACTIVE, FONT_TEXT_1,
+                     GDI_DESIGN_UNPRESSED, gd->bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd->bitmap, gd_x2, gd_y2,
+                     GDI_BORDER_SIZE, gd->border_size, gd->border_size,
+                     GDI_DESIGN_WIDTH, gd->width,
+                     GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_ACTION, HandleScreenGadgets,
+                     GDI_CALLBACK_ACTION_ALWAYS, TRUE,
+                     GDI_END);
+
+    if (gi == NULL)
+      Error(ERR_EXIT, "cannot create gadget");
+
+    screen_gadget[id] = gi;
+  }
+}
+
 void CreateScreenGadgets(void)
 {
   CreateScreenMenubuttons();
 
   CreateScreenScrollbuttons();
   CreateScreenScrollbars();
+
+  CreateScreenTextInputGadgets();
 }
 
 void FreeScreenGadgets(void)
@@ -8448,6 +8708,31 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
        HandleInfoScreen(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE);
       break;
 
+    case SCREEN_CTRL_ID_NETWORK_SERVER:
+    {
+      if (!strEqual(gi->textinput.value, ""))
+      {
+       setString(&setup.network_server_hostname, gi->textinput.value);
+
+       network.server_host = setup.network_server_hostname;
+      }
+      else
+      {
+       setString(&setup.network_server_hostname, STR_NETWORK_AUTO_DETECT);
+
+       network.server_host = NULL;
+      }
+
+      if (strEqual(network.server_host, STR_NETWORK_AUTO_DETECT))
+       network.server_host = NULL;
+
+      execSetupGame_setNetworkServerText();
+
+      DrawSetupScreen();
+
+      break;
+    }
+
     default:
       break;
   }