Complete.Org: Mailing Lists: Archives: freeciv-dev: October 2004:
[Freeciv-Dev] (PR#10575) city dialog tooltips
Home

[Freeciv-Dev] (PR#10575) city dialog tooltips

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#10575) city dialog tooltips
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 21 Oct 2004 20:47:54 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=10575 >

Here's a new version of the patch.  It has support for food, shields,
trade, gold, science, luxury, and pollution.

You'll note immediately that this is a lot of code!  A lot of code
duplicated from city.c, and a lot of code duplicated within the
different functions here.  This means there's a reasonable chance of
bugs.  I've tested it in some situations, but not all.  It also should
make us wonder if there's a way to merge these functions.  This is a big
reason why I'd like to start some work on gen-output.

jason

Index: client/citydlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.c,v
retrieving revision 1.50
diff -u -r1.50 citydlg_common.c
--- client/citydlg_common.c     16 Oct 2004 00:00:10 -0000      1.50
+++ client/citydlg_common.c     22 Oct 2004 03:45:53 -0000
@@ -380,6 +380,298 @@
 }
 
 /**************************************************************************
+  Return text describing the food output.
+**************************************************************************/
+void get_city_dialog_food_text(const struct city *pcity,
+                              char *buf, size_t bufsz)
+{
+  int total = 0;
+
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              _("%+4d : Farmers\n"), pcity->food_prod);
+  total += pcity->food_prod;
+
+  cat_snprintf(buf, bufsz,
+              _("%+4d : Consumed by citizens\n"), -2 * pcity->size);
+  total -= 2 * pcity->size;
+
+  if (pcity->food_upkeep > 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Unit upkeep\n"), -pcity->food_upkeep);
+    total -= pcity->food_upkeep;
+  }
+
+  if (city_unhappy(pcity)) {
+    cat_snprintf(buf, bufsz, _("%+4d : Disorder\n"), -MAX(total, 0));
+  }
+  
+  cat_snprintf(buf, bufsz,
+              _("==== : Adds up to\n"));
+  cat_snprintf(buf, bufsz,
+              _("%4d : Total surplus"), pcity->food_surplus);
+}
+
+/**************************************************************************
+  Return text describing the shield output.
+**************************************************************************/
+void get_city_dialog_shield_text(const struct city *pcity,
+                                char *buf, size_t bufsz)
+{
+  int total = 0, base, bonus = 100;
+  struct effect_source_vector sources;
+
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              _("%+4d : Workers\n"), pcity->shield_prod);
+  total += pcity->shield_prod;
+
+  if (pcity->shield_waste != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Waste\n"), -pcity->shield_waste);
+    total -= pcity->shield_waste;
+  }
+
+  base = total;
+  sources = get_city_bonus_sources(pcity, EFT_PROD_BONUS);
+  effect_source_vector_iterate(&sources, s) {
+    int new_total;
+
+    bonus += s->effect_value;
+    new_total = bonus * base / 100;
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Bonus from %s\n"),
+                (new_total - total), get_improvement_name(s->building));
+    total = new_total;
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
+
+  if (pcity->shield_upkeep > 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Unit upkeep\n"), -pcity->shield_upkeep);
+    total -= pcity->shield_upkeep;
+  }
+
+  if (city_unhappy(pcity)) {
+    cat_snprintf(buf, bufsz, _("%+4d : Disorder\n"), -MAX(total, 0));
+  }
+
+  cat_snprintf(buf, bufsz,
+              _("==== : Adds up to\n"));
+  cat_snprintf(buf, bufsz,
+              _("%4d : Total surplus"), pcity->shield_surplus);
+}
+
+/**************************************************************************
+  Return text describing the food output.
+**************************************************************************/
+void get_city_dialog_trade_text(const struct city *pcity,
+                               char *buf, size_t bufsz)
+{
+  int intercity_trade
+    = pcity->trade_prod - pcity->tile_trade + pcity->corruption;
+
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              _("%+4d : Tile trade\n"), pcity->tile_trade);
+  if (intercity_trade != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Trade routes\n"), -2 * pcity->size);
+  }
+  if (pcity->corruption != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Corruption\n"), -pcity->corruption);
+  }
+  cat_snprintf(buf, bufsz,
+              _("==== : Adds up to\n"));
+  cat_snprintf(buf, bufsz,
+              _("%4d : Total surplus"), pcity->trade_prod);
+}
+
+/**************************************************************************
+  Return text describing the food output.
+**************************************************************************/
+void get_city_dialog_gold_text(const struct city *pcity,
+                              char *buf, size_t bufsz)
+{
+  int sci, lux, gold;
+  int total, surplus, bonus = 100, sp;
+  struct effect_source_vector sources;
+
+  get_tax_income(city_owner(pcity), pcity->trade_prod, &sci, &lux, &gold);
+  surplus = city_gold_surplus(pcity, pcity->tax_total);
+
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              _("%+4d : Gold from trade\n"), gold);
+
+  sp = (pcity->specialists[SP_TAXMAN]
+       * game.rgame.specialists[SP_TAXMAN].bonus);
+  if (sp != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : From %s\n"),
+                sp, game.rgame.specialists[SP_TAXMAN].name);
+    gold += sp;
+  }
+
+  if (city_unhappy(pcity)) {
+    cat_snprintf(buf, bufsz, _("%+4d : Disorder\n"), -gold);
+    gold = 0;
+  }
+
+  total = gold;
+  sources = get_city_bonus_sources(pcity, EFT_TAX_BONUS);
+  effect_source_vector_iterate(&sources, s) {
+    int new_total;
+
+    bonus += s->effect_value;
+    new_total = bonus * lux / 100;
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Bonus from %s\n"),
+                (new_total - total), get_improvement_name(s->building));
+    total = new_total;
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
+
+  if (pcity->gold_unit_upkeep != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Unit upkeep\n"), -pcity->gold_unit_upkeep);
+  }
+  if (pcity->gold_building_upkeep != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Building upkeep\n"), -pcity->gold_building_upkeep);
+  }
+  cat_snprintf(buf, bufsz,
+              _("==== : Adds up to\n"));
+  cat_snprintf(buf, bufsz,
+              _("%4d : Total surplus"), surplus);
+}
+
+/**************************************************************************
+  Return text describing the food output.
+**************************************************************************/
+void get_city_dialog_science_text(const struct city *pcity,
+                                 char *buf, size_t bufsz)
+{
+  int sci, lux, gold;
+  int surplus = pcity->science_total, total, bonus = 100, sp;
+  struct effect_source_vector sources;
+
+  get_tax_income(city_owner(pcity), pcity->trade_prod, &sci, &lux, &gold);
+
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              _("%4d : Science from trade\n"), sci);
+
+  sp = (pcity->specialists[SP_SCIENTIST]
+       * game.rgame.specialists[SP_SCIENTIST].bonus);
+  if (sp != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : From %s\n"),
+                sp, game.rgame.specialists[SP_SCIENTIST].name);
+    sci += sp;
+  }
+
+  if (city_unhappy(pcity)) {
+    cat_snprintf(buf, bufsz, _("%+4d : Disorder\n"), -sci);
+    sci = 0;
+  }
+
+  total = sci;
+  sources = get_city_bonus_sources(pcity, EFT_SCIENCE_BONUS);
+  effect_source_vector_iterate(&sources, s) {
+    int new_total;
+
+    bonus += s->effect_value;
+    new_total = bonus * sci / 100;
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Bonus from %s\n"),
+                (new_total - total), get_improvement_name(s->building));
+    total = new_total;
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
+
+  cat_snprintf(buf, bufsz,
+              _("==== : Adds up to\n"));
+  cat_snprintf(buf, bufsz,
+              _("%4d : Total surplus"), surplus);
+}
+
+/**************************************************************************
+  Return text describing the food output.
+**************************************************************************/
+void get_city_dialog_luxury_text(const struct city *pcity,
+                                char *buf, size_t bufsz)
+{
+  int sci, lux, gold;
+  int surplus = pcity->luxury_total, total, bonus = 100, sp;
+  struct effect_source_vector sources;
+
+  get_tax_income(city_owner(pcity), pcity->trade_prod, &sci, &lux, &gold);
+
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              _("%+4d : Luxury from trade\n"), lux);
+
+  sp = pcity->specialists[SP_ELVIS] * game.rgame.specialists[SP_ELVIS].bonus;
+  if (sp != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : From %s\n"),
+                sp, game.rgame.specialists[SP_ELVIS].name);
+    lux += sp;
+  }
+
+  total = lux;
+  sources = get_city_bonus_sources(pcity, EFT_LUXURY_BONUS);
+  effect_source_vector_iterate(&sources, s) {
+    int new_total;
+
+    bonus += s->effect_value;
+    new_total = bonus * lux / 100;
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Bonus from %s\n"),
+                (new_total - total), get_improvement_name(s->building));
+    total = new_total;
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
+
+  cat_snprintf(buf, bufsz,
+              _("==== : Adds up to\n"));
+  cat_snprintf(buf, bufsz,
+              _("%4d : Total surplus"), surplus);
+}
+
+/**************************************************************************
+  Return text describing the food output.
+**************************************************************************/
+void get_city_dialog_pollution_text(const struct city *pcity,
+                                   char *buf, size_t bufsz)
+{
+  int pollu, prod, pop, mod;
+
+  pollu = city_pollution_types(pcity, pcity->shield_prod,
+                              &prod, &pop, &mod);
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              "%+4d : Pollution from shields\n", prod);
+  cat_snprintf(buf, bufsz,
+              "%+4d : Pollution from citizens\n", pop);
+  cat_snprintf(buf, bufsz,
+              "%+4d : Pollution modifier\n", mod);
+  cat_snprintf(buf, bufsz,
+              "==== : Adds up to\n");
+  cat_snprintf(buf, bufsz,
+              "%4d : Total surplus", pollu);
+}
+
+/**************************************************************************
   Provide a list of all citizens in the city, in order.  "index"
   should be the happiness index (currently [0..4]; 4 = final
   happiness).  "citizens" should be an array large enough to hold all
Index: client/citydlg_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.h,v
retrieving revision 1.27
diff -u -r1.27 citydlg_common.h
--- client/citydlg_common.h     29 Sep 2004 02:24:18 -0000      1.27
+++ client/citydlg_common.h     22 Oct 2004 03:45:53 -0000
@@ -54,6 +54,21 @@
 void get_city_dialog_production_row(char *buf[], size_t column_size, int id,
                                    bool is_unit, struct city *pcity);
 
+void get_city_dialog_food_text(const struct city *pcity,
+                              char *buffer, size_t bufsz);
+void get_city_dialog_shield_text(const struct city *pcity,
+                                char *buffer, size_t bufsz);
+void get_city_dialog_trade_text(const struct city *pcity,
+                               char *buffer, size_t bufsz);
+void get_city_dialog_gold_text(const struct city *pcity,
+                              char *buffer, size_t bufsz);
+void get_city_dialog_science_text(const struct city *pcity,
+                                 char *buffer, size_t bufsz);
+void get_city_dialog_luxury_text(const struct city *pcity,
+                                char *buffer, size_t bufsz);
+void get_city_dialog_pollution_text(const struct city *pcity,
+                                   char *buffer, size_t bufsz);
+
 void get_city_citizen_types(struct city *pcity, int index,
                            struct citizen_type *citizens);
 void city_rotate_specialist(struct city *pcity, int citizen_index);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.411
diff -u -r1.411 packhand.c
--- client/packhand.c   21 Oct 2004 20:27:28 -0000      1.411
+++ client/packhand.c   22 Oct 2004 03:45:54 -0000
@@ -456,7 +456,12 @@
   pcity->tile_trade=packet->tile_trade;
   pcity->corruption=packet->corruption;
   pcity->shield_waste=packet->shield_waste;
-    
+
+  pcity->food_upkeep = packet->food_upkeep;
+  pcity->shield_upkeep = packet->shield_upkeep;
+  pcity->gold_unit_upkeep = packet->gold_unit_upkeep;
+  pcity->gold_building_upkeep = packet->gold_building_upkeep;
+
   pcity->luxury_total=packet->luxury_total;
   pcity->tax_total=packet->tax_total;
   pcity->science_total=packet->science_total;
@@ -730,6 +735,8 @@
     pcity->shield_surplus     = 0;
     pcity->trade_prod         = 0;
     pcity->corruption         = 0;
+    pcity->food_upkeep = 0;
+    pcity->shield_upkeep = 0;
     pcity->luxury_total       = 0;
     pcity->tax_total          = 0;
     pcity->science_total      = 0;
Index: client/text.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/text.c,v
retrieving revision 1.13
diff -u -r1.13 text.c
--- client/text.c       18 Oct 2004 22:40:02 -0000      1.13
+++ client/text.c       22 Oct 2004 03:45:54 -0000
@@ -703,17 +703,17 @@
 const char *get_happiness_buildings(const struct city *pcity)
 {
   int faces = 0;
-  struct building_vector sources;
+  struct effect_source_vector sources;
   INIT;
 
   add_line(_("Buildings: "));
 
   sources = get_city_bonus_sources(pcity, EFT_MAKE_CONTENT);
-  building_vector_iterate(&sources, pbldg) {
+  effect_source_vector_iterate(&sources, src) {
     faces++;
-    add(_("%s. "), get_improvement_name(*pbldg));
-  } building_vector_iterate_end;
-  building_vector_free(&sources);
+    add(_("%s. "), get_improvement_name(src->building));
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
 
   if (faces == 0) {
     add(_("None. "));
@@ -728,31 +728,31 @@
 const char *get_happiness_wonders(const struct city *pcity)
 {
   int faces = 0;
-  struct building_vector sources;
+  struct effect_source_vector sources;
   INIT;
 
   add_line(_("Wonders: "));
 
   sources = get_city_bonus_sources(pcity, EFT_MAKE_HAPPY);
-  building_vector_iterate(&sources, pbldg) {
+  effect_source_vector_iterate(&sources, src) {
     faces++;
-    add(_("%s. "), get_improvement_name(*pbldg));
-  } building_vector_iterate_end;
-  building_vector_free(&sources);
+    add(_("%s. "), get_improvement_name(src->building));
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
 
   sources = get_city_bonus_sources(pcity, EFT_FORCE_CONTENT);
-  building_vector_iterate(&sources, pbldg) {
+  effect_source_vector_iterate(&sources, src) {
     faces++;
-    add(_("%s. "), get_improvement_name(*pbldg));
-  } building_vector_iterate_end;
-  building_vector_free(&sources);
+    add(_("%s. "), get_improvement_name(src->building));
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
 
   sources = get_city_bonus_sources(pcity, EFT_NO_UNHAPPY);
-  building_vector_iterate(&sources, pbldg) {
+  effect_source_vector_iterate(&sources, src) {
     faces++;
-    add(_("%s. "), get_improvement_name(*pbldg));
-  } building_vector_iterate_end;
-  building_vector_free(&sources);
+    add(_("%s. "), get_improvement_name(src->building));
+  } effect_source_vector_iterate_end;
+  effect_source_vector_free(&sources);
 
   if (faces == 0) {
     add(_("None. "));
Index: client/gui-gtk-2.0/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/citydlg.c,v
retrieving revision 1.96
diff -u -r1.96 citydlg.c
--- client/gui-gtk-2.0/citydlg.c        19 Oct 2004 16:35:33 -0000      1.96
+++ client/gui-gtk-2.0/citydlg.c        22 Oct 2004 03:45:54 -0000
@@ -127,6 +127,7 @@
     struct unit_node_vector supported_units;
     struct unit_node_vector present_units;
 
+    GtkWidget *info_ebox[NUM_INFO_FIELDS];
     GtkWidget *info_label[NUM_INFO_FIELDS];
   } overview;
  
@@ -140,6 +141,7 @@
     GtkWidget *map_canvas;
     GtkWidget *map_canvas_pixmap;
     GtkWidget *widget;
+    GtkWidget *info_ebox[NUM_INFO_FIELDS];
     GtkWidget *info_label[NUM_INFO_FIELDS];
   } happiness;
 
@@ -185,7 +187,9 @@
 static gboolean keyboard_handler(GtkWidget * widget, GdkEventKey * event,
                                 struct city_dialog *pdialog);
 
-static GtkWidget *create_city_info_table(GtkWidget **info_label);
+static GtkWidget *create_city_info_table(struct city_dialog *pdialog,
+                                        GtkWidget **info_ebox,
+                                        GtkWidget **info_label);
 static void create_and_append_overview_page(struct city_dialog *pdialog);
 static void create_and_append_worklist_page(struct city_dialog *pdialog);
 static void create_and_append_happiness_page(struct city_dialog *pdialog);
@@ -198,7 +202,8 @@
 
 static void city_dialog_update_title(struct city_dialog *pdialog);
 static void city_dialog_update_citizens(struct city_dialog *pdialog);
-static void city_dialog_update_information(GtkWidget **info_label,
+static void city_dialog_update_information(GtkWidget **info_ebox,
+                                          GtkWidget **info_label,
                                            struct city_dialog *pdialog);
 static void city_dialog_update_map(struct city_dialog *pdialog);
 static void city_dialog_update_building(struct city_dialog *pdialog);
@@ -357,7 +362,8 @@
 
   city_dialog_update_title(pdialog);
   city_dialog_update_citizens(pdialog);
-  city_dialog_update_information(pdialog->overview.info_label, pdialog);
+  city_dialog_update_information(pdialog->overview.info_ebox,
+                                pdialog->overview.info_label, pdialog);
   city_dialog_update_map(pdialog);
   city_dialog_update_building(pdialog);
   city_dialog_update_improvement_list(pdialog);
@@ -372,7 +378,8 @@
 
     refresh_worklist(pdialog->production.worklist);
 
-    city_dialog_update_information(pdialog->happiness.info_label, pdialog);
+    city_dialog_update_information(pdialog->happiness.info_ebox,
+                                  pdialog->happiness.info_label, pdialog);
     refresh_happiness_dialog(pdialog->pcity);
 
     refresh_cma_dialog(pdialog->pcity, REFRESH_ALL);
@@ -482,14 +489,90 @@
   return FALSE;
 }
 
+/**************************************************************************
+...
+**************************************************************************/
+static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev,
+                                        gpointer data)
+{
+  gtk_grab_remove(w);
+  gdk_pointer_ungrab(GDK_CURRENT_TIME);
+  gtk_widget_destroy(w);
+  return FALSE;
+}
+
+enum { FIELD_FOOD, FIELD_SHIELD, FIELD_TRADE, FIELD_GOLD, FIELD_LUXURY,
+       FIELD_SCIENCE, FIELD_GRANARY, FIELD_GROWTH, FIELD_CORRUPTION,
+       FIELD_WASTE, FIELD_POLLUTION 
+};
+
+/****************************************************************
+...
+*****************************************************************/
+static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev,
+                               gpointer data)
+{
+  struct city_dialog *pdialog = g_object_get_data(G_OBJECT(w), "pdialog");
+
+  if (ev->button == 1) {
+    GtkWidget *p, *label;
+    char buf[1024];
+    
+    switch (GPOINTER_TO_UINT(data)) {
+    case FIELD_FOOD:
+      get_city_dialog_food_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    case FIELD_SHIELD:
+      get_city_dialog_shield_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    case FIELD_TRADE:
+      get_city_dialog_trade_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    case FIELD_GOLD:
+      get_city_dialog_gold_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    case FIELD_SCIENCE:
+      get_city_dialog_science_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    case FIELD_LUXURY:
+      get_city_dialog_luxury_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    case FIELD_POLLUTION:
+      get_city_dialog_pollution_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    default:
+      return TRUE;
+    }
+    
+    p = gtk_window_new(GTK_WINDOW_POPUP);
+    gtk_widget_set_name(p, "Freeciv");
+    gtk_container_set_border_width(GTK_CONTAINER(p), 4);
+    gtk_window_set_position(GTK_WINDOW(p), GTK_WIN_POS_MOUSE);
+
+    label = gtk_label_new(buf);
+    gtk_widget_set_name(label, "city info label");
+    gtk_container_add(GTK_CONTAINER(p), label);
+    gtk_widget_show_all(p);
+
+    gdk_pointer_grab(p->window, TRUE, GDK_BUTTON_RELEASE_MASK,
+                    NULL, NULL, ev->time);
+    gtk_grab_add(p);
+
+    g_signal_connect_after(p, "button_release_event",
+                           G_CALLBACK(show_info_button_release), NULL);
+  }
+  return TRUE;
+}
 /****************************************************************
  used once in the overview page and once in the happiness page
  **info_label points to the info_label in the respective struct
 ****************************************************************/
