Removed silencing of gtk warning logs from gtk3.22-client.
[freeciv.git] / client / gui-xaw / citydlg.c
blob9d44c99da517f9d535f3c8e3dd7287a2c0a6e5aa
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 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdio.h>
19 #include <stdlib.h>
21 #include <X11/Intrinsic.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xaw/Form.h>
24 #include <X11/Xaw/Label.h>
25 #include <X11/Xaw/Command.h>
26 #include <X11/Xaw/MenuButton.h>
27 #include <X11/Xaw/SimpleMenu.h>
28 #include <X11/Xaw/SmeBSB.h>
29 #include <X11/Xaw/List.h>
30 #include <X11/Xaw/Viewport.h>
31 #include <X11/Xaw/AsciiText.h>
32 #include <X11/Xaw/Toggle.h>
33 #include <X11/IntrinsicP.h>
35 /* utility */
36 #include "bitvector.h"
37 #include "fcintl.h"
38 #include "log.h"
39 #include "mem.h"
40 #include "genlist.h"
41 #include "shared.h"
42 #include "support.h"
44 /* common */
45 #include "city.h"
46 #include "connection.h" /* can_conn_edit */
47 #include "game.h"
48 #include "map.h"
49 #include "packets.h"
50 #include "player.h"
51 #include "specialist.h"
52 #include "traderoutes.h"
53 #include "unitlist.h"
55 /* client */
56 #include "client_main.h"
57 #include "climap.h"
58 #include "climisc.h"
59 #include "control.h" /* request_xxx and unit_focus_set */
60 #include "options.h"
61 #include "text.h"
62 #include "tilespec.h"
64 #include "cma_fec.h"
66 #include "canvas.h"
67 #include "cityrep.h"
68 #include "cma_fe.h"
69 #include "colors.h"
70 #include "dialogs.h"
71 #include "graphics.h"
72 #include "gui_main.h"
73 #include "gui_stuff.h"
74 #include "helpdlg.h"
75 #include "inputdlg.h"
76 #include "mapctrl.h"
77 #include "mapview.h"
78 #include "optiondlg.h" /* for toggle_callback */
79 #include "pixcomm.h"
80 #include "repodlgs.h"
81 #include "wldlg.h"
83 #include "citydlg_common.h"
84 #include "citydlg.h"
86 #define MIN_NUM_CITIZENS 22
87 #define MAX_NUM_CITIZENS 50
88 #define DEFAULT_NUM_CITIZENS 38
89 #define MIN_NUM_UNITS 8
90 #define MAX_NUM_UNITS 20
91 #define DEFAULT_NUM_UNITS 11
93 struct city_dialog {
94 struct city *pcity;
96 int num_citizens_shown;
97 int num_units_shown;
99 Widget shell;
100 Widget main_form;
101 Widget left_form;
102 Widget cityname_label;
103 Widget *citizen_labels;
104 Widget production_label;
105 Widget output_label;
106 Widget storage_label;
107 Widget pollution_label;
108 Widget sub_form;
109 Widget map_canvas;
110 Widget sell_command;
111 Widget close_command, rename_command, trade_command, activate_command;
112 Widget show_units_command, cityopt_command, cma_command;
113 Widget building_label, progress_label, buy_command, change_command,
114 worklist_command, worklist_label;
115 Widget improvement_viewport, improvement_list;
116 Widget support_unit_label;
117 Widget *support_unit_pixcomms;
118 Widget support_unit_next_command;
119 Widget support_unit_prev_command;
120 Widget present_unit_label;
121 Widget *present_unit_pixcomms;
122 Widget present_unit_next_command;
123 Widget present_unit_prev_command;
124 Widget change_list;
125 Widget rename_input;
126 Widget worklist_shell;
128 Impr_type_id sell_id;
130 int support_unit_base;
131 int present_unit_base;
132 char improvlist_names[B_LAST+1][64];
133 char *improvlist_names_ptrs[B_LAST+1];
135 char *change_list_names_ptrs[B_LAST+1+U_LAST+1+1];
136 char change_list_names[B_LAST+1+U_LAST+1][200];
137 int change_list_ids[B_LAST+1+U_LAST+1];
138 int change_list_num_improvements;
140 /*int is_modal;*/
143 #define SPECLIST_TAG dialog
144 #define SPECLIST_TYPE struct city_dialog
145 #include "speclist.h"
147 #define dialog_list_iterate(dialoglist, pdialog) \
148 TYPED_LIST_ITERATE(struct city_dialog, dialoglist, pdialog)
149 #define dialog_list_iterate_end LIST_ITERATE_END
151 static struct dialog_list *dialog_list = NULL;
152 static bool dialog_list_has_been_initialised = FALSE;
154 static struct city_dialog *get_city_dialog(struct city *pcity);
155 static struct city_dialog *create_city_dialog(struct city *pcity);
156 static void close_city_dialog(struct city_dialog *pdialog);
158 static void city_dialog_update_improvement_list(struct city_dialog *pdialog);
159 static void city_dialog_update_title(struct city_dialog *pdialog);
160 static void city_dialog_update_supported_units(struct city_dialog *pdialog, int id);
161 static void city_dialog_update_present_units(struct city_dialog *pdialog, int id);
162 static void city_dialog_update_citizens(struct city_dialog *pdialog);
163 static void city_dialog_update_production(struct city_dialog *pdialog);
164 static void city_dialog_update_output(struct city_dialog *pdialog);
165 static void city_dialog_update_building(struct city_dialog *pdialog);
166 static void city_dialog_update_storage(struct city_dialog *pdialog);
167 static void city_dialog_update_pollution(struct city_dialog *pdialog);
169 static void sell_callback(Widget w, XtPointer client_data, XtPointer call_data);
170 static void buy_callback(Widget w, XtPointer client_data, XtPointer call_data);
171 static void change_callback(Widget w, XtPointer client_data, XtPointer call_data);
172 static void worklist_callback(Widget w, XtPointer client_data, XtPointer call_data);
173 void commit_city_worklist(struct worklist *pwl, void *data);
174 void cancel_city_worklist(void *data);
175 static void close_callback(Widget w, XtPointer client_data, XtPointer call_data);
176 static void rename_callback(Widget w, XtPointer client_data, XtPointer call_data);
177 static void trade_callback(Widget w, XtPointer client_data, XtPointer call_data);
178 static void activate_callback(Widget w, XtPointer client_data, XtPointer call_data);
179 static void show_units_callback(Widget W, XtPointer client_data, XtPointer call_data);
180 static void units_next_prev_callback(Widget W, XtPointer client_data,
181 XtPointer call_data);
182 static void unitupgrade_callback_yes(Widget w, XtPointer client_data,
183 XtPointer call_data);
184 static void unitupgrade_callback_no(Widget w, XtPointer client_data,
185 XtPointer call_data);
186 static void upgrade_callback(Widget w, XtPointer client_data, XtPointer call_data);
187 static void disband_callback(Widget w, XtPointer client_data, XtPointer call_data);
189 static void present_units_callback(Widget w, XtPointer client_data,
190 XtPointer call_data);
191 static void cityopt_callback(Widget w, XtPointer client_data,
192 XtPointer call_data);
193 static void cma_callback(Widget w, XtPointer client_data,
194 XtPointer call_data);
195 static void popdown_cityopt_dialog(void);
197 /****************************************************************
199 *****************************************************************/
200 static void get_contents_of_pollution(struct city_dialog *pdialog,
201 char *retbuf, int n)
203 struct city *pcity;
204 int pollution=0;
205 int corruption=0;
206 int waste=0;
207 int illness=0;
208 char buf[512];
210 if (pdialog) {
211 pcity=pdialog->pcity;
212 corruption=pcity->waste[O_TRADE];
213 waste=pcity->waste[O_SHIELD];
214 pollution=pcity->pollution;
215 if (!game.info.illness_on) {
216 fc_snprintf(buf, sizeof(buf), " -.-");
217 } else {
218 illness = city_illness_calc(pcity, NULL, NULL, NULL, NULL);
219 /* illness is in tenth of percent */
220 fc_snprintf(buf, sizeof(buf), "%4.1f",
221 (float)illness / 10.0);
225 fc_snprintf(retbuf, n, _("Corruption: %4d\n"
226 "Waste: %4d\n"
227 "Pollution: %4d\n"
228 "Plague Risk: %s"),
229 corruption, waste, pollution, buf);
232 /****************************************************************
234 *****************************************************************/
235 static void get_contents_of_storage(struct city_dialog *pdialog,
236 char *retbuf, int n)
238 struct city *pcity;
239 int foodstock=0;
240 int foodbox=0;
241 int granaryturns=0;
242 char buf[512];
244 if (pdialog) {
245 pcity=pdialog->pcity;
246 foodstock=pcity->food_stock;
247 foodbox=city_granary_size(city_size_get(pcity));
248 granaryturns = city_turns_to_grow(pcity);
249 if (granaryturns == 0) {
250 fc_snprintf(buf, sizeof(buf), _("blocked"));
251 } else if (granaryturns == FC_INFINITY) {
252 fc_snprintf(buf, sizeof(buf), _("never"));
253 } else {
254 /* A negative value means we'll have famine in that many turns.
255 But that's handled down below. */
256 fc_snprintf(buf, sizeof(buf),
257 PL_("%d turn", "%d turns", abs(granaryturns)),
258 abs(granaryturns));
262 /* We used to mark cities with a granary with a "*" here. */
263 fc_snprintf(retbuf, n, _("Granary: %3d/%-3d\n"
264 "Change in: %s"),
265 foodstock, foodbox, buf);
268 /****************************************************************
270 *****************************************************************/
271 static void get_contents_of_production(struct city_dialog *pdialog,
272 char *retbuf, int n)
274 struct city *pcity;
275 int foodprod=0;
276 int foodsurplus=0;
277 int shieldprod=0;
278 int shieldsurplus=0;
279 int tradeprod=0;
280 int tradesurplus=0;
282 if (pdialog) {
283 pcity=pdialog->pcity;
284 foodprod=pcity->prod[O_FOOD];
285 foodsurplus = pcity->surplus[O_FOOD];
286 shieldprod=pcity->prod[O_SHIELD] + pcity->waste[O_SHIELD];
287 shieldsurplus = pcity->surplus[O_SHIELD];
288 tradeprod = pcity->surplus[O_TRADE] + pcity->waste[O_TRADE];
289 tradesurplus = pcity->surplus[O_TRADE];
292 fc_snprintf(retbuf, n,
293 _("Food: %3d (%+-4d)\n"
294 "Prod: %3d (%+-4d)\n"
295 "Trade: %3d (%+-4d)"),
296 foodprod, foodsurplus,
297 shieldprod, shieldsurplus,
298 tradeprod, tradesurplus);
301 /****************************************************************
303 *****************************************************************/
304 static void get_contents_of_output(struct city_dialog *pdialog,
305 char *retbuf, int n)
307 struct city *pcity;
308 int goldtotal=0;
309 int goldsurplus=0;
310 int luxtotal=0;
311 int scitotal=0;
313 if (pdialog) {
314 pcity=pdialog->pcity;
315 goldtotal=pcity->prod[O_GOLD];
316 goldsurplus = pcity->surplus[O_GOLD];
317 luxtotal=pcity->prod[O_LUXURY];
318 scitotal=pcity->prod[O_SCIENCE];
321 fc_snprintf(retbuf, n,
322 _("Gold: %3d (%+-4d)\n"
323 "Lux: %3d\n"
324 "Sci: %3d"),
325 goldtotal, goldsurplus,
326 luxtotal,
327 scitotal);
330 /****************************************************************
332 *****************************************************************/
333 static void get_contents_of_progress(struct city_dialog *pdialog,
334 char *retbuf, int n)
336 get_city_dialog_production(pdialog ? pdialog->pcity : NULL, retbuf, n);
339 /****************************************************************
341 *****************************************************************/
342 static void get_contents_of_worklist(struct city_dialog *pdialog,
343 char *retbuf, int n)
345 struct city *pcity = pdialog ? pdialog->pcity : NULL;
347 if (pcity && worklist_is_empty(&pcity->worklist)) {
348 fc_strlcpy(retbuf, _("(is empty)"), n);
349 } else {
350 fc_strlcpy(retbuf, _("(in prog.)"), n);
354 /****************************************************************
356 *****************************************************************/
357 struct city_dialog *get_city_dialog(struct city *pcity)
359 if (!dialog_list_has_been_initialised) {
360 dialog_list = dialog_list_new();
361 dialog_list_has_been_initialised = TRUE;
364 dialog_list_iterate(dialog_list, pdialog) {
365 if (pdialog->pcity == pcity) {
366 return pdialog;
368 } dialog_list_iterate_end;
370 return NULL;
373 /****************************************************************
375 *****************************************************************/
376 bool city_dialog_is_open(struct city *pcity)
378 return get_city_dialog(pcity) != NULL;
381 /****************************************************************
383 *****************************************************************/
384 void real_city_dialog_refresh(struct city *pcity)
386 struct city_dialog *pdialog;
388 if((pdialog=get_city_dialog(pcity))) {
389 struct canvas store = {XtWindow(pdialog->map_canvas)};
391 city_dialog_update_improvement_list(pdialog);
392 city_dialog_update_title(pdialog);
393 city_dialog_update_supported_units(pdialog, 0);
394 city_dialog_update_present_units(pdialog, 0);
395 city_dialog_update_citizens(pdialog);
396 city_dialog_redraw_map(pdialog->pcity, &store);
397 city_dialog_update_production(pdialog);
398 city_dialog_update_output(pdialog);
399 city_dialog_update_building(pdialog);
400 city_dialog_update_storage(pdialog);
401 city_dialog_update_pollution(pdialog);
403 XtSetSensitive(pdialog->trade_command,
404 city_num_trade_routes(pcity)?True:False);
405 XtSetSensitive(pdialog->activate_command,
406 unit_list_size(pcity->tile->units)
407 ?True:False);
408 XtSetSensitive(pdialog->show_units_command,
409 unit_list_size(pcity->tile->units)
410 ?True:False);
411 XtSetSensitive(pdialog->cma_command, True);
412 XtSetSensitive(pdialog->cityopt_command, True);
415 if (NULL == client.conn.playing
416 || city_owner(pcity) == client.conn.playing) {
417 city_report_dialog_update_city(pcity);
418 economy_report_dialog_update();
419 } else {
420 if (pdialog) {
421 /* Set the buttons we do not want live while a Diplomat investigates */
422 XtSetSensitive(pdialog->buy_command, FALSE);
423 XtSetSensitive(pdialog->change_command, FALSE);
424 XtSetSensitive(pdialog->worklist_command, FALSE);
425 XtSetSensitive(pdialog->sell_command, FALSE);
426 XtSetSensitive(pdialog->rename_command, FALSE);
427 XtSetSensitive(pdialog->activate_command, FALSE);
428 XtSetSensitive(pdialog->show_units_command, FALSE);
429 XtSetSensitive(pdialog->cma_command, FALSE);
430 XtSetSensitive(pdialog->cityopt_command, FALSE);
435 /**************************************************************************
436 Updates supported and present units views in city dialogs for given unit
437 **************************************************************************/
438 void refresh_unit_city_dialogs(struct unit *punit)
440 struct city *pcity_sup, *pcity_pre;
441 struct city_dialog *pdialog;
443 pcity_sup = player_city_by_number(client_player(), punit->homecity);
444 pcity_pre=tile_city(unit_tile(punit));
446 if(pcity_sup && (pdialog=get_city_dialog(pcity_sup)))
447 city_dialog_update_supported_units(pdialog, 0);
449 if(pcity_pre && (pdialog=get_city_dialog(pcity_pre)))
450 city_dialog_update_present_units(pdialog, 0);
453 /****************************************************************
454 popup the dialog 10% inside the main-window
455 *****************************************************************/
456 void real_city_dialog_popup(struct city *pcity)
458 struct city_dialog *pdialog;
460 if(!(pdialog=get_city_dialog(pcity)))
461 pdialog=create_city_dialog(pcity);
463 xaw_set_relative_position(toplevel, pdialog->shell, 10, 10);
464 XtPopup(pdialog->shell, XtGrabNone);
467 /****************************************************************
468 popdown the dialog
469 *****************************************************************/
470 void popdown_city_dialog(struct city *pcity)
472 struct city_dialog *pdialog;
474 if((pdialog=get_city_dialog(pcity)))
475 close_city_dialog(pdialog);
478 /****************************************************************
479 popdown all dialogs
480 *****************************************************************/
481 void popdown_all_city_dialogs(void)
483 if(!dialog_list_has_been_initialised) {
484 return;
486 while (dialog_list_size(dialog_list) > 0) {
487 close_city_dialog(dialog_list_get(dialog_list, 0));
489 popdown_cityopt_dialog();
490 popdown_cma_dialog();
494 /****************************************************************
496 *****************************************************************/
497 static void city_map_canvas_expose(Widget w, XEvent *event, Region exposed,
498 void *client_data)
500 struct city_dialog *pdialog = client_data;
501 struct canvas store = {XtWindow(pdialog->map_canvas)};
503 city_dialog_redraw_map(pdialog->pcity, &store);
507 /****************************************************************
509 *****************************************************************/
511 #define LAYOUT_DEBUG 0
513 struct city_dialog *create_city_dialog(struct city *pcity)
515 char *dummy_improvement_list[]={
516 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
517 "2",
518 "3",
519 "4",
520 "5",
521 "6",
522 "7",
523 "8",
524 "9",
528 int i, itemWidth;
529 struct city_dialog *pdialog;
530 char lblbuf[512];
531 Widget first_citizen, first_support, first_present;
532 XtWidgetGeometry geom;
533 Dimension widthTotal;
534 Dimension widthCitizen, borderCitizen, internalCitizen, spaceCitizen;
535 Dimension widthUnit, borderUnit, internalUnit, spaceUnit;
536 Dimension widthNext, borderNext, internalNext, spaceNext;
537 Dimension widthPrev, borderPrev, internalPrev, spacePrev;
538 Widget relative;
539 enum citizen_category c = CITIZEN_SPECIALIST + DEFAULT_SPECIALIST;
541 if (tileset_tile_height(tileset) < 45) {
542 dummy_improvement_list[5] = 0;
545 if (gui_options.concise_city_production) {
546 dummy_improvement_list[0] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
549 pdialog = fc_malloc(sizeof(struct city_dialog));
550 pdialog->pcity = pcity;
551 pdialog->support_unit_base = 0;
552 pdialog->present_unit_base = 0;
553 pdialog->worklist_shell = NULL;
555 pdialog->shell=
556 XtVaCreatePopupShell(city_name_get(pcity),
557 topLevelShellWidgetClass,
558 toplevel,
559 XtNallowShellResize, True,
560 NULL);
562 pdialog->main_form=
563 XtVaCreateManagedWidget("citymainform",
564 formWidgetClass,
565 pdialog->shell,
566 NULL);
568 pdialog->cityname_label=
569 XtVaCreateManagedWidget("citynamelabel",
570 labelWidgetClass,
571 pdialog->main_form,
572 NULL);
575 first_citizen=
576 XtVaCreateManagedWidget("citizenlabels",
577 commandWidgetClass,
578 pdialog->main_form,
579 XtNfromVert,
580 pdialog->cityname_label,
581 XtNbitmap,
582 get_citizen_pixmap(c, 0, pcity),
583 NULL);
586 pdialog->sub_form=
587 XtVaCreateManagedWidget("citysubform",
588 formWidgetClass,
589 pdialog->main_form,
590 XtNfromVert,
591 (XtArgVal)first_citizen,
592 NULL);
595 pdialog->left_form=
596 XtVaCreateManagedWidget("cityleftform",
597 formWidgetClass,
598 pdialog->sub_form,
599 NULL);
601 get_contents_of_production(NULL, lblbuf, sizeof(lblbuf));
602 pdialog->production_label=
603 XtVaCreateManagedWidget("cityprodlabel",
604 labelWidgetClass,
605 pdialog->left_form,
606 XtNlabel, lblbuf,
607 NULL);
609 get_contents_of_output(NULL, lblbuf, sizeof(lblbuf));
610 pdialog->output_label=
611 XtVaCreateManagedWidget("cityoutputlabel",
612 labelWidgetClass,
613 pdialog->left_form,
614 XtNlabel, lblbuf,
615 XtNfromVert,
616 (XtArgVal)pdialog->production_label,
617 NULL);
619 get_contents_of_storage(NULL, lblbuf, sizeof(lblbuf));
620 pdialog->storage_label=
621 XtVaCreateManagedWidget("citystoragelabel",
622 labelWidgetClass,
623 pdialog->left_form,
624 XtNlabel, lblbuf,
625 XtNfromVert,
626 (XtArgVal)pdialog->output_label,
627 NULL);
629 get_contents_of_pollution(NULL, lblbuf, sizeof(lblbuf));
630 pdialog->pollution_label=
631 XtVaCreateManagedWidget("citypollutionlabel",
632 labelWidgetClass,
633 pdialog->left_form,
634 XtNlabel, lblbuf,
635 XtNfromVert,
636 (XtArgVal)pdialog->storage_label,
637 NULL);
640 pdialog->map_canvas=
641 XtVaCreateManagedWidget("citymapcanvas",
642 xfwfcanvasWidgetClass,
643 pdialog->sub_form,
644 "exposeProc", (XtArgVal)city_map_canvas_expose,
645 "exposeProcData", (XtArgVal)pdialog,
646 XtNfromHoriz, (XtArgVal)pdialog->left_form,
647 XtNwidth, get_citydlg_canvas_width(),
648 XtNheight, get_citydlg_canvas_height(),
649 NULL);
652 pdialog->building_label=
653 XtVaCreateManagedWidget("citybuildinglabel",
654 labelWidgetClass,
655 pdialog->sub_form,
656 XtNfromHoriz,
657 (XtArgVal)pdialog->map_canvas,
658 XtNlabel,
659 gui_options.concise_city_production
660 ? "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
661 : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
662 NULL);
664 get_contents_of_progress(NULL, lblbuf, sizeof(lblbuf));
665 pdialog->progress_label=
666 XtVaCreateManagedWidget("cityprogresslabel",
667 labelWidgetClass,
668 pdialog->sub_form,
669 XtNfromHoriz,
670 (XtArgVal)pdialog->map_canvas,
671 XtNfromVert,
672 pdialog->building_label,
673 XtNlabel, lblbuf,
674 NULL);
676 pdialog->buy_command=
677 I_L(XtVaCreateManagedWidget("citybuycommand",
678 commandWidgetClass,
679 pdialog->sub_form,
680 XtNfromVert,
681 pdialog->building_label,
682 XtNfromHoriz,
683 pdialog->progress_label,
684 NULL));
686 pdialog->change_command=
687 I_L(XtVaCreateManagedWidget("citychangecommand",
688 commandWidgetClass,
689 pdialog->sub_form,
690 XtNfromVert,
691 pdialog->building_label,
692 XtNfromHoriz,
693 pdialog->buy_command,
694 NULL));
696 pdialog->improvement_viewport=
697 XtVaCreateManagedWidget("cityimprovview",
698 viewportWidgetClass,
699 pdialog->sub_form,
700 XtNfromHoriz,
701 (XtArgVal)pdialog->map_canvas,
702 XtNfromVert,
703 pdialog->change_command,
704 NULL);
706 pdialog->improvement_list=
707 XtVaCreateManagedWidget("cityimprovlist",
708 listWidgetClass,
709 pdialog->improvement_viewport,
710 XtNforceColumns, 1,
711 XtNdefaultColumns,1,
712 XtNlist,
713 (XtArgVal)dummy_improvement_list,
714 XtNverticalList, False,
715 NULL);
717 pdialog->sell_command=
718 I_L(XtVaCreateManagedWidget("citysellcommand",
719 commandWidgetClass,
720 pdialog->sub_form,
721 XtNfromVert,
722 pdialog->improvement_viewport,
723 XtNfromHoriz,
724 (XtArgVal)pdialog->map_canvas,
725 NULL));
727 pdialog->worklist_command=
728 I_L(XtVaCreateManagedWidget("cityworklistcommand",
729 commandWidgetClass,
730 pdialog->sub_form,
731 XtNfromVert,
732 pdialog->improvement_viewport,
733 XtNfromHoriz,
734 pdialog->sell_command,
735 NULL));
737 get_contents_of_worklist(NULL, lblbuf, sizeof(lblbuf));
738 pdialog->worklist_label=
739 XtVaCreateManagedWidget("cityworklistlabel",
740 labelWidgetClass,
741 pdialog->sub_form,
742 XtNfromVert,
743 pdialog->improvement_viewport,
744 XtNfromHoriz,
745 pdialog->worklist_command,
746 XtNlabel, lblbuf,
747 NULL);
750 pdialog->support_unit_label=
751 I_L(XtVaCreateManagedWidget("supportunitlabel",
752 labelWidgetClass,
753 pdialog->main_form,
754 XtNfromVert,
755 pdialog->sub_form,
756 NULL));
758 first_support=
759 XtVaCreateManagedWidget("supportunitcanvas",
760 pixcommWidgetClass,
761 pdialog->main_form,
762 XtNfromVert, pdialog->support_unit_label,
763 XtNwidth, tileset_full_tile_width(tileset),
764 XtNheight, 3 * tileset_tile_height(tileset) / 2,
765 NULL);
767 pdialog->present_unit_label=
768 I_L(XtVaCreateManagedWidget("presentunitlabel",
769 labelWidgetClass,
770 pdialog->main_form,
771 XtNfromVert,
772 first_support,
773 NULL));
775 first_present=
776 XtVaCreateManagedWidget("presentunitcanvas",
777 pixcommWidgetClass,
778 pdialog->main_form,
779 XtNfromVert, pdialog->present_unit_label,
780 XtNwidth, tileset_full_tile_width(tileset),
781 XtNheight, tileset_full_tile_height(tileset),
782 NULL);
785 pdialog->support_unit_next_command=
786 XtVaCreateManagedWidget("supportunitnextcommand",
787 commandWidgetClass,
788 pdialog->main_form,
789 NULL);
790 pdialog->support_unit_prev_command=
791 XtVaCreateManagedWidget("supportunitprevcommand",
792 commandWidgetClass,
793 pdialog->main_form,
794 NULL);
796 pdialog->present_unit_next_command=
797 XtVaCreateManagedWidget("presentunitnextcommand",
798 commandWidgetClass,
799 pdialog->main_form,
800 NULL);
801 pdialog->present_unit_prev_command=
802 XtVaCreateManagedWidget("presentunitprevcommand",
803 commandWidgetClass,
804 pdialog->main_form,
805 NULL);
808 pdialog->close_command=
809 I_L(XtVaCreateManagedWidget("cityclosecommand",
810 commandWidgetClass,
811 pdialog->main_form,
812 XtNfromVert, first_present,
813 NULL));
815 pdialog->rename_command=
816 I_L(XtVaCreateManagedWidget("cityrenamecommand",
817 commandWidgetClass,
818 pdialog->main_form,
819 XtNfromVert, first_present,
820 XtNfromHoriz, pdialog->close_command,
821 NULL));
823 pdialog->trade_command=
824 I_L(XtVaCreateManagedWidget("citytradecommand",
825 commandWidgetClass,
826 pdialog->main_form,
827 XtNfromVert, first_present,
828 XtNfromHoriz, pdialog->rename_command,
829 NULL));
831 pdialog->activate_command=
832 I_L(XtVaCreateManagedWidget("cityactivatecommand",
833 commandWidgetClass,
834 pdialog->main_form,
835 XtNfromVert, first_present,
836 XtNfromHoriz, pdialog->trade_command,
837 NULL));
839 pdialog->show_units_command=
840 I_L(XtVaCreateManagedWidget("cityshowunitscommand",
841 commandWidgetClass,
842 pdialog->main_form,
843 XtNfromVert, first_present,
844 XtNfromHoriz, pdialog->activate_command,
845 NULL));
847 pdialog->cma_command =
848 I_L(XtVaCreateManagedWidget("cmacommand",
849 commandWidgetClass,
850 pdialog->main_form,
851 XtNfromVert, first_present,
852 XtNfromHoriz, pdialog->show_units_command,
853 NULL));
855 pdialog->cityopt_command=
856 I_L(XtVaCreateManagedWidget("cityoptionscommand",
857 commandWidgetClass,
858 pdialog->main_form,
859 XtNfromVert, first_present,
860 XtNfromHoriz, pdialog->cma_command,
861 NULL));
864 XtRealizeWidget(pdialog->shell);
865 XtQueryGeometry (pdialog->sub_form, NULL, &geom);
866 widthTotal=geom.width;
867 if (widthTotal>0) {
868 XtQueryGeometry (first_citizen, NULL, &geom);
869 widthCitizen=geom.width;
870 borderCitizen=geom.border_width;
871 XtVaGetValues(first_citizen,
872 XtNinternalWidth, &internalCitizen,
873 XtNhorizDistance, &spaceCitizen,
874 NULL);
875 XtQueryGeometry (first_support, NULL, &geom);
876 widthUnit=geom.width;
877 borderUnit=geom.border_width;
878 XtVaGetValues(first_support,
879 XtNinternalWidth, &internalUnit,
880 XtNhorizDistance, &spaceUnit,
881 NULL);
882 XtQueryGeometry (pdialog->support_unit_next_command, NULL, &geom);
883 widthNext=geom.width;
884 borderNext=geom.border_width;
885 XtVaGetValues(pdialog->support_unit_next_command,
886 XtNinternalWidth, &internalNext,
887 XtNhorizDistance, &spaceNext,
888 NULL);
889 XtQueryGeometry (pdialog->support_unit_prev_command, NULL, &geom);
890 widthPrev=geom.width;
891 borderPrev=geom.border_width;
892 XtVaGetValues(pdialog->support_unit_prev_command,
893 XtNinternalWidth, &internalPrev,
894 XtNhorizDistance, &spacePrev,
895 NULL);
896 #if LAYOUT_DEBUG >= 3
897 printf
899 "T: w: %d\n"
900 "C: wbis: %d %d %d %d\n"
901 "U: wbis: %d %d %d %d\n"
902 "N: wbis: %d %d %d %d\n"
903 "P: wbis: %d %d %d %d\n"
905 widthTotal,
906 widthCitizen, borderCitizen, internalCitizen, spaceCitizen,
907 widthUnit, borderUnit, internalUnit, spaceUnit,
908 widthNext, borderNext, internalNext, spaceNext,
909 widthPrev, borderPrev, internalPrev, spacePrev
911 #endif
912 itemWidth=widthCitizen+2*borderCitizen+2*internalCitizen+spaceCitizen;
913 if (itemWidth>0) {
914 pdialog->num_citizens_shown=widthTotal/itemWidth;
915 if (pdialog->num_citizens_shown<MIN_NUM_CITIZENS)
916 pdialog->num_citizens_shown=MIN_NUM_CITIZENS;
917 else if (pdialog->num_citizens_shown>MAX_NUM_CITIZENS)
918 pdialog->num_citizens_shown=MAX_NUM_CITIZENS;
919 } else {
920 pdialog->num_citizens_shown=MIN_NUM_CITIZENS;
922 #if LAYOUT_DEBUG >= 2
923 printf
925 "C: wT iW nC: %d %d %d\n"
927 widthTotal,
928 itemWidth,
929 pdialog->num_citizens_shown
931 #endif
932 if (widthNext<widthPrev) widthNext=widthPrev;
933 if (borderNext<borderPrev) borderNext=borderPrev;
934 if (internalNext<internalPrev) internalNext=internalPrev;
935 if (spaceNext<spacePrev) spaceNext=spacePrev;
936 widthTotal-=(widthNext+2*borderNext+2*internalNext+spaceNext);
937 itemWidth=widthUnit+2*borderUnit+2*internalUnit+spaceUnit;
938 if (itemWidth>0) {
939 pdialog->num_units_shown=widthTotal/itemWidth;
940 if (pdialog->num_units_shown<MIN_NUM_UNITS)
941 pdialog->num_units_shown=MIN_NUM_UNITS;
942 else if (pdialog->num_units_shown>MAX_NUM_UNITS)
943 pdialog->num_units_shown=MAX_NUM_UNITS;
944 } else {
945 pdialog->num_units_shown=MIN_NUM_UNITS;
947 #if LAYOUT_DEBUG >= 2
948 printf
950 "U: wT iW nU: %d %d %d\n"
952 widthTotal,
953 itemWidth,
954 pdialog->num_units_shown
956 #endif
957 } else {
958 pdialog->num_citizens_shown=DEFAULT_NUM_CITIZENS;
959 pdialog->num_units_shown=DEFAULT_NUM_UNITS;
960 if (tileset_tile_height(tileset)<45) {
961 pdialog->num_citizens_shown-=5;
962 pdialog->num_units_shown+=3;
965 #if LAYOUT_DEBUG >= 1
966 printf
968 "nC nU: %d %d\n"
970 pdialog->num_citizens_shown, pdialog->num_units_shown
972 #endif
974 pdialog->citizen_labels=
975 fc_malloc(pdialog->num_citizens_shown * sizeof(Widget));
977 pdialog->support_unit_pixcomms=
978 fc_malloc(pdialog->num_units_shown * sizeof(Widget));
979 pdialog->present_unit_pixcomms=
980 fc_malloc(pdialog->num_units_shown * sizeof(Widget));
983 pdialog->citizen_labels[0]=first_citizen;
984 for(i=1; i<pdialog->num_citizens_shown; i++)
985 pdialog->citizen_labels[i]=
986 XtVaCreateManagedWidget("citizenlabels",
987 commandWidgetClass,
988 pdialog->main_form,
989 XtNfromVert, pdialog->cityname_label,
990 XtNfromHoriz,
991 (XtArgVal)pdialog->citizen_labels[i-1],
992 XtNbitmap,
993 get_citizen_pixmap(c, 0, pcity),
994 NULL);
997 pdialog->support_unit_pixcomms[0]=first_support;
998 for(i=1; i<pdialog->num_units_shown; i++) {
999 pdialog->support_unit_pixcomms[i]=
1000 XtVaCreateManagedWidget("supportunitcanvas",
1001 pixcommWidgetClass,
1002 pdialog->main_form,
1003 XtNfromVert, pdialog->support_unit_label,
1004 XtNfromHoriz,
1005 (XtArgVal)pdialog->support_unit_pixcomms[i-1],
1006 XtNwidth, tileset_full_tile_width(tileset),
1007 XtNheight, 3 * tileset_tile_height(tileset) / 2,
1008 NULL);
1011 relative=pdialog->support_unit_pixcomms[pdialog->num_units_shown-1];
1012 XtVaSetValues(pdialog->support_unit_next_command,
1013 XtNfromVert, pdialog->support_unit_label,
1014 XtNfromHoriz, (XtArgVal)relative,
1015 NULL);
1016 XtVaSetValues(pdialog->support_unit_prev_command,
1017 XtNfromVert, pdialog->support_unit_next_command,
1018 XtNfromHoriz, (XtArgVal)relative,
1019 NULL);
1021 pdialog->present_unit_pixcomms[0]=first_present;
1022 for(i=1; i<pdialog->num_units_shown; i++) {
1023 pdialog->present_unit_pixcomms[i]=
1024 XtVaCreateManagedWidget("presentunitcanvas",
1025 pixcommWidgetClass,
1026 pdialog->main_form,
1027 XtNfromVert, pdialog->present_unit_label,
1028 XtNfromHoriz,
1029 (XtArgVal)pdialog->support_unit_pixcomms[i-1],
1030 XtNwidth, tileset_full_tile_width(tileset),
1031 XtNheight, tileset_full_tile_height(tileset),
1032 NULL);
1035 relative=pdialog->present_unit_pixcomms[pdialog->num_units_shown-1];
1036 XtVaSetValues(pdialog->present_unit_next_command,
1037 XtNfromVert, pdialog->present_unit_label,
1038 XtNfromHoriz, (XtArgVal)relative,
1039 NULL);
1040 XtVaSetValues(pdialog->present_unit_prev_command,
1041 XtNfromVert, pdialog->present_unit_next_command,
1042 XtNfromHoriz, (XtArgVal)relative,
1043 NULL);
1045 /* FIXME: this ignores the mask. */
1046 XtVaSetValues(pdialog->shell, XtNiconPixmap,
1047 get_icon_sprite(tileset, ICON_CITYDLG), NULL);
1050 XtAddCallback(pdialog->sell_command, XtNcallback, sell_callback,
1051 (XtPointer)pdialog);
1053 XtAddCallback(pdialog->buy_command, XtNcallback, buy_callback,
1054 (XtPointer)pdialog);
1056 XtAddCallback(pdialog->change_command, XtNcallback, change_callback,
1057 (XtPointer)pdialog);
1059 XtAddCallback(pdialog->worklist_command, XtNcallback, worklist_callback,
1060 (XtPointer)pdialog);
1062 XtAddCallback(pdialog->close_command, XtNcallback, close_callback,
1063 (XtPointer)pdialog);
1065 XtAddCallback(pdialog->rename_command, XtNcallback, rename_callback,
1066 (XtPointer)pdialog);
1068 XtAddCallback(pdialog->trade_command, XtNcallback, trade_callback,
1069 (XtPointer)pdialog);
1071 XtAddCallback(pdialog->activate_command, XtNcallback, activate_callback,
1072 (XtPointer)pdialog);
1074 XtAddCallback(pdialog->show_units_command, XtNcallback, show_units_callback,
1075 (XtPointer)pdialog);
1077 XtAddCallback(pdialog->support_unit_next_command, XtNcallback,
1078 units_next_prev_callback, (XtPointer)pdialog);
1079 XtAddCallback(pdialog->support_unit_prev_command, XtNcallback,
1080 units_next_prev_callback, (XtPointer)pdialog);
1081 XtAddCallback(pdialog->present_unit_next_command, XtNcallback,
1082 units_next_prev_callback, (XtPointer)pdialog);
1083 XtAddCallback(pdialog->present_unit_prev_command, XtNcallback,
1084 units_next_prev_callback, (XtPointer)pdialog);
1086 XtAddCallback(pdialog->cityopt_command, XtNcallback, cityopt_callback,
1087 (XtPointer)pdialog);
1089 XtAddCallback(pdialog->cma_command, XtNcallback, cma_callback,
1090 (XtPointer)pdialog);
1092 dialog_list_prepend(dialog_list, pdialog);
1094 for(i=0; i<B_LAST+1; i++)
1095 pdialog->improvlist_names_ptrs[i]=0;
1097 XtRealizeWidget(pdialog->shell);
1099 real_city_dialog_refresh(pdialog->pcity);
1101 if(make_modal)
1102 XtSetSensitive(toplevel, FALSE);
1104 pdialog->is_modal=make_modal;
1107 XSetWMProtocols(display, XtWindow(pdialog->shell), &wm_delete_window, 1);
1108 XtOverrideTranslations(pdialog->shell,
1109 XtParseTranslationTable ("<Message>WM_PROTOCOLS: msg-close-city()"));
1111 XtSetKeyboardFocus(pdialog->shell, pdialog->close_command);
1114 return pdialog;
1117 /****************************************************************
1119 *****************************************************************/
1120 void activate_callback(Widget w, XtPointer client_data,
1121 XtPointer call_data)
1123 struct city_dialog *pdialog = (struct city_dialog *)client_data;
1125 activate_all_units(pdialog->pcity->tile);
1129 /****************************************************************
1131 *****************************************************************/
1132 void show_units_callback(Widget w, XtPointer client_data,
1133 XtPointer call_data)
1135 struct city_dialog *pdialog = (struct city_dialog *)client_data;
1136 struct tile *ptile = pdialog->pcity->tile;
1138 if( unit_list_size(ptile->units) )
1139 unit_select_dialog_popup(ptile);
1143 /****************************************************************
1145 *****************************************************************/
1146 void units_next_prev_callback(Widget w, XtPointer client_data,
1147 XtPointer call_data)
1149 struct city_dialog *pdialog = (struct city_dialog *)client_data;
1151 if (w==pdialog->support_unit_next_command) {
1152 (pdialog->support_unit_base)++;
1153 city_dialog_update_supported_units(pdialog, 0);
1154 } else if (w==pdialog->support_unit_prev_command) {
1155 (pdialog->support_unit_base)--;
1156 city_dialog_update_supported_units(pdialog, 0);
1157 } else if (w==pdialog->present_unit_next_command) {
1158 (pdialog->present_unit_base)++;
1159 city_dialog_update_present_units(pdialog, 0);
1160 } else if (w==pdialog->present_unit_prev_command) {
1161 (pdialog->present_unit_base)--;
1162 city_dialog_update_present_units(pdialog, 0);
1167 #ifdef UNUSED
1168 /****************************************************************
1170 *****************************************************************/
1171 static void present_units_ok_callback(Widget w, XtPointer client_data,
1172 XtPointer call_data)
1174 destroy_message_dialog(w);
1176 #endif
1179 /****************************************************************
1181 *****************************************************************/
1182 static void present_units_activate_callback(Widget w, XtPointer client_data,
1183 XtPointer call_data)
1185 struct unit *punit =
1186 player_unit_by_number(client_player(), (size_t) client_data);
1188 if (NULL != punit) {
1189 struct city *pcity = tile_city(unit_tile(punit));
1191 unit_focus_set(punit);
1192 if (NULL != pcity) {
1193 struct city_dialog *pdialog = get_city_dialog(pcity);
1195 if (NULL != pdialog) {
1196 city_dialog_update_present_units(pdialog, 0);
1201 destroy_message_dialog(w);
1205 /****************************************************************
1207 *****************************************************************/
1208 static void supported_units_activate_callback(Widget w, XtPointer client_data,
1209 XtPointer call_data)
1211 struct unit *punit =
1212 player_unit_by_number(client_player(), (size_t) client_data);
1214 if (NULL != punit) {
1215 struct city *pcity = tile_city(unit_tile(punit));
1217 unit_focus_set(punit);
1218 if (NULL != pcity) {
1219 struct city_dialog *pdialog = get_city_dialog(pcity);
1221 if (NULL != pdialog) {
1222 city_dialog_update_supported_units(pdialog, 0);
1227 destroy_message_dialog(w);
1231 /****************************************************************
1233 *****************************************************************/
1234 static void present_units_activate_close_callback(Widget w,
1235 XtPointer client_data,
1236 XtPointer call_data)
1238 struct unit *punit =
1239 player_unit_by_number(client_player(), (size_t) client_data);
1241 destroy_message_dialog(w);
1243 if (NULL != punit) {
1244 struct city *pcity = tile_city(unit_tile(punit));
1246 unit_focus_set(punit);
1247 if (NULL != pcity) {
1248 struct city_dialog *pdialog = get_city_dialog(pcity);
1250 if (NULL != pdialog) {
1251 close_city_dialog(pdialog);
1257 /****************************************************************
1259 *****************************************************************/
1260 static void supported_units_activate_close_callback(Widget w,
1261 XtPointer client_data,
1262 XtPointer call_data)
1264 struct unit *punit =
1265 player_unit_by_number(client_player(), (size_t) client_data);
1267 destroy_message_dialog(w);
1269 if (NULL != punit) {
1270 struct city *pcity =
1271 player_city_by_number(client_player(), punit->homecity);
1273 unit_focus_set(punit);
1274 if (NULL != pcity) {
1275 struct city_dialog *pdialog = get_city_dialog(pcity);
1277 if (NULL != pdialog) {
1278 close_city_dialog(pdialog);
1285 /****************************************************************
1287 *****************************************************************/
1288 static void present_units_sentry_callback(Widget w, XtPointer client_data,
1289 XtPointer call_data)
1291 struct unit *punit =
1292 player_unit_by_number(client_player(), (size_t) client_data);
1294 if (NULL != punit) {
1295 request_unit_sentry(punit);
1298 destroy_message_dialog(w);
1302 /****************************************************************
1304 *****************************************************************/
1305 static void present_units_fortify_callback(Widget w, XtPointer client_data,
1306 XtPointer call_data)
1308 struct unit *punit =
1309 player_unit_by_number(client_player(), (size_t) client_data);
1311 if (NULL != punit) {
1312 request_unit_fortify(punit);
1315 destroy_message_dialog(w);
1319 /****************************************************************
1321 *****************************************************************/
1322 static void present_units_homecity_callback(Widget w, XtPointer client_data,
1323 XtPointer call_data)
1325 struct unit *punit =
1326 player_unit_by_number(client_player(), (size_t) client_data);
1328 if (NULL != punit) {
1329 request_unit_change_homecity(punit);
1332 destroy_message_dialog(w);
1336 /****************************************************************
1338 *****************************************************************/
1339 static void present_units_cancel_callback(Widget w, XtPointer client_data,
1340 XtPointer call_data)
1342 destroy_message_dialog(w);
1346 /****************************************************************
1348 *****************************************************************/
1349 void present_units_callback(Widget w, XtPointer client_data,
1350 XtPointer call_data)
1352 Widget wd;
1353 struct city_dialog *pdialog;
1354 struct city *pcity;
1355 XEvent *e = (XEvent*)call_data;
1356 struct unit *punit =
1357 player_unit_by_number(client_player(), (size_t) client_data);
1359 if ((NULL != punit
1360 || (can_conn_edit(&client.conn)
1361 && NULL == client.conn.playing
1362 && (punit = game_unit_by_number((size_t) client_data))))
1363 && (pcity = tile_city(unit_tile(punit)))
1364 && (pdialog = get_city_dialog(pcity))) {
1366 if(e->type==ButtonRelease && e->xbutton.button==Button2) {
1367 unit_focus_set(punit);
1368 close_city_dialog(pdialog);
1369 return;
1371 if(e->type==ButtonRelease && e->xbutton.button==Button3) {
1372 unit_focus_set(punit);
1373 return;
1376 wd=popup_message_dialog(pdialog->shell,
1377 "presentunitsdialog",
1378 unit_description(punit),
1379 present_units_activate_callback, punit->id, 1,
1380 present_units_activate_close_callback, punit->id, 1,
1381 present_units_sentry_callback, punit->id, 1,
1382 present_units_fortify_callback, punit->id, 1,
1383 disband_callback, punit->id, 1,
1384 present_units_homecity_callback, punit->id, 1,
1385 upgrade_callback, punit->id, 1,
1386 present_units_cancel_callback, 0, 0,
1387 NULL);
1389 if (punit->activity == ACTIVITY_SENTRY
1390 || !can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
1391 XtSetSensitive(XtNameToWidget(wd, "*button2"), FALSE);
1393 if (punit->activity == ACTIVITY_FORTIFYING
1394 || !can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
1395 XtSetSensitive(XtNameToWidget(wd, "*button3"), FALSE);
1397 if (unit_has_type_flag(punit, UTYF_UNDISBANDABLE)) {
1398 XtSetSensitive(XtNameToWidget(wd, "*button4"), FALSE);
1400 if (punit->homecity == pcity->id) {
1401 XtSetSensitive(XtNameToWidget(wd, "*button5"), FALSE);
1403 if (NULL == client.conn.playing
1404 || (NULL == can_upgrade_unittype(client.conn.playing,
1405 unit_type_get(punit)))) {
1406 XtSetSensitive(XtNameToWidget(wd, "*button6"), FALSE);
1411 /****************************************************************
1413 *****************************************************************/
1414 static void rename_city_callback(Widget w, XtPointer client_data,
1415 XtPointer call_data)
1417 struct city_dialog *pdialog = client_data;
1419 if (pdialog) {
1420 city_rename(pdialog->pcity, input_dialog_get_input(w));
1422 input_dialog_destroy(w);
1429 /****************************************************************
1431 *****************************************************************/
1432 void rename_callback(Widget w, XtPointer client_data, XtPointer call_data)
1434 struct city_dialog *pdialog;
1436 pdialog=(struct city_dialog *)client_data;
1438 input_dialog_create(pdialog->shell,
1439 "shellrenamecity",
1440 _("What should we rename the city to?"),
1441 city_name_get(pdialog->pcity),
1442 rename_city_callback, (XtPointer)pdialog,
1443 rename_city_callback, (XtPointer)0);
1446 /****************************************************************
1448 *****************************************************************/
1449 static void trade_message_dialog_callback(Widget w, XtPointer client_data,
1450 XtPointer call_data)
1452 destroy_message_dialog(w);
1455 /****************************************************************
1457 *****************************************************************/
1458 void trade_callback(Widget w, XtPointer client_data, XtPointer call_data)
1460 int i;
1461 int x=0,total=0;
1462 char buf[512], *bptr=buf;
1463 int nleft = sizeof(buf);
1464 struct city_dialog *pdialog;
1466 pdialog = (struct city_dialog *)client_data;
1468 fc_snprintf(buf, sizeof(buf),
1469 _("These trade routes have been established with %s:\n"),
1470 city_name_get(pdialog->pcity));
1471 bptr = end_of_strn(bptr, &nleft);
1473 for (i = 0; i < MAX_TRADE_ROUTES; i++)
1474 if(pdialog->pcity->trade[i]) {
1475 struct city *pcity;
1476 x=1;
1477 total+=pdialog->pcity->trade_value[i];
1478 if ((pcity = game_city_by_number(pdialog->pcity->trade[i]))) {
1479 fc_snprintf(bptr, nleft, _("%32s: %2d Trade/Year\n"),
1480 city_name_get(pcity), pdialog->pcity->trade_value[i]);
1481 bptr = end_of_strn(bptr, &nleft);
1482 } else {
1483 fc_snprintf(bptr, nleft, _("%32s: %2d Trade/Year\n"), _("Unknown"),
1484 pdialog->pcity->trade_value[i]);
1485 bptr = end_of_strn(bptr, &nleft);
1488 if (!x) {
1489 fc_strlcpy(bptr, _("No trade routes exist.\n"), nleft);
1490 } else {
1491 fc_snprintf(bptr, nleft, _("\nTotal trade %d Trade/Year\n"), total);
1494 popup_message_dialog(pdialog->shell,
1495 "citytradedialog",
1496 buf,
1497 trade_message_dialog_callback, 0, 0,
1498 NULL);
1502 /****************************************************************
1504 *****************************************************************/
1505 void city_dialog_update_pollution(struct city_dialog *pdialog)
1507 char buf[512];
1509 get_contents_of_pollution(pdialog, buf, sizeof(buf));
1510 xaw_set_label(pdialog->pollution_label, buf);
1513 /****************************************************************
1515 *****************************************************************/
1516 void city_dialog_update_storage(struct city_dialog *pdialog)
1518 char buf[512];
1520 get_contents_of_storage(pdialog, buf, sizeof(buf));
1521 xaw_set_label(pdialog->storage_label, buf);
1524 /****************************************************************
1526 *****************************************************************/
1527 void city_dialog_update_building(struct city_dialog *pdialog)
1529 char buf[32];
1530 struct city *pcity=pdialog->pcity;
1532 XtSetSensitive(pdialog->buy_command, city_can_buy(pcity));
1533 /* FIXME: Should not pass NULL as improvement
1534 * to test_player_sell_building_now(). It skips many tests. */
1535 XtSetSensitive(pdialog->sell_command,
1536 test_player_sell_building_now(client.conn.playing,
1537 pcity, NULL) == TR_SUCCESS);
1539 xaw_set_label(pdialog->building_label,
1540 city_production_name_translation(pcity));
1542 get_contents_of_progress(pdialog, buf, sizeof(buf));
1543 xaw_set_label(pdialog->progress_label, buf);
1545 get_contents_of_worklist(pdialog, buf, sizeof(buf));
1546 xaw_set_label(pdialog->worklist_label, buf);
1549 /****************************************************************
1551 *****************************************************************/
1552 void city_dialog_update_production(struct city_dialog *pdialog)
1554 char buf[512];
1556 get_contents_of_production(pdialog, buf, sizeof(buf));
1557 xaw_set_label(pdialog->production_label, buf);
1560 /****************************************************************
1562 *****************************************************************/
1563 void city_dialog_update_output(struct city_dialog *pdialog)
1565 char buf[512];
1567 get_contents_of_output(pdialog, buf, sizeof(buf));
1568 xaw_set_label(pdialog->output_label, buf);
1571 /****************************************************************************
1572 Handle the callback when a citizen sprite widget is clicked.
1573 ****************************************************************************/
1574 static void citizen_callback(Widget w, XtPointer client_data,
1575 XtPointer call_data)
1577 struct city_dialog *pdialog = client_data;
1578 int i;
1580 /* HACK: figure out which figure was clicked. */
1581 for (i = 0; i < city_size_get(pdialog->pcity); i++) {
1582 if (pdialog->citizen_labels[i] == w) {
1583 break;
1586 fc_assert(i < city_size_get(pdialog->pcity));
1588 city_rotate_specialist(pdialog->pcity, i);
1591 /****************************************************************
1593 *****************************************************************/
1594 void city_dialog_update_citizens(struct city_dialog *pdialog)
1596 enum citizen_category categories[MAX_CITY_SIZE];
1597 int i;
1598 struct city *pcity=pdialog->pcity;
1599 int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories);
1601 for (i = 0; i < num_citizens && i < pdialog->num_citizens_shown; i++) {
1602 xaw_set_bitmap(pdialog->citizen_labels[i],
1603 get_citizen_pixmap(categories[i], i, pcity));
1605 /* HACK: set sensitivity/callbacks on the widget */
1606 XtRemoveAllCallbacks(pdialog->citizen_labels[i], XtNcallback);
1607 XtAddCallback(pdialog->citizen_labels[i], XtNcallback,
1608 citizen_callback, (XtPointer)pdialog);
1609 XtSetSensitive(pdialog->citizen_labels[i], TRUE);
1612 if (i >= pdialog->num_citizens_shown && i < num_citizens) {
1613 i = pdialog->num_citizens_shown - 1;
1614 /* FIXME: what about the mask? */
1615 xaw_set_bitmap(pdialog->citizen_labels[i],
1616 get_arrow_sprite(tileset, ARROW_RIGHT)->pixmap);
1617 XtSetSensitive(pdialog->citizen_labels[i], FALSE);
1618 XtRemoveAllCallbacks(pdialog->citizen_labels[i], XtNcallback);
1619 return;
1622 for(; i<pdialog->num_citizens_shown; i++) {
1623 xaw_set_bitmap(pdialog->citizen_labels[i], None);
1624 XtSetSensitive(pdialog->citizen_labels[i], FALSE);
1625 XtRemoveAllCallbacks(pdialog->citizen_labels[i], XtNcallback);
1629 /****************************************************************
1631 *****************************************************************/
1632 static void support_units_callback(Widget w, XtPointer client_data,
1633 XtPointer call_data)
1635 Widget wd;
1636 XEvent *e = (XEvent*)call_data;
1637 struct unit *punit =
1638 player_unit_by_number(client_player(), (size_t) client_data);
1640 if (NULL != punit) {
1641 struct city *pcity = game_city_by_number(punit->homecity);
1643 if (NULL != pcity) {
1644 struct city_dialog *pdialog = get_city_dialog(pcity);
1646 if ( NULL != pdialog) {
1647 if(e->type==ButtonRelease && e->xbutton.button==Button2) {
1648 unit_focus_set(punit);
1649 close_city_dialog(pdialog);
1650 return;
1652 if(e->type==ButtonRelease && e->xbutton.button==Button3) {
1653 unit_focus_set(punit);
1654 return;
1656 wd = popup_message_dialog(pdialog->shell,
1657 "supportunitsdialog",
1658 unit_description(punit),
1659 supported_units_activate_callback, punit->id, 1,
1660 supported_units_activate_close_callback,
1661 punit->id, 1,
1662 disband_callback, punit->id, 1,
1663 present_units_cancel_callback, 0, 0,
1664 NULL);
1665 if (unit_has_type_flag(punit, UTYF_UNDISBANDABLE)) {
1666 XtSetSensitive(XtNameToWidget(wd, "*button3"), FALSE);
1674 /****************************************************************
1676 *****************************************************************/
1677 static int units_scroll_maintenance(int nunits, int nshow, int *base,
1678 Widget next, Widget prev)
1680 int adj_base=FALSE;
1681 int nextra;
1683 nextra=nunits-nshow;
1684 if (nextra<0) nextra=0;
1686 if (*base>nextra) {
1687 *base=nextra;
1688 adj_base=TRUE;
1690 if (*base<0) {
1691 *base=0;
1692 adj_base=TRUE;
1695 if (nextra<=0) {
1696 XtUnmapWidget(next);
1697 XtUnmapWidget(prev);
1698 } else {
1699 XtMapWidget(next);
1700 XtMapWidget(prev);
1701 XtSetSensitive(next, *base<nextra);
1702 XtSetSensitive(prev, *base>0);
1705 return (adj_base);
1708 /****************************************************************
1710 *****************************************************************/
1711 void city_dialog_update_supported_units(struct city_dialog *pdialog,
1712 int unitid)
1714 struct unit_list *plist;
1715 int i, j, adj_base;
1716 Widget pixcomm;
1717 int free_unhappy = get_city_bonus(pdialog->pcity, EFT_MAKE_CONTENT_MIL);
1719 if (NULL != client.conn.playing
1720 && city_owner(pdialog->pcity) != client.conn.playing) {
1721 plist = pdialog->pcity->client.info_units_supported;
1722 } else {
1723 plist = pdialog->pcity->units_supported;
1726 adj_base = units_scroll_maintenance(unit_list_size(plist),
1727 pdialog->num_units_shown,
1728 &(pdialog->support_unit_base),
1729 pdialog->support_unit_next_command,
1730 pdialog->support_unit_prev_command);
1732 i = 0; /* number of displayed units */
1733 j = 0; /* index into list */
1734 unit_list_iterate(plist, punit) {
1735 struct canvas store;
1736 int happy_cost = city_unit_unhappiness(punit, &free_unhappy);
1738 if (j++ < pdialog->support_unit_base) {
1739 continue;
1741 if (i >= pdialog->num_units_shown) {
1742 break;
1745 pixcomm=pdialog->support_unit_pixcomms[i];
1746 store.pixmap = XawPixcommPixmap(pixcomm);
1748 if(!adj_base && unitid && punit->id!=unitid)
1749 continue;
1751 XawPixcommClear(pixcomm); /* STG */
1752 put_unit(punit, &store, 1.0, 0, 0);
1753 put_unit_pixmap_city_overlays(punit,
1754 XawPixcommPixmap(pixcomm),
1755 punit->upkeep, happy_cost);
1757 xaw_expose_now(pixcomm);
1759 XtRemoveAllCallbacks(pixcomm, XtNcallback);
1760 XtAddCallback(pixcomm, XtNcallback,
1761 support_units_callback, INT_TO_XTPOINTER(punit->id));
1762 XtSetSensitive(pixcomm, TRUE);
1763 i++;
1764 } unit_list_iterate_end;
1766 /* Disable any empty slots */
1767 for(; i<pdialog->num_units_shown; i++) {
1768 XawPixcommClear(pdialog->support_unit_pixcomms[i]);
1769 XtSetSensitive(pdialog->support_unit_pixcomms[i], FALSE);
1773 /****************************************************************
1775 *****************************************************************/
1776 void city_dialog_update_present_units(struct city_dialog *pdialog, int unitid)
1778 struct unit_list *plist;
1779 int i, j, adj_base;
1780 Widget pixcomm;
1782 if (NULL != client.conn.playing
1783 && city_owner(pdialog->pcity) != client.conn.playing) {
1784 plist = pdialog->pcity->client.info_units_present;
1785 } else {
1786 plist = pdialog->pcity->tile->units;
1789 adj_base = units_scroll_maintenance(unit_list_size(plist),
1790 pdialog->num_units_shown,
1791 &(pdialog->present_unit_base),
1792 pdialog->present_unit_next_command,
1793 pdialog->present_unit_prev_command);
1795 i = 0; /* number of displayed units */
1796 j = 0; /* index into list */
1797 unit_list_iterate(plist, punit) {
1798 struct canvas store;
1800 if (j++ < pdialog->present_unit_base) {
1801 continue;
1803 if (i >= pdialog->num_units_shown) {
1804 break;
1807 pixcomm=pdialog->present_unit_pixcomms[i];
1808 store.pixmap = XawPixcommPixmap(pixcomm);
1810 if(!adj_base && unitid && punit->id!=unitid)
1811 continue;
1813 XawPixcommClear(pixcomm); /* STG */
1814 put_unit(punit, &store, 1.0, 0, 0);
1816 xaw_expose_now(pixcomm);
1818 XtRemoveAllCallbacks(pixcomm, XtNcallback);
1819 XtAddCallback(pixcomm, XtNcallback,
1820 present_units_callback, INT_TO_XTPOINTER(punit->id));
1821 XtSetSensitive(pixcomm, TRUE);
1822 i++;
1823 } unit_list_iterate_end;
1825 for(; i<pdialog->num_units_shown; i++) {
1826 XawPixcommClear(pdialog->present_unit_pixcomms[i]);
1827 XtSetSensitive(pdialog->present_unit_pixcomms[i], FALSE);
1832 /****************************************************************
1834 *****************************************************************/
1835 void city_dialog_update_title(struct city_dialog *pdialog)
1837 char buf[512];
1838 String now;
1840 fc_snprintf(buf, sizeof(buf), _("%s - %s citizens Governor: %s"),
1841 city_name_get(pdialog->pcity),
1842 population_to_text(city_population(pdialog->pcity)),
1843 cmafec_get_short_descr_of_city(pdialog->pcity));
1845 XtVaGetValues(pdialog->cityname_label, XtNlabel, &now, NULL);
1846 if (strcmp(now, buf) != 0) {
1847 XtVaSetValues(pdialog->cityname_label, XtNlabel, (XtArgVal)buf, NULL);
1848 xaw_horiz_center(pdialog->cityname_label);
1849 XtVaSetValues(pdialog->shell, XtNtitle,
1850 (XtArgVal)city_name_get(pdialog->pcity), NULL);
1854 /****************************************************************
1856 *****************************************************************/
1857 void city_dialog_update_improvement_list(struct city_dialog *pdialog)
1859 int n = 0, flag = 0;
1861 city_built_iterate(pdialog->pcity, pimprove) {
1862 if (!pdialog->improvlist_names_ptrs[n] ||
1863 strcmp(pdialog->improvlist_names_ptrs[n],
1864 city_improvement_name_translation(pdialog->pcity, pimprove)) != 0)
1865 flag = 1;
1866 sz_strlcpy(pdialog->improvlist_names[n],
1867 city_improvement_name_translation(pdialog->pcity, pimprove));
1868 pdialog->improvlist_names_ptrs[n] = pdialog->improvlist_names[n];
1869 n++;
1870 } city_built_iterate_end;
1872 if(pdialog->improvlist_names_ptrs[n]!=0) {
1873 pdialog->improvlist_names_ptrs[n]=0;
1874 flag=1;
1877 if(flag || n==0) {
1878 XawListChange(pdialog->improvement_list, pdialog->improvlist_names_ptrs,
1879 n, 0, False);
1880 /* force refresh of viewport so the scrollbar is added.
1881 * Buggy sun athena requires this */
1882 XtVaSetValues(pdialog->improvement_viewport, XtNforceBars, False, NULL);
1883 XtVaSetValues(pdialog->improvement_viewport, XtNforceBars, True, NULL);
1888 /**************************************************************************
1890 **************************************************************************/
1891 void citydlg_btn_select_citymap(Widget w, XEvent *event)
1893 XButtonEvent *ev=&event->xbutton;
1894 struct city *pcity = NULL;
1896 dialog_list_iterate(dialog_list, pdialog) {
1897 if (pdialog->map_canvas == w) {
1898 pcity = pdialog->pcity;
1899 break;
1901 } dialog_list_iterate_end;
1903 if (pcity) {
1904 if (!cma_is_city_under_agent(pcity, NULL)) {
1905 int xtile, ytile;
1907 if (canvas_to_city_pos(&xtile, &ytile,
1908 city_map_radius_sq_get(pcity), ev->x, ev->y)) {
1909 city_toggle_worker(pcity, xtile, ytile);
1915 /****************************************************************
1917 *****************************************************************/
1918 static void buy_callback_yes(Widget w, XtPointer client_data,
1919 XtPointer call_data)
1921 struct city_dialog *pdialog = client_data;
1923 city_buy_production(pdialog->pcity);
1925 destroy_message_dialog(w);
1929 /****************************************************************
1931 *****************************************************************/
1932 static void buy_callback_no(Widget w, XtPointer client_data,
1933 XtPointer call_data)
1935 destroy_message_dialog(w);
1939 /****************************************************************
1941 *****************************************************************/
1942 void buy_callback(Widget w, XtPointer client_data, XtPointer call_data)
1944 char tbuf[512], buf[512];
1945 struct city_dialog *pdialog = (struct city_dialog *)client_data;;
1946 const char *name = city_production_name_translation(pdialog->pcity);
1947 int value = city_production_buy_gold_cost(pdialog->pcity);
1949 if (!can_client_issue_orders()) {
1950 return;
1953 fc_snprintf(tbuf, ARRAY_SIZE(tbuf), PL_("Treasury contains %d gold.",
1954 "Treasury contains %d gold.",
1955 client_player()->economic.gold),
1956 client_player()->economic.gold);
1958 if (value <= client_player()->economic.gold) {
1959 fc_snprintf(buf, sizeof(buf),
1960 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1961 PL_("Buy %s for %d gold?\n%s",
1962 "Buy %s for %d gold?\n%s", value),
1963 name, value, tbuf);
1964 popup_message_dialog(pdialog->shell, "buydialog", buf,
1965 buy_callback_yes, pdialog, 0,
1966 buy_callback_no, 0, 0,
1967 NULL);
1969 else {
1970 fc_snprintf(buf, sizeof(buf),
1971 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1972 PL_("%s costs %d gold.\n%s",
1973 "%s costs %d gold.\n%s", value),
1974 name, value, tbuf);
1975 popup_message_dialog(pdialog->shell, "buynodialog", buf,
1976 buy_callback_no, 0, 0,
1977 NULL);
1983 /****************************************************************
1985 *****************************************************************/
1986 void unitupgrade_callback_yes(Widget w, XtPointer client_data, XtPointer call_data)
1988 struct unit *punit =
1989 player_unit_by_number(client_player(), (size_t)client_data);
1991 /* Is it right place for breaking? -ev */
1992 if (!can_client_issue_orders()) {
1993 return;
1996 if (NULL != punit) {
1997 request_unit_upgrade(punit);
2000 destroy_message_dialog(w);
2004 /****************************************************************
2006 *****************************************************************/
2007 void unitupgrade_callback_no(Widget w, XtPointer client_data, XtPointer call_data)
2009 destroy_message_dialog(w);
2013 /****************************************************************
2015 *****************************************************************/
2016 void upgrade_callback(Widget w, XtPointer client_data, XtPointer call_data)
2018 char buf[512];
2019 struct unit *punit = player_unit_by_number(client_player(),
2020 (size_t) client_data);
2022 if (!punit) {
2023 return;
2026 if (UU_OK == unit_upgrade_info(punit, buf, sizeof(buf))) {
2027 popup_message_dialog(toplevel, "upgradedialog", buf,
2028 unitupgrade_callback_yes,
2029 INT_TO_XTPOINTER(punit->id), 0,
2030 unitupgrade_callback_no, 0, 0, NULL);
2031 } else {
2032 popup_message_dialog(toplevel, "upgradenodialog", buf,
2033 unitupgrade_callback_no, 0, 0,
2034 NULL);
2037 destroy_message_dialog(w);
2041 /****************************************************************
2043 *****************************************************************/
2044 void disband_callback(Widget w, XtPointer client_data, XtPointer call_data)
2046 struct unit *punit = player_unit_by_number(client_player(),
2047 (size_t) client_data);
2048 struct unit_list *punits;
2050 if (!punit) {
2051 return;
2054 punits = unit_list_new();
2055 unit_list_append(punits, punit);
2056 popup_disband_dialog(punits);
2057 unit_list_destroy(punits);
2058 destroy_message_dialog(w);
2062 /****************************************************************
2063 Production change callback
2064 *****************************************************************/
2065 static void change_to_callback(Widget w, XtPointer client_data,
2066 XtPointer call_data)
2068 struct city_dialog *pdialog;
2069 XawListReturnStruct *ret;
2071 pdialog = (struct city_dialog *)client_data;
2073 ret = XawListShowCurrent(pdialog->change_list);
2075 if (ret->list_index != XAW_LIST_NONE) {
2076 struct universal target =
2077 universal_by_number((ret->list_index >= pdialog->change_list_num_improvements)
2078 ? VUT_UTYPE : VUT_IMPROVEMENT,
2079 pdialog->change_list_ids[ret->list_index]);
2081 city_change_production(pdialog->pcity, &target);
2084 XtDestroyWidget(XtParent(XtParent(w)));
2085 XtSetSensitive(pdialog->shell, TRUE);
2088 /****************************************************************
2090 *****************************************************************/
2091 static void change_no_callback(Widget w, XtPointer client_data,
2092 XtPointer call_data)
2094 struct city_dialog *pdialog;
2096 pdialog=(struct city_dialog *)client_data;
2098 XtDestroyWidget(XtParent(XtParent(w)));
2099 XtSetSensitive(pdialog->shell, TRUE);
2102 /****************************************************************
2104 *****************************************************************/
2105 static void change_help_callback(Widget w, XtPointer client_data,
2106 XtPointer call_data)
2108 struct city_dialog *pdialog;
2109 XawListReturnStruct *ret;
2111 pdialog=(struct city_dialog *)client_data;
2113 ret=XawListShowCurrent(pdialog->change_list);
2114 if(ret->list_index!=XAW_LIST_NONE) {
2115 int idx = pdialog->change_list_ids[ret->list_index];
2116 bool is_unit = (ret->list_index >= pdialog->change_list_num_improvements);
2118 if (is_unit) {
2119 popup_help_dialog_typed(utype_name_translation(utype_by_number(idx)), HELP_UNIT);
2120 } else if (is_great_wonder(improvement_by_number(idx))) {
2121 popup_help_dialog_typed(improvement_name_translation(improvement_by_number(idx)), HELP_WONDER);
2122 } else {
2123 popup_help_dialog_typed(improvement_name_translation(improvement_by_number(idx)), HELP_IMPROVEMENT);
2126 else
2127 popup_help_dialog_string(HELP_IMPROVEMENTS_ITEM);
2131 /****************************************************************
2133 *****************************************************************/
2134 void change_callback(Widget w, XtPointer client_data, XtPointer call_data)
2136 static char *dummy_change_list[]={
2137 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 888 turns",
2138 "2",
2139 "3",
2140 "4",
2141 "5",
2142 "6",
2143 "7",
2144 "8",
2145 "9",
2146 "0",
2147 "1",
2148 "2",
2149 "3",
2150 "4",
2151 "5",
2155 Widget cshell, cform, clabel, cview, button_change, button_cancel, button_help;
2156 Position x, y;
2157 Dimension width, height;
2158 struct city_dialog *pdialog;
2159 struct universal production;
2160 int n;
2162 pdialog=(struct city_dialog *)client_data;
2164 I_T(cshell=XtCreatePopupShell("changedialog", transientShellWidgetClass,
2165 pdialog->shell, NULL, 0));
2167 cform=XtVaCreateManagedWidget("dform", formWidgetClass, cshell, NULL);
2169 I_L(clabel=XtVaCreateManagedWidget("dlabel", labelWidgetClass, cform,
2170 NULL));
2172 cview=XtVaCreateManagedWidget("dview", viewportWidgetClass,
2173 cform,
2174 XtNfromVert,
2175 clabel,
2176 NULL);
2178 pdialog->change_list=XtVaCreateManagedWidget("dlist", listWidgetClass,
2179 cview,
2180 XtNforceColumns, 1,
2181 XtNdefaultColumns,1,
2182 XtNlist,
2183 (XtArgVal)dummy_change_list,
2184 XtNverticalList, False,
2185 NULL);
2188 button_change = I_L(XtVaCreateManagedWidget("buttonchange",
2189 commandWidgetClass,
2190 cform,
2191 XtNfromVert,
2192 cview,
2193 NULL));
2195 button_cancel = I_L(XtVaCreateManagedWidget("buttoncancel",
2196 commandWidgetClass,
2197 cform,
2198 XtNfromVert,
2199 cview,
2200 XtNfromHoriz,
2201 button_change,
2202 NULL));
2204 button_help = I_L(XtVaCreateManagedWidget("buttonhelp",
2205 commandWidgetClass,
2206 cform,
2207 XtNfromVert,
2208 cview,
2209 XtNfromHoriz,
2210 button_cancel,
2211 NULL));
2213 XtAddCallback(button_change, XtNcallback,
2214 change_to_callback, (XtPointer)pdialog);
2215 XtAddCallback(button_cancel, XtNcallback,
2216 change_no_callback, (XtPointer)pdialog);
2217 XtAddCallback(button_help, XtNcallback,
2218 change_help_callback, (XtPointer)pdialog);
2222 XtVaGetValues(pdialog->shell, XtNwidth, &width, XtNheight, &height, NULL);
2223 XtTranslateCoords(pdialog->shell, (Position) width/6, (Position) height/10,
2224 &x, &y);
2225 XtVaSetValues(cshell, XtNx, x, XtNy, y, NULL);
2227 XtPopup(cshell, XtGrabNone);
2229 XtSetSensitive(pdialog->shell, FALSE);
2231 n = 0;
2232 improvement_iterate(pimprove) {
2233 if (can_city_build_improvement_now(pdialog->pcity, pimprove)) {
2234 production.kind = VUT_IMPROVEMENT;
2235 production.value.building = pimprove;
2236 get_city_dialog_production_full(pdialog->change_list_names[n],
2237 sizeof(pdialog->change_list_names[n]),
2238 &production, pdialog->pcity);
2239 pdialog->change_list_names_ptrs[n] = pdialog->change_list_names[n];
2240 pdialog->change_list_ids[n++] = improvement_number(pimprove);
2242 } improvement_iterate_end;
2244 pdialog->change_list_num_improvements = n;
2246 unit_type_iterate(punittype) {
2247 if (can_city_build_unit_now(pdialog->pcity, punittype)) {
2248 production.kind = VUT_UTYPE;
2249 production.value.utype = punittype;
2250 get_city_dialog_production_full(pdialog->change_list_names[n],
2251 sizeof(pdialog->change_list_names[n]),
2252 &production, pdialog->pcity);
2253 pdialog->change_list_names_ptrs[n] = pdialog->change_list_names[n];
2254 pdialog->change_list_ids[n++] = utype_number(punittype);
2256 } unit_type_iterate_end;
2258 pdialog->change_list_names_ptrs[n] = 0;
2260 XawListChange(pdialog->change_list, pdialog->change_list_names_ptrs,
2261 0, 0, False);
2262 /* force refresh of viewport so the scrollbar is added.
2263 * Buggy sun athena requires this */
2264 XtVaSetValues(cview, XtNforceBars, True, NULL);
2268 /****************************************************************
2269 Display the city's worklist.
2270 *****************************************************************/
2271 void worklist_callback(Widget w, XtPointer client_data, XtPointer call_data)
2273 struct city_dialog *pdialog;
2275 pdialog = (struct city_dialog *)client_data;
2277 if (pdialog->worklist_shell) {
2278 XtPopup(pdialog->worklist_shell, XtGrabNone);
2279 } else {
2280 pdialog->worklist_shell =
2281 popup_worklist(pdialog->pcity, NULL,
2282 pdialog->shell, (void *) pdialog, commit_city_worklist,
2283 cancel_city_worklist);
2287 /****************************************************************
2288 Commit the changes to the worklist for the city.
2289 *****************************************************************/
2290 void commit_city_worklist(struct worklist *pwl, void *data)
2292 struct city_dialog *pdialog = data;
2294 city_worklist_commit(pdialog->pcity, pwl);
2297 void cancel_city_worklist(void *data) {
2298 struct city_dialog *pdialog = (struct city_dialog *)data;
2299 pdialog->worklist_shell = NULL;
2302 /****************************************************************
2304 *****************************************************************/
2305 static void sell_callback_yes(Widget w, XtPointer client_data,
2306 XtPointer call_data)
2308 struct city_dialog *pdialog = client_data;
2310 city_sell_improvement(pdialog->pcity, pdialog->sell_id);
2312 destroy_message_dialog(w);
2316 /****************************************************************
2318 *****************************************************************/
2319 static void sell_callback_no(Widget w, XtPointer client_data,
2320 XtPointer call_data)
2322 destroy_message_dialog(w);
2326 /****************************************************************
2328 *****************************************************************/
2329 void sell_callback(Widget w, XtPointer client_data, XtPointer call_data)
2331 struct city_dialog *pdialog;
2332 XawListReturnStruct *ret;
2334 pdialog=(struct city_dialog *)client_data;
2336 ret=XawListShowCurrent(pdialog->improvement_list);
2338 if(ret->list_index!=XAW_LIST_NONE) {
2339 int n = 0;
2340 city_built_iterate(pdialog->pcity, pimprove) {
2341 if (n == ret->list_index) {
2342 char buf[512];
2343 int price;
2345 if (!can_city_sell_building(pdialog->pcity, pimprove)) {
2346 return;
2349 pdialog->sell_id = improvement_number(pimprove);
2350 price = impr_sell_gold(pimprove);
2351 fc_snprintf(buf, sizeof(buf), PL_("Sell %s for %d gold?",
2352 "Sell %s for %d gold?", price),
2353 city_improvement_name_translation(pdialog->pcity, pimprove),
2354 price);
2356 popup_message_dialog(pdialog->shell, "selldialog", buf,
2357 sell_callback_yes, pdialog, 0,
2358 sell_callback_no, pdialog, 0, NULL);
2360 return;
2362 n++;
2363 } city_built_iterate_end;
2367 /****************************************************************
2369 *****************************************************************/
2370 void close_city_dialog(struct city_dialog *pdialog)
2372 if (pdialog->worklist_shell)
2373 XtDestroyWidget(pdialog->worklist_shell);
2375 XtDestroyWidget(pdialog->shell);
2376 dialog_list_remove(dialog_list, pdialog);
2378 free(pdialog->citizen_labels);
2380 free(pdialog->support_unit_pixcomms);
2381 free(pdialog->present_unit_pixcomms);
2384 if(pdialog->is_modal)
2385 XtSetSensitive(toplevel, TRUE);
2387 free(pdialog);
2388 popdown_cma_dialog();
2391 /****************************************************************
2393 *****************************************************************/
2394 void citydlg_key_close(Widget w)
2396 citydlg_msg_close(XtParent(XtParent(w)));
2399 /****************************************************************
2401 *****************************************************************/
2402 void citydlg_msg_close(Widget w)
2404 dialog_list_iterate(dialog_list, pdialog) {
2405 if (pdialog->shell == w) {
2406 close_city_dialog(pdialog);
2407 return;
2409 } dialog_list_iterate_end;
2412 /****************************************************************
2414 *****************************************************************/
2415 void close_callback(Widget w, XtPointer client_data, XtPointer call_data)
2417 close_city_dialog((struct city_dialog *)client_data);
2421 /****************************************************************
2423 City Options dialog: (current only auto-attack options)
2425 Note, there can only be one such dialog at a time, because
2426 I'm lazy. That could be fixed, similar to way you can have
2427 multiple city dialogs.
2429 triggle = tri_toggle (three way toggle button)
2431 *****************************************************************/
2433 #define NUM_CITYOPT_TOGGLES 5
2435 Widget create_cityopt_dialog(const char *cityname);
2436 void cityopt_ok_command_callback(Widget w, XtPointer client_data,
2437 XtPointer call_data);
2438 void cityopt_cancel_command_callback(Widget w, XtPointer client_data,
2439 XtPointer call_data);
2440 void cityopt_newcit_triggle_callback(Widget w, XtPointer client_data,
2441 XtPointer call_data);
2443 char *newcitizen_labels[] = {
2444 N_("Workers"),
2445 N_("Scientists"),
2446 N_("Taxmen")
2449 static Widget cityopt_shell = 0;
2450 static Widget cityopt_triggle;
2451 static Widget cityopt_toggles[NUM_CITYOPT_TOGGLES];
2452 static int cityopt_city_id = 0;
2453 static int newcitizen_index;
2455 /****************************************************************
2457 *****************************************************************/
2458 void cityopt_callback(Widget w, XtPointer client_data,
2459 XtPointer call_data)
2461 struct city_dialog *pdialog = (struct city_dialog *)client_data;
2462 struct city *pcity = pdialog->pcity;
2463 int i;
2465 if (cityopt_shell) {
2466 XtDestroyWidget(cityopt_shell);
2469 cityopt_shell = create_cityopt_dialog(city_name_get(pcity));
2471 /* Doing this here makes the "No"'s centered consistently */
2472 for (i = 0; i < NUM_CITYOPT_TOGGLES; i++) {
2473 bool state = is_city_option_set(pcity, i);
2475 XtVaSetValues(cityopt_toggles[i], XtNstate, state,
2476 XtNlabel, state?_("Yes"):_("No"), NULL);
2479 if (is_city_option_set(pcity, CITYO_NEW_EINSTEIN)) {
2480 newcitizen_index = 1;
2481 } else if (is_city_option_set(pcity, CITYO_NEW_TAXMAN)) {
2482 newcitizen_index = 2;
2483 } else {
2484 newcitizen_index = 0;
2487 XtVaSetValues(cityopt_triggle, XtNstate, 1,
2488 XtNlabel, _(newcitizen_labels[newcitizen_index]),
2489 NULL);
2491 cityopt_city_id = pcity->id;
2493 xaw_set_relative_position(pdialog->shell, cityopt_shell, 15, 15);
2494 XtPopup(cityopt_shell, XtGrabNone);
2498 /**************************************************************************
2500 **************************************************************************/
2501 Widget create_cityopt_dialog(const char *cityname)
2503 Widget shell, form, label, ok, cancel;
2504 int i;
2506 shell = I_T(XtCreatePopupShell("cityoptpopup",
2507 transientShellWidgetClass,
2508 toplevel, NULL, 0));
2509 form = XtVaCreateManagedWidget("cityoptform",
2510 formWidgetClass,
2511 shell, NULL);
2512 label = XtVaCreateManagedWidget("cityoptlabel", labelWidgetClass,
2513 form, XtNlabel, cityname, NULL);
2516 I_L(XtVaCreateManagedWidget("cityoptnewcitlabel", labelWidgetClass,
2517 form, NULL));
2519 cityopt_triggle = XtVaCreateManagedWidget("cityoptnewcittriggle",
2520 toggleWidgetClass,
2521 form, NULL);
2523 /* NOTE: the ordering here is deliberately out of order;
2524 want toggles[] to be in enum city_options order, but
2525 want display in different order. --dwp
2526 - disband and workers options at top
2527 - helicopters (special case air) at bottom
2530 I_L(XtVaCreateManagedWidget("cityoptdisbandlabel", labelWidgetClass,
2531 form, NULL));
2533 cityopt_toggles[4] = XtVaCreateManagedWidget("cityoptdisbandtoggle",
2534 toggleWidgetClass,
2535 form, NULL);
2537 I_L(XtVaCreateManagedWidget("cityoptvlandlabel", labelWidgetClass,
2538 form, NULL));
2540 cityopt_toggles[0] = XtVaCreateManagedWidget("cityoptvlandtoggle",
2541 toggleWidgetClass,
2542 form, NULL);
2544 I_L(XtVaCreateManagedWidget("cityoptvsealabel", labelWidgetClass,
2545 form, NULL));
2547 cityopt_toggles[1] = XtVaCreateManagedWidget("cityoptvseatoggle",
2548 toggleWidgetClass,
2549 form, NULL);
2551 I_L(XtVaCreateManagedWidget("cityoptvairlabel", labelWidgetClass,
2552 form, NULL));
2554 cityopt_toggles[3] = XtVaCreateManagedWidget("cityoptvairtoggle",
2555 toggleWidgetClass,
2556 form, NULL);
2558 I_L(XtVaCreateManagedWidget("cityoptvhelilabel", labelWidgetClass,
2559 form, NULL));
2561 cityopt_toggles[2] = XtVaCreateManagedWidget("cityoptvhelitoggle",
2562 toggleWidgetClass,
2563 form, NULL);
2565 ok = I_L(XtVaCreateManagedWidget("cityoptokcommand",
2566 commandWidgetClass,
2567 form, NULL));
2569 cancel = I_L(XtVaCreateManagedWidget("cityoptcancelcommand",
2570 commandWidgetClass,
2571 form, NULL));
2573 XtAddCallback(ok, XtNcallback, cityopt_ok_command_callback,
2574 (XtPointer)shell);
2575 XtAddCallback(cancel, XtNcallback, cityopt_cancel_command_callback,
2576 (XtPointer)shell);
2577 for(i=0; i<NUM_CITYOPT_TOGGLES; i++) {
2578 XtAddCallback(cityopt_toggles[i], XtNcallback, toggle_callback, NULL);
2580 XtAddCallback(cityopt_triggle, XtNcallback,
2581 cityopt_newcit_triggle_callback, NULL);
2583 XtRealizeWidget(shell);
2585 xaw_horiz_center(label);
2586 return shell;
2589 /**************************************************************************
2591 **************************************************************************/
2592 void cityopt_cancel_command_callback(Widget w, XtPointer client_data,
2593 XtPointer call_data)
2595 XtDestroyWidget(cityopt_shell);
2596 cityopt_shell = 0;
2599 /**************************************************************************
2601 **************************************************************************/
2602 void cityopt_ok_command_callback(Widget w, XtPointer client_data,
2603 XtPointer call_data)
2605 struct city *pcity = game_city_by_number(cityopt_city_id);
2607 if (pcity) {
2608 /* int i; */
2609 bv_city_options new_options;
2610 Boolean b;
2612 fc_assert(CITYO_LAST == 3);
2614 BV_CLR_ALL(new_options);
2615 /* for(i=0; i<NUM_CITYOPT_TOGGLES; i++) {
2616 XtVaGetValues(cityopt_toggles[i], XtNstate, &b, NULL);
2617 if (b) new_options |= (1<<i);
2620 XtVaGetValues(cityopt_toggles[4], XtNstate, &b, NULL);
2621 if (b) {
2622 BV_SET(new_options, CITYO_DISBAND);
2624 if (newcitizen_index == 1) {
2625 BV_SET(new_options, CITYO_NEW_EINSTEIN);
2626 } else if (newcitizen_index == 2) {
2627 BV_SET(new_options, CITYO_NEW_TAXMAN);
2629 dsend_packet_city_options_req(&client.conn, cityopt_city_id,new_options);
2631 XtDestroyWidget(cityopt_shell);
2632 cityopt_shell = 0;
2635 /**************************************************************************
2636 Changes the label of the toggle widget to between newcitizen_labels
2637 and increments (mod 3) newcitizen_index.
2638 **************************************************************************/
2639 void cityopt_newcit_triggle_callback(Widget w, XtPointer client_data,
2640 XtPointer call_data)
2642 newcitizen_index++;
2643 if (newcitizen_index>=3) {
2644 newcitizen_index = 0;
2646 XtVaSetValues(cityopt_triggle, XtNstate, 1,
2647 XtNlabel, _(newcitizen_labels[newcitizen_index]),
2648 NULL);
2651 /**************************************************************************
2653 **************************************************************************/
2654 void popdown_cityopt_dialog(void)
2656 if(cityopt_shell) {
2657 XtDestroyWidget(cityopt_shell);
2658 cityopt_shell = 0;
2662 /****************************************************************
2663 The user clicked on the "CMA..." button in the citydialog.
2664 *****************************************************************/
2665 void cma_callback(Widget w, XtPointer client_data,
2666 XtPointer call_data)
2668 struct city_dialog *pdialog = (struct city_dialog *)client_data;
2669 popdown_cma_dialog();
2670 show_cma_dialog(pdialog->pcity, pdialog->shell);