foxygit / doom Log in
commit 96f7da6adf5d4b6eb7b6ab66bd1758a2b14d1efa
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sun Sep 18 14:16:27 2011 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sun Sep 18 14:16:27 2011 +0000

    Hook query code into setup tool, and add search results window.

    Subversion-branch: /branches/v2-branch
    Subversion-revision: 2383
---
 src/net_query.c             |  10 ++--
 src/setup/multiplayer.c     | 114 +++++++++++++++++++++++++++++++++++---------
 textscreen/txt_desktop.c    |  27 ++++++++++-
 textscreen/txt_desktop.h    |  19 +++++++-
 textscreen/txt_scrollpane.c |  18 +++++--
 5 files changed, 157 insertions(+), 31 deletions(-)

diff --git a/src/net_query.c b/src/net_query.c
index 06391a14..f9f4c918 100644
--- a/src/net_query.c
+++ b/src/net_query.c
@@ -528,10 +528,14 @@ static void NET_Query_QueryLoop(net_query_callback_t callback, void *user_data)

 void NET_Query_Init(void)
 {
-    query_context = NET_NewContext();
-    NET_AddModule(query_context, &net_sdl_module);
-    net_sdl_module.InitClient();
+    if (query_context == NULL)
+    {
+        query_context = NET_NewContext();
+        NET_AddModule(query_context, &net_sdl_module);
+        net_sdl_module.InitClient();
+    }

+    free(targets);
     targets = NULL;
     num_targets = 0;

diff --git a/src/setup/multiplayer.c b/src/setup/multiplayer.c
index b625f056..f34ba558 100644
--- a/src/setup/multiplayer.c
+++ b/src/setup/multiplayer.c
@@ -35,6 +35,9 @@
 #include "mode.h"
 #include "execute.h"

+#include "net_io.h"
+#include "net_query.h"
+
 #define NUM_WADS 10
 #define NUM_EXTRA_PARAMS 10

@@ -44,12 +47,6 @@ typedef enum
     WARP_MAPxy,
 } warptype_t;

-typedef enum
-{
-    JOIN_AUTO_LAN,
-    JOIN_ADDRESS,
-} jointype_t;
-
 // Fallback IWAD if none are found to be installed

 static iwad_t fallback_iwad = { "doom2.wad", doom2, commercial, "Doom II" };
@@ -132,8 +129,6 @@ static char *gamemodes[] =
 static char *net_player_name;
 static char *chat_macros[10];

-static int jointype = JOIN_ADDRESS;
-
 static char *wads[NUM_WADS];
 static char *extra_params[NUM_EXTRA_PARAMS];
 static int character_class = 0;
@@ -156,6 +151,9 @@ static int warpmap = 1;

 static char *connect_address = NULL;

+static txt_window_t *query_window;
+static int query_servers_found;
+
 // Find an IWAD from its description

 static iwad_t *GetCurrentIWAD(void)
@@ -736,14 +734,7 @@ static void DoJoinGame(void *unused1, void *unused2)

     exec = NewExecuteContext();

-    if (jointype == JOIN_ADDRESS)
-    {
-        AddCmdLineParameter(exec, "-connect %s", connect_address);
-    }
-    else if (jointype == JOIN_AUTO_LAN)
-    {
-        AddCmdLineParameter(exec, "-autojoin");
-    }
+    AddCmdLineParameter(exec, "-connect %s", connect_address);

     if (gamemission == hexen)
     {
@@ -778,11 +769,89 @@ static txt_window_action_t *JoinGameAction(void)
     return action;
 }

