? war.cvs.diff
? client/battlegroups.c
? client/battlegroups.h
? data/isotrident/icons.spec
? data/isotrident/icons.xpm
? data/trident/groups.spec
? data/trident/icons.spec
? data/trident/icons.xpm
Index: client/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/Makefile.am,v
retrieving revision 1.44
diff -u -r1.44 Makefile.am
--- client/Makefile.am	2002/08/24 14:37:32	1.44
+++ client/Makefile.am	2002/10/06 04:59:58
@@ -129,6 +129,8 @@
 civclient_SOURCES = $(ESD_FILES) $(SDL_FILES) $(WINMM_FILES) \
 	attribute.h	\
 	attribute.c	\
+	battlegroups.c  \
+	battlegroups.h  \
 	citydlg_common.c \
 	citydlg_common.h \
 	cityrepdata.c	\
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.148
diff -u -r1.148 civclient.c
--- client/civclient.c	2002/09/28 01:36:19	1.148
+++ client/civclient.c	2002/10/06 05:00:01
@@ -414,7 +414,7 @@
     break;
 
   case PACKET_ADVANCE_FOCUS:
-    handle_advance_focus((struct packet_generic_integer *)packet);
+    /* Server should not decide your focus */
     break;
     
   case PACKET_CONN_INFO:
