JSON protocol: fix field_addr memory leak.
[freeciv.git] / client / gui-sdl2 / repodlgs.c
blob518fe3526c6b1b8403570c4a3a58db20030becc2
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 repodlgs.c - description
16 -------------------
17 begin : Nov 15 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 /* utility */
27 #include "fcintl.h"
28 #include "log.h"
30 /* common */
31 #include "game.h"
32 #include "government.h"
33 #include "research.h"
34 #include "unitlist.h"
36 /* client */
37 #include "client_main.h"
38 #include "text.h"
40 /* gui-sdl2 */
41 #include "cityrep.h"
42 #include "colors.h"
43 #include "dialogs.h"
44 #include "graphics.h"
45 #include "gui_id.h"
46 #include "gui_main.h"
47 #include "gui_tilespec.h"
48 #include "helpdlg.h"
49 #include "mapctrl.h"
50 #include "mapview.h"
51 #include "sprite.h"
52 #include "themespec.h"
53 #include "widget.h"
55 #include "repodlgs.h"
58 /* ===================================================================== */
59 /* ======================== Active Units Report ======================== */
60 /* ===================================================================== */
61 static struct ADVANCED_DLG *pUnitsDlg = NULL;
62 static struct SMALL_DLG *pUnits_Upg_Dlg = NULL;
64 struct units_entry {
65 int active_count;
66 int upkeep[O_LAST];
67 int building_count;
68 int soonest_completions;
71 /**************************************************************************
72 Fill unit types specific report data + totals.
73 **************************************************************************/
74 static void get_units_report_data(struct units_entry *entries,
75 struct units_entry *total)
77 int time_to_build;
79 memset(entries, '\0', U_LAST * sizeof(struct units_entry));
80 memset(total, '\0', sizeof(struct units_entry));
81 for (time_to_build = 0; time_to_build < U_LAST; time_to_build++) {
82 entries[time_to_build].soonest_completions = FC_INFINITY;
85 unit_list_iterate(client.conn.playing->units, punit) {
86 Unit_type_id uti = utype_index(unit_type_get(punit));
88 (entries[uti].active_count)++;
89 (total->active_count)++;
90 if (punit->homecity) {
91 output_type_iterate(o) {
92 entries[uti].upkeep[o] += punit->upkeep[o];
93 total->upkeep[o] += punit->upkeep[o];
94 } output_type_iterate_end;
96 } unit_list_iterate_end;
98 city_list_iterate(client.conn.playing->cities, pCity) {
99 if (VUT_UTYPE == pCity->production.kind) {
100 struct unit_type *pUnitType = pCity->production.value.utype;
101 Unit_type_id uti = utype_index(pUnitType);
102 int num_units;
104 /* Account for build slots in city */
105 (void) city_production_build_units(pCity, TRUE, &num_units);
106 /* Unit is in progress even if it won't be done this turn */
107 num_units = MAX(num_units, 1);
108 (entries[uti].building_count) += num_units;
109 (total->building_count) += num_units;
110 entries[uti].soonest_completions =
111 MIN(entries[uti].soonest_completions,
112 city_production_turns_to_build(pCity, TRUE));
114 } city_list_iterate_end;
117 /**************************************************************************
118 User interacted with Units Report button.
119 **************************************************************************/
120 static int units_dialog_callback(struct widget *pWindow)
122 if (Main.event.button.button == SDL_BUTTON_LEFT) {
123 move_window_group(pUnitsDlg->pBeginWidgetList, pWindow);
126 return -1;
129 /* --------------------------------------------------------------- */
131 /**************************************************************************
132 User interacted with accept button of the unit upgrade dialog.
133 **************************************************************************/
134 static int ok_upgrade_unit_window_callback(struct widget *pWidget)
136 if (Main.event.button.button == SDL_BUTTON_LEFT) {
137 int ut1 = MAX_ID - pWidget->ID;
139 /* popdown upgrade dlg */
140 popdown_window_group_dialog(pUnits_Upg_Dlg->pBeginWidgetList,
141 pUnits_Upg_Dlg->pEndWidgetList);
142 FC_FREE(pUnits_Upg_Dlg);
144 dsend_packet_unit_type_upgrade(&client.conn, ut1);
147 return -1;
150 /**************************************************************************
151 User interacted with Upgrade Obsolete button of the unit upgrade dialog.
152 **************************************************************************/
153 static int upgrade_unit_window_callback(struct widget *pWindow)
155 if (Main.event.button.button == SDL_BUTTON_LEFT) {
156 move_window_group(pUnits_Upg_Dlg->pBeginWidgetList, pWindow);
159 return -1;
162 /**************************************************************************
163 User interacted with Cancel button of the unit upgrade dialog.
164 **************************************************************************/
165 static int cancel_upgrade_unit_callback(struct widget *pWidget)
167 if (Main.event.button.button == SDL_BUTTON_LEFT) {
168 if (pUnits_Upg_Dlg) {
169 popdown_window_group_dialog(pUnits_Upg_Dlg->pBeginWidgetList,
170 pUnits_Upg_Dlg->pEndWidgetList);
171 FC_FREE(pUnits_Upg_Dlg);
172 flush_dirty();
176 return -1;
179 /**************************************************************************
180 Open dialog for upgrading units.
181 **************************************************************************/
182 static int popup_upgrade_unit_callback(struct widget *pWidget)
184 if (Main.event.button.button == SDL_BUTTON_LEFT) {
185 struct unit_type *ut1;
186 struct unit_type *ut2;
187 int value;
188 char tBuf[128], cBuf[128];
189 struct widget *pBuf = NULL, *pWindow;
190 utf8_str *pstr;
191 SDL_Surface *pText;
192 SDL_Rect dst;
193 SDL_Rect area;
195 ut1 = utype_by_number(MAX_ID - pWidget->ID);
197 if (pUnits_Upg_Dlg) {
198 return 1;
201 set_wstate(pWidget, FC_WS_NORMAL);
202 selected_widget = NULL;
203 widget_redraw(pWidget);
204 widget_mark_dirty(pWidget);
206 pUnits_Upg_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
208 ut2 = can_upgrade_unittype(client.conn.playing, ut1);
209 value = unit_upgrade_price(client.conn.playing, ut1, ut2);
211 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
212 "Treasury contains %d gold.",
213 client_player()->economic.gold),
214 client_player()->economic.gold);
216 fc_snprintf(cBuf, sizeof(cBuf),
217 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
218 PL_("Upgrade as many %s to %s as possible for %d gold each?\n%s",
219 "Upgrade as many %s to %s as possible for %d gold each?\n%s",
220 value),
221 utype_name_translation(ut1),
222 utype_name_translation(ut2),
223 value, tBuf);
225 pstr = create_utf8_from_char(_("Upgrade Obsolete Units"), adj_font(12));
226 pstr->style |= TTF_STYLE_BOLD;
228 pWindow = create_window_skeleton(NULL, pstr, 0);
230 pWindow->action = upgrade_unit_window_callback;
231 set_wstate(pWindow, FC_WS_NORMAL);
233 add_to_gui_list(ID_WINDOW, pWindow);
235 pUnits_Upg_Dlg->pEndWidgetList = pWindow;
237 area = pWindow->area;
239 /* ============================================================= */
241 /* create text label */
242 pstr = create_utf8_from_char(cBuf, adj_font(10));
243 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
244 pstr->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
246 pText = create_text_surf_from_utf8(pstr);
247 FREEUTF8STR(pstr);
249 area.h += (pText->h + adj_size(10));
250 area.w = MAX(area.w, pText->w + adj_size(20));
252 /* cancel button */
253 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
254 pWindow->dst, _("No"),
255 adj_font(12), 0);
257 pBuf->action = cancel_upgrade_unit_callback;
258 set_wstate(pBuf, FC_WS_NORMAL);
260 area.h += (pBuf->size.h + adj_size(20));
262 add_to_gui_list(ID_BUTTON, pBuf);
264 if (value <= client.conn.playing->economic.gold) {
265 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
266 _("Yes"), adj_font(12), 0);
268 pBuf->action = ok_upgrade_unit_window_callback;
269 set_wstate(pBuf, FC_WS_NORMAL);
271 add_to_gui_list(pWidget->ID, pBuf);
272 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
273 pBuf->next->size.w = pBuf->size.w;
274 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
275 } else {
276 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
278 /* ============================================ */
280 pUnits_Upg_Dlg->pBeginWidgetList = pBuf;
282 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
283 (pWindow->size.w - pWindow->area.w) + area.w,
284 (pWindow->size.h - pWindow->area.h) + area.h);
286 widget_set_position(pWindow,
287 pUnitsDlg->pEndWidgetList->size.x +
288 (pUnitsDlg->pEndWidgetList->size.w - pWindow->size.w) / 2,
289 pUnitsDlg->pEndWidgetList->size.y +
290 (pUnitsDlg->pEndWidgetList->size.h - pWindow->size.h) / 2);
292 /* setup rest of widgets */
293 /* label */
294 dst.x = area.x + (area.w - pText->w) / 2;
295 dst.y = area.y + adj_size(10);
296 alphablit(pText, NULL, pWindow->theme, &dst, 255);
297 FREESURFACE(pText);
299 /* cancel button */
300 pBuf = pWindow->prev;
301 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(10);
303 if (value <= client.conn.playing->economic.gold) {
304 /* sell button */
305 pBuf = pBuf->prev;
306 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
307 pBuf->size.y = pBuf->next->size.y;
309 /* cancel button */
310 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
311 } else {
312 /* x position of cancel button */
313 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
316 /* ================================================== */
317 /* redraw */
318 redraw_group(pUnits_Upg_Dlg->pBeginWidgetList, pWindow, 0);
320 widget_mark_dirty(pWindow);
321 flush_dirty();
324 return -1;
327 /**************************************************************************
328 User interacted with units dialog Close Dialog button.
329 **************************************************************************/
330 static int exit_units_dlg_callback(struct widget *pWidget)
332 if (Main.event.button.button == SDL_BUTTON_LEFT) {
333 if (pUnitsDlg) {
334 if (pUnits_Upg_Dlg) {
335 del_group_of_widgets_from_gui_list(pUnits_Upg_Dlg->pBeginWidgetList,
336 pUnits_Upg_Dlg->pEndWidgetList);
337 FC_FREE(pUnits_Upg_Dlg);
339 popdown_window_group_dialog(pUnitsDlg->pBeginWidgetList,
340 pUnitsDlg->pEndWidgetList);
341 FC_FREE(pUnitsDlg->pScroll);
342 FC_FREE(pUnitsDlg);
343 flush_dirty();
347 return -1;
350 /**************************************************************************
351 Rebuild the units report.
352 **************************************************************************/
353 static void real_activeunits_report_dialog_update(struct units_entry *units,
354 struct units_entry *total)
356 SDL_Color bg_color = {255, 255, 255, 136};
357 struct widget *pBuf = NULL;
358 struct widget *pWindow, *pLast;
359 utf8_str *pstr;
360 SDL_Surface *pText1, *pText2, *pText3 , *pText4, *pText5, *pLogo;
361 int w = 0 , count, ww, hh = 0, name_w = 0;
362 char cbuf[64];
363 SDL_Rect dst;
364 bool upgrade = FALSE;
365 SDL_Rect area;
367 if (pUnitsDlg) {
368 popdown_window_group_dialog(pUnitsDlg->pBeginWidgetList,
369 pUnitsDlg->pEndWidgetList);
370 } else {
371 pUnitsDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
374 fc_snprintf(cbuf, sizeof(cbuf), _("active"));
375 pstr = create_utf8_from_char(cbuf, adj_font(10));
376 pstr->style |= SF_CENTER;
377 pText1 = create_text_surf_from_utf8(pstr);
379 fc_snprintf(cbuf, sizeof(cbuf), _("under\nconstruction"));
380 copy_chars_to_utf8_str(pstr, cbuf);
381 pText2 = create_text_surf_from_utf8(pstr);
383 fc_snprintf(cbuf, sizeof(cbuf), _("soonest\ncompletion"));
384 copy_chars_to_utf8_str(pstr, cbuf);
385 pText5 = create_text_surf_from_utf8(pstr);
387 fc_snprintf(cbuf, sizeof(cbuf), _("Total"));
388 copy_chars_to_utf8_str(pstr, cbuf);
389 pText3 = create_text_surf_from_utf8(pstr);
391 fc_snprintf(cbuf, sizeof(cbuf), _("Units"));
392 copy_chars_to_utf8_str(pstr, cbuf);
393 pText4 = create_text_surf_from_utf8(pstr);
394 name_w = pText4->w;
395 FREEUTF8STR(pstr);
397 /* --------------- */
398 pstr = create_utf8_from_char(_("Units Report"), adj_font(12));
399 pstr->style |= TTF_STYLE_BOLD;
401 pWindow = create_window_skeleton(NULL, pstr, 0);
402 set_wstate(pWindow, FC_WS_NORMAL);
403 pWindow->action = units_dialog_callback;
405 add_to_gui_list(ID_UNITS_DIALOG_WINDOW, pWindow);
407 pUnitsDlg->pEndWidgetList = pWindow;
409 area = pWindow->area;
411 /* ------------------------- */
412 /* exit button */
413 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
414 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
415 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"), adj_font(12));
416 pBuf->action = exit_units_dlg_callback;
417 set_wstate(pBuf, FC_WS_NORMAL);
418 pBuf->key = SDLK_ESCAPE;
420 add_to_gui_list(ID_BUTTON, pBuf);
421 /* ------------------------- */
422 /* totals */
423 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->active_count);
425 pstr = create_utf8_from_char(cbuf, adj_font(10));
426 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
428 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
429 WF_RESTORE_BACKGROUND);
431 area.h += pBuf->size.h;
432 pBuf->size.w = pText1->w + adj_size(6);
433 add_to_gui_list(ID_LABEL, pBuf);
434 /* ---------------------------------------------- */
435 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->upkeep[O_SHIELD]);
437 pstr = create_utf8_from_char(cbuf, adj_font(10));
438 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
440 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
442 pBuf->size.w = pText1->w;
443 add_to_gui_list(ID_LABEL, pBuf);
444 /* ---------------------------------------------- */
445 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->upkeep[O_FOOD]);
447 pstr = create_utf8_from_char(cbuf, adj_font(10));
448 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
450 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
452 pBuf->size.w = pText1->w;
453 add_to_gui_list(ID_LABEL, pBuf);
454 /* ---------------------------------------------- */
455 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->upkeep[O_GOLD]);
457 pstr = create_utf8_from_char(cbuf, adj_font(10));
458 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
460 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
462 pBuf->size.w = pText1->w;
463 add_to_gui_list(ID_LABEL, pBuf);
464 /* ---------------------------------------------- */
465 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->building_count);
467 pstr = create_utf8_from_char(cbuf, adj_font(10));
468 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
470 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
471 WF_RESTORE_BACKGROUND);
473 pBuf->size.w = pText2->w + adj_size(6);
474 add_to_gui_list(ID_LABEL, pBuf);
476 /* ------------------------- */
477 pLast = pBuf;
478 count = 0;
479 unit_type_iterate(i) {
480 if ((units[utype_index(i)].active_count > 0)
481 || (units[utype_index(i)].building_count > 0)) {
482 upgrade = (can_upgrade_unittype(client.conn.playing, i) != NULL);
484 /* unit type icon */
485 pBuf = create_iconlabel(adj_surf(get_unittype_surface(i, direction8_invalid())), pWindow->dst, NULL,
486 WF_RESTORE_BACKGROUND | WF_FREE_THEME);
487 if (count > adj_size(72)) {
488 set_wflag(pBuf, WF_HIDDEN);
490 hh = pBuf->size.h;
491 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
493 /* unit type name */
494 pstr = create_utf8_from_char(utype_name_translation(i), adj_font(12));
495 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
496 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
497 (WF_RESTORE_BACKGROUND | WF_SELECT_WITHOUT_BAR));
498 if (upgrade) {
499 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
500 pBuf->action = popup_upgrade_unit_callback;
501 set_wstate(pBuf, FC_WS_NORMAL);
502 } else {
503 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_UNITSREP_TEXT);
505 pBuf->string_utf8->style &= ~SF_CENTER;
506 if (count > adj_size(72)) {
507 set_wflag(pBuf , WF_HIDDEN);
509 hh = MAX(hh, pBuf->size.h);
510 name_w = MAX(pBuf->size.w, name_w);
511 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
513 /* active */
514 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].active_count);
515 pstr = create_utf8_from_char(cbuf, adj_font(10));
516 pstr->style |= SF_CENTER;
517 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
518 WF_RESTORE_BACKGROUND);
519 if (count > adj_size(72)) {
520 set_wflag(pBuf, WF_HIDDEN);
522 hh = MAX(hh, pBuf->size.h);
523 pBuf->size.w = pText1->w + adj_size(6);
524 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
526 /* shield upkeep */
527 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_SHIELD]);
528 pstr = create_utf8_from_char(cbuf, adj_font(10));
529 pstr->style |= SF_CENTER;
530 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
531 WF_RESTORE_BACKGROUND);
532 if (count > adj_size(72)) {
533 set_wflag(pBuf, WF_HIDDEN);
535 hh = MAX(hh, pBuf->size.h);
536 pBuf->size.w = pText1->w;
537 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
539 /* food upkeep */
540 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_FOOD]);
541 pstr = create_utf8_from_char(cbuf, adj_font(10));
542 pstr->style |= SF_CENTER;
543 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
544 WF_RESTORE_BACKGROUND);
545 if (count > adj_size(72)) {
546 set_wflag(pBuf, WF_HIDDEN);
549 hh = MAX(hh, pBuf->size.h);
550 pBuf->size.w = pText1->w;
551 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
553 /* gold upkeep */
554 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_GOLD]);
555 pstr = create_utf8_from_char(cbuf, adj_font(10));
556 pstr->style |= SF_CENTER;
557 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
558 WF_RESTORE_BACKGROUND);
559 if (count > adj_size(72)) {
560 set_wflag(pBuf, WF_HIDDEN);
563 hh = MAX(hh, pBuf->size.h);
564 pBuf->size.w = pText1->w;
565 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
567 /* building */
568 if (units[utype_index(i)].building_count > 0) {
569 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].building_count);
570 } else {
571 fc_snprintf(cbuf, sizeof(cbuf), "--");
573 pstr = create_utf8_from_char(cbuf, adj_font(10));
574 pstr->style |= SF_CENTER;
575 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
576 WF_RESTORE_BACKGROUND);
577 if (count > adj_size(72)) {
578 set_wflag(pBuf, WF_HIDDEN);
580 hh = MAX(hh, pBuf->size.h);
581 pBuf->size.w = pText2->w + adj_size(6);
582 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
584 /* soonest completion */
585 if (units[utype_index(i)].building_count > 0) {
586 fc_snprintf(cbuf, sizeof(cbuf), "%d %s", units[utype_index(i)].soonest_completions,
587 PL_("turn", "turns", units[utype_index(i)].soonest_completions));
588 } else {
589 fc_snprintf(cbuf, sizeof(cbuf), "--");
592 pstr = create_utf8_from_char(cbuf, adj_font(10));
593 pstr->style |= SF_CENTER;
594 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
595 WF_RESTORE_BACKGROUND);
597 if (count > adj_size(72)) {
598 set_wflag(pBuf, WF_HIDDEN);
600 hh = MAX(hh, pBuf->size.h);
601 pBuf->size.w = pText5->w + adj_size(6);
602 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
604 count += adj_size(8);
605 area.h += (hh/2);
607 } unit_type_iterate_end;
609 pUnitsDlg->pBeginWidgetList = pBuf;
610 area.w = MAX(area.w, (tileset_full_tile_width(tileset) * 2 + name_w + adj_size(15))
611 + (adj_size(4) * pText1->w + adj_size(46)) + (pText2->w + adj_size(16))
612 + (pText5->w + adj_size(6)) + adj_size(2));
613 if (count > 0) {
614 pUnitsDlg->pEndActiveWidgetList = pLast->prev;
615 pUnitsDlg->pBeginActiveWidgetList = pUnitsDlg->pBeginWidgetList;
616 if (count > adj_size(80)) {
617 pUnitsDlg->pActiveWidgetList = pUnitsDlg->pEndActiveWidgetList;
618 if (pUnitsDlg->pScroll) {
619 pUnitsDlg->pScroll->count = count;
621 ww = create_vertical_scrollbar(pUnitsDlg, 8, 10, TRUE, TRUE);
622 area.w += ww;
623 area.h = (hh + 9 * (hh/2) + adj_size(10));
624 } else {
625 area.h += hh/2;
627 } else {
628 area.h = adj_size(50);
631 area.h += pText1->h + adj_size(10);
632 area.w += adj_size(2);
634 pLogo = theme_get_background(theme, BACKGROUND_UNITSREP);
635 resize_window(pWindow, pLogo, NULL,
636 (pWindow->size.w - pWindow->area.w) + area.w,
637 (pWindow->size.h - pWindow->area.h) + area.h);
638 FREESURFACE(pLogo);
640 #if 0
641 pLogo = SDL_DisplayFormat(pWindow->theme);
642 FREESURFACE(pWindow->theme);
643 pWindow->theme = pLogo;
644 pLogo = NULL;
645 #endif /* 0 */
647 area = pWindow->area;
649 widget_set_position(pWindow,
650 (main_window_width() - pWindow->size.w) / 2,
651 (main_window_height() - pWindow->size.h) / 2);
653 /* exit button */
654 pBuf = pWindow->prev;
655 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
656 pBuf->size.y = pWindow->size.y + adj_size(2);
658 /* totals background and label */
659 dst.x = area.x + adj_size(2);
660 dst.y = area.y + area.h - (pText3->h + adj_size(2)) - adj_size(2);
661 dst.w = name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5);
662 dst.h = pText3->h + adj_size(2);
663 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
665 create_frame(pWindow->theme,
666 dst.x, dst.y, dst.w, dst.h - 1,
667 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
669 dst.y += 1;
670 dst.x += ((name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5)) - pText3->w) / 2;
671 alphablit(pText3, NULL, pWindow->theme, &dst, 255);
672 FREESURFACE(pText3);
674 /* total active widget */
675 pBuf = pBuf->prev;
676 pBuf->size.x = area.x + name_w
677 + tileset_full_tile_width(tileset) * 2 + adj_size(17);
678 pBuf->size.y = dst.y;
680 /* total shields cost widget */
681 pBuf = pBuf->prev;
682 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
683 pBuf->size.y = dst.y;
685 /* total food cost widget */
686 pBuf = pBuf->prev;
687 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
688 pBuf->size.y = dst.y;
690 /* total gold cost widget */
691 pBuf = pBuf->prev;
692 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
693 pBuf->size.y = dst.y;
695 /* total building count widget */
696 pBuf = pBuf->prev;
697 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
698 pBuf->size.y = dst.y;
700 /* units background and labels */
701 dst.x = area.x + adj_size(2);
702 dst.y = area.y + 1;
703 dst.w = name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5);
704 dst.h = pText4->h + adj_size(2);
705 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
707 create_frame(pWindow->theme,
708 dst.x, dst.y, dst.w, dst.h - 1,
709 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
711 dst.y += 1;
712 dst.x += ((name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5))- pText4->w) / 2;
713 alphablit(pText4, NULL, pWindow->theme, &dst, 255);
714 FREESURFACE(pText4);
716 /* active count background and label */
717 dst.x = area.x + adj_size(2) + name_w + tileset_full_tile_width(tileset) * 2 + adj_size(15);
718 dst.y = area.y + 1;
719 dst.w = pText1->w + adj_size(6);
720 dst.h = area.h - adj_size(3);
721 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
723 create_frame(pWindow->theme,
724 dst.x, dst.y, dst.w, dst.h - 1,
725 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
727 dst.x += adj_size(3);
728 alphablit(pText1, NULL, pWindow->theme, &dst, 255);
729 ww = pText1->w;
730 hh = pText1->h;
731 FREESURFACE(pText1);
733 /* shields cost background and label */
734 dst.x += (ww + adj_size(13));
735 w = dst.x;
736 dst.w = ww;
737 dst.h = area.h - adj_size(3);
738 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
740 create_frame(pWindow->theme,
741 dst.x, dst.y, dst.w, dst.h - 1,
742 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
744 dst.y = area.y + adj_size(3);
745 dst.x += ((ww - pIcons->pBIG_Shield->w) / 2);
746 alphablit(pIcons->pBIG_Shield, NULL, pWindow->theme, &dst, 255);
748 /* food cost background and label */
749 dst.x = w + ww + adj_size(10);
750 w = dst.x;
751 dst.y = area.y + 1;
752 dst.w = ww;
753 dst.h = area.h - adj_size(3);
754 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
756 create_frame(pWindow->theme,
757 dst.x, dst.y, dst.w, dst.h - 1,
758 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
760 dst.y = area.y + adj_size(3);
761 dst.x += ((ww - pIcons->pBIG_Food->w) / 2);
762 alphablit(pIcons->pBIG_Food, NULL, pWindow->theme, &dst, 255);
764 /* gold cost background and label */
765 dst.x = w + ww + adj_size(10);
766 w = dst.x;
767 dst.y = area.y + 1;
768 dst.w = ww;
769 dst.h = area.h - adj_size(3);
770 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
772 create_frame(pWindow->theme,
773 dst.x, dst.y, dst.w, dst.h - 1,
774 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
776 dst.y = area.y + adj_size(3);
777 dst.x += ((ww - pIcons->pBIG_Coin->w) / 2);
778 alphablit(pIcons->pBIG_Coin, NULL, pWindow->theme, &dst, 255);
780 /* building count background and label */
781 dst.x = w + ww + adj_size(10);
782 dst.y = area.y + 1;
783 dst.w = pText2->w + adj_size(6);
784 ww = pText2->w + adj_size(6);
785 w = dst.x;
786 dst.h = area.h - adj_size(3);
787 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
789 create_frame(pWindow->theme,
790 dst.x, dst.y, dst.w, dst.h - 1,
791 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
793 dst.x += adj_size(3);
794 alphablit(pText2, NULL, pWindow->theme, &dst, 255);
795 FREESURFACE(pText2);
797 /* building count background and label */
798 dst.x = w + ww + adj_size(10);
799 dst.y = area.y + 1;
800 dst.w = pText5->w + adj_size(6);
801 dst.h = area.h - adj_size(3);
802 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
804 create_frame(pWindow->theme,
805 dst.x, dst.y, dst.w, dst.h - 1,
806 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
808 dst.x += adj_size(3);
809 alphablit(pText5, NULL, pWindow->theme, &dst, 255);
810 FREESURFACE(pText5);
812 if (count) {
813 int start_x = area.x + adj_size(2);
814 int start_y = area.y + hh + adj_size(3);
815 int mod = 0;
817 pBuf = pBuf->prev;
818 while (TRUE) {
819 /* Unit type icon */
820 pBuf->size.x = start_x + (mod ? tileset_full_tile_width(tileset) : 0);
821 pBuf->size.y = start_y;
822 hh = pBuf->size.h;
823 mod ^= 1;
825 /* Unit type name */
826 pBuf = pBuf->prev;
827 pBuf->size.w = name_w;
828 pBuf->size.x = start_x + tileset_full_tile_width(tileset) * 2 + adj_size(5);
829 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
831 /* Number active */
832 pBuf = pBuf->prev;
833 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
834 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
836 /* Shield upkeep */
837 pBuf = pBuf->prev;
838 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
839 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
841 /* Food upkeep */
842 pBuf = pBuf->prev;
843 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
844 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
846 /* Gold upkeep */
847 pBuf = pBuf->prev;
848 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
849 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
851 /* Number under construction */
852 pBuf = pBuf->prev;
853 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
854 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
856 /* Soonest completion */
857 pBuf = pBuf->prev;
858 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
859 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
861 start_y += (hh >> 1);
862 if (pBuf == pUnitsDlg->pBeginActiveWidgetList) {
863 break;
865 pBuf = pBuf->prev;
868 if (pUnitsDlg->pScroll) {
869 setup_vertical_scrollbar_area(pUnitsDlg->pScroll,
870 area.x + area.w, area.y,
871 area.h, TRUE);
875 /* ----------------------------------- */
876 redraw_group(pUnitsDlg->pBeginWidgetList, pWindow, 0);
877 widget_mark_dirty(pWindow);
879 flush_dirty();
882 /**************************************************************************
883 update the units report.
884 **************************************************************************/
885 void real_units_report_dialog_update(void)
887 if (pUnitsDlg) {
888 struct units_entry units[U_LAST];
889 struct units_entry units_total;
890 struct widget *pWidget, *pbuf;
891 bool is_in_list = FALSE;
892 char cbuf[32];
893 bool upgrade;
894 bool search_finished;
896 get_units_report_data(units, &units_total);
898 /* find if there are new units entry (if not then rebuild all) */
899 pWidget = pUnitsDlg->pEndActiveWidgetList; /* icon of first list entry */
900 unit_type_iterate(i) {
901 if ((units[utype_index(i)].active_count > 0)
902 || (units[utype_index(i)].building_count > 0)) {
903 is_in_list = FALSE;
905 pbuf = pWidget; /* unit type icon */
906 while (pbuf) {
907 if ((MAX_ID - pbuf->ID) == utype_number(i)) {
908 is_in_list = TRUE;
909 pWidget = pbuf;
910 break;
912 if (pbuf->prev->prev->prev->prev->prev->prev->prev ==
913 pUnitsDlg->pBeginActiveWidgetList) {
914 break;
917 /* first widget of next list entry */
918 pbuf = pbuf->prev->prev->prev->prev->prev->prev->prev->prev;
921 if (!is_in_list) {
922 real_activeunits_report_dialog_update(units, &units_total);
923 return;
926 } unit_type_iterate_end;
928 /* update list */
929 pWidget = pUnitsDlg->pEndActiveWidgetList;
930 unit_type_iterate(i) {
931 pbuf = pWidget; /* first widget (icon) of the first list entry */
933 if ((units[utype_index(i)].active_count > 0) || (units[utype_index(i)].building_count > 0)) {
934 /* the player has at least one unit of this type */
936 search_finished = FALSE;
937 while (!search_finished) {
938 if ((MAX_ID - pbuf->ID) == utype_number(i)) { /* list entry for this unit type found */
940 upgrade = (can_upgrade_unittype(client.conn.playing, i) != NULL);
942 pbuf = pbuf->prev; /* unit type name */
943 if (upgrade) {
944 pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
945 pbuf->action = popup_upgrade_unit_callback;
946 set_wstate(pbuf, FC_WS_NORMAL);
949 pbuf = pbuf->prev; /* active */
950 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].active_count);
951 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
953 pbuf = pbuf->prev; /* shield upkeep */
954 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_SHIELD]);
955 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
957 pbuf = pbuf->prev; /* food upkeep */
958 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_FOOD]);
959 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
961 pbuf = pbuf->prev; /* gold upkeep */
962 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_GOLD]);
963 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
965 pbuf = pbuf->prev; /* building */
966 if (units[utype_index(i)].building_count > 0) {
967 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].building_count);
968 } else {
969 fc_snprintf(cbuf, sizeof(cbuf), "--");
971 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
973 pbuf = pbuf->prev; /* soonest completion */
974 if (units[utype_index(i)].building_count > 0) {
975 fc_snprintf(cbuf, sizeof(cbuf), "%d %s", units[utype_index(i)].soonest_completions,
976 PL_("turn", "turns", units[utype_index(i)].soonest_completions));
977 } else {
978 fc_snprintf(cbuf, sizeof(cbuf), "--");
980 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
982 pWidget = pbuf->prev; /* icon of next unit type */
984 search_finished = TRUE;
986 } else { /* list entry for this unit type not found yet */
988 /* search it */
989 pbuf = pWidget->next;
990 do {
991 del_widget_from_vertical_scroll_widget_list(pUnitsDlg, pbuf->prev);
992 } while (((MAX_ID - pbuf->prev->ID) != utype_number(i))
993 && (pbuf->prev != pUnitsDlg->pBeginActiveWidgetList));
995 if (pbuf->prev == pUnitsDlg->pBeginActiveWidgetList) {
996 /* list entry not found - can this really happen? */
997 del_widget_from_vertical_scroll_widget_list(pUnitsDlg, pbuf->prev);
998 pWidget = pbuf->prev; /* pUnitsDlg->pBeginActiveWidgetList */
999 search_finished = TRUE;
1000 } else {
1001 /* found it */
1002 pbuf = pbuf->prev; /* first widget (icon) of list entry */
1006 } else { /* player has no unit of this type */
1007 if (pbuf && pbuf->next != pUnitsDlg->pBeginActiveWidgetList) {
1008 if (utype_number(i) < (MAX_ID - pbuf->ID)) {
1009 continue;
1010 } else {
1011 pbuf = pbuf->next;
1012 do {
1013 del_widget_from_vertical_scroll_widget_list(pUnitsDlg,
1014 pbuf->prev);
1015 } while (((MAX_ID - pbuf->prev->ID) == utype_number(i))
1016 && (pbuf->prev != pUnitsDlg->pBeginActiveWidgetList));
1017 if (pbuf->prev == pUnitsDlg->pBeginActiveWidgetList) {
1018 del_widget_from_vertical_scroll_widget_list(pUnitsDlg,
1019 pbuf->prev);
1021 pWidget = pbuf->prev;
1025 } unit_type_iterate_end;
1027 /* -------------------------------------- */
1029 /* total active */
1030 pbuf = pUnitsDlg->pEndWidgetList->prev->prev;
1031 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.active_count);
1032 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1034 /* total shields cost */
1035 pbuf = pbuf->prev;
1036 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.upkeep[O_SHIELD]);
1037 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1039 /* total food cost widget */
1040 pbuf = pbuf->prev;
1041 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.upkeep[O_FOOD]);
1042 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1044 /* total gold cost widget */
1045 pbuf = pbuf->prev;
1046 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.upkeep[O_GOLD]);
1047 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1049 /* total building count */
1050 pbuf = pbuf->prev;
1051 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.building_count);
1052 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1054 /* -------------------------------------- */
1055 redraw_group(pUnitsDlg->pBeginWidgetList, pUnitsDlg->pEndWidgetList, 0);
1056 widget_mark_dirty(pUnitsDlg->pEndWidgetList);
1058 flush_dirty();
1062 /**************************************************************************
1063 Popup (or raise) the units report (F2). It may or may not be modal.
1064 **************************************************************************/
1065 void units_report_dialog_popup(bool make_modal)
1067 struct units_entry units[U_LAST];
1068 struct units_entry units_total;
1070 if (pUnitsDlg) {
1071 return;
1074 get_units_report_data(units, &units_total);
1075 real_activeunits_report_dialog_update(units, &units_total);
1078 /**************************************************************************
1079 Popdown the units report.
1080 **************************************************************************/
1081 void units_report_dialog_popdown(void)
1083 if (pUnitsDlg) {
1084 if (pUnits_Upg_Dlg) {
1085 del_group_of_widgets_from_gui_list(pUnits_Upg_Dlg->pBeginWidgetList,
1086 pUnits_Upg_Dlg->pEndWidgetList);
1087 FC_FREE(pUnits_Upg_Dlg);
1089 popdown_window_group_dialog(pUnitsDlg->pBeginWidgetList,
1090 pUnitsDlg->pEndWidgetList);
1091 FC_FREE(pUnitsDlg->pScroll);
1092 FC_FREE(pUnitsDlg);
1096 /* ===================================================================== */
1097 /* ======================== Economy Report ============================= */
1098 /* ===================================================================== */
1099 static struct ADVANCED_DLG *pEconomyDlg = NULL;
1100 static struct SMALL_DLG *pEconomy_Sell_Dlg = NULL;
1102 struct rates_move {
1103 int min, max, tax, x, gov_max;
1104 int *src_rate, *dst_rate;
1105 struct widget *pHoriz_Src, *pHoriz_Dst;
1106 struct widget *pLabel_Src, *pLabel_Dst;
1109 /**************************************************************************
1110 User interacted with Economy Report window.
1111 **************************************************************************/
1112 static int economy_dialog_callback(struct widget *pWindow)
1114 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1115 move_window_group(pEconomyDlg->pBeginWidgetList, pWindow);
1118 return -1;
1121 /**************************************************************************
1122 User interacted with Economy dialog Close Dialog button.
1123 **************************************************************************/
1124 static int exit_economy_dialog_callback(struct widget *pWidget)
1126 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1127 if (pEconomyDlg) {
1128 if (pEconomy_Sell_Dlg) {
1129 del_group_of_widgets_from_gui_list(pEconomy_Sell_Dlg->pBeginWidgetList,
1130 pEconomy_Sell_Dlg->pEndWidgetList);
1131 FC_FREE(pEconomy_Sell_Dlg);
1133 popdown_window_group_dialog(pEconomyDlg->pBeginWidgetList,
1134 pEconomyDlg->pEndWidgetList);
1135 FC_FREE(pEconomyDlg->pScroll);
1136 FC_FREE(pEconomyDlg);
1137 set_wstate(get_tax_rates_widget(), FC_WS_NORMAL);
1138 widget_redraw(get_tax_rates_widget());
1139 widget_mark_dirty(get_tax_rates_widget());
1140 flush_dirty();
1144 return -1;
1147 /**************************************************************************
1148 Toggle Rates dialog locking checkbox.
1149 **************************************************************************/
1150 static int toggle_block_callback(struct widget *pCheckBox)
1152 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1153 switch (pCheckBox->ID) {
1154 case ID_CHANGE_TAXRATE_DLG_LUX_BLOCK_CHECKBOX:
1155 SDL_Client_Flags ^= CF_CHANGE_TAXRATE_LUX_BLOCK;
1156 return -1;
1158 case ID_CHANGE_TAXRATE_DLG_SCI_BLOCK_CHECKBOX:
1159 SDL_Client_Flags ^= CF_CHANGE_TAXRATE_SCI_BLOCK;
1160 return -1;
1162 default:
1163 return -1;
1167 return -1;
1170 /**************************************************************************
1171 User released mouse button while adjusting rates.
1172 **************************************************************************/
1173 static Uint16 report_scroll_mouse_button_up(SDL_MouseButtonEvent *pButtonEvent,
1174 void *pData)
1176 return (Uint16)ID_SCROLLBAR;
1179 /**************************************************************************
1180 User moved a mouse while adjusting rates.
1181 **************************************************************************/
1182 static Uint16 report_scroll_mouse_motion_handler(SDL_MouseMotionEvent *pMotionEvent,
1183 void *pData)
1185 struct rates_move *pMotion = (struct rates_move *)pData;
1186 struct widget *pTax_Label = pEconomyDlg->pEndWidgetList->prev->prev;
1187 struct widget *pbuf = NULL;
1188 char cbuf[8];
1189 int dir, inc, x, *buf_rate = NULL;
1191 pMotionEvent->x -= pMotion->pHoriz_Src->dst->dest_rect.x;
1193 if ((abs(pMotionEvent->x - pMotion->x) > 7)
1194 && (pMotionEvent->x >= pMotion->min)
1195 && (pMotionEvent->x <= pMotion->max)) {
1197 /* set up directions */
1198 if (pMotionEvent->xrel > 0) {
1199 dir = 15;
1200 inc = 10;
1201 } else {
1202 dir = -15;
1203 inc = -10;
1206 /* make checks */
1207 x = pMotion->pHoriz_Src->size.x;
1208 if (((x + dir) <= pMotion->max) && ((x + dir) >= pMotion->min)) {
1209 /* src in range */
1210 if (pMotion->pHoriz_Dst) {
1211 x = pMotion->pHoriz_Dst->size.x;
1212 if (((x + (-1 * dir)) > pMotion->max) || ((x + (-1 * dir)) < pMotion->min)) {
1213 /* dst out of range */
1214 if (pMotion->tax + (-1 * inc) <= pMotion->gov_max
1215 && pMotion->tax + (-1 * inc) >= 0) {
1216 /* tax in range */
1217 pbuf = pMotion->pHoriz_Dst;
1218 pMotion->pHoriz_Dst = NULL;
1219 buf_rate = pMotion->dst_rate;
1220 pMotion->dst_rate = &pMotion->tax;
1221 pMotion->pLabel_Dst = pTax_Label;
1222 } else {
1223 pMotion->x = pMotion->pHoriz_Src->size.x;
1224 return ID_ERROR;
1227 } else {
1228 if (pMotion->tax + (-1 * inc) > pMotion->gov_max
1229 || pMotion->tax + (-1 * inc) < 0) {
1230 pMotion->x = pMotion->pHoriz_Src->size.x;
1231 return ID_ERROR;
1235 /* undraw scrollbars */
1236 widget_undraw(pMotion->pHoriz_Src);
1237 widget_mark_dirty(pMotion->pHoriz_Src);
1239 if (pMotion->pHoriz_Dst) {
1240 widget_undraw(pMotion->pHoriz_Dst);
1241 widget_mark_dirty(pMotion->pHoriz_Dst);
1244 pMotion->pHoriz_Src->size.x += dir;
1245 if (pMotion->pHoriz_Dst) {
1246 pMotion->pHoriz_Dst->size.x -= dir;
1249 *pMotion->src_rate += inc;
1250 *pMotion->dst_rate -= inc;
1252 fc_snprintf(cbuf, sizeof(cbuf), "%d%%", *pMotion->src_rate);
1253 copy_chars_to_utf8_str(pMotion->pLabel_Src->string_utf8, cbuf);
1254 fc_snprintf(cbuf, sizeof(cbuf), "%d%%", *pMotion->dst_rate);
1255 copy_chars_to_utf8_str(pMotion->pLabel_Dst->string_utf8, cbuf);
1257 /* redraw label */
1258 widget_redraw(pMotion->pLabel_Src);
1259 widget_mark_dirty(pMotion->pLabel_Src);
1261 widget_redraw(pMotion->pLabel_Dst);
1262 widget_mark_dirty(pMotion->pLabel_Dst);
1264 /* redraw scroolbar */
1265 if (get_wflags(pMotion->pHoriz_Src) & WF_RESTORE_BACKGROUND) {
1266 refresh_widget_background(pMotion->pHoriz_Src);
1268 widget_redraw(pMotion->pHoriz_Src);
1269 widget_mark_dirty(pMotion->pHoriz_Src);
1271 if (pMotion->pHoriz_Dst) {
1272 if (get_wflags(pMotion->pHoriz_Dst) & WF_RESTORE_BACKGROUND) {
1273 refresh_widget_background(pMotion->pHoriz_Dst);
1275 widget_redraw(pMotion->pHoriz_Dst);
1276 widget_mark_dirty(pMotion->pHoriz_Dst);
1279 flush_dirty();
1281 if (pbuf != NULL) {
1282 pMotion->pHoriz_Dst = pbuf;
1283 pMotion->pLabel_Dst = pMotion->pHoriz_Dst->prev;
1284 pMotion->dst_rate = buf_rate;
1285 pbuf = NULL;
1288 pMotion->x = pMotion->pHoriz_Src->size.x;
1290 } /* if */
1292 return ID_ERROR;
1296 /**************************************************************************
1297 Handle Rates sliders.
1298 **************************************************************************/
1299 static int horiz_taxrate_callback(struct widget *pHoriz_Src)
1301 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1302 struct rates_move pMotion;
1304 pMotion.pHoriz_Src = pHoriz_Src;
1305 pMotion.pLabel_Src = pHoriz_Src->prev;
1307 switch (pHoriz_Src->ID) {
1308 case ID_CHANGE_TAXRATE_DLG_LUX_SCROLLBAR:
1309 if (SDL_Client_Flags & CF_CHANGE_TAXRATE_LUX_BLOCK) {
1310 goto END;
1312 pMotion.src_rate = (int *)pHoriz_Src->data.ptr;
1313 pMotion.pHoriz_Dst = pHoriz_Src->prev->prev->prev; /* sci */
1314 pMotion.dst_rate = (int *)pMotion.pHoriz_Dst->data.ptr;
1315 pMotion.tax = 100 - *pMotion.src_rate - *pMotion.dst_rate;
1316 if ((SDL_Client_Flags & CF_CHANGE_TAXRATE_SCI_BLOCK)) {
1317 if (pMotion.tax <= get_player_bonus(client.conn.playing, EFT_MAX_RATES)) {
1318 pMotion.pHoriz_Dst = NULL; /* tax */
1319 pMotion.dst_rate = &pMotion.tax;
1320 } else {
1321 goto END; /* all blocked */
1325 break;
1327 case ID_CHANGE_TAXRATE_DLG_SCI_SCROLLBAR:
1328 if ((SDL_Client_Flags & CF_CHANGE_TAXRATE_SCI_BLOCK)) {
1329 goto END;
1331 pMotion.src_rate = (int *)pHoriz_Src->data.ptr;
1332 pMotion.pHoriz_Dst = pHoriz_Src->next->next->next; /* lux */
1333 pMotion.dst_rate = (int *)pMotion.pHoriz_Dst->data.ptr;
1334 pMotion.tax = 100 - *pMotion.src_rate - *pMotion.dst_rate;
1335 if (SDL_Client_Flags & CF_CHANGE_TAXRATE_LUX_BLOCK) {
1336 if (pMotion.tax <= get_player_bonus(client.conn.playing, EFT_MAX_RATES)) {
1337 /* tax */
1338 pMotion.pHoriz_Dst = NULL;
1339 pMotion.dst_rate = &pMotion.tax;
1340 } else {
1341 goto END; /* all blocked */
1345 break;
1347 default:
1348 return -1;
1351 if (pMotion.pHoriz_Dst) {
1352 pMotion.pLabel_Dst = pMotion.pHoriz_Dst->prev;
1353 } else {
1354 /* tax label */
1355 pMotion.pLabel_Dst = pEconomyDlg->pEndWidgetList->prev->prev;
1358 pMotion.min = pHoriz_Src->next->size.x + pHoriz_Src->next->size.w + adj_size(2);
1359 pMotion.gov_max = get_player_bonus(client.conn.playing, EFT_MAX_RATES);
1360 pMotion.max = pMotion.min + pMotion.gov_max * 1.5;
1361 pMotion.x = pHoriz_Src->size.x;
1363 MOVE_STEP_Y = 0;
1364 /* Filter mouse motion events */
1365 SDL_SetEventFilter(FilterMouseMotionEvents, NULL);
1366 gui_event_loop((void *)(&pMotion), NULL, NULL, NULL, NULL, NULL,
1367 report_scroll_mouse_button_up,
1368 report_scroll_mouse_motion_handler);
1369 /* Turn off Filter mouse motion events */
1370 SDL_SetEventFilter(NULL, NULL);
1371 MOVE_STEP_Y = DEFAULT_MOVE_STEP;
1373 END:
1374 unselect_widget_action();
1375 selected_widget = pHoriz_Src;
1376 set_wstate(pHoriz_Src, FC_WS_SELECTED);
1377 widget_redraw(pHoriz_Src);
1378 widget_flush(pHoriz_Src);
1381 return -1;
1384 /**************************************************************************
1385 User interacted with Update button of the Rates.
1386 **************************************************************************/
1387 static int apply_taxrates_callback(struct widget *pButton)
1389 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1390 struct widget *pBuf;
1391 int science, luxury, tax;
1393 if (C_S_RUNNING != client_state()) {
1394 return -1;
1397 /* Science Scrollbar */
1398 pBuf = pButton->next->next;
1399 science = *(int *)pBuf->data.ptr;
1401 /* Luxuries Scrollbar */
1402 pBuf = pBuf->next->next->next;
1403 luxury = *(int *)pBuf->data.ptr;
1405 /* Tax */
1406 tax = 100 - luxury - science;
1408 if (tax != client.conn.playing->economic.tax
1409 || science != client.conn.playing->economic.science
1410 || luxury != client.conn.playing->economic.luxury) {
1411 dsend_packet_player_rates(&client.conn, tax, luxury, science);
1414 widget_redraw(pButton);
1415 widget_flush(pButton);
1418 return -1;
1421 /**************************************************************************
1422 Set economy dialog widgets enabled.
1423 **************************************************************************/
1424 static void enable_economy_dlg(void)
1426 /* lux lock */
1427 struct widget *pBuf = pEconomyDlg->pEndWidgetList->prev->prev->prev->prev->prev->prev;
1429 set_wstate(pBuf, FC_WS_NORMAL);
1431 /* lux scrollbar */
1432 pBuf = pBuf->prev;
1433 set_wstate(pBuf, FC_WS_NORMAL);
1435 /* sci lock */
1436 pBuf = pBuf->prev->prev;
1437 set_wstate(pBuf, FC_WS_NORMAL);
1439 /* sci scrollbar */
1440 pBuf = pBuf->prev;
1441 set_wstate(pBuf, FC_WS_NORMAL);
1443 /* update button */
1444 pBuf = pBuf->prev->prev;
1445 set_wstate(pBuf, FC_WS_NORMAL);
1447 /* cancel button */
1448 pBuf = pBuf->prev;
1449 set_wstate(pBuf, FC_WS_NORMAL);
1451 set_group_state(pEconomyDlg->pBeginActiveWidgetList,
1452 pEconomyDlg->pEndActiveWidgetList, FC_WS_NORMAL);
1453 if (pEconomyDlg->pScroll && pEconomyDlg->pActiveWidgetList) {
1454 set_wstate(pEconomyDlg->pScroll->pUp_Left_Button, FC_WS_NORMAL);
1455 set_wstate(pEconomyDlg->pScroll->pDown_Right_Button, FC_WS_NORMAL);
1456 set_wstate(pEconomyDlg->pScroll->pScrollBar, FC_WS_NORMAL);
1460 /**************************************************************************
1461 Set economy dialog widgets disabled.
1462 **************************************************************************/
1463 static void disable_economy_dlg(void)
1465 /* lux lock */
1466 struct widget *pBuf = pEconomyDlg->pEndWidgetList->prev->prev->prev->prev->prev->prev;
1468 set_wstate(pBuf, FC_WS_DISABLED);
1470 /* lux scrollbar */
1471 pBuf = pBuf->prev;
1472 set_wstate(pBuf, FC_WS_DISABLED);
1474 /* sci lock */
1475 pBuf = pBuf->prev->prev;
1476 set_wstate(pBuf, FC_WS_DISABLED);
1478 /* sci scrollbar */
1479 pBuf = pBuf->prev;
1480 set_wstate(pBuf, FC_WS_DISABLED);
1482 /* update button */
1483 pBuf = pBuf->prev->prev;
1484 set_wstate(pBuf, FC_WS_DISABLED);
1486 /* cancel button */
1487 pBuf = pBuf->prev;
1488 set_wstate(pBuf, FC_WS_DISABLED);
1490 set_group_state(pEconomyDlg->pBeginActiveWidgetList,
1491 pEconomyDlg->pEndActiveWidgetList, FC_WS_DISABLED);
1492 if (pEconomyDlg->pScroll && pEconomyDlg->pActiveWidgetList) {
1493 set_wstate(pEconomyDlg->pScroll->pUp_Left_Button, FC_WS_DISABLED);
1494 set_wstate(pEconomyDlg->pScroll->pDown_Right_Button, FC_WS_DISABLED);
1495 set_wstate(pEconomyDlg->pScroll->pScrollBar, FC_WS_DISABLED);
1499 /* --------------------------------------------------------------- */
1501 /**************************************************************************
1502 User interacted with Yes button of the improvement selling dialog.
1503 **************************************************************************/
1504 static int ok_sell_impr_callback(struct widget *pWidget)
1506 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1507 int imp, total_count, count = 0;
1508 struct widget *pImpr = (struct widget *)pWidget->data.ptr;
1510 imp = pImpr->data.cont->id0;
1511 total_count = pImpr->data.cont->id1;
1513 /* popdown sell dlg */
1514 popdown_window_group_dialog(pEconomy_Sell_Dlg->pBeginWidgetList,
1515 pEconomy_Sell_Dlg->pEndWidgetList);
1516 FC_FREE(pEconomy_Sell_Dlg);
1517 enable_economy_dlg();
1519 /* send sell */
1520 city_list_iterate(client.conn.playing->cities, pCity) {
1521 if (!pCity->did_sell && city_has_building(pCity, improvement_by_number(imp))){
1522 count++;
1524 city_sell_improvement(pCity, imp);
1526 } city_list_iterate_end;
1528 if (count == total_count) {
1529 del_widget_from_vertical_scroll_widget_list(pEconomyDlg, pImpr);
1533 return -1;
1536 /**************************************************************************
1537 User interacted with the improvement selling window.
1538 **************************************************************************/
1539 static int sell_impr_window_callback(struct widget *pWindow)
1541 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1542 move_window_group(pEconomy_Sell_Dlg->pBeginWidgetList, pWindow);
1545 return -1;
1548 /**************************************************************************
1549 User interacted with Cancel button of the improvement selling dialog.
1550 **************************************************************************/
1551 static int cancel_sell_impr_callback(struct widget *pWidget)
1553 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1554 if (pEconomy_Sell_Dlg) {
1555 popdown_window_group_dialog(pEconomy_Sell_Dlg->pBeginWidgetList,
1556 pEconomy_Sell_Dlg->pEndWidgetList);
1557 FC_FREE(pEconomy_Sell_Dlg);
1558 enable_economy_dlg();
1559 flush_dirty();
1563 return -1;
1566 /**************************************************************************
1567 Open improvement selling dialog.
1568 **************************************************************************/
1569 static int popup_sell_impr_callback(struct widget *pWidget)
1571 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1572 int imp, total_count ,count = 0, gold = 0;
1573 int value;
1574 char cBuf[128];
1575 struct widget *pBuf = NULL, *pWindow;
1576 utf8_str *pstr;
1577 SDL_Surface *pText;
1578 SDL_Rect dst;
1579 SDL_Rect area;
1581 if (pEconomy_Sell_Dlg) {
1582 return 1;
1585 set_wstate(pWidget, FC_WS_NORMAL);
1586 selected_widget = NULL;
1587 widget_redraw(pWidget);
1588 widget_mark_dirty(pWidget);
1590 pEconomy_Sell_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1592 imp = pWidget->data.cont->id0;
1593 total_count = pWidget->data.cont->id1;
1594 value = impr_sell_gold(improvement_by_number(imp));
1596 city_list_iterate(client.conn.playing->cities, pCity) {
1597 if (!pCity->did_sell && city_has_building(pCity, improvement_by_number(imp))) {
1598 count++;
1599 gold += value;
1601 } city_list_iterate_end;
1603 if (count > 0) {
1604 fc_snprintf(cBuf, sizeof(cBuf),
1605 _("We have %d of %s\n(total value is : %d)\n"
1606 "We can sell %d of them for %d gold."),
1607 total_count,
1608 improvement_name_translation(improvement_by_number(imp)),
1609 total_count * value, count, gold);
1610 } else {
1611 fc_snprintf(cBuf, sizeof(cBuf),
1612 _("We can't sell any %s in this turn."),
1613 improvement_name_translation(improvement_by_number(imp)));
1616 pstr = create_utf8_from_char(_("Sell It?"), adj_font(12));
1617 pstr->style |= TTF_STYLE_BOLD;
1619 pWindow = create_window_skeleton(NULL, pstr, 0);
1621 pWindow->action = sell_impr_window_callback;
1622 set_wstate(pWindow, FC_WS_NORMAL);
1624 pEconomy_Sell_Dlg->pEndWidgetList = pWindow;
1626 add_to_gui_list(ID_WINDOW, pWindow);
1628 area = pWindow->area;
1630 /* ============================================================= */
1632 /* create text label */
1633 pstr = create_utf8_from_char(cBuf, adj_font(10));
1634 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1635 pstr->fgcol = *get_theme_color(COLOR_THEME_SELLIMPR_TEXT);
1637 pText = create_text_surf_from_utf8(pstr);
1638 FREEUTF8STR(pstr);
1640 area.w = MAX(area.w, pText->w + adj_size(20));
1641 area.h += (pText->h + adj_size(10));
1643 /* cancel button */
1644 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1645 pWindow->dst, _("No"),
1646 adj_font(12), 0);
1648 pBuf->action = cancel_sell_impr_callback;
1649 set_wstate(pBuf, FC_WS_NORMAL);
1651 area.h += (pBuf->size.h + adj_size(20));
1653 add_to_gui_list(ID_BUTTON, pBuf);
1655 if (count > 0) {
1656 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
1657 _("Sell"), adj_font(12), 0);
1659 pBuf->action = ok_sell_impr_callback;
1660 set_wstate(pBuf, FC_WS_NORMAL);
1661 pBuf->data.ptr = (void *)pWidget;
1663 add_to_gui_list(ID_BUTTON, pBuf);
1664 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
1665 pBuf->next->size.w = pBuf->size.w;
1666 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
1667 } else {
1668 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
1670 /* ============================================ */
1672 pEconomy_Sell_Dlg->pBeginWidgetList = pBuf;
1674 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1675 (pWindow->size.w - pWindow->area.w) + area.w,
1676 (pWindow->size.h - pWindow->area.h) + area.h);
1678 area = pWindow->area;
1680 widget_set_position(pWindow,
1681 pEconomyDlg->pEndWidgetList->size.x +
1682 (pEconomyDlg->pEndWidgetList->size.w - pWindow->size.w) / 2,
1683 pEconomyDlg->pEndWidgetList->size.y +
1684 (pEconomyDlg->pEndWidgetList->size.h - pWindow->size.h) / 2);
1686 /* setup rest of widgets */
1687 /* label */
1688 dst.x = area.x + (area.w - pText->w) / 2;
1689 dst.y = area.y + adj_size(10);
1690 alphablit(pText, NULL, pWindow->theme, &dst, 255);
1691 FREESURFACE(pText);
1693 /* cancel button */
1694 pBuf = pWindow->prev;
1695 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(10);
1697 if (count > 0) {
1698 /* sell button */
1699 pBuf = pBuf->prev;
1700 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
1701 pBuf->size.y = pBuf->next->size.y;
1703 /* cancel button */
1704 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
1705 } else {
1706 /* x position of cancel button */
1707 pBuf->size.x = area.x + area.w - adj_size(10) - pBuf->size.w;
1710 /* ================================================== */
1711 /* redraw */
1712 redraw_group(pEconomy_Sell_Dlg->pBeginWidgetList, pWindow, 0);
1713 disable_economy_dlg();
1715 widget_mark_dirty(pWindow);
1716 flush_dirty();
1719 return -1;
1722 /**************************************************************************
1723 Update the economy report.
1724 **************************************************************************/
1725 void real_economy_report_dialog_update(void)
1727 if (pEconomyDlg) {
1728 struct widget *pbuf = pEconomyDlg->pEndWidgetList;
1729 int tax, total, entries_used = 0;
1730 char cbuf[128];
1731 struct improvement_entry entries[B_LAST];
1733 get_economy_report_data(entries, &entries_used, &total, &tax);
1735 /* tresure */
1736 pbuf = pbuf->prev;
1737 fc_snprintf(cbuf, sizeof(cbuf), "%d", client.conn.playing->economic.gold);
1738 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1739 remake_label_size(pbuf);
1741 /* Icome */
1742 pbuf = pbuf->prev->prev;
1743 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax);
1744 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1745 remake_label_size(pbuf);
1747 /* Cost */
1748 pbuf = pbuf->prev;
1749 fc_snprintf(cbuf, sizeof(cbuf), "%d", total);
1750 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1751 remake_label_size(pbuf);
1753 /* Netto */
1754 pbuf = pbuf->prev;
1755 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax - total);
1756 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1757 remake_label_size(pbuf);
1758 if (tax - total < 0) {
1759 pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_ECONOMYDLG_NEG_TEXT);
1760 } else {
1761 pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_ECONOMYDLG_TEXT);
1764 /* ---------------- */
1765 redraw_group(pEconomyDlg->pBeginWidgetList, pEconomyDlg->pEndWidgetList, 0);
1766 widget_flush(pEconomyDlg->pEndWidgetList);
1770 /**************************************************************************
1771 Popdown the economy report.
1772 **************************************************************************/
1773 void economy_report_dialog_popdown(void)
1775 if (pEconomyDlg) {
1776 if (pEconomy_Sell_Dlg) {
1777 del_group_of_widgets_from_gui_list(pEconomy_Sell_Dlg->pBeginWidgetList,
1778 pEconomy_Sell_Dlg->pEndWidgetList);
1779 FC_FREE(pEconomy_Sell_Dlg);
1781 popdown_window_group_dialog(pEconomyDlg->pBeginWidgetList,
1782 pEconomyDlg->pEndWidgetList);
1783 FC_FREE(pEconomyDlg->pScroll);
1784 FC_FREE(pEconomyDlg);
1785 set_wstate(get_tax_rates_widget(), FC_WS_NORMAL);
1786 widget_redraw(get_tax_rates_widget());
1787 widget_mark_dirty(get_tax_rates_widget());
1791 #define TARGETS_ROW 2
1792 #define TARGETS_COL 4
1794 /**************************************************************************
1795 Popup (or raise) the economy report (F5). It may or may not be modal.
1796 **************************************************************************/
1797 void economy_report_dialog_popup(bool make_modal)
1799 SDL_Color bg_color = {255,255,255,128};
1800 SDL_Color bg_color2 = {255,255,255,136};
1801 SDL_Color bg_color3 = {255,255,255,64};
1802 struct widget *pBuf;
1803 struct widget *pWindow , *pLast;
1804 utf8_str *pstr, *pstr2;
1805 SDL_Surface *pSurf, *pText_Name, *pText, *pZoom;
1806 SDL_Surface *pBackground;
1807 int i, count , h = 0;
1808 int w = 0; /* left column values */
1809 int w2 = 0; /* right column: lock + scrollbar + ... */
1810 int w3 = 0; /* left column text without values */
1811 int tax, total, entries_used = 0;
1812 char cbuf[128];
1813 struct improvement_entry entries[B_LAST];
1814 SDL_Rect dst;
1815 SDL_Rect area;
1816 struct government *pGov = government_of_player(client.conn.playing);
1817 SDL_Surface *pTreasuryText;
1818 SDL_Surface *pTaxRateText;
1819 SDL_Surface *pTotalIncomeText;
1820 SDL_Surface *pTotalCostText;
1821 SDL_Surface *pNetIncomeText;
1822 SDL_Surface *pMaxRateText;
1824 if (pEconomyDlg) {
1825 return;
1828 /* disable "Economy" button */
1829 pBuf = get_tax_rates_widget();
1830 set_wstate(pBuf, FC_WS_DISABLED);
1831 widget_redraw(pBuf);
1832 widget_mark_dirty(pBuf);
1834 pEconomyDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1836 get_economy_report_data(entries, &entries_used, &total, &tax);
1838 /* --------------- */
1839 pstr = create_utf8_from_char(_("Economy Report"), adj_font(12));
1840 pstr->style |= TTF_STYLE_BOLD;
1842 pWindow = create_window_skeleton(NULL, pstr, 0);
1843 pEconomyDlg->pEndWidgetList = pWindow;
1844 set_wstate(pWindow, FC_WS_NORMAL);
1845 pWindow->action = economy_dialog_callback;
1847 add_to_gui_list(ID_ECONOMY_DIALOG_WINDOW, pWindow);
1849 area = pWindow->area;
1851 /* ------------------------- */
1853 /* "Treasury" text surface */
1854 fc_snprintf(cbuf, sizeof(cbuf), _("Treasury: "));
1855 pstr2 = create_utf8_from_char(cbuf, adj_font(12));
1856 pstr2->style |= TTF_STYLE_BOLD;
1857 pTreasuryText = create_text_surf_from_utf8(pstr2);
1858 w3 = MAX(w3, pTreasuryText->w);
1860 /* "Treasury" value label*/
1861 fc_snprintf(cbuf, sizeof(cbuf), "%d", client.conn.playing->economic.gold);
1862 pstr = create_utf8_from_char(cbuf, adj_font(12));
1863 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1865 pBuf = create_iconlabel(pIcons->pBIG_Coin, pWindow->dst, pstr,
1866 (WF_RESTORE_BACKGROUND|WF_ICON_CENTER_RIGHT));
1868 add_to_gui_list(ID_LABEL, pBuf);
1870 w = MAX(w, pBuf->size.w);
1871 h += pBuf->size.h;
1873 /* "Tax Rate" text surface */
1874 fc_snprintf(cbuf, sizeof(cbuf), _("Tax Rate: "));
1875 copy_chars_to_utf8_str(pstr2, cbuf);
1876 pTaxRateText = create_text_surf_from_utf8(pstr2);
1877 w3 = MAX(w3, pTaxRateText->w);
1879 /* "Tax Rate" value label */
1880 /* it is important to leave 1 space at ending of this string */
1881 fc_snprintf(cbuf, sizeof(cbuf), "%d%% ", client.conn.playing->economic.tax);
1882 pstr = create_utf8_from_char(cbuf, adj_font(12));
1883 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1885 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1887 add_to_gui_list(ID_LABEL, pBuf);
1889 w = MAX(w, pBuf->size.w + pBuf->next->size.w);
1890 h += pBuf->size.h;
1892 /* "Total Income" text surface */
1893 fc_snprintf(cbuf, sizeof(cbuf), _("Total Income: "));
1894 copy_chars_to_utf8_str(pstr2, cbuf);
1895 pTotalIncomeText = create_text_surf_from_utf8(pstr2);
1896 w3 = MAX(w3, pTotalIncomeText->w);
1898 /* "Total Icome" value label */
1899 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax);
1900 pstr = create_utf8_from_char(cbuf, adj_font(12));
1901 pstr->style |= TTF_STYLE_BOLD;
1903 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1905 add_to_gui_list(ID_LABEL, pBuf);
1907 w = MAX(w, pBuf->size.w);
1908 h += pBuf->size.h;
1910 /* "Total Cost" text surface */
1911 fc_snprintf(cbuf, sizeof(cbuf), _("Total Cost: "));
1912 copy_chars_to_utf8_str(pstr2, cbuf);
1913 pTotalCostText = create_text_surf_from_utf8(pstr2);
1915 /* "Total Cost" value label */
1916 fc_snprintf(cbuf, sizeof(cbuf), "%d", total);
1917 pstr = create_utf8_from_char(cbuf, adj_font(12));
1918 pstr->style |= TTF_STYLE_BOLD;
1920 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1922 add_to_gui_list(ID_LABEL, pBuf);
1924 w = MAX(w, pBuf->size.w);
1925 h += pBuf->size.h;
1927 /* "Net Income" text surface */
1928 fc_snprintf(cbuf, sizeof(cbuf), _("Net Income: "));
1929 copy_chars_to_utf8_str(pstr2, cbuf);
1930 pNetIncomeText = create_text_surf_from_utf8(pstr2);
1931 w3 = MAX(w3, pNetIncomeText->w);
1933 /* "Net Icome" value label */
1934 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax - total);
1935 pstr = create_utf8_from_char(cbuf, adj_font(12));
1936 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1938 if (tax - total < 0) {
1939 pstr->fgcol = *get_theme_color(COLOR_THEME_ECONOMYDLG_NEG_TEXT);
1942 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1944 add_to_gui_list(ID_LABEL, pBuf);
1946 w = MAX(w, pBuf->size.w);
1947 h += pBuf->size.h;
1949 /* gov and taxrate */
1950 fc_snprintf(cbuf, sizeof(cbuf), _("%s max rate : %d%%"),
1951 government_name_translation(pGov),
1952 get_player_bonus(client.conn.playing, EFT_MAX_RATES));
1953 copy_chars_to_utf8_str(pstr2, cbuf);
1954 pMaxRateText = create_text_surf_from_utf8(pstr2);
1956 FREEUTF8STR(pstr2);
1958 /* ------------------------- */
1959 /* lux rate */
1961 /* lux rate lock */
1962 fc_snprintf(cbuf, sizeof(cbuf), _("Lock"));
1963 pstr = create_utf8_from_char(cbuf, adj_font(10));
1964 pstr->style |= TTF_STYLE_BOLD;
1966 pBuf = create_checkbox(pWindow->dst,
1967 SDL_Client_Flags & CF_CHANGE_TAXRATE_LUX_BLOCK,
1968 WF_RESTORE_BACKGROUND | WF_WIDGET_HAS_INFO_LABEL);
1969 set_new_checkbox_theme(pBuf, current_theme->LOCK_Icon, current_theme->UNLOCK_Icon);
1970 pBuf->info_label = pstr;
1971 pBuf->action = toggle_block_callback;
1972 set_wstate(pBuf, FC_WS_NORMAL);
1974 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_LUX_BLOCK_CHECKBOX, pBuf);
1976 w2 = adj_size(10) + pBuf->size.w;
1978 /* lux rate slider */
1979 pBuf = create_horizontal(current_theme->Horiz, pWindow->dst, adj_size(30),
1980 (WF_FREE_DATA | WF_RESTORE_BACKGROUND));
1982 pBuf->action = horiz_taxrate_callback;
1983 pBuf->data.ptr = fc_calloc(1, sizeof(int));
1984 *(int *)pBuf->data.ptr = client.conn.playing->economic.luxury;
1985 set_wstate(pBuf, FC_WS_NORMAL);
1987 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_LUX_SCROLLBAR, pBuf);
1989 w2 += adj_size(184);
1991 /* lux rate iconlabel */
1993 /* it is important to leave 1 space at ending of this string */
1994 fc_snprintf(cbuf, sizeof(cbuf), "%d%% ", client.conn.playing->economic.luxury);
1995 pstr = create_utf8_from_char(cbuf, adj_font(11));
1996 pstr->style |= TTF_STYLE_BOLD;
1998 pBuf = create_iconlabel(pIcons->pBIG_Luxury, pWindow->dst, pstr,
1999 WF_RESTORE_BACKGROUND);
2000 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_LUX_LABEL, pBuf);
2002 w2 += (adj_size(5) + pBuf->size.w + adj_size(10));
2004 /* ------------------------- */
2005 /* science rate */
2007 /* science rate lock */
2008 fc_snprintf(cbuf, sizeof(cbuf), _("Lock"));
2009 pstr = create_utf8_from_char(cbuf, adj_font(10));
2010 pstr->style |= TTF_STYLE_BOLD;
2012 pBuf = create_checkbox(pWindow->dst,
2013 SDL_Client_Flags & CF_CHANGE_TAXRATE_SCI_BLOCK,
2014 WF_RESTORE_BACKGROUND | WF_WIDGET_HAS_INFO_LABEL);
2016 set_new_checkbox_theme(pBuf, current_theme->LOCK_Icon, current_theme->UNLOCK_Icon);
2018 pBuf->info_label = pstr;
2019 pBuf->action = toggle_block_callback;
2020 set_wstate(pBuf, FC_WS_NORMAL);
2022 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_SCI_BLOCK_CHECKBOX, pBuf);
2024 /* science rate slider */
2025 pBuf = create_horizontal(current_theme->Horiz, pWindow->dst, adj_size(30),
2026 (WF_FREE_DATA | WF_RESTORE_BACKGROUND));
2028 pBuf->action = horiz_taxrate_callback;
2029 pBuf->data.ptr = fc_calloc(1, sizeof(int));
2030 *(int *)pBuf->data.ptr = client.conn.playing->economic.science;
2032 set_wstate(pBuf, FC_WS_NORMAL);
2034 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_SCI_SCROLLBAR, pBuf);
2036 /* science rate iconlabel */
2037 /* it is important to leave 1 space at ending of this string */
2038 fc_snprintf(cbuf, sizeof(cbuf), "%d%% ", client.conn.playing->economic.science);
2039 pstr = create_utf8_from_char(cbuf, adj_font(11));
2040 pstr->style |= TTF_STYLE_BOLD;
2042 pBuf = create_iconlabel(pIcons->pBIG_Colb, pWindow->dst, pstr,
2043 WF_RESTORE_BACKGROUND);
2045 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_SCI_LABEL, pBuf);
2047 /* ---- */
2049 fc_snprintf(cbuf, sizeof(cbuf), _("Update"));
2050 pstr = create_utf8_from_char(cbuf, adj_font(12));
2051 pBuf = create_themeicon_button(current_theme->Small_OK_Icon, pWindow->dst, pstr, 0);
2052 pBuf->action = apply_taxrates_callback;
2053 set_wstate(pBuf, FC_WS_NORMAL);
2055 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_OK_BUTTON, pBuf);
2057 /* ---- */
2059 fc_snprintf(cbuf, sizeof(cbuf), _("Close Dialog (Esc)"));
2060 pstr = create_utf8_from_char(cbuf, adj_font(12));
2061 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2062 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
2063 pBuf->info_label = pstr;
2064 pBuf->action = exit_economy_dialog_callback;
2065 set_wstate(pBuf, FC_WS_NORMAL);
2066 pBuf->key = SDLK_ESCAPE;
2068 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_CANCEL_BUTTON, pBuf);
2070 h += adj_size(5);
2072 /* ------------------------- */
2073 pLast = pBuf;
2074 if (entries_used > 0) {
2076 /* Create Imprv Background Icon */
2077 pBackground = create_surf(adj_size(116), adj_size(116), SDL_SWSURFACE);
2079 SDL_FillRect(pBackground, NULL, map_rgba(pBackground->format, bg_color));
2081 create_frame(pBackground,
2082 0, 0, pBackground->w - 1, pBackground->h - 1,
2083 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2085 pstr = create_utf8_str(NULL, 0, adj_font(10));
2086 pstr->style |= (SF_CENTER|TTF_STYLE_BOLD);
2087 pstr->bgcol = (SDL_Color) {0, 0, 0, 0};
2089 for (i = 0; i < entries_used; i++) {
2090 struct improvement_entry *p = &entries[i];
2091 struct impr_type *pImprove = p->type;
2093 pSurf = crop_rect_from_surface(pBackground, NULL);
2095 fc_snprintf(cbuf, sizeof(cbuf), "%s", improvement_name_translation(pImprove));
2097 copy_chars_to_utf8_str(pstr, cbuf);
2098 pstr->style |= TTF_STYLE_BOLD;
2099 pText_Name = create_text_surf_smaller_than_w(pstr, pSurf->w - adj_size(4));
2101 fc_snprintf(cbuf, sizeof(cbuf), "%s %d\n%s %d",
2102 _("Built"), p->count, _("U Total"),p->total_cost);
2103 copy_chars_to_utf8_str(pstr, cbuf);
2104 pstr->style &= ~TTF_STYLE_BOLD;
2106 pText = create_text_surf_from_utf8(pstr);
2108 /*-----------------*/
2110 pZoom = get_building_surface(pImprove);
2111 pZoom = zoomSurface(pZoom, DEFAULT_ZOOM * ((float)54 / pZoom->w), DEFAULT_ZOOM * ((float)54 / pZoom->w), 1);
2113 dst.x = (pSurf->w - pZoom->w) / 2;
2114 dst.y = (pSurf->h / 2 - pZoom->h) / 2;
2115 alphablit(pZoom, NULL, pSurf, &dst, 255);
2116 dst.y += pZoom->h;
2117 FREESURFACE(pZoom);
2119 dst.x = (pSurf->w - pText_Name->w)/2;
2120 dst.y += ((pSurf->h - dst.y) -
2121 (pText_Name->h + (pIcons->pBIG_Coin->h + 2) + pText->h)) / 2;
2122 alphablit(pText_Name, NULL, pSurf, &dst, 255);
2124 dst.y += pText_Name->h;
2125 if (p->cost) {
2126 dst.x = (pSurf->w - p->cost * (pIcons->pBIG_Coin->w + 1))/2;
2127 for (count = 0; count < p->cost; count++) {
2128 alphablit(pIcons->pBIG_Coin, NULL, pSurf, &dst, 255);
2129 dst.x += pIcons->pBIG_Coin->w + 1;
2131 } else {
2133 if (!is_wonder(pImprove)) {
2134 copy_chars_to_utf8_str(pstr, _("Nation"));
2135 } else {
2136 copy_chars_to_utf8_str(pstr, _("Wonder"));
2138 /*pstr->style &= ~TTF_STYLE_BOLD;*/
2140 pZoom = create_text_surf_from_utf8(pstr);
2142 dst.x = (pSurf->w - pZoom->w) / 2;
2143 alphablit(pZoom, NULL, pSurf, &dst, 255);
2144 FREESURFACE(pZoom);
2147 dst.y += (pIcons->pBIG_Coin->h + adj_size(2));
2148 dst.x = (pSurf->w - pText->w) / 2;
2149 alphablit(pText, NULL, pSurf, &dst, 255);
2151 FREESURFACE(pText);
2152 FREESURFACE(pText_Name);
2154 pBuf = create_icon2(pSurf, pWindow->dst,
2155 (WF_RESTORE_BACKGROUND|WF_FREE_THEME|WF_FREE_DATA));
2157 set_wstate(pBuf, FC_WS_NORMAL);
2159 pBuf->data.cont = fc_calloc(1, sizeof(struct CONTAINER));
2160 pBuf->data.cont->id0 = improvement_number(p->type);
2161 pBuf->data.cont->id1 = p->count;
2162 pBuf->action = popup_sell_impr_callback;
2164 add_to_gui_list(MAX_ID - i, pBuf);
2166 if (i > (TARGETS_ROW * TARGETS_COL - 1)) {
2167 set_wflag(pBuf, WF_HIDDEN);
2171 FREEUTF8STR(pstr);
2172 FREESURFACE(pBackground);
2174 pEconomyDlg->pEndActiveWidgetList = pLast->prev;
2175 pEconomyDlg->pBeginWidgetList = pBuf;
2176 pEconomyDlg->pBeginActiveWidgetList = pEconomyDlg->pBeginWidgetList;
2178 if (entries_used > (TARGETS_ROW * TARGETS_COL)) {
2179 pEconomyDlg->pActiveWidgetList = pEconomyDlg->pEndActiveWidgetList;
2180 count = create_vertical_scrollbar(pEconomyDlg,
2181 TARGETS_COL, TARGETS_ROW, TRUE, TRUE);
2182 h += (TARGETS_ROW * pBuf->size.h + adj_size(10));
2183 } else {
2184 count = 0;
2185 if (entries_used > TARGETS_COL) {
2186 h += pBuf->size.h;
2188 h += (adj_size(10) + pBuf->size.h);
2190 count = TARGETS_COL * pBuf->size.w + count;
2191 } else {
2192 pEconomyDlg->pBeginWidgetList = pBuf;
2193 h += adj_size(10);
2194 count = 0;
2197 area.w = MAX(area.w, MAX(adj_size(10) + w3 + w + w2, count));
2198 area.h = h;
2200 pBackground = theme_get_background(theme, BACKGROUND_ECONOMYDLG);
2201 if (resize_window(pWindow, pBackground, NULL,
2202 (pWindow->size.w - pWindow->area.w) + area.w,
2203 (pWindow->size.h - pWindow->area.h) + area.h)) {
2204 FREESURFACE(pBackground);
2207 area = pWindow->area;
2209 widget_set_position(pWindow,
2210 (main_window_width() - pWindow->size.w) / 2,
2211 (main_window_height() - pWindow->size.h) / 2);
2213 /* "Treasury" value label */
2214 pBuf = pWindow->prev;
2215 pBuf->size.x = area.x + adj_size(10) + pTreasuryText->w;
2216 pBuf->size.y = area.y + adj_size(5);
2218 w = pTreasuryText->w + pBuf->size.w;
2219 h = pBuf->size.h;
2221 /* "Tax Rate" value label */
2222 pBuf = pBuf->prev;
2223 pBuf->size.x = area.x + adj_size(10) + pTaxRateText->w;
2224 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2226 w = MAX(w, pTaxRateText->w + pBuf->size.w);
2227 h += pBuf->size.h;
2229 /* "Total Income" value label */
2230 pBuf = pBuf->prev;
2231 pBuf->size.x = area.x + adj_size(10) + pTotalIncomeText->w;
2232 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2234 w = MAX(w, pTotalIncomeText->w + pBuf->size.w);
2235 h += pBuf->size.h;
2237 /* "Total Cost" value label */
2238 pBuf = pBuf->prev;
2239 pBuf->size.x = area.x + adj_size(10) + pTotalCostText->w;
2240 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2242 w = MAX(w, pTotalCostText->w + pBuf->size.w);
2243 h += pBuf->size.h;
2245 /* "Net Income" value label */
2246 pBuf = pBuf->prev;
2247 pBuf->size.x = area.x + adj_size(10) + pNetIncomeText->w;
2248 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2250 w = MAX(w, pNetIncomeText->w + pBuf->size.w);
2251 h += pBuf->size.h;
2253 /* Backgrounds */
2254 dst.x = area.x;
2255 dst.y = area.y;
2256 dst.w = area.w;
2257 dst.h = h + adj_size(15);
2258 h = dst.h;
2260 fill_rect_alpha(pWindow->theme, &dst, &bg_color2);
2262 create_frame(pWindow->theme,
2263 dst.x, dst.y, dst.w - 1, dst.h - 1,
2264 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2266 /* draw statical strings */
2267 dst.x = area.x + adj_size(10);
2268 dst.y = area.y + adj_size(5);
2270 /* "Treasury */
2271 alphablit(pTreasuryText, NULL, pWindow->theme, &dst, 255);
2272 dst.y += pTreasuryText->h;
2273 FREESURFACE(pTreasuryText);
2275 /* Tax Rate */
2276 alphablit(pTaxRateText, NULL, pWindow->theme, &dst, 255);
2277 dst.y += pTaxRateText->h;
2278 FREESURFACE(pTaxRateText);
2280 /* Total Income */
2281 alphablit(pTotalIncomeText, NULL, pWindow->theme, &dst, 255);
2282 dst.y += pTotalIncomeText->h;
2283 FREESURFACE(pTotalIncomeText);
2285 /* Total Cost */
2286 alphablit(pTotalCostText, NULL, pWindow->theme, &dst, 255);
2287 dst.y += pTotalCostText->h;
2288 FREESURFACE(pTotalCostText);
2290 /* Net Income */
2291 alphablit(pNetIncomeText, NULL, pWindow->theme, &dst, 255);
2292 dst.y += pNetIncomeText->h;
2293 FREESURFACE(pNetIncomeText);
2295 /* gov and taxrate */
2296 dst.x = area.x + adj_size(10) + w + ((area.w - (w + adj_size(10)) - pMaxRateText->w) / 2);
2297 dst.y = area.y + adj_size(5);
2299 alphablit(pMaxRateText, NULL, pWindow->theme, &dst, 255);
2300 dst.y += (pMaxRateText->h + 1);
2301 FREESURFACE(pMaxRateText);
2303 /* Luxuries Horizontal Scrollbar Background */
2304 dst.x = area.x + adj_size(10) + w + (area.w - (w + adj_size(10)) - adj_size(184)) / 2;
2305 dst.w = adj_size(184);
2306 dst.h = current_theme->Horiz->h - adj_size(2);
2308 fill_rect_alpha(pWindow->theme, &dst, &bg_color3);
2310 create_frame(pWindow->theme,
2311 dst.x, dst.y, dst.w - 1, dst.h - 1,
2312 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2314 /* lock icon */
2315 pBuf = pBuf->prev;
2316 pBuf->size.x = dst.x - pBuf->size.w;
2317 pBuf->size.y = dst.y - adj_size(2);
2319 /* lux scrollbar */
2320 pBuf = pBuf->prev;
2321 pBuf->size.x = dst.x + adj_size(2) + (client.conn.playing->economic.luxury * 3) / 2;
2322 pBuf->size.y = dst.y -1;
2324 /* lux rate */
2325 pBuf = pBuf->prev;
2326 pBuf->size.x = dst.x + dst.w + adj_size(5);
2327 pBuf->size.y = dst.y + 1;
2329 /* Science Horizontal Scrollbar Background */
2330 dst.y += current_theme->Horiz->h + 1;
2331 fill_rect_alpha(pWindow->theme, &dst, &bg_color3);
2333 create_frame(pWindow->theme,
2334 dst.x, dst.y, dst.w - 1, dst.h - 1,
2335 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2337 /* science lock icon */
2338 pBuf = pBuf->prev;
2339 pBuf->size.x = dst.x - pBuf->size.w;
2340 pBuf->size.y = dst.y - adj_size(2);
2342 /* science scrollbar */
2343 pBuf = pBuf->prev;
2344 pBuf->size.x = dst.x + adj_size(2) + (client.conn.playing->economic.science * 3) / 2;
2345 pBuf->size.y = dst.y -1;
2347 /* science rate */
2348 pBuf = pBuf->prev;
2349 pBuf->size.x = dst.x + dst.w + adj_size(5);
2350 pBuf->size.y = dst.y + 1;
2352 /* update */
2353 pBuf = pBuf->prev;
2354 pBuf->size.x = dst.x + (dst.w - pBuf->size.w) / 2;
2355 pBuf->size.y = dst.y + dst.h + adj_size(3);
2357 /* cancel */
2358 pBuf = pBuf->prev;
2359 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2360 pBuf->size.y = pWindow->size.y + adj_size(2);
2361 /* ------------------------------- */
2363 if (entries_used > 0) {
2364 setup_vertical_widgets_position(TARGETS_COL,
2365 area.x,
2366 area.y + h,
2367 0, 0, pEconomyDlg->pBeginActiveWidgetList,
2368 pEconomyDlg->pEndActiveWidgetList);
2369 if (pEconomyDlg->pScroll) {
2370 setup_vertical_scrollbar_area(pEconomyDlg->pScroll,
2371 area.x + area.w - 1,
2372 area.y + h,
2373 area.h - h - 1, TRUE);
2377 /* ------------------------ */
2378 redraw_group(pEconomyDlg->pBeginWidgetList, pWindow, 0);
2379 widget_mark_dirty(pWindow);
2380 flush_dirty();
2383 /* ===================================================================== */
2384 /* ======================== Science Report ============================= */
2385 /* ===================================================================== */
2386 static struct SMALL_DLG *pScienceDlg = NULL;
2388 static struct ADVANCED_DLG *pChangeTechDlg = NULL;
2390 /**************************************************************************
2391 Create icon surface for a tech.
2392 **************************************************************************/
2393 SDL_Surface *create_select_tech_icon(utf8_str *pstr, Tech_type_id tech_id,
2394 enum tech_info_mode mode)
2396 struct unit_type *pUnit = NULL;
2397 SDL_Surface *pSurf, *pText, *pTmp, *pTmp2;
2398 SDL_Surface *Surf_Array[10], **pBuf_Array;
2399 SDL_Rect dst;
2400 SDL_Color color;
2401 int w, h;
2403 color = *get_tech_color(tech_id);
2404 switch (mode)
2406 case SMALL_MODE:
2407 h = adj_size(40);
2408 w = adj_size(135);
2409 break;
2410 case MED_MODE:
2411 color = *get_theme_color(COLOR_THEME_SCIENCEDLG_MED_TECHICON_BG);
2412 default:
2413 h = adj_size(200);
2414 w = adj_size(100);
2415 break;
2418 pText = create_text_surf_smaller_than_w(pstr, adj_size(100 - 4));
2420 /* create label surface */
2421 pSurf = create_surf(w, h, SDL_SWSURFACE);
2423 if (tech_id == research_get(client_player())->researching) {
2424 color.a = 180;
2425 } else {
2426 color.a = 128;
2429 SDL_FillRect(pSurf, NULL, map_rgba(pSurf->format, color));
2431 create_frame(pSurf,
2432 0,0, pSurf->w - 1, pSurf->h - 1,
2433 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2435 pTmp = get_tech_icon(tech_id);
2437 if (mode == SMALL_MODE) {
2438 /* draw name tech text */
2439 dst.x = adj_size(35) + (pSurf->w - pText->w - adj_size(35)) / 2;
2440 dst.y = (pSurf->h - pText->h) / 2;
2441 alphablit(pText, NULL, pSurf, &dst, 255);
2442 FREESURFACE(pText);
2444 /* draw tech icon */
2445 pText = ResizeSurface(pTmp, adj_size(25), adj_size(25), 1);
2446 dst.x = (adj_size(35) - pText->w) / 2;
2447 dst.y = (pSurf->h - pText->h) / 2;
2448 alphablit(pText, NULL, pSurf, &dst, 255);
2449 FREESURFACE(pText);
2451 } else {
2453 /* draw name tech text */
2454 dst.x = (pSurf->w - pText->w) / 2;
2455 dst.y = adj_size(20);
2456 alphablit(pText, NULL, pSurf, &dst, 255);
2457 dst.y += pText->h + adj_size(10);
2458 FREESURFACE(pText);
2460 /* draw tech icon */
2461 dst.x = (pSurf->w - pTmp->w) / 2;
2462 alphablit(pTmp, NULL, pSurf, &dst, 255);
2463 dst.y += pTmp->w + adj_size(10);
2465 /* fill array with iprvm. icons */
2466 w = 0;
2467 improvement_iterate(pImprove) {
2468 requirement_vector_iterate(&pImprove->reqs, preq) {
2469 if (VUT_ADVANCE == preq->source.kind
2470 && advance_number(preq->source.value.advance) == tech_id) {
2471 pTmp2 = get_building_surface(pImprove);
2472 Surf_Array[w++] = zoomSurface(pTmp2, DEFAULT_ZOOM * ((float)36 / pTmp2->w), DEFAULT_ZOOM * ((float)36 / pTmp2->w), 1);
2474 } requirement_vector_iterate_end;
2475 } improvement_iterate_end;
2477 if (w) {
2478 if (w >= 2) {
2479 dst.x = (pSurf->w - 2 * Surf_Array[0]->w) / 2;
2480 } else {
2481 dst.x = (pSurf->w - Surf_Array[0]->w) / 2;
2484 /* draw iprvm. icons */
2485 pBuf_Array = Surf_Array;
2486 h = 0;
2487 while (w) {
2488 alphablit(*pBuf_Array, NULL, pSurf, &dst, 255);
2489 dst.x += (*pBuf_Array)->w;
2490 w--;
2491 h++;
2492 if (!(h % 2)) {
2493 if (w >= 2) {
2494 dst.x = (pSurf->w - 2 * (*pBuf_Array)->w) / 2;
2495 } else {
2496 dst.x = (pSurf->w - (*pBuf_Array)->w) / 2;
2498 dst.y += (*pBuf_Array)->h;
2499 h = 0;
2500 } /* h == 2 */
2501 pBuf_Array++;
2502 } /* while */
2503 dst.y += Surf_Array[0]->h + adj_size(5);
2504 } /* if (w) */
2505 /* -------------------------------------------------------- */
2506 w = 0;
2507 unit_type_iterate(un) {
2508 pUnit = un;
2509 if (advance_number(pUnit->require_advance) == tech_id) {
2510 Surf_Array[w++] = adj_surf(get_unittype_surface(un, direction8_invalid()));
2512 } unit_type_iterate_end;
2514 if (w) {
2515 if (w < 2) {
2516 /* w == 1 */
2517 if (Surf_Array[0]->w > 64) {
2518 float zoom = DEFAULT_ZOOM * (64.0 / Surf_Array[0]->w);
2519 SDL_Surface *zoomed = zoomSurface(Surf_Array[0], zoom, zoom, 1);
2521 dst.x = (pSurf->w - zoomed->w) / 2;
2522 alphablit(zoomed, NULL, pSurf, &dst, 255);
2523 FREESURFACE(zoomed);
2524 } else {
2525 dst.x = (pSurf->w - Surf_Array[0]->w) / 2;
2526 alphablit(Surf_Array[0], NULL, pSurf, &dst, 255);
2528 } else {
2529 float zoom;
2531 if (w > 2) {
2532 zoom = DEFAULT_ZOOM * (38.0 / Surf_Array[0]->w);
2533 } else {
2534 zoom = DEFAULT_ZOOM * (45.0 / Surf_Array[0]->w);
2536 dst.x = (pSurf->w - (Surf_Array[0]->w * 2) * zoom - 2) / 2;
2537 pBuf_Array = Surf_Array;
2538 h = 0;
2539 while (w) {
2540 SDL_Surface *zoomed = zoomSurface((*pBuf_Array), zoom, zoom, 1);
2542 alphablit(zoomed, NULL, pSurf, &dst, 255);
2543 dst.x += zoomed->w + 2;
2544 w--;
2545 h++;
2546 if (!(h % 2)) {
2547 if (w >= 2) {
2548 dst.x = (pSurf->w - 2 * zoomed->w - 2 ) / 2;
2549 } else {
2550 dst.x = (pSurf->w - zoomed->w) / 2;
2552 dst.y += zoomed->h + 2;
2553 h = 0;
2554 } /* h == 2 */
2555 pBuf_Array++;
2556 FREESURFACE(zoomed);
2557 } /* while */
2558 } /* w > 1 */
2559 } /* if (w) */
2562 FREESURFACE(pTmp);
2564 return pSurf;
2567 /**************************************************************************
2568 enable science dialog group ( without window )
2569 **************************************************************************/
2570 static void enable_science_dialog(void)
2572 set_group_state(pScienceDlg->pBeginWidgetList,
2573 pScienceDlg->pEndWidgetList->prev, FC_WS_NORMAL);
2576 /**************************************************************************
2577 disable science dialog group ( without window )
2578 **************************************************************************/
2579 static void disable_science_dialog(void)
2581 set_group_state(pScienceDlg->pBeginWidgetList,
2582 pScienceDlg->pEndWidgetList->prev, FC_WS_DISABLED);
2585 /**************************************************************************
2586 Update the science report.
2587 **************************************************************************/
2588 void real_science_report_dialog_update(void)
2590 SDL_Color bg_color = {255, 255, 255, 136};
2592 if (pScienceDlg) {
2593 const struct research *presearch = research_get(client_player());
2594 char cBuf[128];
2595 utf8_str *pStr;
2596 SDL_Surface *pSurf;
2597 SDL_Surface *pColb_Surface = pIcons->pBIG_Colb;
2598 int step, i, cost;
2599 SDL_Rect dest;
2600 struct unit_type *pUnit;
2601 struct widget *pChangeResearchButton;
2602 struct widget *pChangeResearchGoalButton;
2603 SDL_Rect area;
2604 struct widget *pWindow = pScienceDlg->pEndWidgetList;
2606 area = pWindow->area;
2607 pChangeResearchButton = pWindow->prev;
2608 pChangeResearchGoalButton = pWindow->prev->prev;
2610 if (A_UNSET != presearch->researching) {
2611 cost = presearch->client.researching_cost;
2612 } else {
2613 cost = 0;
2616 /* update current research icons */
2617 FREESURFACE(pChangeResearchButton->theme);
2618 pChangeResearchButton->theme = get_tech_icon(presearch->researching);
2619 FREESURFACE(pChangeResearchGoalButton->theme);
2620 pChangeResearchGoalButton->theme = get_tech_icon(presearch->tech_goal);
2622 /* redraw Window */
2623 widget_redraw(pWindow);
2625 /* ------------------------------------- */
2627 /* research progress text */
2628 pStr = create_utf8_from_char(science_dialog_text(), adj_font(12));
2629 pStr->style |= SF_CENTER;
2630 pStr->fgcol = *get_theme_color(COLOR_THEME_SCIENCEDLG_TEXT);
2632 pSurf = create_text_surf_from_utf8(pStr);
2634 dest.x = area.x + (area.w - pSurf->w) / 2;
2635 dest.y = area.y + adj_size(2);
2636 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2638 dest.y += pSurf->h + adj_size(4);
2640 FREESURFACE(pSurf);
2642 dest.x = area.x + adj_size(16);
2644 /* separator */
2645 create_line(pWindow->dst->surface,
2646 dest.x, dest.y, (area.x + area.w - adj_size(16)), dest.y,
2647 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2649 dest.y += adj_size(6);
2651 widget_set_position(pChangeResearchButton, dest.x, dest.y + adj_size(18));
2653 /* current research text */
2654 fc_snprintf(cBuf, sizeof(cBuf), "%s: %s",
2655 research_advance_name_translation(presearch,
2656 presearch->researching),
2657 get_science_target_text(NULL));
2659 copy_chars_to_utf8_str(pStr, cBuf);
2661 pSurf = create_text_surf_from_utf8(pStr);
2663 dest.x = pChangeResearchButton->size.x + pChangeResearchButton->size.w + adj_size(10);
2665 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2667 dest.y += pSurf->h + adj_size(4);
2669 FREESURFACE(pSurf);
2671 /* progress bar */
2672 if (cost > 0) {
2673 int cost_div_safe = cost - 1;
2675 cost_div_safe = (cost_div_safe != 0 ? cost_div_safe : 1);
2676 dest.w = cost * pColb_Surface->w;
2677 step = pColb_Surface->w;
2678 if (dest.w > (area.w - dest.x - adj_size(16))) {
2679 dest.w = (area.w - dest.x - adj_size(16));
2680 step = ((area.w - dest.x - adj_size(16)) - pColb_Surface->w) / cost_div_safe;
2682 if (step == 0) {
2683 step = 1;
2687 dest.h = pColb_Surface->h + adj_size(4);
2688 fill_rect_alpha(pWindow->dst->surface, &dest, &bg_color);
2690 create_frame(pWindow->dst->surface,
2691 dest.x - 1, dest.y - 1, dest.w, dest.h,
2692 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2694 if (cost > adj_size(286)) {
2695 cost = adj_size(286) * ((float) presearch->bulbs_researched / cost);
2696 } else {
2697 cost = (float) cost * ((float) presearch->bulbs_researched / cost);
2700 dest.y += adj_size(2);
2701 for (i = 0; i < cost; i++) {
2702 alphablit(pColb_Surface, NULL, pWindow->dst->surface, &dest, 255);
2703 dest.x += step;
2707 /* improvement icons */
2709 dest.y += dest.h + adj_size(4);
2710 dest.x = pChangeResearchButton->size.x + pChangeResearchButton->size.w + adj_size(10);
2712 /* buildings */
2713 improvement_iterate(pImprove) {
2714 requirement_vector_iterate(&pImprove->reqs, preq) {
2715 if (VUT_ADVANCE == preq->source.kind
2716 && (advance_number(preq->source.value.advance)
2717 == presearch->researching)) {
2718 pSurf = adj_surf(get_building_surface(pImprove));
2719 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2720 dest.x += pSurf->w + 1;
2722 } requirement_vector_iterate_end;
2723 } improvement_iterate_end;
2725 dest.x += adj_size(5);
2727 /* units */
2728 unit_type_iterate(un) {
2729 pUnit = un;
2730 if (advance_number(pUnit->require_advance) == presearch->researching) {
2731 SDL_Surface *surf = get_unittype_surface(un, direction8_invalid());
2732 int w = surf->w;
2734 if (w > 64) {
2735 float zoom = DEFAULT_ZOOM * (64.0 / w);
2737 pSurf = zoomSurface(surf, zoom, zoom, 1);
2738 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2739 dest.x += pSurf->w + adj_size(2);
2740 FREESURFACE(pSurf);
2741 } else {
2742 pSurf = adj_surf(surf);
2743 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2744 dest.x += pSurf->w + adj_size(2);
2747 } unit_type_iterate_end;
2749 /* -------------------------------- */
2750 /* draw separator line */
2751 dest.x = area.x + adj_size(16);
2752 dest.y += adj_size(48) + adj_size(6);
2754 create_line(pWindow->dst->surface,
2755 dest.x, dest.y, (area.x + area.w - adj_size(16)), dest.y,
2756 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2758 dest.x = pChangeResearchButton->size.x;
2759 dest.y += adj_size(6);
2761 widget_set_position(pChangeResearchGoalButton, dest.x, dest.y + adj_size(16));
2763 /* -------------------------------- */
2765 /* Goals */
2766 if (A_UNSET != presearch->tech_goal) {
2767 /* current goal text */
2768 copy_chars_to_utf8_str(pStr, research_advance_name_translation
2769 (presearch, presearch->tech_goal));
2770 pSurf = create_text_surf_from_utf8(pStr);
2772 dest.x = pChangeResearchGoalButton->size.x + pChangeResearchGoalButton->size.w + adj_size(10);
2773 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2775 dest.y += pSurf->h;
2777 FREESURFACE(pSurf);
2779 copy_chars_to_utf8_str(pStr, get_science_goal_text
2780 (presearch->tech_goal));
2781 pSurf = create_text_surf_from_utf8(pStr);
2783 dest.x = pChangeResearchGoalButton->size.x + pChangeResearchGoalButton->size.w + adj_size(10);
2784 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2786 dest.y += pSurf->h + adj_size(6);
2788 FREESURFACE(pSurf);
2790 /* buildings */
2791 improvement_iterate(pImprove) {
2792 requirement_vector_iterate(&pImprove->reqs, preq) {
2793 if (VUT_ADVANCE == preq->source.kind
2794 && (advance_number(preq->source.value.advance)
2795 == presearch->tech_goal)) {
2796 pSurf = adj_surf(get_building_surface(pImprove));
2797 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2798 dest.x += pSurf->w + 1;
2800 } requirement_vector_iterate_end;
2801 } improvement_iterate_end;
2803 dest.x += adj_size(6);
2805 /* units */
2806 unit_type_iterate(un) {
2807 pUnit = un;
2808 if (advance_number(pUnit->require_advance) == presearch->tech_goal) {
2809 SDL_Surface *surf = get_unittype_surface(un, direction8_invalid());
2810 int w = surf->w;
2812 if (w > 64) {
2813 float zoom = DEFAULT_ZOOM * (64.0 / w);
2815 pSurf = zoomSurface(surf, zoom, zoom, 1);
2816 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2817 dest.x += pSurf->w + adj_size(2);
2818 FREESURFACE(pSurf);
2819 } else {
2820 pSurf = adj_surf(surf);
2821 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2822 dest.x += pSurf->w + adj_size(2);
2825 } unit_type_iterate_end;
2828 /* -------------------------------- */
2829 widget_mark_dirty(pWindow);
2830 redraw_group(pScienceDlg->pBeginWidgetList, pWindow->prev, 1);
2831 flush_dirty();
2833 FREEUTF8STR(pStr);
2837 /**************************************************************************
2838 Close science report dialog.
2839 **************************************************************************/
2840 static void science_report_dialog_popdown(void)
2842 if (pScienceDlg) {
2843 popdown_window_group_dialog(pScienceDlg->pBeginWidgetList,
2844 pScienceDlg->pEndWidgetList);
2845 FC_FREE(pScienceDlg);
2846 set_wstate(get_research_widget(), FC_WS_NORMAL);
2847 widget_redraw(get_research_widget());
2848 widget_mark_dirty(get_research_widget());
2849 flush_dirty();
2853 /**************************************************************************
2854 Close research target changing dialog.
2855 **************************************************************************/
2856 static int exit_change_tech_dlg_callback(struct widget *pWidget)
2858 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2859 if (pChangeTechDlg) {
2860 popdown_window_group_dialog(pChangeTechDlg->pBeginWidgetList,
2861 pChangeTechDlg->pEndWidgetList);
2862 FC_FREE(pChangeTechDlg->pScroll);
2863 FC_FREE(pChangeTechDlg);
2864 enable_science_dialog();
2865 if (pWidget) {
2866 flush_dirty();
2871 return -1;
2874 /**************************************************************************
2875 User interacted with button of specific Tech.
2876 **************************************************************************/
2877 static int change_research_callback(struct widget *pWidget)
2879 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2880 dsend_packet_player_research(&client.conn, (MAX_ID - pWidget->ID));
2881 exit_change_tech_dlg_callback(NULL);
2882 } else if (Main.event.button.button == SDL_BUTTON_MIDDLE) {
2883 popup_tech_info((MAX_ID - pWidget->ID));
2886 return -1;
2889 /**************************************************************************
2890 This function is used by change research and change goals dlgs.
2891 **************************************************************************/
2892 static int change_research_goal_dialog_callback(struct widget *pWindow)
2894 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2895 if (select_window_group_dialog(pChangeTechDlg->pBeginWidgetList, pWindow)) {
2896 widget_flush(pWindow);
2900 return -1;
2903 /**************************************************************************
2904 Popup dialog to change current research.
2905 **************************************************************************/
2906 static void popup_change_research_dialog(void)
2908 const struct research *presearch = research_get(client_player());
2909 struct widget *pBuf = NULL;
2910 struct widget *pWindow;
2911 utf8_str *pstr;
2912 SDL_Surface *pSurf;
2913 int max_col, max_row, col, i, count = 0, h;
2914 SDL_Rect area;
2916 if (is_future_tech(presearch->researching)) {
2917 return;
2920 advance_index_iterate(A_FIRST, aidx) {
2921 if (!research_invention_gettable(presearch, aidx, FALSE)) {
2922 continue;
2924 count++;
2925 } advance_index_iterate_end;
2927 if (count < 2) {
2928 return;
2931 pChangeTechDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
2933 pstr = create_utf8_from_char(_("What should we focus on now?"), adj_font(12));
2934 pstr->style |= TTF_STYLE_BOLD;
2936 pWindow = create_window_skeleton(NULL, pstr, 0);
2937 pChangeTechDlg->pEndWidgetList = pWindow;
2938 set_wstate(pWindow, FC_WS_NORMAL);
2939 pWindow->action = change_research_goal_dialog_callback;
2941 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_REASARCH_WINDOW, pWindow);
2943 area = pWindow->area;
2945 /* ------------------------- */
2946 /* exit button */
2947 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2948 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
2949 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
2950 adj_font(12));
2951 area.w += pBuf->size.w + adj_size(10);
2952 pBuf->action = exit_change_tech_dlg_callback;
2953 set_wstate(pBuf, FC_WS_NORMAL);
2954 pBuf->key = SDLK_ESCAPE;
2956 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
2958 /* ------------------------- */
2959 /* max col - 104 is select tech widget width */
2960 max_col = (main_window_width() - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104);
2961 /* max row - 204 is select tech widget height */
2962 max_row = (main_window_height() - (pWindow->size.h - pWindow->area.h) - adj_size(2)) / adj_size(204);
2964 /* make space on screen for scrollbar */
2965 if (max_col * max_row < count) {
2966 max_col--;
2969 if (count < max_col + 1) {
2970 col = count;
2971 } else {
2972 if (count < max_col + 3) {
2973 col = max_col - 2;
2974 } else {
2975 if (count < max_col + 5) {
2976 col = max_col - 1;
2977 } else {
2978 col = max_col;
2983 pstr = create_utf8_str(NULL, 0, adj_font(10));
2984 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
2986 count = 0;
2987 h = col * max_row;
2988 advance_index_iterate(A_FIRST, aidx) {
2989 if (!research_invention_gettable(presearch, aidx, FALSE)) {
2990 continue;
2993 count++;
2995 copy_chars_to_utf8_str(pstr, advance_name_translation(advance_by_number(aidx)));
2996 pSurf = create_select_tech_icon(pstr, aidx, MED_MODE);
2997 pBuf = create_icon2(pSurf, pWindow->dst,
2998 WF_FREE_THEME | WF_RESTORE_BACKGROUND);
3000 set_wstate(pBuf, FC_WS_NORMAL);
3001 pBuf->action = change_research_callback;
3003 add_to_gui_list(MAX_ID - aidx, pBuf);
3005 if (count > h) {
3006 set_wflag(pBuf, WF_HIDDEN);
3008 } advance_index_iterate_end;
3010 FREEUTF8STR(pstr);
3012 pChangeTechDlg->pBeginWidgetList = pBuf;
3013 pChangeTechDlg->pBeginActiveWidgetList = pChangeTechDlg->pBeginWidgetList;
3014 pChangeTechDlg->pEndActiveWidgetList = pChangeTechDlg->pEndWidgetList->prev->prev;
3016 /* -------------------------------------------------------------- */
3018 i = 0;
3019 if (count > col) {
3020 count = (count + (col - 1)) / col;
3021 if (count > max_row) {
3022 pChangeTechDlg->pActiveWidgetList = pChangeTechDlg->pEndActiveWidgetList;
3023 count = max_row;
3024 i = create_vertical_scrollbar(pChangeTechDlg, col, count, TRUE, TRUE);
3026 } else {
3027 count = 1;
3030 disable_science_dialog();
3032 area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + i));
3033 area.h = MAX(area.h, count * pBuf->size.h + adj_size(2));
3035 /* alloca window theme and win background buffer */
3036 pSurf = theme_get_background(theme, BACKGROUND_CHANGERESEARCHDLG);
3037 resize_window(pWindow, pSurf, NULL,
3038 (pWindow->size.w - pWindow->area.w) + area.w,
3039 (pWindow->size.h - pWindow->area.h) + area.h);
3040 FREESURFACE(pSurf);
3042 area = pWindow->area;
3044 widget_set_position(pWindow,
3045 (main_window_width() - pWindow->size.w) / 2,
3046 (main_window_height() - pWindow->size.h) / 2);
3048 /* exit button */
3049 pBuf = pWindow->prev;
3050 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
3051 pBuf->size.y = pWindow->size.y + adj_size(2);
3053 setup_vertical_widgets_position(col, area.x + 1,
3054 area.y, 0, 0,
3055 pChangeTechDlg->pBeginActiveWidgetList,
3056 pChangeTechDlg->pEndActiveWidgetList);
3058 if (pChangeTechDlg->pScroll) {
3059 setup_vertical_scrollbar_area(pChangeTechDlg->pScroll,
3060 area.x + area.w, area.y,
3061 area.h, TRUE);
3064 redraw_group(pChangeTechDlg->pBeginWidgetList, pWindow, FALSE);
3066 widget_flush(pWindow);
3069 /**************************************************************************
3070 User chose spesic tech as research goal.
3071 **************************************************************************/
3072 static int change_research_goal_callback(struct widget *pWidget)
3074 if (Main.event.button.button == SDL_BUTTON_LEFT) {
3075 dsend_packet_player_tech_goal(&client.conn, (MAX_ID - pWidget->ID));
3077 exit_change_tech_dlg_callback(NULL);
3079 /* Following is to make the menu go back to the current goal;
3080 * there may be a better way to do this? --dwp */
3081 real_science_report_dialog_update();
3082 } else if (Main.event.button.button == SDL_BUTTON_MIDDLE) {
3083 popup_tech_info((MAX_ID - pWidget->ID));
3086 return -1;
3089 /**************************************************************************
3090 Popup dialog to change research goal.
3091 **************************************************************************/
3092 static void popup_change_research_goal_dialog(void)
3094 const struct research *presearch = research_get(client_player());
3095 struct widget *pBuf = NULL;
3096 struct widget *pWindow;
3097 utf8_str *pstr;
3098 SDL_Surface *pSurf;
3099 char cBuf[128];
3100 int max_col, max_row, col, i, count = 0, h , num;
3101 SDL_Rect area;
3103 /* collect all techs which are reachable in under 11 steps
3104 * hist will hold afterwards the techid of the current choice
3106 advance_index_iterate(A_FIRST, aidx) {
3107 if (research_invention_reachable(presearch, aidx)
3108 && TECH_KNOWN != research_invention_state(presearch, aidx)
3109 && (11 > research_goal_unknown_techs(presearch, aidx)
3110 || aidx == presearch->tech_goal)) {
3111 count++;
3113 } advance_index_iterate_end;
3115 if (count < 1) {
3116 return;
3119 pChangeTechDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3121 pstr = create_utf8_from_char(_("Select target :"), adj_font(12));
3122 pstr->style |= TTF_STYLE_BOLD;
3124 pWindow = create_window_skeleton(NULL, pstr, 0);
3125 pChangeTechDlg->pEndWidgetList = pWindow;
3126 set_wstate(pWindow, FC_WS_NORMAL);
3127 pWindow->action = change_research_goal_dialog_callback;
3129 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_GOAL_WINDOW, pWindow);
3131 area = pWindow->area;
3133 /* ------------------------- */
3134 /* exit button */
3135 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3136 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3137 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
3138 adj_font(12));
3139 area.w += pBuf->size.w + adj_size(10);
3140 pBuf->action = exit_change_tech_dlg_callback;
3141 set_wstate(pBuf, FC_WS_NORMAL);
3142 pBuf->key = SDLK_ESCAPE;
3144 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_GOAL_CANCEL_BUTTON, pBuf);
3146 /* ------------------------- */
3147 /* max col - 104 is goal tech widget width */
3148 max_col = (main_window_width() - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104);
3150 /* max row - 204 is goal tech widget height */
3151 max_row = (main_window_height() - (pWindow->size.h - pWindow->area.h) - adj_size(2)) / adj_size(204);
3153 /* make space on screen for scrollbar */
3154 if (max_col * max_row < count) {
3155 max_col--;
3158 if (count < max_col + 1) {
3159 col = count;
3160 } else {
3161 if (count < max_col + 3) {
3162 col = max_col - 2;
3163 } else {
3164 if (count < max_col + 5) {
3165 col = max_col - 1;
3166 } else {
3167 col = max_col;
3172 pstr = create_utf8_str(NULL, 0, adj_font(10));
3173 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
3175 /* collect all techs which are reachable in under 11 steps
3176 * hist will hold afterwards the techid of the current choice
3178 count = 0;
3179 h = col * max_row;
3180 advance_index_iterate(A_FIRST, aidx) {
3181 if (research_invention_reachable(presearch, aidx)
3182 && TECH_KNOWN != research_invention_state(presearch, aidx)
3183 && (11 > (num = research_goal_unknown_techs(presearch, aidx))
3184 || aidx == presearch->tech_goal)) {
3186 count++;
3187 fc_snprintf(cBuf, sizeof(cBuf), "%s\n%d %s",
3188 advance_name_translation(advance_by_number(aidx)),
3189 num,
3190 PL_("step", "steps", num));
3191 copy_chars_to_utf8_str(pstr, cBuf);
3192 pSurf = create_select_tech_icon(pstr, aidx, FULL_MODE);
3193 pBuf = create_icon2(pSurf, pWindow->dst,
3194 WF_FREE_THEME | WF_RESTORE_BACKGROUND);
3196 set_wstate(pBuf, FC_WS_NORMAL);
3197 pBuf->action = change_research_goal_callback;
3199 add_to_gui_list(MAX_ID - aidx, pBuf);
3201 if (count > h) {
3202 set_wflag(pBuf, WF_HIDDEN);
3205 } advance_index_iterate_end;
3207 FREEUTF8STR(pstr);
3209 pChangeTechDlg->pBeginWidgetList = pBuf;
3210 pChangeTechDlg->pBeginActiveWidgetList = pChangeTechDlg->pBeginWidgetList;
3211 pChangeTechDlg->pEndActiveWidgetList = pChangeTechDlg->pEndWidgetList->prev->prev;
3213 /* -------------------------------------------------------------- */
3215 i = 0;
3216 if (count > col) {
3217 count = (count + (col-1)) / col;
3218 if (count > max_row) {
3219 pChangeTechDlg->pActiveWidgetList = pChangeTechDlg->pEndActiveWidgetList;
3220 count = max_row;
3221 i = create_vertical_scrollbar(pChangeTechDlg, col, count, TRUE, TRUE);
3223 } else {
3224 count = 1;
3227 disable_science_dialog();
3229 area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + i));
3230 area.h = MAX(area.h, count * pBuf->size.h + adj_size(2));
3232 /* alloca window theme and win background buffer */
3233 pSurf = theme_get_background(theme, BACKGROUND_CHANGERESEARCHDLG);
3234 resize_window(pWindow, pSurf, NULL,
3235 (pWindow->size.w - pWindow->area.w) + area.w,
3236 (pWindow->size.h - pWindow->area.h) + area.h);
3237 FREESURFACE(pSurf);
3239 area = pWindow->area;
3241 widget_set_position(pWindow,
3242 (main_window_width() - pWindow->size.w) / 2,
3243 (main_window_height() - pWindow->size.h) / 2);
3245 /* exit button */
3246 pBuf = pWindow->prev;
3247 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
3248 pBuf->size.y = pWindow->size.y + adj_size(2);
3250 setup_vertical_widgets_position(col, area.x + 1,
3251 area.y, 0, 0,
3252 pChangeTechDlg->pBeginActiveWidgetList,
3253 pChangeTechDlg->pEndActiveWidgetList);
3255 if (pChangeTechDlg->pScroll) {
3256 setup_vertical_scrollbar_area(pChangeTechDlg->pScroll,
3257 area.x + area.w, area.y,
3258 area.h, TRUE);
3261 redraw_group(pChangeTechDlg->pBeginWidgetList, pWindow, FALSE);
3263 widget_flush(pWindow);
3266 static int science_dialog_callback(struct widget *pWindow)
3268 if (Main.event.button.button == SDL_BUTTON_LEFT) {
3269 if (!pChangeTechDlg) {
3270 if (select_window_group_dialog(pScienceDlg->pBeginWidgetList, pWindow)) {
3271 widget_flush(pWindow);
3273 if (move_window_group_dialog(pScienceDlg->pBeginWidgetList, pWindow)) {
3274 real_science_report_dialog_update();
3279 return -1;
3282 /**************************************************************************
3283 Open research target changing dialog.
3284 **************************************************************************/
3285 static int popup_change_research_dialog_callback(struct widget *pWidget)
3287 if (Main.event.button.button == SDL_BUTTON_LEFT) {
3288 set_wstate(pWidget, FC_WS_NORMAL);
3289 selected_widget = NULL;
3290 widget_redraw(pWidget);
3291 widget_flush(pWidget);
3293 popup_change_research_dialog();
3295 return -1;
3298 /**************************************************************************
3299 Open research goal changing dialog.
3300 **************************************************************************/
3301 static int popup_change_research_goal_dialog_callback(struct widget *pWidget)
3303 if (Main.event.button.button == SDL_BUTTON_LEFT) {
3304 set_wstate(pWidget, FC_WS_NORMAL);
3305 selected_widget = NULL;
3306 widget_redraw(pWidget);
3307 widget_flush(pWidget);
3309 popup_change_research_goal_dialog();
3311 return -1;
3314 /**************************************************************************
3315 Close science dialog.
3316 **************************************************************************/
3317 static int popdown_science_dialog_callback(struct widget *pWidget)
3319 if (Main.event.button.button == SDL_BUTTON_LEFT) {
3320 science_report_dialog_popdown();
3323 return -1;
3326 /**************************************************************************
3327 Popup (or raise) the science report(F6). It may or may not be modal.
3328 **************************************************************************/
3329 void science_report_dialog_popup(bool raise)
3331 const struct research *presearch;
3332 struct widget *pWidget, *pWindow;
3333 struct widget *pChangeResearchButton;
3334 struct widget *pChangeResearchGoalButton;
3335 struct widget *pExitButton;
3336 utf8_str *pstr;
3337 SDL_Surface *pBackground, *pTechIcon;
3338 int count;
3339 SDL_Rect area;
3341 if (pScienceDlg) {
3342 return;
3345 presearch = research_get(client_player());
3347 /* disable research button */
3348 pWidget = get_research_widget();
3349 set_wstate(pWidget, FC_WS_DISABLED);
3350 widget_redraw(pWidget);
3351 widget_mark_dirty(pWidget);
3353 pScienceDlg = fc_calloc(1, sizeof(struct SMALL_DLG));
3355 /* TRANS: Research report title */
3356 pstr = create_utf8_from_char(_("Research"), adj_font(12));
3357 pstr->style |= TTF_STYLE_BOLD;
3359 #ifdef SMALL_SCREEN
3360 pWindow = create_window(NULL, pstr, 200, 132, 0);
3361 #else /* SMALL_SCREEN */
3362 pWindow = create_window(NULL, pstr, adj_size(400), adj_size(246), 0);
3363 #endif /* SMALL_SCREEN */
3364 set_wstate(pWindow, FC_WS_NORMAL);
3365 pWindow->action = science_dialog_callback;
3367 pScienceDlg->pEndWidgetList = pWindow;
3369 pBackground = theme_get_background(theme, BACKGROUND_SCIENCEDLG);
3370 pWindow->theme = ResizeSurface(pBackground, pWindow->size.w, pWindow->size.h, 1);
3371 FREESURFACE(pBackground);
3373 area = pWindow->area;
3375 widget_set_position(pWindow,
3376 (main_window_width() - pWindow->size.w) / 2,
3377 (main_window_height() - pWindow->size.h) / 2);
3379 add_to_gui_list(ID_SCIENCE_DLG_WINDOW, pWindow);
3381 /* count number of researchable techs */
3382 count = 0;
3383 advance_index_iterate(A_FIRST, i) {
3384 if (research_invention_reachable(presearch, i)
3385 && TECH_KNOWN != research_invention_state(presearch, i)) {
3386 count++;
3388 } advance_index_iterate_end;
3390 /* current research icon */
3391 pTechIcon = get_tech_icon(presearch->researching);
3392 pChangeResearchButton = create_icon2(pTechIcon, pWindow->dst, WF_RESTORE_BACKGROUND | WF_FREE_THEME);
3394 pChangeResearchButton->action = popup_change_research_dialog_callback;
3395 if (count > 0) {
3396 set_wstate(pChangeResearchButton, FC_WS_NORMAL);
3399 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_REASARCH_BUTTON, pChangeResearchButton);
3401 /* current research goal icon */
3402 pTechIcon = get_tech_icon(presearch->tech_goal);
3403 pChangeResearchGoalButton = create_icon2(pTechIcon, pWindow->dst, WF_RESTORE_BACKGROUND | WF_FREE_THEME);
3405 pChangeResearchGoalButton->action = popup_change_research_goal_dialog_callback;
3406 if (count > 0) {
3407 set_wstate(pChangeResearchGoalButton, FC_WS_NORMAL);
3410 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_GOAL_BUTTON, pChangeResearchGoalButton);
3412 /* ------ */
3413 /* exit button */
3414 pExitButton = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3415 WF_WIDGET_HAS_INFO_LABEL
3416 | WF_RESTORE_BACKGROUND);
3417 pExitButton->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
3418 adj_font(12));
3419 pExitButton->action = popdown_science_dialog_callback;
3420 set_wstate(pExitButton, FC_WS_NORMAL);
3421 pExitButton->key = SDLK_ESCAPE;
3423 add_to_gui_list(ID_SCIENCE_CANCEL_DLG_BUTTON, pExitButton);
3425 widget_set_position(pExitButton,
3426 area.x + area.w - pExitButton->size.w - adj_size(1),
3427 pWindow->size.y + adj_size(2));
3429 /* ======================== */
3430 pScienceDlg->pBeginWidgetList = pExitButton;
3432 real_science_report_dialog_update();
3435 /**************************************************************************
3436 Popdown all the science reports (report, change tech, change goals).
3437 **************************************************************************/
3438 void science_report_dialogs_popdown_all(void)
3440 if (pChangeTechDlg) {
3441 popdown_window_group_dialog(pChangeTechDlg->pBeginWidgetList,
3442 pChangeTechDlg->pEndWidgetList);
3443 FC_FREE(pChangeTechDlg->pScroll);
3444 FC_FREE(pChangeTechDlg);
3446 if (pScienceDlg) {
3447 popdown_window_group_dialog(pScienceDlg->pBeginWidgetList,
3448 pScienceDlg->pEndWidgetList);
3449 FC_FREE(pScienceDlg);
3450 set_wstate(get_research_widget(), FC_WS_NORMAL);
3451 widget_redraw(get_research_widget());
3452 widget_mark_dirty(get_research_widget());
3456 /****************************************************************************
3457 Resize and redraw the requirement tree.
3458 ****************************************************************************/
3459 void science_report_dialog_redraw(void)
3461 /* No requirement tree yet. */
3464 /* ===================================================================== */
3465 /* ======================== Endgame Report ============================= */
3466 /* ===================================================================== */
3468 static char eg_buffer[150 * MAX_NUM_PLAYERS];
3469 static int eg_player_count = 0;
3470 static int eg_players_received = 0;
3472 /****************************************************************
3473 Show a dialog with player statistics at endgame.
3474 TODO: Display all statistics in packet_endgame_report.
3475 *****************************************************************/
3476 void endgame_report_dialog_start(const struct packet_endgame_report *packet)
3478 eg_buffer[0] = '\0';
3479 eg_player_count = packet->player_num;
3480 eg_players_received = 0;
3483 /****************************************************************
3484 Received endgame report information about single player
3485 *****************************************************************/
3486 void endgame_report_dialog_player(const struct packet_endgame_player *packet)
3488 const struct player *pplayer = player_by_number(packet->player_id);
3490 eg_players_received++;
3492 cat_snprintf(eg_buffer, sizeof(eg_buffer),
3493 PL_("%2d: The %s ruler %s scored %d point\n",
3494 "%2d: The %s ruler %s scored %d points\n",
3495 packet->score),
3496 eg_players_received, nation_adjective_for_player(pplayer),
3497 player_name(pplayer), packet->score);
3499 if (eg_players_received == eg_player_count) {
3500 popup_notify_dialog(_("Final Report:"),
3501 _("The Greatest Civilizations in the world."),
3502 eg_buffer);