-static GtkWidget *create_city_info_table(GtkWidget **info_label)
+static GtkWidget *create_city_info_table(struct city_dialog *pdialog,
+                                        GtkWidget **info_ebox,
+                                        GtkWidget **info_label)
 {
   int i;
-  GtkWidget *hbox, *table, *label;
+  GtkWidget *hbox, *table, *label, *ebox;
 
   static const char *output_label[NUM_INFO_FIELDS] = { N_("Food:"),
     N_("Prod:"),
@@ -523,12 +606,20 @@
     gtk_table_attach(GTK_TABLE(table), label, 0, 1, i, i + 1, GTK_FILL, 0,
                     0, 0);
 
+    ebox = gtk_event_box_new();
+    g_object_set_data(G_OBJECT(ebox), "pdialog", pdialog);
+    g_signal_connect(ebox, "button_press_event",
+       G_CALLBACK(show_info_popup), GUINT_TO_POINTER(i));
+    info_ebox[i] = ebox;
+
     label = gtk_label_new("");
     info_label[i] = label;
     gtk_widget_set_name(label, "city label");  /* ditto */
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-    gtk_table_attach(GTK_TABLE(table), label, 1, 2, i, i + 1, GTK_FILL, 0,
+    gtk_container_add(GTK_CONTAINER(ebox), label);
+
+    gtk_table_attach(GTK_TABLE(table), ebox, 1, 2, i, i + 1, GTK_FILL, 0,
                     0, 0);
   }
 
@@ -577,7 +668,9 @@
   frame = gtk_frame_new(_("Info"));
   gtk_box_pack_start(GTK_BOX(top), frame, FALSE, FALSE, 0);
 
-  table = create_city_info_table(pdialog->overview.info_label);
+  table = create_city_info_table(pdialog,
+                                pdialog->overview.info_ebox,
+                                pdialog->overview.info_label);
   gtk_container_add(GTK_CONTAINER(frame), table);
 
   frame = gtk_frame_new(_("City map"));
@@ -864,7 +957,9 @@
   align = gtk_alignment_new(0.5, 0.5, 0, 0);
   gtk_container_add(GTK_CONTAINER(vbox), align);
   
-  table = create_city_info_table(pdialog->happiness.info_label);
+  table = create_city_info_table(pdialog,
+                                pdialog->happiness.info_ebox,
+                                pdialog->happiness.info_label);
   gtk_container_add(GTK_CONTAINER(align), table);
 
   gtk_widget_show_all(page);
@@ -1072,6 +1167,9 @@
   }
 }
 