@@ -537,6 +537,7 @@
 void send_move_unit(struct unit *punit)
 {
   struct packet_move_unit move;
+  punit->never_moved = FALSE;
 
   move.unid=punit->id;
   move.x=punit->x;
@@ -551,6 +552,7 @@
 void send_goto_unit(struct unit *punit, int dest_x, int dest_y)
 {
   struct packet_unit_request req;
+  punit->never_moved = FALSE;
 
   req.unit_id = punit->id;
   req.name[0] = '\0';
Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.104
diff -u -r1.104 climisc.c
--- client/climisc.c	2002/09/19 21:27:27	1.104
+++ client/climisc.c	2002/10/06 05:00:05
@@ -38,6 +38,7 @@
 #include "packets.h"
 #include "support.h"
 
+#include "battlegroups.h"
 #include "citydlg_g.h"
 #include "cityrep_g.h"
 #include "civclient.h"
@@ -220,6 +221,16 @@
   int hc = punit->homecity;
   struct unit *ufocus = get_unit_in_focus();
 
+  if(game.player_idx==punit->owner) {
+      bg_un_target_tile(punit);
+      bg_unassign_unit(punit);
+      if (punit->ai.charge)
+	  clear_bodyguard_relationship(punit, TRUE);
+      if (punit->ai.bodyguard)
+	  clear_bodyguard_relationship(find_unit_by_id(punit->ai.bodyguard),
+				       FALSE);
+  }
+
   freelog(LOG_DEBUG, "removing unit %d, %s %s (%d %d) hcity %d",
 	  punit->id, get_nation_name(unit_owner(punit)->nation),
 	  unit_name(punit->type), punit->x, punit->y, hc);
@@ -228,7 +239,7 @@
     set_unit_focus_no_center(NULL);
     game_remove_unit(punit);
     punit = ufocus = NULL;
-    advance_unit_focus();
+    advance_unit_focus(FALSE);
   } else {
     /* calculate before punit disappears, use after punit removed: */
     bool update = (ufocus
Index: client/clinet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/clinet.c,v
retrieving revision 1.74
diff -u -r1.74 clinet.c
--- client/clinet.c	2002/09/17 13:09:47	1.74
+++ client/clinet.c	2002/10/06 05:00:08
@@ -63,6 +63,7 @@
 #include "version.h"
 #include "hash.h"
 
+#include "battlegroups.h"
 #include "chatline_g.h"
 #include "civclient.h"
 #include "climisc.h"
@@ -97,6 +98,7 @@
   pc->send_buffer = NULL;
 
   remove_net_input();
+  battlegroups_free();  /* does this belong here? */
   popdown_races_dialog(); 
 
   reports_force_thaw();
@@ -209,6 +211,9 @@
 
   /* call gui-dependent stuff in gui_main.c */
   add_net_input(aconnection.sock);
+
+  /* does this belong here? */
+  battlegroups_allocate();
 
   /* now send join_request package */
 
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.84
diff -u -r1.84 control.c
--- client/control.c	2002/09/11 17:04:39	1.84
+++ client/control.c	2002/10/06 05:00:17
@@ -21,6 +21,7 @@
 #include "log.h"
 #include "map.h"
 #include "mem.h"
+#include "support.h"
 
 #include "chatline_g.h"
 #include "citydlg_g.h"
@@ -31,6 +32,7 @@
 #include "mapview_g.h"
 #include "menu_g.h"
 
+#include "battlegroups.h"
 #include "civclient.h"
 #include "clinet.h"
 #include "goto.h"
@@ -57,9 +59,836 @@
 static struct unit *punit_attacking = NULL;
 static struct unit *punit_defending = NULL;
 
+bool batch_command = FALSE;
+
+/* Unit Focusing and Filtering */
+
+static int previous_focus_id = 0;
+
+static const char *focus_category_names[] =
+{
+  N_("Units"),
+  N_("Diplomats"),
+  N_("Caravans"),
+  N_("Settlers"),
+  N_("Airplanes"),
+  N_("Helicopters"),
+  N_("Infantry"),
+  N_("Warships"),
+  N_("Transporters")
+};
+
+enum unit_filter focus_category = FILTER_NORMAL;
+
+bool filter_new               = FALSE;
+bool filter_veteran           = FALSE;
+bool filter_current_location  = FALSE;
+bool filter_radius            = FALSE;
+bool filter_include_sentries  = FALSE;
+bool filter_include_fortified = FALSE;
+bool filter_include_exhausted = FALSE;
+bool filter_include_gotos     = FALSE;
+bool filter_include_members   = FALSE;
+
 /*************************************************************************/
+
+static struct unit *find_best_focus_candidate(int try_harder);
+
+/* firstunit in batch processing */
+static struct unit *fu;
+static int  fx;
+static int  fy;
+static int  ftype;
+static bool fmf;
+static enum mission_orders fo;
+static int  fbg;
+
+static int  count;
+static int  gcount;
+
+static void batch_r_and_r(void);
+static void batch_wait(void);
+static void batch_wakeup(void);
+static void batch_build_wonder(void);
+static void batch_assign(void);
+static void batch_unassign(void);
+static void batch_goto(int x, int y);
+static void batch_automate(void);
+static void batch_sentry(void);
+static void batch_fortify(void);
+static void batch_explore(void);
+static bool common_filters(struct unit *punit);
+static bool member_flip_filter(struct unit *punit);
+
+/* Area selection with mouse */
+static void area_r_and_r(void);
+static void area_wakeup(void);
+static void area_sentry(void);
+static void area_fortify(void);
+static void area_explore(void);
+
+/**************************************************************************
+...
+***************************************************************************/
+void filter_units(enum unit_filter uf)
+{
+  /* batch filters */
+
+  switch (uf) {
+    case  FILTER_NEW:               filter_new               = TRUE;  break;
+    case  FILTER_VETERAN:           filter_veteran           = TRUE;  break;
+    case  FILTER_CURRENT_LOCATION:  filter_current_location  = TRUE;  break;
+    case  FILTER_RADIUS:            filter_radius            = TRUE;  break;
+    case  FILTER_INCLUDE_SENTRIES:  filter_include_sentries  = TRUE;  break;
+    case  FILTER_INCLUDE_FORTIFIED: filter_include_fortified = TRUE;  break;
+    case  FILTER_INCLUDE_EXHAUSTED: filter_include_exhausted = TRUE;  break;
+    case  FILTER_INCLUDE_GOTOS:     filter_include_gotos     = TRUE;  break;
+    case  FILTER_INCLUDE_MEMBERS:   filter_include_members   = TRUE;  break;
+
+    /* focus filters */
+
+    default:
+      if (focus_category == uf)
+        return;
+
+      focus_category = uf;
+      update_radio_buttons();
+
+      if (focus_category && !unit_is_within_category(punit_focus))  {
+        advance_unit_focus(TRUE);
+      }
+      break;
+  }
+  update_menus();
+}
+
+/**************************************************************************
+ Batch filters only
+***************************************************************************/
+void cancel_filters(void)
+{
+  filter_new                = FALSE;
+  filter_veteran            = FALSE;
+  filter_current_location   = FALSE;
+  filter_radius             = FALSE;
+  filter_include_sentries   = FALSE;
+  filter_include_fortified  = FALSE;
+  filter_include_exhausted  = FALSE;
+  filter_include_gotos      = FALSE;
+  filter_include_members    = FALSE;
+
+  update_menus();
+}
+
+/**************************************************************************
+ FIXME: reclassify Frigates as transporters when Steam is aquired (generic).
+ Make them members of 'warships' category before that.
+***************************************************************************/
+bool unit_is_within_category(struct unit *punit)
+{
+  if (!punit)
+    return FALSE;
+
+  switch (focus_category) {
+  case FILTER_NORMAL:       return  TRUE;
+  case FILTER_DIPLOMATS:    return  unit_flag(punit, F_DIPLOMAT);
+  case FILTER_CARAVANS:     return  unit_flag(punit, F_HELP_WONDER);
+  case FILTER_SETTLERS:     return  unit_flag(punit, F_CITIES);
+  case FILTER_AIRPLANES:    return  (unit_type(punit)->move_type == AIR_MOVING
+                                    && !unit_flag(punit, F_MISSILE));
+  case FILTER_HELICOPTERS:  return  unit_type(punit)->move_type == HELI_MOVING;
+  case FILTER_INFANTRY:     return  (unit_type(punit)->move_type == LAND_MOVING
+                                    && unit_types[punit->type].attack_strength > 0);
+  case FILTER_WARSHIPS:     return  (unit_type(punit)->move_type == SEA_MOVING
+                                    && unit_types[punit->type].attack_strength > 0
+                                    && !get_transporter_capacity(punit));
+  case FILTER_TRANSPORTERS: return  get_transporter_capacity(punit);
+  default:                  return  FALSE; /* error */
+  }
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+const char *get_category_name(void)
+{
+  return focus_category_names[focus_category];
+}
+
+/**************************************************************************
+ Top level processing and print statistics.
+ The static subroutines are responsible for selection and counting.
+
+ - Wakeup always includes firstunit (focus unit).
+ - Assign has firstunit done first, to establish group number.
+ - Goto has firstunit done separately with goto route as normal, last.
+ - Return & Recover only takes damaged ships.
+ - For other batch orders, firstunit is susceptible to filters
+     and may not be included.
+
+  Area (tile) Selection has no concept of focusunit and disregards filters.
+  It only applies to visible units, not in cities.
+
+***************************************************************************/
+void batch_orders(struct unit *firstunit,
+                  enum batch_orders bo, int x, int y)
+{
+  char msg[MAX_LEN_MSG];
+  char *plural;
+  char *verb = NULL;
+
+  if (!tile_units_active)  {
+    assert(firstunit);
+    fu    = firstunit;
+    fx    = firstunit->x;
+    fy    = firstunit->y;
+    ftype = firstunit->type;
+    fmf   = firstunit->mission_flag;
+    fo    = firstunit->orders;
+    fbg   = firstunit->bg;
+  }
+  count  = 0;
+  gcount = 0;   /* old gotos that were cancelled */
+
+  batch_command = FALSE;
+
+    switch (bo) {
+
+  case B_ORDERS_WAIT:
+
+    batch_wait();
+    cancel_filters();
+    return;
+
+  case B_ORDERS_BUILD_WONDER:
+
+    batch_build_wonder();
+    cancel_filters();
+    return;
+
+  case B_ORDERS_R_AND_R:
+
+    tile_units_active ? area_r_and_r() : batch_r_and_r();
+
+    if (count)  {
+      count==1 ? (plural=_("ship")) : (plural=_("ships"));
+      my_snprintf(msg, sizeof(msg), _("Game: Sending %d %s home to recover."),
+        count, plural);
+    } else
+      my_snprintf(msg, sizeof(msg), _("Game: No damaged ships were found."));
+
+    append_output_window(msg);
+
+    cancel_filters();
+    cancel_tile_selection();
+    return;
+
+  case B_ORDERS_WAKEUP: 
+
+    tile_units_active ? area_wakeup() : batch_wakeup();
+    
+    if (count) {
+      count==1 ? (plural=_("unit woke up")) :
+      ((focus_category && !tile_units_active) ? (plural=_("woke up")) :
+      (plural=_("units woke up")));
+
+      if (tile_units_active)  {
+        my_snprintf(msg, sizeof(msg), _("Game: %d %s."), count, plural);
+      } else  {
+        my_snprintf(msg, sizeof(msg), _("Game: %d %s %s."), count,
+          focus_category && count != 1 ? get_category_name() :
+                                         unit_types[ftype].name, plural);
+      }
+      append_output_window(msg);
+    }
+
+    if (gcount) {
+      gcount==1 ? (plural=_("goto was")) : (plural=_("gotos were"));
+      my_snprintf(msg, sizeof(msg), _("Game: %d %s cancelled."), gcount, plural);
+      append_output_window(msg);
+    }
+
+    cancel_filters();
+    cancel_tile_selection();
+    return;
+
+  case B_ORDERS_GOTOMISSION:
+
+    batch_goto(x, y);
+    verb=_("dispatched");
+    count++;  /* firstunit is done with goto route */
+    break;
+
+  case B_ORDERS_ASSIGN:
+
+    /* Note: Drafting by Area Selection done in battlegroups.c */
+
+    batch_assign();
+    count++;  /* firstunit was done in advance to establish group nr */
+    verb=_("drafted");
+    break;
+
+  case B_ORDERS_UNASSIGN:
+
+    batch_unassign();
+    verb=_("discharged");
+    break;
+
+  case B_ORDERS_AUTO:
+
+    batch_automate();
+    verb=_("automated");
+    break;
+  
+  case B_ORDERS_SENTRY:
+
+    tile_units_active ? area_sentry() : batch_sentry();
+    verb=_("sentried");
+    break;
+  
+  case B_ORDERS_FORTIFY:
+
+    tile_units_active ? area_fortify() : batch_fortify();
+    verb=_("digging in");
+    break;
+  
+  case B_ORDERS_EXPLORE:
+
+    tile_units_active ? area_explore() : batch_explore();
+    verb=_("ordered to explore new land");
+    break;
+
+  default:  break;
+    }
+
+
+  /*   Grammar.
+   *
+  *    Poor Sawada Katsuya.
+   *
+   *   For Area Selection it looks like this:
+  *    "5 units were sentried."
+  *
+   *   For Batch Command, depending on Focus Category, it may look like this:
+   *   "12 warships were sentried."
+  *    "7 AEGIS Cruiser units were sentried."
+  *
+   *   Fortifying has different tense:
+   *   "13 Musketeer units are digging in."
+  *
+   *   For mass-Wakeups, units are *either* 'woken up' or 'cancelled goto',
+   *   which is done above.
+  *    For other batches, cancelled gotos are printed as extra information.
+  */
+  if (bo==B_ORDERS_FORTIFY)
+    count==1 ? (plural=_("unit is")) :
+    ((focus_category && !tile_units_active) ? (plural=_("are")) :
+    (plural=_("units are")));
+  else
+    count==1 ? (plural=_("unit has been")) :
+    ((focus_category && !tile_units_active) ? (plural=_("were")) :
+    (plural=_("units were")));
+
+  if (tile_units_active)
+    my_snprintf(msg, sizeof(msg), _("Game: %d %s %s."), count, plural, verb);
+  else
+    my_snprintf(msg, sizeof(msg), _("Game: %d %s %s %s."), count,
+      focus_category && count != 1 ? get_category_name() :
+                                     unit_types[ftype].name, plural, verb);
+  append_output_window(msg);
+
+  if (gcount) {
+    gcount==1 ? (plural=_("goto was")) : (plural=_("gotos were"));
+    my_snprintf(msg, sizeof(msg), _("Game: %d %s cancelled to do this."),
+    gcount, plural);
+    append_output_window(msg);
+  }
+
+  cancel_filters();
+  cancel_tile_selection();
+}
+
+/**************************************************************************
+ Unlike other batch commands, Batch Return and Recover applies to group
+ members / non-members without specifying the <Control> 'M' filter.
+
+ Also, it only applies to damaged ships, and can be invoked without
+ focus unit beeing a ship. Any other batch 'R' would not be useful.
+
+ Filters that apply:  'Include Sentries'
+                      'Include Gotos'
+                      'Radius of 5 only'
+***************************************************************************/
+static void batch_r_and_r(void)
+{
+  int hp;
+
+  unit_list_iterate(game.player_ptr->units, punit) {
+    hp = (10*punit->hp) / get_unit_type(punit->type)->hp;
+    hp = CLIP(0, hp, 10);
+    if(!map_get_city(punit->x, punit->y)
+      && !punit->ai.charge
+      && is_sailing_unit(punit)
+      && hp<9
+      && (punit->activity!=ACTIVITY_GOTO || filter_include_gotos)
+      && !(punit->mission_flag && punit->orders == ORDERS_SENTRY)
+      && (filter_include_sentries || punit->activity!=ACTIVITY_SENTRY)
+      && (!filter_radius || real_map_distance(punit->x, punit->y,
+          fx, fy) <= F_RADIUS))  {
+  return_and_recover(punit);
+  count++;
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+static void batch_wait(void)
+{
+  unit_list_iterate(game.player_ptr->units, punit) {
+    if (punit->type==ftype
+        && punit->activity==ACTIVITY_IDLE
+        && punit->focus_status==FOCUS_AVAIL
+        && punit->moves_left
+        && (!filter_veteran || punit->veteran)
+        && (!filter_new || punit->never_moved)
+        && (!filter_current_location || (punit->x==fx && punit->y==fy))
+        && (!filter_radius || real_map_distance(punit->x, punit->y,
+            fx, fy) <= F_RADIUS))
+  punit->focus_status=FOCUS_WAIT;
+  } unit_list_iterate_end;
+
+  if (punit_focus && punit_focus->focus_status==FOCUS_WAIT)
+    advance_unit_focus(FALSE);
+}
+
+/**************************************************************************
+ This makes units Idle.
+
+ In Batch Wakeup, filter 'Include Gotos' also applies to eXplorers,
+ and to Auto-units except those who are working a task, such as Mine.
+
+ Exhausted units are always included in the wakeup.
+ Sentries are obviously always included in the wakeup.
+
+***************************************************************************/
+static void batch_wakeup(void)
+{
+  filter_include_sentries  = TRUE;
+  filter_include_exhausted = TRUE;
+
+    unit_list_iterate(game.player_ptr->units, punit) {
+  if(punit!=fu && member_flip_filter(punit)
+    && (common_filters(punit)
+        || ((punit->activity==ACTIVITY_EXPLORE && filter_include_gotos)
+            && (punit->type==ftype
+                || (focus_category && unit_is_within_category(punit))))
+        || (punit->ai.control && filter_include_gotos
+            /* autosettler not working a task, such as Mine */
+            && (punit->activity==ACTIVITY_IDLE
+                || punit->activity==ACTIVITY_GOTO)
+            && (punit->type==ftype
+                || (focus_category && unit_is_within_category(punit))))))
+  {
+    if (punit->activity==ACTIVITY_GOTO)  {
+      gcount++;
+      bg_un_target_tile(punit);
+    } else  {
+      count++;
+    }
+    punit->activity=ACTIVITY_IDLE; /* To avoid Wakeup auto-focus */
+    punit->mission_flag = FALSE;
+    request_new_unit_activity(punit, ACTIVITY_IDLE);
+    refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
+  }
+    } unit_list_iterate_end;
+
+  /* Firstunit not regarding filters, always wakeup. Why? You may focus on
+  *  a unit with the 'browse' keys without it beeing Idled, in rare cases.
+  */
+  if (fu->activity!=ACTIVITY_IDLE || fu->ai.control) {
+    if (fu->activity==ACTIVITY_GOTO)  {
+      gcount++;
+      bg_un_target_tile(fu);
+    } else  {
+      count++;
+    }
+    fu->activity=ACTIVITY_IDLE;
+    request_new_unit_activity(fu, ACTIVITY_IDLE);
+  }
+}
+
+/**************************************************************************
+ Just build.
+***************************************************************************/
+static void batch_build_wonder(void)
+{
+    unit_list_iterate(map_get_tile(fx, fy)->units, punit) {
+      if (unit_can_help_build_wonder_here(punit))
+        request_unit_caravan_action(punit, PACKET_UNIT_HELP_BUILD_WONDER);
+    } unit_list_iterate_end;
+}
+
+/**************************************************************************
+ Firstunit done separately to establish what group.
+ Members filter will assign members from other groups to the new one.
+***************************************************************************/
+static void batch_assign(void)
+{
+  unit_list_iterate(game.player_ptr->units, punit) {
+    if(punit != fu && common_filters(punit)
+      && (!punit->bg || (filter_include_members && punit->bg != fbg)))  {
+        bg_assign_unit(punit, fbg - 1);
+        count++;
+        punit->mission_flag = FALSE;
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+static void batch_unassign(void)
+{
+  unit_list_iterate(bg[fbg - 1]->units, punit) {
+    if(common_filters(punit)) {
+      bg_unassign_unit(punit);
+      count++;
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+ Firstunit done separately with goto route in do_unit_goto().
+ Others get no route from client and may sometimes fail.
+***************************************************************************/
+static void batch_goto(int x, int y)
+{
+    unit_list_iterate(game.player_ptr->units, punit) {
+
+    if (unit_types[punit->type].move_type == LAND_MOVING
+  && map_get_tile(punit->x, punit->y)->continent != map_get_tile(x, y)->continent)
+      continue;
+
+  if (punit!=fu && common_filters(punit) && member_flip_filter(punit)) {
+
+      punit->mission_flag = fmf;
+      punit->orders = fo;
+      /* special case: unit is given a goto, but is already there */
+      if(punit->x == x && punit->y == y)  {
+        if(punit->mission_flag) {
+          if (punit->activity==ACTIVITY_GOTO) {
+            bg_un_target_tile(punit);
+            gcount++;
+          }
+          punit->never_moved = FALSE;
+          execute_order(punit);
+          count++;
+          if (punit && punit->activity==ACTIVITY_GOTO)  /* failed to execute */
+            request_new_unit_activity(punit, ACTIVITY_IDLE);
+        } /* already there, but WAS going somewhere else. stop! */
+        else if (punit->activity==ACTIVITY_GOTO)  {
+          bg_un_target_tile(punit);
+          count++;
+          gcount++;
+          request_new_unit_activity(punit, ACTIVITY_IDLE);
+        }
+        /* this line: already there - do nothing - don't count */
+      } else  { /* end of special case */
+          if (punit->activity==ACTIVITY_GOTO) {
+            bg_un_target_tile(punit);
+            gcount++;
+          }
+          send_goto_unit(punit, x, y);
+          count++;
+        }
+  }
+    } unit_list_iterate_end;
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+static void batch_automate(void)
+{
+    unit_list_iterate(game.player_ptr->units, punit) {
+  if (common_filters(punit) && member_flip_filter(punit)) {
+
+    if(can_unit_do_auto(punit)) {
+      if (punit->activity==ACTIVITY_GOTO) {
+        bg_un_target_tile(punit);
+        gcount++;
+      }
+      punit->mission_flag = FALSE;
+      request_unit_auto(punit);
+      count++;
+    }
+  }
+    } unit_list_iterate_end;
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+static void batch_sentry(void)
+{
+    unit_list_iterate(game.player_ptr->units, punit) {
+  if (common_filters(punit) && member_flip_filter(punit)) {
+
+    if (punit->activity!=ACTIVITY_SENTRY) {
+      if (punit->activity==ACTIVITY_GOTO) {
+        bg_un_target_tile(punit);
+        gcount++;
+      }
+      punit->mission_flag = FALSE;
+      request_new_unit_activity(punit, ACTIVITY_SENTRY);
+      count++;
+    }
+  }
+    } unit_list_iterate_end;
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+static void batch_fortify(void)
+{
+    unit_list_iterate(game.player_ptr->units, punit) {
+  if (common_filters(punit) && member_flip_filter(punit)) {
+
+    if (punit->activity!=ACTIVITY_FORTIFYING
+        && punit->activity!=ACTIVITY_FORTIFIED
+        && can_unit_do_activity(punit, ACTIVITY_FORTIFYING))  {
+      if (punit->activity==ACTIVITY_GOTO) {
+        bg_un_target_tile(punit);
+        gcount++;
+      }
+      punit->mission_flag = FALSE;
+      request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
+      count++;
+    }
+  }
+    } unit_list_iterate_end;
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+static void batch_explore(void)
+{
+    unit_list_iterate(game.player_ptr->units, punit) {
+  if (common_filters(punit) && member_flip_filter(punit)) {
+
+    if(can_unit_do_activity(punit, ACTIVITY_EXPLORE)) {
+      if (punit->activity==ACTIVITY_GOTO) {
+        bg_un_target_tile(punit);
+        gcount++;
+      }
+      punit->mission_flag = FALSE;
+      request_new_unit_activity(punit, ACTIVITY_EXPLORE);
+      count++;
+    }
+  }
+    } unit_list_iterate_end;
+}
+
+/**************************************************************************
+ Exclusion by filters
+**************************************************************************/
+static bool common_filters(struct unit *punit)
+{
+  if((punit->type==ftype || (focus_category && unit_is_within_category(punit)))
+    &&  !punit->ai.charge
+    &&  !punit->ai.control
+    && (!filter_veteran || punit->veteran)
+    && (!filter_new || punit->never_moved)
+    && (!filter_current_location || (punit->x==fx && punit->y==fy))
+    && (!filter_radius || real_map_distance(punit->x, punit->y,
+        fx, fy) < F_RADIUS)
+    && (!punit->mission_flag
+        || (punit->activity==ACTIVITY_GOTO && filter_include_gotos))
+
+    && (punit->activity==ACTIVITY_IDLE
+        || (punit->activity==ACTIVITY_GOTO && filter_include_gotos)
+        || (punit->activity==ACTIVITY_SENTRY && filter_include_sentries)
+        || ((punit->activity==ACTIVITY_FORTIFYING
+            || punit->activity==ACTIVITY_FORTIFIED)
+            && filter_include_fortified))
+
+    && (filter_include_exhausted || punit->moves_left
+        || (punit->activity==ACTIVITY_GOTO && filter_include_gotos)
+        || punit==fu))
+
+      return TRUE;
+
+  return FALSE;
+}
+
+/**************************************************************************
+ When firstunit is a groupmember, filter includes free units.
+ When firstunit is not a groupmember, filter includes members of all groups.
+**************************************************************************/
+static bool member_flip_filter(struct unit *punit)
+{
+  if ((!fbg && (!punit->bg || filter_include_members))
+    || (fbg && (punit->bg == fbg || (!punit->bg && filter_include_members))))
+    return TRUE;
 
-static struct unit *find_best_focus_candidate(void);
+  return FALSE;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void area_r_and_r(void)
+{
+  int hp;
+
+  unit_list_iterate(game.player_ptr->units, punit) {
+    hp = (10*punit->hp) / get_unit_type(punit->type)->hp;
+    hp = CLIP(0, hp, 10);
+
+    if (map_get_tile(punit->x, punit->y)->selected == 2
+      && !punit->ai.charge
+      && is_sailing_unit(punit)
+      && hp<9
+      && !(punit->mission_flag && punit->orders == ORDERS_SENTRY))
+    {
+      return_and_recover(punit);
+      count++;
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void area_wakeup(void)
+{
+  unit_list_iterate(game.player_ptr->units, punit) {
+    if (map_get_tile(punit->x, punit->y)->selected == 2
+      && (punit->activity != ACTIVITY_IDLE || punit->ai.control))
+    {
+      if (punit->activity==ACTIVITY_GOTO)  {
+        gcount++;
+        bg_un_target_tile(punit);
+      } else  {
+        count++;
+      }
+      punit->activity=ACTIVITY_IDLE;
+      punit->mission_flag = FALSE;
+      request_new_unit_activity(punit, ACTIVITY_IDLE);
+      refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+ Don't Sentry fortified units.
+**************************************************************************/
+static void area_sentry(void)
+{
+  unit_list_iterate(game.player_ptr->units, punit) {
+    if (map_get_tile(punit->x, punit->y)->selected == 2
+      && !punit->ai.charge
+      && punit->activity != ACTIVITY_FORTIFIED
+      && punit->activity != ACTIVITY_SENTRY)
+    {
+      if (punit->activity==ACTIVITY_GOTO) {
+        bg_un_target_tile(punit);
+        gcount++;
+      }
+      punit->mission_flag = FALSE;
+      request_new_unit_activity(punit, ACTIVITY_SENTRY);
+      count++;
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+ Don't build fortresses.
+**************************************************************************/
+static void area_fortify(void)
+{
+  unit_list_iterate(game.player_ptr->units, punit) {
+    if (map_get_tile(punit->x, punit->y)->selected == 2
+      && !punit->ai.charge
+      && punit->activity != ACTIVITY_FORTIFIED
+      && punit->activity != ACTIVITY_FORTIFYING
+      && can_unit_do_activity(punit, ACTIVITY_FORTIFYING)
+      && !unit_flag(punit, F_SETTLERS))
+    {
+      if (punit->activity==ACTIVITY_GOTO) {
+        bg_un_target_tile(punit);
+        gcount++;
+      }
+      punit->mission_flag = FALSE;
+      request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
+      count++;
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+ Not settlers..
+**************************************************************************/
+static void area_explore(void)
+{
+  unit_list_iterate(game.player_ptr->units, punit) {
+    if (map_get_tile(punit->x, punit->y)->selected == 2
+      && !punit->ai.charge
+      && can_unit_do_activity(punit, ACTIVITY_EXPLORE)
+      && !unit_flag(punit, F_SETTLERS)
+      && !unit_flag(punit, F_HELP_WONDER))
+    {
+      if(can_unit_do_activity(punit, ACTIVITY_EXPLORE)) {
+        if (punit->activity==ACTIVITY_GOTO) {
+          bg_un_target_tile(punit);
+          gcount++;
+        }
+        punit->mission_flag = FALSE;
+        request_new_unit_activity(punit, ACTIVITY_EXPLORE);
+        count++;
+      }
+    }
+  } unit_list_iterate_end;
+}
+
+/**************************************************************************
+ Only ask server if unit not idle, and always after focusing client.
+ It appears the only reason the server was asked in the first place,
+ was to ensure idle/automated units wake up.
+**************************************************************************/
+void fastfocus(struct unit *punit)
+{
+  if (punit_focus != punit) {
+    store_focus();
+    set_unit_focus_and_select(punit);
+  }
+  punit->mission_flag = FALSE;
+  if (punit->activity!=ACTIVITY_IDLE || punit->ai.control)
+    request_unit_selected(punit);
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void store_focus(void)
+{
+    if (punit_focus)
+      previous_focus_id = punit_focus->id;
+}
+
+/**************************************************************************
+ Will not awaken sentries, etc.
+**************************************************************************/
+void recall_previous_focus(void)
+{
+    int id = previous_focus_id;
+    store_focus();
+    set_unit_focus_and_select(find_unit_by_id(id));
+}
 
 /**************************************************************************
 ...
@@ -73,21 +902,22 @@
   else
     hover_unit = 0;
   hover_state = state;
+  update_menus();
   exit_goto_state();
 }
 
 /**************************************************************************
-...
+ Server should not decide client's focus. Suggest remove.
 **************************************************************************/
 void handle_advance_focus(struct packet_generic_integer *packet)
 {
   struct unit *punit = find_unit_by_id(packet->value);
   if (punit && punit_focus == punit)
-    advance_unit_focus();
+    advance_unit_focus(FALSE);
 }
 
 /**************************************************************************
-Center on the focus unit, if off-screen and auto_center_on_unit is true.
+ Center on the focus unit, if off-screen and auto_center_on_unit is true.
 **************************************************************************/
 void auto_center_on_focus_unit(void)
 {
@@ -105,9 +935,17 @@
 void set_unit_focus(struct unit *punit)
 {
   struct unit *punit_old_focus=punit_focus;
+  batch_command = FALSE;
+  cancel_filters();
 
+  if (punit && punit->bg)
+    last_group = punit->bg;
+
   punit_focus=punit;
 
+  if (!unit_is_within_category(punit_focus))
+    filter_units(FILTER_NORMAL);
+
   if(punit) {
     auto_center_on_focus_unit();
 
@@ -166,7 +1004,7 @@
 	 && punit_focus->activity!=ACTIVITY_GOTO)
      || punit_focus->moves_left==0 
      || punit_focus->ai.control) {
-    advance_unit_focus();
+    advance_unit_focus(FALSE);
   }
 }
 
@@ -179,33 +1017,60 @@
 }
 
 /**************************************************************************
-...
+ Try harder to get a unit within the category.
+ User may need one for batch operations.
 **************************************************************************/
-void advance_unit_focus(void)
+void advance_unit_focus(bool try_harder)
 {
-  struct unit *punit_old_focus=punit_focus;
+  char msg[MAX_LEN_MSG];
+  struct unit *punit_old_focus = punit_focus;
 
-  punit_focus=find_best_focus_candidate();
+  store_focus();
+  punit_focus = find_best_focus_candidate(0);
 
   set_hover_state(NULL, HOVER_NONE);
 
   if(!punit_focus) {
     unit_list_iterate(game.player_ptr->units, punit) {
-      if(punit->focus_status==FOCUS_WAIT)
-	punit->focus_status=FOCUS_AVAIL;
-    }
-    unit_list_iterate_end;
-    punit_focus=find_best_focus_candidate();
+      if(punit->focus_status == FOCUS_WAIT)
+	punit->focus_status = FOCUS_AVAIL;
+    } unit_list_iterate_end;
+
+    punit_focus = find_best_focus_candidate(0);
+
     if (punit_focus == punit_old_focus) {
       /* we don't want to same unit as before if there are any others */
-      punit_focus=find_best_focus_candidate();
+      punit_focus = find_best_focus_candidate(0);
       if(!punit_focus) {
 	/* but if that is the only choice, take it: */
-	punit_focus=find_best_focus_candidate();
+	punit_focus = find_best_focus_candidate(0);
       }
     }
+
+    /* User pressing a Focus Category button is a
+    *  very explicit command, so we try harder.
+    */
+    if(!punit_focus && try_harder)
+      punit_focus = find_best_focus_candidate(1);  /* sentry? */
+    if(!punit_focus && try_harder)
+      punit_focus = find_best_focus_candidate(2);  /* fortifying? */
+    if(!punit_focus && try_harder)
+      punit_focus = find_best_focus_candidate(3);  /* damnit */
+    if(!punit_focus && try_harder)  {
+      my_snprintf(msg, sizeof(msg), _("Game: You have no available %s!"),
+      get_category_name());
+      append_output_window(msg);
+    }
   }
 
+  /*  Category exhausted, cancel filter. That function may only
+   *  call this function if focus_category, otherwise infiniloop.
+  */
+  if (focus_category && !punit_focus) {
+    filter_units(FILTER_NORMAL);
+    punit_focus = find_best_focus_candidate(0);
+  }
+
   /* We have to do this ourselves, and not rely on set_unit_focus(),
    * because above we change punit_focus directly.
    */
@@ -214,6 +1079,12 @@
 
   set_unit_focus(punit_focus);
 
+  if (punit_focus /* Don't cancel gotos or autosettlers, but focus on them */
+      &&  punit_focus->activity != ACTIVITY_GOTO
+      && (punit_focus->activity != ACTIVITY_IDLE
+        || (punit_focus->ai.control && !unit_flag(punit_focus, F_SETTLERS))))
+    request_new_unit_activity(punit_focus, ACTIVITY_IDLE);
+
   /* Handle auto-turn-done mode:  If a unit was in focus (did move),
    * but now none are (no more to move), then fake a Turn Done keypress.
    */
@@ -226,7 +1097,7 @@
 in focus (if any).  If the current focus unit is the only possible
 unit, or if there is no possible unit, returns NULL.
 **************************************************************************/
-static struct unit *find_best_focus_candidate(void)
+static struct unit *find_best_focus_candidate(int try_harder)
 {
   struct unit *best_candidate;
   int best_dist=99999;
@@ -241,8 +1112,15 @@
   best_candidate=NULL;
   unit_list_iterate(game.player_ptr->units, punit) {
     if(punit!=punit_focus) {
-      if(punit->focus_status==FOCUS_AVAIL && punit->activity==ACTIVITY_IDLE &&
-	 punit->moves_left > 0 && !punit->ai.control) {
+      if((punit->focus_status==FOCUS_AVAIL || try_harder > 0)
+     && (punit->activity==ACTIVITY_IDLE
+      ||(punit->activity==ACTIVITY_SENTRY && try_harder > 0)
+      ||(punit->activity==ACTIVITY_FORTIFYING && try_harder > 1)
+      || try_harder > 2)
+     && (punit->moves_left > 0 || try_harder > 1)
+     && (!punit->ai.control || try_harder > 0)
+     && !punit->mission_flag && !punit->ai.charge
+     && unit_is_within_category(punit)) {
         int d;
 	d=sq_map_distance(punit->x, punit->y, x, y);
 	if(d<best_dist) {
@@ -298,13 +1176,13 @@
        1: owned transporter.
        2: any owned unit
        3: any transporter
-       4: any unit
+       4: any unit, bodyguards down-prioritized
      (always return first in stack). */
   unit_list_iterate(ptile->units, punit)
     if (unit_owner(punit) == game.player_ptr) {
       if (get_transporter_capacity(punit) > 0) {
 	return punit;
-      } else if (!panyowned) {
+      } else if (!panyowned || panyowned->ai.charge) {
 	panyowned = punit;
       }
     } else if (!ptptother &&
@@ -547,7 +1425,9 @@
 
   if (hover_state != HOVER_GOTO) {
     set_hover_state(punit, HOVER_GOTO);
+    punit->mission_flag = FALSE;
     update_unit_info_label(punit);
+    update_menus();
     /* Not yet implemented for air units */
     if (is_air_unit(punit)) {
       draw_goto_line = FALSE;
@@ -618,6 +1498,7 @@
 {
   unit_list_iterate(map_get_tile(x,y)->units, punit) {
     if(punit->activity==ACTIVITY_SENTRY && game.player_idx==punit->owner) {
+      punit->activity = ACTIVITY_IDLE;  /* To avoid Wakeup auto-focus */
       request_new_unit_activity(punit, ACTIVITY_IDLE);
     }
   }
@@ -669,10 +1550,21 @@
     return;
   }
 
+  cancel_batch_command();
+
+  if (punit->moves_left>0) {
+    if (punit->activity != ACTIVITY_IDLE)
+      request_new_unit_activity(punit, ACTIVITY_IDLE);
   req_unit = *punit;
   req_unit.x = dest_x;
   req_unit.y = dest_y;
   send_move_unit(&req_unit);
+  } else  {                     /* Nice to give gotos with direction keys */
+  punit->mission_flag = FALSE;  /*   for exhausted units.                 */
+  bg_un_target_tile(punit);     /* One way of cancelling an existing goto.*/
+  send_goto_unit(punit, dest_x, dest_y);
+  advance_unit_focus(FALSE);
+  }
 }
 
 /**************************************************************************
@@ -681,6 +1573,7 @@
 void request_new_unit_activity(struct unit *punit, enum unit_activity act)
 {
   struct unit req_unit;
+  punit->never_moved = FALSE;
   req_unit=*punit;
   req_unit.activity=act;
   req_unit.activity_target = S_NO_SPECIAL;
@@ -694,6 +1587,7 @@
 					enum tile_special_type tgt)
 {
   struct unit req_unit;
+  punit->never_moved = FALSE;
   req_unit=*punit;
   req_unit.activity=act;
   req_unit.activity_target=tgt;
@@ -773,6 +1667,7 @@
 {
   if (can_unit_do_auto(punit)) {
     struct packet_unit_request req;
+    punit->never_moved = FALSE;
     req.unit_id=punit->id;
     req.name[0]='\0';
     send_packet_unit_request(&aconnection, &req, PACKET_UNIT_AUTO);
@@ -1104,7 +1999,7 @@
 {
   punit->focus_status=FOCUS_WAIT;
   if(punit==get_unit_in_focus()) {
-    advance_unit_focus();
+    advance_unit_focus(FALSE);
     /* set_unit_focus(punit_focus); */  /* done in advance_unit_focus */
   }
 }
@@ -1116,7 +2011,7 @@
 {
   if(get_unit_in_focus()) {
     get_unit_in_focus()->focus_status=FOCUS_DONE;
-    advance_unit_focus();
+    advance_unit_focus(FALSE);
     /* set_unit_focus(punit_focus); */  /* done in advance_unit_focus */
   }
 }
@@ -1187,7 +2082,7 @@
 /**************************************************************************
  Handles everything when the user clicked a tile
 **************************************************************************/
-void do_map_click(int xtile, int ytile)
+void do_map_click(int xtile, int ytile, enum quicktype qtype)
 {
   struct city *pcity = map_get_city(xtile, ytile);
   struct tile *ptile = map_get_tile(xtile, ytile);
@@ -1220,12 +2115,26 @@
     case HOVER_PATROL:
       do_unit_patrol_to(punit, xtile, ytile);
       break;	
+    case HOVER_BODYGUARD:
+      select_VIU(punit, xtile, ytile);
+      break;   
     }
     set_hover_state(NULL, HOVER_NONE);
     update_unit_info_label(punit);
     return;
   }
   
+  /* Bypass popups if quickselect is specified */
+
+  if (qtype) {
+    struct unit *punit = quickselect(ptile, qtype);
+    if (punit)
+      fastfocus(punit);
+    return;
+  }
+
+  /* otherwise use popups */
+
   if (pcity && game.player_idx==pcity->owner) {
     popup_city_dialog(pcity, FALSE);
     return;
@@ -1235,7 +2144,7 @@
     struct unit *punit=unit_list_get(&ptile->units, 0);
     if(game.player_idx==punit->owner) {
       if(can_unit_do_activity(punit, ACTIVITY_IDLE)) {
-	request_unit_selected(punit);
+	fastfocus(punit);
       }
     }
   } else if(unit_list_size(&ptile->units) >= 2) {
@@ -1249,6 +2158,113 @@
 }
 
 /**************************************************************************
+ Subroutine to choose and return a unit from ptile according to type.
+ May return null.
+**************************************************************************/
+struct unit *quickselect(struct tile *ptile, enum quicktype qtype)
+{
+    int listsize = unit_list_size(&ptile->units);
+    struct unit *panytransporter = NULL, *panymovesea = NULL, *panysea = NULL,
+      *panymoveland = NULL, *panyland = NULL,
+      *panymoveunit = NULL, *panyunit = NULL;
+
+    if (listsize==1) {
+      struct unit *punit=unit_list_get(&ptile->units, 0);
+      if(game.player_idx == punit->owner)
+        return(punit);
+    }
+    else if (listsize==0)
+      return NULL;
+
+/*  Quickselect priorities. Units with moves left
+ *  before exhausted. Focus unit is excluded.
+ *
+ *    SEA:  Transporter
+ *          Sea unit
+ *          Any unit
+ *
+ *    LAND: Military land unit
+ *          Non-combatant
+ *          Sea unit
+ *          Any unit
+ */
+
+    unit_list_iterate(ptile->units, punit)  {
+      if(game.player_idx == punit->owner && punit != punit_focus) {
+
+        if (qtype==SEA) {
+          if (get_transporter_capacity(punit)) {    /* transporter */
+            if (punit->moves_left > 0)  {
+              return(punit);
+            }
+            else if (!panytransporter)
+              panytransporter = punit;
+          }
+          else if (is_sailing_unit(punit)) { /* any sea, pref. moves left */
+            if (punit->moves_left >0) {
+              if (!panymovesea)
+                panymovesea = punit;
+            } else if (!panysea)
+                panysea = punit;
+          }
+        } else if (qtype==LAND) {
+          if (is_ground_unit(punit))  {
+            if (punit->moves_left > 0) {
+              if (is_military_unit(punit)) {
+                return(punit);
+              } else if (!panymoveland)
+                  panymoveland = punit;
+            }
+            else if (!panyland)
+              panyland = punit;
+          }
+          else if (is_sailing_unit(punit)) {
+            if (punit->moves_left >0)
+              panymovesea = punit;
+            else
+              panysea = punit;
+          }
+        }
+        if (punit->moves_left >0 && !panymoveunit)
+          panymoveunit = punit;
+        if (!panyunit)
+          panyunit = punit;
+      }
+    } unit_list_iterate_end;
+
+    /* focus */
+    if (qtype==SEA) {
+      if (panytransporter)
+        return (panytransporter);
+      else if (panymovesea)
+        return (panymovesea);
+      else if (panysea)
+        return (panysea);
+
+      else if (panymoveunit)
+        return (panymoveunit);
+      else if (panyunit)
+        return (panyunit);
+      } else if (qtype==LAND)  {
+      if (panymoveland)
+        return (panymoveland);
+      else if (panyland)
+        return (panyland);
+      else if (panymovesea)
+        return (panymovesea);
+      else if (panysea)
+        return (panysea);
+
+      else if (panymoveunit)
+        return (panymoveunit);
+      else if (panyunit)
+        return (panyunit);
+      }
+
+  return NULL;                    /* No owned unit found */
+  }
+
+/**************************************************************************
  Finish the goto mode and let the unit which is stored in hover_unit move
  to a given location.
 **************************************************************************/
@@ -1260,20 +2276,35 @@
     return;
 
   if (punit) {
-    if (!draw_goto_line) {
-      send_goto_unit(punit, x, y);
+     if(batch_command)
+       batch_orders(punit, B_ORDERS_GOTOMISSION, x, y);
+ 
+    if (!draw_goto_line) {  /* air unit */
+       if(punit->x == x && punit->y == y)  {   /* already there */
+         if(punit->mission_flag)
+           execute_order(punit);
+       } else
+           send_goto_unit(punit, x, y);
     } else {
       int dest_x, dest_y;
       draw_line(x, y);
       get_line_dest(&dest_x, &dest_y);
       if (same_pos(dest_x, dest_y, x, y)) {
-	send_goto_route(punit);
+         bg_un_target_tile(punit);
+         /* already there and no route */
+         if(punit->x == x && punit->y == y && goto_array_index == 0)  {
+           if(punit->mission_flag)
+             execute_order(punit);
+         } else
+             send_goto_route(punit);
       } else {
+        punit->mission_flag = FALSE;
 	append_output_window(_("Game: Didn't find a route to the destination!"));
       }
     }
+   if (punit->moves_left == 0)
+     advance_unit_focus(FALSE);
   }
-
   set_hover_state(NULL, HOVER_NONE);
 }
 
@@ -1295,6 +2326,7 @@
 void do_unit_paradrop_to(struct unit *punit, int x, int y)
 {
   struct packet_unit_request req;
+  punit->never_moved = FALSE;
 
   req.unit_id=punit->id;
   req.x = x;
@@ -1326,11 +2358,179 @@
 }
  
 /**************************************************************************
+ Send ship to closest port and Sentry
+***************************************************************************/
+void return_and_recover(struct unit *punit)
+{
+  struct city *currentcity = map_get_city(punit->x, punit->y);
+  struct city *pcity = find_closest_owned_port(punit, currentcity);
+
+  if(pcity) {
+    if (punit->activity == ACTIVITY_GOTO)
+      bg_un_target_tile(punit);
+    punit->mission_flag = TRUE;
+    punit->orders = ORDERS_SENTRY;
+    send_goto_unit(punit, pcity->x, pcity->y);
+  }
+}
+
+/**************************************************************************
+ 'Mission' order
+***************************************************************************/
+void execute_order(struct unit *punit)
+{
+  bool delay_settle = FALSE;
+  unsigned int bitmask = 0;
+  char msg[MAX_LEN_MSG];
+  int i;
+
+  if(punit->orders==ORDERS_SENTRY) {
+    request_new_unit_activity(punit, ACTIVITY_SENTRY);
+  }
+  else if(punit->orders==ORDERS_FORTIFY
+    && can_unit_do_activity(punit, ACTIVITY_FORTRESS)) {
+      request_new_unit_activity(punit, ACTIVITY_FORTRESS);
+  }
+  else if(punit->orders==ORDERS_FORTIFY
+    && can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
+      request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
+  }
+  else if(punit->orders==ORDERS_MINE
+    && can_unit_do_activity(punit, ACTIVITY_MINE)) {
+      request_new_unit_activity(punit, ACTIVITY_MINE);
+  }
+  else if(punit->orders==ORDERS_IRRIGATE
+    && can_unit_do_activity(punit, ACTIVITY_IRRIGATE)) {
+      request_new_unit_activity(punit, ACTIVITY_IRRIGATE);
+  }
+  else if(punit->orders==ORDERS_TRANSFORM
+    && can_unit_do_activity(punit, ACTIVITY_TRANSFORM)) {
+      request_new_unit_activity(punit, ACTIVITY_TRANSFORM);
+  }
+  else if(punit->orders==ORDERS_AIRBASE
+    && can_unit_do_activity(punit, ACTIVITY_AIRBASE)) {
+      request_new_unit_activity(punit, ACTIVITY_AIRBASE);
+  }
+  else if(punit->orders==ORDERS_POLLUTION
+    && can_unit_do_activity(punit, ACTIVITY_POLLUTION)) {
+      request_new_unit_activity(punit, ACTIVITY_POLLUTION);
+  }
+  else if(punit->orders==ORDERS_FALLOUT
+    && can_unit_do_activity(punit, ACTIVITY_FALLOUT)) {
+      request_new_unit_activity(punit, ACTIVITY_FALLOUT);
+  }
+  else if(punit->orders==ORDERS_EXPLORE
+    && can_unit_do_activity(punit, ACTIVITY_EXPLORE)) {
+      request_new_unit_activity(punit, ACTIVITY_EXPLORE);
+  }
+  else if(punit->orders==ORDERS_UNLOAD) {
+
+  /* Scramble the Army Group(s) of all present
+   * units on this tile to storm the beaches.
+  */
+  unit_list_iterate(map_get_tile(punit->x, punit->y)->units, iunit) {
+    if (iunit->bg && unit_types[iunit->type].move_type == LAND_MOVING)  {
+        bitmask |= (1 << (iunit->bg - 1));
+        iunit->activity = ACTIVITY_IDLE;
+    }
+  } unit_list_iterate_end;
+
+  for (i = 0; i < NUM_BATTLEGROUPS; i++) {
+    if (bitmask & (1 << i)) {
+      my_snprintf(msg, sizeof(msg),
+        _("Game: %s %d attempts to establish a beachhead... going in!"),
+        bg[i]->name, i + 1);
+      append_output_window(msg);
+      bg_scramble(i);
+    }
+  }
+    request_unit_unload(punit);
+  }
+  else if(punit->orders==ORDERS_AUTO && can_unit_do_auto(punit)) {
+    request_unit_auto(punit);
+  }
+  else if(punit->orders==ORDERS_HOMECITY) {
+    request_unit_change_homecity(punit);
+  }
+  else if(punit->orders==ORDERS_DISBAND) {
+    request_unit_disband(punit);
+  }
+  else if(punit->orders==ORDERS_ROAD) {
+    if(can_unit_do_activity(punit, ACTIVITY_ROAD))
+      request_new_unit_activity(punit, ACTIVITY_ROAD);
+    else if(can_unit_do_activity(punit, ACTIVITY_RAILROAD))
+      request_new_unit_activity(punit, ACTIVITY_RAILROAD);
+    else if (unit_can_est_traderoute_here(punit))
+      request_unit_caravan_action(punit, PACKET_UNIT_ESTABLISH_TRADE);
+  }
+  else if(punit->orders==ORDERS_BUILD && unit_flag(punit, F_HELP_WONDER)) {
+    request_unit_caravan_action(punit, PACKET_UNIT_HELP_BUILD_WONDER);
+  }
+  /* Special case: settler with 0 movement points cannot build city,
+     so this is done next turn, directly in packhand.c */
+  else if(punit->orders==ORDERS_BUILD && unit_flag(punit, F_CITIES)) {
+    if(punit->moves_left)
+      request_unit_build_city(punit);
+    else  {
+      punit->orders = ORDERS_BUILD_NOW;
+      delay_settle = TRUE;
+    }
+  }
+
+  if(!delay_settle)
+    punit->mission_flag = FALSE;
+}
+
+/**************************************************************************
 ...
 **************************************************************************/
+void key_popup_cities_toggle(void)
+{
+  if(get_client_state()!=CLIENT_GAME_RUNNING_STATE) return;
+
+  popup_cities ^= 1;
+  if (popup_cities)
+    append_output_window(_("Game: City popups are now ON."));
+  else
+    append_output_window(_("Game: City popups are now OFF."));
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void key_auto_name_cities_toggle(void)
+{
+  if(get_client_state()!=CLIENT_GAME_RUNNING_STATE) return;
+
+  auto_name_cities ^= 1;
+  if (auto_name_cities)
+    append_output_window(_("Game: Auto city naming is now ON."));
+  else
+    append_output_window(_("Game: Auto city naming is now OFF."));
+}
+
+/**************************************************************************
+...
+**************************************************************************/
 void key_cancel_action(void)
 {
   bool popped = FALSE;
+
+  cancel_tile_selection();
+
+  if (!hover_state)  {
+    cancel_batch_command();
+
+    if (filter_new || filter_veteran || filter_current_location
+        || filter_radius || filter_include_sentries
+        || filter_include_fortified || filter_include_exhausted
+        || filter_include_gotos || filter_include_members)
+      cancel_filters();
+
+    else if (focus_category)
+      filter_units(FILTER_NORMAL);
+  }
+
   if (hover_state == HOVER_GOTO || hover_state == HOVER_PATROL)
     if (draw_goto_line)
       popped = goto_pop_waypoint();
@@ -1340,6 +2540,7 @@
 
     set_hover_state(NULL, HOVER_NONE);
 
+    punit->mission_flag = FALSE;
     update_unit_info_label(punit);
   }
 }
@@ -1427,19 +2628,30 @@
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_build_city(void)
+void key_unit_build_city(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    request_unit_build_city(punit_focus);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_BUILD;
+    } else if (punit->moves_left == 0)  {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_BUILD_NOW;
+      advance_unit_focus(FALSE);
+    } else
+      request_unit_build_city(punit);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_build_wonder(void)
+void key_unit_build_wonder(struct unit *punit)
 {
-  if (get_unit_in_focus() && unit_flag(punit_focus, F_HELP_WONDER))
-    request_unit_caravan_action(punit_focus, PACKET_UNIT_HELP_BUILD_WONDER);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_BUILD;
+    }
+    else if(unit_flag(punit, F_HELP_WONDER))
+      request_unit_caravan_action(punit, PACKET_UNIT_HELP_BUILD_WONDER);
 }
 
 /**************************************************************************
@@ -1515,19 +2727,27 @@
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_traderoute(void)
+void key_unit_traderoute(struct unit *punit)
 {
-  if (get_unit_in_focus() && unit_flag(punit_focus, F_TRADE_ROUTE))
-    request_unit_caravan_action(punit_focus, PACKET_UNIT_ESTABLISH_TRADE);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_ROAD;
+    }
+    else if(unit_flag(punit, F_TRADE_ROUTE))
+      request_unit_caravan_action(punit, PACKET_UNIT_ESTABLISH_TRADE);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_unload(void)
+void key_unit_unload(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    request_unit_unload(punit_focus);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_UNLOAD;
+    }
+    else
+      request_unit_unload(punit);
 }
 
 /**************************************************************************
@@ -1550,112 +2770,141 @@
 
 /**************************************************************************
 ...
-**************************************************************************/
-void key_unit_airbase(void)
+***************************************************************************/
+void key_unit_wakeup_self(void)
 {
   if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_AIRBASE))
-      request_new_unit_activity(punit_focus, ACTIVITY_AIRBASE);
+    request_new_unit_activity(punit_focus, ACTIVITY_IDLE);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_auto_attack(void)
+void key_unit_airbase(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(!unit_flag(punit_focus, F_SETTLERS) &&
-       can_unit_do_auto(punit_focus))
-      request_unit_auto(punit_focus);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_AIRBASE;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_AIRBASE))
+      request_new_unit_activity(punit, ACTIVITY_AIRBASE);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_auto_explore(void)
+void key_unit_auto(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_EXPLORE))
-      request_new_unit_activity(punit_focus, ACTIVITY_EXPLORE);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_AUTO;
+    }
+    else
+      request_unit_auto(punit);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_auto_settle(void)
+void key_unit_auto_explore(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(unit_flag(punit_focus, F_SETTLERS) &&
-       can_unit_do_auto(punit_focus))
-      request_unit_auto(punit_focus);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_EXPLORE;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_EXPLORE))
+      request_new_unit_activity(punit, ACTIVITY_EXPLORE);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_disband(void)
+void key_unit_disband(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    request_unit_disband(punit_focus);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_DISBAND;
+    }
+    else
+      request_unit_disband(punit);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_fallout(void)
+void key_unit_fallout(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_FALLOUT))
-      request_new_unit_activity(punit_focus, ACTIVITY_FALLOUT);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_FALLOUT;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_FALLOUT))
+      request_new_unit_activity(punit, ACTIVITY_FALLOUT);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_fortify(void)
+void key_unit_fortify(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_FORTIFYING))
-      request_new_unit_activity(punit_focus, ACTIVITY_FORTIFYING);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_FORTIFY;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_FORTIFYING))
+      request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_fortress(void)
+void key_unit_fortress(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_FORTRESS))
-      request_new_unit_activity(punit_focus, ACTIVITY_FORTRESS);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_FORTIFY;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_FORTRESS))
+      request_new_unit_activity(punit, ACTIVITY_FORTRESS);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_homecity(void)
+void key_unit_homecity(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    request_unit_change_homecity(punit_focus);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_HOMECITY;
+    }
+    else
+      request_unit_change_homecity(punit);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_irrigate(void)
+void key_unit_irrigate(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_IRRIGATE))
-      request_new_unit_activity(punit_focus, ACTIVITY_IRRIGATE);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_IRRIGATE;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_IRRIGATE))
+      request_new_unit_activity(punit, ACTIVITY_IRRIGATE);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_mine(void)
+void key_unit_mine(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_MINE))
-      request_new_unit_activity(punit_focus, ACTIVITY_MINE);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_MINE;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_MINE))
+      request_new_unit_activity(punit, ACTIVITY_MINE);
 }
 
 /**************************************************************************
@@ -1671,48 +2920,123 @@
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_pollution(void)
+void key_unit_pollution(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_POLLUTION))
-      request_new_unit_activity(punit_focus, ACTIVITY_POLLUTION);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_POLLUTION;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_POLLUTION))
+      request_new_unit_activity(punit, ACTIVITY_POLLUTION);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_road(void)
+void key_unit_road(struct unit *punit)
 {
-  if(get_unit_in_focus()) {
-    if(can_unit_do_activity(punit_focus, ACTIVITY_ROAD))
-      request_new_unit_activity(punit_focus, ACTIVITY_ROAD);
-    else if(can_unit_do_activity(punit_focus, ACTIVITY_RAILROAD))
-      request_new_unit_activity(punit_focus, ACTIVITY_RAILROAD);
-  }
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_ROAD;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_ROAD))
+      request_new_unit_activity(punit, ACTIVITY_ROAD);
+    else if(can_unit_do_activity(punit, ACTIVITY_RAILROAD))
+      request_new_unit_activity(punit, ACTIVITY_RAILROAD);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_sentry(void)
+void key_unit_sentry(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_SENTRY))
-      request_new_unit_activity(punit_focus, ACTIVITY_SENTRY);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_SENTRY;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_SENTRY))
+      request_new_unit_activity(punit, ACTIVITY_SENTRY);
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
-void key_unit_transform(void)
+void key_unit_transform(struct unit *punit)
 {
-  if(get_unit_in_focus())
-    if(can_unit_do_activity(punit_focus, ACTIVITY_TRANSFORM))
-      request_new_unit_activity(punit_focus, ACTIVITY_TRANSFORM);
+    if(hover_state==HOVER_GOTO) {
+      punit->mission_flag = TRUE;
+      punit->orders = ORDERS_TRANSFORM;
+    }
+    else if(can_unit_do_activity(punit, ACTIVITY_TRANSFORM))
+      request_new_unit_activity(punit, ACTIVITY_TRANSFORM);
+}
+
+/**************************************************************************
+ This duplicates <Control> Left/Right Click for keyboard lovers
+***************************************************************************/
+void key_quick_unit(enum quicktype qtype)
+{
+  struct tile *ptile;
+  struct unit *punit;
+
+  if(!punit_focus)
+    return;
+
+  ptile = map_get_tile(punit_focus->x, punit_focus->y);
+  punit = quickselect(ptile, qtype);
+
+  if (punit)
+    fastfocus(punit);
 }
 
 /**************************************************************************
 ...
+***************************************************************************/
+void key_batch_command(void)
+{
+  if (!batch_command)  {
+  batch_command = TRUE;
+  update_menus();
+  }
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+void cancel_batch_command(void)
+{
+  if (batch_command)  {
+    batch_command = FALSE;
+    update_menus();
+  }
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+void key_popup_diplomats_toggle(void)
+{
+  popup_diplomats ^= 1;
+  if (popup_diplomats)
+    append_output_window(_("Game: Diplomats use popups."));
+  else
+    append_output_window(_("Game: Diplomats will buy everything."));
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+void key_popup_caravans_toggle(void)
+{
+  popup_caravans ^= 1;
+  if (popup_caravans)
+    append_output_window(_("Game: Caravans will use popups."));
+  else
+    append_output_window(_("Game: Caravans will be silent."));
+}
+
+/**************************************************************************
+...
 **************************************************************************/
 void key_map_grid_toggle(void)
 {
@@ -1830,3 +3154,4 @@
 {
   request_toggle_fog_of_war();
 }
+
Index: client/control.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.h,v
retrieving revision 1.28
diff -u -r1.28 control.h
--- client/control.h	2002/03/17 09:11:51	1.28
+++ client/control.h	2002/10/06 05:00:18
@@ -15,25 +15,103 @@
 
 #include "packets.h"
 
+#define F_RADIUS 5
+
+enum quicktype {
+  NONE = 0,
+  SEA,
+  LAND
+};
+
+enum unit_filter {
+  FILTER_NORMAL = 0,        /* Focus Category filters */
+  FILTER_DIPLOMATS,
+  FILTER_CARAVANS,
+  FILTER_SETTLERS,
+  FILTER_AIRPLANES,
+  FILTER_HELICOPTERS,
+  FILTER_INFANTRY,
+  FILTER_WARSHIPS,
+  FILTER_TRANSPORTERS,
+
+  FILTER_NEW,               /* Exclusive filters */
+  FILTER_VETERAN,
+  FILTER_CURRENT_LOCATION,
+  FILTER_RADIUS,
+
+  FILTER_INCLUDE_SENTRIES,  /* Inclusive filters */
+  FILTER_INCLUDE_FORTIFIED,
+  FILTER_INCLUDE_EXHAUSTED,
+  FILTER_INCLUDE_GOTOS,
+  FILTER_INCLUDE_MEMBERS
+};
+
+enum batch_orders {
+  B_ORDERS_R_AND_R,
+  B_ORDERS_WAIT,
+  B_ORDERS_WAKEUP,
+  B_ORDERS_ASSIGN,
+  B_ORDERS_UNASSIGN,
+  B_ORDERS_GOTOMISSION,     /* With or without mission */
+  B_ORDERS_BUILD_WONDER,
+  B_ORDERS_AUTO,
+  B_ORDERS_SENTRY,
+  B_ORDERS_FORTIFY,
+  B_ORDERS_EXPLORE
+};
+
 enum cursor_hover_state {
   HOVER_NONE = 0,
   HOVER_GOTO,
   HOVER_NUKE,
   HOVER_PARADROP,
   HOVER_CONNECT,
-  HOVER_PATROL
+  HOVER_PATROL,
+  HOVER_BODYGUARD
 };
 
 extern int hover_unit; /* unit hover_state applies to */
 extern enum cursor_hover_state hover_state;
 extern bool draw_goto_line;
 
+extern bool batch_command;
+
+extern enum unit_filter focus_category; /* What we are focusing on */
+
+extern bool filter_new;
+extern bool filter_veteran;
+extern bool filter_current_location;
+extern bool filter_radius;
+extern bool filter_include_sentries;
+extern bool filter_include_fortified;
+extern bool filter_include_exhausted;
+extern bool filter_include_gotos;
+extern bool filter_include_members;
+
+
+void filter_units(enum unit_filter uf);
+void cancel_filters(void);
+bool unit_is_within_category(struct unit *punit);
+const char *get_category_name(void);
+
+void batch_orders(struct unit *firstunit,
+                  enum batch_orders bo, int x, int y);
+
+void fastfocus(struct unit *punit);
+void store_focus(void);
+void recall_previous_focus(void);
+
+void cancel_batch_command(void);
+void execute_order(struct unit *punit);
+void return_and_recover(struct unit *punit);
+struct unit *quickselect(struct tile *ptile, enum quicktype qtype);
+
 void do_move_unit(struct unit *punit, struct packet_unit_info *pinfo);
 void do_unit_goto(int x, int y);
 void do_unit_nuke(struct unit *punit);
 void do_unit_paradrop_to(struct unit *punit, int x, int y);
 void do_unit_patrol_to(struct unit *punit, int x, int y);
-void do_map_click(int xtile, int ytile);
+void do_map_click(int xtile, int ytile, enum quicktype qtype);
 
 void set_hover_state(struct unit *punit, enum cursor_hover_state state);
 void handle_advance_focus(struct packet_generic_integer *packet);
@@ -82,7 +160,7 @@
 void wakeup_sentried_units(int x, int y);
 
 void auto_center_on_focus_unit(void);
-void advance_unit_focus(void);
+void advance_unit_focus(bool try_harder);
 struct unit *get_unit_in_focus(void);
 void set_unit_focus(struct unit *punit);
 void set_unit_focus_no_center(struct unit *punit);
@@ -96,6 +174,12 @@
 void process_caravan_arrival(struct unit *punit);
 void process_diplomat_arrival(struct unit *pdiplomat, int victim_id);
 
+void key_batch_command(void);
+void key_popup_diplomats_toggle(void);
+void key_popup_caravans_toggle(void);
+void key_popup_cities_toggle(void);
+void key_auto_name_cities_toggle(void);
+
 void key_cancel_action(void);
 void key_city_names_toggle(void);
 void key_city_productions_toggle(void);
@@ -121,35 +205,36 @@
 void key_move_south_west(void);
 void key_move_west(void);
 void key_move_north_west(void);
-void key_unit_airbase(void);
-void key_unit_auto_attack(void);
-void key_unit_auto_explore(void);
-void key_unit_auto_settle(void);
-void key_unit_build_city(void);
-void key_unit_build_wonder(void);
+void key_unit_airbase(struct unit *punit);
+void key_unit_auto(struct unit *punit);
+void key_unit_auto_explore(struct unit *punit);
+void key_unit_build_city(struct unit *punit);
+void key_unit_build_wonder(struct unit *punit);
 void key_unit_connect(void);
 void key_unit_diplomat_actions(void);
-void key_unit_disband(void);
+void key_unit_disband(struct unit *punit);
 void key_unit_done(void);
-void key_unit_fallout(void);
-void key_unit_fortify(void);
-void key_unit_fortress(void);
+void key_unit_fallout(struct unit *punit);
+void key_unit_fortify(struct unit *punit);
+void key_unit_fortress(struct unit *punit);
 void key_unit_goto(void);
-void key_unit_homecity(void);
-void key_unit_irrigate(void);
-void key_unit_mine(void);
+void key_unit_homecity(struct unit *punit);
+void key_unit_irrigate(struct unit *punit);
+void key_unit_mine(struct unit *punit);
 void key_unit_nuke(void);
 void key_unit_patrol(void);
 void key_unit_paradrop(void);
 void key_unit_pillage(void);
-void key_unit_pollution(void);
-void key_unit_road(void);
-void key_unit_sentry(void);
-void key_unit_traderoute(void);
-void key_unit_transform(void);
-void key_unit_unload(void);
+void key_unit_pollution(struct unit *punit);
+void key_unit_road(struct unit *punit);
+void key_unit_sentry(struct unit *punit);
+void key_unit_traderoute(struct unit *punit);
+void key_unit_transform(struct unit *punit);
+void key_unit_unload(struct unit *punit);
 void key_unit_wait(void);
 void key_unit_wakeup_others(void);
+void key_unit_wakeup_self(void);
+void key_quick_unit(enum quicktype qtype);
 
 /* don't change this unless you also put more entries in data/Freeciv */
 #define MAX_NUM_UNITS_BELOW 4
Index: client/goto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.c,v
retrieving revision 1.40
diff -u -r1.40 goto.c
--- client/goto.c	2002/09/28 01:36:20	1.40
+++ client/goto.c	2002/10/06 05:00:21
@@ -36,7 +36,7 @@
 static int goto_array_length = INITIAL_ARRAY_LENGTH;
 
 /* points to where the next element should be inserted */
-static int goto_array_index = 0;
+int goto_array_index = 0;
 
 static struct map_position *goto_array = NULL;
 
@@ -831,6 +831,7 @@
 {
   struct packet_goto_route p;
   int i, j;
+  punit->never_moved = FALSE;
   p.unit_id = punit->id;
   p.length = goto_array_index * 2 + 1;
   p.first_index = 0;
@@ -857,6 +858,7 @@
 {
   struct packet_goto_route p;
   int i;
+  punit->never_moved = FALSE;
   p.unit_id = punit->id;
   p.length = goto_array_index + 1;
   p.first_index = 0;
@@ -868,4 +870,37 @@
   send_packet_goto_route(&aconnection, &p, ROUTE_GOTO);
   free(p.pos);
   p.pos = NULL;
+}
+
+/**************************************************************************
+...
+***************************************************************************/
+struct city *find_closest_owned_port(struct unit *punit, struct city *except)
+{
+  int check = -1;
+  int dist = 0;
+  struct city *rcity = NULL;
+
+  city_list_iterate(game.player_ptr->cities, pcity) {
+    if (is_terrain_near_tile(pcity->x, pcity->y, T_OCEAN)
+      && (!except || pcity != except))
+        dist = find_goto_distance(punit, pcity);
+
+    if (dist && (dist < check || check == -1)) {
+      check = dist;
+      rcity = pcity;
+    }
+  }
+  city_list_iterate_end;
+
+  return rcity;
+}
+
+/**************************************************************************
+Ideally, this should return the goto distance for punit to pcity.
+***************************************************************************/
+int find_goto_distance(struct unit *punit, struct city *pcity)
+{
+  return real_map_distance(punit->x, punit->y, pcity->x, pcity->y);
+
 }
Index: client/goto.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.h,v
retrieving revision 1.6
diff -u -r1.6 goto.h
--- client/goto.h	2002/09/28 01:36:20	1.6
+++ client/goto.h	2002/10/06 05:00:22
@@ -15,6 +15,8 @@
 
 #include "map.h"
 
+extern int goto_array_index;
+
 struct client_goto_map {
   short **move_cost;
   char **vector;
@@ -41,5 +43,8 @@
 
 void send_patrol_route(struct unit *punit);
 void send_goto_route(struct unit *punit);
+
+struct city *find_closest_owned_port(struct unit *punit, struct city *except);
+int find_goto_distance(struct unit *punit, struct city *pcity);
 
 #endif /* FC__GOTO_H */
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.12
diff -u -r1.12 mapview_common.c
--- client/mapview_common.c	2002/03/19 15:48:38	1.12
+++ client/mapview_common.c	2002/10/06 05:00:23
@@ -326,16 +326,17 @@
 {
   int turns = city_turns_to_build(pcity, pcity->currently_building,
 				  pcity->is_building_unit, TRUE);
-				
+  int cost = city_buy_cost(pcity);
+
   if (pcity->is_building_unit) {
     struct unit_type *punit_type =
 		get_unit_type(pcity->currently_building);
     if (turns < 999) {
-      my_snprintf(buffer, buffer_len, "%s %d",
-                  punit_type->name, turns);
+      my_snprintf(buffer, buffer_len, "%s %d/%d",
+                  punit_type->name, turns, cost);
     } else {
-      my_snprintf(buffer, buffer_len, "%s -",
-                  punit_type->name);
+      my_snprintf(buffer, buffer_len, "%s -/%d",
+                  punit_type->name, cost);
     }
   } else {
     struct impr_type *pimprovement_type =
@@ -343,11 +344,11 @@
     if (pcity->currently_building == B_CAPITAL) {
       my_snprintf(buffer, buffer_len, "%s", pimprovement_type->name);
     } else if (turns < 999) {
-      my_snprintf(buffer, buffer_len, "%s %d",
-		  pimprovement_type->name, turns);
+      my_snprintf(buffer, buffer_len, "%s %d/%d",
+		  pimprovement_type->name, turns, cost);
     } else {
-      my_snprintf(buffer, buffer_len, "%s -",
-                  pimprovement_type->name);
+      my_snprintf(buffer, buffer_len, "%s -/%d",
+                  pimprovement_type->name, cost);
     }
   }
 }
Index: client/options.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/options.c,v
retrieving revision 1.65
diff -u -r1.65 options.c
--- client/options.c	2002/08/15 20:24:08	1.65
+++ client/options.c	2002/10/06 05:00:27
@@ -49,6 +49,13 @@
 char default_sound_set_name[512] = "stdsounds";
 char default_sound_plugin_name[512] = "\0";
 
+/* Popup killers */
+
+bool auto_name_cities = TRUE;
+bool popup_cities = FALSE;
+bool popup_diplomats = TRUE;
+bool popup_caravans = FALSE;
+
 /** Local Options: **/
 
 bool solid_color_behind_units = FALSE;
Index: client/options.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/options.h,v
retrieving revision 1.20
diff -u -r1.20 options.h
--- client/options.h	2002/08/15 20:24:08	1.20
+++ client/options.h	2002/10/06 05:00:27
@@ -26,6 +26,13 @@
 extern char default_sound_set_name[512];
 extern char default_sound_plugin_name[512];
 
+/** Popups Menu: **/
+
+extern bool auto_name_cities;
+extern bool popup_cities;
+extern bool popup_diplomats;
+extern bool popup_caravans;
+
 /** Local Options: **/
 
 extern bool solid_color_behind_units;
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.256
diff -u -r1.256 packhand.c
--- client/packhand.c	2002/09/23 22:47:09	1.256
+++ client/packhand.c	2002/10/06 05:00:37
@@ -212,6 +212,12 @@
       show_combat = TRUE;
     }
 
+  /* Cancel goto if combat occured */
+  if (game.player_idx == punit0->owner && punit0->activity == ACTIVITY_GOTO)
+    request_new_unit_activity(punit0, ACTIVITY_IDLE);
+  if (game.player_idx == punit1->owner && punit1->activity == ACTIVITY_GOTO)
+    request_new_unit_activity(punit1, ACTIVITY_IDLE);
+
     if (show_combat) {
       int hp0 = packet->attacker_hp, hp1 = packet->defender_hp;
 
@@ -288,7 +294,6 @@
     player_set_unit_focus_status(game.player_ptr);
 
     update_info_label();	/* get initial population right */
-    update_unit_focus();
     update_unit_info_label(get_unit_in_focus());
 
     /* Find something sensible to display instead of the intro gfx. */
@@ -439,7 +444,7 @@
   } impr_type_iterate_end;
 
   popup = (city_is_new && get_client_state()==CLIENT_GAME_RUNNING_STATE && 
-           pcity->owner==game.player_idx) || packet->diplomat_investigate;
+           pcity->owner==game.player_idx && popup_cities) || packet->diplomat_investigate;
 
   if (city_is_new && !city_has_changed_owner) {
     agents_city_new(pcity);
@@ -656,7 +661,6 @@
   update_info_label();
 
   player_set_unit_focus_status(game.player_ptr);
-  update_unit_focus();
   auto_center_on_focus_unit();
 
   update_unit_info_label(get_unit_in_focus());
@@ -795,6 +799,9 @@
   struct unit *punit;
   bool repaint_unit;
   bool repaint_city;		/* regards unit's homecity */
+  bool check_focus = FALSE;   /* conservative focus change */
+  bool process_carv = TRUE;
+
   /* Special case for a diplomat/spy investigating a city:
      The investigator needs to know the supported and present
      units of a city, whether or not they are fogged. So, we
@@ -838,15 +845,60 @@
   punit = player_find_unit_by_id(get_player(packet->owner), packet->id);
 
   if(punit) {
+    struct unit *bodyguard=player_find_unit_by_id(game.player_ptr, punit->ai.bodyguard);
+    struct unit *VIU=player_find_unit_by_id(game.player_ptr, punit->ai.charge);
     int dest_x,dest_y;
     punit->activity_count = packet->activity_count;
     if((punit->activity!=packet->activity)         /* change activity */
        || (punit->activity_target!=packet->activity_target)) { /*   or act's target */
+
+    /* Bodyguard apes the VIU (punit) when VIU (punit) changes activity */
+    if (bodyguard && (bodyguard->x == packet->x && bodyguard->y == packet->y))  {
+      if (packet->activity==ACTIVITY_SENTRY)
+        request_new_unit_activity(bodyguard, ACTIVITY_SENTRY);
+      else if (packet->activity==ACTIVITY_FORTIFYING)
+        request_new_unit_activity(bodyguard, ACTIVITY_FORTIFYING);
+    }
+
+      /* a goto was completed or cancelled */
+      if(punit->owner==game.player_idx && punit->activity==ACTIVITY_GOTO) {
+          bg_un_target_tile(punit);
+        /* failed to reach destination */
+        if(punit->goto_dest_x != packet->x || punit->goto_dest_y != packet->y) {
+          punit->mission_flag = FALSE;
+        }
+    /* A bodyguard (punit) arrives and finds VIU sentried/fortif. Copy that. */
+    if (VIU && (VIU->x == packet->x && VIU->y == packet->y))  {
+      if (VIU->activity==ACTIVITY_SENTRY)
+        request_new_unit_activity(punit, ACTIVITY_SENTRY);
+      else if (VIU->activity==ACTIVITY_FORTIFYING || VIU->activity==ACTIVITY_FORTIFIED)
+        request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
+    }
+      }
+
+      /* May change focus if focus unit gets a new activity.
+         But if new activity is Idle, it means user specifically selected the unit */
+      if(punit == get_unit_in_focus() && packet->activity != ACTIVITY_IDLE)
+        check_focus = TRUE;
+
       repaint_unit = TRUE;
-      if(wakeup_focus && (punit->owner==game.player_idx)
-                      && (punit->activity==ACTIVITY_SENTRY)) {
-        set_unit_focus(punit);
-        /* RP: focus on (each) activated unit (e.g. when unloading a ship) */
+
+      /* Need to separate client batch wakeups from server-initiated wakeups.
+         Client should set punit->activity==ACTIVITY_IDLE before requesting
+         that from the server. Otherwise enemy encounter is indistinguishable here. */
+      if(wakeup_focus
+        && (punit->owner==game.player_idx)
+        && (punit->activity==ACTIVITY_SENTRY)
+        && (packet->activity==ACTIVITY_IDLE)
+        && (packet->movesleft > 0)
+        && (!get_unit_in_focus()  /* only 1 wakeup focus per tile is useful */
+          || !(packet->x==get_unit_in_focus()->x && packet->y==get_unit_in_focus()->y))) {
+        fastfocus(punit);
+        check_focus = FALSE;    /* and keep it */
+
+        /* autocenter on wakeup regardless of local option auto_center_on_unit */
+        if  (!tile_visible_and_not_on_border_mapcanvas(punit->x, punit->y))
+          center_tile_mapcanvas(punit->x, punit->y);
       }
 
       punit->activity=packet->activity;
@@ -856,14 +908,13 @@
         refresh_unit_city_dialogs(punit);
       /*      refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
        *      update_unit_pix_label(punit);
-       *      update_unit_focus();
        */
 
       /* These two lines force the menus to be updated as appropriate when
 	 the unit activity changes. */
       if(punit == get_unit_in_focus())
          update_menus();
-    }
+    } /* end of change activity */
     
     if(punit->homecity!=packet->homecity) { /* change homecity */
       struct city *pcity;
@@ -896,8 +947,25 @@
     if (punit->ai.control!=packet->ai) {
       punit->ai.control=packet->ai;
       repaint_unit = TRUE;
+       if (packet->ai) {    /* But if ai control is cleared, keep focus */
+         check_focus = TRUE;}
+     }
+ 
+     /* May change focus if an attempted move or attack exhausted unit */
+     if (punit->moves_left!=packet->movesleft && punit==get_unit_in_focus()) {
+         check_focus = TRUE;
     }
 
+     /* This update needs to be here and is used below */
+    punit->veteran=packet->veteran;
+    punit->moves_left=packet->movesleft;
+    punit->bribe_cost=0;
+    punit->fuel=packet->fuel;
+    punit->goto_dest_x=packet->goto_dest_x;
+    punit->goto_dest_y=packet->goto_dest_y;
+    punit->paradropped=packet->paradropped;
+    punit->connecting=packet->connecting;
+
     if (!same_pos(punit->x, punit->y, packet->x, packet->y)) { 
       /* change position */
       struct city *pcity;
@@ -907,8 +975,30 @@
          && player_can_see_unit_at_location(game.player_ptr, punit, 
                                             packet->x, packet->y)) {
 	do_move_unit(punit, packet);
-	update_unit_focus();
-      }
+	if(punit->owner==game.player_idx) {   /* Owned unit */
+ 
+	    /* VIU arrives at bg's tile - cancel bg's old goto */
+	    if (bodyguard && bodyguard->x == punit->x && bodyguard->y == punit->y
+		&& bodyguard->activity == ACTIVITY_GOTO)
+		request_new_unit_activity(bodyguard, ACTIVITY_IDLE);
+
+	    /* VIU moved - Issue goto for bodyguard */
+	    if (bodyguard && (bodyguard->x != punit->x || bodyguard->y != punit->y)
+		&& (punit->moves_left==0 || punit->activity != ACTIVITY_GOTO
+		    || (punit->goto_dest_x==punit->x && punit->goto_dest_y==punit->y))
+		&& !packet->carried) {
+		send_goto_unit(bodyguard, punit->x, punit->y);
+	    }
+ 
+	    /* A mission destination was reached. Orders? */
+	    if(punit->goto_dest_x==punit->x && punit->goto_dest_y==punit->y
+	       && punit->mission_flag) {
+		execute_order(punit);
+		process_carv = FALSE;  /* Caravan with mission not to cause any popups */
+	    }
+	} /* end of owned unit */
+ 
+      } /* end of tile known */
       else {
 	do_move_unit(punit, packet); /* nice to see where a unit is going */
 	client_remove_unit(punit);
@@ -935,13 +1025,14 @@
 	       same_pos(punit->goto_dest_x, punit->goto_dest_y,
 			pcity->x, pcity->y))
 	   && (unit_can_help_build_wonder_here(punit)
-	       || unit_can_est_traderoute_here(punit))) {
+	       || unit_can_est_traderoute_here(punit))
+       && (popup_caravans) && (process_carv) && (!punit->mission_flag)) {
 	  process_caravan_arrival(punit);
 	}
       }
       
       repaint_unit = FALSE;
-    }
+    } /* end of change position */
     if (punit->unhappiness!=packet->unhappiness) {
       punit->unhappiness=packet->unhappiness;
       repaint_city = TRUE;
@@ -963,15 +1054,6 @@
 	refresh_city_dialog(pcity);
       }
     }
-
-    punit->veteran=packet->veteran;
-    punit->moves_left=packet->movesleft;
-    punit->bribe_cost=0;
-    punit->fuel=packet->fuel;
-    punit->goto_dest_x=packet->goto_dest_x;
-    punit->goto_dest_y=packet->goto_dest_y;
-    punit->paradropped=packet->paradropped;
-    punit->connecting=packet->connecting;
   
     dest_x = packet->x;
     dest_y = packet->y;
@@ -981,11 +1063,25 @@
       refresh_tile_mapcanvas(dest_x, dest_y, TRUE);
     }
     agents_unit_changed(punit);
+
+    /* special settler mission case */
+    if(punit->mission_flag && punit->orders==ORDERS_BUILD_NOW && punit->moves_left)  {
+      request_unit_build_city(punit);
+      punit->mission_flag = FALSE;
+    }
+
   }
 
   else {      /* create new unit */
     punit=fc_malloc(sizeof(struct unit));
     unpackage_unit(punit, packet);
+    punit->never_moved = TRUE;
+    punit->ai.bodyguard = 0;
+    punit->ai.charge = 0;
+    punit->mission_flag = FALSE;
+    punit->bg = 0;
+    punit->zx = -1;
+    punit->zy = -1;
     idex_register_unit(punit);
 
     unit_list_insert(&get_player(packet->owner)->units, punit);
@@ -1014,11 +1110,8 @@
   if(repaint_unit)
     refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
 
-  if(packet->select_it && (punit->owner==game.player_idx)) {
-    set_unit_focus_and_select(punit);
-  } else {
+  if (check_focus || get_unit_in_focus()==NULL)
     update_unit_focus(); 
-  }
 }
 
 /**************************************************************************
@@ -1117,7 +1210,6 @@
     boot_help_texts();		/* reboot, after setting game.spacerace */
   }
 
-  update_unit_focus();
 }
 
 /**************************************************************************
@@ -2199,7 +2291,13 @@
   
   punit = player_find_unit_by_id(game.player_ptr, packet->id);
   if (punit) {
-    popup_newcity_dialog(punit, packet->name);
+    if (auto_name_cities) {
+      struct packet_unit_request req;
+      req.unit_id=punit->id;
+      sz_strlcpy(req.name, packet->name);
+      send_packet_unit_request(&aconnection, &req, PACKET_UNIT_BUILD_CITY);
+    } else
+      popup_newcity_dialog(punit, packet->name);
     return;
   }
   /* maybe unit died; ignore */
Index: client/packhand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.h,v
retrieving revision 1.29
diff -u -r1.29 packhand.h
--- client/packhand.h	2002/09/10 14:01:06	1.29
+++ client/packhand.h	2002/10/06 05:00:37
@@ -15,6 +15,8 @@
 
 #include "packets.h"
 
+#include "battlegroups.h"
+
 void handle_join_game_reply(struct packet_join_game_reply *packet);
 
 void handle_tile_info(struct packet_tile_info *packet);
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.85
diff -u -r1.85 tilespec.c
--- client/tilespec.c	2002/09/28 01:36:20	1.85
+++ client/tilespec.c	2002/10/06 05:00:44
@@ -582,6 +582,15 @@
   SET_SPRITE(unit.transform,    "unit.transform");
   SET_SPRITE(unit.connect,      "unit.connect");
   SET_SPRITE(unit.patrol,       "unit.patrol");
+  SET_SPRITE(unit.veteran,      "unit.veteran");
+  SET_SPRITE(unit.bodyguard,    "unit.bodyguard");
+  SET_SPRITE(unit.mission_flag, "unit.mission_flag");
+  SET_SPRITE(unit.mission_build, "unit.mission_build");
+
+  for(i=0; i<NUM_BATTLEGROUPS; i++) {
+    my_snprintf(buffer, sizeof(buffer), "unit.battlegroup%d", i + 1);
+    SET_SPRITE(unit.battlegroup[i], buffer);
+  }
 
   for(i=0; i<NUM_TILES_HP_BAR; i++) {
     my_snprintf(buffer, sizeof(buffer), "unit.hp_%d", i*10);
@@ -612,6 +621,8 @@
   SET_SPRITE(upkeep.shield, "upkeep.shield");
   
   SET_SPRITE(user.attention, "user.attention");
+  SET_SPRITE(user.units_selected, "user.units_selected");
+  SET_SPRITE(user.city_selected,  "user.city_selected");
 
   SET_SPRITE(tx.fallout,    "tx.fallout");
   SET_SPRITE(tx.farmland,   "tx.farmland");
@@ -1070,6 +1081,75 @@
   ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
   *sprs++ = sprites.unit.hp_bar[ihp];
 
+  if (punit->ai.bodyguard || punit->ai.charge) {
+    *sprs++ = sprites.unit.bodyguard;
+  }
+
+  if (punit->veteran) {
+    *sprs++ = sprites.unit.veteran;
+  }
+
+  if (punit->mission_flag)  {
+    if (punit->orders==ORDERS_BUILD || punit->orders==ORDERS_BUILD_NOW)
+      *sprs++ = sprites.unit.mission_build;
+    else
+      *sprs++ = sprites.unit.mission_flag;
+  }
+
+  /*  In non-isometric mode,
+   * 'A'uto and 'X'plore sprites collide with the group icon.
+  */
+  if (punit->bg && (is_isometric || (punit->activity!=ACTIVITY_EXPLORE
+                                     && !punit->ai.control))) {
+    *sprs++ = sprites.unit.battlegroup[punit->bg - 1];
+  }
+
+  /* Temporary mission indication */
+  if (hover_state==HOVER_GOTO && punit->mission_flag) {
+    struct Sprite *s = NULL;
+    switch (punit->orders)  {
+    case ORDERS_AUTO:
+      if(is_military_unit(punit))
+        s = sprites.unit.auto_attack;
+      else
+        s = sprites.unit.auto_settler;
+      break;
+    case ORDERS_MINE:
+      s = sprites.unit.mine;
+      break;
+    case ORDERS_POLLUTION:
+      s = sprites.unit.pollution;
+      break;
+    case ORDERS_FALLOUT:
+      s = sprites.unit.fallout;
+      break;
+    case ORDERS_ROAD:
+      s = sprites.unit.road;
+      break;
+    case ORDERS_IRRIGATE:
+      s = sprites.unit.irrigate;
+      break;
+    case ORDERS_EXPLORE:
+      s = sprites.unit.auto_explore;
+      break;
+    case ORDERS_FORTIFY:
+      s = sprites.unit.fortifying;
+      break;
+    case ORDERS_AIRBASE:
+      s = sprites.unit.airbase;
+      break;
+    case ORDERS_SENTRY:
+      s = sprites.unit.sentry;
+      break;
+    case ORDERS_TRANSFORM:
+      s = sprites.unit.transform;
+      break;
+    default:
+      break;
+    }
+    *sprs++ = s;
+  }
+
   return sprs - save_sprs;
 }
 
@@ -1323,6 +1403,11 @@
     dither[dir] = get_dither(ttype, other);
   }
 
+  if (map_get_tile(x, y)->selected == 1)
+    *sprs++ = sprites.user.city_selected;
+  else if (map_get_tile(x, y)->selected == 2)
+    *sprs++ = sprites.user.units_selected;
+
   return sprs - save_sprs;
 }
 
@@ -1633,6 +1718,12 @@
       }
     }
   }
+
+  if (ptile->selected == 1)
+    *sprs++ = sprites.user.city_selected;
+  else if (ptile->selected == 2)
+    *sprs++ = sprites.user.units_selected;
+
 
   return sprs - save_sprs;
 }
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.30
diff -u -r1.30 tilespec.h
--- client/tilespec.h	2002/09/28 01:36:20	1.30
+++ client/tilespec.h	2002/10/06 05:00:45
@@ -20,6 +20,8 @@
 #define FC__TILESPEC_H
 #include "map.h"		/* NUM_DIRECTION_NSEW */
 
+#include "battlegroups.h"
+
 #include "colors_g.h"
 
 struct Sprite;			/* opaque; gui-dep */
@@ -117,6 +119,11 @@
   } explode;
   struct {
     struct Sprite
+      *bodyguard,
+      *veteran,
+      *mission_build,
+      *mission_flag,
+      *battlegroup[NUM_BATTLEGROUPS],
       *hp_bar[NUM_TILES_HP_BAR],
       *auto_attack,
       *auto_settler,
@@ -157,7 +164,10 @@
       ***tile;
   } city;
   struct {
-    struct Sprite *attention;
+    struct Sprite
+      *attention,
+      *units_selected,
+      *city_selected;
   } user;
   struct {
     struct Sprite
Index: client/gui-gtk/cityrep.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/cityrep.c,v
retrieving revision 1.64
diff -u -r1.64 cityrep.c
--- client/gui-gtk/cityrep.c	2002/09/25 20:24:51	1.64
+++ client/gui-gtk/cityrep.c	2002/10/06 05:00:51
@@ -87,6 +87,47 @@
 static int city_dialog_shell_is_modal;
 
 /****************************************************************
+ Area selection with mouse-drag on mapcanvas.
+*****************************************************************/
+void cities_on_map_selection(void)
+{
+  gint i;
+
+  if (!city_dialog_shell)
+    return;
+
+  gtk_clist_unselect_all( GTK_CLIST(city_list));
+
+  for(i = 0; i < GTK_CLIST(city_list)->rows; i++)
+  {
+    struct city *pcity = gtk_clist_get_row_data(GTK_CLIST(city_list), i);
+
+    if (map_get_tile(pcity->x, pcity->y)->selected)
+      gtk_clist_select_row(GTK_CLIST(city_list), i, 0);
+  }
+
+  return;
+}
+
+/****************************************************************
+...
+*****************************************************************/
+void city_on_map_select(struct city *pcity, bool on_off)
+{
+  gint i;
+
+  if (!city_dialog_shell)
+    return;
+
+  i = gtk_clist_find_row_from_data(GTK_CLIST(city_list), pcity);
+
+  if (on_off)
+	gtk_clist_select_row(GTK_CLIST(city_list), i, 0);     
+  else
+	gtk_clist_unselect_row(GTK_CLIST(city_list), i, 0);
+}
+
+/****************************************************************
  Sort cities by column...
 *****************************************************************/
 static void sort_cities_callback( GtkButton *button, gpointer *data )
Index: client/gui-gtk/cityrep.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/cityrep.h,v
retrieving revision 1.1
diff -u -r1.1 cityrep.h
--- client/gui-gtk/cityrep.h	1999/07/20 11:43:14	1.1
+++ client/gui-gtk/cityrep.h	2002/10/06 05:00:51
@@ -15,6 +15,9 @@
 
 #include "cityrep_g.h"
 
+void cities_on_map_selection(void);
+void city_on_map_select(struct city *pcity, bool on_off);
+
 /* nothing else */
 
 #endif  /* FC__CITYREP_H */
Index: client/gui-gtk/dialogs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/dialogs.c,v
retrieving revision 1.107
diff -u -r1.107 dialogs.c
--- client/gui-gtk/dialogs.c	2002/09/28 13:52:51	1.107
+++ client/gui-gtk/dialogs.c	2002/10/06 05:01:00
@@ -388,8 +388,12 @@
 void popup_bribe_dialog(struct unit *punit)
 {
   char buf[128];
+  char msg[MAX_LEN_MSG];
   
   if(game.player_ptr->economic.gold>=punit->bribe_cost) {
+      if (!popup_diplomats)
+        diplomat_bribe_yes_callback(0);
+      else  {
     my_snprintf(buf, sizeof(buf),
 		_("Bribe unit for %d gold?\nTreasury contains %d gold."), 
 		punit->bribe_cost, game.player_ptr->economic.gold);
@@ -397,11 +401,18 @@
 			 dummy_close_callback, NULL,
 			 _("_Yes"), diplomat_bribe_yes_callback, 0, 
 			 _("_No"), NULL, 0, 0);
+      }
   } else {
     my_snprintf(buf, sizeof(buf),
 		_("Bribing the unit costs %d gold.\n"
 		  "Treasury contains %d gold."), 
 		punit->bribe_cost, game.player_ptr->economic.gold);
+      if (!popup_diplomats) {
+        my_snprintf(msg, sizeof(msg),
+          _("Game: Bribing the unit costs %d gold. Treasury contains %d gold."),
+		  punit->bribe_cost, game.player_ptr->economic.gold);
+        append_output_window(msg);
+      } else
     popup_message_dialog(top_vbox, _("Traitors Demand Too Much!"), buf,
 			 dummy_close_callback, NULL, _("Darn"), NULL, 0, 0);
   }
@@ -948,14 +959,22 @@
 void popup_incite_dialog(struct city *pcity)
 {
   char buf[128];
+  char msg[MAX_LEN_MSG];
 
   if (pcity->incite_revolt_cost == INCITE_IMPOSSIBLE_COST) {
     my_snprintf(buf, sizeof(buf), _("You can't incite a revolt in %s."),
 		pcity->name);
-    popup_message_dialog(top_vbox, _("City can't be incited!"), buf,
+    if (!popup_diplomats) {
+      my_snprintf(msg, sizeof(msg), _("Game: %s"), buf);
+      append_output_window(msg);
+    } else
+      popup_message_dialog(top_vbox, _("City can't be incited!"), buf,
 			 diplomat_incite_close_callback, NULL,
 			 _("Darn"), NULL, 0, 0);
   } else if (game.player_ptr->economic.gold >= pcity->incite_revolt_cost) {
+      if (!popup_diplomats)
+        diplomat_incite_yes_callback(0);
+      else  {
     my_snprintf(buf, sizeof(buf),
 		_("Incite a revolt for %d gold?\nTreasury contains %d gold."), 
 		pcity->incite_revolt_cost, game.player_ptr->economic.gold);
@@ -963,11 +982,18 @@
 			diplomat_incite_close_callback, NULL,
 		       _("_Yes"), diplomat_incite_yes_callback, 0,
 		       _("_No"), NULL, 0, 0);
+      }
   } else {
     my_snprintf(buf, sizeof(buf),
 		_("Inciting a revolt costs %d gold.\n"
 		  "Treasury contains %d gold."), 
 		pcity->incite_revolt_cost, game.player_ptr->economic.gold);
+    if (!popup_diplomats) {
+      my_snprintf(msg, sizeof(msg),
+      _("Game: Inciting a revolt costs %d gold. Treasury contains %d gold."),
+      pcity->incite_revolt_cost, game.player_ptr->economic.gold);
+      append_output_window(msg);
+    } else
    popup_message_dialog(top_vbox, _("Traitors Demand Too Much!"), buf,
 			diplomat_incite_close_callback, NULL,
 		       _("Darn"), NULL, 0, 
@@ -1020,6 +1046,18 @@
 
   diplomat_id=punit->id;
 
+  if (!popup_diplomats) { /* revolt or bribe, don't ask */
+    if((pcity=map_get_city(dest_x, dest_y))){
+      diplomat_target_id=pcity->id;
+      diplomat_incite_callback(0);
+    }else{ 
+      if((ptunit=unit_list_get(&map_get_tile(dest_x, dest_y)->units, 0))){
+        diplomat_target_id=ptunit->id;
+        diplomat_bribe_callback(0);
+      }
+    }
+  } else  { /* use popup */
+
   if((pcity=map_get_city(dest_x, dest_y))){
     /* Spy/Diplomat acting against a city */
 
@@ -1105,6 +1143,7 @@
        if(!diplomat_can_do_action(punit, SPY_SABOTAGE_UNIT, dest_x, dest_y))
         message_dialog_button_set_sensitive(shl,"button1",FALSE);
     }
+  }
   }
 }
 
Index: client/gui-gtk/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/gui_main.c,v
retrieving revision 1.115
diff -u -r1.115 gui_main.c
--- client/gui-gtk/gui_main.c	2002/09/28 01:36:22	1.115
+++ client/gui-gtk/gui_main.c	2002/10/06 05:01:05
@@ -41,6 +41,7 @@
 #include "support.h"
 #include "version.h"
 
+#include "battlegroups.h"
 #include "chatline.h"
 #include "civclient.h"
 #include "climisc.h"
@@ -63,7 +64,6 @@
 #include "resources.h"
 #include "tilespec.h"
 
-
 #include "freeciv.ico"
 
 const char *client_string = "gui-gtk";
@@ -188,6 +188,8 @@
 **************************************************************************/
 static gint keyboard_handler(GtkWidget *w, GdkEventKey *ev)
 {
+  struct unit *funit = get_unit_in_focus();
+  bool common = FALSE;
   /* inputline history code */
   if (GTK_WIDGET_HAS_FOCUS(inputline) || !GTK_WIDGET_IS_SENSITIVE(top_vbox)) {
     void *data = NULL;
@@ -226,131 +228,112 @@
 
   if (is_isometric && !client_is_observer()) {
     switch (ev->keyval) {
-      case GDK_Up:
       case GDK_KP_Up:
-      case GDK_8:
       case GDK_KP_8: 		key_move_north_west();	break;
 
-      case GDK_Page_Up:
       case GDK_KP_Page_Up:
-      case GDK_9:
       case GDK_KP_9: 		key_move_north();	break;
 
-      case GDK_Right:
       case GDK_KP_Right:
-      case GDK_6:
       case GDK_KP_6: 		key_move_north_east();	break;
 
-      case GDK_Page_Down:
       case GDK_KP_Page_Down:
-      case GDK_3:
       case GDK_KP_3: 		key_move_east();	break;
 
-      case GDK_Down:
       case GDK_KP_Down:
-      case GDK_2:
       case GDK_KP_2: 		key_move_south_east();	break;
 
-      case GDK_End:
       case GDK_KP_End:
-      case GDK_1:
       case GDK_KP_1: 		key_move_south();	break;
 
-      case GDK_Left:
       case GDK_KP_Left:
-      case GDK_4:
       case GDK_KP_4: 		key_move_south_west();	break;
 
-      case GDK_Home:
       case GDK_KP_Home:
-      case GDK_7:
       case GDK_KP_7: 		key_move_west();	break;
- 
-      case GDK_KP_Begin:
-      case GDK_5:
-      case GDK_KP_5:
-        focus_to_next_unit();
-        break;
-  
-      case GDK_Return:
-      case GDK_KP_Enter:
-        key_end_turn();
-        break;
-  
-      case GDK_Escape:
-        key_cancel_action();
-        break;
-  
-      case GDK_t:
-        key_city_workers(w, ev);
-        break;
 
-      default:
-        return FALSE;
+      default:              common = TRUE;    break;
     }
   } else if (!client_is_observer()) {
     switch (ev->keyval) {
-      case GDK_Up:
       case GDK_KP_Up:
-      case GDK_8:
       case GDK_KP_8: 		key_move_north();	break;
 
-      case GDK_Page_Up:
       case GDK_KP_Page_Up:
-      case GDK_9:
       case GDK_KP_9: 		key_move_north_east();	break;
 
-      case GDK_Right:
       case GDK_KP_Right:
-      case GDK_6:
       case GDK_KP_6: 		key_move_east();	break;
 
-      case GDK_Page_Down:
       case GDK_KP_Page_Down:
-      case GDK_3:
       case GDK_KP_3: 		key_move_south_east();	break;
 
-      case GDK_Down:
       case GDK_KP_Down:
-      case GDK_2:
       case GDK_KP_2: 		key_move_south();	break;
 
-      case GDK_End:
       case GDK_KP_End:
-      case GDK_1:
       case GDK_KP_1: 		key_move_south_west();	break;
 
-      case GDK_Left:
       case GDK_KP_Left:
-      case GDK_4:
       case GDK_KP_4: 		key_move_west();	break;
 
-      case GDK_Home:
       case GDK_KP_Home:		
-      case GDK_7:
       case GDK_KP_7: 		key_move_north_west();	break;
 
-      case GDK_KP_Begin:
-      case GDK_Return:
-      case GDK_KP_Enter:
-        key_end_turn();
-        break;
-  
-      case GDK_5:
-      case GDK_KP_5: 
-        focus_to_next_unit(); 
-        break;
-  
-      case GDK_Escape:
-        key_cancel_action();
-        break;
-  
-      case GDK_t:
-        key_city_workers(w, ev);
-        break;
+      default:              common = TRUE;    break;
+    }
+  }
+
+  if (common) {             /* Common to both modes */
+    switch (ev->keyval) {
+
+  case GDK_Return:
+  case GDK_KP_Enter:      key_end_turn();             break;
 
-      default:
-        return FALSE;
+  case GDK_KP_Begin:
+  case GDK_KP_5:          focus_to_next_unit();       break;
+
+  case GDK_Escape:        key_cancel_action();        break;
+
+  case GDK_bar:           recall_previous_focus();    break;
+
+  case GDK_Left:          scroll_map(DIR8_WEST);      break;
+  case GDK_Right:         scroll_map(DIR8_EAST);      break;
+  case GDK_Up:            scroll_map(DIR8_NORTH);     break;
+  case GDK_Down:          scroll_map(DIR8_SOUTH);     break;
+
+  case GDK_Insert:        bg_key_assign_unit(funit,
+                          last_group - 1);                  break;
+  case GDK_Delete:        bg_key_unassign_unit(funit);      break;
+
+  case GDK_Home:          request_center_capital();   break;
+
+  case GDK_Page_Up:       bg_groups_browse(TRUE);     break;
+  case GDK_Page_Down:     bg_groups_browse(FALSE);    break;
+
+  case GDK_KP_Add:        bg_browse(TRUE);            break;
+  case GDK_KP_Subtract:   bg_browse(FALSE);           break;
+
+  case GDK_KP_Insert:
+  case GDK_KP_0:          bg_test_map();              break;
+
+  case GDK_KP_Multiply:   key_quick_unit(LAND);       break;
+  case GDK_KP_Divide:     key_quick_unit(SEA);        break;
+
+  /* Battlegroups map bookmarks. GTK menus will
+   * not read shift number keys !"#¤%&/()
+  */
+  case GDK_exclam:        bg_define_zero(0);          break;
+  case GDK_quotedbl:      bg_define_zero(1);          break;
+  case GDK_numbersign:    bg_define_zero(2);          break;
+  case GDK_currency:      bg_define_zero(3);          break;
+  case GDK_percent:       bg_define_zero(4);          break;
+  case GDK_ampersand:     bg_define_zero(5);          break;
+  case GDK_slash:         bg_define_zero(6);          break;
+  case GDK_parenleft:     bg_define_zero(7);          break;
+  case GDK_parenright:    bg_define_zero(8);          break;
+
+  default:  return FALSE;
     }
   }
 
@@ -643,6 +626,7 @@
 
   gtk_widget_set_events(map_canvas, GDK_EXPOSURE_MASK
                                    |GDK_BUTTON_PRESS_MASK
+                                   |GDK_BUTTON_RELEASE_MASK
                                    |GDK_KEY_PRESS_MASK
                                    |GDK_POINTER_MOTION_MASK);
 
@@ -665,6 +649,9 @@
 
   gtk_signal_connect(GTK_OBJECT(map_canvas), "button_press_event",
                      GTK_SIGNAL_FUNC(butt_down_mapcanvas), NULL);
+
+  gtk_signal_connect(GTK_OBJECT(map_canvas), "button_release_event",
+                     GTK_SIGNAL_FUNC(butt_release_mapcanvas), NULL);
 
   gtk_signal_connect(GTK_OBJECT(toplevel), "key_press_event",
                      GTK_SIGNAL_FUNC(keyboard_handler), NULL);
Index: client/gui-gtk/mapctrl.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapctrl.c,v
retrieving revision 1.67
diff -u -r1.67 mapctrl.c
--- client/gui-gtk/mapctrl.c	2002/09/11 17:04:40	1.67
+++ client/gui-gtk/mapctrl.c	2002/10/06 05:01:08
@@ -24,6 +24,7 @@
 #include "support.h"
 #include "unit.h"
 
+#include "battlegroups.h"
 #include "chatline.h"
 #include "citydlg.h"
 #include "civclient.h"
@@ -48,6 +49,303 @@
 /* Color to use to display the workers */
 int city_workers_color = COLOR_STD_WHITE;
 
+/* Copy and Paste city production, defaults to Settler (0) */
+static int clipboard = 0;
+static int clipboard_is_unit = 1;
+
+/* Selection Rectangle */
+static int  first_x, first_y, old_x, old_y;
+/* NW & SE corners after a selection */
+static int rect_x1, rect_y1, rect_x2, rect_y2;
+static bool rbutton_down = FALSE;
+static bool rectangle_active = FALSE;
+
+/* This changes the behaviour of left mouse button */
+bool tile_cities_active = FALSE;
+bool tile_units_active  = FALSE;
+
+/*************************************************************************/
+
+static void draw_rectangle(int src_x, int src_y, int dest_x, int dest_y,
+                           bool draw);
+static void update_rect(void);
+static void select_rect_tiles(void);
+static void toggle_tile_select(int x, int y);
+static bool tile_has_suitable_unit(struct tile *ptile);
+
+static void buy_production(struct city *pcity);
+static void copy_production(int x, int y);
+static void paste_production(struct city *pcity);
+static void send_production_packet(struct city *pcity);
+
+/**************************************************************************
+ Define Zero for battlegroup
+**************************************************************************/
+void bg_define_zero(int group)
+{
+  int x, y;
+
+  if (get_client_state() != CLIENT_GAME_RUNNING_STATE)
+    return;
+  
+  gdk_window_get_pointer(map_canvas->window, &x, &y, NULL);
+  get_map_xy(x, y, &x, &y);
+
+  if (bg[group]->zx != -1)
+    refresh_tile_mapcanvas(bg[group]->zx, bg[group]->zy, TRUE);
+
+  bg[group]->zx = x;
+  bg[group]->zy = y;
+
+  put_cross_overlay_tile(x, y);
+  last_group = group + 1;
+}
+
+/**************************************************************************
+ Focus on Zero
+**************************************************************************/
+void bg_focus_zero(int group)
+{
+  if (get_client_state() != CLIENT_GAME_RUNNING_STATE)
+    return;
+
+  if (bg[group]->zx == -1)  {
+    char msg[MAX_LEN_MSG];
+    my_snprintf(msg, sizeof(msg), _("Game: %s %d has not been directed!"),
+      bg[group]->name, group + 1);
+    append_output_window(msg);
+    return;
+  }
+
+  center_tile_mapcanvas(bg[group]->zx, bg[group]->zy);
+  put_cross_overlay_tile(bg[group]->zx, bg[group]->zy);
+  last_group = group + 1;
+}
+
+/**************************************************************************
+ Go home
+**************************************************************************/
+void request_center_capital(void)
+{
+  struct city *capital = find_palace(game.player_ptr);
+
+  if (capital)  {
+    center_tile_mapcanvas(capital->x, capital->y);
+    put_cross_overlay_tile(capital->x, capital->y);
+  } else
+  append_output_window(_("Game: Oh my! You seem to have no capital!"));
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void scroll_map(int dir)
+{
+  int pos_x, pos_y;
+  int width, height;
+
+  gdk_window_get_size(map_canvas->window, &width, &height);
+  width /= single_tile_pixmap_width;
+  height /= single_tile_pixmap_height;
+  get_center_tile_mapcanvas(&pos_x, &pos_y);
+
+  if (is_isometric)  {
+    switch (dir)  {
+      case  DIR8_EAST:  pos_x += width/2;
+                        pos_y -= height/2;  break;
+      case  DIR8_WEST:  pos_x -= width/2;
+                        pos_y += height/2;  break;
+      case  DIR8_NORTH: pos_y -= height/2;
+                        pos_x -= width/2;   break;
+      case  DIR8_SOUTH: pos_y += height/2;
+                        pos_x += width/2;   break;
+    }
+  } else  {
+    switch (dir)  {
+      case  DIR8_EAST:  pos_x += width/2;   break;
+      case  DIR8_WEST:  pos_x -= width/2;   break;
+      case  DIR8_NORTH: pos_y -= height/2;  break;
+      case  DIR8_SOUTH: pos_y += height/2;  break;
+    }
+  }
+  center_tile_mapcanvas(pos_x, pos_y);
+  update_rect();
+}
+
+/**************************************************************************
+ Make tiles within the rectangle, that contain owned cities
+ or units, selected (on map, and in City List window).
+    ptile->selected == 1    owned city
+    ptile->selected == 2    owned unit(s)
+**************************************************************************/
+static void select_rect_tiles(void)
+{
+  int dist_x = real_map_distance(rect_x1, rect_y1, rect_x2, rect_y1);
+  int dist_y = real_map_distance(rect_x1, rect_y1, rect_x1, rect_y2);
+  struct tile *ptile;
+  struct city *pcity;
+  int x, y, xx, yy;
+
+  for (yy = 0; yy <= dist_y; yy++) {      /* No macro? */
+    for (xx = 0; xx <= dist_x; xx++) {
+      x = rect_x1 + xx;
+      y = rect_y1 + yy;
+      normalize_map_pos(&x, &y);
+
+      ptile = map_get_tile(x, y);
+      pcity = map_get_city(x, y);
+
+      if (pcity && pcity->owner==game.player_idx) {
+        ptile->selected = 1;
+        refresh_tile_mapcanvas(x, y, TRUE);
+        tile_cities_active = TRUE;
+
+      } else if (tile_has_suitable_unit(ptile)) {
+        ptile->selected = 2;
+        refresh_tile_mapcanvas(x, y, TRUE);
+        if (!tile_units_active) {
+          tile_units_active = TRUE;   /* only if something found */
+          update_menus();
+        }
+      }
+    }
+  }
+
+  if (tile_cities_active)
+    cities_on_map_selection();  /* cityrep.c */
+}
+
+/**************************************************************************
+ Left Mouse Button in area selection mode.
+**************************************************************************/
+static void toggle_tile_select(int x, int y)
+{
+  struct tile *ptile = map_get_tile(x, y);
+  struct city *pcity = map_get_city(x, y);
+
+  if (ptile->selected == 1)  {
+    city_on_map_select(pcity, FALSE);
+    ptile->selected = 0;
+
+  } else if (ptile->selected == 2)  {
+    ptile->selected = 0;
+
+  } else if (pcity && pcity->owner==game.player_idx)  {
+    ptile->selected = 1;
+    tile_cities_active = TRUE;
+    city_on_map_select(pcity, TRUE);
+
+  } else if (tile_has_suitable_unit(ptile)) {
+    ptile->selected = 2;
+    if (!tile_units_active) {
+      tile_units_active = TRUE;
+      update_menus();
+    }
+  } else
+    return;
+
+  refresh_tile_mapcanvas(x, y, TRUE);
+}
+
+/**************************************************************************
+ All owned units are currently suitable.
+**************************************************************************/
+static bool tile_has_suitable_unit(struct tile *ptile)
+{
+  if (unit_list_size(&ptile->units)==0)
+    return FALSE;
+
+  unit_list_iterate(ptile->units, punit) {
+    if (punit->owner == game.player_idx)
+        return TRUE;
+  } unit_list_iterate_end;
+
+  return FALSE;
+}
+
+/**************************************************************************
+ The mapcanvas clipboard.
+ Shift-Left-Click on owned city or any visible unit to copy.
+**************************************************************************/
+static void copy_production(int x, int y)
+{
+  char msg[MAX_LEN_MSG];
+  struct city *pcity = map_get_city(x, y);
+  struct tile *ptile = map_get_tile(x, y);
+
+  if (pcity) {
+    if (pcity->owner != game.player_idx)
+      return;
+    clipboard = pcity->currently_building;
+    clipboard_is_unit = pcity->is_building_unit;
+  } else  {
+    struct unit *punit = find_visible_unit(ptile);
+    if (!punit)
+      return;
+    clipboard_is_unit = TRUE;
+    clipboard = punit->type;
+  }
+  my_snprintf(msg, sizeof(msg), _("Game: Copy %s."),
+    clipboard_is_unit ? unit_types[clipboard].name :
+    get_improvement_name(clipboard));
+  append_output_window(msg);
+}
+
+/****************************************************************
+...
+*****************************************************************/
+static void buy_production(struct city *pcity)
+{
+  struct packet_city_request packet;
+
+  if ( pcity == NULL)
+      return;
+
+  packet.city_id = pcity->id;
+  send_packet_city_request(&aconnection, &packet, PACKET_CITY_BUY);
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void paste_production(struct city *pcity)
+{
+  if (!tile_cities_active) {
+    if (pcity && pcity->owner == game.player_idx)
+      send_production_packet(pcity);
+    return;
+
+  } else {
+    city_list_iterate(game.player_ptr->cities, pcity) {
+      if (map_get_tile(pcity->x, pcity->y)->selected)
+        send_production_packet(pcity);
+    } city_list_iterate_end;
+  }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void send_production_packet(struct city *pcity)
+{
+  struct packet_city_request packet;
+  int cid = clipboard;
+
+  if (clipboard_is_unit)
+    cid += B_LAST;
+
+  if (pcity->currently_building == clipboard
+    || !city_can_build_impr_or_unit(pcity, cid))
+    return;
+
+  packet.city_id=pcity->id;
+  packet.name[0]='\0';
+  packet.worklist.name[0] = '\0';
+  packet.build_id=clipboard;
+  packet.is_build_id_unit_id=clipboard_is_unit;
+  send_packet_city_request(&aconnection, &packet, PACKET_CITY_CHANGE);
+}
+
 /**************************************************************************
 ...
 **************************************************************************/
@@ -277,9 +575,9 @@
 {
   int xtile, ytile;
 
-  /* when you get a <SHIFT>+<LMB> pow! */
+  /* <CONTROL> + Middle Mouse Button: Wake up sentries */
   if (get_client_state() != CLIENT_GAME_RUNNING_STATE
-      || !(ev->state & GDK_SHIFT_MASK)) {
+      || !(ev->state & GDK_CONTROL_MASK)  || !(ev->button==2)) {
     return TRUE;
   }
 
@@ -290,36 +588,162 @@
 }
 
 /**************************************************************************
-...
+ Handle 'Right Mouse Button released'.
 **************************************************************************/
+gint butt_release_mapcanvas(GtkWidget *w, GdkEventButton *ev)
+{
+  int xtile, ytile;
+  int test_x;
+
+  if(ev->button!=3 || !rbutton_down)
+    return TRUE;
+
+  get_map_xy(ev->x, ev->y, &xtile, &ytile);
+
+  /* Did user move mouse pointer between press and release? */
+
+  if ((xtile != first_x || ytile != first_y) && !hover_state) {
+    if (rectangle_active) {
+      draw_rectangle(first_x, first_y, old_x, old_y, FALSE);
+      rectangle_active = FALSE;
+    }
+
+    /* Define NW & SE corners for a rectangle finished. */
+
+    test_x = first_x + real_map_distance(first_x, first_y, xtile, first_y);
+    normalize_map_pos(&test_x, &first_y);
+
+    if (test_x == xtile)  {
+      rect_x1 = first_x;  rect_x2 = xtile;
+    } else  {
+      rect_x1 = xtile;    rect_x2 = first_x;
+    }
+    if (ytile >= first_y) {
+      rect_y1 = first_y;  rect_y2 = ytile;
+    } else  {
+      rect_y1 = ytile;    rect_y2 = first_y;
+    }
+    select_rect_tiles();
+    update_city_descriptions();
+  } else  {
+    center_tile_mapcanvas(xtile, ytile);
+    }
+  rbutton_down = FALSE;
+
+  return TRUE;
+}
+
+/**************************************************************************
+ Handle various clicks on mapcanvas.
+**************************************************************************/
 gint butt_down_mapcanvas(GtkWidget *w, GdkEventButton *ev)
 {
   int xtile, ytile;
-  
+  enum quicktype qtype = NONE;
+  struct city *pcity;
+
   if(get_client_state() != CLIENT_GAME_RUNNING_STATE)
-    return TRUE;
-  
-  if ((ev->button == 1) && (ev->state & GDK_SHIFT_MASK)) {
-    adjust_workers(w, ev);
     return TRUE;
+
+  /*  <SHIFT> + <CONTROL> + LMB : Adjust workers
+  */
+  if((ev->button==1) && (ev->state & GDK_SHIFT_MASK)
+    && (ev->state & GDK_CONTROL_MASK)) {
+      adjust_workers(w, ev);
+      return TRUE;
   }
 
   get_map_xy(ev->x, ev->y, &xtile, &ytile);
+  pcity = map_get_tile(xtile, ytile)->city;
 
-  if (ev->button == 1) {
-    do_map_click(xtile, ytile);
+  /*  <SHIFT> + <CONTROL> + RMB : Buy Production
+  */
+  if((ev->button==3) && (ev->state & GDK_SHIFT_MASK)
+    && (ev->state & GDK_CONTROL_MASK)) {
+      buy_production(pcity);
+      return TRUE;
+  }
+
+  /*  <SHIFT> + LMB Copy Production
+   *  <SHIFT> + RMB Paste Production
+  */
+  if((ev->button==1) && (ev->state & GDK_SHIFT_MASK)) {
+    copy_production(xtile, ytile);
+    return TRUE;
+  }
+  if((ev->button==3) && (ev->state & GDK_SHIFT_MASK)) {
+    paste_production(pcity);
+    cancel_tile_selection();
+    return TRUE;
+  }
+
+  /*  <CONTROL> + LMB quickselect a Sea unit
+   *  <CONTROL> + RMB quickselect a Land unit
+  */
+  if((ev->button==1) && (ev->state & GDK_CONTROL_MASK)) {
+    qtype = SEA;
+  } else if((ev->button==3) && (ev->state & GDK_CONTROL_MASK))  {
+    qtype = LAND;
+  }
+  if(ev->button==1 && (tile_cities_active || tile_units_active)) {
+    toggle_tile_select(xtile, ytile);
+  } else if(ev->button==1 || qtype) {
+    do_map_click(xtile, ytile, qtype);
     gtk_widget_grab_focus(turn_done_button);
-  } else if ((ev->button == 2) || (ev->state & GDK_CONTROL_MASK)) {
+  }
+  else if(ev->button==2)
     popit(ev, xtile, ytile);
-  } else {
-    center_tile_mapcanvas(xtile, ytile);
+
+  else  /* Right Mouse Button Press */
+  {
+    /* A foolproof user will depress button on canvas, release it on another
+    *  widget, and return to canvas to find rectangle still active.
+    */
+    if (rectangle_active) {
+      rbutton_down = TRUE;
+      butt_release_mapcanvas(w, ev);
+      rbutton_down = FALSE;
+      return TRUE;
+    }
+
+    cancel_tile_selection();
+    rbutton_down = TRUE;
+    first_x = xtile;          /* record mouse position */
+    first_y = ytile;
+    old_x = xtile;
+    old_y = ytile;
   }
+
   return TRUE;
 }
 
 /**************************************************************************
 ...
 **************************************************************************/
+void cancel_tile_selection(void)
+{
+  struct tile *ptile;
+
+  if (tile_cities_active || tile_units_active)  {
+    if (tile_units_active)  {
+      tile_units_active  = FALSE;
+      update_menus();
+    }
+    tile_cities_active = FALSE;
+
+    whole_map_iterate(x, y) {
+      ptile = map_get_tile(x, y);
+      if (ptile->selected) {
+        ptile->selected = 0;
+        refresh_tile_mapcanvas(x, y, TRUE);
+      }
+    } whole_map_iterate_end;
+  }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
 void create_line_at_mouse_pos(void)
 {
   int x, y;
@@ -350,9 +774,91 @@
 /**************************************************************************
 ...
 **************************************************************************/
+static void update_rect(void)
+{
+  int x, y;
+
+  /* Reading mouse pos saves unneccessay redrawing (queueing) */
+  gdk_window_get_pointer(map_canvas->window, &x, &y, NULL);
+  get_map_xy(x, y, &x, &y);
+
+  if (rbutton_down && (old_x != x || old_y != y)) {
+    draw_rectangle(first_x, first_y, old_x, old_y, FALSE);
+    draw_rectangle(first_x, first_y, x, y, TRUE);
+    rectangle_active = TRUE;
+
+    old_x = x;
+    old_y = y;
+  }
+}
+
+/**************************************************************************
+ Draw or undraw a rectangle. Takes two sets of coords and figures out
+ directions. Both Iso and Non-Iso. Use drawing funtions from mapview.c.
+
+    (1)
+      *--*
+      |  |
+      *--*
+         (2)
+
+**************************************************************************/
+static void draw_rectangle(int src_x, int src_y, int dest_x, int dest_y,
+                           bool draw)
+{
+  int x1, y1, x2, y2;
+  int dist_x, dist_y;
+  int i, test_x;
+
+  dist_x = real_map_distance(src_x, src_y, dest_x, src_y);
+  dist_y = real_map_distance(src_x, src_y, src_x, dest_y);
+
+  test_x = src_x + dist_x;
+  normalize_map_pos(&test_x, &src_y);
+
+  if (test_x == dest_x)  {        /* is dest to the right of src? */
+    x1 = src_x;     x2 = dest_x;
+  } else  {
+    x1 = dest_x;    x2 = src_x;
+  }
+  if (dest_y >= src_y) {          /* vertical is simple */
+    y1 = src_y;     y2 = dest_y;
+  } else  {
+    y1 = dest_y;    y2 = src_y;
+  }
+
+  if (x1 != x2) {
+    for (i = 0; i < dist_x; i++) {
+      if (draw) {
+        draw_segment(x1 + i, y1, DIR8_EAST);
+        draw_segment(x1 + i, y2, DIR8_EAST);
+      } else  {
+        undraw_segment(x1 + i, y1, DIR8_EAST);
+        undraw_segment(x1 + i, y2, DIR8_EAST);
+      }
+    }
+  }
+  if (y1 != y2) {
+    for (i = 0; i < dist_y; i++) {
+      if (draw) {
+        draw_segment(x1, y1 + i, DIR8_SOUTH);
+        draw_segment(x2, y1 + i, DIR8_SOUTH);
+      } else  {
+        undraw_segment(x1, y1 + i, DIR8_SOUTH);
+        undraw_segment(x2, y1 + i, DIR8_SOUTH);
+      }
+    }
+  }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
 gint move_mapcanvas(GtkWidget *widget, GdkEventButton *event)
 {
   update_line(event->x, event->y);
+  if (!hover_state)
+    update_rect();
   return TRUE;
 }
 
@@ -470,5 +976,5 @@
 **************************************************************************/
 void focus_to_next_unit(void)
 {
-  advance_unit_focus();
+  advance_unit_focus(FALSE);
 }
Index: client/gui-gtk/mapctrl.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapctrl.h,v
retrieving revision 1.10
diff -u -r1.10 mapctrl.h
--- client/gui-gtk/mapctrl.h	2002/08/27 21:15:40	1.10
+++ client/gui-gtk/mapctrl.h	2002/10/06 05:01:09
@@ -15,14 +15,22 @@
 
 #include <gtk/gtk.h>
 
+#include "cityrep.h"
 #include "mapctrl_g.h"
 
 struct unit;
 struct t_popup_pos {int xroot, yroot;};
 
+void bg_define_zero(int group);
+void bg_focus_zero(int group);
+
+void request_center_capital(void);
+void scroll_map(int dir);
+
 void key_city_workers(GtkWidget *w, GdkEventKey *ev);
 void adjust_workers(GtkWidget *widget, GdkEventButton *ev);
 
+gint butt_release_mapcanvas(GtkWidget *w, GdkEventButton *ev);
 gint butt_down_mapcanvas(GtkWidget *w, GdkEventButton *ev);
 gint butt_down_wakeup(GtkWidget *w, GdkEventButton *ev);
 gint butt_down_overviewcanvas(GtkWidget *w, GdkEventButton *ev);
@@ -37,5 +45,6 @@
 
 /* Color to use to display the workers */
 extern int city_workers_color;
+
 
 #endif  /* FC__MAPCTRL_H */
Index: client/gui-gtk/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapview.c,v
retrieving revision 1.127
diff -u -r1.127 mapview.c
--- client/gui-gtk/mapview.c	2002/08/25 11:20:56	1.127
+++ client/gui-gtk/mapview.c	2002/10/06 05:01:17
@@ -437,7 +437,8 @@
 
     my_snprintf(buffer, sizeof(buffer), "%s\n%s\n%s%s%s",
 		(hover_unit == punit->id) ?
-		_("Select destination") : unit_activity_text(punit),
+        ((hover_state == HOVER_BODYGUARD) ? _("Select V.I.U.") :
+		_("Select destination")) : unit_activity_text(punit),
 		map_get_tile_info_text(punit->x, punit->y),
 		infrastructure ?
 		map_get_infrastructure_text(infrastructure) : "",
@@ -456,6 +457,7 @@
       break;
     case HOVER_GOTO:
     case HOVER_CONNECT:
+    case HOVER_BODYGUARD:
       gdk_window_set_cursor (root_window, goto_cursor);
       break;
     case HOVER_NUKE:
Index: client/gui-gtk/menu.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/menu.c,v
retrieving revision 1.69
diff -u -r1.69 menu.c
--- client/gui-gtk/menu.c	2002/06/23 16:06:24	1.69
+++ client/gui-gtk/menu.c	2002/10/06 05:01:24
@@ -28,6 +28,7 @@
 #include "support.h"
 #include "unit.h"
 
+#include "battlegroups.h"
 #include "chatline.h"
 #include "cityrep.h"
 #include "civclient.h"
@@ -94,8 +95,73 @@
   MENU_VIEW_SHOW_FOG_OF_WAR,
   MENU_VIEW_CENTER_VIEW,
 
-  MENU_ORDER_BUILD_CITY,     /* shared with BUILD_WONDER */
-  MENU_ORDER_ROAD,           /* shared with TRADEROUTE */
+  MENU_REPORT_CITIES,
+  MENU_REPORT_UNITS,
+  MENU_REPORT_PLAYERS,
+  MENU_REPORT_ECONOMY,
+  MENU_REPORT_SCIENCE,
+  MENU_REPORT_WOW,
+  MENU_REPORT_TOP_CITIES,
+  MENU_REPORT_MESSAGES,
+  MENU_REPORT_DEMOGRAPHIC,
+  MENU_REPORT_SPACESHIP,
+
+  MENU_POPUPS_POPUP_CITIES,
+  MENU_POPUPS_AUTO_NAME_CITIES,
+  MENU_POPUPS_POPUP_DIPLOMATS,
+  MENU_POPUPS_POPUP_CARAVANS,
+
+  MENU_GROUPS_DISPERSION0,
+  MENU_GROUPS_DISPERSION1,
+  MENU_GROUPS_DISPERSION2,
+  MENU_GROUPS_FOCUS_ZERO1,
+  MENU_GROUPS_FOCUS_ZERO2,
+  MENU_GROUPS_FOCUS_ZERO3,
+  MENU_GROUPS_FOCUS_ZERO4,
+  MENU_GROUPS_FOCUS_ZERO5,
+  MENU_GROUPS_FOCUS_ZERO6,
+  MENU_GROUPS_FOCUS_ZERO7,
+  MENU_GROUPS_FOCUS_ZERO8,
+  MENU_GROUPS_FOCUS_ZERO9,
+  MENU_GROUPS_UNASSIGN,
+  MENU_GROUPS_ASSIGN1,
+  MENU_GROUPS_ASSIGN2,
+  MENU_GROUPS_ASSIGN3,
+  MENU_GROUPS_ASSIGN4,
+  MENU_GROUPS_ASSIGN5,
+  MENU_GROUPS_ASSIGN6,
+  MENU_GROUPS_ASSIGN7,
+  MENU_GROUPS_ASSIGN8,
+  MENU_GROUPS_ASSIGN9,
+  MENU_GROUPS_JOIN,
+  MENU_GROUPS_SCRAMBLE,
+  MENU_GROUPS_DEFINE_ZERO,
+  MENU_GROUPS_AUTOJOIN,
+  MENU_GROUPS_AGGRESSION,
+
+  MENU_FILTERS_NORMAL,
+  MENU_FILTERS_DIPLOMATS,
+  MENU_FILTERS_CARAVANS,
+  MENU_FILTERS_SETTLERS,
+  MENU_FILTERS_AIRPLANES,
+  MENU_FILTERS_HELICOPTERS,
+  MENU_FILTERS_INFANTRY,
+  MENU_FILTERS_WARSHIPS,
+  MENU_FILTERS_TRANSPORTERS,
+
+  MENU_FILTERS_NEW,
+  MENU_FILTERS_VETERAN,
+  MENU_FILTERS_CURRENT_LOCATION,
+  MENU_FILTERS_RADIUS,
+
+  MENU_FILTERS_INCLUDE_SENTRIES,
+  MENU_FILTERS_INCLUDE_FORTIFIED,
+  MENU_FILTERS_INCLUDE_EXHAUSTED,
+  MENU_FILTERS_INCLUDE_GOTOS,
+  MENU_FILTERS_INCLUDE_MEMBERS,
+
+  MENU_ORDER_BUILD_CITY,     /* shared with BUILD_WONDER and BODYGUARD */
+  MENU_ORDER_ROAD,           /* shared with TRADEROUTE and RETURN & RECOVER*/
   MENU_ORDER_IRRIGATE,
   MENU_ORDER_MINE,
   MENU_ORDER_TRANSFORM,
@@ -117,20 +183,10 @@
   MENU_ORDER_DISBAND,
   MENU_ORDER_DIPLOMAT_DLG,
   MENU_ORDER_NUKE,
+  MENU_ORDER_BATCH,
   MENU_ORDER_WAIT,
   MENU_ORDER_DONE,
 
-  MENU_REPORT_CITIES,
-  MENU_REPORT_UNITS,
-  MENU_REPORT_PLAYERS,
-  MENU_REPORT_ECONOMY,
-  MENU_REPORT_SCIENCE,
-  MENU_REPORT_WOW,
-  MENU_REPORT_TOP_CITIES,
-  MENU_REPORT_MESSAGES,
-  MENU_REPORT_DEMOGRAPHIC,
-  MENU_REPORT_SPACESHIP,
-
   MENU_HELP_LANGUAGES,
   MENU_HELP_CONNECTING,
   MENU_HELP_CONTROLS,
@@ -295,82 +351,253 @@
 /****************************************************************
 ...
 *****************************************************************/
+static void reports_menu_callback(gpointer callback_data,
+				  guint callback_action, GtkWidget *widget)
+{
+  switch(callback_action) {
+   case MENU_REPORT_CITIES:
+    popup_city_report_dialog(0);
+    break;
+   case MENU_REPORT_UNITS:
+    popup_activeunits_report_dialog(0);
+    break;
+  case MENU_REPORT_PLAYERS:
+    popup_players_dialog();
+    break;
+   case MENU_REPORT_ECONOMY:
+    popup_economy_report_dialog(0);
+    break;
+   case MENU_REPORT_SCIENCE:
+    popup_science_dialog(0);
+    break;
+   case MENU_REPORT_WOW:
+    send_report_request(REPORT_WONDERS_OF_THE_WORLD);
+    break;
+   case MENU_REPORT_TOP_CITIES:
+    send_report_request(REPORT_TOP_5_CITIES);
+    break;
+  case MENU_REPORT_MESSAGES:
+    popup_meswin_dialog();
+    break;
+   case MENU_REPORT_DEMOGRAPHIC:
+    send_report_request(REPORT_DEMOGRAPHIC);
+    break;
+   case MENU_REPORT_SPACESHIP:
+    popup_spaceship_dialog(game.player_ptr);
+    break;
+  }
+}
+
+/****************************************************************
+...
+*****************************************************************/
+static void popups_menu_callback(gpointer callback_data,
+				  guint callback_action, GtkWidget *widget)
+{
+  switch(callback_action) {
+    case MENU_POPUPS_POPUP_CITIES:
+      if (popup_cities ^ GTK_CHECK_MENU_ITEM(widget)->active)
+        key_popup_cities_toggle();
+      break;
+    case MENU_POPUPS_AUTO_NAME_CITIES:
+      if (auto_name_cities ^ GTK_CHECK_MENU_ITEM(widget)->active)
+        key_auto_name_cities_toggle();
+      break;
+    case MENU_POPUPS_POPUP_DIPLOMATS:
+      if (popup_diplomats ^ GTK_CHECK_MENU_ITEM(widget)->active)
+        key_popup_diplomats_toggle();
+      break;
+    case MENU_POPUPS_POPUP_CARAVANS:
+      if (popup_caravans ^ GTK_CHECK_MENU_ITEM(widget)->active)
+        key_popup_caravans_toggle();
+      break;
+  }
+}
+
+/****************************************************************
+...
+*****************************************************************/
+static void groups_menu_callback(gpointer callback_data,
+				  guint callback_action, GtkWidget *widget)
+{
+  struct unit *punit = get_unit_in_focus();
+
+  switch(callback_action) {
+    case MENU_GROUPS_DISPERSION0: bg_dispersion(punit, 0);      break;
+    case MENU_GROUPS_DISPERSION1: bg_dispersion(punit, 1);      break;
+    case MENU_GROUPS_DISPERSION2: bg_dispersion(punit, 2);      break;
+    case MENU_GROUPS_FOCUS_ZERO1: bg_focus_zero(0);             break;
+    case MENU_GROUPS_FOCUS_ZERO2: bg_focus_zero(1);             break;
+    case MENU_GROUPS_FOCUS_ZERO3: bg_focus_zero(2);             break;
+    case MENU_GROUPS_FOCUS_ZERO4: bg_focus_zero(3);             break;
+    case MENU_GROUPS_FOCUS_ZERO5: bg_focus_zero(4);             break;
+    case MENU_GROUPS_FOCUS_ZERO6: bg_focus_zero(5);             break;
+    case MENU_GROUPS_FOCUS_ZERO7: bg_focus_zero(6);             break;
+    case MENU_GROUPS_FOCUS_ZERO8: bg_focus_zero(7);             break;
+    case MENU_GROUPS_FOCUS_ZERO9: bg_focus_zero(8);             break;
+    case MENU_GROUPS_UNASSIGN:    bg_key_unassign_unit(punit);  break;
+    case MENU_GROUPS_ASSIGN1:     bg_key_assign_unit(punit, 0); break;
+    case MENU_GROUPS_ASSIGN2:     bg_key_assign_unit(punit, 1); break;
+    case MENU_GROUPS_ASSIGN3:     bg_key_assign_unit(punit, 2); break;
+    case MENU_GROUPS_ASSIGN4:     bg_key_assign_unit(punit, 3); break;
+    case MENU_GROUPS_ASSIGN5:     bg_key_assign_unit(punit, 4); break;
+    case MENU_GROUPS_ASSIGN6:     bg_key_assign_unit(punit, 5); break;
+    case MENU_GROUPS_ASSIGN7:     bg_key_assign_unit(punit, 6); break;
+    case MENU_GROUPS_ASSIGN8:     bg_key_assign_unit(punit, 7); break;
+    case MENU_GROUPS_ASSIGN9:     bg_key_assign_unit(punit, 8); break;
+    case MENU_GROUPS_AGGRESSION:  bg_aggression(punit);         break;
+    case MENU_GROUPS_JOIN:        bg_join(punit);               break;
+    case MENU_GROUPS_DEFINE_ZERO: bg_menu_define_zero();        break;
+
+    case MENU_GROUPS_SCRAMBLE:
+      if (punit && punit->bg)
+        bg_scramble(punit->bg - 1);
+      else if (last_group)
+        bg_scramble(last_group - 1);
+      break;
+
+    case MENU_GROUPS_AUTOJOIN:
+      if (autojoin ^ GTK_CHECK_MENU_ITEM(widget)->active)
+        bg_autojoin_toggle();
+      break;
+  }
+}
+
+/****************************************************************
+...
+*****************************************************************/
+static void filters_menu_callback(gpointer callback_data,
+				  guint callback_action, GtkWidget *widget)
+{
+  switch(callback_action) {
+    case MENU_FILTERS_NORMAL:             filter_units(FILTER_NORMAL);            break;
+    case MENU_FILTERS_DIPLOMATS:          filter_units(FILTER_DIPLOMATS);         break;
+    case MENU_FILTERS_CARAVANS:           filter_units(FILTER_CARAVANS);          break;
+    case MENU_FILTERS_SETTLERS:           filter_units(FILTER_SETTLERS);          break;
+    case MENU_FILTERS_AIRPLANES:          filter_units(FILTER_AIRPLANES);         break;
+    case MENU_FILTERS_HELICOPTERS:        filter_units(FILTER_HELICOPTERS);       break;
+    case MENU_FILTERS_INFANTRY:           filter_units(FILTER_INFANTRY);          break;
+    case MENU_FILTERS_WARSHIPS:           filter_units(FILTER_WARSHIPS);          break;
+    case MENU_FILTERS_TRANSPORTERS:       filter_units(FILTER_TRANSPORTERS);      break;
+
+    case MENU_FILTERS_NEW:                filter_units(FILTER_NEW);               break;
+    case MENU_FILTERS_VETERAN:            filter_units(FILTER_VETERAN);           break;
+    case MENU_FILTERS_CURRENT_LOCATION:   filter_units(FILTER_CURRENT_LOCATION);  break;
+    case MENU_FILTERS_RADIUS:             filter_units(FILTER_RADIUS);            break;
+
+    case MENU_FILTERS_INCLUDE_SENTRIES:   filter_units(FILTER_INCLUDE_SENTRIES);  break;
+    case MENU_FILTERS_INCLUDE_FORTIFIED:  filter_units(FILTER_INCLUDE_FORTIFIED); break;
+    case MENU_FILTERS_INCLUDE_EXHAUSTED:  filter_units(FILTER_INCLUDE_EXHAUSTED); break;
+    case MENU_FILTERS_INCLUDE_GOTOS:      filter_units(FILTER_INCLUDE_GOTOS);     break;
+    case MENU_FILTERS_INCLUDE_MEMBERS:    filter_units(FILTER_INCLUDE_MEMBERS);   break;
+  }
+}
+
+/****************************************************************
+ Some notes on Batch Command: (Example:)
+ key_unit_build_wonder() in control.c will either set a mission
+ flag or execute now depending on goto state. Batch is called
+ from here. But for 'Assign to Battlegroup' batch is called from
+ that function, as it is not available as mission order.
+*****************************************************************/
 static void orders_menu_callback(gpointer callback_data,
 				 guint callback_action, GtkWidget *widget)
 {
+  struct unit *punit = get_unit_in_focus();
   switch(callback_action) {
    case MENU_ORDER_BUILD_CITY:
-    if (get_unit_in_focus()) {
-      struct unit *punit = get_unit_in_focus();
-      /* Enable the button for adding to a city in all cases, so we
-	 get an eventual error message from the server if we try. */
-      if (can_unit_add_or_build_city(punit)) {
-	key_unit_build_city();
-      } else {
-	key_unit_build_wonder();
+      if (is_military_unit(punit) && (is_ground_unit(punit) || is_sailing_unit(punit)))
+    request_unit_bodyguard(punit);
+      else if (unit_flag(punit, F_CITIES))
+    key_unit_build_city(punit);
+      else if (unit_flag(punit, F_HELP_WONDER)) {
+        if(batch_command && hover_state!=HOVER_GOTO)
+          batch_orders(punit, B_ORDERS_BUILD_WONDER, 0, 0);
+        else
+          key_unit_build_wonder(punit);
       }
-    }
     break;
    case MENU_ORDER_ROAD:
-    if (get_unit_in_focus()) {
-      if (unit_can_est_traderoute_here(get_unit_in_focus()))
-	key_unit_traderoute();
-      else
-	key_unit_road();
-    }
+    if (tile_units_active)
+      batch_orders(NULL, B_ORDERS_R_AND_R, 0, 0);
+    else if (batch_command && hover_state!=HOVER_GOTO)
+      batch_orders(punit, B_ORDERS_R_AND_R, 0, 0);
+    else if (is_sailing_unit(punit) && !batch_command && hover_state!=HOVER_GOTO)
+      return_and_recover(punit);
+    else if (unit_flag(punit, F_TRADE_ROUTE))
+      key_unit_traderoute(punit);
+    else if (unit_flag(punit, F_SETTLERS))
+      key_unit_road(punit);
     break;
    case MENU_ORDER_IRRIGATE:
-    key_unit_irrigate();
+    key_unit_irrigate(punit);
     break;
    case MENU_ORDER_MINE:
-    key_unit_mine();
+    key_unit_mine(punit);
     break;
    case MENU_ORDER_TRANSFORM:
-    key_unit_transform();
+    key_unit_transform(punit);
     break;
    case MENU_ORDER_FORTRESS:
-    if (get_unit_in_focus()) {
-      if (can_unit_do_activity(get_unit_in_focus(), ACTIVITY_FORTRESS))
-	key_unit_fortress();
-      else
-	key_unit_fortify();
-    }
+    if (tile_units_active)
+      batch_orders(NULL, B_ORDERS_FORTIFY, 0, 0);
+    else if (unit_flag(punit, F_SETTLERS))
+      key_unit_fortress(punit);
+    else if(batch_command && hover_state!=HOVER_GOTO)
+      batch_orders(punit, B_ORDERS_FORTIFY, 0, 0);
+    else
+      key_unit_fortify(punit);
     break;
    case MENU_ORDER_AIRBASE:
-    key_unit_airbase(); 
+    key_unit_airbase(punit); 
     break;
    case MENU_ORDER_POLLUTION:
-    if (get_unit_in_focus()) {
-      if (can_unit_paradrop(get_unit_in_focus()))
+      if (can_unit_paradrop(punit))
 	key_unit_paradrop();
       else
-	key_unit_pollution();
-    }
+	key_unit_pollution(punit);
     break;
    case MENU_ORDER_FALLOUT:
-    key_unit_fallout();
+    key_unit_fallout(punit);
     break;
    case MENU_ORDER_SENTRY:
-    key_unit_sentry();
+    if (tile_units_active)
+      batch_orders(NULL, B_ORDERS_SENTRY, 0, 0);
+    else if(batch_command && hover_state!=HOVER_GOTO)
+      batch_orders(punit, B_ORDERS_SENTRY, 0, 0);
+    else
+      key_unit_sentry(punit);
     break;
    case MENU_ORDER_PILLAGE:
     key_unit_pillage();
     break;
    case MENU_ORDER_HOMECITY:
-    key_unit_homecity();
+    key_unit_homecity(punit);
     break;
    case MENU_ORDER_UNLOAD:
-    key_unit_unload();
+    key_unit_unload(punit);
     break;
    case MENU_ORDER_WAKEUP_OTHERS:
-    key_unit_wakeup_others();
+    if (tile_units_active)
+      batch_orders(NULL, B_ORDERS_WAKEUP, 0, 0);
+    else if (batch_command)
+      batch_orders(punit, B_ORDERS_WAKEUP, 0, 0);
+    else
+      key_unit_wakeup_others();
     break;
    case MENU_ORDER_AUTO_SETTLER:
-    if(get_unit_in_focus())
-      request_unit_auto(get_unit_in_focus());
+    if(batch_command && hover_state!=HOVER_GOTO)
+      batch_orders(punit, B_ORDERS_AUTO, 0, 0);
+    else
+      key_unit_auto(punit);
     break;
    case MENU_ORDER_AUTO_EXPLORE:
-    key_unit_auto_explore();
+    if (tile_units_active)
+      batch_orders(NULL, B_ORDERS_EXPLORE, 0, 0);
+    else if(batch_command && hover_state!=HOVER_GOTO)
+      batch_orders(punit, B_ORDERS_EXPLORE, 0, 0);
+    else
+      key_unit_auto_explore(punit);
     break;
    case MENU_ORDER_CONNECT:
     key_unit_connect();
@@ -382,11 +609,11 @@
     key_unit_goto();
     break;
    case MENU_ORDER_GOTO_CITY:
-    if(get_unit_in_focus())
+    if(punit)
       popup_goto_dialog();
     break;
    case MENU_ORDER_DISBAND:
-    key_unit_disband();
+    key_unit_disband(punit);
     break;
    case MENU_ORDER_DIPLOMAT_DLG:
     key_unit_diplomat_actions();
@@ -394,8 +621,14 @@
    case MENU_ORDER_NUKE:
     key_unit_nuke();
     break;
+   case MENU_ORDER_BATCH:
+    key_batch_command();
+    break;
    case MENU_ORDER_WAIT:
-    key_unit_wait();
+    if(batch_command && hover_state!=HOVER_GOTO)
+      batch_orders(punit, B_ORDERS_WAIT, 0, 0);
+    else
+      key_unit_wait();
     break;
    case MENU_ORDER_DONE:
     key_unit_done();
@@ -403,51 +636,9 @@
   }
 }
 
-
 /****************************************************************
 ...
 *****************************************************************/
-static void reports_menu_callback(gpointer callback_data,
-				  guint callback_action, GtkWidget *widget)
-{
-  switch(callback_action) {
-   case MENU_REPORT_CITIES:
-    popup_city_report_dialog(0);
-    break;
-   case MENU_REPORT_UNITS:
-    popup_activeunits_report_dialog(0);
-    break;
-  case MENU_REPORT_PLAYERS:
-    popup_players_dialog();
-    break;
-   case MENU_REPORT_ECONOMY:
-    popup_economy_report_dialog(0);
-    break;
-   case MENU_REPORT_SCIENCE:
-    popup_science_dialog(0);
-    break;
-   case MENU_REPORT_WOW:
-    send_report_request(REPORT_WONDERS_OF_THE_WORLD);
-    break;
-   case MENU_REPORT_TOP_CITIES:
-    send_report_request(REPORT_TOP_5_CITIES);
-    break;
-  case MENU_REPORT_MESSAGES:
-    popup_meswin_dialog();
-    break;
-   case MENU_REPORT_DEMOGRAPHIC:
-    send_report_request(REPORT_DEMOGRAPHIC);
-    break;
-   case MENU_REPORT_SPACESHIP:
-    popup_spaceship_dialog(game.player_ptr);
-    break;
-  }
-}
-
-
-/****************************************************************
-...
-*****************************************************************/
 static void help_menu_callback(gpointer callback_data,
 			       guint callback_action, GtkWidget *widget)
 {
@@ -570,7 +761,7 @@
 	NULL,			0,					"<Separator>"	},
   { "/" N_("Game") "/" N_("_Disconnect"),		NULL,
 	game_menu_callback,	MENU_GAME_DISCONNECT					},
-  { "/" N_("Game") "/" N_("_Quit"),			"<control>q",
+  { "/" N_("Game") "/" N_("_Quit"),			    NULL,
 	gtk_main_quit,		0							},
   /* Kingdom menu ... */
   { "/" N_("_Kingdom"),					NULL,
@@ -594,11 +785,11 @@
 	NULL,			0,					"<Branch>"	},
   { "/" N_("View") "/tearoff1",				NULL,
 	NULL,			0,					"<Tearoff>"	},
-  { "/" N_("View") "/" N_("Map _Grid"),			"<control>g",
+  { "/" N_("View") "/" N_("Map _Grid"),			"<shift>g",
 	view_menu_callback,	MENU_VIEW_SHOW_MAP_GRID,		"<CheckItem>"	},
-  { "/" N_("View") "/" N_("City _Names"),		"<control>n",
+  { "/" N_("View") "/" N_("City _Names"),		"<shift>n",
 	view_menu_callback,	MENU_VIEW_SHOW_CITY_NAMES,		"<CheckItem>"	},
-  { "/" N_("View") "/" N_("City _Productions"),		"<control>p",
+  { "/" N_("View") "/" N_("City _Productions"),		"<shift>p",
 	view_menu_callback,	MENU_VIEW_SHOW_CITY_PRODUCTIONS,	"<CheckItem>"	},
   { "/" N_("View") "/sep1",				NULL,
 	NULL,			0,					"<Separator>"	},
@@ -634,13 +825,226 @@
 	NULL,			0,					"<Separator>"	},
   { "/" N_("View") "/" N_("_Center View"),		"c",
 	view_menu_callback,	MENU_VIEW_CENTER_VIEW					},
+
+  /* Reports menu ... */
+  { "/" N_("_Reports"),					NULL,
+	NULL,			0,					"<Branch>"	},
+  { "/" N_("Reports") "/tearoff1",			NULL,
+	NULL,			0,					"<Tearoff>"	},
+  { "/" N_("Reports") "/" N_("_Cities"),		"F1",
+	reports_menu_callback,	MENU_REPORT_CITIES					},
+  { "/" N_("Reports") "/" N_("_Units"),			"F2",
+	reports_menu_callback,	MENU_REPORT_UNITS					},
+  { "/" N_("Reports") "/" N_("_Players"),		"F3",
+	reports_menu_callback,	MENU_REPORT_PLAYERS					},
+  { "/" N_("Reports") "/" N_("_Economy"),		"F5",
+	reports_menu_callback,	MENU_REPORT_ECONOMY					},
+  { "/" N_("Reports") "/" N_("_Science"),		"F6",
+	reports_menu_callback,	MENU_REPORT_SCIENCE					},
+  { "/" N_("Reports") "/sep1",				NULL,
+	NULL,			0,					"<Separator>"	},
+  { "/" N_("Reports") "/" N_("_Wonders of the World"),	"F7",
+	reports_menu_callback,	MENU_REPORT_WOW						},
+  { "/" N_("Reports") "/" N_("_Top Five Cities"),	"F8",
+	reports_menu_callback,	MENU_REPORT_TOP_CITIES					},
+  { "/" N_("Reports") "/" N_("_Messages"),		"F10",
+	reports_menu_callback,	MENU_REPORT_MESSAGES					},
+  { "/" N_("Reports") "/" N_("_Demographics"),		"F11",
+	reports_menu_callback,	MENU_REPORT_DEMOGRAPHIC					},
+  { "/" N_("Reports") "/" N_("S_paceship"),		"F12",
+	reports_menu_callback,	MENU_REPORT_SPACESHIP					},
+
+
+  /* Popups menu ... */
+  { "/" N_("_Popups"),					            NULL,
+	NULL,			0,					"<Branch>"	            },
+  { "/" N_("Popups") "/tearoff1",			        NULL,
+	NULL,			0,					"<Tearoff>"	            },
+  { "/" N_("Popups") "/" N_("P_opup new cities"),	        "<control>o",
+	popups_menu_callback,	MENU_POPUPS_POPUP_CITIES,       "<CheckItem>" },
+  { "/" N_("Popups") "/" N_("_Auto name cities"),   NULL,
+	popups_menu_callback,	MENU_POPUPS_AUTO_NAME_CITIES,   "<CheckItem>" },
+  { "/" N_("Popups") "/sep1",		                NULL,
+	NULL,			0,					"<Separator>"	        },
+  { "/" N_("Popups") "/" N_("Diplomat Popups"),	            "<control>b",
+	popups_menu_callback,	MENU_POPUPS_POPUP_DIPLOMATS,    "<CheckItem>" },
+  { "/" N_("Popups") "/" N_("Caravan Popups"),	    NULL,
+	popups_menu_callback,	MENU_POPUPS_POPUP_CARAVANS,     "<CheckItem>" },
+
+  /* Battlegroups menu ... */
+  { "/" N_("_Battlegroups"),					NULL,
+	NULL,			0,					"<Branch>"	            },
+  { "/" N_("Battlegroups") "/tearoff1",			NULL,
+	NULL,			0,					"<Tearoff>"	            },
+  { "/" N_("Battlegroups") "/" N_("Dispersion"),	NULL,
+	NULL,	        0,                  "<Branch>"		        },
+  { "/" N_("Battlegroups") "/" N_("Dispersion") "/tearoff2",	NULL,
+	NULL,			0,					"<Tearoff>"	},
+  { "/" N_("Battlegroups") "/" N_("Dispersion") "/" N_("Close Formation"), NULL,
+	groups_menu_callback,   MENU_GROUPS_DISPERSION0                },
+  { "/" N_("Battlegroups") "/" N_("Dispersion") "/" N_("1 tile"), NULL,
+	groups_menu_callback,   MENU_GROUPS_DISPERSION1                },
+  { "/" N_("Battlegroups") "/" N_("Dispersion") "/" N_("2 tiles"), NULL,
+	groups_menu_callback,   MENU_GROUPS_DISPERSION2                },
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero"),	NULL,
+	NULL,	        0,                  "<Branch>"		        },
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/tearoff3",	NULL,
+	NULL,			0,					"<Tearoff>"	},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 1"), "1",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO1             },
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 2"), "2",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO2 			},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 3"), "3",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO3 			},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero")  "/sep1",		NULL,
+	NULL,			0,					        "<Separator>"	},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 4"), "4",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO4 			},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 5"), "5",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO5 			},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 6"), "6",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO6 			},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero")  "/sep2",		NULL,
+	NULL,			0,					        "<Separator>"	},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 7"), "7",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO7 			},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 8"), "8",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO8 			},
+  { "/" N_("Battlegroups") "/" N_("Focus on Zero") "/" N_("Group 9"), "9",
+	groups_menu_callback,   MENU_GROUPS_FOCUS_ZERO9 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup"),	NULL,
+	NULL,	        0,                  "<Branch>"		        },
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/tearoff4",	    NULL,
+	NULL,			0,					"<Tearoff>"	},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Unassign"), "0",
+	groups_menu_callback,   MENU_GROUPS_UNASSIGN            },
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup")  "/sep1",		NULL,
+	NULL,			0,					        "<Separator>"	},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 1"), "<control>1",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN1             },
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 2"), "<control>2",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN2 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 3"), "<control>3",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN3 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup")  "/sep2",		NULL,
+	NULL,			0,					        "<Separator>"	},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 4"), "<control>4",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN4 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 5"), "<control>5",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN5 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 6"), "<control>6",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN6 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup")  "/sep3",		NULL,
+	NULL,			0,					        "<Separator>"	},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 7"), "<control>7",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN7 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 8"), "<control>8",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN8 			},
+  { "/" N_("Battlegroups") "/" N_("Assign to Battlegroup") "/" N_("Group 9"), "<control>9",
+	groups_menu_callback,   MENU_GROUPS_ASSIGN9 			},
+  { "/" N_("Battlegroups") "/" N_("Join"),		"j",
+	groups_menu_callback,	MENU_GROUPS_JOIN	                },
+  { "/" N_("Battlegroups") "/" N_("Scramble"),  "z",
+	groups_menu_callback,	MENU_GROUPS_SCRAMBLE			    },
+  { "/" N_("Battlegroups") "/" N_("Define Ground Zero"),  NULL,
+	groups_menu_callback,	MENU_GROUPS_DEFINE_ZERO		        },
+  { "/" N_("Battlegroups") "/sep1",				            NULL,
+	NULL,			0,					"<Separator>"	        },
+  { "/" N_("Battlegroups") "/" N_("Autojoin"),  	  "<control>j",
+	groups_menu_callback,	MENU_GROUPS_AUTOJOIN,    "<CheckItem>"  },
+  { "/" N_("Battlegroups") "/" N_("Toggle Aggression"),  "<control>k",
+	groups_menu_callback,	MENU_GROUPS_AGGRESSION              },
+  { "/" N_("Battlegroups") "/sep2",				            NULL,
+	NULL,			0,					"<Separator>"	        },
+  { "/" N_("Battlegroups") "/" N_("Statistics"),	                NULL,
+	NULL,	        0,                  "<Branch>"		        },
+  { "/" N_("Battlegroups") "/" N_("Statistics")        "/tearoff5", NULL,
+	NULL,			0,					"<Tearoff>"	},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("1. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("2. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("3. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/sep1",            NULL,
+	NULL,			0,					"<Separator>"	        },
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("4. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("5. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("6. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/sep2",            NULL,
+	NULL,			0,					"<Separator>"	        },
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("7. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("8. Group"), NULL,
+	NULL,           0},
+  { "/" N_("Battlegroups") "/" N_("Statistics") "/" N_("9. Group"), NULL,
+	NULL,           0},
+
+
+  /* Filters menu ... */
+  { "/" N_("_Filters"),					NULL,
+	NULL,			0,					"<Branch>"	            },
+  { "/" N_("Filters") "/tearoff1",			NULL,
+	NULL,			0,					"<Tearoff>"	            },
+  { "/" N_("Filters") "/" N_("Focus Category"),	    NULL,
+	NULL,	        0,                  "<Branch>"		        },
+  { "/" N_("Filters") "/" N_("Focus Category") "/tearoff2",	NULL,
+	NULL,			0,					"<Tearoff>"	},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("Normal"),        "<control>n",
+	filters_menu_callback,	MENU_FILTERS_NORMAL,   "<RadioItem>"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("_Diplomats"),    "<control>d",
+	filters_menu_callback,	MENU_FILTERS_DIPLOMATS, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("_Caravans"),	    "<control>c",
+	filters_menu_callback,	MENU_FILTERS_CARAVANS, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("Settlers"),	    "<control>l",
+	filters_menu_callback,	MENU_FILTERS_SETTLERS, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("_Airplanes"),    "<control>a",
+	filters_menu_callback,	MENU_FILTERS_AIRPLANES, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("_Helicopters"),  "<control>h",
+	filters_menu_callback,	MENU_FILTERS_HELICOPTERS, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("_Infantry"),	    "<control>i",
+	filters_menu_callback,	MENU_FILTERS_INFANTRY, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("_Warships"),	    "<control>w",
+	filters_menu_callback,	MENU_FILTERS_WARSHIPS, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/" N_("Focus Category") "/" N_("_Transporters"),	"<control>t",
+	filters_menu_callback,	MENU_FILTERS_TRANSPORTERS, "/Filters/Focus Category/Normal"},
+  { "/" N_("Filters") "/sep1",				            NULL,
+	NULL,			0,					"<Separator>"	        },
+  { "/" N_("Filters") "/" N_("_New Units"),	        "n",
+	filters_menu_callback,	MENU_FILTERS_NEW					},
+  { "/" N_("Filters") "/" N_("_Veteran Units"),	    "v",
+	filters_menu_callback,	MENU_FILTERS_VETERAN				},
+  { "/" N_("Filters") "/" N_("Current _Location"),   "l",
+	filters_menu_callback,	MENU_FILTERS_CURRENT_LOCATION		},
+  { "/" N_("Filters") "/" N_("_Radius of 5"),   "<control>r",
+	filters_menu_callback,	MENU_FILTERS_RADIUS         		},
+  { "/" N_("Filters") "/sep2",				            NULL,
+	NULL,			0,					"<Separator>"	        },
+  { "/" N_("Filters") "/" N_("Include _Sentries"),  "<control>s",
+	filters_menu_callback,	MENU_FILTERS_INCLUDE_SENTRIES		},
+  { "/" N_("Filters") "/" N_("Include _Fortified"), "<control>f",
+	filters_menu_callback,	MENU_FILTERS_INCLUDE_FORTIFIED		},
+  { "/" N_("Filters") "/" N_("Include _Exhausted"), "<control>e",
+	filters_menu_callback,	MENU_FILTERS_INCLUDE_EXHAUSTED		},
+  { "/" N_("Filters") "/" N_("Include _Gotos"), "<control>g",
+	filters_menu_callback,	MENU_FILTERS_INCLUDE_GOTOS  		},
+  { "/" N_("Filters") "/" N_("Include _Members"), "<control>m",
+	filters_menu_callback,	MENU_FILTERS_INCLUDE_MEMBERS  		},
+
   /* Orders menu ... */
   { "/" N_("_Orders"),					NULL,
 	NULL,			0,					"<Branch>"	},
   { "/" N_("Orders") "/tearoff1",			NULL,
 	NULL,			0,					"<Tearoff>"	},
+  { "/" N_("Orders") "/" N_("Batch Command"),			"y",
+	orders_menu_callback,	MENU_ORDER_BATCH					},
+  { "/" N_("Orders") "/sep1",				NULL,
+	NULL,			0,					"<Separator>"	},
   { "/" N_("Orders") "/" N_("_Build City"),		"b",
-	orders_menu_callback,	MENU_ORDER_BUILD_CITY					},
+	orders_menu_callback,	MENU_ORDER_BUILD_CITY				},
   { "/" N_("Orders") "/" N_("Build _Road"),		"r",
 	orders_menu_callback,	MENU_ORDER_ROAD						},
   { "/" N_("Orders") "/" N_("Build _Irrigation"),	"i",
@@ -648,30 +1052,30 @@
   { "/" N_("Orders") "/" N_("Build _Mine"),		"m",
 	orders_menu_callback,	MENU_ORDER_MINE						},
   { "/" N_("Orders") "/" N_("Transf_orm Terrain"),	"o",
-	orders_menu_callback,	MENU_ORDER_TRANSFORM					},
+	orders_menu_callback,	MENU_ORDER_TRANSFORM				},
   { "/" N_("Orders") "/" N_("Build _Fortress"),		"f",
 	orders_menu_callback,	MENU_ORDER_FORTRESS					},
   { "/" N_("Orders") "/" N_("Build Airbas_e"),		"e",
 	orders_menu_callback,	MENU_ORDER_AIRBASE					},
   { "/" N_("Orders") "/" N_("Clean _Pollution"),	"p",
-	orders_menu_callback,	MENU_ORDER_POLLUTION					},
-  { "/" N_("Orders") "/" N_("Clean _Nuclear Fallout"),	"n",
+	orders_menu_callback,	MENU_ORDER_POLLUTION				},
+  { "/" N_("Orders") "/" N_("Clean Nuclear _Fallout"),	NULL,
 	orders_menu_callback,	MENU_ORDER_FALLOUT					},
