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

The working patch for trunk handles all the above issues.  (The patch
for S2_1 differs in 2 lines, but we're waiting for a beta release.)


Index: client/control.c
===================================================================
--- client/control.c    (revision 13376)
+++ client/control.c    (working copy)
@@ -1036,18 +1036,18 @@
 **************************************************************************/
 void request_unit_connect(enum unit_activity activity)
 {
-  if (!can_units_do_connect(get_units_in_focus(), activity)) {
+  struct unit_list *punits = get_units_in_focus();
+
+  if (!can_units_do_connect(punits, activity)) {
     return;
   }
 
   if (hover_state != HOVER_CONNECT || connect_activity != activity) {
-    /* Enter or change the hover connect state. */
-    set_hover_state(get_units_in_focus(), HOVER_CONNECT,
-                   activity, ORDER_LAST);
-    update_unit_info_label(get_units_in_focus());
-
-    enter_goto_state(get_units_in_focus());
+    set_hover_state(punits, HOVER_CONNECT, activity, ORDER_LAST);
+    enter_goto_state(punits);
     create_line_at_mouse_pos();
+    update_unit_info_label(punits);
+    handle_mouse_cursor(NULL);
   } else {
     assert(goto_is_active());
     goto_add_waypoint();
@@ -2078,20 +2078,16 @@
 }
 
 /**************************************************************************
- Finish the goto mode and let the unit which is stored in hover_unit move
+ Finish the goto mode and let the units stored in hover_units move
  to a given location.
 **************************************************************************/
 void do_unit_goto(struct tile *ptile)
 {
-  struct tile *dest_tile;
-
   if (hover_state != HOVER_GOTO && hover_state != HOVER_NUKE) {
     return;
   }
 
-  draw_line(ptile);
-  dest_tile = get_line_dest();
-  if (ptile == dest_tile) {
+  if (is_valid_goto_draw_line(ptile)) {
     send_goto_route();
   } else {
     create_event(ptile, E_BAD_COMMAND,
@@ -2120,15 +2116,11 @@
 **************************************************************************/
 void do_unit_patrol_to(struct tile *ptile)
 {
-  struct tile *dest_tile;
-
-  draw_line(ptile);
-  dest_tile = get_line_dest();
-  if (ptile == dest_tile
+  if (is_valid_goto_draw_line(ptile)
       && !is_non_allied_unit_tile(ptile, game.player_ptr)) {
     send_patrol_route();
   } else {
-    create_event(dest_tile, E_BAD_COMMAND,
+    create_event(ptile, E_BAD_COMMAND,
                 _("Didn't find a route to the destination!"));
   }
 
@@ -2141,11 +2133,7 @@
 void do_unit_connect(struct tile *ptile,
                     enum unit_activity activity)
 {
-  struct tile *dest_tile;
-
-  draw_line(ptile);
-  dest_tile = get_line_dest();
-  if (same_pos(dest_tile, ptile)) {
+  if (is_valid_goto_draw_line(ptile)) {
     send_connect_route(activity);
   } else {
     create_event(ptile, E_BAD_COMMAND,
@@ -2164,9 +2152,14 @@
 
   cancel_tile_hiliting();
 
-  if (hover_state == HOVER_GOTO || hover_state == HOVER_PATROL) {
+  switch (hover_state) {
+  case HOVER_GOTO:
+  case HOVER_PATROL:
+  case HOVER_CONNECT:
     popped = goto_pop_waypoint();
-  }
+  default:
+    break;
+  };
 
   if (hover_state != HOVER_NONE && !popped) {
     set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
Index: client/text.c
===================================================================
--- client/text.c       (revision 13376)
+++ client/text.c       (working copy)
@@ -699,8 +699,9 @@
   if (count > 0 && unit_list_size(hover_units) > 0) {
     int min, max;
 
-    goto_get_turns(&min, &max);
-    if (min == max) {
+    if (!goto_get_turns(&min, &max)) {
+      astr_add_line(&str, _("Turns to target: %d"), min);
+    } else if (min == max) {
       astr_add_line(&str, _("Turns to target: %d"), max);
     } else {
       astr_add_line(&str, _("Turns to target: %d to %d"), min, max);
Index: client/goto.c
===================================================================
--- client/goto.c       (revision 13376)
+++ client/goto.c       (working copy)
@@ -39,9 +39,9 @@
 #define PACKET_LOG_LEVEL        LOG_DEBUG
 
 /*
- * The whole path is seperated by waypoints into parts. The number of parts is
- * number of waypoints + 1.  Each part has its own starting position and 
- * therefore requires it's own map.
+ * The whole path is separated by waypoints into parts.  Each part has its
+ * own starting position and requires its own map.  When the unit is unable
+ * to move, end_tile equals start_tile.
  */
 struct part {
   int start_moves_left, start_fuel_left;
@@ -62,14 +62,17 @@
  *   only one has number less than 4
  * 2. There _can_ be more than one line drawn between two tiles, because of 
  * the waypoints. */
-static struct {
+struct goto_tiles {
   unsigned char drawn[4];
-} *tiles;
+};
+static struct goto_tiles *tiles = NULL;
 
 struct goto_map {
-  int unit_id;                  /* The unit of the goto map */
   struct part *parts;
   int num_parts;
+  int unit_id;                  /* One of the hover_units */
+  int connect_initial;
+  int connect_speed;
   struct pf_parameter template;
 };
 
@@ -85,7 +88,7 @@
 /* Iterate over goto maps, filtering out dead units. */
 #define goto_map_iterate(gotolist, pgoto, punit)                           \
   goto_map_list_iterate(gotolist, pgoto) {                                 \
-    struct unit *punit = game_find_unit_by_number(pgoto->unit_id);             
    \
+    struct unit *punit = game_find_unit_by_number(pgoto->unit_id);         \
                                                                            \
     if (punit) {                                                           \
       assert(unit_is_in_focus(punit));                                     \
@@ -96,7 +99,7 @@
     }                                                                      \
   } goto_map_list_iterate_end;
 
-static struct goto_map_list *goto_maps;
+static struct goto_map_list *goto_maps = NULL;
 
 #define DRAWN(ptile, dir) (tiles[(ptile)->index].drawn[dir])
 
@@ -108,10 +111,7 @@
 /**************************************************************************
   Various stuff for the goto routes
 **************************************************************************/
-static bool is_active = FALSE;
-static bool is_init = FALSE;
-static bool is_goto_valid = FALSE;
-static int connect_initial;
+static struct tile *goto_destination = NULL;
 
 /****************************************************************************
   Create a new goto map.
@@ -123,6 +123,8 @@
   goto_map->unit_id = -1;
   goto_map->parts = NULL;
   goto_map->num_parts = 0;
+  goto_map->connect_initial = 0;
+  goto_map->connect_speed = 0;
 
   return goto_map;
 }
@@ -139,62 +141,55 @@
 }
 
 /********************************************************************** 
-  Called once per game.
+  Called only by handle_map_info() in client/packhand.c.
 ***********************************************************************/
 void init_client_goto(void)
 {
-  if (is_init) {
-    free_client_goto();
-  }
+  free_client_goto();
 
   goto_maps = goto_map_list_new();
 
-  tiles = fc_malloc(MAP_INDEX_SIZE * sizeof(*tiles));
-  whole_map_iterate(ptile) {
-    int dir;
-
-    for (dir = 0; dir < 4; dir++) {
-      DRAWN(ptile, dir) = 0;
-    }
-  } whole_map_iterate_end;
-
-  is_init = TRUE;
+  tiles = fc_calloc(MAP_INDEX_SIZE, sizeof(*tiles));
 }
 
 /********************************************************************** 
-  Deallocate goto structures.
+  Called above, and by client_game_free() in client/civclient.c.
 ***********************************************************************/
 void free_client_goto(void)
 {
-  if (is_init) {
+  if (NULL != goto_maps) {
     goto_map_list_iterate(goto_maps, goto_map) {
       goto_map_free(goto_map);
     } goto_map_list_iterate_end;
     goto_map_list_unlink_all(goto_maps);
     goto_map_list_free(goto_maps);
+    goto_maps = NULL;
+  }
 
+  if (NULL != tiles) {
     free(tiles);
-
-    is_init = FALSE;
+    tiles = NULL;
   }
 }
 
 /**********************************************************************
   Determines if a goto to the destination tile is allowed.
 ***********************************************************************/
-bool is_valid_goto_destination(struct tile *ptile) 
+bool is_valid_goto_destination(const struct tile *ptile) 
 {
-  return is_goto_valid;
+  return (NULL != goto_destination && ptile == goto_destination);
 }
 
 /********************************************************************** 
-  Change the destination of the last part to the given position if a
-  path can be found. If not the destination is set to the start.
+  Change the destination of the last part to the given location.
+  If a path cannot be found, the destination is set to the start.
+  Return TRUE when the new path is valid.
 ***********************************************************************/
-static void update_last_part(struct goto_map *goto_map, struct tile *ptile)
+static bool update_last_part(struct goto_map *goto_map,
+                            struct tile *ptile)
 {
+  struct pf_path *new_path;
   struct part *p = &goto_map->parts[goto_map->num_parts - 1];
-  struct pf_path *new_path;
   struct tile *old_tile = p->start_tile;
   int i, start_index = 0;
 
@@ -202,12 +197,10 @@
           TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
   new_path = pf_get_path(p->map, ptile);
 
-  is_goto_valid = (new_path != NULL);
-
   if (!new_path) {
     freelog(PATH_LOG_LEVEL, "  no path found");
     reset_last_part(goto_map);
-    return;
+    return FALSE;
   }
 
   freelog(PATH_LOG_LEVEL, "  path found:");
@@ -265,11 +258,11 @@
     int moves = pf_last_position(p->path)->total_MC;
 
     p->time = moves / move_rate;
-    if (connect_initial > 0) {
-      p->time += connect_initial;
+    if (goto_map->connect_initial > 0) {
+      p->time += goto_map->connect_initial;
     }
     freelog(PATH_LOG_LEVEL, "To (%d,%d) MC: %d, connect_initial: %d",
-           TILE_XY(ptile), moves, connect_initial);
+           TILE_XY(ptile), moves, goto_map->connect_initial);
   } else {
     p->time = pf_last_position(p->path)->turn;
   }
@@ -277,6 +270,7 @@
   /* Refresh tiles so turn information is shown. */
   refresh_tile_mapcanvas(old_tile, FALSE, FALSE);
   refresh_tile_mapcanvas(ptile, FALSE, FALSE);
+  return TRUE;
 }
 
 /********************************************************************** 
@@ -356,17 +350,35 @@
 /********************************************************************** 
   Inserts a waypoint at the end of the current goto line.
 ***********************************************************************/
-void goto_add_waypoint(void)
+bool goto_add_waypoint(void)
 {
-  assert(is_active);
+  struct tile *ptile_start = NULL;
+
+  assert(goto_is_active());
+  if (NULL == goto_destination) {
+    /* Not a valid position. */
+    return FALSE;
+  }
+
   goto_map_iterate(goto_maps, goto_map, punit) {
-    struct part *p = &goto_map->parts[goto_map->num_parts - 1];
+    struct part *first_part = &goto_map->parts[0];
+    struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
 
-    if (!same_pos(p->start_tile, p->end_tile)) {
-      /* Otherwise the last part has zero length. */
-      add_part(goto_map);
+    if (same_pos(last_part->start_tile, last_part->end_tile)) {
+      /* The current part has zero length. */
+      return FALSE;
+    } else if (NULL == ptile_start) {
+      ptile_start = first_part->start_tile;
+    } else if (ptile_start != first_part->start_tile) {
+      /* Scattered group (not all in same location). */
+      return FALSE;
     }
   } goto_map_iterate_end;
+
+  goto_map_iterate(goto_maps, goto_map, punit) {
+    add_part(goto_map);
+  } goto_map_iterate_end;
+  return TRUE;
 }
 
 /********************************************************************** 
@@ -377,7 +389,7 @@
 {
   bool popped = FALSE;
 
-  assert(is_active);
+  assert(goto_is_active());
   goto_map_iterate(goto_maps, goto_map, punit) {
     struct part *p = &goto_map->parts[goto_map->num_parts - 1];
     struct tile *end_tile = p->end_tile;
@@ -722,16 +734,18 @@
   Fill the PF parameter with the correct client-goto values.
 ***********************************************************************/
 static void fill_client_goto_parameter(struct unit *punit,
-                                      struct pf_parameter *parameter)
+                                      struct pf_parameter *parameter,
+                                      int *connect_initial,
+                                      int *connect_speed)
 {
-  static int speed;
-
   pft_fill_unit_parameter(parameter, punit);
   assert(parameter->get_EC == NULL);
   parameter->get_EC = get_EC;
   assert(parameter->get_TB == NULL);
   assert(parameter->get_MC != NULL);
-  if (hover_state == HOVER_CONNECT) {
+
+  switch (hover_state) {
+  case HOVER_CONNECT:
     if (connect_activity == ACTIVITY_IRRIGATE) {
       parameter->get_costs = get_connect_irrig;
     } else {
@@ -739,22 +753,29 @@
     }
     parameter->is_pos_dangerous = NULL;
 
-    speed = get_activity_rate(punit) / ACTIVITY_FACTOR;
-    parameter->data = &speed;
+    *connect_speed = get_activity_rate(punit) / ACTIVITY_FACTOR;
+    parameter->data = connect_speed;
 
     /* Take into account the activity time at the origin */
-    connect_initial = get_activity_time(punit->tile, 
-                                        unit_owner(punit)) / speed;
-    assert(connect_initial >= 0);
-    if (connect_initial > 0) {
+    *connect_initial = get_activity_time(punit->tile, unit_owner(punit))
+                     / *connect_speed;
+    if (*connect_initial > 0) {
       parameter->moves_left_initially = 0;
       if (punit->moves_left == 0) {
-       connect_initial++;
+       *connect_initial += 1;
       }
-    } /* otherwise moves_left_initially = punit->moves_left (default) */
-  } else if (hover_state == HOVER_NUKE) {
+    } else {
+      /* otherwise moves_left_initially = punit->moves_left (default) */
+      assert(*connect_initial == 0);
+    }
+    break;
+  case HOVER_NUKE:
     parameter->is_pos_dangerous = NULL; /* nuclear safety? pwah! */
-  }
+    /* FALLTHRU */
+  default:
+    *connect_initial = 0;
+    break;
+  };
 
   if (is_attack_unit(punit) || is_diplomat_unit(punit)) {
     parameter->get_TB = get_TB_aggr;
@@ -783,8 +804,7 @@
 ***********************************************************************/
 void enter_goto_state(struct unit_list *punits)
 {
-  assert(!is_active);
-  assert(goto_map_list_size(goto_maps) == 0);
+  assert(!goto_is_active());
 
   /* Can't have selection rectangle and goto going on at the same time. */
   cancel_selection_rectangle();
@@ -793,15 +813,15 @@
     struct goto_map *goto_map = goto_map_new();
 
     goto_map->unit_id = punit->id;
-    assert(goto_map->num_parts == 0);
 
-    fill_client_goto_parameter(punit, &goto_map->template);
+    fill_client_goto_parameter(punit, &goto_map->template,
+                               &goto_map->connect_initial,
+                               &goto_map->connect_speed);
 
     add_part(goto_map);
 
     goto_map_list_append(goto_maps, goto_map);
   } unit_list_iterate_end;
-  is_active = TRUE;
 }
 
 /********************************************************************** 
@@ -809,7 +829,7 @@
 ***********************************************************************/
 void exit_goto_state(void)
 {
-  if (!is_active) {
+  if (!goto_is_active()) {
     return;
   }
 
@@ -821,7 +841,7 @@
   } goto_map_list_iterate_end;
   goto_map_list_unlink_all(goto_maps);
 
-  is_active = FALSE;
+  goto_destination = NULL;
 }
 
 /********************************************************************** 
@@ -829,28 +849,14 @@
 ***********************************************************************/
 bool goto_is_active(void)
 {
-  return is_active;
+  return (NULL != goto_maps && 0 != goto_map_list_size(goto_maps));
 }
 
-/********************************************************************** 
-  Return the current end of the drawn goto line.
-***********************************************************************/
-struct tile *get_line_dest(void)
-{
-  if (is_active) {
-    struct goto_map *goto_map = goto_map_list_get(goto_maps, 0);
-    struct part *p = &goto_map->parts[goto_map->num_parts - 1];
-
-    return p->end_tile;
-  } else {
-    return NULL;
-  }
-}
-
 /**************************************************************************
   Return the path length (in turns).
+  WARNING: not useful for determining paths of scattered groups.
 ***************************************************************************/
-void goto_get_turns(int *min, int *max)
+bool goto_get_turns(int *min, int *max)
 {
   if (min) {
     *min = FC_INFINITY;
@@ -858,22 +864,29 @@
   if (max) {
     *max = -1;
   }
-  if (is_active) {
-    goto_map_iterate(goto_maps, goto_map, punit) {
-      int time = 0, i;
+  if (!goto_is_active()) {
+    return FALSE;
+  }
+  if (NULL == goto_destination) {
+    /* Not a valid position. */
+    return FALSE;
+  }
 
-      for (i = 0; i < goto_map->num_parts; i++) {
-       time += goto_map->parts[i].time;
-      }
+  goto_map_iterate(goto_maps, goto_map, punit) {
+    int i, time = 0;
 
-      if (min) {
-       *min = MIN(*min, time);
-      }
-      if (max) {
-       *max = MAX(*max, time);
-      }
-    } goto_map_iterate_end;
-  }
+    for (i = 0; i < goto_map->num_parts; i++) {
+      time += goto_map->parts[i].time;
+    }
+
+    if (min) {
+      *min = MIN(*min, time);
+    }
+    if (max) {
+      *max = MAX(*max, time);
+    }
+  } goto_map_iterate_end;
+  return TRUE;
 }
 
 /********************************************************************** 
@@ -881,16 +894,25 @@
   goto_map.
   If there is no route to the dest then don't draw anything.
 ***********************************************************************/
-void draw_line(struct tile *dest_tile)
+bool is_valid_goto_draw_line(struct tile *dest_tile)
 {
-  assert(is_active);
+  assert(goto_is_active());
+  if (NULL == dest_tile) {
+    return FALSE;
+  }
 
+  /* assume valid destination */
+  goto_destination = dest_tile;
+
   goto_map_iterate(goto_maps, goto_map, punit) {
-    update_last_part(goto_map, dest_tile);
+    if (!update_last_part(goto_map, dest_tile)) {
+      goto_destination = NULL;
+    }
   } goto_map_iterate_end;
 
   /* Update goto data in info label. */
   update_unit_info_label(get_units_in_focus());
+  return (NULL != goto_destination);
 }
 
 /****************************************************************************
@@ -994,11 +1016,12 @@
 ****************************************************************************/
 bool send_goto_tile(struct unit *punit, struct tile *ptile)
 {
+  int dummy1, dummy2;
   struct pf_parameter parameter;
   struct pf_map *map;
   struct pf_path *path = NULL;
 
-  fill_client_goto_parameter(punit, &parameter);
+  fill_client_goto_parameter(punit, &parameter, &dummy1, &dummy2);
   map = pf_create_map(&parameter);
 
   pf_iterator(map, pos) {
@@ -1023,18 +1046,23 @@
 **************************************************************************/
 void send_patrol_route(void)
 {
-  assert(is_active);
+  assert(goto_is_active());
   goto_map_iterate(goto_maps, goto_map, punit) {
     int i;
-    struct pf_path *path = NULL, *return_path;
+    struct pf_map *map;
+    struct pf_path *return_path;
+    struct pf_path *path = NULL;
     struct pf_parameter parameter = goto_map->template;
-    struct pf_map *map;
+    struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
 
-    parameter.start_tile = goto_map->parts[goto_map->num_parts - 1].end_tile;
-    parameter.moves_left_initially
-      = goto_map->parts[goto_map->num_parts - 1].end_moves_left;
-    parameter.fuel_left_initially
-      = goto_map->parts[goto_map->num_parts - 1].end_fuel_left;
+    if (last_part->end_tile == last_part->start_tile) {
+      /* Cannot move there */
+      continue;
+    }
+
+    parameter.start_tile = last_part->end_tile;
+    parameter.moves_left_initially = last_part->end_moves_left;
+    parameter.fuel_left_initially = last_part->end_fuel_left;
     map = pf_create_map(&parameter);
     return_path = pf_get_path(map, goto_map->parts[0].start_tile);
     if (!return_path) {
@@ -1061,13 +1089,19 @@
 **************************************************************************/
 void send_connect_route(enum unit_activity activity)
 {
-  assert(is_active);
+  assert(goto_is_active());
   goto_map_iterate(goto_maps, goto_map, punit) {
-    struct pf_path *path = NULL;
     int i;
     struct packet_unit_orders p;
     struct tile *old_tile;
+    struct pf_path *path = NULL;
+    struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
 
+    if (last_part->end_tile == last_part->start_tile) {
+      /* Cannot move there */
+      continue;
+    }
+
     memset(&p, 0, sizeof(p));
 
     for (i = 0; i < goto_map->num_parts; i++) {
@@ -1142,11 +1176,17 @@
 **************************************************************************/
 void send_goto_route(void)
 {
-  assert(is_active);
+  assert(goto_is_active());
   goto_map_iterate(goto_maps, goto_map, punit) {
+    int i;
     struct pf_path *path = NULL;
-    int i;
+    struct part *last_part = &goto_map->parts[goto_map->num_parts - 1];
 
+    if (last_part->end_tile == last_part->start_tile) {
+      /* Cannot move there */
+      continue;
+    }
+
     for (i = 0; i < goto_map->num_parts; i++) {
       path = pft_concat(path, goto_map->parts[i].path);
     }
@@ -1250,17 +1290,18 @@
 ***************************************************************************/
 struct pf_path *path_to_nearest_allied_city(struct unit *punit)
 {
-  struct city *pcity = NULL;
+  int dummy1, dummy2;
   struct pf_parameter parameter;
   struct pf_map *map;
   struct pf_path *path = NULL;
+  struct city *pcity = is_allied_city_tile(punit->tile, punit->owner);
 
-  if ((pcity = is_allied_city_tile(punit->tile, punit->owner))) {
+  if (pcity) {
     /* We're already on a city - don't go anywhere. */
     return NULL;
   }
 
-  fill_client_goto_parameter(punit, &parameter);
+  fill_client_goto_parameter(punit, &parameter, &dummy1, &dummy2);
   map = pf_create_map(&parameter);
 
   while (pf_next(map)) {
Index: client/goto.h
===================================================================
--- client/goto.h       (revision 13376)
+++ client/goto.h       (working copy)
@@ -21,18 +21,16 @@
 void free_client_goto(void);
 void enter_goto_state(struct unit_list *punits);
 void exit_goto_state(void);
+
 bool goto_is_active(void);
-struct tile *get_line_dest(void);
-void goto_get_turns(int *min, int *max);
-void goto_add_waypoint(void);
+bool goto_get_turns(int *min, int *max);
+bool goto_add_waypoint(void);
 bool goto_pop_waypoint(void);
-bool is_valid_goto_destination(struct tile *ptile);
 
-void draw_line(struct tile *dest_tile);
+bool is_valid_goto_destination(const struct tile *ptile);
+bool is_valid_goto_draw_line(struct tile *dest_tile);
 bool is_drawn_line(struct tile *dest_tile, int dir);
  
-bool is_endpoint(struct tile *ptile);
-
 void request_orders_cleared(struct unit *punit);
 void send_goto_path(struct unit *punit, struct pf_path *path,
                    struct unit_order *last_order);
Index: client/gui-sdl/mapview.c
===================================================================
--- client/gui-sdl/mapview.c    (revision 13376)
+++ client/gui-sdl/mapview.c    (working copy)
@@ -553,8 +553,9 @@
   if (count > 0 && unit_list_size(hover_units) > 0) {
     int min, max;
 
-    goto_get_turns(&min, &max);
-    if (min == max) {
+    if (!goto_get_turns(&min, &max)) {
+      astr_add_line(&str, _("Turns to target: %d"), min);
+    } else if (min == max) {
       astr_add_line(&str, _("Turns to target: %d"), max);
     } else {
       astr_add_line(&str, _("Turns to target: %d to %d"), min, max);
Index: client/tilespec.c
===================================================================
--- client/tilespec.c   (revision 13376)
+++ client/tilespec.c   (working copy)
@@ -4159,15 +4159,10 @@
 {
   struct drawn_sprite *saved_sprs = sprs;
 
-  if (!goto_is_active()) {
-    return 0;
-  }
-  if (ptile && ptile == get_line_dest()) {
+  if (is_valid_goto_destination(ptile)) {
     int length, units, tens;
 
     goto_get_turns(NULL, &length);
-    units = length % NUM_TILES_DIGITS;
-    tens = (length / 10) % NUM_TILES_DIGITS;
     if (length < 0 || length >= 100) {
       static bool reported = FALSE;
 
@@ -4178,6 +4173,9 @@
        reported = TRUE;
       }
       tens = units = 9;
+    } else {
+      tens = (length / 10) % NUM_TILES_DIGITS;
+      units = length % NUM_TILES_DIGITS;
     }
 
     ADD_SPRITE_SIMPLE(t->sprites.path.turns[units]);
@@ -4482,7 +4480,9 @@
     break;
 
   case LAYER_GOTO:
-    sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
+    if (ptile && goto_is_active()) {
+      sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
+    }
     break;
 
   case LAYER_COUNT:
Index: client/mapctrl_common.c
===================================================================
--- client/mapctrl_common.c     (revision 13376)
+++ client/mapctrl_common.c     (working copy)
@@ -654,21 +654,18 @@
 **************************************************************************/
 void update_line(int canvas_x, int canvas_y)
 {
-  if (hover_state == HOVER_GOTO
-      || hover_state == HOVER_PATROL
-      || hover_state == HOVER_CONNECT) {
-    struct tile *ptile, *old_tile;
+  struct tile *ptile;
 
+  switch (hover_state) {
+  case HOVER_GOTO:
+  case HOVER_PATROL:
+  case HOVER_CONNECT:
     ptile = canvas_pos_to_tile(canvas_x, canvas_y);
-    if (!ptile) {
-      return;
-    }
 
-    old_tile = get_line_dest();
-    if (!same_pos(old_tile, ptile)) {
-      draw_line(ptile);
-    }
-  }
+    is_valid_goto_draw_line(ptile);
+  default:
+    break;
+  };
 }
 
 /****************************************************************************
@@ -676,20 +673,20 @@
 ****************************************************************************/
 void overview_update_line(int overview_x, int overview_y)
 {
-  if (hover_state == HOVER_GOTO
-      || hover_state == HOVER_PATROL
-      || hover_state == HOVER_CONNECT) {
-    struct tile *ptile, *old_tile;
-    int x, y;
+  struct tile *ptile;
+  int x, y;
 
+  switch (hover_state) {
+  case HOVER_GOTO:
+  case HOVER_PATROL:
+  case HOVER_CONNECT:
     overview_to_map_pos(&x, &y, overview_x, overview_y);
     ptile = map_pos_to_tile(x, y);
 
-    old_tile = get_line_dest();
-    if (!same_pos(ptile, old_tile)) {
-      draw_line(ptile);
-    }
-  }
+    is_valid_goto_draw_line(ptile);
+  default:
+    break;
+  };
 }
 
 /****************************************************************************
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to