Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2006:
[Freeciv-Dev] Re: (PR#16459) Lots of conndlg errors
Home

[Freeciv-Dev] Re: (PR#16459) Lots of conndlg errors

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#16459) Lots of conndlg errors
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Sat, 15 Apr 2006 13:56:02 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=16459 >

On Sat, 15 Apr 2006, Per I. Mathisen wrote:
> 1. Load savegame with username not in savegame. Try to 'take' your own
> connection.
>
> 2. As in 1, but try to 'observe' your own connection.
>
> 3. As in 1, but the 'take' button in the 'taskbar' of the conndlg says
> 'Take player' although no player is selected, and executes 'take -' on the
> server (meaning detach).
>
> 4. As in 3, but 'take' button also does nothing if a player is selected.
>
> 5. You cannot aitoggle, observe or take a player in the conndlg if the
> player name contains spaces.

This patch fixes the above, and does this:
 - the 'pick nation' button becomes 'create player' button when client
connection is detached from any player
 - observe button is a toggle on/off, except if client connections has
taken a player, then it becomes a 'release player' button
 - lots of non-sane combinations checked and disabled
 - detaching from a player creates an ugly duplication of usernames in the
username list if the detached player is not AI, as the detached player's
username will show as the same name as the detached connection's name; to
improve this, the client will automatically un-AI a taken player, and
automatically AI a detached player

When right-clicking on a non-attached connection in the conn/plr-list, the
menu should contain a list of possible players this connection can attach.
Currently there is no way to force a connection that is not you to take a
player, but this is possible with cmdline. This is the next step, but I
got tired so not in this patch.

  - Per

Index: utility/support.c
===================================================================
--- utility/support.c   (revision 11842)
+++ utility/support.c   (working copy)
@@ -133,7 +133,28 @@
 #endif
 }
 
+/***************************************************************
+  Compare strings like strncasecmp() but ignoring quotes in
+  either string. Quotes still count towards n.
+***************************************************************/
+int mystrncasequotecmp(const char *str0, const char *str1, size_t n)
+{
+  size_t i;
+  char c;
 
+  for (i = 0; i < n && *str0 != '\0'; i++) {
+    if (my_tolower(*str0) != my_tolower(*str1)
+        && *str0 != '"' && *str1 != '"') {
+      return ((int) (unsigned char) my_tolower(*str0))
+             - ((int) (unsigned char) my_tolower(*str1));
+    }
+    c = *str0;
+    str0 += (*str1 != '"');
+    str1 += (c != '"');
+  }
+  return 0;
+}
+
 /***************************************************************
   Return a string which describes a given error (errno-style.)
 ***************************************************************/
Index: utility/support.h
===================================================================
--- utility/support.h   (revision 11842)
+++ utility/support.h   (working copy)
@@ -75,6 +75,7 @@
 
 int mystrcasecmp(const char *str0, const char *str1);
 int mystrncasecmp(const char *str0, const char *str1, size_t n);
+int mystrncasequotecmp(const char *str0, const char *str1, size_t n);
 
 const char *mystrerror(void);
 void myusleep(unsigned long usec);
Index: common/player.c
===================================================================
--- common/player.c     (revision 11842)
+++ common/player.c     (working copy)
@@ -292,7 +292,7 @@
   int ind;
 
   *result = match_prefix(pname_accessor, game.info.nplayers, MAX_LEN_NAME-1,
-                        mystrncasecmp, name, &ind);
+                        mystrncasequotecmp, name, &ind);
 
   if (*result < M_PRE_AMBIGUOUS) {
     return get_player(ind);
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
--- client/gui-gtk-2.0/gui_main.c       (revision 11842)
+++ client/gui-gtk-2.0/gui_main.c       (working copy)
@@ -1469,10 +1469,19 @@
   }
   gtk_widget_set_sensitive(ready_button, (game.player_ptr != NULL));
 