-  { "/" N_("Orders") "/sep1",			NULL,
+  { "/" N_("Orders") "/sep2",			NULL,
 	NULL,			0,					"<Separator>"	},
   { "/" N_("Orders") "/" N_("_Sentry"),			"s",
 	orders_menu_callback,	MENU_ORDER_SENTRY					},
-  { "/" N_("Orders") "/" N_("Pillage"),		        "<shift>p",
+  { "/" N_("Orders") "/" N_("Pillage"),		        "<control>p",
 	orders_menu_callback,	MENU_ORDER_PILLAGE					},
-  { "/" N_("Orders") "/sep2",				NULL,
+  { "/" N_("Orders") "/sep3",				NULL,
 	NULL,			0,					"<Separator>"	},
   { "/" N_("Orders") "/" N_("Make _Homecity"),		"h",
 	orders_menu_callback,	MENU_ORDER_HOMECITY					},
   { "/" N_("Orders") "/" N_("_Unload"),			"u",
 	orders_menu_callback,	MENU_ORDER_UNLOAD					},
   { "/" N_("Orders") "/" N_("Wake up o_thers"),		"<shift>w",
-	orders_menu_callback,	MENU_ORDER_WAKEUP_OTHERS				},
-  { "/" N_("Orders") "/sep3",				NULL,
+	orders_menu_callback,	MENU_ORDER_WAKEUP_OTHERS			},
+  { "/" N_("Orders") "/sep4",				NULL,
 	NULL,			0,					"<Separator>"	},
   { "/" N_("Orders") "/" N_("_Auto Settler"),		"a",
 	orders_menu_callback,	MENU_ORDER_AUTO_SETTLER					},
@@ -683,49 +1087,23 @@
 	orders_menu_callback,	MENU_ORDER_PATROL					},
   { "/" N_("Orders") "/" N_("_Go to"),			"g",
 	orders_menu_callback,	MENU_ORDER_GOTO						},
-  { "/" N_("Orders") "/" N_("Go|Airlift to City"),	"l",
+  { "/" N_("Orders") "/" N_("Go|Airlift to City"),	NULL,
 	orders_menu_callback,	MENU_ORDER_GOTO_CITY					},
-  { "/" N_("Orders") "/sep4",				NULL,
+  { "/" N_("Orders") "/sep5",				NULL,
 	NULL,			0,					"<Separator>"	},
   { "/" N_("Orders") "/" N_("Disband Unit"),		"<shift>d",
 	orders_menu_callback,	MENU_ORDER_DISBAND					},
   { "/" N_("Orders") "/" N_("Diplomat|Spy Actions"),	"d",
 	orders_menu_callback,	MENU_ORDER_DIPLOMAT_DLG					},
-  { "/" N_("Orders") "/" N_("Explode Nuclear"),        "<shift>n",
+  { "/" N_("Orders") "/" N_("Explode Nuclear"),        NULL,
 	orders_menu_callback,	MENU_ORDER_NUKE						},
-  { "/" N_("Orders") "/sep5",				NULL,
+  { "/" N_("Orders") "/sep6",				NULL,
 	NULL,			0,					"<Separator>"	},
   { "/" N_("Orders") "/" N_("_Wait"),			"w",
 	orders_menu_callback,	MENU_ORDER_WAIT						},
   { "/" N_("Orders") "/" N_("Done"),			"space",
 	orders_menu_callback,	MENU_ORDER_DONE						},
-  /* Reports menu ... */
-  { "/" N_("_Reports"),					NULL,
-	NULL,			0,					"<Branch>"	},
-  { "/" N_("Reports") "/tearoff1",			NULL,
-	NULL,			0,					"<Tearoff>"	},
-  { "/" N_("Reports") "/" N_("_Cities"),		"F1",
-	reports_menu_callback,	MENU_REPORT_CITIES					},
-  { "/" N_("Reports") "/" N_("_Units"),			"F2",
-	reports_menu_callback,	MENU_REPORT_UNITS					},
-  { "/" N_("Reports") "/" N_("_Players"),		"F3",
-	reports_menu_callback,	MENU_REPORT_PLAYERS					},
-  { "/" N_("Reports") "/" N_("_Economy"),		"F5",
-	reports_menu_callback,	MENU_REPORT_ECONOMY					},
-  { "/" N_("Reports") "/" N_("_Science"),		"F6",
-	reports_menu_callback,	MENU_REPORT_SCIENCE					},
-  { "/" N_("Reports") "/sep1",				NULL,
-	NULL,			0,					"<Separator>"	},
-  { "/" N_("Reports") "/" N_("_Wonders of the World"),	"F7",
-	reports_menu_callback,	MENU_REPORT_WOW						},
-  { "/" N_("Reports") "/" N_("_Top Five Cities"),	"F8",
-	reports_menu_callback,	MENU_REPORT_TOP_CITIES					},
-  { "/" N_("Reports") "/" N_("_Messages"),		"F10",
-	reports_menu_callback,	MENU_REPORT_MESSAGES					},
-  { "/" N_("Reports") "/" N_("_Demographics"),		"F11",
-	reports_menu_callback,	MENU_REPORT_DEMOGRAPHIC					},
-  { "/" N_("Reports") "/" N_("S_paceship"),		"F12",
-	reports_menu_callback,	MENU_REPORT_SPACESHIP					},
+
   /* Help menu ... */
   { "/" N_("_Help"),					NULL,
 	NULL,			0,					"<LastBranch>"	},
@@ -734,15 +1112,15 @@
   { "/" N_("Help") "/" N_("Language_s"),		NULL,
 	help_menu_callback,	MENU_HELP_LANGUAGES					},
   { "/" N_("Help") "/" N_("Co_nnecting"),		NULL,
-	help_menu_callback,	MENU_HELP_CONNECTING					},
+	help_menu_callback,	MENU_HELP_CONNECTING				},
   { "/" N_("Help") "/" N_("C_ontrols"),			NULL,
 	help_menu_callback,	MENU_HELP_CONTROLS					},
   { "/" N_("Help") "/" N_("C_hatline"),			NULL,
 	help_menu_callback,	MENU_HELP_CHATLINE					},
-  { "/" N_("Help") "/" N_("_Worklist Editor"),			NULL,
-	help_menu_callback,	MENU_HELP_WORKLIST_EDITOR				},
-  { "/" N_("Help") "/" N_("Citizen _Management"),			NULL,
-	help_menu_callback,	MENU_HELP_CMA						},
+  { "/" N_("Help") "/" N_("_Worklist Editor"),         NULL,
+   help_menu_callback, MENU_HELP_WORKLIST_EDITOR               },
+  { "/" N_("Help") "/" N_("Citizen _Management"),          NULL,
+   help_menu_callback, MENU_HELP_CMA                       },
   { "/" N_("Help") "/" N_("_Playing"),			NULL,
 	help_menu_callback,	MENU_HELP_PLAYING					},
   { "/" N_("Help") "/sep1",				NULL,
@@ -762,11 +1140,11 @@
   { "/" N_("Help") "/" N_("Won_ders"),			NULL,
 	help_menu_callback,	MENU_HELP_WONDERS					},
   { "/" N_("Help") "/" N_("_Government"),		NULL,
-	help_menu_callback,	MENU_HELP_GOVERNMENT					},
+	help_menu_callback,	MENU_HELP_GOVERNMENT				},
   { "/" N_("Help") "/" N_("Happin_ess"),		NULL,
 	help_menu_callback,	MENU_HELP_HAPPINESS					},
   { "/" N_("Help") "/" N_("Space _Race"),		NULL,
-	help_menu_callback,	MENU_HELP_SPACE_RACE					},
+	help_menu_callback,	MENU_HELP_SPACE_RACE				},
   { "/" N_("Help") "/sep2",				NULL,
 	NULL,			0,					"<Separator>"	},
   { "/" N_("Help") "/" N_("_Copying"),			NULL,
@@ -963,19 +1341,31 @@
     menus_set_sensitive("<main>/_Reports", FALSE);
     menus_set_sensitive("<main>/_Kingdom", FALSE);
     menus_set_sensitive("<main>/_View", FALSE);
+    menus_set_sensitive("<main>/_Popups", FALSE);
+    menus_set_sensitive("<main>/_Battlegroups", FALSE);
+    menus_set_sensitive("<main>/_Filters", FALSE);
     menus_set_sensitive("<main>/_Orders", FALSE);
+
   } else {
-    struct unit *punit;
+    char bgfocus[64], bgassign[64], bgstatistics[64],
+         bgmembers[64], dispersiontext[64];
+    char *dispersion  = _(",  Dispersion: %d");
+    int i;
+    struct unit *punit = get_unit_in_focus();
     menus_set_sensitive("<main>/_Reports", TRUE);
     menus_set_sensitive("<main>/_Kingdom", TRUE);
     menus_set_sensitive("<main>/_View", TRUE);
+    menus_set_sensitive("<main>/_Popups", TRUE);
+    menus_set_sensitive("<main>/_Battlegroups", TRUE);
+    menus_set_sensitive("<main>/_Filters", !tile_units_active);
     menus_set_sensitive("<main>/_Orders", !client_is_observer());
 
     menus_set_sensitive("<main>/_Kingdom/_Tax Rates", !client_is_observer());
     menus_set_sensitive("<main>/_Kingdom/Work_lists", !client_is_observer());
     menus_set_sensitive("<main>/_Kingdom/_Revolution",
-			!client_is_observer());
+           !client_is_observer());
 
+  
     menus_set_sensitive("<main>/_Reports/S_paceship",
 			(game.player_ptr->spaceship.state!=SSHIP_NONE));
 
@@ -996,18 +1386,66 @@
     menus_set_active("<main>/_View/Focus Unit", draw_focus_unit);
     menus_set_sensitive("<main>/_View/Focus Unit", !draw_units);
     menus_set_active("<main>/_View/Fog of War", draw_fog_of_war);
+
+    menus_set_active("<main>/_Popups/P_opup new cities", popup_cities);
+    menus_set_active("<main>/_Popups/_Auto name cities", auto_name_cities);
+    menus_set_active("<main>/_Popups/Diplomat Popups", popup_diplomats);
+    menus_set_active("<main>/_Popups/Caravan Popups", popup_caravans);
 
-    /* Remaining part of this function: Update Orders menu */
+    menus_set_active("<main>/_Battlegroups/Autojoin", autojoin);
 
+
     if (client_is_observer()) {
       return;
     }
+
+    /* Area Selection of units has no concept of focus unit */
 
-    if((punit=get_unit_in_focus())) {
+    if (tile_units_active) {
+      menus_set_sensitive("<main>/_Orders/Build _Road",     TRUE);
+      menus_set_sensitive("<main>/_Orders/Build _Fortress", TRUE);
+      menus_set_sensitive("<main>/_Orders/_Sentry",         TRUE);
+      menus_set_sensitive("<main>/_Orders/Wake up o_thers", TRUE);
+      menus_set_sensitive("<main>/_Orders/Auto E_xplore",   TRUE);
+
+      menus_set_sensitive("<main>/_Orders/Batch Command",           FALSE);
+      menus_set_sensitive("<main>/_Orders/_Build City",             FALSE);
+      menus_set_sensitive("<main>/_Orders/Build _Irrigation",       FALSE);
+      menus_set_sensitive("<main>/_Orders/Build _Mine",             FALSE);
+      menus_set_sensitive("<main>/_Orders/Transf_orm Terrain",      FALSE);
+      menus_set_sensitive("<main>/_Orders/Build Airbas_e",          FALSE);
+      menus_set_sensitive("<main>/_Orders/Clean _Pollution",        FALSE);
+      menus_set_sensitive("<main>/_Orders/Clean _Nuclear Fallout",  FALSE);
+      menus_set_sensitive("<main>/_Orders/Pillage",                 FALSE);
+      menus_set_sensitive("<main>/_Orders/Make _Homecity",          FALSE);
+      menus_set_sensitive("<main>/_Orders/_Unload",                 FALSE);
+      menus_set_sensitive("<main>/_Orders/_Auto Settler",           FALSE);
+      menus_set_sensitive("<main>/_Orders/_Connect",                FALSE);
+      menus_set_sensitive("<main>/_Orders/Patrol (_Q)",             FALSE);
+      menus_set_sensitive("<main>/_Orders/_Go to",                  FALSE);
+      menus_set_sensitive("<main>/_Orders/Diplomat|Spy Actions",    FALSE);
+      menus_set_sensitive("<main>/_Orders/Explode Nuclear",         FALSE);
+      menus_set_sensitive("<main>/_Orders/Wait",                    FALSE);
+      menus_set_sensitive("<main>/_Orders/Done",                    FALSE);
+      menus_set_sensitive("<main>/_Orders/Go|Airlift to City",      FALSE);
+      menus_set_sensitive("<main>/_Orders/Disband Unit",            FALSE);
+
+      menus_rename("<main>/_Orders", _("Orders: Area Selection"));
+      menus_rename("<main>/_Orders/Build _Road", _("_Return & Recover Ships"));
+      menus_rename("<main>/_Orders/Build _Fortress", _("_Fortify"));
+      menus_rename("<main>/_Orders/Wake up o_thers", _("Wake up"));
+    } else  {
+
+
+    if(punit) {
+      char *otext  = _("_Orders:  %s");
+      char *motext = _("Mission _Orders:  %s");
+      char *botext = _("Batch _Orders:  %s");
+      char *bmtext = _("Batch Missi_ons:  %s");
       char *irrfmt = _("Change to %s (_I)");
       char *minfmt = _("Change to %s (_M)");
       char *transfmt = _("Transf_orm to %s");
-      char irrtext[128], mintext[128], transtext[128];
+      char irrtext[128], mintext[128], transtext[128], orderstext[128], filterstext[128];
       char *roadtext;
       enum tile_terrain_type  ttype;
       struct tile_type *      tinfo;
@@ -1015,83 +1453,184 @@
       sz_strlcpy(irrtext, _("Build _Irrigation"));
       sz_strlcpy(mintext, _("Build _Mine"));
       sz_strlcpy(transtext, _("Transf_orm Terrain"));
-      
+
+      /*   When hover state is goto, enable possible missions orders only.
+       *   Validity of mission order is to be checked on arrival.
+       *   When batch command, but not goto, is active, only these orders may be
+       *   available: Auto, Sentry, Fortify, Build Wonder, Explore, Wakeup, Wait, R&R.
+       */
+      menus_set_sensitive("<main>/_Orders/Batch Command", !batch_command
+        && (hover_state==HOVER_NONE || hover_state==HOVER_GOTO));
       /* Enable the button for adding to a city in all cases, so we
 	 get an eventual error message from the server if we try. */
       menus_set_sensitive("<main>/_Orders/_Build City",
-			  can_unit_add_or_build_city(punit) ||
-			  unit_can_help_build_wonder_here(punit));
+	    ((unit_flag(punit, F_CITIES) && !batch_command)
+        || unit_can_help_build_wonder_here(punit)
+        || (is_military_unit(punit) && (is_ground_unit(punit) || is_sailing_unit(punit))
+          && hover_state!=HOVER_GOTO && !batch_command)
+        || (hover_state==HOVER_GOTO
+          && ((unit_flag(punit, F_CITIES) && !batch_command)
+            || (unit_flag(punit, F_HELP_WONDER))))));
       menus_set_sensitive("<main>/_Orders/Build _Road",
-                          (can_unit_do_activity(punit, ACTIVITY_ROAD) ||
-                           can_unit_do_activity(punit, ACTIVITY_RAILROAD) ||
-                           unit_can_est_traderoute_here(punit)));
+        ((can_unit_do_activity(punit, ACTIVITY_ROAD) && !batch_command)
+        || (can_unit_do_activity(punit, ACTIVITY_RAILROAD) && !batch_command)
+        || (unit_can_est_traderoute_here(punit) && !batch_command)
+        || (is_sailing_unit(punit) && hover_state!=HOVER_GOTO)
+        || (hover_state==HOVER_GOTO
+           && (unit_flag(punit, F_SETTLERS) || unit_flag(punit, F_TRADE_ROUTE)))
+        || (batch_command && hover_state!=HOVER_GOTO)));
       menus_set_sensitive("<main>/_Orders/Build _Irrigation",
-                          can_unit_do_activity(punit, ACTIVITY_IRRIGATE));
+        ((can_unit_do_activity(punit, ACTIVITY_IRRIGATE) && !batch_command)
+        || (hover_state==HOVER_GOTO && unit_flag(punit, F_SETTLERS))));
       menus_set_sensitive("<main>/_Orders/Build _Mine",
-                          can_unit_do_activity(punit, ACTIVITY_MINE));
+        ((can_unit_do_activity(punit, ACTIVITY_MINE) && !batch_command)
+        || (hover_state==HOVER_GOTO && unit_flag(punit, F_SETTLERS))));
       menus_set_sensitive("<main>/_Orders/Transf_orm Terrain",
-			  can_unit_do_activity(punit, ACTIVITY_TRANSFORM));
+        ((can_unit_do_activity(punit, ACTIVITY_TRANSFORM) && !batch_command)
+        || (hover_state==HOVER_GOTO && unit_flag(punit, F_SETTLERS))));
       menus_set_sensitive("<main>/_Orders/Build _Fortress",
-                          (can_unit_do_activity(punit, ACTIVITY_FORTRESS) ||
-                           can_unit_do_activity(punit, ACTIVITY_FORTIFYING)));
+        ((can_unit_do_activity(punit, ACTIVITY_FORTRESS) && !batch_command)
+        || can_unit_do_activity(punit, ACTIVITY_FORTIFYING)
+        || (hover_state==HOVER_GOTO && is_ground_unit(punit)
+          && (!unit_flag(punit, F_SETTLERS)
+            || player_knows_techs_with_flag(game.player_ptr, TF_FORTRESS)))));
       menus_set_sensitive("<main>/_Orders/Build Airbas_e",
-			  can_unit_do_activity(punit, ACTIVITY_AIRBASE));
+		((can_unit_do_activity(punit, ACTIVITY_AIRBASE) && !batch_command)
+        || (hover_state==HOVER_GOTO && unit_flag(punit, F_AIRBASE)
+          && player_knows_techs_with_flag(game.player_ptr, TF_AIRBASE))));
       menus_set_sensitive("<main>/_Orders/Clean _Pollution",
-                          (can_unit_do_activity(punit, ACTIVITY_POLLUTION) ||
-                           can_unit_paradrop(punit)));
+        ((can_unit_do_activity(punit, ACTIVITY_POLLUTION) && !batch_command)
+        || (can_unit_paradrop(punit) && !batch_command)
+        || (hover_state==HOVER_GOTO && unit_flag(punit, F_SETTLERS))));
       menus_set_sensitive("<main>/_Orders/Clean _Nuclear Fallout",
-			  can_unit_do_activity(punit, ACTIVITY_FALLOUT));
+		((can_unit_do_activity(punit, ACTIVITY_FALLOUT) && !batch_command)
+        || (hover_state==HOVER_GOTO && unit_flag(punit, F_SETTLERS))));
       menus_set_sensitive("<main>/_Orders/_Sentry",
-			  can_unit_do_activity(punit, ACTIVITY_SENTRY));
+		can_unit_do_activity(punit, ACTIVITY_SENTRY));
       menus_set_sensitive("<main>/_Orders/Pillage",
-			  can_unit_do_activity(punit, ACTIVITY_PILLAGE));
+        (can_unit_do_activity(punit, ACTIVITY_PILLAGE)
+         && hover_state!=HOVER_GOTO && !batch_command));
       menus_set_sensitive("<main>/_Orders/Make _Homecity",
-			  can_unit_change_homecity(punit));
+		((can_unit_change_homecity(punit) && !batch_command)
+        || (hover_state==HOVER_GOTO)));
       menus_set_sensitive("<main>/_Orders/_Unload",
-			  get_transporter_capacity(punit)>0);
+		get_transporter_capacity(punit)>0
+        && (!batch_command || hover_state==HOVER_GOTO));
       menus_set_sensitive("<main>/_Orders/Wake up o_thers", 
-			  is_unit_activity_on_tile(ACTIVITY_SENTRY,
-                                                   punit->x, punit->y));
+		((is_unit_activity_on_tile(ACTIVITY_SENTRY, punit->x, punit->y)
+          || batch_command)
+        && hover_state!=HOVER_GOTO));
       menus_set_sensitive("<main>/_Orders/_Auto Settler",
-                          can_unit_do_auto(punit));
+        (can_unit_do_auto(punit)
+        || (hover_state==HOVER_GOTO
+          && (unit_flag(punit, F_SETTLERS) || is_military_unit(punit)))));
       menus_set_sensitive("<main>/_Orders/Auto E_xplore",
-                          can_unit_do_activity(punit, ACTIVITY_EXPLORE));
+        can_unit_do_activity(punit, ACTIVITY_EXPLORE));
       menus_set_sensitive("<main>/_Orders/_Connect",
-                          can_unit_do_connect(punit, ACTIVITY_IDLE));
+        (can_unit_do_connect(punit, ACTIVITY_IDLE)
+        && hover_state!=HOVER_GOTO && !batch_command));
+      menus_set_sensitive("<main>/_Orders/_Go to", TRUE);
       menus_set_sensitive("<main>/_Orders/Patrol (_Q)",
-                          can_unit_do_activity(punit, ACTIVITY_PATROL));
+        (can_unit_do_activity(punit, ACTIVITY_PATROL)
+        && hover_state!=HOVER_GOTO && !batch_command));
       menus_set_sensitive("<main>/_Orders/Diplomat|Spy Actions",
-                          (is_diplomat_unit(punit)
-                           && diplomat_can_do_action(punit, DIPLOMAT_ANY_ACTION,
-						     punit->x, punit->y)));
+        (is_diplomat_unit(punit)
+          && diplomat_can_do_action(punit, DIPLOMAT_ANY_ACTION, punit->x, punit->y)
+          && hover_state!=HOVER_GOTO && !batch_command));
       menus_set_sensitive("<main>/_Orders/Explode Nuclear",
-			  unit_flag(punit, F_NUCLEAR));
+		unit_flag(punit, F_NUCLEAR)
+        && hover_state!=HOVER_GOTO && !batch_command); /* how about mass-nuking? */
+      menus_set_sensitive("<main>/_Orders/Wait", hover_state!=HOVER_GOTO);
+      menus_set_sensitive("<main>/_Orders/Done", hover_state!=HOVER_GOTO && !batch_command);
+      menus_set_sensitive("<main>/_Orders/Go|Airlift to City",
+        hover_state!=HOVER_GOTO && !batch_command);
+      menus_set_sensitive("<main>/_Orders/Disband Unit", !batch_command);
+
+      menus_set_sensitive("<main>/_Filters/_New Units",         !filter_new);
+      menus_set_sensitive("<main>/_Filters/_Veteran Units",     !filter_veteran);
+      menus_set_sensitive("<main>/_Filters/Current _Location",  !filter_current_location);
+      menus_set_sensitive("<main>/_Filters/_Radius of 5",       !filter_radius);
+      menus_set_sensitive("<main>/_Filters/Include _Sentries",  !filter_include_sentries);
+      menus_set_sensitive("<main>/_Filters/Include _Fortified", !filter_include_fortified);
+      menus_set_sensitive("<main>/_Filters/Include _Exhausted", !filter_include_exhausted);
+      menus_set_sensitive("<main>/_Filters/Include _Gotos",     !filter_include_gotos);
+      menus_set_sensitive("<main>/_Filters/Include _Members",   !filter_include_members);
+
+    /* renaming menus */
+
+      if  (batch_command)
+            my_snprintf (orderstext, sizeof(orderstext),
+              hover_state==HOVER_GOTO ? bmtext : botext,
+                focus_category ? get_category_name() : unit_types[punit->type].name);
+      else
+            my_snprintf (orderstext, sizeof(orderstext),
+              hover_state==HOVER_GOTO ? motext : otext,
+                focus_category ? get_category_name() : unit_types[punit->type].name);
+
+      menus_rename("<main>/_Orders", orderstext);
+
+      my_snprintf (filterstext, sizeof(filterstext), _("_Filters: [%s%s%s%s%s%s%s%s%s]"),
+        filter_new                ? "N" : "  ",
+        filter_veteran            ? "V" : "  ",
+        filter_current_location   ? "L" : "  ",
+        filter_radius             ? "R" : "  ",
+        filter_include_sentries   ? "S" : "  ",
+        filter_include_fortified  ? "F" : "  ",
+        filter_include_exhausted  ? "E" : "  ",
+        filter_include_gotos      ? "G" : "  ",
+        filter_include_members    ? "M" : "  ");
+      menus_rename("<main>/_Filters", filterstext);
+
+      if (get_unit_in_focus() && get_unit_in_focus()->bg)
+        menus_rename("<main>/_Filters/Include _Members", _("Include Non-_Members"));
+      else
+        menus_rename("<main>/_Filters/Include _Members", _("Include _Members"));
+
+      if (hover_state==HOVER_GOTO)
+	menus_rename("<main>/_Orders/_Go to", _("Add _Goto Waypoint"));
+      else
+	menus_rename("<main>/_Orders/_Go to", _("_Go to"));
+
       if (unit_flag(punit, F_HELP_WONDER))
 	menus_rename("<main>/_Orders/_Build City", _("Help _Build Wonder"));
       else if (unit_flag(punit, F_CITIES)) {
-	if (map_get_city(punit->x, punit->y))
+	if (map_get_city(punit->x, punit->y) && hover_state!=HOVER_GOTO)
 	  menus_rename("<main>/_Orders/_Build City", _("Add to City (_B)"));
 	else
 	  menus_rename("<main>/_Orders/_Build City", _("_Build City"));
       }
