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

Not the way I'd planned to spend my Wednesday evening, but here's the
minimal backport from S2_2 to S2_1 that fixes the crash.  In addition, it
should handle all the other potential bugs reported on this ticket
concerning leaving and starting another game (without quitting the client).
Obviously not a code path that was well tested....  Committing immediately,
and I'd appreciate independent testing, please.

Committed S2_1 revision 14139.
Committed S2_2 revision 14140.
Committed trunk revision 14141.

Index: client/control.c
===================================================================
--- client/control.c    (revision 14138)
+++ client/control.c    (working copy)
@@ -62,11 +62,11 @@
 
 /* These should be set via set_hover_state() */
 enum cursor_hover_state hover_state = HOVER_NONE;
-struct tile *hover_tile = NULL;
 enum cursor_action_state action_state = CURSOR_ACTION_DEFAULT;
 enum unit_activity connect_activity;
 enum unit_orders goto_last_order; /* Last order for goto */
 
+static struct tile *hover_tile = NULL;
 static struct unit_list *battlegroups[MAX_NUM_BATTLEGROUPS];
 
 /* units involved in current combat */
@@ -89,7 +89,7 @@
                                 enum quickselect_type qtype);
 
 /**************************************************************************
-  Called only by main() in client/civclient.c.
+  Called only by client_game_init() in client/civclient.c
 **************************************************************************/
 void control_init(void)
 {
@@ -105,10 +105,11 @@
   for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
     battlegroups[i] = unit_list_new();
   }
+  hover_tile = NULL;
 }
 
 /**************************************************************************
-  Called only by client_exit() in client/civclient.c.
+  Called only by client_game_free() in client/civclient.c
 **************************************************************************/
 void control_done(void)
 {
@@ -124,6 +125,7 @@
   for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
     unit_list_free(battlegroups[i]);
   }
+  free_client_goto();
 }
 
 /**************************************************************************
@@ -896,7 +898,7 @@
     enter_goto_state(punits);
     create_line_at_mouse_pos();
     update_unit_info_label(punits);
-    handle_mouse_cursor(NULL);
+    control_mouse_cursor(NULL);
   } else {
     assert(goto_is_active());
     goto_add_waypoint();
@@ -923,12 +925,17 @@
   and the information gathered from the tile which is under the mouse 
   cursor (ptile).
 **************************************************************************/
-void handle_mouse_cursor(struct tile *ptile)
+void control_mouse_cursor(struct tile *ptile)
 {
   struct unit *punit = NULL;
   struct city *pcity = NULL;
   struct unit_list *active_units = get_units_in_focus();
 
+  if (C_S_RUNNING != client_state()) {
+    action_state = CURSOR_ACTION_DEFAULT;
+    return;
+  }
+
   if (is_server_busy()) {
     /* Server will not accept any commands. */
     action_state = CURSOR_ACTION_WAIT;
@@ -938,11 +945,14 @@
 
   if (!ptile) {
     if (hover_tile) {
-      /* hover_tile is the tile which is currently under the mouse cursor. */
+      /* hover_tile is the tile that was previously under the mouse cursor. */
       ptile = hover_tile;
     } else {
+      action_state = CURSOR_ACTION_DEFAULT;
       return;
     }
+  } else {
+    hover_tile = ptile;
   }
 
   punit = find_visible_unit(ptile);
@@ -991,8 +1001,6 @@
     /* FIXME */
     break;
   };
-
-  update_unit_info_label(active_units);
 }
 
 /**************************************************************************
@@ -1076,7 +1084,7 @@
     enter_goto_state(punits);
     create_line_at_mouse_pos();
     update_unit_info_label(punits);
-    handle_mouse_cursor(NULL);
+    control_mouse_cursor(NULL);
   } else {
     assert(goto_is_active());
     goto_add_waypoint();
Index: client/gui-gtk-2.0/mapview.c
===================================================================
--- client/gui-gtk-2.0/mapview.c        (revision 14138)
+++ client/gui-gtk-2.0/mapview.c        (working copy)
@@ -178,7 +178,7 @@
 
   gdk_window_set_cursor(root_window,
                 fc_cursors[cursor_type][cursor_frame]);
-  handle_mouse_cursor(NULL);
+  control_mouse_cursor(NULL);
   return TRUE;
 }
 
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
--- client/gui-gtk-2.0/gui_main.c       (revision 14138)
+++ client/gui-gtk-2.0/gui_main.c       (working copy)
@@ -607,7 +607,6 @@
 static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev)
 {
   int scroll_x, scroll_y, xstep, ystep;
-  struct tile *ptile = NULL;
 
   if (!can_client_change_view()) {
     return FALSE;
@@ -647,9 +646,7 @@
     maybe_activate_keyboardless_goto(cur_x, cur_y);
   }
 
-  ptile = canvas_pos_to_tile(cur_x, cur_y);
-  handle_mouse_cursor(ptile);
-  hover_tile = ptile;
+  control_mouse_cursor(canvas_pos_to_tile(cur_x, cur_y));
 
   return TRUE;
 }
Index: client/gui-gtk-2.0/mapctrl.c
===================================================================
--- client/gui-gtk-2.0/mapctrl.c        (revision 14138)
+++ client/gui-gtk-2.0/mapctrl.c        (working copy)
@@ -370,8 +370,6 @@
 **************************************************************************/
 gboolean move_mapcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
 {
-  struct tile *ptile = NULL;
-
   if (!GTK_WIDGET_HAS_FOCUS(map_canvas)) {
     gtk_widget_grab_focus(map_canvas);
   }
@@ -383,9 +381,7 @@
   if (keyboardless_goto_button_down && hover_state == HOVER_NONE) {
     maybe_activate_keyboardless_goto(ev->x, ev->y);
   }
-  ptile = canvas_pos_to_tile(ev->x, ev->y);
-  handle_mouse_cursor(ptile);
-  hover_tile = ptile;
+  control_mouse_cursor(canvas_pos_to_tile(ev->x, ev->y));
 
   return TRUE;
 }