-// When an address is entered, select "address" mode.
+static void SelectQueryAddress(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(addr))
+{
+    TXT_CAST_ARG(txt_button_t, button);
+
+    free(connect_address);
+    connect_address = strdup(button->label);
+    TXT_CloseWindow(query_window);
+}
+
+static void QueryResponseCallback(net_addr_t *addr,
+                                  net_querydata_t *querydata,
+                                  unsigned int ping_time,
+                                  TXT_UNCAST_ARG(results_table))
+{
+    TXT_CAST_ARG(txt_table_t, results_table);
+    char ping_time_str[16];
+    char description[47];
+
+    sprintf(ping_time_str, "%ims", ping_time);
+    strncpy(description, querydata->description, 46);
+    description[46] = '\0';
+
+    TXT_AddWidgets(results_table,
+                   TXT_NewButton2(NET_AddrToString(addr),
+                                  SelectQueryAddress, addr),
+                   TXT_NewLabel(description),
+                   TXT_NewLabel(ping_time_str),
+                   NULL);
+
+    ++query_servers_found;
+}
+
+static void QueryPeriodicCallback(TXT_UNCAST_ARG(results_table))
+{
+    TXT_CAST_ARG(txt_table_t, results_table);
+
+    if (!NET_Query_Poll(QueryResponseCallback, results_table))
+    {
+        TXT_SetPeriodicCallback(NULL, NULL, 0);
+
+        if (query_servers_found == 0)
+        {
+            TXT_AddWidget(results_table, NULL);
+            TXT_AddWidget(results_table, TXT_NewLabel("No servers found."));
+        }
+    }
+}
+
+static void QueryWindowClosed(TXT_UNCAST_ARG(window), void *unused)
+{
+    TXT_SetPeriodicCallback(NULL, NULL, 0);
+}
+
+static void ServerQueryWindow(char *title)
+{
+    txt_table_t *results_table;
+
+    query_servers_found = 0;
+
+    query_window = TXT_NewWindow(title);
+
+    TXT_AddWidget(query_window,
+                  TXT_NewScrollPane(70, 10,
+                                    results_table = TXT_NewTable(3)));
+
+    TXT_SetColumnWidths(results_table, 16, 46, 8);
+    TXT_SetPeriodicCallback(QueryPeriodicCallback, results_table, 1);
+
+    TXT_SignalConnect(query_window, "closed", QueryWindowClosed, NULL);
+}
+
+static void FindInternetServer(TXT_UNCAST_ARG(widget),
+                               TXT_UNCAST_ARG(user_data))
+{
+    NET_StartMasterQuery();
+    ServerQueryWindow("Find internet server");
+}

-static void SelectAddressJoin(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused))
+static void FindLANServer(TXT_UNCAST_ARG(widget),
+                          TXT_UNCAST_ARG(user_data))
 {
-    jointype = JOIN_ADDRESS;
+    NET_StartLANQuery();
+    ServerQueryWindow("Find LAN server");
 }

 void JoinMultiGame(void)
@@ -823,11 +892,12 @@ void JoinMultiGame(void)
                            TXT_NewLabel("Connect to address: "),
                            address_box = TXT_NewInputBox(&connect_address, 30),
                            NULL),
-                   TXT_NewButton("Find server on Internet..."),
-                   TXT_NewButton("Find server on local network..."),
+                   TXT_NewButton2("Find server on Internet...",
+                                  FindInternetServer, NULL),
+                   TXT_NewButton2("Find server on local network...",
+                                  FindLANServer, NULL),
                    NULL);

-    TXT_SignalConnect(address_box, "changed", SelectAddressJoin, NULL);
     TXT_SelectWidget(window, address_box);

     TXT_SetWindowAction(window, TXT_HORIZ_CENTER, WadWindowAction());
diff --git a/textscreen/txt_desktop.c b/textscreen/txt_desktop.c
index c497f0e3..31c3921e 100644
--- a/textscreen/txt_desktop.c
+++ b/textscreen/txt_desktop.c
@@ -39,6 +39,10 @@ static txt_window_t *all_windows[MAXWINDOWS];
 static int num_windows = 0;
 static int main_loop_running = 0;

+static TxtIdleCallback periodic_callback = NULL;
+static void *periodic_callback_data;
+static unsigned int periodic_callback_period;
+
 void TXT_AddDesktopWindow(txt_window_t *win)
 {
     all_windows[num_windows] = win;
@@ -197,6 +201,15 @@ void TXT_DrawASCIITable(void)
     TXT_UpdateScreen();
 }