+      else if (is_military_unit(punit) && (is_ground_unit(punit) || is_sailing_unit(punit)))
+	menus_rename("<main>/_Orders/_Build City", _("_Bodyguard"));
       else 
 	menus_rename("<main>/_Orders/_Build City", _("_Build City"));
- 
+
+    /* R&R key in batch mode applies to all damaged ships regardless of
+     * focus unit. Batch build Road or establish tradeRoute is not useful.
+    */
+    if ((batch_command && hover_state!=HOVER_GOTO))
+      roadtext = _("_Return & Recover Ships");
+    else  {
       if (unit_flag(punit, F_TRADE_ROUTE))
-	menus_rename("<main>/_Orders/Build _Road", _("Make Trade _Route"));
+        roadtext = _("Make Trade _Route");
       else if (unit_flag(punit, F_SETTLERS)) {
-	if (map_has_special(punit->x, punit->y, S_ROAD)) {
-	  roadtext = _("Build _Railroad");
-	  road_activity=ACTIVITY_RAILROAD;  
-	} 
-	else {
-	  roadtext = _("Build _Road");
-	  road_activity=ACTIVITY_ROAD;  
-	}
-	menus_rename("<main>/_Orders/Build _Road", roadtext);
+        if (hover_state!=HOVER_GOTO){
+          if (map_has_special(punit->x, punit->y, S_ROAD)) {
+            roadtext = _("Build _Railroad");
+            road_activity=ACTIVITY_RAILROAD;  
+          }
+          else {
+            roadtext = _("Build _Road");
+            road_activity=ACTIVITY_ROAD;  
+          }
+        } else
+        roadtext = _("Build _Road or Railroad");
       }
+      else if (is_sailing_unit(punit))
+        roadtext = _("_Return & Recover");
       else
-	menus_rename("<main>/_Orders/Build _Road", _("Build _Road"));
+        roadtext = _("Build _Road");
+    }
+    menus_rename("<main>/_Orders/Build _Road", roadtext);
 
       ttype = map_get_tile(punit->x, punit->y)->terrain;
       tinfo = get_tile_type(ttype);