@@ -396,9 +392,13 @@
 gboolean leave_mapcanvas(GtkWidget *widget, GdkEventCrossing *event)
 {
   int canvas_x, canvas_y;
-  bool map_is_topmost = 
-       (gtk_notebook_get_current_page(GTK_NOTEBOOK(top_notebook))
-       == gtk_notebook_page_num(GTK_NOTEBOOK(top_notebook), map_widget));
+
+  if (gtk_notebook_get_current_page(GTK_NOTEBOOK(top_notebook))
+      != gtk_notebook_page_num(GTK_NOTEBOOK(top_notebook), map_widget)) {
+    /* Map is not currently topmost tab. Do not use tile specific cursors. */
+    action_state = CURSOR_ACTION_DEFAULT;
+    return TRUE;
+  }
   
   /* Bizarrely, this function can be called even when we don't "leave"
    * the map canvas, for instance, it gets called any time the mouse is
@@ -406,14 +406,13 @@
   gdk_window_get_pointer(map_canvas->window, &canvas_x, &canvas_y, NULL);
   if (map_exists()
       && canvas_x >= 0 && canvas_y >= 0
-      && canvas_x < mapview.width && canvas_y < mapview.height
-      && map_is_topmost) {
-    handle_mouse_cursor(canvas_pos_to_tile(canvas_x, canvas_y));
-    /* update_unit_info_label is handled inside handle_mouse_cursor. */
+      && canvas_x < mapview.width && canvas_y < mapview.height) {
+    control_mouse_cursor(canvas_pos_to_tile(canvas_x, canvas_y));
   } else {
     action_state = CURSOR_ACTION_DEFAULT;
-    update_unit_info_label(get_units_in_focus());
   }
+
+  update_unit_info_label(get_units_in_focus());
   return TRUE;
 }
 
Index: client/control.h
===================================================================
--- client/control.h    (revision 14138)
+++ client/control.h    (working copy)
@@ -53,8 +53,6 @@
 extern enum unit_orders goto_last_order;
 extern bool non_ai_unit_focus;
 
-extern struct tile *hover_tile;
-
 bool can_unit_do_connect(struct unit *punit, enum unit_activity activity);
 
 void do_move_unit(struct unit *punit, struct unit *target_unit);
@@ -65,7 +63,7 @@
 void do_unit_connect(struct tile *ptile,
                     enum unit_activity activity);
 void do_map_click(struct tile *ptile, enum quickselect_type qtype);
