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 /***********************************************************************
15                           citydlg.c  -  description
16                              -------------------
17     begin                : Wed Sep 04 2002
18     copyright            : (C) 2002 by Rafał Bursig
19     email                : Rafał Bursig <bursig@poczta.fm>
20 ***********************************************************************/
21 
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
25 
26 /* SDL */
27 #include <SDL/SDL.h>
28 
29 /* utility */
30 #include "bitvector.h"
31 #include "fcintl.h"
32 #include "log.h"
33 
34 /* common */
35 #include "game.h"
36 #include "movement.h"
37 #include "specialist.h"
38 #include "unitlist.h"
39 
40 /* client */
41 #include "client_main.h"
42 #include "climisc.h"
43 #include "control.h"
44 #include "text.h"
45 
46 /* gui-sdl */
47 #include "cityrep.h"
48 #include "cma_fe.h"
49 #include "colors.h"
50 #include "dialogs.h"
51 #include "graphics.h"
52 #include "gui_iconv.h"
53 #include "gui_id.h"
54 #include "gui_main.h"
55 #include "gui_tilespec.h"
56 #include "mapview.h"
57 #include "menu.h"
58 #include "sprite.h"
59 #include "themespec.h"
60 #include "widget.h"
61 #include "wldlg.h"
62 
63 #include "citydlg.h"
64 
65 /* ============================================================= */
66 
67 static struct city_dialog {
68   struct city *pCity;
69 
70   enum {
71     INFO_PAGE = 0,
72     HAPPINESS_PAGE = 1,
73     ARMY_PAGE,
74     SUPPORTED_UNITS_PAGE,
75     MISC_PAGE
76   } page;
77 
78   /* main window group list */
79   struct widget *pBeginCityWidgetList;
80   struct widget *pEndCityWidgetList;
81 
82   /* Imprvm. vscrollbar */
83   struct ADVANCED_DLG *pImprv;
84 
85   /* Penel group list */
86   struct ADVANCED_DLG *pPanel;
87 
88   /* Menu imprv. dlg. */
89   struct widget *pBeginCityMenuWidgetList;
90   struct widget *pEndCityMenuWidgetList;
91 
92   /* shortcuts */
93   struct widget *pAdd_Point;
94   struct widget *pBuy_Button;
95   struct widget *pResource_Map;
96   struct widget *pCity_Name_Edit;
97 
98   int citizen_step;
99 
100   SDL_Rect spec_area;
101 
102   bool lock;
103 } *pCityDlg = NULL;
104 
105 enum specialist_type {
106   SP_ELVIS, SP_SCIENTIST, SP_TAXMAN, SP_LAST
107 };
108 
109 static float city_map_zoom = 1;
110 
111 static struct SMALL_DLG *pHurry_Prod_Dlg = NULL;
112 
113 static void popdown_hurry_production_dialog(void);
114 static void disable_city_dlg_widgets(void);
115 static void redraw_city_dialog(struct city *pCity);
116 static void rebuild_imprm_list(struct city *pCity);
117 static void rebuild_citydlg_title_str(struct widget *pWindow, struct city *pCity);
118 
119 /* ======================================================================= */
120 
121 /**************************************************************************
122   Return first building that has given effect.
123 
124   FIXME: Some callers would work better if they got building actually
125          provides the effect at the moment, and not just first potential
126          one.
127 **************************************************************************/
get_building_for_effect(enum effect_type effect_type)128 struct impr_type *get_building_for_effect(enum effect_type effect_type)
129 {
130   improvement_iterate(pImprove) {
131     if (building_has_effect(pImprove, effect_type))
132       return pImprove;
133   } improvement_iterate_end;
134 
135   return NULL;
136 }
137 
138 /**************************************************************************
139   Destroy City Menu Dlg but not undraw.
140 **************************************************************************/
popdown_city_menu_dlg(bool enable_city_dialog_widgets)141 static void popdown_city_menu_dlg(bool enable_city_dialog_widgets)
142 {
143   if (pCityDlg->pEndCityMenuWidgetList) {
144     popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
145 				pCityDlg->pEndCityMenuWidgetList);
146     pCityDlg->pEndCityMenuWidgetList = NULL;
147   }
148   if (enable_city_dialog_widgets) {
149     /* enable city dlg */
150     enable_city_dlg_widgets();
151   }
152 }
153 
154 /**************************************************************************
155   Destroy City Dlg
156 **************************************************************************/
del_city_dialog(void)157 static void del_city_dialog(void)
158 {
159   if (pCityDlg) {
160 
161     if (pCityDlg->pImprv->pEndWidgetList) {
162       del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
163 					 pCityDlg->pImprv->pEndWidgetList);
164     }
165     FC_FREE(pCityDlg->pImprv->pScroll);
166     FC_FREE(pCityDlg->pImprv);
167 
168     if (pCityDlg->pPanel) {
169       del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
170 					 pCityDlg->pPanel->pEndWidgetList);
171       FC_FREE(pCityDlg->pPanel->pScroll);
172       FC_FREE(pCityDlg->pPanel);
173     }
174 
175     if (pHurry_Prod_Dlg)
176     {
177       del_group_of_widgets_from_gui_list(pHurry_Prod_Dlg->pBeginWidgetList,
178 			      		 pHurry_Prod_Dlg->pEndWidgetList);
179 
180       FC_FREE(pHurry_Prod_Dlg);
181     }
182 
183     free_city_units_lists();
184     popdown_city_menu_dlg(FALSE);
185 
186     popdown_window_group_dialog(pCityDlg->pBeginCityWidgetList,
187 				       pCityDlg->pEndCityWidgetList);
188     FC_FREE(pCityDlg);
189   }
190 }
191 
192 /**************************************************************************
193   Main City Dlg. window callback.
194   This implements specialist change ( Elvis, Taxman, Scientist )
195 **************************************************************************/
city_dlg_callback(struct widget * pWindow)196 static int city_dlg_callback(struct widget *pWindow)
197 {
198   if (Main.event.button.button == SDL_BUTTON_LEFT) {
199     if (!cma_is_city_under_agent(pCityDlg->pCity, NULL)
200        && city_owner(pCityDlg->pCity) == client.conn.playing) {
201 
202       if (is_in_rect_area(Main.event.motion.x, Main.event.motion.y,
203                           pCityDlg->spec_area)) {
204         city_rotate_specialist(pCityDlg->pCity,
205                                (Main.event.motion.x - pCityDlg->spec_area.x)
206                                / pCityDlg->citizen_step);
207 
208         return -1;
209       }
210     }
211 
212     if (!pCityDlg->lock) {
213       if (pCityDlg->pPanel) {
214         sellect_window_group_dialog(pCityDlg->pBeginCityWidgetList, pWindow);
215         sellect_window_group_dialog(pCityDlg->pPanel->pBeginWidgetList,
216                                     pCityDlg->pPanel->pEndWidgetList);
217         widget_flush(pWindow);
218       } else {
219         if (sellect_window_group_dialog(pCityDlg->pBeginCityWidgetList, pWindow)) {
220           widget_flush(pWindow);
221         }
222       }
223     }
224   }
225   return -1;
226 }
227 
228 /* ===================================================================== */
229 /* ========================== Units Orders Menu ======================== */
230 /* ===================================================================== */
231 
232 /**************************************************************************
233   Popdown unit city orders menu.
234 **************************************************************************/
cancel_units_orders_city_dlg_callback(struct widget * pButton)235 static int cancel_units_orders_city_dlg_callback(struct widget *pButton)
236 {
237   if (Main.event.button.button == SDL_BUTTON_LEFT) {
238     popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
239                                 pCityDlg->pEndCityMenuWidgetList);
240     pCityDlg->pEndCityMenuWidgetList = NULL;
241 
242     /* enable city dlg */
243     enable_city_dlg_widgets();
244     flush_dirty();
245   }
246   return -1;
247 }
248 
249 /**************************************************************************
250   activate unit and del unit order dlg. widget group.
251 **************************************************************************/
activate_units_orders_city_dlg_callback(struct widget * pButton)252 static int activate_units_orders_city_dlg_callback(struct widget *pButton)
253 {
254   if (Main.event.button.button == SDL_BUTTON_LEFT) {
255     struct unit *pUnit = pButton->data.unit;
256 
257     popdown_city_menu_dlg(TRUE);
258     if(pUnit) {
259       unit_focus_set(pUnit);
260     }
261   }
262   return -1;
263 }
264 
265 /**************************************************************************
266   activate unit and popdow city dlg. + center on unit.
267 **************************************************************************/
activate_and_exit_units_orders_city_dlg_callback(struct widget * pButton)268 static int activate_and_exit_units_orders_city_dlg_callback(struct widget *pButton)
269 {
270   if (Main.event.button.button == SDL_BUTTON_LEFT) {
271     struct unit *pUnit = pButton->data.unit;
272 
273     if(pUnit) {
274 
275       popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
276                                   pCityDlg->pEndCityMenuWidgetList);
277       pCityDlg->pEndCityMenuWidgetList = NULL;
278 
279       popdown_city_dialog(pCityDlg->pCity);
280 
281       center_tile_mapcanvas(unit_tile(pUnit));
282       unit_focus_set(pUnit);
283     }
284   }
285   return -1;
286 }
287 
288 /**************************************************************************
289   sentry unit and del unit order dlg. widget group.
290 **************************************************************************/
sentry_units_orders_city_dlg_callback(struct widget * pButton)291 static int sentry_units_orders_city_dlg_callback(struct widget *pButton)
292 {
293   if (Main.event.button.button == SDL_BUTTON_LEFT) {
294     struct unit *pUnit = pButton->data.unit;
295 
296     popdown_city_menu_dlg(TRUE);
297     if(pUnit) {
298       request_unit_sentry(pUnit);
299     }
300   }
301   return -1;
302 }
303 
304 /**************************************************************************
305   fortify unit and del unit order dlg. widget group.
306 **************************************************************************/
fortify_units_orders_city_dlg_callback(struct widget * pButton)307 static int fortify_units_orders_city_dlg_callback(struct widget *pButton)
308 {
309   if (Main.event.button.button == SDL_BUTTON_LEFT) {
310     struct unit *pUnit = pButton->data.unit;
311 
312     popdown_city_menu_dlg(TRUE);
313     if(pUnit) {
314       request_unit_fortify(pUnit);
315     }
316   }
317   return -1;
318 }
319 
320 /**************************************************************************
321   disband unit and del unit order dlg. widget group.
322 **************************************************************************/
disband_units_orders_city_dlg_callback(struct widget * pButton)323 static int disband_units_orders_city_dlg_callback(struct widget *pButton)
324 {
325   if (Main.event.button.button == SDL_BUTTON_LEFT) {
326     struct unit *pUnit = pButton->data.unit;
327 
328     popdown_city_menu_dlg(TRUE);
329     popup_unit_disband_dlg(pUnit, TRUE);
330   }
331   return -1;
332 }
333 
334 /**************************************************************************
335   homecity unit and del unit order dlg. widget group.
336 **************************************************************************/
homecity_units_orders_city_dlg_callback(struct widget * pButton)337 static int homecity_units_orders_city_dlg_callback(struct widget *pButton)
338 {
339   if (Main.event.button.button == SDL_BUTTON_LEFT) {
340     struct unit *pUnit = pButton->data.unit;
341 
342     popdown_city_menu_dlg(TRUE);
343     if(pUnit) {
344       request_unit_change_homecity(pUnit);
345     }
346   }
347   return -1;
348 }
349 
350 /**************************************************************************
351   upgrade unit and del unit order dlg. widget group.
352 **************************************************************************/
upgrade_units_orders_city_dlg_callback(struct widget * pButton)353 static int upgrade_units_orders_city_dlg_callback(struct widget *pButton)
354 {
355   if (Main.event.button.button == SDL_BUTTON_LEFT) {
356     struct unit *pUnit = pButton->data.unit;
357 
358     popdown_city_menu_dlg(TRUE);
359     popup_unit_upgrade_dlg(pUnit, TRUE);
360   }
361   return -1;
362 }
363 
364 /**************************************************************************
365   Main unit order dlg. callback.
366 **************************************************************************/
units_orders_dlg_callback(struct widget * pButton)367 static int units_orders_dlg_callback(struct widget *pButton)
368 {
369   return -1;
370 }
371 
372 /**************************************************************************
373   popup units orders menu.
374 **************************************************************************/
units_orders_city_dlg_callback(struct widget * pButton)375 static int units_orders_city_dlg_callback(struct widget *pButton)
376 {
377   if (Main.event.button.button == SDL_BUTTON_LEFT) {
378     SDL_String16 *pStr;
379     char cBuf[80];
380     struct widget *pBuf, *pWindow = pCityDlg->pEndCityWidgetList;
381     struct unit *pUnit;
382     struct unit_type *pUType;
383     Uint16 i = 0, hh = 0;
384     SDL_Rect area;
385 
386     pUnit = player_unit_by_number(client_player(), MAX_ID - pButton->ID);
387 
388     if(!pUnit || !can_client_issue_orders()) {
389       return -1;
390     }
391 
392     if(Main.event.button.button == SDL_BUTTON_RIGHT) {
393       popdown_city_dialog(pCityDlg->pCity);
394       center_tile_mapcanvas(unit_tile(pUnit));
395       unit_focus_set(pUnit);
396       return -1;
397     }
398 
399     /* Disable city dlg */
400     unsellect_widget_action();
401     disable_city_dlg_widgets();
402 
403     pUType = unit_type_get(pUnit);
404 
405     /* window */
406     fc_snprintf(cBuf, sizeof(cBuf), "%s:", _("Unit commands"));
407     pStr = create_str16_from_char(cBuf, adj_font(12));
408     pStr->style |= TTF_STYLE_BOLD;
409     pWindow = create_window_skeleton(NULL, pStr, 0);
410 
411     pWindow->action = units_orders_dlg_callback;
412     set_wstate(pWindow, FC_WS_NORMAL);
413     add_to_gui_list(ID_REVOLUTION_DLG_WINDOW, pWindow);
414     pCityDlg->pEndCityMenuWidgetList = pWindow;
415 
416     area = pWindow->area;
417 
418     /* unit description */
419     fc_snprintf(cBuf, sizeof(cBuf), "%s", unit_description(pUnit));
420     pStr = create_str16_from_char(cBuf, adj_font(12));
421     pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
422     pBuf = create_iconlabel(adj_surf(get_unittype_surface(pUType, pUnit->facing)),
423                             pWindow->dst, pStr, WF_FREE_THEME);
424     area.w = MAX(area.w, pBuf->size.w);
425     add_to_gui_list(ID_LABEL, pBuf);
426 
427     /* Activate unit */
428     pBuf =
429         create_icon_button_from_chars(NULL, pWindow->dst,
430                                                 _("Activate unit"), adj_font(12), 0);
431     i++;
432     area.w = MAX(area.w, pBuf->size.w);
433     hh = MAX(hh, pBuf->size.h);
434     pBuf->action = activate_units_orders_city_dlg_callback;
435     pBuf->data = pButton->data;
436     set_wstate(pBuf, FC_WS_NORMAL);
437     add_to_gui_list(pButton->ID, pBuf);
438 
439     /* Activate unit, close dlg. */
440     pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
441                     _("Activate unit, close dialog"),  adj_font(12), 0);
442     i++;
443     area.w = MAX(area.w, pBuf->size.w);
444     hh = MAX(hh, pBuf->size.h);
445     pBuf->action = activate_and_exit_units_orders_city_dlg_callback;
446     pBuf->data = pButton->data;
447     set_wstate(pBuf, FC_WS_NORMAL);
448     add_to_gui_list(pButton->ID, pBuf);
449     /* ----- */
450 
451     if (pCityDlg->page == ARMY_PAGE) {
452       /* Sentry unit */
453       pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
454                                           _("Sentry unit"), adj_font(12), 0);
455       i++;
456       area.w = MAX(area.w, pBuf->size.w);
457       hh = MAX(hh, pBuf->size.h);
458       pBuf->data = pButton->data;
459       pBuf->action = sentry_units_orders_city_dlg_callback;
460       if (pUnit->activity != ACTIVITY_SENTRY
461           && can_unit_do_activity(pUnit, ACTIVITY_SENTRY)) {
462         set_wstate(pBuf, FC_WS_NORMAL);
463       }
464       add_to_gui_list(pButton->ID, pBuf);
465       /* ----- */
466 
467       /* Fortify unit */
468       pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
469                                               _("Fortify unit"), adj_font(12), 0);
470       i++;
471       area.w = MAX(area.w, pBuf->size.w);
472       hh = MAX(hh, pBuf->size.h);
473       pBuf->data = pButton->data;
474       pBuf->action = fortify_units_orders_city_dlg_callback;
475       if (pUnit->activity != ACTIVITY_FORTIFYING
476           && can_unit_do_activity(pUnit, ACTIVITY_FORTIFYING)) {
477         set_wstate(pBuf, FC_WS_NORMAL);
478       }
479       add_to_gui_list(pButton->ID, pBuf);
480     }
481     /* ----- */
482 
483     /* Disband unit */
484     pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
485                                     _("Disband unit"), adj_font(12), 0);
486     i++;
487     area.w = MAX(area.w, pBuf->size.w);
488     hh = MAX(hh, pBuf->size.h);
489     pBuf->data = pButton->data;
490     pBuf->action = disband_units_orders_city_dlg_callback;
491     set_wstate(pBuf, FC_WS_NORMAL);
492     add_to_gui_list(pButton->ID, pBuf);
493     /* ----- */
494 
495     if (pCityDlg->page == ARMY_PAGE) {
496       if (pUnit->homecity != pCityDlg->pCity->id) {
497         /* Make new Homecity */
498         pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
499                                           _("Set Home City"), adj_font(12), 0);
500         i++;
501         area.w = MAX(area.w, pBuf->size.w);
502         hh = MAX(hh, pBuf->size.h);
503         pBuf->data = pButton->data;
504         pBuf->action = homecity_units_orders_city_dlg_callback;
505         set_wstate(pBuf, FC_WS_NORMAL);
506         add_to_gui_list(pButton->ID, pBuf);
507       }
508       /* ----- */
509 
510       if (can_upgrade_unittype(client.conn.playing, pUType)) {
511         /* Upgrade unit */
512         pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
513                                               _("Upgrade unit"), adj_font(12), 0);
514         i++;
515         area.w = MAX(area.w, pBuf->size.w);
516         hh = MAX(hh, pBuf->size.h);
517         pBuf->data = pButton->data;
518         pBuf->action = upgrade_units_orders_city_dlg_callback;
519         set_wstate(pBuf, FC_WS_NORMAL);
520         add_to_gui_list(pButton->ID, pBuf);
521       }
522     }
523 
524     /* ----- */
525     /* Cancel */
526     pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
527                                                   _("Cancel"), adj_font(12), 0);
528     i++;
529     area.w = MAX(area.w, pBuf->size.w);
530     hh = MAX(hh, pBuf->size.h);
531     pBuf->key = SDLK_ESCAPE;
532     pBuf->action = cancel_units_orders_city_dlg_callback;
533     set_wstate(pBuf, FC_WS_NORMAL);
534     add_to_gui_list(pButton->ID, pBuf);
535     pCityDlg->pBeginCityMenuWidgetList = pBuf;
536 
537     /* ================================================== */
538     unsellect_widget_action();
539     /* ================================================== */
540 
541     area.w += adj_size(10);
542     hh += adj_size(4);
543 
544     /* create window background */
545     resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
546                   (pWindow->size.w - pWindow->area.w) + area.w,
547                   (pWindow->size.h - pWindow->area.h) + pWindow->prev->size.h +
548                   (i * hh) + adj_size(5));
549 
550     area = pWindow->area;
551 
552     widget_set_position(pWindow,
553                         pButton->size.x + adj_size(2),
554                         pWindow->area.y + pButton->size.y + 1);
555 
556     /* label */
557     pBuf = pWindow->prev;
558     pBuf->size.w = area.w;
559     pBuf->size.x = area.x;
560     pBuf->size.y = area.y + 1;
561     pBuf = pBuf->prev;
562 
563     /* first button */
564     pBuf->size.w = area.w;
565     pBuf->size.h = hh;
566     pBuf->size.x = area.x;
567     pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(5);
568     pBuf = pBuf->prev;
569 
570     while (pBuf) {
571       pBuf->size.w = area.w;
572       pBuf->size.h = hh;
573       pBuf->size.x = pBuf->next->size.x;
574       pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
575       if (pBuf == pCityDlg->pBeginCityMenuWidgetList) {
576         break;
577       }
578       pBuf = pBuf->prev;
579     }
580 
581     /* ================================================== */
582     /* redraw */
583     redraw_group(pCityDlg->pBeginCityMenuWidgetList, pWindow, 0);
584     widget_flush(pWindow);
585   }
586   return -1;
587 }
588 
589 /* ======================================================================= */
590 /* ======================= City Dlg. Panels ============================== */
591 /* ======================================================================= */
592 
593 /**************************************************************************
594   create unit icon with support icons.
595 **************************************************************************/
create_unit_surface(struct unit * punit,bool support,int w,int h)596 static SDL_Surface *create_unit_surface(struct unit *punit, bool support,
597                                         int w, int h)
598 {
599   int i, step;
600   SDL_Rect src_rect, dest;
601   SDL_Surface *psurf;
602   struct canvas *destcanvas;
603 
604   destcanvas = canvas_create_with_alpha(tileset_full_tile_width(tileset),
605                                         tileset_unit_with_small_upkeep_height(tileset));
606 
607   put_unit(punit, destcanvas, 1.0, 0, 0);
608   /* Get unit sprite width, but do not limit height by it */
609   src_rect = get_smaller_surface_rect(destcanvas->surf);
610   src_rect.y = 0;
611   src_rect.h = destcanvas->surf->h;
612 
613   if (support) {
614     int free_unhappy;
615     int happy_cost;
616 
617     free_unhappy = get_city_bonus(pCityDlg->pCity, EFT_MAKE_CONTENT_MIL);
618     happy_cost = city_unit_unhappiness(punit, &free_unhappy);
619 
620     i = punit->upkeep[O_SHIELD] + punit->upkeep[O_FOOD] +
621         punit->upkeep[O_GOLD] + happy_cost;
622 
623     if (i * pIcons->pFood->w > src_rect.w / 2) {
624       step = (src_rect.w / 2 - pIcons->pFood->w) / (i - 1);
625     } else {
626       step = pIcons->pFood->w;
627     }
628 
629     dest.y = tileset_unit_layout_small_offset_y(tileset);
630     dest.x = src_rect.x + src_rect.w / 8;
631 
632     for (i = 0; i < punit->upkeep[O_SHIELD]; i++) {
633       alphablit(pIcons->pShield, NULL, destcanvas->surf, &dest);
634       dest.x += step;
635     }
636 
637     for (i = 0; i < punit->upkeep[O_FOOD]; i++) {
638       alphablit(pIcons->pFood, NULL, destcanvas->surf, &dest);
639       dest.x += step;
640     }
641 
642     for (i = 0; i < punit->upkeep[O_GOLD]; i++) {
643       alphablit(pIcons->pCoin, NULL, destcanvas->surf, &dest);
644       dest.x += step;
645     }
646 
647     for (i = 0; i < happy_cost; i++) {
648       alphablit(pIcons->pFace, NULL, destcanvas->surf, &dest);
649       dest.x += step;
650     }
651   }
652 
653   psurf = create_surf_alpha(src_rect.w, src_rect.h, SDL_SWSURFACE);
654   alphablit(destcanvas->surf, &src_rect, psurf, NULL);
655 
656   canvas_free(destcanvas);
657 
658   if (w != src_rect.w || h != src_rect.h) {
659     SDL_Surface *pzoomed;
660 
661     pzoomed = ResizeSurfaceBox(psurf, w, h, 1, TRUE, TRUE);
662     FREESURFACE(psurf);
663     psurf = pzoomed;
664   }
665 
666   return psurf;
667 }
668 
669 /**************************************************************************
670   create present/supported units widget list
671   207 pixels is panel width in city dlg.
672   220 - max y position pixel position belong to panel area.
673 **************************************************************************/
create_present_supported_units_widget_list(struct unit_list * pList)674 static void create_present_supported_units_widget_list(struct unit_list *pList)
675 {
676   int i;
677   struct widget *pBuf = NULL;
678   struct widget *pEnd = NULL;
679   struct widget *pWindow = pCityDlg->pEndCityWidgetList;
680   struct city *pHome_City;
681   struct unit_type *pUType;
682   SDL_Surface *pSurf;
683   SDL_String16 *pStr;
684   char cBuf[256];
685   int num_x, num_y, w, h;
686 
687   i = 0;
688 
689   num_x = (adj_size(160) / (tileset_full_tile_width(tileset) + adj_size(4)));
690   if (num_x < 4) {
691     num_x = 4;
692     w = adj_size(160 - 4*4) / 4;
693   } else {
694     w = tileset_full_tile_width(tileset) + (adj_size(160) % (tileset_full_tile_width(tileset)+4)) / num_x;
695   }
696 
697   num_y = (adj_size(151) / (tileset_full_tile_height(tileset)+4));
698   if (num_y < 4) {
699     num_y = 4;
700     h = adj_size(151 - 4*4) / 4;
701   } else {
702     h = tileset_full_tile_height(tileset) + (adj_size(151) % (tileset_full_tile_height(tileset)+4)) / num_y;
703   }
704 
705   unit_list_iterate(pList, pUnit) {
706     const char *vetname;
707 
708     pUType = unit_type_get(pUnit);
709     vetname = utype_veteran_name_translation(pUType, pUnit->veteran);
710     pHome_City = game_city_by_number(pUnit->homecity);
711     fc_snprintf(cBuf, sizeof(cBuf), "%s (%d,%d,%s)%s%s\n%s\n(%d/%d)\n%s",
712                 utype_name_translation(pUType),
713                 pUType->attack_strength,
714                 pUType->defense_strength,
715                 move_points_text(pUType->move_rate, FALSE),
716                 (vetname != NULL ? "\n" : ""),
717                 (vetname != NULL ? vetname : ""),
718                 unit_activity_text(pUnit),
719                 pUnit->hp, pUType->hp,
720                 pHome_City ? pHome_City->name : Q_("?homecity:None"));
721 
722     if (pCityDlg->page == SUPPORTED_UNITS_PAGE) {
723       int pCity_near_dist;
724       struct city *pNear_City = get_nearest_city(pUnit, &pCity_near_dist);
725 
726       sz_strlcat(cBuf, "\n");
727       sz_strlcat(cBuf, get_nearest_city_text(pNear_City, pCity_near_dist));
728       pSurf = adj_surf(create_unit_surface(pUnit, TRUE, w, h));
729     } else {
730       pSurf = adj_surf(create_unit_surface(pUnit, FALSE, w, h));
731     }
732 
733     pStr = create_str16_from_char(cBuf, adj_font(10));
734     pStr->style |= SF_CENTER;
735 
736     pBuf = create_icon2(pSurf, pWindow->dst, WF_FREE_THEME
737                         | WF_RESTORE_BACKGROUND | WF_WIDGET_HAS_INFO_LABEL);
738     pBuf->info_label = pStr;
739     pBuf->data.unit = pUnit;
740     add_to_gui_list(MAX_ID - pUnit->id, pBuf);
741 
742     if (!pEnd) {
743       pEnd = pBuf;
744     }
745 
746     if (++i > num_x * num_y) {
747       set_wflag(pBuf, WF_HIDDEN);
748     }
749 
750     if (city_owner(pCityDlg->pCity) == client.conn.playing) {
751       set_wstate(pBuf, FC_WS_NORMAL);
752     }
753 
754     pBuf->action = units_orders_city_dlg_callback;
755 
756   } unit_list_iterate_end;
757 
758   pCityDlg->pPanel = fc_calloc(1, sizeof(struct ADVANCED_DLG));
759   pCityDlg->pPanel->pEndWidgetList = pEnd;
760   pCityDlg->pPanel->pBeginWidgetList = pBuf;
761   pCityDlg->pPanel->pEndActiveWidgetList = pCityDlg->pPanel->pEndWidgetList;
762   pCityDlg->pPanel->pBeginActiveWidgetList = pCityDlg->pPanel->pBeginWidgetList;
763   pCityDlg->pPanel->pActiveWidgetList = pCityDlg->pPanel->pEndActiveWidgetList;
764 
765   setup_vertical_widgets_position(num_x,
766 	pWindow->area.x + adj_size(5),
767 	pWindow->area.y + adj_size(44),
768 	  0, 0, pCityDlg->pPanel->pBeginActiveWidgetList,
769 			  pCityDlg->pPanel->pEndActiveWidgetList);
770 
771   if (i > num_x * num_y) {
772 
773     create_vertical_scrollbar(pCityDlg->pPanel,
774 	                      num_x, num_y, TRUE, TRUE);
775 
776     setup_vertical_scrollbar_area(pCityDlg->pPanel->pScroll,
777 		pWindow->area.x + adj_size(185),
778                 pWindow->area.y + adj_size(45),
779                 adj_size(150), TRUE);
780   }
781 
782 }
783 
784 /**************************************************************************
785   free city present/supported units panel list.
786 **************************************************************************/
free_city_units_lists(void)787 void free_city_units_lists(void)
788 {
789   if (pCityDlg && pCityDlg->pPanel) {
790     del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
791 					 pCityDlg->pPanel->pEndWidgetList);
792     FC_FREE(pCityDlg->pPanel->pScroll);
793     FC_FREE(pCityDlg->pPanel);
794   }
795 }
796 
797 /**************************************************************************
798   change to present units panel.
799 **************************************************************************/
army_city_dlg_callback(struct widget * pButton)800 static int army_city_dlg_callback(struct widget *pButton)
801 {
802   if (Main.event.button.button == SDL_BUTTON_LEFT) {
803     if (pCityDlg->page != ARMY_PAGE) {
804       free_city_units_lists();
805       pCityDlg->page = ARMY_PAGE;
806       redraw_city_dialog(pCityDlg->pCity);
807       flush_dirty();
808     } else {
809       widget_redraw(pButton);
810       widget_flush(pButton);
811     }
812   }
813   return -1;
814 }
815 
816 /**************************************************************************
817   change to supported units panel.
818 **************************************************************************/
supported_unit_city_dlg_callback(struct widget * pButton)819 static int supported_unit_city_dlg_callback(struct widget *pButton)
820 {
821   if (Main.event.button.button == SDL_BUTTON_LEFT) {
822     if (pCityDlg->page != SUPPORTED_UNITS_PAGE) {
823       free_city_units_lists();
824       pCityDlg->page = SUPPORTED_UNITS_PAGE;
825       redraw_city_dialog(pCityDlg->pCity);
826       flush_dirty();
827     } else {
828       widget_redraw(pButton);
829       widget_flush(pButton);
830     }
831   }
832   return -1;
833 }
834 
835 /* ---------------------- */
836 
837 /**************************************************************************
838   change to info panel.
839 **************************************************************************/
info_city_dlg_callback(struct widget * pButton)840 static int info_city_dlg_callback(struct widget *pButton)
841 {
842   if (Main.event.button.button == SDL_BUTTON_LEFT) {
843     if (pCityDlg->page != INFO_PAGE) {
844       free_city_units_lists();
845       pCityDlg->page = INFO_PAGE;
846       redraw_city_dialog(pCityDlg->pCity);
847       flush_dirty();
848     } else {
849       widget_redraw(pButton);
850       widget_flush(pButton);
851     }
852   }
853   return -1;
854 }
855 
856 /* ---------------------- */
857 /**************************************************************************
858   change to happines panel.
859 **************************************************************************/
happy_city_dlg_callback(struct widget * pButton)860 static int happy_city_dlg_callback(struct widget *pButton)
861 {
862   if (Main.event.button.button == SDL_BUTTON_LEFT) {
863     if (pCityDlg->page != HAPPINESS_PAGE) {
864       free_city_units_lists();
865       pCityDlg->page = HAPPINESS_PAGE;
866       redraw_city_dialog(pCityDlg->pCity);
867       flush_dirty();
868     } else {
869       widget_redraw(pButton);
870       widget_flush(pButton);
871     }
872   }
873   return -1;
874 }
875 
876 /**************************************************************************
877   city option callback
878 **************************************************************************/
misc_panel_city_dlg_callback(struct widget * pWidget)879 static int misc_panel_city_dlg_callback(struct widget *pWidget)
880 {
881   if (Main.event.button.button == SDL_BUTTON_LEFT) {
882 /*  int new = pCityDlg->pCity->city_options & 0xff; */
883     bv_city_options new_options = pCityDlg->pCity->city_options;
884 
885     switch (MAX_ID - pWidget->ID) {
886     case 0x10:
887       if (BV_ISSET(new_options, CITYO_DISBAND))
888         BV_CLR(new_options, CITYO_DISBAND);
889       else
890         BV_SET(new_options, CITYO_DISBAND);
891       break;
892     case 0x20:
893       if (BV_ISSET(new_options, CITYO_NEW_EINSTEIN))
894         BV_CLR(new_options, CITYO_NEW_EINSTEIN);
895       else
896         BV_SET(new_options, CITYO_NEW_EINSTEIN);
897 
898       if (BV_ISSET(new_options, CITYO_NEW_TAXMAN))
899         BV_CLR(new_options, CITYO_NEW_TAXMAN);
900       else
901         BV_SET(new_options, CITYO_NEW_TAXMAN);
902 
903       pWidget->theme2 = get_tax_surface(O_GOLD);
904       pWidget->ID = MAX_ID - 0x40;
905       widget_redraw(pWidget);
906       widget_flush(pWidget);
907       break;
908     case 0x40:
909       BV_CLR(new_options, CITYO_NEW_EINSTEIN);
910       BV_CLR(new_options, CITYO_NEW_TAXMAN);
911       pWidget->theme2 = get_tax_surface(O_LUXURY);
912       pWidget->ID = MAX_ID - 0x60;
913       widget_redraw(pWidget);
914       widget_flush(pWidget);
915       break;
916     case 0x60:
917       if (BV_ISSET(new_options, CITYO_NEW_EINSTEIN))
918         BV_CLR(new_options, CITYO_NEW_EINSTEIN);
919       else
920         BV_SET(new_options, CITYO_NEW_EINSTEIN);
921       pWidget->theme2 = get_tax_surface(O_SCIENCE);
922       pWidget->ID = MAX_ID - 0x20;
923       widget_redraw(pWidget);
924       widget_flush(pWidget);
925       break;
926     }
927 
928     dsend_packet_city_options_req(&client.conn, pCityDlg->pCity->id, new_options);
929   }
930   return -1;
931 }
932 
933 /**************************************************************************
934   Create city options widgets.
935 **************************************************************************/
create_city_options_widget_list(struct city * pCity)936 static void create_city_options_widget_list(struct city *pCity)
937 {
938   struct widget *pBuf, *pWindow = pCityDlg->pEndCityWidgetList;
939   SDL_Surface *pSurf;
940   SDL_String16 *pStr;
941   char cBuf[80];
942 
943   fc_snprintf(cBuf, sizeof(cBuf),
944 	      _("Allow unit production\nto disband city"));
945   pStr = create_str16_from_char(cBuf, adj_font(10));
946   pStr->style |= TTF_STYLE_BOLD;
947   pStr->fgcol = *get_theme_color(COLOR_THEME_CHECKBOX_LABEL_TEXT);
948 
949   pBuf =
950       create_textcheckbox(pWindow->dst, BV_ISSET(pCity->city_options, CITYO_DISBAND), pStr,
951 			  WF_RESTORE_BACKGROUND);
952   set_wstate(pBuf, FC_WS_NORMAL);
953   pBuf->action = misc_panel_city_dlg_callback;
954   add_to_gui_list(MAX_ID - 0x10, pBuf);
955   pBuf->size.x = pWindow->area.x + adj_size(7);
956   pBuf->size.y = pWindow->area.y + adj_size(45);
957 
958   /* ----- */
959 
960   pCityDlg->pPanel = fc_calloc(1, sizeof(struct ADVANCED_DLG));
961   pCityDlg->pPanel->pEndWidgetList = pBuf;
962 
963   /* ----- */
964 
965   fc_snprintf(cBuf, sizeof(cBuf), "%s:", _("New citizens are"));
966   pStr = create_str16_from_char(cBuf, adj_font(11));
967   pStr->style |= SF_CENTER;
968 
969   if (BV_ISSET(pCity->city_options, CITYO_NEW_EINSTEIN)) {
970     pSurf = get_tax_surface(O_SCIENCE);
971     pBuf = create_icon_button(pSurf, pWindow->dst, pStr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
972     add_to_gui_list(MAX_ID - 0x20, pBuf);
973   } else {
974     if (BV_ISSET(pCity->city_options, CITYO_NEW_TAXMAN)) {
975       pSurf = get_tax_surface(O_GOLD);
976       pBuf = create_icon_button(pSurf, pWindow->dst,
977 				      pStr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
978       add_to_gui_list(MAX_ID - 0x40, pBuf);
979     } else {
980       pSurf = get_tax_surface(O_LUXURY);
981       pBuf = create_icon_button(pSurf, pWindow->dst,
982 				pStr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
983       add_to_gui_list(MAX_ID - 0x60, pBuf);
984     }
985   }
986 
987   pBuf->size.w = adj_size(177);
988   pBuf->action = misc_panel_city_dlg_callback;
989   set_wstate(pBuf, FC_WS_NORMAL);
990 
991   pBuf->size.x = pBuf->next->size.x;
992   pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(5);
993   pCityDlg->pPanel->pBeginWidgetList = pBuf;
994 }
995 
996 /**************************************************************************
997   change to city options panel.
998 **************************************************************************/
options_city_dlg_callback(struct widget * pButton)999 static int options_city_dlg_callback(struct widget *pButton)
1000 {
1001   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1002     if (pCityDlg->page != MISC_PAGE) {
1003       free_city_units_lists();
1004       pCityDlg->page = MISC_PAGE;
1005       redraw_city_dialog(pCityDlg->pCity);
1006       flush_dirty();
1007     } else {
1008       widget_redraw(pButton);
1009       widget_flush(pButton);
1010     }
1011   }
1012   return -1;
1013 }
1014 
1015 /* ======================================================================= */
1016 
1017 /**************************************************************************
1018   User interacted with Citizen Governor button.
1019 **************************************************************************/
cma_city_dlg_callback(struct widget * pButton)1020 static int cma_city_dlg_callback(struct widget *pButton)
1021 {
1022   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1023     disable_city_dlg_widgets();
1024     popup_city_cma_dialog(pCityDlg->pCity);
1025   }
1026   return -1;
1027 }
1028 
1029 /**************************************************************************
1030   Exit city dialog.
1031 **************************************************************************/
exit_city_dlg_callback(struct widget * pButton)1032 static int exit_city_dlg_callback(struct widget *pButton)
1033 {
1034   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1035     popdown_city_dialog(pCityDlg->pCity);
1036   }
1037   return -1;
1038 }
1039 
1040 /* ======================================================================= */
1041 /* ======================== Buy Production Dlg. ========================== */
1042 /* ======================================================================= */
1043 
1044 /**************************************************************************
1045   popdown buy productions dlg.
1046 **************************************************************************/
cancel_buy_prod_city_dlg_callback(struct widget * pButton)1047 static int cancel_buy_prod_city_dlg_callback(struct widget *pButton)
1048 {
1049   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1050     popdown_hurry_production_dialog();
1051 
1052     if (pCityDlg)
1053     {
1054       /* enable city dlg */
1055       enable_city_dlg_widgets();
1056     }
1057   }
1058   return -1;
1059 }
1060 
1061 /**************************************************************************
1062   buy productions.
1063 **************************************************************************/
ok_buy_prod_city_dlg_callback(struct widget * pButton)1064 static int ok_buy_prod_city_dlg_callback(struct widget *pButton)
1065 {
1066   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1067     struct city *pCity = pButton->data.city;    /* Save it. */
1068 
1069     popdown_hurry_production_dialog();
1070     city_buy_production(pCity);
1071 
1072     if (pCityDlg) {
1073       /* enable city dlg */
1074       enable_city_dlg_widgets();
1075 
1076       /* disable buy button */
1077       set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
1078       widget_redraw(pCityDlg->pBuy_Button);
1079       widget_mark_dirty(pCityDlg->pBuy_Button);
1080       flush_dirty();
1081     }
1082 
1083   }
1084   return -1;
1085 }
1086 
1087 /**************************************************************************
1088   popup buy productions dlg.
1089 **************************************************************************/
buy_prod_city_dlg_callback(struct widget * pButton)1090 static int buy_prod_city_dlg_callback(struct widget *pButton)
1091 {
1092   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1093     widget_redraw(pButton);
1094     widget_flush(pButton);
1095     disable_city_dlg_widgets();
1096     popup_hurry_production_dialog(pCityDlg->pCity, pButton->dst->surface);
1097   }
1098   return -1;
1099 }
1100 
1101 /**************************************************************************
1102   popup buy productions dlg.
1103 **************************************************************************/
popdown_hurry_production_dialog(void)1104 static void popdown_hurry_production_dialog(void)
1105 {
1106   if (pHurry_Prod_Dlg) {
1107     popdown_window_group_dialog(pHurry_Prod_Dlg->pBeginWidgetList,
1108                                 pHurry_Prod_Dlg->pEndWidgetList);
1109     FC_FREE(pHurry_Prod_Dlg);
1110     flush_dirty();
1111   }
1112 }
1113 
1114 /**************************************************************************
1115   main hurry productions dlg. callback
1116 **************************************************************************/
hurry_production_window_callback(struct widget * pWindow)1117 static int hurry_production_window_callback(struct widget *pWindow)
1118 {
1119   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1120     move_window_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow);
1121   }
1122   return -1;
1123 }
1124 
1125 /**************************************************************************
1126   popup buy productions dlg.
1127 **************************************************************************/
popup_hurry_production_dialog(struct city * pCity,SDL_Surface * pDest)1128 void popup_hurry_production_dialog(struct city *pCity, SDL_Surface *pDest)
1129 {
1130 
1131   char tBuf[512], cBuf[512];
1132   struct widget *pBuf = NULL, *pWindow;
1133   SDL_String16 *pStr;
1134   SDL_Surface *pText;
1135   SDL_Rect dst;
1136   int window_x = 0, window_y = 0;
1137   SDL_Rect area;
1138   const char *name = city_production_name_translation(pCity);
1139   int value = city_production_buy_gold_cost(pCity);
1140 
1141   if (pHurry_Prod_Dlg) {
1142     return;
1143   }
1144 
1145   fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
1146                                           "Treasury contains %d gold.",
1147                                           client_player()->economic.gold),
1148               client_player()->economic.gold);
1149 
1150   pHurry_Prod_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1151 
1152   if (city_can_buy(pCity)) {
1153     if (value <= client_player()->economic.gold) {
1154       fc_snprintf(cBuf, sizeof(cBuf),
1155                   /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1156                   PL_("Buy %s for %d gold?\n%s",
1157                       "Buy %s for %d gold?\n%s", value),
1158                   name, value, tBuf);
1159     } else {
1160       fc_snprintf(cBuf, sizeof(cBuf),
1161                   /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1162                   PL_("%s costs %d gold.\n%s",
1163                       "%s costs %d gold.\n%s", value),
1164                   name, value, tBuf);
1165     }
1166   } else {
1167     if (pCity->did_buy) {
1168       fc_snprintf(cBuf, sizeof(cBuf),
1169                   _("Sorry, you have already bought here in this turn."));
1170     } else {
1171       fc_snprintf(cBuf, sizeof(cBuf),
1172                   _("Sorry, you can't buy here in this turn."));
1173     }
1174   }
1175 
1176   pStr = create_str16_from_char(_("Buy it?"), adj_font(12));
1177   pStr->style |= TTF_STYLE_BOLD;
1178   pWindow = create_window_skeleton(NULL, pStr, 0);
1179   pWindow->action = hurry_production_window_callback;
1180   set_wstate(pWindow, FC_WS_NORMAL);
1181   add_to_gui_list(ID_WINDOW, pWindow);
1182 
1183   pHurry_Prod_Dlg->pEndWidgetList = pWindow;
1184 
1185   area = pWindow->area;
1186 
1187   area.h += 1;
1188 
1189   /* ============================================================= */
1190 
1191   /* label */
1192   pStr = create_str16_from_char(cBuf, adj_font(10));
1193   pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1194   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_BUY);
1195 
1196   pText = create_text_surf_from_str16(pStr);
1197   FREESTRING16(pStr);
1198   area.w = MAX(area.w , pText->w);
1199   area.h += pText->h + adj_size(5);
1200 
1201   pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1202                                             pWindow->dst, _("No"), adj_font(12), 0);
1203 
1204   pBuf->action = cancel_buy_prod_city_dlg_callback;
1205   set_wstate(pBuf, FC_WS_NORMAL);
1206   pBuf->key = SDLK_ESCAPE;
1207   area.h += pBuf->size.h;
1208 
1209   add_to_gui_list(ID_BUTTON, pBuf);
1210 
1211   if (city_can_buy(pCity) && (value <= client.conn.playing->economic.gold)) {
1212     pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
1213                                               _("Yes"), adj_font(12), 0);
1214 
1215     pBuf->action = ok_buy_prod_city_dlg_callback;
1216     set_wstate(pBuf, FC_WS_NORMAL);
1217     pBuf->data.city = pCity;
1218     pBuf->key = SDLK_RETURN;
1219     add_to_gui_list(ID_BUTTON, pBuf);
1220     pBuf->size.w = MAX(pBuf->next->size.w, pBuf->size.w);
1221     pBuf->next->size.w = pBuf->size.w;
1222     area.w = MAX(area.w , 2 * pBuf->size.w + adj_size(20));
1223   }
1224 
1225   pHurry_Prod_Dlg->pBeginWidgetList = pBuf;
1226 
1227   /* setup window size and start position */
1228   area.w += adj_size(10);
1229   area.h += adj_size(5);
1230 
1231   resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1232                 (pWindow->size.w - pWindow->area.w) + area.w,
1233                 (pWindow->size.h - pWindow->area.h) + area.h);
1234 
1235   area = pWindow->area;
1236 
1237   pBuf = pWindow->prev;
1238 
1239   if (city_dialog_is_open(pCity))
1240   {
1241     window_x = pCityDlg->pBuy_Button->size.x;
1242     window_y = pCityDlg->pBuy_Button->size.y - pWindow->size.h;
1243   } else {
1244     if(is_city_report_open()) {
1245       fc_assert(pSellected_Widget != NULL);
1246       if (pSellected_Widget->size.x + tileset_tile_width(tileset) + pWindow->size.w > Main.screen->w)
1247       {
1248         window_x = pSellected_Widget->size.x - pWindow->size.w;
1249       } else {
1250         window_x = pSellected_Widget->size.x + tileset_tile_width(tileset);
1251       }
1252 
1253       window_y = pSellected_Widget->size.y + (pSellected_Widget->size.h - pWindow->size.h) / 2;
1254       if (window_y + pWindow->size.h > Main.screen->h)
1255       {
1256 	window_y = Main.screen->h - pWindow->size.h - 1;
1257       } else {
1258         if (window_y < 0) {
1259 	  window_y = 0;
1260 	}
1261       }
1262     } else {
1263       put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h, pCity->tile);
1264     }
1265 
1266   }
1267 
1268   widget_set_position(pWindow, window_x, window_y);
1269 
1270   /* setup rest of widgets */
1271   /* label */
1272   dst.x = area.x + (area.w - pText->w) / 2;
1273   dst.y = area.y + 1;
1274   alphablit(pText, NULL, pWindow->theme, &dst);
1275   dst.y += pText->h + adj_size(5);
1276   FREESURFACE(pText);
1277 
1278   /* no */
1279   pBuf = pWindow->prev;
1280   pBuf->size.y = dst.y;
1281 
1282   if (city_can_buy(pCity) && value <= client.conn.playing->economic.gold) {
1283     /* yes */
1284     pBuf = pBuf->prev;
1285     pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(20))) / 2;
1286     pBuf->size.y = dst.y;
1287 
1288     /* no */
1289     pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(20);
1290   } else {
1291     /* no */
1292     pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
1293   }
1294   /* ================================================== */
1295   /* redraw */
1296   redraw_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow, 0);
1297   widget_mark_dirty(pWindow);
1298   flush_dirty();
1299 }
1300 
1301 /* =======================================================================*/
1302 /* ========================== CHANGE PRODUCTION ==========================*/
1303 /* =======================================================================*/
1304 
1305 /**************************************************************************
1306   Popup the change production dialog.
1307 **************************************************************************/
change_prod_dlg_callback(struct widget * pButton)1308 static int change_prod_dlg_callback(struct widget *pButton)
1309 {
1310   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1311     widget_redraw(pButton);
1312     widget_flush(pButton);
1313 
1314     disable_city_dlg_widgets();
1315     popup_worklist_editor(pCityDlg->pCity, NULL);
1316   }
1317   return -1;
1318 }
1319 
1320 /* =======================================================================*/
1321 /* =========================== SELL IMPROVMENTS ==========================*/
1322 /* =======================================================================*/
1323 
1324 /**************************************************************************
1325   Popdown Sell Imprv. Dlg. and exit without sell.
1326 **************************************************************************/
sell_imprvm_dlg_cancel_callback(struct widget * pCancel_Button)1327 static int sell_imprvm_dlg_cancel_callback(struct widget *pCancel_Button)
1328 {
1329   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1330     popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
1331                                 pCityDlg->pEndCityMenuWidgetList);
1332     pCityDlg->pEndCityMenuWidgetList = NULL;
1333     enable_city_dlg_widgets();
1334     redraw_city_dialog(pCityDlg->pCity);
1335     flush_dirty();
1336   }
1337   return -1;
1338 }
1339 
1340 /**************************************************************************
1341   Popdown Sell Imprv. Dlg. and exit with sell.
1342 **************************************************************************/
sell_imprvm_dlg_ok_callback(struct widget * pOK_Button)1343 static int sell_imprvm_dlg_ok_callback(struct widget *pOK_Button)
1344 {
1345   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1346     struct widget *pTmp = (struct widget *)pOK_Button->data.ptr;
1347 
1348     city_sell_improvement(pCityDlg->pCity, MAX_ID - 3000 - pTmp->ID);
1349 
1350     /* popdown, we don't redraw and flush because this is made by redraw city dlg.
1351        when response from server comes */
1352     popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
1353                                 pCityDlg->pEndCityMenuWidgetList);
1354 
1355     pCityDlg->pEndCityMenuWidgetList = NULL;
1356 
1357     /* del imprv from widget list */
1358     del_widget_from_vertical_scroll_widget_list(pCityDlg->pImprv, pTmp);
1359 
1360     enable_city_dlg_widgets();
1361 
1362     if (pCityDlg->pImprv->pEndWidgetList) {
1363       set_group_state(pCityDlg->pImprv->pBeginActiveWidgetList,
1364                       pCityDlg->pImprv->pEndActiveWidgetList, FC_WS_DISABLED);
1365     }
1366 
1367     redraw_city_dialog(pCityDlg->pCity);
1368     flush_dirty();
1369   }
1370   return -1;
1371 }
1372 
1373 /**************************************************************************
1374   Popup Sell Imprvm. Dlg.
1375 **************************************************************************/
sell_imprvm_dlg_callback(struct widget * pImpr)1376 static int sell_imprvm_dlg_callback(struct widget *pImpr)
1377 {
1378   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1379     struct SDL_String16 *pStr = NULL;
1380     struct widget *pLabel = NULL;
1381     struct widget *pWindow = NULL;
1382     struct widget *pCancel_Button = NULL;
1383     struct widget *pOK_Button = NULL;
1384     char cBuf[80];
1385     int id;
1386     SDL_Rect area;
1387     int price;
1388 
1389     unsellect_widget_action();
1390     disable_city_dlg_widgets();
1391 
1392     pStr = create_str16_from_char(_("Sell it?"), adj_font(12));
1393     pStr->style |= TTF_STYLE_BOLD;
1394     pWindow = create_window_skeleton(NULL, pStr, 0);
1395     /*pWindow->action = move_sell_imprvm_dlg_callback; */
1396     /*set_wstate( pWindow, FC_WS_NORMAL ); */
1397     add_to_gui_list(ID_WINDOW, pWindow);
1398     pCityDlg->pEndCityMenuWidgetList = pWindow;
1399 
1400     area = pWindow->area;
1401 
1402     /* create text label */
1403     id = MAX_ID - 3000 - pImpr->ID;
1404 
1405     price = impr_sell_gold(improvement_by_number(id));
1406     fc_snprintf(cBuf, sizeof(cBuf), PL_("Sell %s for %d gold?",
1407                                         "Sell %s for %d gold?", price),
1408                 city_improvement_name_translation(pCityDlg->pCity, improvement_by_number(id)),
1409                 price);
1410     pStr = create_str16_from_char(cBuf, adj_font(10));
1411     pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1412     pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SELL);
1413     pLabel = create_iconlabel(NULL, pWindow->dst, pStr, 0);
1414     add_to_gui_list(ID_LABEL, pLabel);
1415 
1416     /* create cancel button */
1417     pCancel_Button =
1418         create_themeicon_button_from_chars(current_theme->Small_CANCEL_Icon,
1419                           pWindow->dst, _("Cancel"), adj_font(10), 0);
1420     pCancel_Button->action = sell_imprvm_dlg_cancel_callback;
1421     pCancel_Button->key = SDLK_ESCAPE;
1422     set_wstate(pCancel_Button, FC_WS_NORMAL);
1423     add_to_gui_list(ID_BUTTON, pCancel_Button);
1424 
1425     /* create ok button */
1426     pOK_Button = create_themeicon_button_from_chars(current_theme->Small_OK_Icon,
1427                                                     pWindow->dst, _("Sell"),
1428                                                     adj_font(10), 0);
1429     pOK_Button->data.ptr = (void *)pImpr;
1430     pOK_Button->size.w = pCancel_Button->size.w;
1431     pOK_Button->action = sell_imprvm_dlg_ok_callback;
1432     pOK_Button->key = SDLK_RETURN;
1433     set_wstate(pOK_Button, FC_WS_NORMAL);
1434     add_to_gui_list(ID_BUTTON, pOK_Button);
1435 
1436     pCityDlg->pBeginCityMenuWidgetList = pOK_Button;
1437 
1438     /* correct sizes */
1439     if ((pOK_Button->size.w + pCancel_Button->size.w + adj_size(30)) >
1440         pLabel->size.w + adj_size(20)) {
1441       area.w = MAX(area.w, pOK_Button->size.w + pCancel_Button->size.w + adj_size(30));
1442     } else {
1443       area.w = MAX(area.w, pLabel->size.w + adj_size(20));
1444     }
1445 
1446     area.h = MAX(area.h, pOK_Button->size.h + pLabel->size.h + adj_size(25));
1447 
1448     /* create window background */
1449     resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1450                   (pWindow->size.w - pWindow->area.w) + area.w,
1451                   (pWindow->size.h - pWindow->area.h) + area.h);
1452 
1453     area = pWindow->area;
1454 
1455     /* set start positions */
1456     widget_set_position(pWindow,
1457                         (Main.screen->w - pWindow->size.w) / 2,
1458                         (Main.screen->h - pWindow->size.h) / 2 + adj_size(10));
1459 
1460     pOK_Button->size.x = area.x + adj_size(10);
1461     pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
1462 
1463     pCancel_Button->size.y = pOK_Button->size.y;
1464     pCancel_Button->size.x = area.x + area.w - pCancel_Button->size.w - adj_size(10);
1465 
1466     pLabel->size.x = area.x;
1467     pLabel->size.y = area.y + adj_size(4);
1468     pLabel->size.w = area.w;
1469 
1470     /* redraw */
1471     redraw_group(pCityDlg->pBeginCityMenuWidgetList,
1472                  pCityDlg->pEndCityMenuWidgetList, 0);
1473 
1474     widget_mark_dirty(pWindow);
1475     flush_dirty();
1476   }
1477   return -1;
1478 }
1479 /* ====================================================================== */
1480 
1481 /**************************************************************************
1482   Enable city dialog widgets that can be enabled.
1483 **************************************************************************/
enable_city_dlg_widgets(void)1484 void enable_city_dlg_widgets(void)
1485 {
1486   if (pCityDlg) {
1487     set_group_state(pCityDlg->pBeginCityWidgetList,
1488 		  pCityDlg->pEndCityWidgetList->prev, FC_WS_NORMAL);
1489 
1490     if (pCityDlg->pImprv->pEndActiveWidgetList) {
1491 
1492       if (pCityDlg->pImprv->pScroll) {
1493         set_wstate(pCityDlg->pImprv->pScroll->pScrollBar, FC_WS_NORMAL);	/* vscroll */
1494         set_wstate(pCityDlg->pImprv->pScroll->pUp_Left_Button, FC_WS_NORMAL); /* up */
1495         set_wstate(pCityDlg->pImprv->pScroll->pDown_Right_Button, FC_WS_NORMAL); /* down */
1496       }
1497 
1498       /* There is common function test_player_sell_building_now(),
1499        * but we are not using it here, since we want to use set_group_state()
1500        * when possible */
1501       if (pCityDlg->pCity->did_sell
1502           || pCityDlg->pCity->owner != client.conn.playing) {
1503         set_group_state(pCityDlg->pImprv->pBeginActiveWidgetList,
1504 		      pCityDlg->pImprv->pEndActiveWidgetList, FC_WS_DISABLED);
1505       } else {
1506         struct widget *pTmpWidget = pCityDlg->pImprv->pEndActiveWidgetList;
1507 
1508         while (TRUE) {
1509           struct impr_type *pimpr = improvement_by_number(MAX_ID - 3000 -
1510                                                           pTmpWidget->ID);
1511 
1512           if (!can_city_sell_building(pCityDlg->pCity, pimpr)) {
1513 	    set_wstate(pTmpWidget, FC_WS_DISABLED);
1514 	  } else {
1515 	    set_wstate(pTmpWidget, FC_WS_NORMAL);
1516 	  }
1517 
1518 	  if (pTmpWidget == pCityDlg->pImprv->pBeginActiveWidgetList) {
1519 	    break;
1520 	  }
1521 
1522 	  pTmpWidget = pTmpWidget->prev;
1523 
1524         }				/* while */
1525       }
1526     }
1527 
1528     if (!city_can_buy(pCityDlg->pCity) && pCityDlg->pBuy_Button) {
1529       set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
1530     }
1531 
1532     if (pCityDlg->pPanel) {
1533       set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1534 		    pCityDlg->pPanel->pEndWidgetList, FC_WS_NORMAL);
1535     }
1536 
1537     if (cma_is_city_under_agent(pCityDlg->pCity, NULL)) {
1538       set_wstate(pCityDlg->pResource_Map, FC_WS_DISABLED);
1539     }
1540 
1541     pCityDlg->lock = FALSE;
1542   }
1543 }
1544 
1545 /**************************************************************************
1546   Disable all city dialog widgets
1547 **************************************************************************/
disable_city_dlg_widgets(void)1548 static void disable_city_dlg_widgets(void)
1549 {
1550   if (pCityDlg->pPanel) {
1551     set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1552 		    pCityDlg->pPanel->pEndWidgetList, FC_WS_DISABLED);
1553   }
1554 
1555 
1556   if (pCityDlg->pImprv->pEndWidgetList) {
1557     set_group_state(pCityDlg->pImprv->pBeginWidgetList,
1558 		    pCityDlg->pImprv->pEndWidgetList, FC_WS_DISABLED);
1559   }
1560 
1561   set_group_state(pCityDlg->pBeginCityWidgetList,
1562 		  pCityDlg->pEndCityWidgetList->prev, FC_WS_DISABLED);
1563   pCityDlg->lock = TRUE;
1564 }
1565 /* ======================================================================== */
1566 
1567 /**************************************************************************
1568   Return scaled city map.
1569 **************************************************************************/
get_scaled_city_map(struct city * pCity)1570 SDL_Surface *get_scaled_city_map(struct city *pCity)
1571 {
1572   SDL_Surface *pBuf = create_city_map(pCity);
1573 
1574   city_map_zoom = ((pBuf->w * 159 > pBuf->h * 249) ?
1575                      (float)adj_size(249) / pBuf->w
1576                    : (float)adj_size(159) / pBuf->h);
1577 
1578   return zoomSurface(pBuf, city_map_zoom, city_map_zoom, 1);
1579 }
1580 
1581 /**************************************************************************
1582   city resource map: event callback
1583 **************************************************************************/
resource_map_city_dlg_callback(struct widget * pMap)1584 static int resource_map_city_dlg_callback(struct widget *pMap)
1585 {
1586   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1587     int col, row;
1588 
1589     if (canvas_to_city_pos(&col, &row,
1590                            city_map_radius_sq_get(pCityDlg->pCity),
1591       1/city_map_zoom * (Main.event.motion.x - pMap->dst->dest_rect.x
1592                          - pMap->size.x),
1593       1/city_map_zoom * (Main.event.motion.y - pMap->dst->dest_rect.y
1594                          - pMap->size.y))) {
1595 
1596       city_toggle_worker(pCityDlg->pCity, col, row);
1597     }
1598   }
1599   return -1;
1600 }
1601 
1602 /* ====================================================================== */
1603 
1604 /************************************************************************
1605   Helper for switch_city_callback.
1606 *************************************************************************/
city_comp_by_turn_founded(const void * a,const void * b)1607 static int city_comp_by_turn_founded(const void *a, const void *b)
1608 {
1609   struct city *pCity1 = *((struct city **) a);
1610   struct city *pCity2 = *((struct city **) b);
1611 
1612   return pCity1->turn_founded - pCity2->turn_founded;
1613 }
1614 
1615 /**************************************************************************
1616   Callback for next/prev city button
1617 **************************************************************************/
next_prev_city_dlg_callback(struct widget * pButton)1618 static int next_prev_city_dlg_callback(struct widget *pButton)
1619 {
1620   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1621     struct city **array;
1622     int i, dir, non_open_size;
1623     int size = city_list_size(client.conn.playing->cities);
1624 
1625     fc_assert_ret_val(size >= 1, -1);
1626     fc_assert_ret_val(city_owner(pCityDlg->pCity)
1627                       == client.conn.playing, -1);
1628 
1629     if (size == 1) {
1630       return -1;
1631     }
1632 
1633     /* dir = 1 will advance to the city, dir = -1 will get previous */
1634     if (pButton->ID == ID_CITY_DLG_NEXT_BUTTON) {
1635       dir = 1;
1636     } else {
1637       if (pButton->ID == ID_CITY_DLG_PREV_BUTTON) {
1638         dir = -1;
1639       } else {
1640         /* Always fails. */
1641         fc_assert_ret_val(pButton->ID == ID_CITY_DLG_NEXT_BUTTON
1642                           || pButton->ID != ID_CITY_DLG_PREV_BUTTON, -1);
1643         dir = 1;
1644       }
1645     }
1646 
1647     array = fc_calloc(1, size * sizeof(struct city *));
1648 
1649     non_open_size = 0;
1650     for (i = 0; i < size; i++) {
1651       array[non_open_size++] = city_list_get(client.conn.playing->cities, i);
1652     }
1653 
1654     fc_assert_ret_val(non_open_size > 0, -1);
1655 
1656     if (non_open_size == 1) {
1657       FC_FREE(array);
1658       return -1;
1659     }
1660 
1661     qsort(array, non_open_size, sizeof(struct city *),
1662                                                   city_comp_by_turn_founded);
1663 
1664     for (i = 0; i < non_open_size; i++) {
1665       if (pCityDlg->pCity == array[i]) {
1666         break;
1667       }
1668     }
1669 
1670     fc_assert_ret_val(i < non_open_size, -1);
1671     pCityDlg->pCity = array[(i + dir + non_open_size) % non_open_size];
1672     FC_FREE(array);
1673 
1674     /* free panel widgets */
1675     free_city_units_lists();
1676     /* refresh resource map */
1677     FREESURFACE(pCityDlg->pResource_Map->theme);
1678     pCityDlg->pResource_Map->theme = get_scaled_city_map(pCityDlg->pCity);
1679     rebuild_imprm_list(pCityDlg->pCity);
1680 
1681     /* redraw */
1682     redraw_city_dialog(pCityDlg->pCity);
1683     flush_dirty();
1684   }
1685   return -1;
1686 }
1687 
1688 /**************************************************************************
1689   Rename city name:
1690 **************************************************************************/
new_name_city_dlg_callback(struct widget * pEdit)1691 static int new_name_city_dlg_callback(struct widget *pEdit)
1692 {
1693   if (Main.event.button.button == SDL_BUTTON_LEFT) {
1694     char *tmp = convert_to_chars(pEdit->string16->text);
1695 
1696     if (tmp) {
1697       if (strcmp(tmp, city_name_get(pCityDlg->pCity))) {
1698         SDL_Client_Flags |= CF_CHANGED_CITY_NAME;
1699         city_rename(pCityDlg->pCity, tmp);
1700       }
1701 
1702       FC_FREE(tmp);
1703     } else {
1704       /* empty input -> restore previous content */
1705       copy_chars_to_string16(pEdit->string16, city_name_get(pCityDlg->pCity));
1706       widget_redraw(pEdit);
1707       widget_mark_dirty(pEdit);
1708       flush_dirty();
1709     }
1710   }
1711 
1712   return -1;
1713 }
1714 
1715 /* ======================================================================= */
1716 /* ======================== Redrawing City Dlg. ========================== */
1717 /* ======================================================================= */
1718 
1719 /**************************************************************************
1720   Refresh (update) the city names for the dialog
1721 **************************************************************************/
refresh_city_names(struct city * pcity)1722 static void refresh_city_names(struct city *pcity)
1723 {
1724   if (pCityDlg->pCity_Name_Edit) {
1725     char name[MAX_LEN_NAME];
1726 
1727     convertcopy_to_chars(name, MAX_LEN_NAME,
1728                          pCityDlg->pCity_Name_Edit->string16->text);
1729     if ((strcmp(city_name_get(pcity), name) != 0)
1730         || (SDL_Client_Flags & CF_CHANGED_CITY_NAME)) {
1731       copy_chars_to_string16(pCityDlg->pCity_Name_Edit->string16, city_name_get(pcity));
1732       rebuild_citydlg_title_str(pCityDlg->pEndCityWidgetList, pcity);
1733       SDL_Client_Flags &= ~CF_CHANGED_CITY_NAME;
1734     }
1735   }
1736 }
1737 
1738 /**************************************************************************
1739   Redraw city option panel
1740   207 = max panel width
1741 **************************************************************************/
redraw_misc_city_dialog(struct widget * pCityWindow,struct city * pCity)1742 static void redraw_misc_city_dialog(struct widget *pCityWindow,
1743 				    struct city *pCity)
1744 {
1745   char cBuf[60];
1746   SDL_String16 *pStr;
1747   SDL_Surface *pSurf;
1748   SDL_Rect dest;
1749 
1750   fc_snprintf(cBuf, sizeof(cBuf), _("City options"));
1751 
1752   pStr = create_str16_from_char(cBuf, adj_font(10));
1753   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1754   pStr->style |= TTF_STYLE_BOLD;
1755 
1756   pSurf = create_text_surf_from_str16(pStr);
1757 
1758   dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1759   dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1760 
1761   alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1762 
1763   FREESURFACE(pSurf);
1764   FREESTRING16(pStr);
1765 
1766   if (!pCityDlg->pPanel) {
1767     create_city_options_widget_list(pCity);
1768   }
1769   redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1770 		 pCityDlg->pPanel->pEndWidgetList, 0);
1771 }
1772 
1773 /**************************************************************************
1774   Redraw supported unit panel
1775   207 = max panel width
1776 **************************************************************************/
redraw_supported_units_city_dialog(struct widget * pCityWindow,struct city * pCity)1777 static void redraw_supported_units_city_dialog(struct widget *pCityWindow,
1778 					       struct city *pCity)
1779 {
1780   char cBuf[60];
1781   SDL_String16 *pStr;
1782   SDL_Surface *pSurf;
1783   SDL_Rect dest;
1784   struct unit_list *pList;
1785   int size;
1786 
1787   if (city_owner(pCityDlg->pCity) != client.conn.playing) {
1788     pList = (pCityDlg->pCity->client.info_units_supported);
1789   } else {
1790     pList = (pCityDlg->pCity->units_supported);
1791   }
1792 
1793   size = unit_list_size(pList);
1794 
1795   fc_snprintf(cBuf, sizeof(cBuf), _("Supported units: %d"), size);
1796 
1797   pStr = create_str16_from_char(cBuf, adj_font(10));
1798   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1799   pStr->style |= TTF_STYLE_BOLD;
1800 
1801   pSurf = create_text_surf_from_str16(pStr);
1802 
1803   dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1804   dest.y = pCityWindow->area.y + + adj_size(4) + current_theme->INFO_Icon->h;
1805 
1806   alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1807 
1808   FREESURFACE(pSurf);
1809   FREESTRING16(pStr);
1810 
1811   if (pCityDlg->pPanel) {
1812     if (size) {
1813       redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1814 		   pCityDlg->pPanel->pEndWidgetList, 0);
1815     } else {
1816       del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
1817 					 pCityDlg->pPanel->pEndWidgetList);
1818       FC_FREE(pCityDlg->pPanel->pScroll);
1819       FC_FREE(pCityDlg->pPanel);
1820     }
1821   } else {
1822     if (size) {
1823       create_present_supported_units_widget_list(pList);
1824       redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1825 		   pCityDlg->pPanel->pEndWidgetList, 0);
1826     }
1827   }
1828 }
1829 
1830 /**************************************************************************
1831   Redraw garrison panel
1832   207 = max panel width
1833 **************************************************************************/
redraw_army_city_dialog(struct widget * pCityWindow,struct city * pCity)1834 static void redraw_army_city_dialog(struct widget *pCityWindow,
1835 				    struct city *pCity)
1836 {
1837   char cBuf[60];
1838   SDL_String16 *pStr;
1839   SDL_Surface *pSurf;
1840   SDL_Rect dest;
1841   struct unit_list *pList;
1842 
1843   int size;
1844 
1845   if (city_owner(pCityDlg->pCity) != client.conn.playing) {
1846     pList = pCityDlg->pCity->client.info_units_present;
1847   } else {
1848     pList = pCityDlg->pCity->tile->units;
1849   }
1850 
1851   size = unit_list_size(pList);
1852 
1853   fc_snprintf(cBuf, sizeof(cBuf), _("Present units: %d"), size);
1854 
1855   pStr = create_str16_from_char(cBuf, adj_font(10));
1856   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1857   pStr->style |= TTF_STYLE_BOLD;
1858 
1859   pSurf = create_text_surf_from_str16(pStr);
1860 
1861   dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1862   dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1863 
1864   alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1865 
1866   FREESURFACE(pSurf);
1867   FREESTRING16(pStr);
1868 
1869   if (pCityDlg->pPanel) {
1870     if (size) {
1871       redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1872 		   pCityDlg->pPanel->pEndWidgetList, 0);
1873     } else {
1874       del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
1875 					 pCityDlg->pPanel->pEndWidgetList);
1876       FC_FREE(pCityDlg->pPanel->pScroll);
1877       FC_FREE(pCityDlg->pPanel);
1878     }
1879   } else {
1880     if (size) {
1881       create_present_supported_units_widget_list(pList);
1882       redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1883 		   pCityDlg->pPanel->pEndWidgetList, 0);
1884     }
1885   }
1886 }
1887 
1888 /**************************************************************************
1889   Redraw Info panel
1890   207 = max panel width
1891 **************************************************************************/
redraw_info_city_dialog(struct widget * pCityWindow,struct city * pCity)1892 static void redraw_info_city_dialog(struct widget *pCityWindow,
1893 				    struct city *pCity)
1894 {
1895   char cBuf[30];
1896   struct city *pTradeCity = NULL;
1897   int step, i, xx;
1898   SDL_String16 *pStr = NULL;
1899   SDL_Surface *pSurf = NULL;
1900   SDL_Rect dest;
1901 
1902   fc_snprintf(cBuf, sizeof(cBuf), _("City info"));
1903   pStr = create_str16_from_char(cBuf, adj_font(10));
1904   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1905   pStr->style |= TTF_STYLE_BOLD;
1906 
1907   pSurf = create_text_surf_from_str16(pStr);
1908 
1909   dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1910   dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1911 
1912   alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1913 
1914   dest.x = pCityWindow->size.x + adj_size(10);
1915   dest.y += pSurf->h + 1;
1916 
1917   FREESURFACE(pSurf);
1918 
1919   change_ptsize16(pStr, adj_font(11));
1920   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_INFOPANEL);
1921 
1922   if (pCity->pollution) {
1923     fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: %d"),
1924 		pCity->pollution);
1925 
1926     copy_chars_to_string16(pStr, cBuf);
1927 
1928     pSurf = create_text_surf_from_str16(pStr);
1929 
1930     alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1931 
1932     dest.y += pSurf->h + adj_size(3);
1933 
1934     FREESURFACE(pSurf);
1935 
1936     if (((pIcons->pPollution->w + 1) * pCity->pollution) > adj_size(187)) {
1937       step = (adj_size(187) - pIcons->pPollution->w) / (pCity->pollution - 1);
1938     } else {
1939       step = pIcons->pPollution->w + 1;
1940     }
1941 
1942     for (i = 0; i < pCity->pollution; i++) {
1943       alphablit(pIcons->pPollution, NULL, pCityWindow->dst->surface, &dest);
1944       dest.x += step;
1945     }
1946 
1947     dest.x = pCityWindow->size.x + adj_size(10);
1948     dest.y += pIcons->pPollution->h + adj_size(3);
1949 
1950   } else {
1951     fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: none"));
1952 
1953     copy_chars_to_string16(pStr, cBuf);
1954 
1955     pSurf = create_text_surf_from_str16(pStr);
1956 
1957     alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1958 
1959     dest.y += pSurf->h + adj_size(3);
1960 
1961     FREESURFACE(pSurf);
1962   }
1963 
1964   if (game.info.illness_on) {
1965     int risk_pml = city_illness_calc(pCity, NULL, NULL, NULL, NULL);
1966 
1967     fc_snprintf(cBuf, sizeof(cBuf), _("Plague risk: %.1f%%"),
1968 		(double)risk_pml / 10.0);
1969   } else {
1970     fc_snprintf(cBuf, sizeof(cBuf), _("Plague risk: none"));
1971   }
1972 
1973   copy_chars_to_string16(pStr, cBuf);
1974   pSurf = create_text_surf_from_str16(pStr);
1975   alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1976   dest.y += pSurf->h + adj_size(3);
1977   FREESURFACE(pSurf);
1978 
1979   fc_snprintf(cBuf, sizeof(cBuf), _("Trade routes: "));
1980 
1981   copy_chars_to_string16(pStr, cBuf);
1982 
1983   pSurf = create_text_surf_from_str16(pStr);
1984 
1985   alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1986 
1987   xx = dest.x + pSurf->w;
1988   dest.y += pSurf->h + adj_size(3);
1989 
1990   FREESURFACE(pSurf);
1991 
1992   step = 0;
1993   dest.x = pCityWindow->size.x + adj_size(10);
1994 
1995   for (i = 0; i < MAX_TRADE_ROUTES; i++) {
1996     if (pCity->trade[i]) {
1997       step += pCity->trade_value[i];
1998 
1999       if ((pTradeCity = game_city_by_number(pCity->trade[i]))) {
2000         fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", city_name_get(pTradeCity),
2001                     pCity->trade_value[i]);
2002       } else {
2003         fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", _("Unknown"),
2004                     pCity->trade_value[i]);
2005       }
2006 
2007       copy_chars_to_string16(pStr, cBuf);
2008 
2009       pSurf = create_text_surf_from_str16(pStr);
2010 
2011       alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2012 
2013       /* blit trade icon */
2014       dest.x += pSurf->w + adj_size(3);
2015       dest.y += adj_size(4);
2016       alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest);
2017       dest.x = pCityWindow->size.x + adj_size(10);
2018       dest.y -= adj_size(4);
2019 
2020       dest.y += pSurf->h;
2021 
2022       FREESURFACE(pSurf);
2023     }
2024   }
2025 
2026   if (step) {
2027     fc_snprintf(cBuf, sizeof(cBuf), _("Trade: +%d"), step);
2028 
2029     copy_chars_to_string16(pStr, cBuf);
2030     pSurf = create_text_surf_from_str16(pStr);
2031     alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2032 
2033     dest.x += pSurf->w + adj_size(3);
2034     dest.y += adj_size(4);
2035     alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest);
2036 
2037     FREESURFACE(pSurf);
2038   } else {
2039     fc_snprintf(cBuf, sizeof(cBuf), _("none"));
2040 
2041     copy_chars_to_string16(pStr, cBuf);
2042 
2043     pSurf = create_text_surf_from_str16(pStr);
2044 
2045     dest.x = xx;
2046     dest.y -= pSurf->h + adj_size(3);
2047     alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2048 
2049     FREESURFACE(pSurf);
2050   }
2051 
2052 
2053   FREESTRING16(pStr);
2054 }
2055 
2056 /**************************************************************************
2057   Redraw (refresh/update) the happiness info for the dialog
2058   207 - max panel width
2059   180 - max citizens icons area width
2060 **************************************************************************/
redraw_happyness_city_dialog(const struct widget * pCityWindow,struct city * pCity)2061 static void redraw_happyness_city_dialog(const struct widget *pCityWindow,
2062 					 struct city *pCity)
2063 {
2064   char cBuf[30];
2065   int step, i, j, count;
2066   SDL_Surface *pTmp;
2067   SDL_String16 *pStr = NULL;
2068   SDL_Surface *pSurf = NULL;
2069   SDL_Rect dest = {0, 0, 0, 0};
2070   struct effect_list *sources = effect_list_new();
2071 
2072   fc_snprintf(cBuf, sizeof(cBuf), _("Happiness"));
2073 
2074   pStr = create_str16_from_char(cBuf, adj_font(10));
2075   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
2076   pStr->style |= TTF_STYLE_BOLD;
2077 
2078   pSurf = create_text_surf_from_str16(pStr);
2079 
2080   dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
2081   dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
2082   alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2083 
2084   dest.x = pCityWindow->size.x + adj_size(10);
2085   dest.y += pSurf->h + 1;
2086 
2087   FREESURFACE(pSurf);
2088   FREESTRING16(pStr);
2089 
2090   count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
2091 	   + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
2092 	   + city_specialists(pCity));
2093 
2094   if (count * pIcons->pMale_Happy->w > adj_size(166)) {
2095     step = (adj_size(166) - pIcons->pMale_Happy->w) / (count - 1);
2096   } else {
2097     step = pIcons->pMale_Happy->w;
2098   }
2099 
2100   for (j = 0; j < FEELING_LAST; j++) {
2101     if (j == 0 || pCity->feel[CITIZEN_HAPPY][j - 1] != pCity->feel[CITIZEN_HAPPY][j]
2102 	|| pCity->feel[CITIZEN_CONTENT][j - 1] != pCity->feel[CITIZEN_CONTENT][j]
2103 	|| pCity->feel[CITIZEN_UNHAPPY][j - 1] != pCity->feel[CITIZEN_UNHAPPY][j]
2104 	|| pCity->feel[CITIZEN_ANGRY][j - 1] != pCity->feel[CITIZEN_ANGRY][j]) {
2105       int spe, spe_max;
2106 
2107       if (j != 0) {
2108 	putline(pCityWindow->dst->surface,
2109 	        dest.x, dest.y, dest.x + adj_size(176), dest.y,
2110                get_theme_color(COLOR_THEME_CITYDLG_FRAME));
2111 	dest.y += adj_size(5);
2112       }
2113 
2114       if (pCity->feel[CITIZEN_HAPPY][j]) {
2115 	pSurf = pIcons->pMale_Happy;
2116 	for (i = 0; i < pCity->feel[CITIZEN_HAPPY][j]; i++) {
2117 	  alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2118 	  dest.x += step;
2119 	  if (pSurf == pIcons->pMale_Happy) {
2120 	    pSurf = pIcons->pFemale_Happy;
2121 	  } else {
2122 	    pSurf = pIcons->pMale_Happy;
2123 	  }
2124 	}
2125       }
2126 
2127       if (pCity->feel[CITIZEN_CONTENT][j]) {
2128 	pSurf = pIcons->pMale_Content;
2129 	for (i = 0; i < pCity->feel[CITIZEN_CONTENT][j]; i++) {
2130 	  alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2131 	  dest.x += step;
2132 	  if (pSurf == pIcons->pMale_Content) {
2133 	    pSurf = pIcons->pFemale_Content;
2134 	  } else {
2135 	    pSurf = pIcons->pMale_Content;
2136 	  }
2137 	}
2138       }
2139 
2140       if (pCity->feel[CITIZEN_UNHAPPY][j]) {
2141 	pSurf = pIcons->pMale_Unhappy;
2142 	for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][j]; i++) {
2143 	  alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2144 	  dest.x += step;
2145 	  if (pSurf == pIcons->pMale_Unhappy) {
2146 	    pSurf = pIcons->pFemale_Unhappy;
2147 	  } else {
2148 	    pSurf = pIcons->pMale_Unhappy;
2149 	  }
2150 	}
2151       }
2152 
2153       if (pCity->feel[CITIZEN_ANGRY][j]) {
2154 	pSurf = pIcons->pMale_Angry;
2155 	for (i = 0; i < pCity->feel[CITIZEN_ANGRY][j]; i++) {
2156 	  alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2157 	  dest.x += step;
2158 	  if (pSurf == pIcons->pMale_Angry) {
2159 	    pSurf = pIcons->pFemale_Angry;
2160 	  } else {
2161 	    pSurf = pIcons->pMale_Angry;
2162 	  }
2163 	}
2164       }
2165 
2166       spe_max = specialist_count();
2167       for (spe = 0 ; spe < spe_max; spe++) {
2168         if (pCity->specialists[spe]) {
2169           for (i = 0; i < pCity->specialists[spe]; i++) {
2170             alphablit(pIcons->specialists[spe], NULL, pCityWindow->dst->surface, &dest);
2171             dest.x += step;
2172           }
2173         }
2174       }
2175 
2176       if (j == 1) { /* luxury effect */
2177 	dest.x =
2178 	    pCityWindow->size.x + adj_size(212) - pIcons->pBIG_Luxury->w - adj_size(2);
2179 	count = dest.y;
2180 	dest.y += (pIcons->pMale_Happy->h -
2181 		   pIcons->pBIG_Luxury->h) / 2;
2182 	alphablit(pIcons->pBIG_Luxury, NULL, pCityWindow->dst->surface, &dest);
2183 	dest.y = count;
2184       }
2185 
2186       if (j == 2) { /* improvements effects */
2187 	pSurf = NULL;
2188 	count = 0;
2189 
2190         get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_CONTENT);
2191 
2192         effect_list_iterate(sources, psource) {
2193 
2194           pTmp = get_building_surface(get_building_for_effect(psource->type));
2195           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2196 
2197 	  count += (pTmp->h + 1);
2198 
2199           if (!pSurf) {
2200 	    pSurf = pTmp;
2201 	  } else {
2202             FREESURFACE(pTmp);
2203           }
2204 
2205         } effect_list_iterate_end;
2206 
2207 	dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2208 	i = dest.y;
2209 	dest.y += (pIcons->pMale_Happy->h - count) / 2;
2210 
2211         FREESURFACE(pSurf);
2212 
2213         effect_list_iterate(sources, psource) {
2214 
2215           pTmp = get_building_surface(get_building_for_effect(psource->type));
2216           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2217 
2218 	  alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2219 	  dest.y += (pTmp->h + 1);
2220 
2221           FREESURFACE(pTmp);
2222         } effect_list_iterate_end;
2223 
2224         effect_list_clear(sources);
2225 
2226 	dest.y = i;
2227 
2228         /* TODO: check if code replacement above is correct */
2229 #if 0
2230 	if (city_has_building(pCity, improvement_by_number(B_TEMPLE))) {
2231 	  pTmp1 =
2232 	    zoomSurface(GET_SURF(improvement_by_number(B_TEMPLE)->sprite),
2233 			0.5, 0.5, 1);
2234 	  count += (pTmp1->h + 1);
2235 	  pSurf = pTmp1;
2236 	} else {
2237 	  pTmp1 = NULL;
2238 	}
2239 
2240 	if (city_has_building(pCity, improvement_by_number(B_COLOSSEUM))) {
2241 	  pTmp2 =
2242 	    zoomSurface(GET_SURF(improvement_by_number(B_COLOSSEUM)->sprite),
2243 			0.5, 0.5, 1);
2244 	  count += (pTmp2->h + 1);
2245 	  if (!pSurf) {
2246 	    pSurf = pTmp2;
2247 	  }
2248 	} else {
2249 	  pTmp2 = NULL;
2250 	}
2251 
2252 	if (city_has_building(pCity, improvement_by_number(B_CATHEDRAL)) ||
2253 	    city_affected_by_wonder(pCity, B_MICHELANGELO)) {
2254 	  pTmp3 =
2255 	    zoomSurface(GET_SURF(improvement_by_number(B_CATHEDRAL)->sprite),
2256 			0.5, 0.5, 1);
2257 	  count += (pTmp3->h + 1);
2258 	  if (!pSurf) {
2259 	    pSurf = pTmp3;
2260 	  }
2261 	} else {
2262 	  pTmp3 = NULL;
2263 	}
2264 
2265 
2266 	dest.x = pCityWindow->size.x + adj_size(212) - pSurf->w - adj_size(2);
2267 	i = dest.y;
2268 	dest.y += (pIcons->pMale_Happy->h - count) / 2;
2269 
2270 
2271 	if (pTmp1) { /* Temple */
2272 	  alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest);
2273 	  dest.y += (pTmp1->h + 1);
2274 	}
2275 
2276 	if (pTmp2) { /* Colosseum */
2277 	  alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest);
2278 	  dest.y += (pTmp2->h + 1);
2279 	}
2280 
2281 	if (pTmp3) { /* Cathedral */
2282 	  alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest);
2283 	  /*dest.y += (pTmp3->h + 1); */
2284 	}
2285 
2286 
2287 	FREESURFACE(pTmp1);
2288 	FREESURFACE(pTmp2);
2289 	FREESURFACE(pTmp3);
2290 	dest.y = i;
2291 #endif
2292       }
2293 
2294       if (j == 3) { /* police effect */
2295 	dest.x = pCityWindow->size.x + adj_size(187) - pIcons->pPolice->w - adj_size(5);
2296 	i = dest.y;
2297 	dest.y +=
2298 	    (pIcons->pMale_Happy->h - pIcons->pPolice->h) / 2;
2299 	alphablit(pIcons->pPolice, NULL, pCityWindow->dst->surface, &dest);
2300 	dest.y = i;
2301       }
2302 
2303       if (j == 4) { /* wonders effect */
2304 	count = 0;
2305 
2306         get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2307         effect_list_iterate(sources, psource) {
2308 
2309           pTmp = get_building_surface(get_building_for_effect( psource->type));
2310           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2311 
2312 	  count += (pTmp->h + 1);
2313 
2314           if (!pSurf) {
2315 	    pSurf = pTmp;
2316 	  } else {
2317             FREESURFACE(pTmp);
2318           }
2319 
2320         } effect_list_iterate_end;
2321 
2322         effect_list_clear(sources);
2323 
2324         get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2325 
2326         effect_list_iterate(sources, psource) {
2327 
2328           pTmp = get_building_surface(get_building_for_effect(psource->type));
2329           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2330 	  count += (pTmp->h + 1);
2331 
2332           if (!pSurf) {
2333 	    pSurf = pTmp;
2334 	  } else {
2335             FREESURFACE(pTmp);
2336           }
2337 
2338         } effect_list_iterate_end;
2339 
2340         effect_list_clear(sources);
2341 
2342         get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2343 
2344         effect_list_iterate(sources, psource) {
2345 
2346           pTmp = get_building_surface(get_building_for_effect(psource->type));
2347           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2348 
2349 	  count += (pTmp->h + 1);
2350 
2351           FREESURFACE(pTmp);
2352 
2353         } effect_list_iterate_end;
2354 
2355         effect_list_clear(sources);
2356 
2357 
2358 	dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2359 	i = dest.y;
2360 	dest.y += (pIcons->pMale_Happy->h - count) / 2;
2361 
2362         FREESURFACE(pSurf);
2363 
2364         get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2365 
2366         effect_list_iterate(sources, psource) {
2367 
2368           pTmp = get_building_surface(get_building_for_effect(psource->type));
2369           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2370 
2371           alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2372 	  dest.y += (pTmp->h + 1);
2373 
2374           FREESURFACE(pTmp);
2375 
2376         } effect_list_iterate_end;
2377         effect_list_clear(sources);
2378 
2379         get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2380 
2381         effect_list_iterate(sources, psource) {
2382 
2383           pTmp = get_building_surface(get_building_for_effect(psource->type));
2384           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2385 
2386 	  alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2387 	  dest.y += (pTmp->h + 1);
2388 
2389           FREESURFACE(pTmp);
2390 
2391         } effect_list_iterate_end;
2392         effect_list_clear(sources);
2393 
2394         get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2395 
2396         effect_list_iterate(sources, psource) {
2397 
2398           pTmp = get_building_surface(get_building_for_effect(psource->type));
2399           pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2400 
2401 	  alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2402 	  dest.y += (pTmp->h + 1);
2403 
2404           FREESURFACE(pTmp);
2405 
2406         } effect_list_iterate_end;
2407         effect_list_clear(sources);
2408 
2409 	dest.y = i;
2410 
2411         /* TODO: check if code replacement above is correct */
2412 #if 0
2413 	if (city_affected_by_wonder(pCity, B_CURE)) {
2414 	  pTmp1 =
2415 	    zoomSurface(GET_SURF(improvement_by_number(B_CURE)->sprite),
2416 			0.5, 0.5, 1);
2417 	  count += (pTmp1->h + 1);
2418 	  pSurf = pTmp1;
2419 	} else {
2420 	  pTmp1 = NULL;
2421 	}
2422 
2423 	if (city_affected_by_wonder(pCity, B_SHAKESPEARE)) {
2424 	  pTmp2 = zoomSurface(
2425 	  	GET_SURF(improvement_by_number(B_SHAKESPEARE)->sprite),
2426 			      0.5, 0.5, 1);
2427 	  count += (pTmp2->h + 1);
2428 	  if (!pSurf) {
2429 	    pSurf = pTmp2;
2430 	  }
2431 	} else {
2432 	  pTmp2 = NULL;
2433 	}
2434 
2435 	if (city_affected_by_wonder(pCity, B_BACH)) {
2436 	  pTmp3 =
2437 	    zoomSurface(GET_SURF(improvement_by_number(B_BACH)->sprite),
2438 			0.5, 0.5, 1);
2439 	  count += (pTmp3->h + 1);
2440 	  if (!pSurf) {
2441 	    pSurf = pTmp3;
2442 	  }
2443 	} else {
2444 	  pTmp3 = NULL;
2445 	}
2446 
2447 	if (city_affected_by_wonder(pCity, B_HANGING)) {
2448 	  pTmp4 =
2449 	    zoomSurface(GET_SURF(improvement_by_number(B_HANGING)->sprite),
2450 			0.5, 0.5, 1);
2451 	  count += (pTmp4->h + 1);
2452 	  if (!pSurf) {
2453 	    pSurf = pTmp4;
2454 	  }
2455 	} else {
2456 	  pTmp4 = NULL;
2457 	}
2458 
2459 	dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2460 	i = dest.y;
2461 	dest.y += (pIcons->pMale_Happy->h - count) / 2;
2462 
2463 
2464 	if (pTmp1) { /* Cure of Cancer */
2465 	  alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest);
2466 	  dest.y += (pTmp1->h + 1);
2467 	}
2468 
2469 	if (pTmp2) { /* Shakespeare Theater */
2470 	  alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest);
2471 	  dest.y += (pTmp2->h + 1);
2472 	}
2473 
2474 	if (pTmp3) { /* J. S. Bach ... */
2475 	  alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest);
2476 	  dest.y += (pTmp3->h + 1);
2477 	}
2478 
2479 	if (pTmp4) { /* Hanging Gardens */
2480 	  alphablit(pTmp4, NULL, pCityWindow->dst->surface, &dest);
2481 	  /*dest.y += (pTmp4->h + 1); */
2482 	}
2483 
2484 	FREESURFACE(pTmp1);
2485 	FREESURFACE(pTmp2);
2486 	FREESURFACE(pTmp3);
2487 	FREESURFACE(pTmp4);
2488 	dest.y = i;
2489 #endif /* 0 */
2490       }
2491 
2492       dest.x = pCityWindow->size.x + adj_size(10);
2493       dest.y += pIcons->pMale_Happy->h + adj_size(5);
2494 
2495     }
2496   }
2497 
2498   effect_list_destroy(sources);
2499 }
2500 
2501 /**************************************************************************
2502   Redraw the dialog.
2503 **************************************************************************/
redraw_city_dialog(struct city * pCity)2504 static void redraw_city_dialog(struct city *pCity)
2505 {
2506   char cBuf[40];
2507   int i, step, count, limit;
2508   int cost = 0;
2509   SDL_Rect dest;
2510   struct widget *pWindow = pCityDlg->pEndCityWidgetList;
2511   SDL_Surface *pBuf = NULL, *pBuf2 = NULL;
2512   SDL_String16 *pStr = NULL;
2513   int spe, spe_max;
2514 
2515   refresh_city_names(pCity);
2516 
2517   if ((city_unhappy(pCity) || city_celebrating(pCity) || city_happy(pCity) ||
2518       cma_is_city_under_agent(pCity, NULL))
2519       ^ ((SDL_Client_Flags & CF_CITY_STATUS_SPECIAL) == CF_CITY_STATUS_SPECIAL)) {
2520     /* city status was changed : NORMAL <-> DISORDER, HAPPY, CELEBR. */
2521 
2522     SDL_Client_Flags ^= CF_CITY_STATUS_SPECIAL;
2523 
2524 #if 0
2525     /* upd. resource map */
2526     FREESURFACE(pCityDlg->pResource_Map->theme);
2527     pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2528 #endif
2529 
2530     /* upd. window title */
2531     rebuild_citydlg_title_str(pCityDlg->pEndCityWidgetList, pCity);
2532   }
2533 
2534   /* update resource map */
2535   FREESURFACE(pCityDlg->pResource_Map->theme);
2536   pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2537 
2538   /* redraw city dlg */
2539   redraw_group(pCityDlg->pBeginCityWidgetList,
2540 	       			pCityDlg->pEndCityWidgetList, 0);
2541 
2542   /* ================================================================= */
2543   fc_snprintf(cBuf, sizeof(cBuf), _("City map"));
2544 
2545   pStr = create_str16_from_char(cBuf, adj_font(10));
2546   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2547   pStr->style |= TTF_STYLE_BOLD;
2548 
2549   pBuf = create_text_surf_from_str16(pStr);
2550 
2551   dest.x = pWindow->size.x + adj_size(196) + (adj_size(132) - pBuf->w) / 2;
2552   dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2553 
2554   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2555 
2556   FREESURFACE(pBuf);
2557 
2558   fc_snprintf(cBuf, sizeof(cBuf), _("Citizens"));
2559 
2560   copy_chars_to_string16(pStr, cBuf);
2561   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2562 
2563   pBuf = create_text_surf_from_str16(pStr);
2564 
2565   dest.x = pWindow->size.x + adj_size(344) + (adj_size(146) - pBuf->w) / 2;
2566   dest.y = pWindow->size.y + adj_size(47) + (adj_size(13) - pBuf->h) / 2;
2567 
2568   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2569 
2570   FREESURFACE(pBuf);
2571 
2572   fc_snprintf(cBuf, sizeof(cBuf), _("City improvements"));
2573 
2574   copy_chars_to_string16(pStr, cBuf);
2575   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2576 
2577   pBuf = create_text_surf_from_str16(pStr);
2578 
2579   dest.x = pWindow->size.x + adj_size(504) + (adj_size(132) - pBuf->w) / 2;
2580   dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2581 
2582   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2583 
2584   FREESURFACE(pBuf);
2585   /* ================================================================= */
2586   /* food label */
2587   fc_snprintf(cBuf, sizeof(cBuf), _("Food: %d per turn"),
2588 	      pCity->prod[O_FOOD]);
2589 
2590   copy_chars_to_string16(pStr, cBuf);
2591 
2592   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOODPERTURN);
2593 
2594   pBuf = create_text_surf_from_str16(pStr);
2595 
2596   dest.x = pWindow->size.x + adj_size(200);
2597   dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2598 
2599   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2600 
2601   FREESURFACE(pBuf);
2602 
2603   /* draw food income */
2604   dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pIcons->pBIG_Food->h) / 2;
2605   dest.x = pWindow->size.x + adj_size(203);
2606 
2607   if (pCity->surplus[O_FOOD] >= 0) {
2608     count = pCity->prod[O_FOOD] - pCity->surplus[O_FOOD];
2609   } else {
2610     count = pCity->prod[O_FOOD];
2611   }
2612 
2613   if (((pIcons->pBIG_Food->w + 1) * count) > adj_size(200)) {
2614     step = (adj_size(200) - pIcons->pBIG_Food->w) / (count - 1);
2615   } else {
2616     step = pIcons->pBIG_Food->w + 1;
2617   }
2618 
2619   for (i = 0; i < count; i++) {
2620     alphablit(pIcons->pBIG_Food, NULL, pWindow->dst->surface, &dest);
2621     dest.x += step;
2622   }
2623 
2624   fc_snprintf(cBuf, sizeof(cBuf), Q_("?food:Surplus: %d"),
2625 					      pCity->surplus[O_FOOD]);
2626 
2627   copy_chars_to_string16(pStr, cBuf);
2628   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOOD_SURPLUS);
2629 
2630   pBuf = create_text_surf_from_str16(pStr);
2631 
2632   dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2633   dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2634 
2635   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2636 
2637   FREESURFACE(pBuf);
2638 
2639   /* draw surplus of food */
2640   if (pCity->surplus[O_FOOD]) {
2641 
2642     if (pCity->surplus[O_FOOD] > 0) {
2643       count = pCity->surplus[O_FOOD];
2644       pBuf = pIcons->pBIG_Food;
2645     } else {
2646       count = -1 * pCity->surplus[O_FOOD];
2647       pBuf = pIcons->pBIG_Food_Corr;
2648     }
2649 
2650     dest.x = pWindow->size.x + adj_size(423);
2651     dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pBuf->h) / 2;
2652 
2653     /*if ( ((pBuf->w + 1) * count ) > 30 ) */
2654     if (count > 2) {
2655       if (count < 18) {
2656 	step = (adj_size(30) - pBuf->w) / (count - 1);
2657       } else {
2658 	step = 1;
2659 	count = 17;
2660       }
2661     } else {
2662       step = pBuf->w + 1;
2663     }
2664 
2665     for (i = 0; i < count; i++) {
2666       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2667       dest.x -= step;
2668     }
2669   }
2670   /* ================================================================= */
2671   /* productions label */
2672   fc_snprintf(cBuf, sizeof(cBuf), _("Production: %d (%d) per turn"),
2673 	      pCity->surplus[O_SHIELD] ,
2674 		  pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD]);
2675 
2676   copy_chars_to_string16(pStr, cBuf);
2677   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PROD);
2678 
2679   pBuf = create_text_surf_from_str16(pStr);
2680 
2681   dest.x = pWindow->size.x + adj_size(200);
2682   dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2683 
2684   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2685 
2686   FREESURFACE(pBuf);
2687 
2688   /* draw productions schields */
2689   if (pCity->surplus[O_SHIELD]) {
2690 
2691     if (pCity->surplus[O_SHIELD] > 0) {
2692       count = pCity->surplus[O_SHIELD] + pCity->waste[O_SHIELD];
2693       pBuf = pIcons->pBIG_Shield;
2694     } else {
2695       count = -1 * pCity->surplus[O_SHIELD];
2696       pBuf = pIcons->pBIG_Shield_Corr;
2697     }
2698 
2699     dest.y = pWindow->size.y + adj_size(281) + (adj_size(16) - pBuf->h) / 2;
2700     dest.x = pWindow->size.x + adj_size(203);
2701 
2702     if ((pBuf->w * count) > adj_size(200)) {
2703       step = (adj_size(200) - pBuf->w) / (count - 1);
2704     } else {
2705       step = pBuf->w;
2706     }
2707 
2708     for (i = 0; i < count; i++) {
2709       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2710       dest.x += step;
2711       if(i > pCity->surplus[O_SHIELD]) {
2712 	pBuf = pIcons->pBIG_Shield_Corr;
2713       }
2714     }
2715   }
2716 
2717   /* support shields label */
2718   fc_snprintf(cBuf, sizeof(cBuf), Q_("?production:Support: %d"),
2719 	  pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD] - pCity->surplus[O_SHIELD]);
2720 
2721   copy_chars_to_string16(pStr, cBuf);
2722   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SUPPORT);
2723 
2724   pBuf = create_text_surf_from_str16(pStr);
2725 
2726   dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2727   dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2728 
2729   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2730 
2731   FREESURFACE(pBuf);
2732 
2733   /* draw support shields */
2734   if (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]) {
2735     dest.x = pWindow->size.x + adj_size(423);
2736     dest.y =
2737 	pWindow->size.y + adj_size(281) + (adj_size(16) - pIcons->pBIG_Shield->h) / 2;
2738 
2739     if ((pIcons->pBIG_Shield->w + 1) * (pCity->prod[O_SHIELD] -
2740 					    pCity->surplus[O_SHIELD]) > adj_size(30)) {
2741       step =
2742 	  (adj_size(30) - pIcons->pBIG_Food->w) / (pCity->prod[O_SHIELD] -
2743 					     pCity->surplus[O_SHIELD] - 1);
2744     } else {
2745       step = pIcons->pBIG_Shield->w + 1;
2746     }
2747 
2748     for (i = 0; i < (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]); i++) {
2749       alphablit(pIcons->pBIG_Shield, NULL, pWindow->dst->surface, &dest);
2750       dest.x -= step;
2751     }
2752   }
2753   /* ================================================================= */
2754 
2755   /* trade label */
2756   fc_snprintf(cBuf, sizeof(cBuf), _("Trade: %d per turn"),
2757 	      pCity->surplus[O_TRADE]);
2758 
2759   copy_chars_to_string16(pStr, cBuf);
2760   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
2761 
2762   pBuf = create_text_surf_from_str16(pStr);
2763 
2764   dest.x = pWindow->size.x + adj_size(200);
2765   dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2766 
2767   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2768 
2769   FREESURFACE(pBuf);
2770 
2771   /* draw total (trade - corruption) */
2772   if (pCity->surplus[O_TRADE]) {
2773     dest.y =
2774 	pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2775     dest.x = pWindow->size.x + adj_size(203);
2776 
2777     if (((pIcons->pBIG_Trade->w + 1) * pCity->surplus[O_TRADE]) > adj_size(200)) {
2778       step = (adj_size(200) - pIcons->pBIG_Trade->w) / (pCity->surplus[O_TRADE] - 1);
2779     } else {
2780       step = pIcons->pBIG_Trade->w + 1;
2781     }
2782 
2783     for (i = 0; i < pCity->surplus[O_TRADE]; i++) {
2784       alphablit(pIcons->pBIG_Trade, NULL, pWindow->dst->surface, &dest);
2785       dest.x += step;
2786     }
2787   }
2788 
2789   /* corruption label */
2790   fc_snprintf(cBuf, sizeof(cBuf), _("Corruption: %d"),
2791 	      pCity->waste[O_TRADE]);
2792 
2793   copy_chars_to_string16(pStr, cBuf);
2794   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_CORRUPTION);
2795 
2796   pBuf = create_text_surf_from_str16(pStr);
2797 
2798   dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2799   dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2800 
2801   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2802 
2803   FREESURFACE(pBuf);
2804 
2805   /* draw corruption */
2806   if (pCity->waste[O_TRADE] > 0) {
2807     dest.x = pWindow->size.x + adj_size(423);
2808     dest.y =
2809 	pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2810 
2811     if (((pIcons->pBIG_Trade_Corr->w + 1) * pCity->waste[O_TRADE]) > adj_size(30)) {
2812       step =
2813 	  (adj_size(30) - pIcons->pBIG_Trade_Corr->w) / (pCity->waste[O_TRADE] - 1);
2814     } else {
2815       step = pIcons->pBIG_Trade_Corr->w + 1;
2816     }
2817 
2818     for (i = 0; i < pCity->waste[O_TRADE]; i++) {
2819       alphablit(pIcons->pBIG_Trade_Corr, NULL, pWindow->dst->surface,
2820 		      &dest);
2821       dest.x -= step;
2822     }
2823 
2824   }
2825   /* ================================================================= */
2826   /* gold label */
2827   fc_snprintf(cBuf, sizeof(cBuf), _("Gold: %d (%d) per turn"),
2828 	      pCity->surplus[O_GOLD], pCity->prod[O_GOLD]);
2829 
2830   copy_chars_to_string16(pStr, cBuf);
2831   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2832 
2833   pBuf = create_text_surf_from_str16(pStr);
2834 
2835   dest.x = pWindow->size.x + adj_size(200);
2836   dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2837 
2838   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2839 
2840   FREESURFACE(pBuf);
2841 
2842   /* draw coins */
2843   count = pCity->surplus[O_GOLD];
2844   if (count) {
2845 
2846     if (count > 0) {
2847       pBuf = pIcons->pBIG_Coin;
2848     } else {
2849       count *= -1;
2850       pBuf = pIcons->pBIG_Coin_Corr;
2851     }
2852 
2853     dest.y = pWindow->size.y + adj_size(359) + (adj_size(16) - pBuf->h) / 2;
2854     dest.x = pWindow->size.x + adj_size(203);
2855 
2856     if ((pBuf->w * count) > adj_size(110)) {
2857       step = (adj_size(110) - pBuf->w) / (count - 1);
2858       if (!step) {
2859 	step = 1;
2860 	count = 97;
2861       }
2862     } else {
2863       step = pBuf->w;
2864     }
2865 
2866     for (i = 0; i < count; i++) {
2867       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2868       dest.x += step;
2869     }
2870 
2871   }
2872 
2873   /* upkeep label */
2874   fc_snprintf(cBuf, sizeof(cBuf), _("Upkeep: %d"),
2875 	      pCity->prod[O_GOLD] - pCity->surplus[O_GOLD]);
2876 
2877   copy_chars_to_string16(pStr, cBuf);
2878   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_UPKEEP);
2879 
2880   pBuf = create_text_surf_from_str16(pStr);
2881 
2882   dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2883   dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2884 
2885   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2886 
2887   FREESURFACE(pBuf);
2888 
2889   /* draw upkeep */
2890   count = pCity->surplus[O_GOLD];
2891   if (pCity->prod[O_GOLD] - count) {
2892 
2893     dest.x = pWindow->size.x + adj_size(423);
2894     dest.y = pWindow->size.y + adj_size(359)
2895       + (adj_size(16) - pIcons->pBIG_Coin_UpKeep->h) / 2;
2896 
2897     if (((pIcons->pBIG_Coin_UpKeep->w + 1) *
2898 	 (pCity->prod[O_GOLD] - count)) > adj_size(110)) {
2899       step = (adj_size(110) - pIcons->pBIG_Coin_UpKeep->w) /
2900 	  (pCity->prod[O_GOLD] - count - 1);
2901     } else {
2902       step = pIcons->pBIG_Coin_UpKeep->w + 1;
2903     }
2904 
2905     for (i = 0; i < (pCity->prod[O_GOLD] - count); i++) {
2906       alphablit(pIcons->pBIG_Coin_UpKeep, NULL, pWindow->dst->surface,
2907 		      &dest);
2908       dest.x -= step;
2909     }
2910   }
2911   /* ================================================================= */
2912   /* science label */
2913   fc_snprintf(cBuf, sizeof(cBuf), _("Science: %d per turn"),
2914 	      pCity->prod[O_SCIENCE]);
2915 
2916   copy_chars_to_string16(pStr, cBuf);
2917   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SCIENCE);
2918 
2919   pBuf = create_text_surf_from_str16(pStr);
2920 
2921   dest.x = pWindow->size.x + adj_size(200);
2922   dest.y = pWindow->size.y + adj_size(376) + (adj_size(15) - pBuf->h) / 2;
2923 
2924   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2925 
2926   FREESURFACE(pBuf);
2927 
2928   /* draw colb */
2929   count = pCity->prod[O_SCIENCE];
2930   if (count) {
2931 
2932     dest.y =
2933 	pWindow->size.y + adj_size(394) + (adj_size(16) - pIcons->pBIG_Colb->h) / 2;
2934     dest.x = pWindow->size.x + adj_size(203);
2935 
2936     if ((pIcons->pBIG_Colb->w * count) > adj_size(235)) {
2937       step = (adj_size(235) - pIcons->pBIG_Colb->w) / (count - 1);
2938       if (!step) {
2939 	step = 1;
2940 	count = 222;
2941       }
2942     } else {
2943       step = pIcons->pBIG_Colb->w;
2944     }
2945 
2946     for (i = 0; i < count; i++) {
2947       alphablit(pIcons->pBIG_Colb, NULL, pWindow->dst->surface, &dest);
2948       dest.x += step;
2949     }
2950   }
2951   /* ================================================================= */
2952   /* luxury label */
2953   fc_snprintf(cBuf, sizeof(cBuf), _("Luxury: %d per turn"),
2954 	      pCity->prod[O_LUXURY]);
2955 
2956   copy_chars_to_string16(pStr, cBuf);
2957   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2958 
2959   pBuf = create_text_surf_from_str16(pStr);
2960 
2961   dest.x = pWindow->size.x + adj_size(200);
2962   dest.y = pWindow->size.y + adj_size(412) + (adj_size(15) - pBuf->h) / 2;
2963 
2964   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2965 
2966   FREESURFACE(pBuf);
2967 
2968   /* draw luxury */
2969   if (pCity->prod[O_LUXURY]) {
2970 
2971     dest.y =
2972 	pWindow->size.y + adj_size(429) + (adj_size(16) - pIcons->pBIG_Luxury->h) / 2;
2973     dest.x = pWindow->size.x + adj_size(203);
2974 
2975     if ((pIcons->pBIG_Luxury->w * pCity->prod[O_LUXURY]) > adj_size(235)) {
2976       step =
2977 	  (adj_size(235) - pIcons->pBIG_Luxury->w) / (pCity->prod[O_LUXURY] - 1);
2978     } else {
2979       step = pIcons->pBIG_Luxury->w;
2980     }
2981 
2982     for (i = 0; i < pCity->prod[O_LUXURY]; i++) {
2983       alphablit(pIcons->pBIG_Luxury, NULL, pWindow->dst->surface, &dest);
2984       dest.x += step;
2985     }
2986   }
2987   /* ================================================================= */
2988   /* turns to grow label */
2989   count = city_turns_to_grow(pCity);
2990   if (count == 0) {
2991     fc_snprintf(cBuf, sizeof(cBuf), _("City growth: blocked"));
2992   } else if (count == FC_INFINITY) {
2993     fc_snprintf(cBuf, sizeof(cBuf), _("City growth: never"));
2994   } else if (count < 0) {
2995     /* turns until famine */
2996     fc_snprintf(cBuf, sizeof(cBuf),
2997 		_("City shrinks: %d %s"), abs(count),
2998 		PL_("turn", "turns", abs(count)));
2999   } else {
3000     fc_snprintf(cBuf, sizeof(cBuf),
3001 		_("City growth: %d %s"), count,
3002 		PL_("turn", "turns", count));
3003   }
3004 
3005   copy_chars_to_string16(pStr, cBuf);
3006 
3007   pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GROWTH);
3008 
3009   pBuf = create_text_surf_from_str16(pStr);
3010 
3011   dest.x = pWindow->size.x + adj_size(445) + (adj_size(192) - pBuf->w) / 2;
3012   dest.y = pWindow->size.y + adj_size(227);
3013 
3014   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3015 
3016   FREESURFACE(pBuf);
3017 
3018 
3019   count = (city_granary_size(city_size_get(pCity))) / 10;
3020 
3021   if (count > 12) {
3022     step = (adj_size(168) - pIcons->pBIG_Food->h) / adj_size((11 + count - 12));
3023     i = (count - 1) * step + 14;
3024     count = 12;
3025   } else {
3026     step = pIcons->pBIG_Food->h;
3027     i = count * step;
3028   }
3029 
3030   /* food stock */
3031 
3032     /* FIXME: check if this code replacement is correct */
3033     /*  if (city_has_building(pCity, improvement_by_number(B_GRANARY)) */
3034     /*      || city_affected_by_wonder(pCity, B_PYRAMIDS)) { */
3035 
3036     if (get_city_bonus(pCity, EFT_GROWTH_FOOD) > 0) {
3037 
3038     /* with granary */
3039     /* stocks label */
3040     copy_chars_to_string16(pStr, _("Stock"));
3041     pBuf = create_text_surf_from_str16(pStr);
3042 
3043     dest.x = pWindow->size.x + adj_size(461) + (adj_size(76) - pBuf->w) / 2;
3044     dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3045 
3046     alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3047 
3048     FREESURFACE(pBuf);
3049 
3050     /* granary label */
3051     copy_chars_to_string16(pStr, _("Granary"));
3052     pBuf = create_text_surf_from_str16(pStr);
3053 
3054     dest.x = pWindow->size.x + adj_size(549) + (adj_size(76) - pBuf->w) / 2;
3055     dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3056 
3057     alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3058 
3059     FREESURFACE(pBuf);
3060 
3061     /* draw bcgd granary */
3062     dest.x = pWindow->size.x + adj_size(462);
3063     dest.y = pWindow->size.y + adj_size(260);
3064     dest.w = 70 + 4;
3065     dest.h = i + 4;
3066 
3067     SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_GRANARY));
3068 
3069     putframe(pWindow->dst->surface,
3070              dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3071              get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3072 
3073     /* draw bcgd stocks*/
3074     dest.x = pWindow->size.x + adj_size(550);
3075     dest.y = pWindow->size.y + adj_size(260);
3076 
3077     SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_STOCKS));
3078 
3079     putframe(pWindow->dst->surface,
3080              dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3081              get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3082 
3083     /* draw stocks icons */
3084     cost = city_granary_size(city_size_get(pCity));
3085     if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3086       count = cost;
3087     } else {
3088       if(pCity->surplus[O_FOOD] < 0) {
3089         count = pCity->food_stock;
3090       } else {
3091 	count = pCity->food_stock + pCity->surplus[O_FOOD];
3092       }
3093     }
3094     cost /= 2;
3095 
3096     if(pCity->surplus[O_FOOD] < 0) {
3097       limit = pCity->food_stock + pCity->surplus[O_FOOD];
3098       if(limit < 0) {
3099 	limit = 0;
3100       }
3101     } else {
3102       limit = 0xffff;
3103     }
3104 
3105     dest.x += 2;
3106     dest.y += 2;
3107     i = 0;
3108     pBuf = pIcons->pBIG_Food;
3109     while (count && cost) {
3110       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3111       dest.x += pBuf->w;
3112       count--;
3113       cost--;
3114       i++;
3115       if (dest.x > pWindow->size.x + adj_size(620)) {
3116 	dest.x = pWindow->size.x + adj_size(552);
3117 	dest.y += step;
3118       }
3119       if(i > limit - 1) {
3120 	pBuf = pIcons->pBIG_Food_Corr;
3121       } else {
3122         if(i > pCity->food_stock - 1)
3123         {
3124 	  pBuf = pIcons->pBIG_Food_Surplus;
3125         }
3126       }
3127     }
3128     /* draw granary icons */
3129     dest.x = pWindow->size.x + adj_size(462) + adj_size(2);
3130     dest.y = pWindow->size.y + adj_size(260) + adj_size(2);
3131 
3132     while (count) {
3133       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3134       dest.x += pBuf->w;
3135       count--;
3136       i++;
3137       if (dest.x > pWindow->size.x + adj_size(532)) {
3138 	dest.x = pWindow->size.x + adj_size(464);
3139 	dest.y += step;
3140       }
3141       if(i > limit - 1) {
3142 	pBuf = pIcons->pBIG_Food_Corr;
3143       } else {
3144         if(i > pCity->food_stock - 1)
3145         {
3146 	  pBuf = pIcons->pBIG_Food_Surplus;
3147         }
3148       }
3149     }
3150 
3151   } else {
3152     /* without granary */
3153     /* stocks label */
3154     copy_chars_to_string16(pStr, _("Stock"));
3155     pBuf = create_text_surf_from_str16(pStr);
3156 
3157     dest.x = pWindow->size.x + adj_size(461) + (adj_size(144) - pBuf->w) / 2;
3158     dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3159 
3160     alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3161     FREESURFACE(pBuf);
3162 
3163     /* food stock */
3164 
3165     /* draw bcgd */
3166     dest.x = pWindow->size.x + adj_size(462);
3167     dest.y = pWindow->size.y + adj_size(260);
3168     dest.w = adj_size(144);
3169     dest.h = i + adj_size(4);
3170 
3171     SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_FOODSTOCK));
3172 
3173     putframe(pWindow->dst->surface,
3174              dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3175              get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3176 
3177     /* draw icons */
3178     cost = city_granary_size(city_size_get(pCity));
3179     if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3180       count = cost;
3181     } else {
3182       if(pCity->surplus[O_FOOD] < 0) {
3183         count = pCity->food_stock;
3184       } else {
3185 	count = pCity->food_stock + pCity->surplus[O_FOOD];
3186       }
3187     }
3188 
3189     if(pCity->surplus[O_FOOD] < 0) {
3190       limit = pCity->food_stock + pCity->surplus[O_FOOD];
3191       if(limit < 0) {
3192 	limit = 0;
3193       }
3194     } else {
3195       limit = 0xffff;
3196     }
3197 
3198     dest.x += adj_size(2);
3199     dest.y += adj_size(2);
3200     i = 0;
3201     pBuf = pIcons->pBIG_Food;
3202     while (count) {
3203       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3204       dest.x += pBuf->w;
3205       count--;
3206       i++;
3207       if (dest.x > pWindow->size.x + adj_size(602)) {
3208 	dest.x = pWindow->size.x + adj_size(464);
3209 	dest.y += step;
3210       }
3211       if(i > limit - 1) {
3212 	pBuf = pIcons->pBIG_Food_Corr;
3213       } else {
3214         if(i > pCity->food_stock - 1)
3215         {
3216 	  pBuf = pIcons->pBIG_Food_Surplus;
3217         }
3218       }
3219     }
3220   }
3221   /* ================================================================= */
3222 
3223   /* draw productions shields progress */
3224   if (VUT_UTYPE == pCity->production.kind) {
3225     struct unit_type *pUnitType = pCity->production.value.utype;
3226     cost = utype_build_shield_cost(pUnitType);
3227     count = cost / 10;
3228 
3229     copy_chars_to_string16(pStr, utype_name_translation(pUnitType));
3230     pBuf = create_text_surf_from_str16(pStr);
3231 
3232     pBuf2 = get_unittype_surface(pUnitType, direction8_invalid());
3233     pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h), DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3234 
3235     /* blit unit icon */
3236     dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3237     dest.y = pWindow->size.y + adj_size(233);
3238 
3239     alphablit(pBuf2, NULL, pWindow->dst->surface, &dest);
3240 
3241     dest.y += (pBuf2->h - pBuf->h) / 2;
3242     dest.x += pBuf2->w + adj_size(5);
3243 
3244   } else {
3245     struct impr_type *pImprove = pCity->production.value.building;
3246 
3247     if (improvement_has_flag(pImprove, IF_GOLD)) {
3248 
3249       if (pCityDlg->pBuy_Button
3250 	 && get_wstate(pCityDlg->pBuy_Button) != FC_WS_DISABLED) {
3251 	set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
3252 	widget_redraw(pCityDlg->pBuy_Button);
3253       }
3254 
3255       /* You can't see capitalization progres */
3256       count = 0;
3257 
3258     } else {
3259 
3260       if (city_can_buy(pCity) && pCityDlg->pBuy_Button
3261 	 && (get_wstate(pCityDlg->pBuy_Button) == FC_WS_DISABLED)) {
3262 	set_wstate(pCityDlg->pBuy_Button, FC_WS_NORMAL);
3263 	widget_redraw(pCityDlg->pBuy_Button);
3264       }
3265 
3266       cost = impr_build_shield_cost(pImprove);
3267       count = cost / 10;
3268 
3269     }
3270 
3271     copy_chars_to_string16(pStr, improvement_name_translation(pImprove));
3272     pBuf = create_text_surf_from_str16(pStr);
3273 
3274     pBuf2 = get_building_surface(pCity->production.value.building);
3275     pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h), DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3276 
3277     /* blit impr icon */
3278     dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3279     dest.y = pWindow->size.y + adj_size(233);
3280 
3281     alphablit(pBuf2, NULL, pWindow->dst->surface, &dest);
3282 
3283     dest.y += (pBuf2->h - pBuf->h) / 2;
3284     dest.x += pBuf2->w + adj_size(5);
3285   }
3286 
3287   /* blit unit/impr name */
3288   alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3289 
3290   FREESURFACE(pBuf);
3291   FREESURFACE(pBuf2);
3292 
3293   if (count) {
3294     if (count > 11) {
3295       step = (adj_size(154) - pIcons->pBIG_Shield->h) / adj_size((10 + count - 11));
3296 
3297       if(!step) step = 1;
3298 
3299       i = (step * (count - 1)) + pIcons->pBIG_Shield->h;
3300     } else {
3301       step = pIcons->pBIG_Shield->h;
3302       i = count * step;
3303     }
3304 
3305     /* draw sheild stock background */
3306     dest.x = pWindow->size.x + adj_size(28);
3307     dest.y = pWindow->size.y + adj_size(270);
3308     dest.w = adj_size(144);
3309     dest.h = i + adj_size(4);
3310 
3311     SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_SHIELDSTOCK));
3312     putframe(pWindow->dst->surface,
3313              dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3314              get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3315 
3316     /* draw production progres text */
3317     dest.y = pWindow->size.y + adj_size(270) + dest.h + 1;
3318 
3319     if (pCity->shield_stock < cost) {
3320       count = city_production_turns_to_build(pCity, TRUE);
3321       if (count == 999) {
3322         fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3323 		  		pCity->shield_stock, cost,  _("blocked"));
3324       } else {
3325         fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %d %s",
3326 	    pCity->shield_stock, cost, count, PL_("turn", "turns", count));
3327      }
3328    } else {
3329      fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3330 		    		pCity->shield_stock, cost, _("finished"));
3331    }
3332 
3333     copy_chars_to_string16(pStr, cBuf);
3334     pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
3335 
3336     pBuf = create_text_surf_from_str16(pStr);
3337 
3338     dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - pBuf->w) / 2;
3339 
3340     alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3341 
3342     FREESTRING16(pStr);
3343     FREESURFACE(pBuf);
3344 
3345     /* draw sheild stock */
3346     if (pCity->shield_stock + pCity->surplus[O_SHIELD] <= cost) {
3347       count = pCity->shield_stock + pCity->surplus[O_SHIELD];
3348     } else {
3349       count = cost;
3350     }
3351     dest.x = pWindow->size.x + adj_size(29) + adj_size(2);
3352     dest.y = pWindow->size.y + adj_size(270) + adj_size(2);
3353     i = 0;
3354 
3355     pBuf = pIcons->pBIG_Shield;
3356     while (count > 0) {
3357       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3358       dest.x += pBuf->w;
3359       count--;
3360       if (dest.x > pWindow->size.x + adj_size(170)) {
3361 	dest.x = pWindow->size.x + adj_size(31);
3362 	dest.y += step;
3363       }
3364       i++;
3365       if(i > pCity->shield_stock - 1) {
3366 	pBuf = pIcons->pBIG_Shield_Surplus;
3367       }
3368     }
3369   }
3370 
3371   /* count != 0 */
3372   /* ==================================================== */
3373   /* Draw Citizens */
3374   count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
3375            + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
3376            + city_specialists(pCity));
3377 
3378   pBuf = get_citizen_surface(CITIZEN_HAPPY, 0);
3379 
3380   if (count > 13) {
3381     step = (adj_size(440) - pBuf->w) / (adj_size(12 + count - 13));
3382   } else {
3383     step = pBuf->w;
3384   }
3385 
3386   pCityDlg->citizen_step = step;
3387 
3388   dest.x = pWindow->size.x + adj_size(198);
3389   dest.y = pWindow->size.y + pWindow->area.y + adj_size(1) + (adj_size(22) - pBuf->h) / 2;
3390 
3391   pCityDlg->spec_area.x = pWindow->dst->dest_rect.x + dest.x;
3392   pCityDlg->spec_area.y = pWindow->dst->dest_rect.y + dest.y;
3393   pCityDlg->spec_area.w = count * step;
3394   pCityDlg->spec_area.h = pBuf->h;
3395 
3396   if (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]) {
3397     for (i = 0; i < pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]; i++) {
3398       pBuf = adj_surf(get_citizen_surface(CITIZEN_HAPPY, i));
3399 
3400       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3401       dest.x += step;
3402       FREESURFACE(pBuf);
3403     }
3404   }
3405 
3406   if (pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]) {
3407     for (i = 0; i < pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]; i++) {
3408       pBuf = adj_surf(get_citizen_surface(CITIZEN_CONTENT, i));
3409 
3410       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3411       dest.x += step;
3412       FREESURFACE(pBuf);
3413     }
3414   }
3415 
3416   if (pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]) {
3417     for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]; i++) {
3418       pBuf = adj_surf(get_citizen_surface(CITIZEN_UNHAPPY, i));
3419 
3420       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3421       dest.x += step;
3422       FREESURFACE(pBuf);
3423     }
3424   }
3425 
3426   if (pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]) {
3427     for (i = 0; i < pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]; i++) {
3428       pBuf = adj_surf(get_citizen_surface(CITIZEN_ANGRY, i));
3429       alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3430       dest.x += step;
3431       FREESURFACE(pBuf);
3432     }
3433   }
3434 
3435   spe_max = specialist_count();
3436   for (spe = 0; spe < spe_max; spe++) {
3437     if (pCity->specialists[spe] > 0) {
3438       pBuf = adj_surf(get_citizen_surface(CITIZEN_SPECIALIST + spe, i));
3439 
3440       for (i = 0; i < pCity->specialists[spe]; i++) {
3441         alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3442         dest.x += step;
3443       }
3444       FREESURFACE(pBuf);
3445     }
3446   }
3447 
3448   /* ==================================================== */
3449 
3450 
3451   switch (pCityDlg->page) {
3452   case INFO_PAGE:
3453     redraw_info_city_dialog(pWindow, pCity);
3454     break;
3455 
3456   case HAPPINESS_PAGE:
3457     redraw_happyness_city_dialog(pWindow, pCity);
3458     break;
3459 
3460   case ARMY_PAGE:
3461     redraw_army_city_dialog(pWindow, pCity);
3462     break;
3463 
3464   case SUPPORTED_UNITS_PAGE:
3465     redraw_supported_units_city_dialog(pWindow, pCity);
3466     break;
3467 
3468   case MISC_PAGE:
3469     redraw_misc_city_dialog(pWindow, pCity);
3470     break;
3471 
3472   default:
3473     break;
3474 
3475   }
3476 
3477   /* redraw "sell improvement" dialog */
3478   redraw_group(pCityDlg->pBeginCityMenuWidgetList,
3479 	       pCityDlg->pEndCityMenuWidgetList, 0);
3480 
3481   widget_mark_dirty(pWindow);
3482 }
3483 
3484 /* ============================================================== */
3485 
3486 /**************************************************************************
3487   Recreate improvement list for city dialog.
3488 **************************************************************************/
rebuild_imprm_list(struct city * pCity)3489 static void rebuild_imprm_list(struct city *pCity)
3490 {
3491   int count = 0;
3492   struct widget *pWindow = pCityDlg->pEndCityWidgetList;
3493   struct widget *pAdd_Dock, *pBuf, *pLast;
3494   SDL_Surface *pLogo = NULL;
3495   SDL_String16 *pStr = NULL;
3496   struct player *pOwner = city_owner(pCity);
3497   int prev_y = 0;
3498 
3499   if(!pCityDlg->pImprv) {
3500     pCityDlg->pImprv = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3501   }
3502 
3503   /* free old list */
3504   if (pCityDlg->pImprv->pEndWidgetList) {
3505     del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
3506 				       pCityDlg->pImprv->pEndWidgetList);
3507     pCityDlg->pImprv->pEndWidgetList = NULL;
3508     pCityDlg->pImprv->pBeginWidgetList = NULL;
3509     pCityDlg->pImprv->pEndActiveWidgetList = NULL;
3510     pCityDlg->pImprv->pBeginActiveWidgetList = NULL;
3511     pCityDlg->pImprv->pActiveWidgetList = NULL;
3512     FC_FREE(pCityDlg->pImprv->pScroll);
3513   }
3514 
3515   pAdd_Dock = pCityDlg->pAdd_Point;
3516   pBuf = pLast = pAdd_Dock;
3517 
3518   /* allock new */
3519   city_built_iterate(pCity, pImprove) {
3520 
3521     pStr = create_str16_from_char(city_improvement_name_translation(pCity, pImprove), adj_font(10));
3522     pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_IMPR);
3523 
3524     pStr->style |= TTF_STYLE_BOLD;
3525 
3526     pLogo = get_building_surface(pImprove);
3527     pLogo = ResizeSurfaceBox(pLogo, adj_size(22), adj_size(22), 1, TRUE, TRUE);
3528 
3529     pBuf = create_iconlabel(pLogo, pWindow->dst, pStr,
3530 			 (WF_FREE_THEME | WF_RESTORE_BACKGROUND));
3531 
3532     pBuf->size.x = pWindow->size.x + adj_size(450);
3533     pBuf->size.y = pWindow->size.y + adj_size(66) + prev_y;
3534 
3535     prev_y += pBuf->size.h;
3536 
3537     pBuf->size.w = adj_size(165);
3538     pBuf->action = sell_imprvm_dlg_callback;
3539 
3540     if (!pCityDlg->pCity->did_sell
3541         && !is_wonder(pImprove) && (pOwner == client.conn.playing)) {
3542       set_wstate(pBuf, FC_WS_NORMAL);
3543     }
3544 
3545     pBuf->ID = MAX_ID - improvement_number(pImprove) - 3000;
3546     DownAdd(pBuf, pAdd_Dock);
3547     pAdd_Dock = pBuf;
3548 
3549     count++;
3550 
3551     if (count > 7) {
3552       set_wflag(pBuf, WF_HIDDEN);
3553     }
3554 
3555   } city_built_iterate_end;
3556 
3557   if (count) {
3558     pCityDlg->pImprv->pEndWidgetList = pLast->prev;
3559     pCityDlg->pImprv->pEndActiveWidgetList = pCityDlg->pImprv->pEndWidgetList;
3560     pCityDlg->pImprv->pBeginWidgetList = pBuf;
3561     pCityDlg->pImprv->pBeginActiveWidgetList = pCityDlg->pImprv->pBeginWidgetList;
3562 
3563     if (count > 7) {
3564       pCityDlg->pImprv->pActiveWidgetList = pCityDlg->pImprv->pEndActiveWidgetList;
3565 
3566       create_vertical_scrollbar(pCityDlg->pImprv, 1, 7, TRUE, TRUE);
3567 
3568       setup_vertical_scrollbar_area(pCityDlg->pImprv->pScroll,
3569 	                            pWindow->size.x + adj_size(635),
3570                                     pWindow->size.y + adj_size(66),
3571                                     adj_size(155), TRUE);
3572     }
3573   }
3574 }
3575 
3576 /**************************************************************************
3577   Recreate citydialog title.
3578 **************************************************************************/
rebuild_citydlg_title_str(struct widget * pWindow,struct city * pCity)3579 static void rebuild_citydlg_title_str(struct widget *pWindow,
3580                                       struct city *pCity)
3581 {
3582   char cBuf[512];
3583 
3584   fc_snprintf(cBuf, sizeof(cBuf),
3585               _("City of %s (Population %s citizens)"),
3586               city_name_get(pCity),
3587               population_to_text(city_population(pCity)));
3588 
3589   if (city_unhappy(pCity)) {
3590     /* TRANS: preserve leading space */
3591     fc_strlcat(cBuf, _(" - DISORDER"), sizeof(cBuf));
3592   } else {
3593     if (city_celebrating(pCity)) {
3594       /* TRANS: preserve leading space */
3595       fc_strlcat(cBuf, _(" - celebrating"), sizeof(cBuf));
3596     } else {
3597       if (city_happy(pCity)) {
3598         /* TRANS: preserve leading space */
3599 	fc_strlcat(cBuf, _(" - happy"), sizeof(cBuf));
3600       }
3601     }
3602   }
3603 
3604   if (cma_is_city_under_agent(pCity, NULL)) {
3605     /* TRANS: preserve leading space */
3606     fc_strlcat(cBuf, _(" - under Citizen Governor control."), sizeof(cBuf));
3607   }
3608 
3609   copy_chars_to_string16(pWindow->string16, cBuf);
3610 }
3611 
3612 
3613 /* ========================= Public ================================== */
3614 
3615 /**************************************************************************
3616   Pop up (or bring to the front) a dialog for the given city.  It may or
3617   may not be modal.
3618 **************************************************************************/
real_city_dialog_popup(struct city * pCity)3619 void real_city_dialog_popup(struct city *pCity)
3620 {
3621   struct widget *pWindow = NULL, *pBuf = NULL;
3622   SDL_Surface *pLogo = NULL;
3623   SDL_String16 *pStr = NULL;
3624   int cs;
3625   struct player *pOwner = city_owner(pCity);
3626   SDL_Rect area;
3627 
3628   if (pCityDlg) {
3629     return;
3630   }
3631 
3632   menus_update();
3633 
3634   pCityDlg = fc_calloc(1, sizeof(struct city_dialog));
3635   pCityDlg->pCity = pCity;
3636   pCityDlg->page = ARMY_PAGE;
3637 
3638   pStr = create_string16(NULL, 0, adj_font(12));
3639   pStr->style |= TTF_STYLE_BOLD;
3640   pWindow = create_window(NULL, pStr, adj_size(640), adj_size(480), 0);
3641 
3642   rebuild_citydlg_title_str(pWindow, pCity);
3643 
3644   pWindow->action = city_dlg_callback;
3645   set_wstate(pWindow, FC_WS_NORMAL);
3646 
3647   add_to_gui_list(ID_CITY_DLG_WINDOW, pWindow);
3648 
3649   pCityDlg->pEndCityWidgetList = pWindow;
3650 
3651   /* create window background */
3652   pLogo = theme_get_background(theme, BACKGROUND_CITYDLG);
3653   if (resize_window(pWindow, pLogo, NULL, adj_size(640), adj_size(480))) {
3654     FREESURFACE(pLogo);
3655   }
3656 
3657   pLogo = get_city_gfx();
3658   alphablit(pLogo, NULL, pWindow->theme, NULL);
3659 
3660   area = pWindow->area;
3661 
3662   widget_set_position(pWindow,
3663                       (Main.screen->w - pWindow->size.w) / 2,
3664                       (Main.screen->h - pWindow->size.h) / 2);
3665 
3666   /* ============================================================= */
3667 
3668   /* close dialog button */
3669   pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3670                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3671   pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
3672                                             adj_font(12));
3673   pBuf->action = exit_city_dlg_callback;
3674   pBuf->size.x = area.x + area.w - pBuf->size.w;
3675   pBuf->size.y = pWindow->size.y + adj_size(2);
3676   pBuf->key = SDLK_ESCAPE;
3677   set_wstate(pBuf, FC_WS_NORMAL);
3678   add_to_gui_list(ID_CITY_DLG_EXIT_BUTTON, pBuf);
3679 
3680   /* -------- */
3681 
3682   pBuf = create_themeicon(current_theme->Army_Icon, pWindow->dst,
3683                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3684   pBuf->info_label = create_str16_from_char(_("Present units"),
3685                                             adj_font(12));
3686   pBuf->action = army_city_dlg_callback;
3687   pBuf->size.x = area.x + adj_size(2) + ((adj_size(183) - 5 * pBuf->size.w) / 6);
3688   pBuf->size.y = area.y + adj_size(2);
3689   set_wstate(pBuf, FC_WS_NORMAL);
3690   add_to_gui_list(ID_CITY_DLG_ARMY_BUTTON, pBuf);
3691   /* -------- */
3692 
3693   pBuf = create_themeicon(current_theme->Support_Icon, pWindow->dst,
3694                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3695   pBuf->info_label = create_str16_from_char(_("Supported units"),
3696                                             adj_font(12));
3697   pBuf->action = supported_unit_city_dlg_callback;
3698   pBuf->size.x =
3699       area.x + adj_size(2) + 2 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + pBuf->size.w;
3700   pBuf->size.y = area.y + adj_size(2);
3701 
3702   set_wstate(pBuf, FC_WS_NORMAL);
3703   add_to_gui_list(ID_CITY_DLG_SUPPORT_BUTTON, pBuf);
3704   /* -------- */
3705 
3706   pBuf = create_themeicon(current_theme->Happy_Icon, pWindow->dst,
3707                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3708   pBuf->info_label = create_str16_from_char(_("Happiness"), adj_font(12));
3709   pBuf->action = happy_city_dlg_callback;
3710   pBuf->size.x =
3711       area.x + adj_size(2) + 3 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 2 * pBuf->size.w;
3712   pBuf->size.y = area.y + adj_size(2);
3713   set_wstate(pBuf, FC_WS_NORMAL);
3714   add_to_gui_list(ID_CITY_DLG_HAPPY_BUTTON, pBuf);
3715   /* -------- */
3716 
3717   pBuf = create_themeicon(current_theme->INFO_Icon, pWindow->dst,
3718                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3719   pBuf->info_label = create_str16_from_char(_("City info"), adj_font(12));
3720   pBuf->action = info_city_dlg_callback;
3721   pBuf->size.x =
3722       area.x + adj_size(4) + 4 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 3 * pBuf->size.w;
3723   pBuf->size.y = area.y + adj_size(2);
3724   set_wstate(pBuf, FC_WS_NORMAL);
3725   add_to_gui_list(ID_CITY_DLG_INFO_BUTTON, pBuf);
3726 
3727   pCityDlg->pAdd_Point = pBuf;
3728   pCityDlg->pBeginCityWidgetList = pBuf;
3729   /* ===================================================== */
3730   rebuild_imprm_list(pCity);
3731   /* ===================================================== */
3732 
3733   pLogo = get_scaled_city_map(pCity);
3734 
3735   pBuf = create_themelabel(pLogo, pWindow->dst, NULL,
3736                            pLogo->w, pLogo->h, WF_SELLECT_WITHOUT_BAR);
3737 
3738   pCityDlg->pResource_Map = pBuf;
3739 
3740   pBuf->action = resource_map_city_dlg_callback;
3741   if (!cma_is_city_under_agent(pCity, NULL) && (pOwner == client.conn.playing)) {
3742     set_wstate(pBuf, FC_WS_NORMAL);
3743   }
3744   pBuf->size.x = area.x + adj_size(193) + (adj_size(249) - pBuf->size.w) / 2;
3745   pBuf->size.y = area.y + adj_size(41) + (adj_size(158) - pBuf->size.h) / 2;
3746   add_to_gui_list(ID_CITY_DLG_RESOURCE_MAP, pBuf);
3747   /* -------- */
3748 
3749   pBuf = create_themeicon(current_theme->Options_Icon, pWindow->dst,
3750                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3751   pBuf->info_label = create_str16_from_char(_("City options"), adj_font(12));
3752   pBuf->action = options_city_dlg_callback;
3753   pBuf->size.x =
3754     area.x + adj_size(4) + 5 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 4 * pBuf->size.w;
3755   pBuf->size.y = area.y + adj_size(2);
3756   if (pOwner == client.conn.playing) {
3757     set_wstate(pBuf, FC_WS_NORMAL);
3758   }
3759   add_to_gui_list(ID_CITY_DLG_OPTIONS_BUTTON, pBuf);
3760   /* -------- */
3761 
3762   pBuf = create_themeicon(current_theme->PROD_Icon, pWindow->dst,
3763                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3764   pBuf->info_label = create_str16_from_char(_("Change production"),
3765                                             adj_font(12));
3766   pBuf->action = change_prod_dlg_callback;
3767   pBuf->size.x = area.x + adj_size(7);
3768   pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3769   if (pOwner == client.conn.playing) {
3770     set_wstate(pBuf, FC_WS_NORMAL);
3771   }
3772   pBuf->key = SDLK_c;
3773   add_to_gui_list(ID_CITY_DLG_CHANGE_PROD_BUTTON, pBuf);
3774   /* -------- */
3775 
3776   pBuf = create_themeicon(current_theme->Buy_PROD_Icon, pWindow->dst,
3777                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3778   pBuf->info_label = create_str16_from_char(_("Hurry production"),
3779                                             adj_font(12));
3780   pBuf->action = buy_prod_city_dlg_callback;
3781   pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2));
3782   pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3783   pCityDlg->pBuy_Button = pBuf;
3784   pBuf->key = SDLK_h;
3785   if (city_can_buy(pCity)) {
3786     set_wstate(pBuf, FC_WS_NORMAL);
3787   }
3788   add_to_gui_list(ID_CITY_DLG_PROD_BUY_BUTTON, pBuf);
3789   /* -------- */
3790 
3791   pBuf = create_themeicon(current_theme->CMA_Icon, pWindow->dst,
3792                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3793   pBuf->info_label = create_str16_from_char(_("Citizen Governor"),
3794                                             adj_font(12));
3795   pBuf->action = cma_city_dlg_callback;
3796   pBuf->key = SDLK_a;
3797   pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2)) * 2;
3798   pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3799   if (pOwner == client.conn.playing) {
3800     set_wstate(pBuf, FC_WS_NORMAL);
3801   }
3802   add_to_gui_list(ID_CITY_DLG_CMA_BUTTON, pBuf);
3803 
3804   /* -------- */
3805 
3806   pBuf = create_themeicon(current_theme->L_ARROW_Icon, pWindow->dst,
3807                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3808   pBuf->info_label = create_str16_from_char(_("Previous city"),
3809                                             adj_font(12));
3810   pBuf->action = next_prev_city_dlg_callback;
3811   pBuf->size.x = area.x + adj_size(220) - pBuf->size.w - adj_size(8);
3812   pBuf->size.y = area.y + area.h - pBuf->size.h;
3813   if (pOwner == client.conn.playing) {
3814     set_wstate(pBuf, FC_WS_NORMAL);
3815   }
3816   pBuf->key = SDLK_LEFT;
3817   pBuf->mod = KMOD_LSHIFT;
3818   add_to_gui_list(ID_CITY_DLG_PREV_BUTTON, pBuf);
3819   /* -------- */
3820 
3821   pBuf = create_themeicon(current_theme->R_ARROW_Icon, pWindow->dst,
3822                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3823   pBuf->info_label = create_str16_from_char(_("Next city"), adj_font(12));
3824   pBuf->action = next_prev_city_dlg_callback;
3825   pBuf->size.x = area.x + adj_size(420) + adj_size(2);
3826   pBuf->size.y = area.y + area.h - pBuf->size.h;
3827   if (pOwner == client.conn.playing) {
3828     set_wstate(pBuf, FC_WS_NORMAL);
3829   }
3830   pBuf->key = SDLK_RIGHT;
3831   pBuf->mod = KMOD_LSHIFT;
3832   add_to_gui_list(ID_CITY_DLG_NEXT_BUTTON, pBuf);
3833   /* -------- */
3834 
3835   pBuf = create_edit_from_chars(NULL, pWindow->dst, city_name_get(pCity),
3836                                 adj_font(10), adj_size(200), WF_RESTORE_BACKGROUND);
3837   pBuf->action = new_name_city_dlg_callback;
3838   pBuf->size.x = area.x + (area.w - pBuf->size.w) / 2;
3839   pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(2);
3840   if (pOwner == client.conn.playing) {
3841     set_wstate(pBuf, FC_WS_NORMAL);
3842   }
3843 
3844   pCityDlg->pCity_Name_Edit = pBuf;
3845   add_to_gui_list(ID_CITY_DLG_NAME_EDIT, pBuf);
3846 
3847   pCityDlg->pBeginCityWidgetList = pBuf;
3848 
3849   /* check if Citizen Icons style was loaded */
3850   cs = style_of_city(pCity);
3851 
3852   if (cs != pIcons->style) {
3853     reload_citizens_icons(cs);
3854   }
3855 
3856   /* ===================================================== */
3857   if ((city_unhappy(pCity) || city_celebrating(pCity)
3858        || city_happy(pCity))) {
3859     SDL_Client_Flags |= CF_CITY_STATUS_SPECIAL;
3860   }
3861   /* ===================================================== */
3862 
3863   redraw_city_dialog(pCity);
3864   flush_dirty();
3865 }
3866 
3867 /**************************************************************************
3868   Close the dialog for the given city.
3869 **************************************************************************/
popdown_city_dialog(struct city * pCity)3870 void popdown_city_dialog(struct city *pCity)
3871 {
3872   if (city_dialog_is_open(pCity)) {
3873     del_city_dialog();
3874 
3875     flush_dirty();
3876 
3877     SDL_Client_Flags &= ~CF_CITY_STATUS_SPECIAL;
3878     menus_update();
3879   }
3880 }
3881 
3882 /**************************************************************************
3883   Close all cities dialogs.
3884 **************************************************************************/
popdown_all_city_dialogs(void)3885 void popdown_all_city_dialogs(void)
3886 {
3887   if (pCityDlg) {
3888     popdown_city_dialog(pCityDlg->pCity);
3889   }
3890 }
3891 
3892 /**************************************************************************
3893   Refresh (update) all data for the given city's dialog.
3894 **************************************************************************/
real_city_dialog_refresh(struct city * pCity)3895 void real_city_dialog_refresh(struct city *pCity)
3896 {
3897   if (city_dialog_is_open(pCity)) {
3898     redraw_city_dialog(pCityDlg->pCity);
3899     flush_dirty();
3900   }
3901 }
3902 
3903 /**************************************************************************
3904   Update city dialogs when the given unit's status changes.  This
3905   typically means updating both the unit's home city (if any) and the
3906   city in which it is present (if any).
3907 **************************************************************************/
refresh_unit_city_dialogs(struct unit * pUnit)3908 void refresh_unit_city_dialogs(struct unit *pUnit)
3909 {
3910 
3911   struct city *pCity_sup = game_city_by_number(pUnit->homecity);
3912   struct city *pCity_pre = tile_city(unit_tile(pUnit));
3913 
3914   if (pCityDlg && ((pCityDlg->pCity == pCity_sup)
3915 		   || (pCityDlg->pCity == pCity_pre))) {
3916     free_city_units_lists();
3917     redraw_city_dialog(pCityDlg->pCity);
3918     flush_dirty();
3919   }
3920 
3921 }
3922 
3923 /**************************************************************************
3924   Return whether the dialog for the given city is open.
3925 **************************************************************************/
city_dialog_is_open(struct city * pCity)3926 bool city_dialog_is_open(struct city *pCity)
3927 {
3928   return (pCityDlg && (pCityDlg->pCity == pCity));
3929 }
3930 
3931 /**************************************************************************
3932   City is about to disappear from client
3933 **************************************************************************/
city_to_disappear(struct city * pcity)3934 void city_to_disappear(struct city *pcity)
3935 {
3936 }
3937