@@ -1115,7 +1654,11 @@
 	  my_snprintf (transtext, sizeof(transtext), transfmt,
 		   (get_tile_type(tinfo->transform_result))->terrain_name);
 	}
-
+      if (hover_state==HOVER_GOTO)  {
+            sz_strlcpy (irrtext, _("Build _Irrigation"));
+            sz_strlcpy (mintext, _("Build _Mine"));
+            sz_strlcpy (transtext, _("Transf_orm Terrain"));
+      }
       menus_rename("<main>/_Orders/Build _Irrigation", irrtext);
       menus_rename("<main>/_Orders/Build _Mine", mintext);
       menus_rename("<main>/_Orders/Transf_orm Terrain", transtext);
@@ -1130,6 +1673,8 @@
       else
 	menus_rename("<main>/_Orders/Clean _Pollution", _("Clean _Pollution"));
 
+    menus_rename("<main>/_Orders/Wake up o_thers", _("Wake up o_thers"));
+
       if (!unit_flag(punit, F_SETTLERS))
 	menus_rename("<main>/_Orders/_Auto Settler", _("_Auto Attack"));
       else
@@ -1139,5 +1684,64 @@
     }
     else
       menus_set_sensitive("<main>/_Orders", FALSE);
+    }
+
+    /* Battlegroups menu */
+
+    for (i = 0; i < NUM_BATTLEGROUPS; i++)
+    {
+	  my_snprintf (bgfocus, sizeof(bgfocus),
+        _("<main>/_Battlegroups/Focus on Zero/Group %d"), i + 1);
+
+	  my_snprintf (bgassign, sizeof(bgassign),
+        _("<main>/_Battlegroups/Assign to Battlegroup/Group %d"), i + 1);
+
+	  my_snprintf (bgstatistics, sizeof(bgstatistics),
+        _("<main>/_Battlegroups/Statistics/%d. Group"), i + 1);
+
+	  my_snprintf (dispersiontext, sizeof(dispersiontext),
+        dispersion, bg[i]->dispersion);
+
+	  my_snprintf (bgmembers, sizeof(bgmembers),
+        _("%d. %s:  %d %s%s%s"),
+        i + 1,
+        bg[i]->name,
+        unit_list_size(&bg[i]->units),
+        unit_list_size(&bg[i]->units) == 1 ? _("member") : _("members"),
+        bg[i]->aggression ? _(",  Aggression") : "",
+        bg[i]->dispersion ? dispersiontext : "");
+
+      menus_rename(bgfocus, bg[i]->name);
+      menus_rename(bgassign, bg[i]->name);
+      menus_rename(bgstatistics, bgmembers);
+      menus_set_sensitive(bgstatistics, unit_list_size(&bg[i]->units));
+    }
   }