-void handle_mouse_cursor(struct tile *ptile);
+void control_mouse_cursor(struct tile *ptile);
 
 void set_hover_state(struct unit_list *punits, enum cursor_hover_state state,
                     enum unit_activity connect_activity,
Index: client/gui-win32/mapctrl.c
===================================================================
--- client/gui-win32/mapctrl.c  (revision 14138)
+++ client/gui-win32/mapctrl.c  (working copy)
@@ -61,13 +61,9 @@
 *************************************************************************/
 void map_handle_move(int window_x, int window_y)
 {
-  struct tile *ptile = NULL;
-
   update_line(window_x, window_y);
 
-  ptile = canvas_pos_to_tile(window_x, window_y);
-  handle_mouse_cursor(ptile);
-  hover_tile = ptile;
+  control_mouse_cursor(canvas_pos_to_tile(window_x, window_y));
 }
 
 /*************************************************************************
Index: client/goto.c
===================================================================
--- client/goto.c       (revision 14138)
+++ client/goto.c       (working copy)
@@ -151,7 +151,7 @@
 }
 
 /********************************************************************** 
-  Called above, and by client_game_free() in client/civclient.c.
+  Called above, and by control_done() in client/control.c.
 ***********************************************************************/
 void free_client_goto(void)
 {
@@ -840,7 +840,7 @@
 }
 
 /********************************************************************** 
-  Called from control_unit_killed() in control.c
+  Called from control_unit_killed() in client/control.c
 ***********************************************************************/
 void goto_unit_killed(struct unit *punit)
 {
Index: client/gui-sdl/gui_main.c
===================================================================
--- client/gui-sdl/gui_main.c   (revision 14138)
+++ client/gui-sdl/gui_main.c   (working copy)
@@ -409,12 +409,7 @@
     if (pSellected_Widget) {
       unsellect_widget_action();
     } else {
-      if (C_S_RUNNING == client_state()) {
-        struct tile *ptile = canvas_pos_to_tile(pMotionEvent->x, 
pMotionEvent->y);
-
-        handle_mouse_cursor(ptile);
-        hover_tile = ptile;
-      }
+      control_mouse_cursor(canvas_pos_to_tile(pMotionEvent->x, 
pMotionEvent->y));
     }
   }
 
Index: client/civclient.c
===================================================================
--- client/civclient.c  (revision 14138)
+++ client/civclient.c  (working copy)
@@ -61,7 +61,6 @@
 #include "dialogs_g.h"
 #include "diplodlg_g.h"
 #include "ggzclient.h"
-#include "goto.h"
 #include "gui_main_g.h"
 #include "helpdata.h"          /* boot_help_texts() */
 #include "mapctrl_g.h"
@@ -177,6 +176,29 @@
 }
 
 /**************************************************************************
+  Called only by set_client_state() below.
+**************************************************************************/
+static void client_game_init(void)
+{
+  game_init();
+  attribute_init();
+  agents_init();
+  control_init();
+}
+
+/**************************************************************************
+  Called by set_client_state() and client_exit() below.
+**************************************************************************/
+static void client_game_free(void)
+{
+  control_done();
+  free_help_texts();
+  attribute_free();
+  agents_free();
+  game_free();
+}
+
+/**************************************************************************
 ...
 **************************************************************************/
 int main(int argc, char *argv[])
@@ -365,7 +387,6 @@
   /* This seed is not saved anywhere; randoms in the client should
      have cosmetic effects only (eg city name suggestions).  --dwp */
   mysrand(time(NULL));
-  control_init();
   helpdata_init();
   boot_help_texts();
 
@@ -402,7 +423,6 @@
   
   ui_exit();
   
-  control_done();
   chatline_common_done();
   message_options_free();
   client_game_free();
@@ -473,30 +493,8 @@
 }
 
 /**************************************************************************
- called whenever client is changed to pre-game state.
-**************************************************************************/
-void client_game_init()
-{
-  game_init();
-  attribute_init();
-  agents_init();
-}
-
-/**************************************************************************
 ...
 **************************************************************************/
-void client_game_free()
-{
-  free_client_goto();
-  free_help_texts();
-  attribute_free();
-  agents_free();
-  game_free();
-}
-
-/**************************************************************************
-...
-**************************************************************************/
 void set_client_state(enum client_states newstate)
 {
   bool connect_error = (C_S_PREPARING == civclient_state)
@@ -531,7 +529,8 @@
       
     civclient_state = newstate;
 
-    if (C_S_RUNNING == civclient_state) {
+    switch (civclient_state) {
+    case C_S_RUNNING:
       init_city_report_game_data();
       load_ruleset_specific_options();
       create_event(NULL, E_GAME_START, _("Game started."));
@@ -545,23 +544,26 @@
       update_unit_focus();
       can_slide = TRUE;
       set_client_page(PAGE_GAME);
-    }
-    else if (C_S_PREPARING == civclient_state) {
+      break;
+    case C_S_PREPARING:
       popdown_all_city_dialogs();
       close_all_diplomacy_dialogs();
       popdown_all_game_dialogs();
-      set_unit_focus(NULL);
       clear_notify_window();
       if (C_S_INITIAL != oldstate) {
        client_game_free();
       }
       client_game_init();
+      set_unit_focus(NULL);
       if (!aconnection.established && !with_ggz) {
        set_client_page(in_ggz ? PAGE_GGZ : PAGE_MAIN);
       } else {
        set_client_page(PAGE_START);
       }
-    }
+      break;
+    default:
+      break;
+    };
     update_menus();
   }
   if (!aconnection.established && C_S_PREPARING == civclient_state) {
@@ -791,7 +793,7 @@
     server_busy = busy;
 
     /* This may mean that we have to change from or to wait cursor */
-    handle_mouse_cursor(NULL);
+    control_mouse_cursor(NULL);
   }
 }
 
Index: client/civclient.h
===================================================================
--- client/civclient.h  (revision 14138)
+++ client/civclient.h  (working copy)
@@ -64,8 +64,6 @@
 bool can_meet_with_player(const struct player *pplayer);
 bool can_intel_with_player(const struct player *pplayer);
 
-void client_game_init(void);
-void client_game_free(void);
 void client_exit(void);
 
 /* Set in GUI code. */
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to