+void TXT_SetPeriodicCallback(TxtIdleCallback callback,
+                             void *user_data,
+                             unsigned int period)
+{
+    periodic_callback = callback;
+    periodic_callback_data = user_data;
+    periodic_callback_period = period;
+}
+
 void TXT_GUIMainLoop(void)
 {
     main_loop_running = 1;
@@ -211,10 +224,20 @@ void TXT_GUIMainLoop(void)
         {
             TXT_ExitMainLoop();
         }
-
+
         TXT_DrawDesktop();
 //        TXT_DrawASCIITable();
-        TXT_Sleep(0);
+
+        if (periodic_callback == NULL)
+        {
+            TXT_Sleep(0);
+        }
+        else
+        {
+            TXT_Sleep(periodic_callback_period);
+
+            periodic_callback(periodic_callback_data);
+        }
     }
 }

diff --git a/textscreen/txt_desktop.h b/textscreen/txt_desktop.h
index 42a011e7..4b6bd4b5 100644
--- a/textscreen/txt_desktop.h
+++ b/textscreen/txt_desktop.h
@@ -30,6 +30,8 @@

 #include "txt_window.h"

+typedef void (*TxtIdleCallback)(void *user_data);
+
 void TXT_AddDesktopWindow(txt_window_t *win);
 void TXT_RemoveDesktopWindow(txt_window_t *win);
 void TXT_DrawDesktop(void);
@@ -72,6 +74,21 @@ void TXT_GUIMainLoop(void);

 txt_window_t *TXT_GetActiveWindow(void);

-#endif /* #ifndef TXT_DESKTOP_H */
+/**
+ * Set a callback function to be invoked periodically by the main
+ * loop code.
+ *
+ * @param callback      The callback to invoke, or NULL to cancel
+ *                      an existing callback.
+ * @param user_data     Extra data to pass to the callback.
+ * @param period        Maximum time between invoking each callback.
+ *                      eg. a value of 200 will cause the callback
+ *                      to be invoked at least once every 200ms.
+ */
+
+void TXT_SetPeriodicCallback(TxtIdleCallback callback,
+                             void *user_data,
+                             unsigned int period);

+#endif /* #ifndef TXT_DESKTOP_H */

diff --git a/textscreen/txt_scrollpane.c b/textscreen/txt_scrollpane.c
index 2fd45c55..dba69d30 100644
--- a/textscreen/txt_scrollpane.c
+++ b/textscreen/txt_scrollpane.c
@@ -158,6 +158,18 @@ static void TXT_ScrollPaneSizeCalc(TXT_UNCAST_ARG(scrollpane))
     {
         ++scrollpane->widget.w;
     }
+
+    if (scrollpane->child != NULL)
+    {
+        if (scrollpane->child->w < scrollpane->w)
+        {
+            scrollpane->child->w = scrollpane->w;
+        }
+        if (scrollpane->child->h < scrollpane->h)
+        {
+            scrollpane->child->h = scrollpane->h;
+        }
+    }
 }

 static void TXT_ScrollPaneDrawer(TXT_UNCAST_ARG(scrollpane), int selected)
@@ -382,10 +394,10 @@ static int TXT_ScrollPaneKeyPress(TXT_UNCAST_ARG(scrollpane), int key)
         // automatically move the scroll pane to show the new
         // selected item.

-        if (scrollpane->child->widget_class == &txt_table_class
-         && (key == KEY_UPARROW || key == KEY_DOWNARROW
+        if ((key == KEY_UPARROW || key == KEY_DOWNARROW
           || key == KEY_LEFTARROW || key == KEY_RIGHTARROW
-          || key == KEY_PGUP || key == KEY_PGDN))
+          || key == KEY_PGUP || key == KEY_PGDN)
+         && scrollpane->child->widget_class == &txt_table_class)
         {
             if (PageSelectedWidget(scrollpane, key))
             {