+}
+
+/****************************************************************
+ Separate to avoid horrible spaghetti code.
+ Radio buttons generate multiple callbacks.
+ Must be called when code changes focus_category directly.
+*****************************************************************/
+void update_radio_buttons(void)
+{
+  menus_set_active("<main>/_Filters/Focus Category/Normal",
+                    focus_category == FILTER_NORMAL);
+  menus_set_active("<main>/_Filters/Focus Category/_Diplomats",
+                    focus_category == FILTER_DIPLOMATS);
+  menus_set_active("<main>/_Filters/Focus Category/_Caravans",
+                    focus_category == FILTER_CARAVANS);
+  menus_set_active("<main>/_Filters/Focus Category/Settlers",
+                    focus_category == FILTER_SETTLERS);
+  menus_set_active("<main>/_Filters/Focus Category/_Airplanes",
+                    focus_category == FILTER_AIRPLANES);
+  menus_set_active("<main>/_Filters/Focus Category/_Helicopters",
+                    focus_category == FILTER_HELICOPTERS);
+  menus_set_active("<main>/_Filters/Focus Category/_Infantry",
+                    focus_category == FILTER_INFANTRY);
+  menus_set_active("<main>/_Filters/Focus Category/_Warships",
+                    focus_category == FILTER_WARSHIPS);
+  menus_set_active("<main>/_Filters/Focus Category/_Transporters",
+                    focus_category == FILTER_TRANSPORTERS);
 }