-  if (game.player_ptr && !aconnection.observer) {
+  if (aconnection.player) {
+    gtk_stockbutton_set_label(nation_button, _("Pick _Nation"));
+  } else {
+    gtk_stockbutton_set_label(nation_button, _("Create _player"));
+    gtk_widget_set_sensitive(nation_button, game.info.is_new_game);
+  }
+
+  if (aconnection.player) {
+    gtk_stockbutton_set_label(take_button, _("_Release player"));
+  } else if (!aconnection.observer) {
     gtk_stockbutton_set_label(take_button, _("_Observe"));
   } else {
-    gtk_stockbutton_set_label(take_button, _("_Take player"));
+    gtk_stockbutton_set_label(take_button, _("_Do not observe"));
   }
 
   gtk_tree_view_column_set_visible(record_col, (with_ggz || in_ggz));
Index: client/gui-gtk-2.0/pages.c
===================================================================
--- client/gui-gtk-2.0/pages.c  (revision 11842)
+++ client/gui-gtk-2.0/pages.c  (working copy)
@@ -57,7 +57,7 @@
 GtkTreeViewColumn *rating_col, *record_col;
 
 static GtkWidget *start_options_table;
-GtkWidget *take_button, *ready_button;
+GtkWidget *take_button, *ready_button, *nation_button;
 
 static GtkWidget *scenario_description;
 
@@ -990,8 +990,10 @@
 **************************************************************************/
 static void pick_nation_callback(GtkWidget *w, gpointer data)
 {
-  if (game.player_ptr) {
+  if (aconnection.player) {
     popup_races_dialog(game.player_ptr);
+  } else if (game.info.is_new_game) {
+    send_chat("/take -");
   }
 }
 
@@ -1000,10 +1002,21 @@
 **************************************************************************/
 static void take_callback(GtkWidget *w, gpointer data)
 {
-  if (game.player_ptr && !aconnection.observer) {
+  if (aconnection.player) {
+    if (!aconnection.player->ai.control) {
+      /* Make sure player reverts to AI control. This is much more neat,
+       * and hides the ugly double username in the name list because
+       * the player username equals the connection username. */
+      char buf[512];
+
+      my_snprintf(buf, sizeof(buf), "/ai %s", aconnection.player->name);
+      send_chat(buf);
+    }
+    send_chat("/detach");
+  } else if (!aconnection.observer) {
     send_chat("/observe");
   } else {
-    send_chat("/take -");
+    send_chat("/detach");
   }
 }
 
@@ -1066,12 +1079,27 @@
   char buf[1024];
   char *command = data;
 
-  /* FIXME: We should use quotes here, but because of a bug in the server
-   * it doesn't parse the quotes properly for some commands (e.g. "hard")! */
-  my_snprintf(buf, sizeof(buf), "/%s %s", command, conn_menu_player->name);
+  my_snprintf(buf, sizeof(buf), "/%s \"%s\"", command, 
+              conn_menu_player->name);
   send_chat(buf);
 }
 
+/****************************************************************************
+  Take command in the conn menu.
+****************************************************************************/
+static void conn_menu_player_take(GtkMenuItem *menuitem, gpointer data)
+{
+  char buf[1024];
+
+  if (conn_menu_player->ai.control) {
+    /* See comment on detach command for why */
+    my_snprintf(buf, sizeof(buf), "/ai \"%s\"", conn_menu_player->name);
+    send_chat(buf);
+  }
+  my_snprintf(buf, sizeof(buf), "/take \"%s\"", conn_menu_player->name);
+  send_chat(buf);
+}
+
 /**************************************************************************
  Show details about a user in the Connected Users dialog in a popup.
 **************************************************************************/
@@ -1080,8 +1108,13 @@
   GtkWidget *popup;
   char buf[1024] = "";
 
-  cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
-              pconn ? pconn->username : pplayer->name);
+  if (pconn) {
+    cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
+                 pconn->username);
+  } else {
+    cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
+                 pplayer->name);
+  }
   cat_snprintf(buf, sizeof(buf), "\n");
   if (pconn) {
     cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
@@ -1128,43 +1161,42 @@
   g_signal_connect(GTK_OBJECT(entry), "activate",
                   GTK_SIGNAL_FUNC(conn_menu_info_chosen), NULL);
 
-  entry = gtk_menu_item_new_with_label(_("Toggle player ready"));
-  gtk_widget_set_sensitive(entry, pplayer && !pplayer->ai.control);
-  g_object_set_data_full(G_OBJECT(menu),
-                        "ready", entry,
-                        (GtkDestroyNotify) gtk_widget_unref);
-  gtk_container_add(GTK_CONTAINER(menu), entry);
-  g_signal_connect(GTK_OBJECT(entry), "activate",
-                  GTK_SIGNAL_FUNC(conn_menu_ready_chosen), NULL);
+  if (pplayer) {
+    entry = gtk_menu_item_new_with_label(_("Toggle player ready"));
+    gtk_widget_set_sensitive(entry, pplayer && !pplayer->ai.control);
+    g_object_set_data_full(G_OBJECT(menu), "ready", entry,
+                           (GtkDestroyNotify) gtk_widget_unref);
+    gtk_container_add(GTK_CONTAINER(menu), entry);
+    g_signal_connect(GTK_OBJECT(entry), "activate",
+                     GTK_SIGNAL_FUNC(conn_menu_ready_chosen), NULL);
 
-  entry = gtk_menu_item_new_with_label(_("Pick nation"));
-  gtk_widget_set_sensitive(entry,
-                          pplayer
-                          && can_conn_edit_players_nation(&aconnection,
-                                                          pplayer));
-  g_object_set_data_full(G_OBJECT(menu),
-                        "nation", entry,
-                        (GtkDestroyNotify) gtk_widget_unref);
-  gtk_container_add(GTK_CONTAINER(menu), entry);
-  g_signal_connect(GTK_OBJECT(entry), "activate",
-                  GTK_SIGNAL_FUNC(conn_menu_nation_chosen), NULL);
+    entry = gtk_menu_item_new_with_label(_("Pick nation"));
+    gtk_widget_set_sensitive(entry,
+                             can_conn_edit_players_nation(&aconnection,
+                                                          pplayer));
+    g_object_set_data_full(G_OBJECT(menu), "nation", entry,
+                           (GtkDestroyNotify) gtk_widget_unref);
+    gtk_container_add(GTK_CONTAINER(menu), entry);
+    g_signal_connect(GTK_OBJECT(entry), "activate",
+                     GTK_SIGNAL_FUNC(conn_menu_nation_chosen), NULL);
 
-  entry = gtk_menu_item_new_with_label(_("Observe this player"));
-  g_object_set_data_full(G_OBJECT(menu),
-                        "observe", entry,
-                        (GtkDestroyNotify) gtk_widget_unref);
-  gtk_container_add(GTK_CONTAINER(menu), entry);
-  g_signal_connect(GTK_OBJECT(entry), "activate",
-                  GTK_SIGNAL_FUNC(conn_menu_player_command), "observe");
+    entry = gtk_menu_item_new_with_label(_("Observe this player"));
+    g_object_set_data_full(G_OBJECT(menu), "observe", entry,
+                           (GtkDestroyNotify) gtk_widget_unref);
+    gtk_container_add(GTK_CONTAINER(menu), entry);
+    g_signal_connect(GTK_OBJECT(entry), "activate",
+                     GTK_SIGNAL_FUNC(conn_menu_player_command), "observe");
 
-  entry = gtk_menu_item_new_with_label(_("Take this player"));
-  g_object_set_data_full(G_OBJECT(menu), "take", entry,
-                        (GtkDestroyNotify) gtk_widget_unref);
-  gtk_container_add(GTK_CONTAINER(menu), entry);
-  g_signal_connect(GTK_OBJECT(entry), "activate",
-                  GTK_SIGNAL_FUNC(conn_menu_player_command), "take");
+    entry = gtk_menu_item_new_with_label(_("Take this player"));
+    g_object_set_data_full(G_OBJECT(menu), "take", entry,
+                           (GtkDestroyNotify) gtk_widget_unref);
+    gtk_container_add(GTK_CONTAINER(menu), entry);
+    g_signal_connect(GTK_OBJECT(entry), "activate",
+                     GTK_SIGNAL_FUNC(conn_menu_player_take), "take");
+  }
 
-  if (aconnection.access_level >= ALLOW_CTRL && pconn) {
+  if (aconnection.access_level >= ALLOW_CTRL && pconn
+      && (pconn->id != aconnection.id || pplayer)) {
     entry = gtk_separator_menu_item_new();
     g_object_set_data_full(G_OBJECT(menu),
                           "ctrl", entry,
@@ -1189,7 +1221,8 @@
     g_signal_connect(GTK_OBJECT(entry), "activate",
                     GTK_SIGNAL_FUNC(conn_menu_player_command), "aitoggle");
 
-    if (pplayer->player_no != game.info.player_idx) {
+    if (pplayer->player_no != game.info.player_idx
+        && game.info.is_new_game) {
       entry = gtk_menu_item_new_with_label(_("Remove player"));
       g_object_set_data_full(G_OBJECT(menu), "remove", entry,
                             (GtkDestroyNotify) gtk_widget_unref);
@@ -1527,10 +1560,10 @@
   g_signal_connect(button, "clicked",
       G_CALLBACK(main_callback), NULL);
 
-  button = gtk_stockbutton_new(GTK_STOCK_PROPERTIES, _("Pick _Nation"));
-  g_signal_connect(button, "clicked",
+  nation_button = gtk_stockbutton_new(GTK_STOCK_PROPERTIES, _("Pick _Nation"));
+  g_signal_connect(nation_button, "clicked",
                   G_CALLBACK(pick_nation_callback), NULL);
-  gtk_container_add(GTK_CONTAINER(bbox), button);
+  gtk_container_add(GTK_CONTAINER(bbox), nation_button);
 
   take_button = gtk_stockbutton_new(GTK_STOCK_ZOOM_IN, _("_Observe"));
   g_signal_connect(take_button, "clicked",
Index: client/gui-gtk-2.0/pages.h
===================================================================
--- client/gui-gtk-2.0/pages.h  (revision 11842)
+++ client/gui-gtk-2.0/pages.h  (working copy)
@@ -20,7 +20,7 @@
 #include "pages_g.h"
 
 extern GtkWidget *start_message_area;
-extern GtkWidget *take_button, *ready_button;
+extern GtkWidget *take_button, *ready_button, *nation_button;
 extern GtkTreeViewColumn *rating_col, *record_col;
 
 GtkWidget *create_main_page(void);

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Re: (PR#16459) Lots of conndlg errors, Per I. Mathisen <=