1 /***********************************************************************
2  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ***********************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17 
18 /* SDL2 */
19 #ifdef SDL2_PLAIN_INCLUDE
20 #include <SDL.h>
21 #else  /* SDL2_PLAIN_INCLUDE */
22 #include <SDL2/SDL.h>
23 #endif /* SDL2_PLAIN_INCLUDE */
24 
25 /* utility */
26 #include "fcintl.h"
27 #include "log.h"
28 
29 /* common */
30 #include "game.h"
31 
32 /* client */
33 #include "client_main.h"
34 
35 /* gui-sdl2 */
36 #include "citydlg.h"
37 #include "cma_fe.h"
38 #include "colors.h"
39 #include "graphics.h"
40 #include "gui_id.h"
41 #include "gui_main.h"
42 #include "gui_tilespec.h"
43 #include "mapctrl.h"
44 #include "mapview.h"
45 #include "repodlgs.h"
46 #include "sprite.h"
47 #include "themespec.h"
48 #include "widget.h"
49 #include "wldlg.h"
50 
51 #include "cityrep.h"
52 
53 static struct ADVANCED_DLG *pCityRep = NULL;
54 
55 static void real_info_city_report_dialog_update(void);
56 
57 /* ==================================================================== */
58 
59 /**************************************************************************
60   Close city report dialog.
61 **************************************************************************/
city_report_dialog_popdown(void)62 void city_report_dialog_popdown(void)
63 {
64   if (pCityRep) {
65     popdown_window_group_dialog(pCityRep->pBeginWidgetList,
66                                 pCityRep->pEndWidgetList);
67     FC_FREE(pCityRep->pScroll);
68     FC_FREE(pCityRep);
69 
70     enable_and_redraw_find_city_button();
71     flush_dirty();
72   }
73 }
74 
75 /**************************************************************************
76   User interacted with cityreport window.
77 **************************************************************************/
city_report_windows_callback(struct widget * pWindow)78 static int city_report_windows_callback(struct widget *pWindow)
79 {
80   if (PRESSED_EVENT(Main.event)) {
81     move_window_group(pCityRep->pBeginWidgetList, pWindow);
82   }
83 
84   return -1;
85 }
86 
87 /**************************************************************************
88   User interacted with city report close button.
89 **************************************************************************/
exit_city_report_callback(struct widget * pWidget)90 static int exit_city_report_callback(struct widget *pWidget)
91 {
92   if (PRESSED_EVENT(Main.event)) {
93     city_report_dialog_popdown();
94   }
95 
96   return -1;
97 }
98 
99 /**************************************************************************
100   User interacted with city button on city report.
101 **************************************************************************/
popup_citydlg_from_city_report_callback(struct widget * pWidget)102 static int popup_citydlg_from_city_report_callback(struct widget *pWidget)
103 {
104   if (PRESSED_EVENT(Main.event)) {
105     popup_city_dialog(pWidget->data.city);
106   }
107 
108   return -1;
109 }
110 
111 /**************************************************************************
112   User interacted with worklist button on city report.
113 **************************************************************************/
popup_worklist_from_city_report_callback(struct widget * pWidget)114 static int popup_worklist_from_city_report_callback(struct widget *pWidget)
115 {
116   if (PRESSED_EVENT(Main.event)) {
117     popup_worklist_editor(pWidget->data.city, NULL);
118   }
119 
120   return -1;
121 }
122 
123 /**************************************************************************
124   User interacted with city production button on city report.
125 **************************************************************************/
popup_buy_production_from_city_report_callback(struct widget * pWidget)126 static int popup_buy_production_from_city_report_callback(struct widget *pWidget)
127 {
128   if (PRESSED_EVENT(Main.event)) {
129     popup_hurry_production_dialog(pWidget->data.city, NULL);
130   }
131 
132   return -1;
133 }
134 
135 /**************************************************************************
136   User interacted with cma button on city report.
137 **************************************************************************/
popup_cma_from_city_report_callback(struct widget * pWidget)138 static int popup_cma_from_city_report_callback(struct widget *pWidget)
139 {
140   if (PRESSED_EVENT(Main.event)) {
141     struct city *pCity = game_city_by_number(MAX_ID - pWidget->ID);
142 
143     /* state is changed before enter this function */
144     if (!get_checkbox_state(pWidget)) {
145       cma_release_city(pCity);
146       city_report_dialog_update_city(pCity);
147     } else {
148       popup_city_cma_dialog(pCity);
149     }
150   }
151 
152   return -1;
153 }
154 
155 #if 0
156 /**************************************************************************
157   User interacted with information report button.
158 **************************************************************************/
159 static int info_city_report_callback(struct widget *pWidget)
160 {
161   if (PRESSED_EVENT(Main.event)) {
162     set_wstate(pWidget, FC_WS_NORMAL);
163     selected_widget = NULL;
164     widget_redraw(pWidget);
165     widget_mark_dirty(pWidget);
166     real_info_city_report_dialog_update();
167   }
168 
169   return -1;
170 }
171 #endif /* 0 */
172 
173 #define COL	17
174 
175 /**************************************************************************
176   Rebuild the city info report.
177 **************************************************************************/
real_info_city_report_dialog_update(void)178 static void real_info_city_report_dialog_update(void)
179 {
180   SDL_Color bg_color = {255, 255, 255, 136};
181 
182   struct widget *pbuf = NULL;
183   struct widget *pWindow, *pLast;
184   utf8_str *pstr;
185   SDL_Surface *pText1, *pText2, *pText3, *pUnits_Icon, *pCMA_Icon, *pText4;
186   SDL_Surface *pLogo;
187   int togrow, w = 0 , count, ww = 0, hh = 0, name_w = 0, prod_w = 0, H;
188   char cbuf[128];
189   const char *pName;
190   SDL_Rect dst;
191   SDL_Rect area;
192 
193   if (pCityRep) {
194     popdown_window_group_dialog(pCityRep->pBeginWidgetList,
195                                 pCityRep->pEndWidgetList);
196   } else {
197     pCityRep = fc_calloc(1, sizeof(struct ADVANCED_DLG));
198   }
199 
200   fc_snprintf(cbuf, sizeof(cbuf), _("size"));
201   pstr = create_utf8_from_char(cbuf, adj_font(10));
202   pstr->style |= SF_CENTER;
203   pText1 = create_text_surf_from_utf8(pstr);
204 
205   fc_snprintf(cbuf, sizeof(cbuf), _("time\nto grow"));
206   copy_chars_to_utf8_str(pstr, cbuf);
207   pText2 = create_text_surf_from_utf8(pstr);
208 
209   fc_snprintf(cbuf, sizeof(cbuf), _("City Name"));
210   copy_chars_to_utf8_str(pstr, cbuf);
211   pText3 = create_text_surf_from_utf8(pstr);
212   name_w = pText3->w + adj_size(6);
213 
214   fc_snprintf(cbuf, sizeof(cbuf), _("Production"));
215   copy_chars_to_utf8_str(pstr, cbuf);
216   pstr->fgcol = *get_theme_color(COLOR_THEME_CITYREP_TEXT);
217   pText4 = create_text_surf_from_utf8(pstr);
218   prod_w = pText4->w;
219   FREEUTF8STR(pstr);
220 
221   pUnits_Icon = create_icon_from_theme(current_theme->UNITS_Icon, 0);
222   pCMA_Icon = create_icon_from_theme(current_theme->CMA_Icon, 0);
223 
224   /* --------------- */
225   pstr = create_utf8_from_char(_("Cities Report"), adj_font(12));
226   pstr->style |= TTF_STYLE_BOLD;
227 
228   pWindow = create_window_skeleton(NULL, pstr, 0);
229   pCityRep->pEndWidgetList = pWindow;
230   set_wstate(pWindow, FC_WS_NORMAL);
231   pWindow->action = city_report_windows_callback;
232 
233   add_to_gui_list(ID_WINDOW, pWindow);
234 
235   area = pWindow->area;
236 
237   /* ------------------------- */
238   /* exit button */
239   pbuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
240                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
241   pbuf->info_label = create_utf8_from_char(_("Close Dialog"), adj_font(12));
242   pbuf->action = exit_city_report_callback;
243   set_wstate(pbuf, FC_WS_NORMAL);
244   pbuf->key = SDLK_ESCAPE;
245 
246   add_to_gui_list(ID_BUTTON, pbuf);
247 
248 /* FIXME: not implemented yet */
249 #if 0
250   /* ------------------------- */
251   pbuf = create_themeicon(current_theme->INFO_Icon, pWindow->dst,
252                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
253   pbuf->info_label = create_str16_from_char(_("Information Report"),
254                                             adj_font(12));
255 /*
256   pbuf->action = info_city_report_callback;
257   set_wstate(pbuf, FC_WS_NORMAL);
258 */
259   add_to_gui_list(ID_BUTTON, pbuf);
260   /* -------- */
261   pbuf = create_themeicon(current_theme->Happy_Icon, pWindow->dst,
262                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
263   pbuf->info_label = create_str16_from_char(_("Happiness Report"), adj_font(12));
264 /*
265   pbuf->action = happy_city_report_callback;
266   set_wstate(pbuf, FC_WS_NORMAL);
267 */
268   add_to_gui_list(ID_BUTTON, pbuf);
269   /* -------- */
270   pbuf = create_themeicon(current_theme->Army_Icon, pWindow->dst,
271                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
272 
273   pbuf->info_label = create_str16_from_char(_("Garrison Report"),
274                                             adj_font(12));
275 /*
276   pbuf->action = army_city_dlg_callback;
277   set_wstate(pbuf, FC_WS_NORMAL);
278 */
279   add_to_gui_list(ID_BUTTON, pbuf);
280   /* -------- */
281   pbuf = create_themeicon(current_theme->Support_Icon, pWindow->dst,
282                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
283   pbuf->info_label = create_str16_from_char(_("Maintenance Report"),
284                                             adj_font(12));
285 /*
286   pbuf->action = supported_unit_city_dlg_callback;
287   set_wstate(pbuf, FC_WS_NORMAL);
288 */
289   add_to_gui_list(ID_BUTTON, pbuf);
290   /* ------------------------ */
291 #endif /* 0 */
292 
293   pLast = pbuf;
294   count = 0;
295   city_list_iterate(client.conn.playing->cities, pCity) {
296     pstr = create_utf8_from_char(city_name_get(pCity), adj_font(12));
297     pstr->style |= TTF_STYLE_BOLD;
298     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
299                             (WF_RESTORE_BACKGROUND | WF_SELECT_WITHOUT_BAR));
300 
301     if (city_unhappy(pCity)) {
302       pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
303     } else {
304       if (city_celebrating(pCity)) {
305         pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_CELEB);
306       } else {
307         if (city_happy(pCity)) {
308           pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_HAPPY);
309         }
310       }
311     }
312 
313     pbuf->action = popup_citydlg_from_city_report_callback;
314     set_wstate(pbuf, FC_WS_NORMAL);
315     pbuf->data.city = pCity;
316     if (count > 13 * COL) {
317       set_wflag(pbuf , WF_HIDDEN);
318     }
319     hh = pbuf->size.h;
320     name_w = MAX(pbuf->size.w, name_w);
321     add_to_gui_list(MAX_ID - pCity->id, pbuf);
322 
323     /* ----------- */
324     fc_snprintf(cbuf, sizeof(cbuf), "%d", city_size_get(pCity));
325     pstr = create_utf8_from_char(cbuf, adj_font(10));
326     pstr->style |= SF_CENTER;
327     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
328                             WF_RESTORE_BACKGROUND);
329     if (count > 13 * COL) {
330       set_wflag(pbuf, WF_HIDDEN);
331     }
332     hh = MAX(hh, pbuf->size.h);
333     pbuf->size.w = pText1->w + adj_size(8);
334     add_to_gui_list(MAX_ID - pCity->id, pbuf);
335 
336     /* ----------- */
337     pbuf = create_checkbox(pWindow->dst,
338                            cma_is_city_under_agent(pCity, NULL), WF_RESTORE_BACKGROUND);
339     if (count > 13 * COL) {
340       set_wflag(pbuf, WF_HIDDEN);
341     }
342     hh = MAX(hh, pbuf->size.h);
343     fc_assert(MAX_ID > pCity->id);
344     add_to_gui_list(MAX_ID - pCity->id, pbuf);
345     set_wstate(pbuf, FC_WS_NORMAL);
346     pbuf->action = popup_cma_from_city_report_callback;
347 
348     /* ----------- */
349     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->prod[O_FOOD] - pCity->surplus[O_FOOD]);
350     pstr = create_utf8_from_char(cbuf, adj_font(10));
351     pstr->style |= SF_CENTER;
352     pstr->fgcol = *get_game_color(COLOR_OVERVIEW_LAND);
353     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
354                             WF_RESTORE_BACKGROUND);
355     if (count > 13 * COL) {
356       set_wflag(pbuf, WF_HIDDEN);
357     }
358     hh = MAX(hh, pbuf->size.h);
359     pbuf->size.w = pIcons->pBIG_Food->w + adj_size(6);
360     add_to_gui_list(MAX_ID - pCity->id, pbuf);
361 
362     /* ----------- */
363     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_FOOD]);
364     pstr = create_utf8_from_char(cbuf, adj_font(10));
365     pstr->style |= SF_CENTER;
366     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOOD_SURPLUS);
367     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
368                             WF_RESTORE_BACKGROUND);
369     if (count > 13 * COL) {
370       set_wflag(pbuf, WF_HIDDEN);
371     }
372     hh = MAX(hh, pbuf->size.h);
373     pbuf->size.w = pIcons->pBIG_Food_Corr->w + adj_size(6);
374     add_to_gui_list(MAX_ID - pCity->id, pbuf);
375 
376     /* ----------- */
377     togrow = city_turns_to_grow(pCity);
378     switch (togrow) {
379     case 0:
380       fc_snprintf(cbuf, sizeof(cbuf), "#");
381       break;
382     case FC_INFINITY:
383       fc_snprintf(cbuf, sizeof(cbuf), "--");
384       break;
385     default:
386       fc_snprintf(cbuf, sizeof(cbuf), "%d", togrow);
387       break;
388     }
389 
390     pstr = create_utf8_from_char(cbuf, adj_font(10));
391     pstr->style |= SF_CENTER;
392     if (togrow < 0) {
393       pstr->fgcol.r = 255;
394     }
395     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
396                             WF_RESTORE_BACKGROUND);
397     if (count > 13 * COL) {
398       set_wflag(pbuf, WF_HIDDEN);
399     }
400     hh = MAX(hh, pbuf->size.h);
401     pbuf->size.w = pText2->w + adj_size(6);
402     add_to_gui_list(MAX_ID - pCity->id, pbuf);
403 
404     /* ----------- */
405     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_TRADE]);
406     pstr = create_utf8_from_char(cbuf, adj_font(10));
407     pstr->style |= SF_CENTER;
408     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
409     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
410                             WF_RESTORE_BACKGROUND);
411     if (count > 13 * COL) {
412       set_wflag(pbuf, WF_HIDDEN);
413     }
414     hh = MAX(hh, pbuf->size.h);
415     pbuf->size.w = pIcons->pBIG_Trade->w + adj_size(6);
416     add_to_gui_list(MAX_ID - pCity->id, pbuf);
417 
418     /* ----------- */
419     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->waste[O_TRADE]);
420     pstr = create_utf8_from_char(cbuf, adj_font(10));
421     pstr->style |= SF_CENTER;
422     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
423                             WF_RESTORE_BACKGROUND);
424     if (count > 13 * COL) {
425       set_wflag(pbuf, WF_HIDDEN);
426     }
427     hh = MAX(hh, pbuf->size.h);
428     pbuf->size.w = pIcons->pBIG_Trade_Corr->w + adj_size(6);
429     add_to_gui_list(MAX_ID - pCity->id, pbuf);
430 
431     /* ----------- */
432     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_GOLD]);
433     pstr = create_utf8_from_char(cbuf, adj_font(10));
434     pstr->style |= SF_CENTER;
435     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
436     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
437                             WF_RESTORE_BACKGROUND);
438     if (count > 13 * COL) {
439       set_wflag(pbuf, WF_HIDDEN);
440     }
441     hh = MAX(hh, pbuf->size.h);
442     pbuf->size.w = pIcons->pBIG_Coin->w + adj_size(6);
443     add_to_gui_list(MAX_ID - pCity->id, pbuf);
444 
445     /* ----------- */
446     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->prod[O_SCIENCE]);
447     pstr = create_utf8_from_char(cbuf, adj_font(10));
448     pstr->style |= SF_CENTER;
449     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SCIENCE);
450     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
451                             WF_RESTORE_BACKGROUND);
452     if (count > 13 * COL) {
453       set_wflag(pbuf, WF_HIDDEN);
454     }
455     hh = MAX(hh, pbuf->size.h);
456     pbuf->size.w = pIcons->pBIG_Colb->w + adj_size(6);
457     add_to_gui_list(MAX_ID - pCity->id, pbuf);
458 
459     /* ----------- */
460     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->prod[O_LUXURY]);
461     pstr = create_utf8_from_char(cbuf, adj_font(10));
462     pstr->style |= SF_CENTER;
463     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
464     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
465                             WF_RESTORE_BACKGROUND);
466     if (count > 13 * COL) {
467       set_wflag(pbuf, WF_HIDDEN);
468     }
469     hh = MAX(hh, pbuf->size.h);
470     pbuf->size.w = pIcons->pBIG_Luxury->w + adj_size(6);
471     add_to_gui_list(MAX_ID - pCity->id, pbuf);
472 
473     /* ----------- */
474     fc_snprintf(cbuf, sizeof(cbuf), "%d",
475                 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD]);
476     pstr = create_utf8_from_char(cbuf, adj_font(10));
477     pstr->style |= SF_CENTER;
478     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PROD);
479     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
480                             WF_RESTORE_BACKGROUND);
481     if (count > 13 * COL) {
482       set_wflag(pbuf, WF_HIDDEN);
483     }
484     hh = MAX(hh, pbuf->size.h);
485     pbuf->size.w = pIcons->pBIG_Shield->w + adj_size(6);
486     add_to_gui_list(MAX_ID - pCity->id, pbuf);
487 
488     /* ----------- */
489     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->waste[O_SHIELD]);
490     pstr = create_utf8_from_char(cbuf, adj_font(10));
491     pstr->style |= SF_CENTER;
492     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
493                             WF_RESTORE_BACKGROUND);
494     if (count > 13 * COL) {
495       set_wflag(pbuf, WF_HIDDEN);
496     }
497     hh = MAX(hh, pbuf->size.h);
498     pbuf->size.w = pIcons->pBIG_Shield_Corr->w + adj_size(6);
499     add_to_gui_list(MAX_ID - pCity->id, pbuf);
500 
501     /* ----------- */
502     fc_snprintf(cbuf, sizeof(cbuf), "%d",
503                 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD] - pCity->surplus[O_SHIELD]);
504     pstr = create_utf8_from_char(cbuf, adj_font(10));
505     pstr->style |= SF_CENTER;
506     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SUPPORT);
507     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
508                             WF_RESTORE_BACKGROUND);
509     if (count > 13 * COL) {
510       set_wflag(pbuf, WF_HIDDEN);
511     }
512     hh = MAX(hh, pbuf->size.h);
513     pbuf->size.w = pUnits_Icon->w + adj_size(6);
514     add_to_gui_list(MAX_ID - pCity->id, pbuf);
515 
516     /* ----------- */
517     fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_SHIELD]);
518     pstr = create_utf8_from_char(cbuf, adj_font(10));
519     pstr->style |= SF_CENTER;
520     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
521     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
522                             WF_RESTORE_BACKGROUND);
523     if (count > 13 * COL) {
524       set_wflag(pbuf, WF_HIDDEN);
525     }
526     hh = MAX(hh, pbuf->size.h);
527     pbuf->size.w = pIcons->pBIG_Shield_Surplus->w + adj_size(6);
528     add_to_gui_list(MAX_ID - pCity->id, pbuf);
529 
530     /* ----------- */
531     if (VUT_UTYPE == pCity->production.kind) {
532       struct unit_type *pUnitType = pCity->production.value.utype;
533 
534       pLogo = ResizeSurfaceBox(get_unittype_surface(pUnitType, direction8_invalid()),
535                                adj_size(36), adj_size(24), 1,
536                                TRUE, TRUE);
537       togrow = utype_build_shield_cost(pUnitType);
538       pName = utype_name_translation(pUnitType);
539     } else {
540       struct impr_type *pImprove = pCity->production.value.building;
541 
542       pLogo = ResizeSurfaceBox(get_building_surface(pCity->production.value.building),
543                                adj_size(36), adj_size(24), 1,
544                                TRUE, TRUE);
545       togrow = impr_build_shield_cost(pImprove);
546       pName = improvement_name_translation(pImprove);
547     }
548 
549     if (!worklist_is_empty(&(pCity->worklist))) {
550       dst.x = pLogo->w - pIcons->pWorklist->w;
551       dst.y = 0;
552       alphablit(pIcons->pWorklist, NULL, pLogo, &dst, 255);
553       fc_snprintf(cbuf, sizeof(cbuf), "%s\n(%d/%d)\n%s",
554                   pName, pCity->shield_stock, togrow, _("worklist"));
555     } else {
556       fc_snprintf(cbuf, sizeof(cbuf), "%s\n(%d/%d)%s",
557                   pName, pCity->shield_stock, togrow,
558                   pCity->shield_stock > togrow ? _("\nfinished"): "" );
559     }
560 
561     /* info string */
562     pstr = create_utf8_from_char(cbuf, adj_font(10));
563     pstr->style |= SF_CENTER;
564 
565     togrow = city_production_turns_to_build(pCity, TRUE);
566     if (togrow == 999) {
567       fc_snprintf(cbuf, sizeof(cbuf), "%s", _("never"));
568     } else {
569       fc_snprintf(cbuf, sizeof(cbuf), "%d %s",
570                   togrow, PL_("turn", "turns", togrow));
571     }
572 
573     pbuf = create_icon2(pLogo, pWindow->dst,
574                         WF_WIDGET_HAS_INFO_LABEL |WF_RESTORE_BACKGROUND
575                         | WF_FREE_THEME);
576     pbuf->info_label = pstr;
577     if (count > 13 * COL) {
578       set_wflag(pbuf, WF_HIDDEN);
579     }
580     hh = MAX(hh, pbuf->size.h);
581     add_to_gui_list(MAX_ID - pCity->id, pbuf);
582     set_wstate(pbuf, FC_WS_NORMAL);
583     pbuf->action = popup_worklist_from_city_report_callback;
584     pbuf->data.city = pCity;
585 
586     pstr = create_utf8_from_char(cbuf, adj_font(10));
587     pstr->style |= SF_CENTER;
588     pstr->fgcol = *get_theme_color(COLOR_THEME_CITYREP_TEXT);
589     pbuf = create_iconlabel(NULL, pWindow->dst, pstr,
590                             (WF_SELECT_WITHOUT_BAR | WF_RESTORE_BACKGROUND));
591     if (count > 13 * COL) {
592       set_wflag(pbuf, WF_HIDDEN);
593     }
594     hh = MAX(hh, pbuf->size.h);
595     prod_w = MAX(prod_w, pbuf->size.w);
596     add_to_gui_list(MAX_ID - pCity->id, pbuf);
597     pbuf->data.city = pCity;
598     pbuf->action = popup_buy_production_from_city_report_callback;
599     if (city_can_buy(pCity)) {
600       set_wstate(pbuf, FC_WS_NORMAL);
601     }
602 
603     count += COL;
604   } city_list_iterate_end;
605 
606   H = hh;
607   pCityRep->pBeginWidgetList = pbuf;
608   /* setup window width */
609   area.w = name_w + adj_size(6) + pText1->w + adj_size(8) + pCMA_Icon->w
610     + (pIcons->pBIG_Food->w + adj_size(6)) * 10 + pText2->w + adj_size(6)
611     + pUnits_Icon->w + adj_size(6) + prod_w + adj_size(170);
612 
613   if (count) {
614     pCityRep->pEndActiveWidgetList = pLast->prev;
615     pCityRep->pBeginActiveWidgetList = pCityRep->pBeginWidgetList;
616     if (count > 14 * COL) {
617       pCityRep->pActiveWidgetList = pCityRep->pEndActiveWidgetList;
618       if (pCityRep->pScroll) {
619 	pCityRep->pScroll->count = count;
620       }
621       ww = create_vertical_scrollbar(pCityRep, COL, 14, TRUE, TRUE);
622       area.w += ww;
623       area.h = 14 * (hh + adj_size(2));
624     } else {
625       area.h = (count / COL) * (hh + adj_size(2));
626     }
627   }
628 
629   area.h += pText2->h + adj_size(6);
630   area.w += adj_size(2);
631 
632   pLogo = theme_get_background(theme, BACKGROUND_CITYREP);
633   resize_window(pWindow, pLogo,	NULL,
634                 (pWindow->size.w - pWindow->area.w) + area.w,
635                 (pWindow->size.h - pWindow->area.h) + area.h);
636   FREESURFACE(pLogo);
637 
638 #if 0
639   pLogo = SDL_DisplayFormat(pWindow->theme);
640   FREESURFACE(pWindow->theme);
641   pWindow->theme = pLogo;
642   pLogo = NULL;
643 #endif
644 
645   area = pWindow->area;
646 
647   widget_set_position(pWindow,
648                       (main_window_width() - pWindow->size.w) / 2,
649                       (main_window_height() - pWindow->size.h) / 2);
650 
651   /* exit button */
652   pbuf = pWindow->prev;
653   pbuf->size.x = area.x + area.w - pbuf->size.w - 1;
654   pbuf->size.y = pWindow->size.y + adj_size(2);
655 
656 /* FIXME: not implemented yet */
657 #if 0
658   /* info button */
659   pbuf = pbuf->prev;
660   pbuf->size.x = area.x + area.w - pbuf->size.w - adj_size(5);
661   pbuf->size.y = area.y + area.h - pbuf->size.h - adj_size(5);
662 
663   /* happy button */
664   pbuf = pbuf->prev;
665   pbuf->size.x = pbuf->next->size.x - adj_size(5) - pbuf->size.w;
666   pbuf->size.y = pbuf->next->size.y;
667 
668   /* army button */
669   pbuf = pbuf->prev;
670   pbuf->size.x = pbuf->next->size.x - adj_size(5) - pbuf->size.w;
671   pbuf->size.y = pbuf->next->size.y;
672 
673   /* supported button */
674   pbuf = pbuf->prev;
675   pbuf->size.x = pbuf->next->size.x - adj_size(5) - pbuf->size.w;
676   pbuf->size.y = pbuf->next->size.y;
677 #endif /* 0 */
678 
679   /* cities background and labels */
680   dst.x = area.x + adj_size(2);
681   dst.y = area.y + 1;
682   dst.w = (name_w + adj_size(6)) + (pText1->w + adj_size(8)) + adj_size(5);
683   dst.h = area.h - adj_size(2);
684   fill_rect_alpha(pWindow->theme, &dst, &bg_color);
685 
686   create_frame(pWindow->theme,
687                dst.x , dst.y, dst.w, dst.h - 1,
688                get_theme_color(COLOR_THEME_CITYREP_FRAME));
689 
690   dst.y += (pText2->h - pText3->h) / 2;
691   dst.x += ((name_w + adj_size(6)) - pText3->w) / 2;
692   alphablit(pText3, NULL, pWindow->theme, &dst, 255);
693   FREESURFACE(pText3);
694 
695   /* city size background and label */
696   dst.x = area.x + adj_size(5) + name_w + adj_size(5 + 4);
697   alphablit(pText1, NULL, pWindow->theme, &dst, 255);
698   ww = pText1->w;
699   FREESURFACE(pText1);
700 
701   /* cma icon */
702   dst.x += (ww + adj_size(9));
703   dst.y = area.y + 1 + (pText2->h - pCMA_Icon->h) / 2;
704   alphablit(pCMA_Icon, NULL, pWindow->theme, &dst, 255);
705   ww = pCMA_Icon->w;
706   FREESURFACE(pCMA_Icon);
707 
708   /* -------------- */
709   /* populations food unkeep background and label */
710   dst.x += (ww + 1);
711   dst.y = area.y + 1;
712   w = dst.x + adj_size(2);
713   dst.w = (pIcons->pBIG_Food->w + adj_size(6)) + adj_size(10)
714     + (pIcons->pBIG_Food_Surplus->w + adj_size(6)) + adj_size(10)
715     + pText2->w + adj_size(6 + 2);
716   dst.h = area.h - adj_size(2);
717   fill_rect_alpha(pWindow->theme, &dst, get_theme_color(COLOR_THEME_CITYREP_FOODSTOCK));
718 
719   create_frame(pWindow->theme,
720                dst.x, dst.y, dst.w, dst.h - 1,
721                get_theme_color(COLOR_THEME_CITYREP_FRAME));
722 
723   dst.y = area.y + 1 + (pText2->h - pIcons->pBIG_Food->h) / 2;
724   dst.x += adj_size(5);
725   alphablit(pIcons->pBIG_Food, NULL, pWindow->theme, &dst, 255);
726 
727   /* food surplus Icon */
728   w += (pIcons->pBIG_Food->w + adj_size(6)) + adj_size(10);
729   dst.x = w + adj_size(3);
730   alphablit(pIcons->pBIG_Food_Surplus, NULL, pWindow->theme, &dst, 255);
731 
732   /* to grow label */
733   w += (pIcons->pBIG_Food_Surplus->w + adj_size(6)) + adj_size(10);
734   dst.x = w + adj_size(3);
735   dst.y = area.y + 1;
736   alphablit(pText2, NULL, pWindow->theme, &dst, 255);
737   hh = pText2->h;
738   ww = pText2->w;
739   FREESURFACE(pText2);
740   /* -------------- */
741 
742   /* trade, corruptions, gold, science, luxury income background and label */
743   dst.x = w + (ww + adj_size(8));
744   dst.y = area.y + 1;
745   w = dst.x + adj_size(2);
746   dst.w = (pIcons->pBIG_Trade->w + adj_size(6)) + adj_size(10) +
747 	  (pIcons->pBIG_Trade_Corr->w + adj_size(6)) + adj_size(10) +
748 	  (pIcons->pBIG_Coin->w + adj_size(6)) + adj_size(10) +
749 	  (pIcons->pBIG_Colb->w + adj_size(6)) + adj_size(10) +
750 	  (pIcons->pBIG_Luxury->w + adj_size(6)) + adj_size(4);
751   dst.h = area.h - adj_size(2);
752 
753   fill_rect_alpha(pWindow->theme, &dst, get_theme_color(COLOR_THEME_CITYREP_TRADE));
754 
755   create_frame(pWindow->theme,
756                dst.x , dst.y, dst.w, dst.h - 1,
757                get_theme_color(COLOR_THEME_CITYREP_FRAME));
758 
759   dst.y = area.y + 1 + (hh - pIcons->pBIG_Trade->h) / 2;
760   dst.x += adj_size(5);
761   alphablit(pIcons->pBIG_Trade, NULL, pWindow->theme, &dst, 255);
762 
763   w += (pIcons->pBIG_Trade->w + adj_size(6)) + adj_size(10);
764   dst.x = w + adj_size(3);
765   alphablit(pIcons->pBIG_Trade_Corr, NULL, pWindow->theme, &dst, 255);
766 
767   w += (pIcons->pBIG_Food_Corr->w + adj_size(6)) + adj_size(10);
768   dst.x = w + adj_size(3);
769   alphablit(pIcons->pBIG_Coin, NULL, pWindow->theme, &dst, 255);
770 
771   w += (pIcons->pBIG_Coin->w + adj_size(6)) + adj_size(10);
772   dst.x = w + adj_size(3);
773   alphablit(pIcons->pBIG_Colb, NULL, pWindow->theme, &dst, 255);
774 
775   w += (pIcons->pBIG_Colb->w + adj_size(6)) + adj_size(10);
776   dst.x = w + adj_size(3);
777   alphablit(pIcons->pBIG_Luxury, NULL, pWindow->theme, &dst, 255);
778   /* --------------------- */
779 
780   /* total productions, waste, support, shields surplus background and label */
781   w += (pIcons->pBIG_Luxury->w + adj_size(6)) + adj_size(4);
782   dst.x = w;
783   w += adj_size(2);
784   dst.y = area.y + 1;
785   dst.w = (pIcons->pBIG_Shield->w + adj_size(6)) + adj_size(10) +
786 	  (pIcons->pBIG_Shield_Corr->w + adj_size(6)) + adj_size(10) +
787 	  (pUnits_Icon->w + adj_size(6)) + adj_size(10) +
788 	  (pIcons->pBIG_Shield_Surplus->w + adj_size(6)) + adj_size(4);
789   dst.h = area.h - adj_size(2);
790 
791   fill_rect_alpha(pWindow->theme, &dst, get_theme_color(COLOR_THEME_CITYREP_PROD));
792 
793   create_frame(pWindow->theme,
794                dst.x , dst.y, dst.w, dst.h - 1,
795                get_theme_color(COLOR_THEME_CITYREP_FRAME));
796 
797   dst.y = area.y + 1 + (hh - pIcons->pBIG_Shield->h) / 2;
798   dst.x += adj_size(5);
799   alphablit(pIcons->pBIG_Shield, NULL, pWindow->theme, &dst, 255);
800 
801   w += (pIcons->pBIG_Shield->w + adj_size(6)) + adj_size(10);
802   dst.x = w + adj_size(3);
803   alphablit(pIcons->pBIG_Shield_Corr, NULL, pWindow->theme, &dst, 255);
804 
805   w += (pIcons->pBIG_Shield_Corr->w + adj_size(6)) + adj_size(10);
806   dst.x = w + adj_size(3);
807   dst.y = area.y + 1 + (hh - pUnits_Icon->h) / 2;
808   alphablit(pUnits_Icon, NULL, pWindow->theme, &dst, 255);
809 
810   w += (pUnits_Icon->w + adj_size(6)) + adj_size(10);
811   FREESURFACE(pUnits_Icon);
812   dst.x = w + adj_size(3);
813   dst.y = area.y + 1 + (hh - pIcons->pBIG_Shield_Surplus->h) / 2;
814   alphablit(pIcons->pBIG_Shield_Surplus, NULL, pWindow->theme, &dst, 255);
815   /* ------------------------------- */
816 
817   w += (pIcons->pBIG_Shield_Surplus->w + adj_size(6)) + adj_size(10);
818   dst.x = w;
819   w += adj_size(2);
820   dst.y = area.y + 1;
821   dst.w = adj_size(36) + adj_size(5) + prod_w;
822   dst.h = hh + adj_size(2);
823 
824   fill_rect_alpha(pWindow->theme, &dst, get_theme_color(COLOR_THEME_CITYREP_PROD));
825 
826   create_frame(pWindow->theme,
827                dst.x , dst.y, dst.w, dst.h - 1,
828                get_theme_color(COLOR_THEME_CITYREP_FRAME));
829 
830   dst.y = area.y + 1 + (hh - pText4->h) / 2;
831   dst.x += (dst.w - pText4->w) / 2;
832   alphablit(pText4, NULL, pWindow->theme, &dst, 255);
833   FREESURFACE(pText4);
834 
835   if (count) {
836     int start_x = area.x + adj_size(5);
837     int start_y = area.y + hh + adj_size(3);
838 
839     H += adj_size(2);
840     pbuf = pbuf->prev;
841     while (TRUE) {
842 
843       /* city name */
844       pbuf->size.x = start_x;
845       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
846       pbuf->size.w = name_w;
847 
848       /* city size */
849       pbuf = pbuf->prev;
850       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(5);
851       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
852 
853       /* cma */
854       pbuf = pbuf->prev;
855       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(6);
856       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
857 
858       /* food cons. */
859       pbuf = pbuf->prev;
860       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(6);
861       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
862 
863       /* food surplus */
864       pbuf = pbuf->prev;
865       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
866       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
867 
868       /* time to grow */
869       pbuf = pbuf->prev;
870       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
871       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
872 
873       /* trade */
874       pbuf = pbuf->prev;
875       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(5);
876       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
877 
878       /* trade corruptions */
879       pbuf = pbuf->prev;
880       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
881       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
882 
883       /* net gold income */
884       pbuf = pbuf->prev;
885       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
886       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
887 
888       /* science income */
889       pbuf = pbuf->prev;
890       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
891       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
892 
893       /* luxuries income */
894       pbuf = pbuf->prev;
895       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
896       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
897 
898       /* total production */
899       pbuf = pbuf->prev;
900       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(6);
901       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
902 
903       /* waste */
904       pbuf = pbuf->prev;
905       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
906       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
907 
908       /* units support */
909       pbuf = pbuf->prev;
910       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
911       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
912 
913       /* producrion surplus */
914       pbuf = pbuf->prev;
915       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
916       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
917 
918       /* currently build */
919       /* icon */
920       pbuf = pbuf->prev;
921       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(10);
922       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
923 
924       /* label */
925       pbuf = pbuf->prev;
926       pbuf->size.x = pbuf->next->size.x + pbuf->next->size.w + adj_size(5);
927       pbuf->size.y = start_y + (H - pbuf->size.h) / 2;
928       pbuf->size.w = prod_w;
929 
930       start_y += H;
931       if (pbuf == pCityRep->pBeginActiveWidgetList) {
932         break;
933       }
934       pbuf = pbuf->prev;
935     }
936 
937     if (pCityRep->pScroll) {
938       setup_vertical_scrollbar_area(pCityRep->pScroll,
939                                     area.x + area.w, area.y,
940                                     area.h, TRUE);
941     }
942 
943   }
944   /* ----------------------------------- */
945   redraw_group(pCityRep->pBeginWidgetList, pWindow, 0);
946   widget_mark_dirty(pWindow);
947   flush_dirty();
948 }
949 
950 /**************************************************************************
951   Update city information in city report.
952 **************************************************************************/
real_city_report_dialog_update_city(struct widget * pWidget,struct city * pCity)953 static struct widget *real_city_report_dialog_update_city(struct widget *pWidget,
954                                                           struct city *pCity)
955 {
956   char cbuf[64];
957   const char *pName;
958   int togrow;
959   SDL_Surface *pLogo;
960   SDL_Rect dst;
961 
962   /* city name status */
963   if (city_unhappy(pCity)) {
964     pWidget->string_utf8->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
965   } else {
966     if (city_celebrating(pCity)) {
967       pWidget->string_utf8->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_CELEB);
968     } else {
969       if (city_happy(pCity)) {
970 	pWidget->string_utf8->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_HAPPY);
971       }
972     }
973   }
974 
975   /* city size */
976   pWidget = pWidget->prev;
977   fc_snprintf(cbuf, sizeof(cbuf), "%d", city_size_get(pCity));
978   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
979 
980   /* cma check box */
981   pWidget = pWidget->prev;
982   if (cma_is_city_under_agent(pCity, NULL) != get_checkbox_state(pWidget)) {
983     toggle_checkbox(pWidget);
984   }
985 
986   /* food consumptions */
987   pWidget = pWidget->prev;
988   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->prod[O_FOOD] - pCity->surplus[O_FOOD]);
989   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
990 
991   /* food surplus */
992   pWidget = pWidget->prev;
993   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_FOOD]);
994   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
995 
996   /* time to grow */
997   pWidget = pWidget->prev;
998   togrow = city_turns_to_grow(pCity);
999   switch (togrow) {
1000     case 0:
1001       fc_snprintf(cbuf, sizeof(cbuf), "#");
1002     break;
1003     case FC_INFINITY:
1004       fc_snprintf(cbuf, sizeof(cbuf), "--");
1005     break;
1006     default:
1007       fc_snprintf(cbuf, sizeof(cbuf), "%d", togrow);
1008     break;
1009   }
1010   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1011 
1012   if (togrow < 0) {
1013     pWidget->string_utf8->fgcol.r = 255;
1014   } else {
1015     pWidget->string_utf8->fgcol.r = 0;
1016   }
1017 
1018   /* trade production */
1019   pWidget = pWidget->prev;
1020   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_TRADE]);
1021   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1022 
1023   /* corruptions */
1024   pWidget = pWidget->prev;
1025   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->waste[O_TRADE]);
1026   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1027 
1028   /* gold surplus */
1029   pWidget = pWidget->prev;
1030   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_GOLD]);
1031   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1032 
1033   /* science income */
1034   pWidget = pWidget->prev;
1035   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->prod[O_SCIENCE]);
1036   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1037 
1038   /* lugury income */
1039   pWidget = pWidget->prev;
1040   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->prod[O_LUXURY]);
1041   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1042 
1043   /* total production */
1044   pWidget = pWidget->prev;
1045   fc_snprintf(cbuf, sizeof(cbuf), "%d",
1046               pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD]);
1047   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1048 
1049   /* waste */
1050   pWidget = pWidget->prev;
1051   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->waste[O_SHIELD]);
1052   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1053 
1054   /* units support */
1055   pWidget = pWidget->prev;
1056   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->prod[O_SHIELD] +
1057               pCity->waste[O_SHIELD] - pCity->surplus[O_SHIELD]);
1058   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1059 
1060   /* production income */
1061   pWidget = pWidget->prev;
1062   fc_snprintf(cbuf, sizeof(cbuf), "%d", pCity->surplus[O_SHIELD]);
1063   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1064 
1065   /* change production */
1066   if (VUT_UTYPE == pCity->production.kind) {
1067     struct unit_type *pUnitType = pCity->production.value.utype;
1068 
1069     pLogo = ResizeSurface(get_unittype_surface(pUnitType, direction8_invalid()),
1070                           adj_size(36), adj_size(24), 1);
1071     togrow = utype_build_shield_cost(pUnitType);
1072     pName = utype_name_translation(pUnitType);
1073   } else {
1074     struct impr_type *pImprove = pCity->production.value.building;
1075 
1076     pLogo = ResizeSurface(get_building_surface(pCity->production.value.building),
1077                           adj_size(36), adj_size(24), 1);
1078     togrow = impr_build_shield_cost(pImprove);
1079     pName = improvement_name_translation(pImprove);
1080   }
1081 
1082   if (!worklist_is_empty(&(pCity->worklist))) {
1083     dst.x = pLogo->w - pIcons->pWorklist->w;
1084     dst.y = 0;
1085     alphablit(pIcons->pWorklist, NULL, pLogo, &dst, 255);
1086     fc_snprintf(cbuf, sizeof(cbuf), "%s\n(%d/%d)\n%s",
1087                 pName, pCity->shield_stock, togrow, _("worklist"));
1088   } else {
1089     fc_snprintf(cbuf, sizeof(cbuf), "%s\n(%d/%d)",
1090       		pName, pCity->shield_stock, togrow);
1091   }
1092 
1093   pWidget = pWidget->prev;
1094   copy_chars_to_utf8_str(pWidget->info_label, cbuf);
1095   FREESURFACE(pWidget->theme);
1096   pWidget->theme = pLogo;
1097 
1098   /* hurry productions */
1099   pWidget = pWidget->prev;
1100   togrow = city_production_turns_to_build(pCity, TRUE);
1101   if (togrow == 999) {
1102     fc_snprintf(cbuf, sizeof(cbuf), "%s", _("never"));
1103   } else {
1104     fc_snprintf(cbuf, sizeof(cbuf), "%d %s",
1105                 togrow, PL_("turn", "turns", togrow));
1106   }
1107 
1108   copy_chars_to_utf8_str(pWidget->string_utf8, cbuf);
1109 
1110   return pWidget->prev;
1111 }
1112 
1113 /* ======================================================================== */
1114 
1115 /**************************************************************************
1116   Check if city report is open.
1117 **************************************************************************/
is_city_report_open(void)1118 bool is_city_report_open(void)
1119 {
1120   return (pCityRep != NULL);
1121 }
1122 
1123 /**************************************************************************
1124   Pop up or brings forward the city report dialog.  It may or may not
1125   be modal.
1126 **************************************************************************/
city_report_dialog_popup(bool make_modal)1127 void city_report_dialog_popup(bool make_modal)
1128 {
1129   if (!pCityRep) {
1130     real_info_city_report_dialog_update();
1131   }
1132 }
1133 
1134 /**************************************************************************
1135   Update (refresh) the entire city report dialog.
1136 **************************************************************************/
real_city_report_dialog_update(void * unused)1137 void real_city_report_dialog_update(void *unused)
1138 {
1139   if (pCityRep) {
1140     struct widget *pWidget;
1141     int count;
1142 
1143     /* find if the lists are identical (if not then rebuild all) */
1144     pWidget = pCityRep->pEndActiveWidgetList;/* name of first city */
1145     city_list_iterate(client.conn.playing->cities, pCity) {
1146       if (pCity->id == MAX_ID - pWidget->ID) {
1147         count = COL;
1148 
1149         while (count) {
1150           count--;
1151           pWidget = pWidget->prev;
1152         }
1153       } else {
1154         real_info_city_report_dialog_update();
1155         return;
1156       }
1157     } city_list_iterate_end;
1158 
1159     /* check it there are some city widgets left on list */
1160     if (pWidget && pWidget->next != pCityRep->pBeginActiveWidgetList) {
1161       real_info_city_report_dialog_update();
1162       return;
1163     }
1164 
1165     /* update widget city list (widget list is the same that city list) */
1166     pWidget = pCityRep->pEndActiveWidgetList;
1167     city_list_iterate(client.conn.playing->cities, pCity) {
1168       pWidget = real_city_report_dialog_update_city(pWidget, pCity);
1169     } city_list_iterate_end;
1170 
1171     /* -------------------------------------- */
1172     redraw_group(pCityRep->pBeginWidgetList, pCityRep->pEndWidgetList, 0);
1173     widget_mark_dirty(pCityRep->pEndWidgetList);
1174 
1175     flush_dirty();
1176   }
1177 }
1178 
1179 /**************************************************************************
1180   Update the city report dialog for a single city.
1181 **************************************************************************/
real_city_report_update_city(struct city * pCity)1182 void real_city_report_update_city(struct city *pCity)
1183 {
1184   if (pCityRep && pCity) {
1185     struct widget *pBuf = pCityRep->pEndActiveWidgetList;
1186 
1187     while (pCity->id != MAX_ID - pBuf->ID
1188            && pBuf != pCityRep->pBeginActiveWidgetList) {
1189       pBuf = pBuf->prev;
1190     }
1191 
1192     if (pBuf == pCityRep->pBeginActiveWidgetList) {
1193       real_info_city_report_dialog_update();
1194       return;
1195     }
1196     real_city_report_dialog_update_city(pBuf, pCity);
1197 
1198     /* -------------------------------------- */
1199     redraw_group(pCityRep->pBeginWidgetList, pCityRep->pEndWidgetList, 0);
1200     widget_mark_dirty(pCityRep->pEndWidgetList);
1201 
1202     flush_dirty();
1203   }
1204 }
1205 
1206 /****************************************************************
1207  After a selection rectangle is defined, make the cities that
1208  are hilited on the canvas exclusively hilited in the
1209  City List window.
1210 *****************************************************************/
hilite_cities_from_canvas(void)1211 void hilite_cities_from_canvas(void)
1212 {
1213   log_debug("hilite_cities_from_canvas : PORT ME");
1214 }
1215 
1216 /****************************************************************
1217  Toggle a city's hilited status.
1218 *****************************************************************/
toggle_city_hilite(struct city * pCity,bool on_off)1219 void toggle_city_hilite(struct city *pCity, bool on_off)
1220 {
1221   log_debug("toggle_city_hilite : PORT ME");
1222 }
1223