Index: client/include/mapctrl_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/mapctrl_g.h,v
retrieving revision 1.9
diff -u -r1.9 mapctrl_g.h
--- client/include/mapctrl_g.h	2002/08/24 14:37:49	1.9
+++ client/include/mapctrl_g.h	2002/10/06 05:01:26
@@ -17,6 +17,9 @@
 
 #include "mapctrl_common.h"
 
+extern bool tile_cities_active;
+extern bool tile_units_active;
+
 struct unit;
 struct city;
 
@@ -27,5 +30,7 @@
 void set_turn_done_button_state(bool state);
 
 void create_line_at_mouse_pos(void);
+
+void cancel_tile_selection(void);
 
 #endif  /* FC__MAPCTRL_G_H */
Index: client/include/menu_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/menu_g.h,v
retrieving revision 1.2
diff -u -r1.2 menu_g.h
--- client/include/menu_g.h	2001/12/11 16:16:37	1.2
+++ client/include/menu_g.h	2002/10/06 05:01:26
@@ -14,5 +14,6 @@
 #define FC__MENU_G_H
 
 void update_menus(void);
+void update_radio_buttons(void);
 
 #endif  /* FC__MENU_G_H */
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.126
diff -u -r1.126 map.c
--- common/map.c	2002/09/11 17:04:42	1.126
+++ common/map.c	2002/10/06 05:01:31
@@ -1148,6 +1148,8 @@
   unit_list_init(&ptile->units);
   ptile->worked   = NULL; /* pointer to city working tile */
   ptile->assigned = 0; /* bitvector */