+
+
+
 /****************************************************************
 ...
 *****************************************************************/
@@ -1299,54 +1397,52 @@
 /****************************************************************
 ...
 *****************************************************************/
-static void city_dialog_update_information(GtkWidget **info_label,
+static void city_dialog_update_information(GtkWidget **info_ebox,
+                                          GtkWidget **info_label,
                                            struct city_dialog *pdialog)
 {
   int i, style;
   char buf[NUM_INFO_FIELDS][512];
   struct city *pcity = pdialog->pcity;
   int granaryturns;
-  enum { FOOD, SHIELD, TRADE, GOLD, LUXURY, SCIENCE, 
-        GRANARY, GROWTH, CORRUPTION, WASTE, POLLUTION 
-  };
 
   /* fill the buffers with the necessary info */
 
-  my_snprintf(buf[FOOD], sizeof(buf[FOOD]), "%2d (%+2d)",
+  my_snprintf(buf[FIELD_FOOD], sizeof(buf[FIELD_FOOD]), "%2d (%+2d)",
              pcity->food_prod, pcity->food_surplus);
-  my_snprintf(buf[SHIELD], sizeof(buf[SHIELD]), "%2d (%+2d)",
+  my_snprintf(buf[FIELD_SHIELD], sizeof(buf[FIELD_SHIELD]), "%2d (%+2d)",
              pcity->shield_prod + pcity->shield_waste,
              pcity->shield_surplus);
-  my_snprintf(buf[TRADE], sizeof(buf[TRADE]), "%2d (%+2d)",
+  my_snprintf(buf[FIELD_TRADE], sizeof(buf[FIELD_TRADE]), "%2d (%+2d)",
              pcity->trade_prod + pcity->corruption, pcity->trade_prod);
-  my_snprintf(buf[GOLD], sizeof(buf[GOLD]), "%2d (%+2d)",
+  my_snprintf(buf[FIELD_GOLD], sizeof(buf[FIELD_GOLD]), "%2d (%+2d)",
              pcity->tax_total, city_gold_surplus(pcity, pcity->tax_total));
-  my_snprintf(buf[LUXURY], sizeof(buf[LUXURY]), "%2d      ",
+  my_snprintf(buf[FIELD_LUXURY], sizeof(buf[FIELD_LUXURY]), "%2d      ",
              pcity->luxury_total);
 
-  my_snprintf(buf[SCIENCE], sizeof(buf[SCIENCE]), "%2d",
+  my_snprintf(buf[FIELD_SCIENCE], sizeof(buf[FIELD_SCIENCE]), "%2d",
              pcity->science_total);
 
-  my_snprintf(buf[GRANARY], sizeof(buf[GRANARY]), "%d/%-d",
+  my_snprintf(buf[FIELD_GRANARY], sizeof(buf[FIELD_GRANARY]), "%d/%-d",
              pcity->food_stock, city_granary_size(pcity->size));
-       
+
   granaryturns = city_turns_to_grow(pcity);
   if (granaryturns == 0) {
-    my_snprintf(buf[GROWTH], sizeof(buf[GROWTH]), _("blocked"));
+    my_snprintf(buf[FIELD_GROWTH], sizeof(buf[FIELD_GROWTH]), _("blocked"));
   } else if (granaryturns == FC_INFINITY) {
-    my_snprintf(buf[GROWTH], sizeof(buf[GROWTH]), _("never"));
+    my_snprintf(buf[FIELD_GROWTH], sizeof(buf[FIELD_GROWTH]), _("never"));
   } else {
     /* A negative value means we'll have famine in that many turns.
        But that's handled down below. */
-    my_snprintf(buf[GROWTH], sizeof(buf[GROWTH]),
+    my_snprintf(buf[FIELD_GROWTH], sizeof(buf[FIELD_GROWTH]),
                PL_("%d turn", "%d turns", abs(granaryturns)),
                abs(granaryturns));
   }
-  my_snprintf(buf[CORRUPTION], sizeof(buf[CORRUPTION]), "%2d",
+  my_snprintf(buf[FIELD_CORRUPTION], sizeof(buf[FIELD_CORRUPTION]), "%2d",
              pcity->corruption);
-  my_snprintf(buf[WASTE], sizeof(buf[WASTE]), "%2d",
+  my_snprintf(buf[FIELD_WASTE], sizeof(buf[FIELD_WASTE]), "%2d",
           pcity->shield_waste);
-  my_snprintf(buf[POLLUTION], sizeof(buf[POLLUTION]), "%2d",
+  my_snprintf(buf[FIELD_POLLUTION], sizeof(buf[FIELD_POLLUTION]), "%2d",
              pcity->pollution);
 
   /* stick 'em in the labels */
@@ -1360,16 +1456,17 @@
    * "4" below is arbitrary. 3 turns should be enough of a warning.
    */
   style = (granaryturns > -4 && granaryturns < 0) ? RED : NORMAL;
-  gtk_widget_modify_style(info_label[GRANARY], info_label_style[style]);
+  gtk_widget_modify_style(info_label[FIELD_GRANARY], info_label_style[style]);
 
   style = (granaryturns == 0 || pcity->food_surplus < 0) ? RED : NORMAL;
-  gtk_widget_modify_style(info_label[GROWTH], info_label_style[style]);
+  gtk_widget_modify_style(info_label[FIELD_GROWTH], info_label_style[style]);
 
   /* someone could add the info_label_style[ORANGE]
    * style for better granularity here */
 
   style = (pcity->pollution >= 10) ? RED : NORMAL;
-  gtk_widget_modify_style(info_label[POLLUTION], info_label_style[style]);
+  gtk_widget_modify_style(info_label[FIELD_POLLUTION],
+                         info_label_style[style]);
 }
 
 /****************************************************************
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.252
diff -u -r1.252 city.c
--- common/city.c       19 Oct 2004 06:46:57 -0000      1.252
+++ common/city.c       22 Oct 2004 03:45:55 -0000
@@ -1908,30 +1908,47 @@
 }
 
 /**************************************************************************
-  Calculate pollution for the city.  The shield_total must be passed in
-  (most callers will want to pass pcity->shield_prod).
+  Calculate the pollution from production and population in the city.
 **************************************************************************/
-int city_pollution(struct city *pcity, int shield_total)
+int city_pollution_types(const struct city *pcity, int shield_total,
+                        int *pollu_prod, int *pollu_pop, int *pollu_mod)
 {
   struct player *pplayer = city_owner(pcity);
-  int mod, pollution;
+  int prod, pop, mod;
 
   /* Add one one pollution per shield, multipled by the bonus. */
   mod = 100 + get_city_bonus(pcity, EFT_POLLU_PROD_PCT);
   mod = MAX(0, mod);
-  pollution = shield_total * mod / 100;
+  prod = shield_total * mod / 100;
 
   /* Add one 1/4 pollution per citizen per tech, multiplied by the bonus. */
   mod = 100 + get_city_bonus(pcity, EFT_POLLU_POP_PCT);
   mod = MAX(0, mod);
-  pollution += (pcity->size
-               * num_known_tech_with_flag(pplayer,
-                                          TF_POPULATION_POLLUTION_INC)
-               * mod) / (4 * 100);
+  pop = (pcity->size
+        * num_known_tech_with_flag(pplayer, TF_POPULATION_POLLUTION_INC)
+        * mod) / (4 * 100);
 
-  pollution = MAX(0, pollution - 20);
+  mod = -20;
 
-  return pollution;
+  if (pollu_prod) {
+    *pollu_prod = prod;
+  }
+  if (pollu_pop) {
+    *pollu_pop = pop;
+  }
+  if (pollu_mod) {
+    *pollu_mod = -20;
+  }
+  return MAX(prod + pop + mod, 0);
+}
+
+/**************************************************************************
+  Calculate pollution for the city.  The shield_total must be passed in
+  (most callers will want to pass pcity->shield_prod).
+**************************************************************************/
+int city_pollution(struct city *pcity, int shield_total)
+{
+  return city_pollution_types(pcity, shield_total, NULL, NULL, NULL);
 }
 
 /**************************************************************************
@@ -2038,6 +2055,10 @@
 
   /* loop over units, subtracting appropriate amounts of food, shields,
    * gold etc -- SKi */
+  pcity->food_upkeep = 0;
+  pcity->shield_upkeep = 0;
+  pcity->gold_unit_upkeep = 0;
+  pcity->gold_building_upkeep = 0;
   unit_list_iterate(pcity->units_supported, this_unit) {
     struct unit_type *ut = unit_type(this_unit);
     int shield_cost = utype_shield_cost(ut, g);
@@ -2086,6 +2107,7 @@
     if (shield_cost > 0) {
       adjust_city_free_cost(&free_shield, &shield_cost);
       if (shield_cost > 0) {
+       pcity->shield_upkeep += shield_cost;
        pcity->shield_surplus -= shield_cost;
        this_unit->upkeep = shield_cost;
       }
@@ -2093,6 +2115,7 @@
     if (food_cost > 0) {
       adjust_city_free_cost(&free_food, &food_cost);
       if (food_cost > 0) {
+       pcity->food_upkeep += food_cost;
        pcity->food_surplus -= food_cost;
        this_unit->upkeep_food = food_cost;
       }
@@ -2102,6 +2125,7 @@
       if (gold_cost > 0) {
        /* FIXME: This is not implemented -- SKi */
        this_unit->upkeep_gold = gold_cost;
+       pcity->gold_unit_upkeep += gold_cost;
       }
     }
 
@@ -2115,6 +2139,10 @@
     }
   }
   unit_list_iterate_end;
+
+  built_impr_iterate(pcity, i) {
+    pcity->gold_building_upkeep += improvement_upkeep(pcity, i);
+  } built_impr_iterate_end;
 }
 
 /**************************************************************************
@@ -2391,7 +2419,8 @@
   int i;
   struct city *pcity;
 
-  pcity = fc_malloc(sizeof(struct city));
+  pcity = fc_malloc(sizeof(*pcity));
+  memset(pcity, 0, sizeof(*pcity));
 
   pcity->id = 0;
   pcity->owner = pplayer->player_no;
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.165
diff -u -r1.165 city.h
--- common/city.h       20 Oct 2004 18:20:53 -0000      1.165
+++ common/city.h       22 Oct 2004 03:45:55 -0000
@@ -243,6 +243,9 @@
   int shield_prod, shield_surplus, shield_waste; 
   int trade_prod, corruption, tile_trade;
 
+  /* Upkeeps (gold upkeep is done globally, not per-city). */
+  int food_upkeep, shield_upkeep, gold_unit_upkeep, gold_building_upkeep;
+
   /* Cached values for CPU savings. */
   int shield_bonus, luxury_bonus, tax_bonus, science_bonus;
 
@@ -522,6 +525,8 @@
 void get_tax_income(struct player *pplayer, int trade, int *sci,
                     int *lux, int *tax);
 int get_city_tithes_bonus(const struct city *pcity);
+int city_pollution_types(const struct city *pcity, int shield_total,
+                        int *pollu_prod, int *pollu_pop, int *pollu_mod);
 int city_pollution(struct city *pcity, int shield_total);
 
 /*
Index: common/effects.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/effects.c,v
retrieving revision 1.14
diff -u -r1.14 effects.c
--- common/effects.c    10 Oct 2004 21:14:11 -0000      1.14
+++ common/effects.c    22 Oct 2004 03:45:55 -0000
@@ -1149,13 +1149,13 @@
   source gives the source type of the effect
   effect_type gives the effect type to be considered
 **************************************************************************/
-static int get_effect_value(enum target_type target,
-                           const struct player *target_player,
-                           const struct city *target_city,
-                           Impr_Type_id target_building,
-                           const struct tile *target_tile,
-                           Impr_Type_id source,
-                           enum effect_type effect_type)
+int get_effect_value(enum target_type target,
+                    const struct player *target_player,
+                    const struct city *target_city,
+                    Impr_Type_id target_building,
+                    const struct tile *target_tile,
+                    Impr_Type_id source,
+                    enum effect_type effect_type)
 {
   int value = 0;
 
@@ -1249,20 +1249,24 @@
   The returned vector must be freed (building_vector_free) when the caller
   is done with it.
 **************************************************************************/
-struct building_vector get_city_bonus_sources(const struct city *pcity,
-                                             enum effect_type effect_type)
+struct effect_source_vector get_city_bonus_sources(const struct city *pcity,
+                                                enum effect_type effect_type)
 {
   struct player *pplayer = city_owner(pcity);
-  struct building_vector sources;
+  struct effect_source_vector sources;
 
-  building_vector_init(&sources);
+  effect_source_vector_init(&sources);
 
   building_vector_iterate(get_buildings_with_effect(effect_type), pbldg) {
-    if (get_effect_value(TARGET_CITY, pplayer, pcity,
-                        B_LAST, NULL, *pbldg, effect_type) > 0) {
-      building_vector_append(&sources, pbldg);
+    struct effect_source e;
+
+    e.building = *pbldg;
+    e.effect_value = get_effect_value(TARGET_CITY, pplayer, pcity,
+                                     B_LAST, NULL, *pbldg, effect_type);
+    if (e.effect_value != 0) {
+      effect_source_vector_append(&sources, &e);
     }
-  } building_vector_iterate_end;
+  } effect_source_vector_iterate_end;
 
   return sources;
 }
Index: common/effects.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/effects.h,v
retrieving revision 1.9
diff -u -r1.9 effects.h
--- common/effects.h    22 Sep 2004 15:42:28 -0000      1.9
+++ common/effects.h    22 Oct 2004 03:45:55 -0000
@@ -199,6 +199,17 @@
   TYPED_LIST_ITERATE(struct effect, effect_list, peffect)
 #define effect_list_iterate_end LIST_ITERATE_END
 
+struct effect_source {
+  Impr_Type_id building;
+  int effect_value;
+};
+#define SPECVEC_TAG effect_source
+#define SPECVEC_TYPE struct effect_source
+#include "specvec.h"
+#define effect_source_vector_iterate(vector, psource) \
+  TYPED_VECTOR_ITERATE(struct effect_source, vector, psource)
+#define effect_source_vector_iterate_end VECTOR_ITERATE_END
+
 /* ruleset cache creation and communication functions */
 void ruleset_cache_init(void);
 void ruleset_cache_free(void);
@@ -239,6 +250,13 @@
                      Impr_Type_id target_building,
                      const struct tile *target_tile,
                      Impr_Type_id source, const struct effect *effect);
+int get_effect_value(enum target_type target,
+                    const struct player *target_player,
+                    const struct city *target_city,
+                    Impr_Type_id target_building,
+                    const struct tile *target_tile,
+                    Impr_Type_id source,
+                    enum effect_type effect_type);
 
 bool is_building_replaced(const struct city *pcity, Impr_Type_id building);
 
@@ -255,8 +273,8 @@
                                         enum effect_type effect_type);
 struct effect_type_vector *get_building_effect_types(Impr_Type_id building);
 
-struct building_vector get_city_bonus_sources(const struct city *pcity,
-                                             enum effect_type effect_type);
+struct effect_source_vector get_city_bonus_sources(const struct city *pcity,
+                                       enum effect_type effect_type);
 
 bool building_has_effect(Impr_Type_id building,
                         enum effect_type effect_type);
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.57
diff -u -r1.57 packets.def
--- common/packets.def  21 Oct 2004 20:27:28 -0000      1.57
+++ common/packets.def  22 Oct 2004 03:45:56 -0000
@@ -398,6 +398,7 @@
   UINT8 specialists[SP_COUNT];
 
   UINT16 food_prod, shield_prod, trade_prod;
+  UINT16 food_upkeep, shield_upkeep, gold_unit_upkeep, gold_building_upkeep;
   SINT16 food_surplus, shield_surplus, tile_trade;
   UINT16 food_stock, shield_stock, corruption;
 
Index: data/freeciv.rc-2.0
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/freeciv.rc-2.0,v
retrieving revision 1.20
diff -u -r1.20 freeciv.rc-2.0
--- data/freeciv.rc-2.0 18 Oct 2004 23:49:27 -0000      1.20
+++ data/freeciv.rc-2.0 22 Oct 2004 03:45:56 -0000
@@ -1,3 +1,8 @@
+style "city_info_label"
+{
+  font_name = "Monospace 8"
+}
+
 style "city_label"
 {
   font_name = "Monospace 8"
@@ -75,6 +80,7 @@
   font_name = "Serif 10"
 }
 
+widget "Freeciv*.city info label"      style   "city_info_label"
 widget "Freeciv*.city label"           style   "city_label"
 widget "Freeciv*.notify label"         style   "notify_label"
 widget "Freeciv*.spaceship label"      style   "spaceship_label"
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.277
diff -u -r1.277 citytools.c
--- server/citytools.c  19 Oct 2004 06:46:57 -0000      1.277
+++ server/citytools.c  22 Oct 2004 03:45:56 -0000
@@ -1588,7 +1588,12 @@
   packet->trade_prod=pcity->trade_prod;
   packet->tile_trade=pcity->tile_trade;
   packet->corruption=pcity->corruption;
-  
+
+  packet->food_upkeep = pcity->food_upkeep;
+  packet->shield_upkeep = pcity->shield_upkeep;
+  packet->gold_unit_upkeep = pcity->gold_unit_upkeep;
+  packet->gold_building_upkeep = pcity->gold_building_upkeep;
+
   packet->shield_waste=pcity->shield_waste;
     
   packet->luxury_total=pcity->luxury_total;

[Prev in Thread] Current Thread [Next in Thread]