Use correct factor in all situations when scaling down sdl-client citymap.
[freeciv.git] / client / gui-sdl / citydlg.c
blobe1b43519a9173b8b0be82457b3276a89f11b2a69
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.
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 ***********************************************************************/
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 ***********************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
26 /* SDL */
27 #include <SDL/SDL.h>
29 /* utility */
30 #include "bitvector.h"
31 #include "fcintl.h"
32 #include "log.h"
34 /* common */
35 #include "game.h"
36 #include "movement.h"
37 #include "specialist.h"
38 #include "unitlist.h"
40 /* client */
41 #include "client_main.h"
42 #include "climisc.h"
43 #include "control.h"
44 #include "text.h"
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"
63 #include "citydlg.h"
65 /* ============================================================= */
67 static struct city_dialog {
68 struct city *pCity;
70 enum {
71 INFO_PAGE = 0,
72 HAPPINESS_PAGE = 1,
73 ARMY_PAGE,
74 SUPPORTED_UNITS_PAGE,
75 MISC_PAGE
76 } page;
78 /* main window group list */
79 struct widget *pBeginCityWidgetList;
80 struct widget *pEndCityWidgetList;
82 /* Imprvm. vscrollbar */
83 struct ADVANCED_DLG *pImprv;
85 /* Penel group list */
86 struct ADVANCED_DLG *pPanel;
88 /* Menu imprv. dlg. */
89 struct widget *pBeginCityMenuWidgetList;
90 struct widget *pEndCityMenuWidgetList;
92 /* shortcuts */
93 struct widget *pAdd_Point;
94 struct widget *pBuy_Button;
95 struct widget *pResource_Map;
96 struct widget *pCity_Name_Edit;
98 int citizen_step;
100 SDL_Rect spec_area;
102 bool lock;
103 } *pCityDlg = NULL;
105 enum specialist_type {
106 SP_ELVIS, SP_SCIENTIST, SP_TAXMAN, SP_LAST
109 static float city_map_zoom = 1;
111 static struct SMALL_DLG *pHurry_Prod_Dlg = NULL;
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);
119 /* ======================================================================= */
121 /**************************************************************************
122 Return first building that has given effect.
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 **************************************************************************/
128 struct impr_type *get_building_for_effect(enum effect_type effect_type)
130 improvement_iterate(pImprove) {
131 if (building_has_effect(pImprove, effect_type))
132 return pImprove;
133 } improvement_iterate_end;
135 return NULL;
138 /**************************************************************************
139 Destroy City Menu Dlg but not undraw.
140 **************************************************************************/
141 static void popdown_city_menu_dlg(bool enable_city_dialog_widgets)
143 if (pCityDlg->pEndCityMenuWidgetList) {
144 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
145 pCityDlg->pEndCityMenuWidgetList);
146 pCityDlg->pEndCityMenuWidgetList = NULL;
148 if (enable_city_dialog_widgets) {
149 /* enable city dlg */
150 enable_city_dlg_widgets();
154 /**************************************************************************
155 Destroy City Dlg
156 **************************************************************************/
157 static void del_city_dialog(void)
159 if (pCityDlg) {
161 if (pCityDlg->pImprv->pEndWidgetList) {
162 del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
163 pCityDlg->pImprv->pEndWidgetList);
165 FC_FREE(pCityDlg->pImprv->pScroll);
166 FC_FREE(pCityDlg->pImprv);
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);
175 if (pHurry_Prod_Dlg)
177 del_group_of_widgets_from_gui_list(pHurry_Prod_Dlg->pBeginWidgetList,
178 pHurry_Prod_Dlg->pEndWidgetList);
180 FC_FREE(pHurry_Prod_Dlg);
183 free_city_units_lists();
184 popdown_city_menu_dlg(FALSE);
186 popdown_window_group_dialog(pCityDlg->pBeginCityWidgetList,
187 pCityDlg->pEndCityWidgetList);
188 FC_FREE(pCityDlg);
192 /**************************************************************************
193 Main City Dlg. window callback.
194 This implements specialist change ( Elvis, Taxman, Scientist )
195 **************************************************************************/
196 static int city_dlg_callback(struct widget *pWindow)
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) {
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);
208 return -1;
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);
225 return -1;
228 /* ===================================================================== */
229 /* ========================== Units Orders Menu ======================== */
230 /* ===================================================================== */
232 /**************************************************************************
233 Popdown unit city orders menu.
234 **************************************************************************/
235 static int cancel_units_orders_city_dlg_callback(struct widget *pButton)
237 if (Main.event.button.button == SDL_BUTTON_LEFT) {
238 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
239 pCityDlg->pEndCityMenuWidgetList);
240 pCityDlg->pEndCityMenuWidgetList = NULL;
242 /* enable city dlg */
243 enable_city_dlg_widgets();
244 flush_dirty();
246 return -1;
249 /**************************************************************************
250 activate unit and del unit order dlg. widget group.
251 **************************************************************************/
252 static int activate_units_orders_city_dlg_callback(struct widget *pButton)
254 if (Main.event.button.button == SDL_BUTTON_LEFT) {
255 struct unit *pUnit = pButton->data.unit;
257 popdown_city_menu_dlg(TRUE);
258 if(pUnit) {
259 unit_focus_set(pUnit);
262 return -1;
265 /**************************************************************************
266 activate unit and popdow city dlg. + center on unit.
267 **************************************************************************/
268 static int activate_and_exit_units_orders_city_dlg_callback(struct widget *pButton)
270 if (Main.event.button.button == SDL_BUTTON_LEFT) {
271 struct unit *pUnit = pButton->data.unit;
273 if(pUnit) {
275 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
276 pCityDlg->pEndCityMenuWidgetList);
277 pCityDlg->pEndCityMenuWidgetList = NULL;
279 popdown_city_dialog(pCityDlg->pCity);
281 center_tile_mapcanvas(unit_tile(pUnit));
282 unit_focus_set(pUnit);
285 return -1;
288 /**************************************************************************
289 sentry unit and del unit order dlg. widget group.
290 **************************************************************************/
291 static int sentry_units_orders_city_dlg_callback(struct widget *pButton)
293 if (Main.event.button.button == SDL_BUTTON_LEFT) {
294 struct unit *pUnit = pButton->data.unit;
296 popdown_city_menu_dlg(TRUE);
297 if(pUnit) {
298 request_unit_sentry(pUnit);
301 return -1;
304 /**************************************************************************
305 fortify unit and del unit order dlg. widget group.
306 **************************************************************************/
307 static int fortify_units_orders_city_dlg_callback(struct widget *pButton)
309 if (Main.event.button.button == SDL_BUTTON_LEFT) {
310 struct unit *pUnit = pButton->data.unit;
312 popdown_city_menu_dlg(TRUE);
313 if(pUnit) {
314 request_unit_fortify(pUnit);
317 return -1;
320 /**************************************************************************
321 disband unit and del unit order dlg. widget group.
322 **************************************************************************/
323 static int disband_units_orders_city_dlg_callback(struct widget *pButton)
325 if (Main.event.button.button == SDL_BUTTON_LEFT) {
326 struct unit *pUnit = pButton->data.unit;
328 popdown_city_menu_dlg(TRUE);
329 popup_unit_disband_dlg(pUnit, TRUE);
331 return -1;
334 /**************************************************************************
335 homecity unit and del unit order dlg. widget group.
336 **************************************************************************/
337 static int homecity_units_orders_city_dlg_callback(struct widget *pButton)
339 if (Main.event.button.button == SDL_BUTTON_LEFT) {
340 struct unit *pUnit = pButton->data.unit;
342 popdown_city_menu_dlg(TRUE);
343 if(pUnit) {
344 request_unit_change_homecity(pUnit);
347 return -1;
350 /**************************************************************************
351 upgrade unit and del unit order dlg. widget group.
352 **************************************************************************/
353 static int upgrade_units_orders_city_dlg_callback(struct widget *pButton)
355 if (Main.event.button.button == SDL_BUTTON_LEFT) {
356 struct unit *pUnit = pButton->data.unit;
358 popdown_city_menu_dlg(TRUE);
359 popup_unit_upgrade_dlg(pUnit, TRUE);
361 return -1;
364 /**************************************************************************
365 Main unit order dlg. callback.
366 **************************************************************************/
367 static int units_orders_dlg_callback(struct widget *pButton)
369 return -1;
372 /**************************************************************************
373 popup units orders menu.
374 **************************************************************************/
375 static int units_orders_city_dlg_callback(struct widget *pButton)
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;
386 pUnit = player_unit_by_number(client_player(), MAX_ID - pButton->ID);
388 if(!pUnit || !can_client_issue_orders()) {
389 return -1;
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;
399 /* Disable city dlg */
400 unsellect_widget_action();
401 disable_city_dlg_widgets();
403 pUType = unit_type_get(pUnit);
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);
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;
416 area = pWindow->area;
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);
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);
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 /* ----- */
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);
464 add_to_gui_list(pButton->ID, pBuf);
465 /* ----- */
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);
479 add_to_gui_list(pButton->ID, pBuf);
481 /* ----- */
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 /* ----- */
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);
508 /* ----- */
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);
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;
537 /* ================================================== */
538 unsellect_widget_action();
539 /* ================================================== */
541 area.w += adj_size(10);
542 hh += adj_size(4);
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));
550 area = pWindow->area;
552 widget_set_position(pWindow,
553 pButton->size.x + adj_size(2),
554 pWindow->area.y + pButton->size.y + 1);
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;
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;
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;
578 pBuf = pBuf->prev;
581 /* ================================================== */
582 /* redraw */
583 redraw_group(pCityDlg->pBeginCityMenuWidgetList, pWindow, 0);
584 widget_flush(pWindow);
586 return -1;
589 /* ======================================================================= */
590 /* ======================= City Dlg. Panels ============================== */
591 /* ======================================================================= */
593 /**************************************************************************
594 create unit icon with support icons.
595 **************************************************************************/
596 static SDL_Surface *create_unit_surface(struct unit *punit, bool support,
597 int w, int h)
599 int i, step;
600 SDL_Rect src_rect, dest;
601 SDL_Surface *psurf;
602 struct canvas *destcanvas;
604 destcanvas = canvas_create_with_alpha(tileset_full_tile_width(tileset),
605 tileset_unit_with_small_upkeep_height(tileset));
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;
613 if (support) {
614 int free_unhappy;
615 int happy_cost;
617 free_unhappy = get_city_bonus(pCityDlg->pCity, EFT_MAKE_CONTENT_MIL);
618 happy_cost = city_unit_unhappiness(punit, &free_unhappy);
620 i = punit->upkeep[O_SHIELD] + punit->upkeep[O_FOOD] +
621 punit->upkeep[O_GOLD] + happy_cost;
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;
629 dest.y = tileset_unit_layout_small_offset_y(tileset);
630 dest.x = src_rect.x + src_rect.w / 8;
632 for (i = 0; i < punit->upkeep[O_SHIELD]; i++) {
633 alphablit(pIcons->pShield, NULL, destcanvas->surf, &dest);
634 dest.x += step;
637 for (i = 0; i < punit->upkeep[O_FOOD]; i++) {
638 alphablit(pIcons->pFood, NULL, destcanvas->surf, &dest);
639 dest.x += step;
642 for (i = 0; i < punit->upkeep[O_GOLD]; i++) {
643 alphablit(pIcons->pCoin, NULL, destcanvas->surf, &dest);
644 dest.x += step;
647 for (i = 0; i < happy_cost; i++) {
648 alphablit(pIcons->pFace, NULL, destcanvas->surf, &dest);
649 dest.x += step;
653 psurf = create_surf_alpha(src_rect.w, src_rect.h, SDL_SWSURFACE);
654 alphablit(destcanvas->surf, &src_rect, psurf, NULL);
656 canvas_free(destcanvas);
658 if (w != src_rect.w || h != src_rect.h) {
659 SDL_Surface *pzoomed;
661 pzoomed = ResizeSurfaceBox(psurf, w, h, 1, TRUE, TRUE);
662 FREESURFACE(psurf);
663 psurf = pzoomed;
666 return psurf;
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 **************************************************************************/
674 static void create_present_supported_units_widget_list(struct unit_list *pList)
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;
687 i = 0;
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;
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;
705 unit_list_iterate(pList, pUnit) {
706 const char *vetname;
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"));
722 if (pCityDlg->page == SUPPORTED_UNITS_PAGE) {
723 int pCity_near_dist;
724 struct city *pNear_City = get_nearest_city(pUnit, &pCity_near_dist);
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));
733 pStr = create_str16_from_char(cBuf, adj_font(10));
734 pStr->style |= SF_CENTER;
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);
742 if (!pEnd) {
743 pEnd = pBuf;
746 if (++i > num_x * num_y) {
747 set_wflag(pBuf, WF_HIDDEN);
750 if (city_owner(pCityDlg->pCity) == client.conn.playing) {
751 set_wstate(pBuf, FC_WS_NORMAL);
754 pBuf->action = units_orders_city_dlg_callback;
756 } unit_list_iterate_end;
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;
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);
771 if (i > num_x * num_y) {
773 create_vertical_scrollbar(pCityDlg->pPanel,
774 num_x, num_y, TRUE, TRUE);
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);
784 /**************************************************************************
785 free city present/supported units panel list.
786 **************************************************************************/
787 void free_city_units_lists(void)
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);
797 /**************************************************************************
798 change to present units panel.
799 **************************************************************************/
800 static int army_city_dlg_callback(struct widget *pButton)
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);
813 return -1;
816 /**************************************************************************
817 change to supported units panel.
818 **************************************************************************/
819 static int supported_unit_city_dlg_callback(struct widget *pButton)
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);
832 return -1;
835 /* ---------------------- */
837 /**************************************************************************
838 change to info panel.
839 **************************************************************************/
840 static int info_city_dlg_callback(struct widget *pButton)
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);
853 return -1;
856 /* ---------------------- */
857 /**************************************************************************
858 change to happines panel.
859 **************************************************************************/
860 static int happy_city_dlg_callback(struct widget *pButton)
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);
873 return -1;
876 /**************************************************************************
877 city option callback
878 **************************************************************************/
879 static int misc_panel_city_dlg_callback(struct widget *pWidget)
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;
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);
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);
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;
928 dsend_packet_city_options_req(&client.conn, pCityDlg->pCity->id, new_options);
930 return -1;
933 /**************************************************************************
934 Create city options widgets.
935 **************************************************************************/
936 static void create_city_options_widget_list(struct city *pCity)
938 struct widget *pBuf, *pWindow = pCityDlg->pEndCityWidgetList;
939 SDL_Surface *pSurf;
940 SDL_String16 *pStr;
941 char cBuf[80];
943 fc_snprintf(cBuf, sizeof(cBuf),
944 _("Disband if build\nsettler at size 1"));
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);
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);
958 /* ----- */
960 pCityDlg->pPanel = fc_calloc(1, sizeof(struct ADVANCED_DLG));
961 pCityDlg->pPanel->pEndWidgetList = pBuf;
963 /* ----- */
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;
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);
987 pBuf->size.w = adj_size(177);
988 pBuf->action = misc_panel_city_dlg_callback;
989 set_wstate(pBuf, FC_WS_NORMAL);
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;
996 /**************************************************************************
997 change to city options panel.
998 **************************************************************************/
999 static int options_city_dlg_callback(struct widget *pButton)
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);
1012 return -1;
1015 /* ======================================================================= */
1017 /**************************************************************************
1018 User interacted with Citizen Governor button.
1019 **************************************************************************/
1020 static int cma_city_dlg_callback(struct widget *pButton)
1022 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1023 disable_city_dlg_widgets();
1024 popup_city_cma_dialog(pCityDlg->pCity);
1026 return -1;
1029 /**************************************************************************
1030 Exit city dialog.
1031 **************************************************************************/
1032 static int exit_city_dlg_callback(struct widget *pButton)
1034 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1035 popdown_city_dialog(pCityDlg->pCity);
1037 return -1;
1040 /* ======================================================================= */
1041 /* ======================== Buy Production Dlg. ========================== */
1042 /* ======================================================================= */
1044 /**************************************************************************
1045 popdown buy productions dlg.
1046 **************************************************************************/
1047 static int cancel_buy_prod_city_dlg_callback(struct widget *pButton)
1049 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1050 popdown_hurry_production_dialog();
1052 if (pCityDlg)
1054 /* enable city dlg */
1055 enable_city_dlg_widgets();
1058 return -1;
1061 /**************************************************************************
1062 buy productions.
1063 **************************************************************************/
1064 static int ok_buy_prod_city_dlg_callback(struct widget *pButton)
1066 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1067 struct city *pCity = pButton->data.city; /* Save it. */
1069 popdown_hurry_production_dialog();
1070 city_buy_production(pCity);
1072 if (pCityDlg) {
1073 /* enable city dlg */
1074 enable_city_dlg_widgets();
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();
1084 return -1;
1087 /**************************************************************************
1088 popup buy productions dlg.
1089 **************************************************************************/
1090 static int buy_prod_city_dlg_callback(struct widget *pButton)
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);
1098 return -1;
1101 /**************************************************************************
1102 popup buy productions dlg.
1103 **************************************************************************/
1104 static void popdown_hurry_production_dialog(void)
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();
1114 /**************************************************************************
1115 main hurry productions dlg. callback
1116 **************************************************************************/
1117 static int hurry_production_window_callback(struct widget *pWindow)
1119 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1120 move_window_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow);
1122 return -1;
1125 /**************************************************************************
1126 popup buy productions dlg.
1127 **************************************************************************/
1128 void popup_hurry_production_dialog(struct city *pCity, SDL_Surface *pDest)
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);
1141 if (pHurry_Prod_Dlg) {
1142 return;
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);
1150 pHurry_Prod_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
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);
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."));
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);
1183 pHurry_Prod_Dlg->pEndWidgetList = pWindow;
1185 area = pWindow->area;
1187 area.h += 1;
1189 /* ============================================================= */
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);
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);
1201 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1202 pWindow->dst, _("No"), adj_font(12), 0);
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;
1209 add_to_gui_list(ID_BUTTON, pBuf);
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);
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));
1225 pHurry_Prod_Dlg->pBeginWidgetList = pBuf;
1227 /* setup window size and start position */
1228 area.w += adj_size(10);
1229 area.h += adj_size(5);
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);
1235 area = pWindow->area;
1237 pBuf = pWindow->prev;
1239 if (city_dialog_is_open(pCity))
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)
1248 window_x = pSellected_Widget->size.x - pWindow->size.w;
1249 } else {
1250 window_x = pSellected_Widget->size.x + tileset_tile_width(tileset);
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)
1256 window_y = Main.screen->h - pWindow->size.h - 1;
1257 } else {
1258 if (window_y < 0) {
1259 window_y = 0;
1262 } else {
1263 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h, pCity->tile);
1268 widget_set_position(pWindow, window_x, window_y);
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);
1278 /* no */
1279 pBuf = pWindow->prev;
1280 pBuf->size.y = dst.y;
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;
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);
1294 /* ================================================== */
1295 /* redraw */
1296 redraw_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow, 0);
1297 widget_mark_dirty(pWindow);
1298 flush_dirty();
1301 /* =======================================================================*/
1302 /* ========================== CHANGE PRODUCTION ==========================*/
1303 /* =======================================================================*/
1305 /**************************************************************************
1306 Popup the change production dialog.
1307 **************************************************************************/
1308 static int change_prod_dlg_callback(struct widget *pButton)
1310 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1311 widget_redraw(pButton);
1312 widget_flush(pButton);
1314 disable_city_dlg_widgets();
1315 popup_worklist_editor(pCityDlg->pCity, NULL);
1317 return -1;
1320 /* =======================================================================*/
1321 /* =========================== SELL IMPROVMENTS ==========================*/
1322 /* =======================================================================*/
1324 /**************************************************************************
1325 Popdown Sell Imprv. Dlg. and exit without sell.
1326 **************************************************************************/
1327 static int sell_imprvm_dlg_cancel_callback(struct widget *pCancel_Button)
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();
1337 return -1;
1340 /**************************************************************************
1341 Popdown Sell Imprv. Dlg. and exit with sell.
1342 **************************************************************************/
1343 static int sell_imprvm_dlg_ok_callback(struct widget *pOK_Button)
1345 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1346 struct widget *pTmp = (struct widget *)pOK_Button->data.ptr;
1348 city_sell_improvement(pCityDlg->pCity, MAX_ID - 3000 - pTmp->ID);
1350 /* popdown, we don't redraw and flush becouse this is make by redraw city dlg.
1351 when response from server come */
1352 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
1353 pCityDlg->pEndCityMenuWidgetList);
1355 pCityDlg->pEndCityMenuWidgetList = NULL;
1357 /* del imprv from widget list */
1358 del_widget_from_vertical_scroll_widget_list(pCityDlg->pImprv, pTmp);
1360 enable_city_dlg_widgets();
1362 if (pCityDlg->pImprv->pEndWidgetList) {
1363 set_group_state(pCityDlg->pImprv->pBeginActiveWidgetList,
1364 pCityDlg->pImprv->pEndActiveWidgetList, FC_WS_DISABLED);
1367 redraw_city_dialog(pCityDlg->pCity);
1368 flush_dirty();
1370 return -1;
1373 /**************************************************************************
1374 Popup Sell Imprvm. Dlg.
1375 **************************************************************************/
1376 static int sell_imprvm_dlg_callback(struct widget *pImpr)
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;
1389 unsellect_widget_action();
1390 disable_city_dlg_widgets();
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;
1400 area = pWindow->area;
1402 /* create text label */
1403 id = MAX_ID - 3000 - pImpr->ID;
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);
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);
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);
1436 pCityDlg->pBeginCityMenuWidgetList = pOK_Button;
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));
1446 area.h = MAX(area.h, pOK_Button->size.h + pLabel->size.h + adj_size(25));
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);
1453 area = pWindow->area;
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));
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);
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);
1466 pLabel->size.x = area.x;
1467 pLabel->size.y = area.y + adj_size(4);
1468 pLabel->size.w = area.w;
1470 /* redraw */
1471 redraw_group(pCityDlg->pBeginCityMenuWidgetList,
1472 pCityDlg->pEndCityMenuWidgetList, 0);
1474 widget_mark_dirty(pWindow);
1475 flush_dirty();
1477 return -1;
1479 /* ====================================================================== */
1481 /**************************************************************************
1482 Enable city dialog widgets that can be enabled.
1483 **************************************************************************/
1484 void enable_city_dlg_widgets(void)
1486 if (pCityDlg) {
1487 set_group_state(pCityDlg->pBeginCityWidgetList,
1488 pCityDlg->pEndCityWidgetList->prev, FC_WS_NORMAL);
1490 if (pCityDlg->pImprv->pEndActiveWidgetList) {
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 */
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;
1508 while (TRUE) {
1509 struct impr_type *pimpr = improvement_by_number(MAX_ID - 3000 -
1510 pTmpWidget->ID);
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);
1518 if (pTmpWidget == pCityDlg->pImprv->pBeginActiveWidgetList) {
1519 break;
1522 pTmpWidget = pTmpWidget->prev;
1524 } /* while */
1528 if (!city_can_buy(pCityDlg->pCity) && pCityDlg->pBuy_Button) {
1529 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
1532 if (pCityDlg->pPanel) {
1533 set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1534 pCityDlg->pPanel->pEndWidgetList, FC_WS_NORMAL);
1537 if (cma_is_city_under_agent(pCityDlg->pCity, NULL)) {
1538 set_wstate(pCityDlg->pResource_Map, FC_WS_DISABLED);
1541 pCityDlg->lock = FALSE;
1545 /**************************************************************************
1546 Disable all city dialog widgets
1547 **************************************************************************/
1548 static void disable_city_dlg_widgets(void)
1550 if (pCityDlg->pPanel) {
1551 set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1552 pCityDlg->pPanel->pEndWidgetList, FC_WS_DISABLED);
1556 if (pCityDlg->pImprv->pEndWidgetList) {
1557 set_group_state(pCityDlg->pImprv->pBeginWidgetList,
1558 pCityDlg->pImprv->pEndWidgetList, FC_WS_DISABLED);
1561 set_group_state(pCityDlg->pBeginCityWidgetList,
1562 pCityDlg->pEndCityWidgetList->prev, FC_WS_DISABLED);
1563 pCityDlg->lock = TRUE;
1565 /* ======================================================================== */
1567 /**************************************************************************
1568 Return scaled city map.
1569 **************************************************************************/
1570 SDL_Surface *get_scaled_city_map(struct city *pCity)
1572 SDL_Surface *pBuf = create_city_map(pCity);
1574 city_map_zoom = ((pBuf->w * 159 > pBuf->h * 249) ?
1575 (float)adj_size(249) / pBuf->w
1576 : (float)adj_size(159) / pBuf->h);
1578 return zoomSurface(pBuf, city_map_zoom, city_map_zoom, 1);
1581 /**************************************************************************
1582 city resource map: event callback
1583 **************************************************************************/
1584 static int resource_map_city_dlg_callback(struct widget *pMap)
1586 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1587 int col, row;
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))) {
1596 city_toggle_worker(pCityDlg->pCity, col, row);
1599 return -1;
1602 /* ====================================================================== */
1604 /************************************************************************
1605 Helper for switch_city_callback.
1606 *************************************************************************/
1607 static int city_comp_by_turn_founded(const void *a, const void *b)
1609 struct city *pCity1 = *((struct city **) a);
1610 struct city *pCity2 = *((struct city **) b);
1612 return pCity1->turn_founded - pCity2->turn_founded;
1615 /**************************************************************************
1616 Callback for next/prev city button
1617 **************************************************************************/
1618 static int next_prev_city_dlg_callback(struct widget *pButton)
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);
1625 fc_assert_ret_val(size >= 1, -1);
1626 fc_assert_ret_val(city_owner(pCityDlg->pCity)
1627 == client.conn.playing, -1);
1629 if (size == 1) {
1630 return -1;
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;
1647 array = fc_calloc(1, size * sizeof(struct city *));
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);
1654 fc_assert_ret_val(non_open_size > 0, -1);
1656 if (non_open_size == 1) {
1657 FC_FREE(array);
1658 return -1;
1661 qsort(array, non_open_size, sizeof(struct city *),
1662 city_comp_by_turn_founded);
1664 for (i = 0; i < non_open_size; i++) {
1665 if (pCityDlg->pCity == array[i]) {
1666 break;
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);
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);
1681 /* redraw */
1682 redraw_city_dialog(pCityDlg->pCity);
1683 flush_dirty();
1685 return -1;
1688 /**************************************************************************
1689 Rename city name:
1690 **************************************************************************/
1691 static int new_name_city_dlg_callback(struct widget *pEdit)
1693 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1694 char *tmp = convert_to_chars(pEdit->string16->text);
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);
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();
1712 return -1;
1715 /* ======================================================================= */
1716 /* ======================== Redrawing City Dlg. ========================== */
1717 /* ======================================================================= */
1719 /**************************************************************************
1720 Refresh (update) the city names for the dialog
1721 **************************************************************************/
1722 static void refresh_city_names(struct city *pcity)
1724 if (pCityDlg->pCity_Name_Edit) {
1725 char name[MAX_LEN_NAME];
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;
1738 /**************************************************************************
1739 Redraw city option panel
1740 207 = max panel width
1741 **************************************************************************/
1742 static void redraw_misc_city_dialog(struct widget *pCityWindow,
1743 struct city *pCity)
1745 char cBuf[60];
1746 SDL_String16 *pStr;
1747 SDL_Surface *pSurf;
1748 SDL_Rect dest;
1750 fc_snprintf(cBuf, sizeof(cBuf), _("City options"));
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;
1756 pSurf = create_text_surf_from_str16(pStr);
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;
1761 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1763 FREESURFACE(pSurf);
1764 FREESTRING16(pStr);
1766 if (!pCityDlg->pPanel) {
1767 create_city_options_widget_list(pCity);
1769 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1770 pCityDlg->pPanel->pEndWidgetList, 0);
1773 /**************************************************************************
1774 Redraw supported unit panel
1775 207 = max panel width
1776 **************************************************************************/
1777 static void redraw_supported_units_city_dialog(struct widget *pCityWindow,
1778 struct city *pCity)
1780 char cBuf[60];
1781 SDL_String16 *pStr;
1782 SDL_Surface *pSurf;
1783 SDL_Rect dest;
1784 struct unit_list *pList;
1785 int size;
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);
1793 size = unit_list_size(pList);
1795 fc_snprintf(cBuf, sizeof(cBuf), _("Supported units: %d"), size);
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;
1801 pSurf = create_text_surf_from_str16(pStr);
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;
1806 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1808 FREESURFACE(pSurf);
1809 FREESTRING16(pStr);
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);
1821 } else {
1822 if (size) {
1823 create_present_supported_units_widget_list(pList);
1824 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1825 pCityDlg->pPanel->pEndWidgetList, 0);
1830 /**************************************************************************
1831 Redraw garrison panel
1832 207 = max panel width
1833 **************************************************************************/
1834 static void redraw_army_city_dialog(struct widget *pCityWindow,
1835 struct city *pCity)
1837 char cBuf[60];
1838 SDL_String16 *pStr;
1839 SDL_Surface *pSurf;
1840 SDL_Rect dest;
1841 struct unit_list *pList;
1843 int size;
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;
1851 size = unit_list_size(pList);
1853 fc_snprintf(cBuf, sizeof(cBuf), _("Present units: %d"), size);
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;
1859 pSurf = create_text_surf_from_str16(pStr);
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;
1864 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1866 FREESURFACE(pSurf);
1867 FREESTRING16(pStr);
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);
1879 } else {
1880 if (size) {
1881 create_present_supported_units_widget_list(pList);
1882 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1883 pCityDlg->pPanel->pEndWidgetList, 0);
1888 /**************************************************************************
1889 Redraw Info panel
1890 207 = max panel width
1891 **************************************************************************/
1892 static void redraw_info_city_dialog(struct widget *pCityWindow,
1893 struct city *pCity)
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;
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;
1907 pSurf = create_text_surf_from_str16(pStr);
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;
1912 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1914 dest.x = pCityWindow->size.x + adj_size(10);
1915 dest.y += pSurf->h + 1;
1917 FREESURFACE(pSurf);
1919 change_ptsize16(pStr, adj_font(11));
1920 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_INFOPANEL);
1922 if (pCity->pollution) {
1923 fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: %d"),
1924 pCity->pollution);
1926 copy_chars_to_string16(pStr, cBuf);
1928 pSurf = create_text_surf_from_str16(pStr);
1930 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1932 dest.y += pSurf->h + adj_size(3);
1934 FREESURFACE(pSurf);
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;
1942 for (i = 0; i < pCity->pollution; i++) {
1943 alphablit(pIcons->pPollution, NULL, pCityWindow->dst->surface, &dest);
1944 dest.x += step;
1947 dest.x = pCityWindow->size.x + adj_size(10);
1948 dest.y += pIcons->pPollution->h + adj_size(30);
1950 } else {
1951 fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: none"));
1953 copy_chars_to_string16(pStr, cBuf);
1955 pSurf = create_text_surf_from_str16(pStr);
1957 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1959 dest.y += pSurf->h + adj_size(3);
1961 FREESURFACE(pSurf);
1964 fc_snprintf(cBuf, sizeof(cBuf), _("Trade routes: "));
1966 copy_chars_to_string16(pStr, cBuf);
1968 pSurf = create_text_surf_from_str16(pStr);
1970 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1972 xx = dest.x + pSurf->w;
1973 dest.y += pSurf->h + adj_size(3);
1975 FREESURFACE(pSurf);
1977 step = 0;
1978 dest.x = pCityWindow->size.x + adj_size(10);
1980 for (i = 0; i < MAX_TRADE_ROUTES; i++) {
1981 if (pCity->trade[i]) {
1982 step += pCity->trade_value[i];
1984 if ((pTradeCity = game_city_by_number(pCity->trade[i]))) {
1985 fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", city_name_get(pTradeCity),
1986 pCity->trade_value[i]);
1987 } else {
1988 fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", _("Unknown"),
1989 pCity->trade_value[i]);
1992 copy_chars_to_string16(pStr, cBuf);
1994 pSurf = create_text_surf_from_str16(pStr);
1996 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1998 /* blit trade icon */
1999 dest.x += pSurf->w + adj_size(3);
2000 dest.y += adj_size(4);
2001 alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest);
2002 dest.x = pCityWindow->size.x + adj_size(10);
2003 dest.y -= adj_size(4);
2005 dest.y += pSurf->h;
2007 FREESURFACE(pSurf);
2011 if (step) {
2012 fc_snprintf(cBuf, sizeof(cBuf), _("Trade: +%d"), step);
2014 copy_chars_to_string16(pStr, cBuf);
2015 pSurf = create_text_surf_from_str16(pStr);
2016 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2018 dest.x += pSurf->w + adj_size(3);
2019 dest.y += adj_size(4);
2020 alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest);
2022 FREESURFACE(pSurf);
2023 } else {
2024 fc_snprintf(cBuf, sizeof(cBuf), _("none"));
2026 copy_chars_to_string16(pStr, cBuf);
2028 pSurf = create_text_surf_from_str16(pStr);
2030 dest.x = xx;
2031 dest.y -= pSurf->h + adj_size(3);
2032 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2034 FREESURFACE(pSurf);
2038 FREESTRING16(pStr);
2041 /**************************************************************************
2042 Redraw (refresh/update) the happiness info for the dialog
2043 207 - max panel width
2044 180 - max citizens icons area width
2045 **************************************************************************/
2046 static void redraw_happyness_city_dialog(const struct widget *pCityWindow,
2047 struct city *pCity)
2049 char cBuf[30];
2050 int step, i, j, count;
2051 SDL_Surface *pTmp;
2052 SDL_String16 *pStr = NULL;
2053 SDL_Surface *pSurf = NULL;
2054 SDL_Rect dest = {0, 0, 0, 0};
2055 struct effect_list *sources = effect_list_new();
2057 fc_snprintf(cBuf, sizeof(cBuf), _("Happiness"));
2059 pStr = create_str16_from_char(cBuf, adj_font(10));
2060 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
2061 pStr->style |= TTF_STYLE_BOLD;
2063 pSurf = create_text_surf_from_str16(pStr);
2065 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
2066 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
2067 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2069 dest.x = pCityWindow->size.x + adj_size(10);
2070 dest.y += pSurf->h + 1;
2072 FREESURFACE(pSurf);
2073 FREESTRING16(pStr);
2075 count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
2076 + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
2077 + city_specialists(pCity));
2079 if (count * pIcons->pMale_Happy->w > adj_size(166)) {
2080 step = (adj_size(166) - pIcons->pMale_Happy->w) / (count - 1);
2081 } else {
2082 step = pIcons->pMale_Happy->w;
2085 for (j = 0; j < FEELING_LAST; j++) {
2086 if (j == 0 || pCity->feel[CITIZEN_HAPPY][j - 1] != pCity->feel[CITIZEN_HAPPY][j]
2087 || pCity->feel[CITIZEN_CONTENT][j - 1] != pCity->feel[CITIZEN_CONTENT][j]
2088 || pCity->feel[CITIZEN_UNHAPPY][j - 1] != pCity->feel[CITIZEN_UNHAPPY][j]
2089 || pCity->feel[CITIZEN_ANGRY][j - 1] != pCity->feel[CITIZEN_ANGRY][j]) {
2090 int spe, spe_max;
2092 if (j != 0) {
2093 putline(pCityWindow->dst->surface,
2094 dest.x, dest.y, dest.x + adj_size(176), dest.y,
2095 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
2096 dest.y += adj_size(5);
2099 if (pCity->feel[CITIZEN_HAPPY][j]) {
2100 pSurf = pIcons->pMale_Happy;
2101 for (i = 0; i < pCity->feel[CITIZEN_HAPPY][j]; i++) {
2102 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2103 dest.x += step;
2104 if (pSurf == pIcons->pMale_Happy) {
2105 pSurf = pIcons->pFemale_Happy;
2106 } else {
2107 pSurf = pIcons->pMale_Happy;
2112 if (pCity->feel[CITIZEN_CONTENT][j]) {
2113 pSurf = pIcons->pMale_Content;
2114 for (i = 0; i < pCity->feel[CITIZEN_CONTENT][j]; i++) {
2115 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2116 dest.x += step;
2117 if (pSurf == pIcons->pMale_Content) {
2118 pSurf = pIcons->pFemale_Content;
2119 } else {
2120 pSurf = pIcons->pMale_Content;
2125 if (pCity->feel[CITIZEN_UNHAPPY][j]) {
2126 pSurf = pIcons->pMale_Unhappy;
2127 for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][j]; i++) {
2128 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2129 dest.x += step;
2130 if (pSurf == pIcons->pMale_Unhappy) {
2131 pSurf = pIcons->pFemale_Unhappy;
2132 } else {
2133 pSurf = pIcons->pMale_Unhappy;
2138 if (pCity->feel[CITIZEN_ANGRY][j]) {
2139 pSurf = pIcons->pMale_Angry;
2140 for (i = 0; i < pCity->feel[CITIZEN_ANGRY][j]; i++) {
2141 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2142 dest.x += step;
2143 if (pSurf == pIcons->pMale_Angry) {
2144 pSurf = pIcons->pFemale_Angry;
2145 } else {
2146 pSurf = pIcons->pMale_Angry;
2151 spe_max = specialist_count();
2152 for (spe = 0 ; spe < spe_max; spe++) {
2153 if (pCity->specialists[spe]) {
2154 for (i = 0; i < pCity->specialists[spe]; i++) {
2155 alphablit(pIcons->specialists[spe], NULL, pCityWindow->dst->surface, &dest);
2156 dest.x += step;
2161 if (j == 1) { /* luxury effect */
2162 dest.x =
2163 pCityWindow->size.x + adj_size(212) - pIcons->pBIG_Luxury->w - adj_size(2);
2164 count = dest.y;
2165 dest.y += (pIcons->pMale_Happy->h -
2166 pIcons->pBIG_Luxury->h) / 2;
2167 alphablit(pIcons->pBIG_Luxury, NULL, pCityWindow->dst->surface, &dest);
2168 dest.y = count;
2171 if (j == 2) { /* improvements effects */
2172 pSurf = NULL;
2173 count = 0;
2175 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_CONTENT);
2177 effect_list_iterate(sources, psource) {
2179 pTmp = get_building_surface(get_building_for_effect(psource->type));
2180 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2182 count += (pTmp->h + 1);
2184 if (!pSurf) {
2185 pSurf = pTmp;
2186 } else {
2187 FREESURFACE(pTmp);
2190 } effect_list_iterate_end;
2192 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2193 i = dest.y;
2194 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2196 FREESURFACE(pSurf);
2198 effect_list_iterate(sources, psource) {
2200 pTmp = get_building_surface(get_building_for_effect(psource->type));
2201 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2203 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2204 dest.y += (pTmp->h + 1);
2206 FREESURFACE(pTmp);
2207 } effect_list_iterate_end;
2209 effect_list_clear(sources);
2211 dest.y = i;
2213 /* TODO: check if code replacement above is correct */
2214 #if 0
2215 if (city_has_building(pCity, improvement_by_number(B_TEMPLE))) {
2216 pTmp1 =
2217 zoomSurface(GET_SURF(improvement_by_number(B_TEMPLE)->sprite),
2218 0.5, 0.5, 1);
2219 count += (pTmp1->h + 1);
2220 pSurf = pTmp1;
2221 } else {
2222 pTmp1 = NULL;
2225 if (city_has_building(pCity, improvement_by_number(B_COLOSSEUM))) {
2226 pTmp2 =
2227 zoomSurface(GET_SURF(improvement_by_number(B_COLOSSEUM)->sprite),
2228 0.5, 0.5, 1);
2229 count += (pTmp2->h + 1);
2230 if (!pSurf) {
2231 pSurf = pTmp2;
2233 } else {
2234 pTmp2 = NULL;
2237 if (city_has_building(pCity, improvement_by_number(B_CATHEDRAL)) ||
2238 city_affected_by_wonder(pCity, B_MICHELANGELO)) {
2239 pTmp3 =
2240 zoomSurface(GET_SURF(improvement_by_number(B_CATHEDRAL)->sprite),
2241 0.5, 0.5, 1);
2242 count += (pTmp3->h + 1);
2243 if (!pSurf) {
2244 pSurf = pTmp3;
2246 } else {
2247 pTmp3 = NULL;
2251 dest.x = pCityWindow->size.x + adj_size(212) - pSurf->w - adj_size(2);
2252 i = dest.y;
2253 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2256 if (pTmp1) { /* Temple */
2257 alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest);
2258 dest.y += (pTmp1->h + 1);
2261 if (pTmp2) { /* Colosseum */
2262 alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest);
2263 dest.y += (pTmp2->h + 1);
2266 if (pTmp3) { /* Cathedral */
2267 alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest);
2268 /*dest.y += (pTmp3->h + 1); */
2272 FREESURFACE(pTmp1);
2273 FREESURFACE(pTmp2);
2274 FREESURFACE(pTmp3);
2275 dest.y = i;
2276 #endif
2279 if (j == 3) { /* police effect */
2280 dest.x = pCityWindow->size.x + adj_size(187) - pIcons->pPolice->w - adj_size(5);
2281 i = dest.y;
2282 dest.y +=
2283 (pIcons->pMale_Happy->h - pIcons->pPolice->h) / 2;
2284 alphablit(pIcons->pPolice, NULL, pCityWindow->dst->surface, &dest);
2285 dest.y = i;
2288 if (j == 4) { /* wonders effect */
2289 count = 0;
2291 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2292 effect_list_iterate(sources, psource) {
2294 pTmp = get_building_surface(get_building_for_effect( psource->type));
2295 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2297 count += (pTmp->h + 1);
2299 if (!pSurf) {
2300 pSurf = pTmp;
2301 } else {
2302 FREESURFACE(pTmp);
2305 } effect_list_iterate_end;
2307 effect_list_clear(sources);
2309 get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2311 effect_list_iterate(sources, psource) {
2313 pTmp = get_building_surface(get_building_for_effect(psource->type));
2314 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2315 count += (pTmp->h + 1);
2317 if (!pSurf) {
2318 pSurf = pTmp;
2319 } else {
2320 FREESURFACE(pTmp);
2323 } effect_list_iterate_end;
2325 effect_list_clear(sources);
2327 get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2329 effect_list_iterate(sources, psource) {
2331 pTmp = get_building_surface(get_building_for_effect(psource->type));
2332 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2334 count += (pTmp->h + 1);
2336 FREESURFACE(pTmp);
2338 } effect_list_iterate_end;
2340 effect_list_clear(sources);
2343 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2344 i = dest.y;
2345 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2347 FREESURFACE(pSurf);
2349 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2351 effect_list_iterate(sources, psource) {
2353 pTmp = get_building_surface(get_building_for_effect(psource->type));
2354 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2356 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2357 dest.y += (pTmp->h + 1);
2359 FREESURFACE(pTmp);
2361 } effect_list_iterate_end;
2362 effect_list_clear(sources);
2364 get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2366 effect_list_iterate(sources, psource) {
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);
2371 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2372 dest.y += (pTmp->h + 1);
2374 FREESURFACE(pTmp);
2376 } effect_list_iterate_end;
2377 effect_list_clear(sources);
2379 get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2381 effect_list_iterate(sources, psource) {
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);
2386 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2387 dest.y += (pTmp->h + 1);
2389 FREESURFACE(pTmp);
2391 } effect_list_iterate_end;
2392 effect_list_clear(sources);
2394 dest.y = i;
2396 /* TODO: check if code replacement above is correct */
2397 #if 0
2398 if (city_affected_by_wonder(pCity, B_CURE)) {
2399 pTmp1 =
2400 zoomSurface(GET_SURF(improvement_by_number(B_CURE)->sprite),
2401 0.5, 0.5, 1);
2402 count += (pTmp1->h + 1);
2403 pSurf = pTmp1;
2404 } else {
2405 pTmp1 = NULL;
2408 if (city_affected_by_wonder(pCity, B_SHAKESPEARE)) {
2409 pTmp2 = zoomSurface(
2410 GET_SURF(improvement_by_number(B_SHAKESPEARE)->sprite),
2411 0.5, 0.5, 1);
2412 count += (pTmp2->h + 1);
2413 if (!pSurf) {
2414 pSurf = pTmp2;
2416 } else {
2417 pTmp2 = NULL;
2420 if (city_affected_by_wonder(pCity, B_BACH)) {
2421 pTmp3 =
2422 zoomSurface(GET_SURF(improvement_by_number(B_BACH)->sprite),
2423 0.5, 0.5, 1);
2424 count += (pTmp3->h + 1);
2425 if (!pSurf) {
2426 pSurf = pTmp3;
2428 } else {
2429 pTmp3 = NULL;
2432 if (city_affected_by_wonder(pCity, B_HANGING)) {
2433 pTmp4 =
2434 zoomSurface(GET_SURF(improvement_by_number(B_HANGING)->sprite),
2435 0.5, 0.5, 1);
2436 count += (pTmp4->h + 1);
2437 if (!pSurf) {
2438 pSurf = pTmp4;
2440 } else {
2441 pTmp4 = NULL;
2444 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2445 i = dest.y;
2446 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2449 if (pTmp1) { /* Cure of Cancer */
2450 alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest);
2451 dest.y += (pTmp1->h + 1);
2454 if (pTmp2) { /* Shakespeare Theater */
2455 alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest);
2456 dest.y += (pTmp2->h + 1);
2459 if (pTmp3) { /* J. S. Bach ... */
2460 alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest);
2461 dest.y += (pTmp3->h + 1);
2464 if (pTmp4) { /* Hanging Gardens */
2465 alphablit(pTmp4, NULL, pCityWindow->dst->surface, &dest);
2466 /*dest.y += (pTmp4->h + 1); */
2469 FREESURFACE(pTmp1);
2470 FREESURFACE(pTmp2);
2471 FREESURFACE(pTmp3);
2472 FREESURFACE(pTmp4);
2473 dest.y = i;
2474 #endif /* 0 */
2477 dest.x = pCityWindow->size.x + adj_size(10);
2478 dest.y += pIcons->pMale_Happy->h + adj_size(5);
2483 effect_list_destroy(sources);
2486 /**************************************************************************
2487 Redraw the dialog.
2488 **************************************************************************/
2489 static void redraw_city_dialog(struct city *pCity)
2491 char cBuf[40];
2492 int i, step, count, limit;
2493 int cost = 0;
2494 SDL_Rect dest;
2495 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
2496 SDL_Surface *pBuf = NULL, *pBuf2 = NULL;
2497 SDL_String16 *pStr = NULL;
2498 int spe, spe_max;
2500 refresh_city_names(pCity);
2502 if ((city_unhappy(pCity) || city_celebrating(pCity) || city_happy(pCity) ||
2503 cma_is_city_under_agent(pCity, NULL))
2504 ^ ((SDL_Client_Flags & CF_CITY_STATUS_SPECIAL) == CF_CITY_STATUS_SPECIAL)) {
2505 /* city status was changed : NORMAL <-> DISORDER, HAPPY, CELEBR. */
2507 SDL_Client_Flags ^= CF_CITY_STATUS_SPECIAL;
2509 #if 0
2510 /* upd. resource map */
2511 FREESURFACE(pCityDlg->pResource_Map->theme);
2512 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2513 #endif
2515 /* upd. window title */
2516 rebuild_citydlg_title_str(pCityDlg->pEndCityWidgetList, pCity);
2519 /* update resource map */
2520 FREESURFACE(pCityDlg->pResource_Map->theme);
2521 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2523 /* redraw city dlg */
2524 redraw_group(pCityDlg->pBeginCityWidgetList,
2525 pCityDlg->pEndCityWidgetList, 0);
2527 /* ================================================================= */
2528 fc_snprintf(cBuf, sizeof(cBuf), _("City map"));
2530 pStr = create_str16_from_char(cBuf, adj_font(10));
2531 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2532 pStr->style |= TTF_STYLE_BOLD;
2534 pBuf = create_text_surf_from_str16(pStr);
2536 dest.x = pWindow->size.x + adj_size(196) + (adj_size(132) - pBuf->w) / 2;
2537 dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2539 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2541 FREESURFACE(pBuf);
2543 fc_snprintf(cBuf, sizeof(cBuf), _("Citizens"));
2545 copy_chars_to_string16(pStr, cBuf);
2546 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2548 pBuf = create_text_surf_from_str16(pStr);
2550 dest.x = pWindow->size.x + adj_size(344) + (adj_size(146) - pBuf->w) / 2;
2551 dest.y = pWindow->size.y + adj_size(47) + (adj_size(13) - pBuf->h) / 2;
2553 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2555 FREESURFACE(pBuf);
2557 fc_snprintf(cBuf, sizeof(cBuf), _("City improvements"));
2559 copy_chars_to_string16(pStr, cBuf);
2560 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2562 pBuf = create_text_surf_from_str16(pStr);
2564 dest.x = pWindow->size.x + adj_size(504) + (adj_size(132) - pBuf->w) / 2;
2565 dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2567 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2569 FREESURFACE(pBuf);
2570 /* ================================================================= */
2571 /* food label */
2572 fc_snprintf(cBuf, sizeof(cBuf), _("Food: %d per turn"),
2573 pCity->prod[O_FOOD]);
2575 copy_chars_to_string16(pStr, cBuf);
2577 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOODPERTURN);
2579 pBuf = create_text_surf_from_str16(pStr);
2581 dest.x = pWindow->size.x + adj_size(200);
2582 dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2584 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2586 FREESURFACE(pBuf);
2588 /* draw food income */
2589 dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pIcons->pBIG_Food->h) / 2;
2590 dest.x = pWindow->size.x + adj_size(203);
2592 if (pCity->surplus[O_FOOD] >= 0) {
2593 count = pCity->prod[O_FOOD] - pCity->surplus[O_FOOD];
2594 } else {
2595 count = pCity->prod[O_FOOD];
2598 if (((pIcons->pBIG_Food->w + 1) * count) > adj_size(200)) {
2599 step = (adj_size(200) - pIcons->pBIG_Food->w) / (count - 1);
2600 } else {
2601 step = pIcons->pBIG_Food->w + 1;
2604 for (i = 0; i < count; i++) {
2605 alphablit(pIcons->pBIG_Food, NULL, pWindow->dst->surface, &dest);
2606 dest.x += step;
2609 fc_snprintf(cBuf, sizeof(cBuf), Q_("?food:Surplus: %d"),
2610 pCity->surplus[O_FOOD]);
2612 copy_chars_to_string16(pStr, cBuf);
2613 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOOD_SURPLUS);
2615 pBuf = create_text_surf_from_str16(pStr);
2617 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2618 dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2620 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2622 FREESURFACE(pBuf);
2624 /* draw surplus of food */
2625 if (pCity->surplus[O_FOOD]) {
2627 if (pCity->surplus[O_FOOD] > 0) {
2628 count = pCity->surplus[O_FOOD];
2629 pBuf = pIcons->pBIG_Food;
2630 } else {
2631 count = -1 * pCity->surplus[O_FOOD];
2632 pBuf = pIcons->pBIG_Food_Corr;
2635 dest.x = pWindow->size.x + adj_size(423);
2636 dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pBuf->h) / 2;
2638 /*if ( ((pBuf->w + 1) * count ) > 30 ) */
2639 if (count > 2) {
2640 if (count < 18) {
2641 step = (adj_size(30) - pBuf->w) / (count - 1);
2642 } else {
2643 step = 1;
2644 count = 17;
2646 } else {
2647 step = pBuf->w + 1;
2650 for (i = 0; i < count; i++) {
2651 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2652 dest.x -= step;
2655 /* ================================================================= */
2656 /* productions label */
2657 fc_snprintf(cBuf, sizeof(cBuf), _("Production: %d (%d) per turn"),
2658 pCity->surplus[O_SHIELD] ,
2659 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD]);
2661 copy_chars_to_string16(pStr, cBuf);
2662 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PROD);
2664 pBuf = create_text_surf_from_str16(pStr);
2666 dest.x = pWindow->size.x + adj_size(200);
2667 dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2669 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2671 FREESURFACE(pBuf);
2673 /* draw productions schields */
2674 if (pCity->surplus[O_SHIELD]) {
2676 if (pCity->surplus[O_SHIELD] > 0) {
2677 count = pCity->surplus[O_SHIELD] + pCity->waste[O_SHIELD];
2678 pBuf = pIcons->pBIG_Shield;
2679 } else {
2680 count = -1 * pCity->surplus[O_SHIELD];
2681 pBuf = pIcons->pBIG_Shield_Corr;
2684 dest.y = pWindow->size.y + adj_size(281) + (adj_size(16) - pBuf->h) / 2;
2685 dest.x = pWindow->size.x + adj_size(203);
2687 if ((pBuf->w * count) > adj_size(200)) {
2688 step = (adj_size(200) - pBuf->w) / (count - 1);
2689 } else {
2690 step = pBuf->w;
2693 for (i = 0; i < count; i++) {
2694 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2695 dest.x += step;
2696 if(i > pCity->surplus[O_SHIELD]) {
2697 pBuf = pIcons->pBIG_Shield_Corr;
2702 /* support shields label */
2703 fc_snprintf(cBuf, sizeof(cBuf), Q_("?production:Support: %d"),
2704 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD] - pCity->surplus[O_SHIELD]);
2706 copy_chars_to_string16(pStr, cBuf);
2707 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SUPPORT);
2709 pBuf = create_text_surf_from_str16(pStr);
2711 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2712 dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2714 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2716 FREESURFACE(pBuf);
2718 /* draw support shields */
2719 if (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]) {
2720 dest.x = pWindow->size.x + adj_size(423);
2721 dest.y =
2722 pWindow->size.y + adj_size(281) + (adj_size(16) - pIcons->pBIG_Shield->h) / 2;
2724 if ((pIcons->pBIG_Shield->w + 1) * (pCity->prod[O_SHIELD] -
2725 pCity->surplus[O_SHIELD]) > adj_size(30)) {
2726 step =
2727 (adj_size(30) - pIcons->pBIG_Food->w) / (pCity->prod[O_SHIELD] -
2728 pCity->surplus[O_SHIELD] - 1);
2729 } else {
2730 step = pIcons->pBIG_Shield->w + 1;
2733 for (i = 0; i < (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]); i++) {
2734 alphablit(pIcons->pBIG_Shield, NULL, pWindow->dst->surface, &dest);
2735 dest.x -= step;
2738 /* ================================================================= */
2740 /* trade label */
2741 fc_snprintf(cBuf, sizeof(cBuf), _("Trade: %d per turn"),
2742 pCity->surplus[O_TRADE]);
2744 copy_chars_to_string16(pStr, cBuf);
2745 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
2747 pBuf = create_text_surf_from_str16(pStr);
2749 dest.x = pWindow->size.x + adj_size(200);
2750 dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2752 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2754 FREESURFACE(pBuf);
2756 /* draw total (trade - corruption) */
2757 if (pCity->surplus[O_TRADE]) {
2758 dest.y =
2759 pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2760 dest.x = pWindow->size.x + adj_size(203);
2762 if (((pIcons->pBIG_Trade->w + 1) * pCity->surplus[O_TRADE]) > adj_size(200)) {
2763 step = (adj_size(200) - pIcons->pBIG_Trade->w) / (pCity->surplus[O_TRADE] - 1);
2764 } else {
2765 step = pIcons->pBIG_Trade->w + 1;
2768 for (i = 0; i < pCity->surplus[O_TRADE]; i++) {
2769 alphablit(pIcons->pBIG_Trade, NULL, pWindow->dst->surface, &dest);
2770 dest.x += step;
2774 /* corruption label */
2775 fc_snprintf(cBuf, sizeof(cBuf), _("Corruption: %d"),
2776 pCity->waste[O_TRADE]);
2778 copy_chars_to_string16(pStr, cBuf);
2779 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_CORRUPTION);
2781 pBuf = create_text_surf_from_str16(pStr);
2783 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2784 dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2786 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2788 FREESURFACE(pBuf);
2790 /* draw corruption */
2791 if (pCity->waste[O_TRADE] > 0) {
2792 dest.x = pWindow->size.x + adj_size(423);
2793 dest.y =
2794 pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2796 if (((pIcons->pBIG_Trade_Corr->w + 1) * pCity->waste[O_TRADE]) > adj_size(30)) {
2797 step =
2798 (adj_size(30) - pIcons->pBIG_Trade_Corr->w) / (pCity->waste[O_TRADE] - 1);
2799 } else {
2800 step = pIcons->pBIG_Trade_Corr->w + 1;
2803 for (i = 0; i < pCity->waste[O_TRADE]; i++) {
2804 alphablit(pIcons->pBIG_Trade_Corr, NULL, pWindow->dst->surface,
2805 &dest);
2806 dest.x -= step;
2810 /* ================================================================= */
2811 /* gold label */
2812 fc_snprintf(cBuf, sizeof(cBuf), _("Gold: %d (%d) per turn"),
2813 pCity->surplus[O_GOLD], pCity->prod[O_GOLD]);
2815 copy_chars_to_string16(pStr, cBuf);
2816 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2818 pBuf = create_text_surf_from_str16(pStr);
2820 dest.x = pWindow->size.x + adj_size(200);
2821 dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2823 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2825 FREESURFACE(pBuf);
2827 /* draw coins */
2828 count = pCity->surplus[O_GOLD];
2829 if (count) {
2831 if (count > 0) {
2832 pBuf = pIcons->pBIG_Coin;
2833 } else {
2834 count *= -1;
2835 pBuf = pIcons->pBIG_Coin_Corr;
2838 dest.y = pWindow->size.y + adj_size(359) + (adj_size(16) - pBuf->h) / 2;
2839 dest.x = pWindow->size.x + adj_size(203);
2841 if ((pBuf->w * count) > adj_size(110)) {
2842 step = (adj_size(110) - pBuf->w) / (count - 1);
2843 if (!step) {
2844 step = 1;
2845 count = 97;
2847 } else {
2848 step = pBuf->w;
2851 for (i = 0; i < count; i++) {
2852 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2853 dest.x += step;
2858 /* upkeep label */
2859 fc_snprintf(cBuf, sizeof(cBuf), _("Upkeep: %d"),
2860 pCity->prod[O_GOLD] - pCity->surplus[O_GOLD]);
2862 copy_chars_to_string16(pStr, cBuf);
2863 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_UPKEEP);
2865 pBuf = create_text_surf_from_str16(pStr);
2867 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2868 dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2870 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2872 FREESURFACE(pBuf);
2874 /* draw upkeep */
2875 count = pCity->surplus[O_GOLD];
2876 if (pCity->prod[O_GOLD] - count) {
2878 dest.x = pWindow->size.x + adj_size(423);
2879 dest.y = pWindow->size.y + adj_size(359)
2880 + (adj_size(16) - pIcons->pBIG_Coin_UpKeep->h) / 2;
2882 if (((pIcons->pBIG_Coin_UpKeep->w + 1) *
2883 (pCity->prod[O_GOLD] - count)) > adj_size(110)) {
2884 step = (adj_size(110) - pIcons->pBIG_Coin_UpKeep->w) /
2885 (pCity->prod[O_GOLD] - count - 1);
2886 } else {
2887 step = pIcons->pBIG_Coin_UpKeep->w + 1;
2890 for (i = 0; i < (pCity->prod[O_GOLD] - count); i++) {
2891 alphablit(pIcons->pBIG_Coin_UpKeep, NULL, pWindow->dst->surface,
2892 &dest);
2893 dest.x -= step;
2896 /* ================================================================= */
2897 /* science label */
2898 fc_snprintf(cBuf, sizeof(cBuf), _("Science: %d per turn"),
2899 pCity->prod[O_SCIENCE]);
2901 copy_chars_to_string16(pStr, cBuf);
2902 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SCIENCE);
2904 pBuf = create_text_surf_from_str16(pStr);
2906 dest.x = pWindow->size.x + adj_size(200);
2907 dest.y = pWindow->size.y + adj_size(376) + (adj_size(15) - pBuf->h) / 2;
2909 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2911 FREESURFACE(pBuf);
2913 /* draw colb */
2914 count = pCity->prod[O_SCIENCE];
2915 if (count) {
2917 dest.y =
2918 pWindow->size.y + adj_size(394) + (adj_size(16) - pIcons->pBIG_Colb->h) / 2;
2919 dest.x = pWindow->size.x + adj_size(203);
2921 if ((pIcons->pBIG_Colb->w * count) > adj_size(235)) {
2922 step = (adj_size(235) - pIcons->pBIG_Colb->w) / (count - 1);
2923 if (!step) {
2924 step = 1;
2925 count = 222;
2927 } else {
2928 step = pIcons->pBIG_Colb->w;
2931 for (i = 0; i < count; i++) {
2932 alphablit(pIcons->pBIG_Colb, NULL, pWindow->dst->surface, &dest);
2933 dest.x += step;
2936 /* ================================================================= */
2937 /* luxury label */
2938 fc_snprintf(cBuf, sizeof(cBuf), _("Luxury: %d per turn"),
2939 pCity->prod[O_LUXURY]);
2941 copy_chars_to_string16(pStr, cBuf);
2942 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2944 pBuf = create_text_surf_from_str16(pStr);
2946 dest.x = pWindow->size.x + adj_size(200);
2947 dest.y = pWindow->size.y + adj_size(412) + (adj_size(15) - pBuf->h) / 2;
2949 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2951 FREESURFACE(pBuf);
2953 /* draw luxury */
2954 if (pCity->prod[O_LUXURY]) {
2956 dest.y =
2957 pWindow->size.y + adj_size(429) + (adj_size(16) - pIcons->pBIG_Luxury->h) / 2;
2958 dest.x = pWindow->size.x + adj_size(203);
2960 if ((pIcons->pBIG_Luxury->w * pCity->prod[O_LUXURY]) > adj_size(235)) {
2961 step =
2962 (adj_size(235) - pIcons->pBIG_Luxury->w) / (pCity->prod[O_LUXURY] - 1);
2963 } else {
2964 step = pIcons->pBIG_Luxury->w;
2967 for (i = 0; i < pCity->prod[O_LUXURY]; i++) {
2968 alphablit(pIcons->pBIG_Luxury, NULL, pWindow->dst->surface, &dest);
2969 dest.x += step;
2972 /* ================================================================= */
2973 /* turns to grow label */
2974 count = city_turns_to_grow(pCity);
2975 if (count == 0) {
2976 fc_snprintf(cBuf, sizeof(cBuf), _("City growth: blocked"));
2977 } else if (count == FC_INFINITY) {
2978 fc_snprintf(cBuf, sizeof(cBuf), _("City growth: never"));
2979 } else if (count < 0) {
2980 /* turns until famine */
2981 fc_snprintf(cBuf, sizeof(cBuf),
2982 _("City shrinks: %d %s"), abs(count),
2983 PL_("turn", "turns", abs(count)));
2984 } else {
2985 fc_snprintf(cBuf, sizeof(cBuf),
2986 _("City growth: %d %s"), count,
2987 PL_("turn", "turns", count));
2990 copy_chars_to_string16(pStr, cBuf);
2992 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GROWTH);
2994 pBuf = create_text_surf_from_str16(pStr);
2996 dest.x = pWindow->size.x + adj_size(445) + (adj_size(192) - pBuf->w) / 2;
2997 dest.y = pWindow->size.y + adj_size(227);
2999 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3001 FREESURFACE(pBuf);
3004 count = (city_granary_size(city_size_get(pCity))) / 10;
3006 if (count > 12) {
3007 step = (adj_size(168) - pIcons->pBIG_Food->h) / adj_size((11 + count - 12));
3008 i = (count - 1) * step + 14;
3009 count = 12;
3010 } else {
3011 step = pIcons->pBIG_Food->h;
3012 i = count * step;
3015 /* food stock */
3017 /* FIXME: check if this code replacement is correct */
3018 /* if (city_has_building(pCity, improvement_by_number(B_GRANARY)) */
3019 /* || city_affected_by_wonder(pCity, B_PYRAMIDS)) { */
3021 if (get_city_bonus(pCity, EFT_GROWTH_FOOD) > 0) {
3023 /* with granary */
3024 /* stocks label */
3025 copy_chars_to_string16(pStr, _("Stock"));
3026 pBuf = create_text_surf_from_str16(pStr);
3028 dest.x = pWindow->size.x + adj_size(461) + (adj_size(76) - pBuf->w) / 2;
3029 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3031 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3033 FREESURFACE(pBuf);
3035 /* granary label */
3036 copy_chars_to_string16(pStr, _("Granary"));
3037 pBuf = create_text_surf_from_str16(pStr);
3039 dest.x = pWindow->size.x + adj_size(549) + (adj_size(76) - pBuf->w) / 2;
3040 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3042 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3044 FREESURFACE(pBuf);
3046 /* draw bcgd granary */
3047 dest.x = pWindow->size.x + adj_size(462);
3048 dest.y = pWindow->size.y + adj_size(260);
3049 dest.w = 70 + 4;
3050 dest.h = i + 4;
3052 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_GRANARY));
3054 putframe(pWindow->dst->surface,
3055 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3056 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3058 /* draw bcgd stocks*/
3059 dest.x = pWindow->size.x + adj_size(550);
3060 dest.y = pWindow->size.y + adj_size(260);
3062 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_STOCKS));
3064 putframe(pWindow->dst->surface,
3065 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3066 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3068 /* draw stocks icons */
3069 cost = city_granary_size(city_size_get(pCity));
3070 if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3071 count = cost;
3072 } else {
3073 if(pCity->surplus[O_FOOD] < 0) {
3074 count = pCity->food_stock;
3075 } else {
3076 count = pCity->food_stock + pCity->surplus[O_FOOD];
3079 cost /= 2;
3081 if(pCity->surplus[O_FOOD] < 0) {
3082 limit = pCity->food_stock + pCity->surplus[O_FOOD];
3083 if(limit < 0) {
3084 limit = 0;
3086 } else {
3087 limit = 0xffff;
3090 dest.x += 2;
3091 dest.y += 2;
3092 i = 0;
3093 pBuf = pIcons->pBIG_Food;
3094 while (count && cost) {
3095 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3096 dest.x += pBuf->w;
3097 count--;
3098 cost--;
3099 i++;
3100 if (dest.x > pWindow->size.x + adj_size(620)) {
3101 dest.x = pWindow->size.x + adj_size(552);
3102 dest.y += step;
3104 if(i > limit - 1) {
3105 pBuf = pIcons->pBIG_Food_Corr;
3106 } else {
3107 if(i > pCity->food_stock - 1)
3109 pBuf = pIcons->pBIG_Food_Surplus;
3113 /* draw granary icons */
3114 dest.x = pWindow->size.x + adj_size(462) + adj_size(2);
3115 dest.y = pWindow->size.y + adj_size(260) + adj_size(2);
3117 while (count) {
3118 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3119 dest.x += pBuf->w;
3120 count--;
3121 i++;
3122 if (dest.x > pWindow->size.x + adj_size(532)) {
3123 dest.x = pWindow->size.x + adj_size(464);
3124 dest.y += step;
3126 if(i > limit - 1) {
3127 pBuf = pIcons->pBIG_Food_Corr;
3128 } else {
3129 if(i > pCity->food_stock - 1)
3131 pBuf = pIcons->pBIG_Food_Surplus;
3136 } else {
3137 /* without granary */
3138 /* stocks label */
3139 copy_chars_to_string16(pStr, _("Stock"));
3140 pBuf = create_text_surf_from_str16(pStr);
3142 dest.x = pWindow->size.x + adj_size(461) + (adj_size(144) - pBuf->w) / 2;
3143 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3145 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3146 FREESURFACE(pBuf);
3148 /* food stock */
3150 /* draw bcgd */
3151 dest.x = pWindow->size.x + adj_size(462);
3152 dest.y = pWindow->size.y + adj_size(260);
3153 dest.w = adj_size(144);
3154 dest.h = i + adj_size(4);
3156 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_FOODSTOCK));
3158 putframe(pWindow->dst->surface,
3159 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3160 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3162 /* draw icons */
3163 cost = city_granary_size(city_size_get(pCity));
3164 if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3165 count = cost;
3166 } else {
3167 if(pCity->surplus[O_FOOD] < 0) {
3168 count = pCity->food_stock;
3169 } else {
3170 count = pCity->food_stock + pCity->surplus[O_FOOD];
3174 if(pCity->surplus[O_FOOD] < 0) {
3175 limit = pCity->food_stock + pCity->surplus[O_FOOD];
3176 if(limit < 0) {
3177 limit = 0;
3179 } else {
3180 limit = 0xffff;
3183 dest.x += adj_size(2);
3184 dest.y += adj_size(2);
3185 i = 0;
3186 pBuf = pIcons->pBIG_Food;
3187 while (count) {
3188 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3189 dest.x += pBuf->w;
3190 count--;
3191 i++;
3192 if (dest.x > pWindow->size.x + adj_size(602)) {
3193 dest.x = pWindow->size.x + adj_size(464);
3194 dest.y += step;
3196 if(i > limit - 1) {
3197 pBuf = pIcons->pBIG_Food_Corr;
3198 } else {
3199 if(i > pCity->food_stock - 1)
3201 pBuf = pIcons->pBIG_Food_Surplus;
3206 /* ================================================================= */
3208 /* draw productions shields progress */
3209 if (VUT_UTYPE == pCity->production.kind) {
3210 struct unit_type *pUnitType = pCity->production.value.utype;
3211 cost = utype_build_shield_cost(pUnitType);
3212 count = cost / 10;
3214 copy_chars_to_string16(pStr, utype_name_translation(pUnitType));
3215 pBuf = create_text_surf_from_str16(pStr);
3217 pBuf2 = get_unittype_surface(pUnitType, direction8_invalid());
3218 pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h), DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3220 /* blit unit icon */
3221 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3222 dest.y = pWindow->size.y + adj_size(233);
3224 alphablit(pBuf2, NULL, pWindow->dst->surface, &dest);
3226 dest.y += (pBuf2->h - pBuf->h) / 2;
3227 dest.x += pBuf2->w + adj_size(5);
3229 } else {
3230 struct impr_type *pImprove = pCity->production.value.building;
3232 if (improvement_has_flag(pImprove, IF_GOLD)) {
3234 if (pCityDlg->pBuy_Button
3235 && get_wstate(pCityDlg->pBuy_Button) != FC_WS_DISABLED) {
3236 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
3237 widget_redraw(pCityDlg->pBuy_Button);
3240 /* You can't see capitalization progres */
3241 count = 0;
3243 } else {
3245 if (city_can_buy(pCity) && pCityDlg->pBuy_Button
3246 && (get_wstate(pCityDlg->pBuy_Button) == FC_WS_DISABLED)) {
3247 set_wstate(pCityDlg->pBuy_Button, FC_WS_NORMAL);
3248 widget_redraw(pCityDlg->pBuy_Button);
3251 cost = impr_build_shield_cost(pImprove);
3252 count = cost / 10;
3256 copy_chars_to_string16(pStr, improvement_name_translation(pImprove));
3257 pBuf = create_text_surf_from_str16(pStr);
3259 pBuf2 = get_building_surface(pCity->production.value.building);
3260 pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h), DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3262 /* blit impr icon */
3263 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3264 dest.y = pWindow->size.y + adj_size(233);
3266 alphablit(pBuf2, NULL, pWindow->dst->surface, &dest);
3268 dest.y += (pBuf2->h - pBuf->h) / 2;
3269 dest.x += pBuf2->w + adj_size(5);
3272 /* blit unit/impr name */
3273 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3275 FREESURFACE(pBuf);
3276 FREESURFACE(pBuf2);
3278 if (count) {
3279 if (count > 11) {
3280 step = (adj_size(154) - pIcons->pBIG_Shield->h) / adj_size((10 + count - 11));
3282 if(!step) step = 1;
3284 i = (step * (count - 1)) + pIcons->pBIG_Shield->h;
3285 } else {
3286 step = pIcons->pBIG_Shield->h;
3287 i = count * step;
3290 /* draw sheild stock background */
3291 dest.x = pWindow->size.x + adj_size(28);
3292 dest.y = pWindow->size.y + adj_size(270);
3293 dest.w = adj_size(144);
3294 dest.h = i + adj_size(4);
3296 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_SHIELDSTOCK));
3297 putframe(pWindow->dst->surface,
3298 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3299 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3301 /* draw production progres text */
3302 dest.y = pWindow->size.y + adj_size(270) + dest.h + 1;
3304 if (pCity->shield_stock < cost) {
3305 count = city_production_turns_to_build(pCity, TRUE);
3306 if (count == 999) {
3307 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3308 pCity->shield_stock, cost, _("blocked"));
3309 } else {
3310 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %d %s",
3311 pCity->shield_stock, cost, count, PL_("turn", "turns", count));
3313 } else {
3314 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3315 pCity->shield_stock, cost, _("finished"));
3318 copy_chars_to_string16(pStr, cBuf);
3319 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
3321 pBuf = create_text_surf_from_str16(pStr);
3323 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - pBuf->w) / 2;
3325 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3327 FREESTRING16(pStr);
3328 FREESURFACE(pBuf);
3330 /* draw sheild stock */
3331 if (pCity->shield_stock + pCity->surplus[O_SHIELD] <= cost) {
3332 count = pCity->shield_stock + pCity->surplus[O_SHIELD];
3333 } else {
3334 count = cost;
3336 dest.x = pWindow->size.x + adj_size(29) + adj_size(2);
3337 dest.y = pWindow->size.y + adj_size(270) + adj_size(2);
3338 i = 0;
3340 pBuf = pIcons->pBIG_Shield;
3341 while (count > 0) {
3342 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3343 dest.x += pBuf->w;
3344 count--;
3345 if (dest.x > pWindow->size.x + adj_size(170)) {
3346 dest.x = pWindow->size.x + adj_size(31);
3347 dest.y += step;
3349 i++;
3350 if(i > pCity->shield_stock - 1) {
3351 pBuf = pIcons->pBIG_Shield_Surplus;
3356 /* count != 0 */
3357 /* ==================================================== */
3358 /* Draw Citizens */
3359 count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
3360 + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
3361 + city_specialists(pCity));
3363 pBuf = get_citizen_surface(CITIZEN_HAPPY, 0);
3365 if (count > 13) {
3366 step = (adj_size(440) - pBuf->w) / (adj_size(12 + count - 13));
3367 } else {
3368 step = pBuf->w;
3371 pCityDlg->citizen_step = step;
3373 dest.x = pWindow->size.x + adj_size(198);
3374 dest.y = pWindow->size.y + pWindow->area.y + adj_size(1) + (adj_size(22) - pBuf->h) / 2;
3376 pCityDlg->spec_area.x = pWindow->dst->dest_rect.x + dest.x;
3377 pCityDlg->spec_area.y = pWindow->dst->dest_rect.y + dest.y;
3378 pCityDlg->spec_area.w = count * step;
3379 pCityDlg->spec_area.h = pBuf->h;
3381 if (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]) {
3382 for (i = 0; i < pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]; i++) {
3383 pBuf = adj_surf(get_citizen_surface(CITIZEN_HAPPY, i));
3385 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3386 dest.x += step;
3387 FREESURFACE(pBuf);
3391 if (pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]) {
3392 for (i = 0; i < pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]; i++) {
3393 pBuf = adj_surf(get_citizen_surface(CITIZEN_CONTENT, i));
3395 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3396 dest.x += step;
3397 FREESURFACE(pBuf);
3401 if (pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]) {
3402 for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]; i++) {
3403 pBuf = adj_surf(get_citizen_surface(CITIZEN_UNHAPPY, i));
3405 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3406 dest.x += step;
3407 FREESURFACE(pBuf);
3411 if (pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]) {
3412 for (i = 0; i < pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]; i++) {
3413 pBuf = adj_surf(get_citizen_surface(CITIZEN_ANGRY, i));
3414 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3415 dest.x += step;
3416 FREESURFACE(pBuf);
3420 spe_max = specialist_count();
3421 for (spe = 0; spe < spe_max; spe++) {
3422 if (pCity->specialists[spe] > 0) {
3423 pBuf = adj_surf(get_citizen_surface(CITIZEN_SPECIALIST + spe, i));
3425 for (i = 0; i < pCity->specialists[spe]; i++) {
3426 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3427 dest.x += step;
3429 FREESURFACE(pBuf);
3433 /* ==================================================== */
3436 switch (pCityDlg->page) {
3437 case INFO_PAGE:
3438 redraw_info_city_dialog(pWindow, pCity);
3439 break;
3441 case HAPPINESS_PAGE:
3442 redraw_happyness_city_dialog(pWindow, pCity);
3443 break;
3445 case ARMY_PAGE:
3446 redraw_army_city_dialog(pWindow, pCity);
3447 break;
3449 case SUPPORTED_UNITS_PAGE:
3450 redraw_supported_units_city_dialog(pWindow, pCity);
3451 break;
3453 case MISC_PAGE:
3454 redraw_misc_city_dialog(pWindow, pCity);
3455 break;
3457 default:
3458 break;
3462 /* redraw "sell improvement" dialog */
3463 redraw_group(pCityDlg->pBeginCityMenuWidgetList,
3464 pCityDlg->pEndCityMenuWidgetList, 0);
3466 widget_mark_dirty(pWindow);
3469 /* ============================================================== */
3471 /**************************************************************************
3472 Recreate improvement list for city dialog.
3473 **************************************************************************/
3474 static void rebuild_imprm_list(struct city *pCity)
3476 int count = 0;
3477 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
3478 struct widget *pAdd_Dock, *pBuf, *pLast;
3479 SDL_Surface *pLogo = NULL;
3480 SDL_String16 *pStr = NULL;
3481 struct player *pOwner = city_owner(pCity);
3482 int prev_y = 0;
3484 if(!pCityDlg->pImprv) {
3485 pCityDlg->pImprv = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3488 /* free old list */
3489 if (pCityDlg->pImprv->pEndWidgetList) {
3490 del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
3491 pCityDlg->pImprv->pEndWidgetList);
3492 pCityDlg->pImprv->pEndWidgetList = NULL;
3493 pCityDlg->pImprv->pBeginWidgetList = NULL;
3494 pCityDlg->pImprv->pEndActiveWidgetList = NULL;
3495 pCityDlg->pImprv->pBeginActiveWidgetList = NULL;
3496 pCityDlg->pImprv->pActiveWidgetList = NULL;
3497 FC_FREE(pCityDlg->pImprv->pScroll);
3500 pAdd_Dock = pCityDlg->pAdd_Point;
3501 pBuf = pLast = pAdd_Dock;
3503 /* allock new */
3504 city_built_iterate(pCity, pImprove) {
3506 pStr = create_str16_from_char(city_improvement_name_translation(pCity, pImprove), adj_font(10));
3507 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_IMPR);
3509 pStr->style |= TTF_STYLE_BOLD;
3511 pLogo = get_building_surface(pImprove);
3512 pLogo = ResizeSurfaceBox(pLogo, adj_size(22), adj_size(22), 1, TRUE, TRUE);
3514 pBuf = create_iconlabel(pLogo, pWindow->dst, pStr,
3515 (WF_FREE_THEME | WF_RESTORE_BACKGROUND));
3517 pBuf->size.x = pWindow->size.x + adj_size(450);
3518 pBuf->size.y = pWindow->size.y + adj_size(66) + prev_y;
3520 prev_y += pBuf->size.h;
3522 pBuf->size.w = adj_size(165);
3523 pBuf->action = sell_imprvm_dlg_callback;
3525 if (!pCityDlg->pCity->did_sell
3526 && !is_wonder(pImprove) && (pOwner == client.conn.playing)) {
3527 set_wstate(pBuf, FC_WS_NORMAL);
3530 pBuf->ID = MAX_ID - improvement_number(pImprove) - 3000;
3531 DownAdd(pBuf, pAdd_Dock);
3532 pAdd_Dock = pBuf;
3534 count++;
3536 if (count > 7) {
3537 set_wflag(pBuf, WF_HIDDEN);
3540 } city_built_iterate_end;
3542 if (count) {
3543 pCityDlg->pImprv->pEndWidgetList = pLast->prev;
3544 pCityDlg->pImprv->pEndActiveWidgetList = pCityDlg->pImprv->pEndWidgetList;
3545 pCityDlg->pImprv->pBeginWidgetList = pBuf;
3546 pCityDlg->pImprv->pBeginActiveWidgetList = pCityDlg->pImprv->pBeginWidgetList;
3548 if (count > 7) {
3549 pCityDlg->pImprv->pActiveWidgetList = pCityDlg->pImprv->pEndActiveWidgetList;
3551 create_vertical_scrollbar(pCityDlg->pImprv, 1, 7, TRUE, TRUE);
3553 setup_vertical_scrollbar_area(pCityDlg->pImprv->pScroll,
3554 pWindow->size.x + adj_size(635),
3555 pWindow->size.y + adj_size(66),
3556 adj_size(155), TRUE);
3561 /**************************************************************************
3562 Recreate citydialog title.
3563 **************************************************************************/
3564 static void rebuild_citydlg_title_str(struct widget *pWindow,
3565 struct city *pCity)
3567 char cBuf[512];
3569 fc_snprintf(cBuf, sizeof(cBuf),
3570 _("City of %s (Population %s citizens)"),
3571 city_name_get(pCity),
3572 population_to_text(city_population(pCity)));
3574 if (city_unhappy(pCity)) {
3575 fc_strlcat(cBuf, _(" - DISORDER"), sizeof(cBuf));
3576 } else {
3577 if (city_celebrating(pCity)) {
3578 fc_strlcat(cBuf, _(" - celebrating"), sizeof(cBuf));
3579 } else {
3580 if (city_happy(pCity)) {
3581 fc_strlcat(cBuf, _(" - happy"), sizeof(cBuf));
3586 if (cma_is_city_under_agent(pCity, NULL)) {
3587 fc_strlcat(cBuf, _(" - under Citizen Governor control."), sizeof(cBuf));
3590 copy_chars_to_string16(pWindow->string16, cBuf);
3594 /* ========================= Public ================================== */
3596 /**************************************************************************
3597 Pop up (or bring to the front) a dialog for the given city. It may or
3598 may not be modal.
3599 **************************************************************************/
3600 void real_city_dialog_popup(struct city *pCity)
3602 struct widget *pWindow = NULL, *pBuf = NULL;
3603 SDL_Surface *pLogo = NULL;
3604 SDL_String16 *pStr = NULL;
3605 int cs;
3606 struct player *pOwner = city_owner(pCity);
3607 SDL_Rect area;
3609 if (pCityDlg) {
3610 return;
3613 menus_update();
3615 pCityDlg = fc_calloc(1, sizeof(struct city_dialog));
3616 pCityDlg->pCity = pCity;
3617 pCityDlg->page = ARMY_PAGE;
3619 pStr = create_string16(NULL, 0, adj_font(12));
3620 pStr->style |= TTF_STYLE_BOLD;
3621 pWindow = create_window(NULL, pStr, adj_size(640), adj_size(480), 0);
3623 rebuild_citydlg_title_str(pWindow, pCity);
3625 pWindow->action = city_dlg_callback;
3626 set_wstate(pWindow, FC_WS_NORMAL);
3628 add_to_gui_list(ID_CITY_DLG_WINDOW, pWindow);
3630 pCityDlg->pEndCityWidgetList = pWindow;
3632 /* create window background */
3633 pLogo = theme_get_background(theme, BACKGROUND_CITYDLG);
3634 if (resize_window(pWindow, pLogo, NULL, adj_size(640), adj_size(480))) {
3635 FREESURFACE(pLogo);
3638 pLogo = get_city_gfx();
3639 alphablit(pLogo, NULL, pWindow->theme, NULL);
3641 area = pWindow->area;
3643 widget_set_position(pWindow,
3644 (Main.screen->w - pWindow->size.w) / 2,
3645 (Main.screen->h - pWindow->size.h) / 2);
3647 /* ============================================================= */
3649 /* close dialog button */
3650 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3651 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3652 pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
3653 adj_font(12));
3654 pBuf->action = exit_city_dlg_callback;
3655 pBuf->size.x = area.x + area.w - pBuf->size.w;
3656 pBuf->size.y = pWindow->size.y + adj_size(2);
3657 pBuf->key = SDLK_ESCAPE;
3658 set_wstate(pBuf, FC_WS_NORMAL);
3659 add_to_gui_list(ID_CITY_DLG_EXIT_BUTTON, pBuf);
3661 /* -------- */
3663 pBuf = create_themeicon(current_theme->Army_Icon, pWindow->dst,
3664 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3665 pBuf->info_label = create_str16_from_char(_("Present units"),
3666 adj_font(12));
3667 pBuf->action = army_city_dlg_callback;
3668 pBuf->size.x = area.x + adj_size(2) + ((adj_size(183) - 5 * pBuf->size.w) / 6);
3669 pBuf->size.y = area.y + adj_size(2);
3670 set_wstate(pBuf, FC_WS_NORMAL);
3671 add_to_gui_list(ID_CITY_DLG_ARMY_BUTTON, pBuf);
3672 /* -------- */
3674 pBuf = create_themeicon(current_theme->Support_Icon, pWindow->dst,
3675 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3676 pBuf->info_label = create_str16_from_char(_("Supported units"),
3677 adj_font(12));
3678 pBuf->action = supported_unit_city_dlg_callback;
3679 pBuf->size.x =
3680 area.x + adj_size(2) + 2 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + pBuf->size.w;
3681 pBuf->size.y = area.y + adj_size(2);
3683 set_wstate(pBuf, FC_WS_NORMAL);
3684 add_to_gui_list(ID_CITY_DLG_SUPPORT_BUTTON, pBuf);
3685 /* -------- */
3687 pBuf = create_themeicon(current_theme->Happy_Icon, pWindow->dst,
3688 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3689 pBuf->info_label = create_str16_from_char(_("Happiness"), adj_font(12));
3690 pBuf->action = happy_city_dlg_callback;
3691 pBuf->size.x =
3692 area.x + adj_size(2) + 3 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 2 * pBuf->size.w;
3693 pBuf->size.y = area.y + adj_size(2);
3694 set_wstate(pBuf, FC_WS_NORMAL);
3695 add_to_gui_list(ID_CITY_DLG_HAPPY_BUTTON, pBuf);
3696 /* -------- */
3698 pBuf = create_themeicon(current_theme->INFO_Icon, pWindow->dst,
3699 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3700 pBuf->info_label = create_str16_from_char(_("City info"), adj_font(12));
3701 pBuf->action = info_city_dlg_callback;
3702 pBuf->size.x =
3703 area.x + adj_size(4) + 4 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 3 * pBuf->size.w;
3704 pBuf->size.y = area.y + adj_size(2);
3705 set_wstate(pBuf, FC_WS_NORMAL);
3706 add_to_gui_list(ID_CITY_DLG_INFO_BUTTON, pBuf);
3708 pCityDlg->pAdd_Point = pBuf;
3709 pCityDlg->pBeginCityWidgetList = pBuf;
3710 /* ===================================================== */
3711 rebuild_imprm_list(pCity);
3712 /* ===================================================== */
3714 pLogo = get_scaled_city_map(pCity);
3716 pBuf = create_themelabel(pLogo, pWindow->dst, NULL,
3717 pLogo->w, pLogo->h, WF_SELLECT_WITHOUT_BAR);
3719 pCityDlg->pResource_Map = pBuf;
3721 pBuf->action = resource_map_city_dlg_callback;
3722 if (!cma_is_city_under_agent(pCity, NULL) && (pOwner == client.conn.playing)) {
3723 set_wstate(pBuf, FC_WS_NORMAL);
3725 pBuf->size.x = area.x + adj_size(193) + (adj_size(249) - pBuf->size.w) / 2;
3726 pBuf->size.y = area.y + adj_size(41) + (adj_size(158) - pBuf->size.h) / 2;
3727 add_to_gui_list(ID_CITY_DLG_RESOURCE_MAP, pBuf);
3728 /* -------- */
3730 pBuf = create_themeicon(current_theme->Options_Icon, pWindow->dst,
3731 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3732 pBuf->info_label = create_str16_from_char(_("City options"), adj_font(12));
3733 pBuf->action = options_city_dlg_callback;
3734 pBuf->size.x =
3735 area.x + adj_size(4) + 5 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 4 * pBuf->size.w;
3736 pBuf->size.y = area.y + adj_size(2);
3737 if (pOwner == client.conn.playing) {
3738 set_wstate(pBuf, FC_WS_NORMAL);
3740 add_to_gui_list(ID_CITY_DLG_OPTIONS_BUTTON, pBuf);
3741 /* -------- */
3743 pBuf = create_themeicon(current_theme->PROD_Icon, pWindow->dst,
3744 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3745 pBuf->info_label = create_str16_from_char(_("Change production"),
3746 adj_font(12));
3747 pBuf->action = change_prod_dlg_callback;
3748 pBuf->size.x = area.x + adj_size(7);
3749 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3750 if (pOwner == client.conn.playing) {
3751 set_wstate(pBuf, FC_WS_NORMAL);
3753 pBuf->key = SDLK_c;
3754 add_to_gui_list(ID_CITY_DLG_CHANGE_PROD_BUTTON, pBuf);
3755 /* -------- */
3757 pBuf = create_themeicon(current_theme->Buy_PROD_Icon, pWindow->dst,
3758 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3759 pBuf->info_label = create_str16_from_char(_("Hurry production"),
3760 adj_font(12));
3761 pBuf->action = buy_prod_city_dlg_callback;
3762 pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2));
3763 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3764 pCityDlg->pBuy_Button = pBuf;
3765 pBuf->key = SDLK_h;
3766 if (city_can_buy(pCity)) {
3767 set_wstate(pBuf, FC_WS_NORMAL);
3769 add_to_gui_list(ID_CITY_DLG_PROD_BUY_BUTTON, pBuf);
3770 /* -------- */
3772 pBuf = create_themeicon(current_theme->CMA_Icon, pWindow->dst,
3773 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3774 pBuf->info_label = create_str16_from_char(_("Citizen Governor"),
3775 adj_font(12));
3776 pBuf->action = cma_city_dlg_callback;
3777 pBuf->key = SDLK_a;
3778 pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2)) * 2;
3779 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3780 if (pOwner == client.conn.playing) {
3781 set_wstate(pBuf, FC_WS_NORMAL);
3783 add_to_gui_list(ID_CITY_DLG_CMA_BUTTON, pBuf);
3785 /* -------- */
3787 pBuf = create_themeicon(current_theme->L_ARROW_Icon, pWindow->dst,
3788 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3789 pBuf->info_label = create_str16_from_char(_("Previous city"),
3790 adj_font(12));
3791 pBuf->action = next_prev_city_dlg_callback;
3792 pBuf->size.x = area.x + adj_size(220) - pBuf->size.w - adj_size(8);
3793 pBuf->size.y = area.y + area.h - pBuf->size.h;
3794 if (pOwner == client.conn.playing) {
3795 set_wstate(pBuf, FC_WS_NORMAL);
3797 pBuf->key = SDLK_LEFT;
3798 pBuf->mod = KMOD_LSHIFT;
3799 add_to_gui_list(ID_CITY_DLG_PREV_BUTTON, pBuf);
3800 /* -------- */
3802 pBuf = create_themeicon(current_theme->R_ARROW_Icon, pWindow->dst,
3803 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3804 pBuf->info_label = create_str16_from_char(_("Next city"), adj_font(12));
3805 pBuf->action = next_prev_city_dlg_callback;
3806 pBuf->size.x = area.x + adj_size(420) + adj_size(2);
3807 pBuf->size.y = area.y + area.h - pBuf->size.h;
3808 if (pOwner == client.conn.playing) {
3809 set_wstate(pBuf, FC_WS_NORMAL);
3811 pBuf->key = SDLK_RIGHT;
3812 pBuf->mod = KMOD_LSHIFT;
3813 add_to_gui_list(ID_CITY_DLG_NEXT_BUTTON, pBuf);
3814 /* -------- */
3816 pBuf = create_edit_from_chars(NULL, pWindow->dst, city_name_get(pCity),
3817 adj_font(10), adj_size(200), WF_RESTORE_BACKGROUND);
3818 pBuf->action = new_name_city_dlg_callback;
3819 pBuf->size.x = area.x + (area.w - pBuf->size.w) / 2;
3820 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(2);
3821 if (pOwner == client.conn.playing) {
3822 set_wstate(pBuf, FC_WS_NORMAL);
3825 pCityDlg->pCity_Name_Edit = pBuf;
3826 add_to_gui_list(ID_CITY_DLG_NAME_EDIT, pBuf);
3828 pCityDlg->pBeginCityWidgetList = pBuf;
3830 /* check if Citizen Icons style was loaded */
3831 cs = style_of_city(pCity);
3833 if (cs != pIcons->style) {
3834 reload_citizens_icons(cs);
3837 /* ===================================================== */
3838 if ((city_unhappy(pCity) || city_celebrating(pCity)
3839 || city_happy(pCity))) {
3840 SDL_Client_Flags |= CF_CITY_STATUS_SPECIAL;
3842 /* ===================================================== */
3844 redraw_city_dialog(pCity);
3845 flush_dirty();
3848 /**************************************************************************
3849 Close the dialog for the given city.
3850 **************************************************************************/
3851 void popdown_city_dialog(struct city *pCity)
3853 if (city_dialog_is_open(pCity)) {
3854 del_city_dialog();
3856 flush_dirty();
3858 SDL_Client_Flags &= ~CF_CITY_STATUS_SPECIAL;
3859 menus_update();
3863 /**************************************************************************
3864 Close all cities dialogs.
3865 **************************************************************************/
3866 void popdown_all_city_dialogs(void)
3868 if (pCityDlg) {
3869 popdown_city_dialog(pCityDlg->pCity);
3873 /**************************************************************************
3874 Refresh (update) all data for the given city's dialog.
3875 **************************************************************************/
3876 void real_city_dialog_refresh(struct city *pCity)
3878 if (city_dialog_is_open(pCity)) {
3879 redraw_city_dialog(pCityDlg->pCity);
3880 flush_dirty();
3884 /**************************************************************************
3885 Update city dialogs when the given unit's status changes. This
3886 typically means updating both the unit's home city (if any) and the
3887 city in which it is present (if any).
3888 **************************************************************************/
3889 void refresh_unit_city_dialogs(struct unit *pUnit)
3892 struct city *pCity_sup = game_city_by_number(pUnit->homecity);
3893 struct city *pCity_pre = tile_city(unit_tile(pUnit));
3895 if (pCityDlg && ((pCityDlg->pCity == pCity_sup)
3896 || (pCityDlg->pCity == pCity_pre))) {
3897 free_city_units_lists();
3898 redraw_city_dialog(pCityDlg->pCity);
3899 flush_dirty();
3904 /**************************************************************************
3905 Return whether the dialog for the given city is open.
3906 **************************************************************************/
3907 bool city_dialog_is_open(struct city *pCity)
3909 return (pCityDlg && (pCityDlg->pCity == pCity));