+  ptile->selected = 0;
+  ptile->targeted_by = 0;
 }
 
 /***************************************************************
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.130
diff -u -r1.130 map.h
--- common/map.h	2002/09/10 13:30:56	1.130
+++ common/map.h	2002/10/06 05:01:34
@@ -62,6 +62,8 @@
   struct city *worked;      /* city working tile, or NULL if none */
   signed short continent;
   signed char move_cost[8]; /* don't know if this helps! */
+  int selected;     /* Area Selection. 1=city, 2=unit(s). Client. */
+  int targeted_by;  /* Unit that intends to occupy this tile. Client. */
 };
 
 
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.89
diff -u -r1.89 unit.h
--- common/unit.h	2002/08/07 11:21:49	1.89
+++ common/unit.h	2002/10/06 05:01:35
@@ -22,6 +22,27 @@
 struct goto_route;
 struct tile;
 
+/* To be executed on arrival at goto destination */
+enum mission_orders {
+  ORDERS_SENTRY,
+  ORDERS_FORTIFY,
+  ORDERS_AUTO,
+  ORDERS_MINE,
+  ORDERS_IRRIGATE,
+  ORDERS_TRANSFORM,
+  ORDERS_AIRBASE,
+  ORDERS_POLLUTION,
+  ORDERS_FALLOUT,
+  ORDERS_UNLOAD,
+  ORDERS_EXPLORE,
+  ORDERS_HOMECITY,
+  ORDERS_DISBAND,
+  ORDERS_ROAD,      /* Establish traderoute for caravans */
+  ORDERS_BUILD,     /* Build Wonder for caravans */
+  ORDERS_BUILD_NOW  /* For delayed settlers */
+};
+
+
 enum unit_activity {
   ACTIVITY_IDLE, ACTIVITY_POLLUTION, ACTIVITY_ROAD, ACTIVITY_MINE,
   ACTIVITY_IRRIGATE, ACTIVITY_FORTIFIED, ACTIVITY_FORTRESS, ACTIVITY_SENTRY,
@@ -109,6 +130,7 @@
   int id;
   int owner;
   int x, y;                           
+  bool never_moved;
   bool veteran;
   int homecity;
   int moves_left;
@@ -134,6 +156,11 @@
   bool connecting;
   int transported_by;
   struct goto_route *pgr;
+  bool mission_flag;
+  enum mission_orders orders;
+  int bg;     /* battlegroup. 0 means none. */
+  int range;  /* distance to the battlefield (Zero). */
+  int zx, zy; /* Zero coord at the time of last scramble. */
 };
 
 
Index: data/isotrident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident.tilespec,v
retrieving revision 1.2
diff -u -r1.2 isotrident.tilespec
--- data/isotrident.tilespec	2002/05/03 16:05:34	1.2
+++ data/isotrident.tilespec	2002/10/06 05:01:35
@@ -40,6 +40,7 @@
   "isotrident/terrain1.spec",
   "isotrident/terrain2.spec",
   "isotrident/tiles.spec",
+  "isotrident/icons.spec",
   "isotrident/small.spec",
   "isotrident/units.spec",
   "isotrident/flags.spec",
Index: data/trident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident.tilespec,v
retrieving revision 1.10
diff -u -r1.10 trident.tilespec
--- data/trident.tilespec	2001/12/11 16:16:40	1.10
+++ data/trident.tilespec	2002/10/06 05:01:36
@@ -37,6 +37,8 @@
 ; tag is used).
 files = 
   "trident/tiles.spec",
+  "trident/icons.spec",
+  "trident/groups.spec",
   "misc/small.spec",
   "trident/units.spec",
   "trident/flags.spec",
Index: data/trident_shields.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident_shields.tilespec,v
retrieving revision 1.3
diff -u -r1.3 trident_shields.tilespec
--- data/trident_shields.tilespec	2000/04/02 17:26:59	1.3
+++ data/trident_shields.tilespec	2002/10/06 05:01:36
@@ -36,6 +36,7 @@
 ; tag is used).
 files = 
   "trident/tiles.spec",
+  "trident/icons.spec",
   "misc/small.spec",
   "trident/units.spec",
   "trident/flags.spec",
Index: data/isotrident/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident/Makefile.am,v
retrieving revision 1.1
diff -u -r1.1 Makefile.am
--- data/isotrident/Makefile.am	2002/05/02 05:46:54	1.1
+++ data/isotrident/Makefile.am	2002/10/06 05:01:36
@@ -8,6 +8,8 @@
 	cities.spec	\
 	flags.xpm	\
 	flags.spec	\
+	icons.xpm	\
+	icons.spec	\
 	nuke.spec	\
 	nuke.xpm	\
 	small.spec	\
Index: data/trident/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident/Makefile.am,v
retrieving revision 1.6
diff -u -r1.6 Makefile.am
--- data/trident/Makefile.am	2000/01/22 17:00:31	1.6
+++ data/trident/Makefile.am	2002/10/06 05:01:36
@@ -11,6 +11,9 @@
 	explosions.spec	\
 	flags.xpm	\
 	flags.spec	\
+	groups.spec	\
+	icons.xpm	\
+	icons.spec	\
 	roads.xpm	\
 	roads.spec	\
 	tiles.xpm	\
