1 /***********************************************************************
2  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ***********************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 
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>
34 
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"
43 
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"
54 
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"
63 
64 #include "cma_fec.h"
65 
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"
82 
83 #include "citydlg_common.h"
84 #include "citydlg.h"
85 
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
92 
93 struct city_dialog {
94   struct city *pcity;
95 
96   int num_citizens_shown;
97   int num_units_shown;
98 
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;
127 
128   Impr_type_id sell_id;
129 
130   int support_unit_base;
131   int present_unit_base;
132   char improvlist_names[B_LAST+1][64];
133   CONST_FOR_XAW_LIST_CHANGE char *improvlist_names_ptrs[B_LAST + 1];
134 
135   CONST_FOR_XAW_LIST_CHANGE 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;
139 
140   /*int is_modal;*/
141 };
142 
143 #define SPECLIST_TAG dialog
144 #define SPECLIST_TYPE struct city_dialog
145 #include "speclist.h"
146 
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
150 
151 static struct dialog_list *dialog_list = NULL;
152 static bool dialog_list_has_been_initialised = FALSE;
153 
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);
157 
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);
168 
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);
188 
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);
196 
197 /****************************************************************
198 ...
199 *****************************************************************/
get_contents_of_pollution(struct city_dialog * pdialog,char * retbuf,int n)200 static void get_contents_of_pollution(struct city_dialog *pdialog,
201 				      char *retbuf, int n)
202 {
203   struct city *pcity;
204   int pollution=0;
205   int corruption=0;
206   int waste=0;
207   int illness=0;
208   char buf[512];
209 
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);
222     }
223   }
224 
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);
230 }
231 
232 /****************************************************************
233 ...
234 *****************************************************************/
get_contents_of_storage(struct city_dialog * pdialog,char * retbuf,int n)235 static void get_contents_of_storage(struct city_dialog *pdialog,
236 				    char *retbuf, int n)
237 {
238   struct city *pcity;
239   int foodstock=0;
240   int foodbox=0;
241   int granaryturns=0;
242   char buf[512];
243 
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));
259     }
260   }
261 
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);
266 }
267 
268 /****************************************************************
269 ...
270 *****************************************************************/
get_contents_of_production(struct city_dialog * pdialog,char * retbuf,int n)271 static void get_contents_of_production(struct city_dialog *pdialog,
272 				       char *retbuf, int n)
273 {
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;
281 
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];
290   }
291 
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);
299 }
300 
301 /****************************************************************
302 ...
303 *****************************************************************/
get_contents_of_output(struct city_dialog * pdialog,char * retbuf,int n)304 static void get_contents_of_output(struct city_dialog *pdialog,
305 				   char *retbuf, int n)
306 {
307   struct city *pcity;
308   int goldtotal=0;
309   int goldsurplus=0;
310   int luxtotal=0;
311   int scitotal=0;
312 
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];
319   }
320 
321   fc_snprintf(retbuf, n,
322 	  _("Gold:  %3d (%+-4d)\n"
323 	    "Lux:   %3d\n"
324 	    "Sci:   %3d"),
325 	  goldtotal, goldsurplus,
326 	  luxtotal,
327 	  scitotal);
328 }
329 
330 /****************************************************************
331 ...
332 *****************************************************************/
get_contents_of_progress(struct city_dialog * pdialog,char * retbuf,int n)333 static void get_contents_of_progress(struct city_dialog *pdialog,
334 				     char *retbuf, int n)
335 {
336   get_city_dialog_production(pdialog ? pdialog->pcity : NULL, retbuf, n);
337 }
338 
339 /****************************************************************
340 ...
341 *****************************************************************/
get_contents_of_worklist(struct city_dialog * pdialog,char * retbuf,int n)342 static void get_contents_of_worklist(struct city_dialog *pdialog,
343 				     char *retbuf, int n)
344 {
345   struct city *pcity = pdialog ? pdialog->pcity : NULL;
346 
347   if (pcity && worklist_is_empty(&pcity->worklist)) {
348     fc_strlcpy(retbuf, _("(is empty)"), n);
349   } else {
350     fc_strlcpy(retbuf, _("(in prog.)"), n);
351   }
352 }
353 
354 /****************************************************************
355 ...
356 *****************************************************************/
get_city_dialog(struct city * pcity)357 struct city_dialog *get_city_dialog(struct city *pcity)
358 {
359   if (!dialog_list_has_been_initialised) {
360     dialog_list = dialog_list_new();
361     dialog_list_has_been_initialised = TRUE;
362   }
363 
364   dialog_list_iterate(dialog_list, pdialog) {
365     if (pdialog->pcity == pcity) {
366       return pdialog;
367     }
368   } dialog_list_iterate_end;
369 
370   return NULL;
371 }
372 
373 /****************************************************************
374 ...
375 *****************************************************************/
city_dialog_is_open(struct city * pcity)376 bool city_dialog_is_open(struct city *pcity)
377 {
378   return get_city_dialog(pcity) != NULL;
379 }
380 
381 /****************************************************************
382 ...
383 *****************************************************************/
real_city_dialog_refresh(struct city * pcity)384 void real_city_dialog_refresh(struct city *pcity)
385 {
386   struct city_dialog *pdialog;
387 
388   if((pdialog=get_city_dialog(pcity))) {
389     struct canvas store = {XtWindow(pdialog->map_canvas)};
390 
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);
402 
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);
413   }
414 
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);
431     }
432   }
433 }
434 
435 /**************************************************************************
436   Updates supported and present units views in city dialogs for given unit
437 **************************************************************************/
refresh_unit_city_dialogs(struct unit * punit)438 void refresh_unit_city_dialogs(struct unit *punit)
439 {
440   struct city *pcity_sup, *pcity_pre;
441   struct city_dialog *pdialog;
442 
443   pcity_sup = player_city_by_number(client_player(), punit->homecity);
444   pcity_pre=tile_city(unit_tile(punit));
445 
446   if(pcity_sup && (pdialog=get_city_dialog(pcity_sup)))
447     city_dialog_update_supported_units(pdialog, 0);
448 
449   if(pcity_pre && (pdialog=get_city_dialog(pcity_pre)))
450     city_dialog_update_present_units(pdialog, 0);
451 }
452 
453 /****************************************************************
454 popup the dialog 10% inside the main-window
455 *****************************************************************/
real_city_dialog_popup(struct city * pcity)456 void real_city_dialog_popup(struct city *pcity)
457 {
458   struct city_dialog *pdialog;
459 
460   if(!(pdialog=get_city_dialog(pcity)))
461     pdialog=create_city_dialog(pcity);
462 
463   xaw_set_relative_position(toplevel, pdialog->shell, 10, 10);
464   XtPopup(pdialog->shell, XtGrabNone);
465 }
466 
467 /****************************************************************
468 popdown the dialog
469 *****************************************************************/
popdown_city_dialog(struct city * pcity)470 void popdown_city_dialog(struct city *pcity)
471 {
472   struct city_dialog *pdialog;
473 
474   if((pdialog=get_city_dialog(pcity)))
475     close_city_dialog(pdialog);
476 }
477 
478 /****************************************************************
479 popdown all dialogs
480 *****************************************************************/
popdown_all_city_dialogs(void)481 void popdown_all_city_dialogs(void)
482 {
483   if(!dialog_list_has_been_initialised) {
484     return;
485   }
486   while (dialog_list_size(dialog_list) > 0) {
487     close_city_dialog(dialog_list_get(dialog_list, 0));
488   }
489   popdown_cityopt_dialog();
490   popdown_cma_dialog();
491 }
492 
493 
494 /****************************************************************
495 ...
496 *****************************************************************/
city_map_canvas_expose(Widget w,XEvent * event,Region exposed,void * client_data)497 static void city_map_canvas_expose(Widget w, XEvent *event, Region exposed,
498 				   void *client_data)
499 {
500   struct city_dialog *pdialog = client_data;
501   struct canvas store = {XtWindow(pdialog->map_canvas)};
502 
503   city_dialog_redraw_map(pdialog->pcity, &store);
504 }
505 
506 
507 /****************************************************************
508 ...
509 *****************************************************************/
510 
511 #define LAYOUT_DEBUG 0
512 
create_city_dialog(struct city * pcity)513 struct city_dialog *create_city_dialog(struct city *pcity)
514 {
515   char *dummy_improvement_list[]={
516     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
517     "2",
518     "3",
519     "4",
520     "5",
521     "6",
522     "7",
523     "8",
524     "9",
525     0
526   };
527 
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;
540 
541   if (tileset_tile_height(tileset) < 45) {
542     dummy_improvement_list[5] = 0;
543   }
544 
545   if (gui_options.concise_city_production) {
546     dummy_improvement_list[0] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
547   }
548 
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;
554 
555   pdialog->shell=
556     XtVaCreatePopupShell(city_name_get(pcity),
557                          topLevelShellWidgetClass,
558                          toplevel,
559                          XtNallowShellResize, True,
560                          NULL);
561 
562   pdialog->main_form=
563     XtVaCreateManagedWidget("citymainform",
564 			    formWidgetClass,
565 			    pdialog->shell,
566 			    NULL);
567 
568   pdialog->cityname_label=
569     XtVaCreateManagedWidget("citynamelabel",
570 			    labelWidgetClass,
571 			    pdialog->main_form,
572 			    NULL);
573 
574 
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);
584 
585 
586   pdialog->sub_form=
587     XtVaCreateManagedWidget("citysubform",
588 			    formWidgetClass,
589 			    pdialog->main_form,
590 			    XtNfromVert,
591 			    (XtArgVal)first_citizen,
592 			    NULL);
593 
594 
595   pdialog->left_form=
596     XtVaCreateManagedWidget("cityleftform",
597 			    formWidgetClass,
598 			    pdialog->sub_form,
599 			    NULL);
600 
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);
608 
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);
618 
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);
628 
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);
638 
639 
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);
650 
651 
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);
663 
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);
675 
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));
685 
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));
695 
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);
705 
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);
716 
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));
726 
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));
736 
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);
748 
749 
750   pdialog->support_unit_label=
751     I_L(XtVaCreateManagedWidget("supportunitlabel",
752 			    labelWidgetClass,
753 			    pdialog->main_form,
754 			    XtNfromVert,
755 			    pdialog->sub_form,
756 			    NULL));
757 
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);
766 
767   pdialog->present_unit_label=
768     I_L(XtVaCreateManagedWidget("presentunitlabel",
769 			    labelWidgetClass,
770 			    pdialog->main_form,
771 			    XtNfromVert,
772 			    first_support,
773 			    NULL));
774 
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);
783 
784 
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);
795 
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);
806 
807 
808   pdialog->close_command=
809     I_L(XtVaCreateManagedWidget("cityclosecommand",
810 			    commandWidgetClass,
811 			    pdialog->main_form,
812 			    XtNfromVert, first_present,
813 			    NULL));
814 
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));
822 
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));
830 
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));
838 
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));
846 
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));
854 
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));
862 
863 
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
898     (
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"
904      ,
905      widthTotal,
906      widthCitizen, borderCitizen, internalCitizen, spaceCitizen,
907      widthUnit, borderUnit, internalUnit, spaceUnit,
908      widthNext, borderNext, internalNext, spaceNext,
909      widthPrev, borderPrev, internalPrev, spacePrev
910     );
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;
921     }
922 #if LAYOUT_DEBUG >= 2
923     printf
924     (
925      "C: wT iW nC: %d %d %d\n"
926      ,
927      widthTotal,
928      itemWidth,
929      pdialog->num_citizens_shown
930     );
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;
946     }
947 #if LAYOUT_DEBUG >= 2
948     printf
949     (
950      "U: wT iW nU: %d %d %d\n"
951      ,
952      widthTotal,
953      itemWidth,
954      pdialog->num_units_shown
955     );
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;
963     }
964   }
965 #if LAYOUT_DEBUG >= 1
966     printf
967     (
968      "nC nU: %d %d\n"
969      ,
970      pdialog->num_citizens_shown, pdialog->num_units_shown
971     );
972 #endif
973 
974   pdialog->citizen_labels=
975     fc_malloc(pdialog->num_citizens_shown * sizeof(Widget));
976 
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));
981 
982 
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);
995 
996 
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);
1009   }
1010 
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);
1020 
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);
1033   }
1034 
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);
1044 
1045   /* FIXME: this ignores the mask. */
1046   XtVaSetValues(pdialog->shell, XtNiconPixmap,
1047 		get_icon_sprite(tileset, ICON_CITYDLG), NULL);
1048 
1049 
1050   XtAddCallback(pdialog->sell_command, XtNcallback, sell_callback,
1051 		(XtPointer)pdialog);
1052 
1053   XtAddCallback(pdialog->buy_command, XtNcallback, buy_callback,
1054 		(XtPointer)pdialog);
1055 
1056   XtAddCallback(pdialog->change_command, XtNcallback, change_callback,
1057 		(XtPointer)pdialog);
1058 
1059   XtAddCallback(pdialog->worklist_command, XtNcallback, worklist_callback,
1060 		(XtPointer)pdialog);
1061 
1062   XtAddCallback(pdialog->close_command, XtNcallback, close_callback,
1063 		(XtPointer)pdialog);
1064 
1065   XtAddCallback(pdialog->rename_command, XtNcallback, rename_callback,
1066 		(XtPointer)pdialog);
1067 
1068   XtAddCallback(pdialog->trade_command, XtNcallback, trade_callback,
1069 		(XtPointer)pdialog);
1070 
1071   XtAddCallback(pdialog->activate_command, XtNcallback, activate_callback,
1072 		(XtPointer)pdialog);
1073 
1074   XtAddCallback(pdialog->show_units_command, XtNcallback, show_units_callback,
1075 		(XtPointer)pdialog);
1076 
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);
1085 
1086   XtAddCallback(pdialog->cityopt_command, XtNcallback, cityopt_callback,
1087 		(XtPointer)pdialog);
1088 
1089   XtAddCallback(pdialog->cma_command, XtNcallback, cma_callback,
1090                 (XtPointer)pdialog);
1091 
1092   dialog_list_prepend(dialog_list, pdialog);
1093 
1094   for(i=0; i<B_LAST+1; i++)
1095     pdialog->improvlist_names_ptrs[i]=0;
1096 
1097   XtRealizeWidget(pdialog->shell);
1098 
1099   real_city_dialog_refresh(pdialog->pcity);
1100 /*
1101   if(make_modal)
1102     XtSetSensitive(toplevel, FALSE);
1103 
1104   pdialog->is_modal=make_modal;
1105 */
1106 
1107   XSetWMProtocols(display, XtWindow(pdialog->shell), &wm_delete_window, 1);
1108   XtOverrideTranslations(pdialog->shell,
1109     XtParseTranslationTable ("<Message>WM_PROTOCOLS: msg-close-city()"));
1110 
1111   XtSetKeyboardFocus(pdialog->shell, pdialog->close_command);
1112 
1113 
1114   return pdialog;
1115 }
1116 
1117 /****************************************************************
1118 ...
1119 *****************************************************************/
activate_callback(Widget w,XtPointer client_data,XtPointer call_data)1120 void activate_callback(Widget w, XtPointer client_data,
1121 		       XtPointer call_data)
1122 {
1123   struct city_dialog *pdialog = (struct city_dialog *)client_data;
1124 
1125   activate_all_units(pdialog->pcity->tile);
1126 }
1127 
1128 
1129 /****************************************************************
1130 ...
1131 *****************************************************************/
show_units_callback(Widget w,XtPointer client_data,XtPointer call_data)1132 void show_units_callback(Widget w, XtPointer client_data,
1133                         XtPointer call_data)
1134 {
1135   struct city_dialog *pdialog = (struct city_dialog *)client_data;
1136   struct tile *ptile = pdialog->pcity->tile;
1137 
1138   if( unit_list_size(ptile->units) )
1139     unit_select_dialog_popup(ptile);
1140 }
1141 
1142 
1143 /****************************************************************
1144 ...
1145 *****************************************************************/
units_next_prev_callback(Widget w,XtPointer client_data,XtPointer call_data)1146 void units_next_prev_callback(Widget w, XtPointer client_data,
1147 			      XtPointer call_data)
1148 {
1149   struct city_dialog *pdialog = (struct city_dialog *)client_data;
1150 
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);
1163   }
1164 }
1165 
1166 
1167 #ifdef UNUSED
1168 /****************************************************************
1169 ...
1170 *****************************************************************/
present_units_ok_callback(Widget w,XtPointer client_data,XtPointer call_data)1171 static void present_units_ok_callback(Widget w, XtPointer client_data,
1172 				      XtPointer call_data)
1173 {
1174   destroy_message_dialog(w);
1175 }
1176 #endif
1177 
1178 
1179 /****************************************************************
1180 ...
1181 *****************************************************************/
present_units_activate_callback(Widget w,XtPointer client_data,XtPointer call_data)1182 static void present_units_activate_callback(Widget w, XtPointer client_data,
1183 					    XtPointer call_data)
1184 {
1185   struct unit *punit =
1186     player_unit_by_number(client_player(), (size_t) client_data);
1187 
1188   if (NULL != punit) {
1189     struct city *pcity = tile_city(unit_tile(punit));
1190 
1191     unit_focus_set(punit);
1192     if (NULL != pcity) {
1193       struct city_dialog *pdialog = get_city_dialog(pcity);
1194 
1195       if (NULL != pdialog) {
1196 	city_dialog_update_present_units(pdialog, 0);
1197       }
1198     }
1199   }
1200 
1201   destroy_message_dialog(w);
1202 }
1203 
1204 
1205 /****************************************************************
1206 ...
1207 *****************************************************************/
supported_units_activate_callback(Widget w,XtPointer client_data,XtPointer call_data)1208 static void supported_units_activate_callback(Widget w, XtPointer client_data,
1209 					      XtPointer call_data)
1210 {
1211   struct unit *punit =
1212     player_unit_by_number(client_player(), (size_t) client_data);
1213 
1214   if (NULL != punit) {
1215     struct city *pcity = tile_city(unit_tile(punit));
1216 
1217     unit_focus_set(punit);
1218     if (NULL != pcity) {
1219       struct city_dialog *pdialog = get_city_dialog(pcity);
1220 
1221       if (NULL != pdialog) {
1222 	city_dialog_update_supported_units(pdialog, 0);
1223       }
1224     }
1225   }
1226 
1227   destroy_message_dialog(w);
1228 }
1229 
1230 
1231 /****************************************************************
1232 ...
1233 *****************************************************************/
present_units_activate_close_callback(Widget w,XtPointer client_data,XtPointer call_data)1234 static void present_units_activate_close_callback(Widget w,
1235 						  XtPointer client_data,
1236 						  XtPointer call_data)
1237 {
1238   struct unit *punit =
1239     player_unit_by_number(client_player(), (size_t) client_data);
1240 
1241   destroy_message_dialog(w);
1242 
1243   if (NULL != punit) {
1244     struct city *pcity = tile_city(unit_tile(punit));
1245 
1246     unit_focus_set(punit);
1247     if (NULL != pcity) {
1248       struct city_dialog *pdialog = get_city_dialog(pcity);
1249 
1250       if (NULL != pdialog) {
1251 	close_city_dialog(pdialog);
1252       }
1253     }
1254   }
1255 }
1256 
1257 /****************************************************************
1258 ...
1259 *****************************************************************/
supported_units_activate_close_callback(Widget w,XtPointer client_data,XtPointer call_data)1260 static void supported_units_activate_close_callback(Widget w,
1261 						    XtPointer client_data,
1262 						    XtPointer call_data)
1263 {
1264   struct unit *punit =
1265     player_unit_by_number(client_player(), (size_t) client_data);
1266 
1267   destroy_message_dialog(w);
1268 
1269   if (NULL != punit) {
1270     struct city *pcity =
1271       player_city_by_number(client_player(), punit->homecity);
1272 
1273     unit_focus_set(punit);
1274     if (NULL != pcity) {
1275       struct city_dialog *pdialog = get_city_dialog(pcity);
1276 
1277       if (NULL != pdialog) {
1278 	close_city_dialog(pdialog);
1279       }
1280     }
1281   }
1282 }
1283 
1284 
1285 /****************************************************************
1286 ...
1287 *****************************************************************/
present_units_sentry_callback(Widget w,XtPointer client_data,XtPointer call_data)1288 static void present_units_sentry_callback(Widget w, XtPointer client_data,
1289 					   XtPointer call_data)
1290 {
1291   struct unit *punit =
1292     player_unit_by_number(client_player(), (size_t) client_data);
1293 
1294   if (NULL != punit) {
1295     request_unit_sentry(punit);
1296   }
1297 
1298   destroy_message_dialog(w);
1299 }
1300 
1301 
1302 /****************************************************************
1303 ...
1304 *****************************************************************/
present_units_fortify_callback(Widget w,XtPointer client_data,XtPointer call_data)1305 static void present_units_fortify_callback(Widget w, XtPointer client_data,
1306 					   XtPointer call_data)
1307 {
1308   struct unit *punit =
1309     player_unit_by_number(client_player(), (size_t) client_data);
1310 
1311   if (NULL != punit) {
1312     request_unit_fortify(punit);
1313   }
1314 
1315   destroy_message_dialog(w);
1316 }
1317 
1318 
1319 /****************************************************************
1320 ...
1321 *****************************************************************/
present_units_homecity_callback(Widget w,XtPointer client_data,XtPointer call_data)1322 static void present_units_homecity_callback(Widget w, XtPointer client_data,
1323 					    XtPointer call_data)
1324 {
1325   struct unit *punit =
1326     player_unit_by_number(client_player(), (size_t) client_data);
1327 
1328   if (NULL != punit) {
1329     request_unit_change_homecity(punit);
1330   }
1331 
1332   destroy_message_dialog(w);
1333 }
1334 
1335 
1336 /****************************************************************
1337 ...
1338 *****************************************************************/
present_units_cancel_callback(Widget w,XtPointer client_data,XtPointer call_data)1339 static void present_units_cancel_callback(Widget w, XtPointer client_data,
1340 					  XtPointer call_data)
1341 {
1342   destroy_message_dialog(w);
1343 }
1344 
1345 
1346 /****************************************************************
1347 ...
1348 *****************************************************************/
present_units_callback(Widget w,XtPointer client_data,XtPointer call_data)1349 void present_units_callback(Widget w, XtPointer client_data,
1350 			    XtPointer call_data)
1351 {
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);
1358 
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))) {
1365 
1366     if(e->type==ButtonRelease && e->xbutton.button==Button2)  {
1367       unit_focus_set(punit);
1368       close_city_dialog(pdialog);
1369       return;
1370     }
1371     if(e->type==ButtonRelease && e->xbutton.button==Button3)  {
1372       unit_focus_set(punit);
1373       return;
1374     }
1375 
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);
1388 
1389     if (punit->activity == ACTIVITY_SENTRY
1390 	|| !can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
1391       XtSetSensitive(XtNameToWidget(wd, "*button2"), FALSE);
1392     }
1393     if (punit->activity == ACTIVITY_FORTIFYING
1394 	|| !can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
1395       XtSetSensitive(XtNameToWidget(wd, "*button3"), FALSE);
1396     }
1397     if (unit_has_type_flag(punit, UTYF_UNDISBANDABLE)) {
1398       XtSetSensitive(XtNameToWidget(wd, "*button4"), FALSE);
1399     }
1400     if (punit->homecity == pcity->id) {
1401       XtSetSensitive(XtNameToWidget(wd, "*button5"), FALSE);
1402     }
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);
1407     }
1408   }
1409 }
1410 
1411 /****************************************************************
1412 ...
1413 *****************************************************************/
rename_city_callback(Widget w,XtPointer client_data,XtPointer call_data)1414 static void rename_city_callback(Widget w, XtPointer client_data,
1415 				 XtPointer call_data)
1416 {
1417   struct city_dialog *pdialog = client_data;
1418 
1419   if (pdialog) {
1420     city_rename(pdialog->pcity, input_dialog_get_input(w));
1421   }
1422   input_dialog_destroy(w);
1423 }
1424 
1425 
1426 
1427 
1428 
1429 /****************************************************************
1430 ...
1431 *****************************************************************/
rename_callback(Widget w,XtPointer client_data,XtPointer call_data)1432 void rename_callback(Widget w, XtPointer client_data, XtPointer call_data)
1433 {
1434   struct city_dialog *pdialog;
1435 
1436   pdialog=(struct city_dialog *)client_data;
1437 
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);
1444 }
1445 
1446 /****************************************************************
1447 ...
1448 *****************************************************************/
trade_message_dialog_callback(Widget w,XtPointer client_data,XtPointer call_data)1449 static void trade_message_dialog_callback(Widget w, XtPointer client_data,
1450 					  XtPointer call_data)
1451 {
1452   destroy_message_dialog(w);
1453 }
1454 
1455 /****************************************************************
1456 ...
1457 *****************************************************************/
trade_callback(Widget w,XtPointer client_data,XtPointer call_data)1458 void trade_callback(Widget w, XtPointer client_data, XtPointer call_data)
1459 {
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;
1465 
1466   pdialog = (struct city_dialog *)client_data;
1467 
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);
1472 
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);
1486       }
1487     }
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);
1492   }
1493 
1494   popup_message_dialog(pdialog->shell,
1495 		       "citytradedialog",
1496 		       buf,
1497 		       trade_message_dialog_callback, 0, 0,
1498 		       NULL);
1499 }
1500 
1501 
1502 /****************************************************************
1503 ...
1504 *****************************************************************/
city_dialog_update_pollution(struct city_dialog * pdialog)1505 void city_dialog_update_pollution(struct city_dialog *pdialog)
1506 {
1507   char buf[512];
1508 
1509   get_contents_of_pollution(pdialog, buf, sizeof(buf));
1510   xaw_set_label(pdialog->pollution_label, buf);
1511 }
1512 
1513 /****************************************************************
1514 ...
1515 *****************************************************************/
city_dialog_update_storage(struct city_dialog * pdialog)1516 void city_dialog_update_storage(struct city_dialog *pdialog)
1517 {
1518   char buf[512];
1519 
1520   get_contents_of_storage(pdialog, buf, sizeof(buf));
1521   xaw_set_label(pdialog->storage_label, buf);
1522 }
1523 
1524 /****************************************************************
1525 ...
1526 *****************************************************************/
city_dialog_update_building(struct city_dialog * pdialog)1527 void city_dialog_update_building(struct city_dialog *pdialog)
1528 {
1529   char buf[32];
1530   struct city *pcity=pdialog->pcity;
1531 
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);
1538 
1539   xaw_set_label(pdialog->building_label,
1540 		city_production_name_translation(pcity));
1541 
1542   get_contents_of_progress(pdialog, buf, sizeof(buf));
1543   xaw_set_label(pdialog->progress_label, buf);
1544 
1545   get_contents_of_worklist(pdialog, buf, sizeof(buf));
1546   xaw_set_label(pdialog->worklist_label, buf);
1547 }
1548 
1549 /****************************************************************
1550 ...
1551 *****************************************************************/
city_dialog_update_production(struct city_dialog * pdialog)1552 void city_dialog_update_production(struct city_dialog *pdialog)
1553 {
1554   char buf[512];
1555 
1556   get_contents_of_production(pdialog, buf, sizeof(buf));
1557   xaw_set_label(pdialog->production_label, buf);
1558 }
1559 
1560 /****************************************************************
1561 ...
1562 *****************************************************************/
city_dialog_update_output(struct city_dialog * pdialog)1563 void city_dialog_update_output(struct city_dialog *pdialog)
1564 {
1565   char buf[512];
1566 
1567   get_contents_of_output(pdialog, buf, sizeof(buf));
1568   xaw_set_label(pdialog->output_label, buf);
1569 }
1570 
1571 /****************************************************************************
1572   Handle the callback when a citizen sprite widget is clicked.
1573 ****************************************************************************/
citizen_callback(Widget w,XtPointer client_data,XtPointer call_data)1574 static void citizen_callback(Widget w, XtPointer client_data,
1575 			     XtPointer call_data)
1576 {
1577   struct city_dialog *pdialog = client_data;
1578   int i;
1579 
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;
1584     }
1585   }
1586   fc_assert(i < city_size_get(pdialog->pcity));
1587 
1588   city_rotate_specialist(pdialog->pcity, i);
1589 }
1590 
1591 /****************************************************************
1592 ...
1593 *****************************************************************/
city_dialog_update_citizens(struct city_dialog * pdialog)1594 void city_dialog_update_citizens(struct city_dialog *pdialog)
1595 {
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);
1600 
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));
1604 
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);
1610   }
1611 
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;
1620   }
1621 
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);
1626   }
1627 }
1628 
1629 /****************************************************************
1630 ...
1631 *****************************************************************/
support_units_callback(Widget w,XtPointer client_data,XtPointer call_data)1632 static void support_units_callback(Widget w, XtPointer client_data,
1633 				   XtPointer call_data)
1634 {
1635   Widget wd;
1636   XEvent *e = (XEvent*)call_data;
1637   struct unit *punit =
1638     player_unit_by_number(client_player(), (size_t) client_data);
1639 
1640   if (NULL != punit) {
1641     struct city *pcity = game_city_by_number(punit->homecity);
1642 
1643     if (NULL != pcity) {
1644       struct city_dialog *pdialog = get_city_dialog(pcity);
1645 
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;
1651 	}
1652 	if(e->type==ButtonRelease && e->xbutton.button==Button3)  {
1653 	  unit_focus_set(punit);
1654 	  return;
1655 	}
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);
1667         }
1668       }
1669     }
1670   }
1671 }
1672 
1673 
1674 /****************************************************************
1675 ...
1676 *****************************************************************/
units_scroll_maintenance(int nunits,int nshow,int * base,Widget next,Widget prev)1677 static int units_scroll_maintenance(int nunits, int nshow, int *base,
1678 				    Widget next, Widget prev)
1679 {
1680   int adj_base=FALSE;
1681   int nextra;
1682 
1683   nextra=nunits-nshow;
1684   if (nextra<0) nextra=0;
1685 
1686   if (*base>nextra) {
1687     *base=nextra;
1688     adj_base=TRUE;
1689   }
1690   if (*base<0) {
1691     *base=0;
1692     adj_base=TRUE;
1693   }
1694 
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);
1703   }
1704 
1705   return (adj_base);
1706 }
1707 
1708 /****************************************************************
1709 ...
1710 *****************************************************************/
city_dialog_update_supported_units(struct city_dialog * pdialog,int unitid)1711 void city_dialog_update_supported_units(struct city_dialog *pdialog,
1712 					int unitid)
1713 {
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);
1718 
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;
1724   }
1725 
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);
1731 
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);
1737 
1738     if (j++ < pdialog->support_unit_base) {
1739       continue;
1740     }
1741     if (i >= pdialog->num_units_shown) {
1742       break;
1743     }
1744 
1745     pixcomm=pdialog->support_unit_pixcomms[i];
1746     store.pixmap = XawPixcommPixmap(pixcomm);
1747 
1748     if(!adj_base && unitid && punit->id!=unitid)
1749       continue;
1750 
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);
1756 
1757     xaw_expose_now(pixcomm);
1758 
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;
1765 
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);
1770   }
1771 }
1772 
1773 /****************************************************************
1774 ...
1775 *****************************************************************/
city_dialog_update_present_units(struct city_dialog * pdialog,int unitid)1776 void city_dialog_update_present_units(struct city_dialog *pdialog, int unitid)
1777 {
1778   struct unit_list *plist;
1779   int i, j, adj_base;
1780   Widget pixcomm;
1781 
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;
1787   }
1788 
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);
1794 
1795   i = 0; /* number of displayed units */
1796   j = 0; /* index into list */
1797   unit_list_iterate(plist, punit) {
1798     struct canvas store;
1799 
1800     if (j++ < pdialog->present_unit_base) {
1801       continue;
1802     }
1803     if (i >= pdialog->num_units_shown) {
1804       break;
1805     }
1806 
1807     pixcomm=pdialog->present_unit_pixcomms[i];
1808     store.pixmap = XawPixcommPixmap(pixcomm);
1809 
1810     if(!adj_base && unitid && punit->id!=unitid)
1811       continue;
1812 
1813     XawPixcommClear(pixcomm); /* STG */
1814     put_unit(punit, &store, 1.0, 0, 0);
1815 
1816     xaw_expose_now(pixcomm);
1817 
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;
1824 
1825   for(; i<pdialog->num_units_shown; i++) {
1826     XawPixcommClear(pdialog->present_unit_pixcomms[i]);
1827     XtSetSensitive(pdialog->present_unit_pixcomms[i], FALSE);
1828   }
1829 }
1830 
1831 
1832 /****************************************************************
1833 ...
1834 *****************************************************************/
city_dialog_update_title(struct city_dialog * pdialog)1835 void city_dialog_update_title(struct city_dialog *pdialog)
1836 {
1837   char buf[512];
1838   String now;
1839 
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));
1844 
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);
1851   }
1852 }
1853 
1854 /****************************************************************
1855 ...
1856 *****************************************************************/
city_dialog_update_improvement_list(struct city_dialog * pdialog)1857 void city_dialog_update_improvement_list(struct city_dialog *pdialog)
1858 {
1859   int n = 0, flag = 0;
1860 
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;
1871 
1872   if(pdialog->improvlist_names_ptrs[n]!=0) {
1873     pdialog->improvlist_names_ptrs[n]=0;
1874     flag=1;
1875   }
1876 
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);
1884   }
1885 }
1886 
1887 
1888 /**************************************************************************
1889 ...
1890 **************************************************************************/
citydlg_btn_select_citymap(Widget w,XEvent * event)1891 void citydlg_btn_select_citymap(Widget w, XEvent *event)
1892 {
1893   XButtonEvent *ev=&event->xbutton;
1894   struct city *pcity = NULL;
1895 
1896   dialog_list_iterate(dialog_list, pdialog) {
1897     if (pdialog->map_canvas == w) {
1898       pcity = pdialog->pcity;
1899       break;
1900     }
1901   } dialog_list_iterate_end;
1902 
1903   if (pcity) {
1904     if (!cma_is_city_under_agent(pcity, NULL)) {
1905       int xtile, ytile;
1906 
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);
1910       }
1911     }
1912   }
1913 }
1914 
1915 /****************************************************************
1916 ...
1917 *****************************************************************/
buy_callback_yes(Widget w,XtPointer client_data,XtPointer call_data)1918 static void buy_callback_yes(Widget w, XtPointer client_data,
1919 			     XtPointer call_data)
1920 {
1921   struct city_dialog *pdialog = client_data;
1922 
1923   city_buy_production(pdialog->pcity);
1924 
1925   destroy_message_dialog(w);
1926 }
1927 
1928 
1929 /****************************************************************
1930 ...
1931 *****************************************************************/
buy_callback_no(Widget w,XtPointer client_data,XtPointer call_data)1932 static void buy_callback_no(Widget w, XtPointer client_data,
1933 			    XtPointer call_data)
1934 {
1935   destroy_message_dialog(w);
1936 }
1937 
1938 
1939 /****************************************************************
1940 ...
1941 *****************************************************************/
buy_callback(Widget w,XtPointer client_data,XtPointer call_data)1942 void buy_callback(Widget w, XtPointer client_data, XtPointer call_data)
1943 {
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);
1948 
1949   if (!can_client_issue_orders()) {
1950     return;
1951   }
1952 
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);
1957 
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);
1968   }
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);
1978   }
1979 
1980 }
1981 
1982 
1983 /****************************************************************
1984 ...
1985 *****************************************************************/
unitupgrade_callback_yes(Widget w,XtPointer client_data,XtPointer call_data)1986 void unitupgrade_callback_yes(Widget w, XtPointer client_data, XtPointer call_data)
1987 {
1988   struct unit *punit =
1989     player_unit_by_number(client_player(), (size_t)client_data);
1990 
1991   /* Is it right place for breaking? -ev */
1992   if (!can_client_issue_orders()) {
1993     return;
1994   }
1995 
1996   if (NULL != punit) {
1997     request_unit_upgrade(punit);
1998   }
1999 
2000   destroy_message_dialog(w);
2001 }
2002 
2003 
2004 /****************************************************************
2005 ...
2006 *****************************************************************/
unitupgrade_callback_no(Widget w,XtPointer client_data,XtPointer call_data)2007 void unitupgrade_callback_no(Widget w, XtPointer client_data, XtPointer call_data)
2008 {
2009   destroy_message_dialog(w);
2010 }
2011 
2012 
2013 /****************************************************************
2014 ...
2015 *****************************************************************/
upgrade_callback(Widget w,XtPointer client_data,XtPointer call_data)2016 void upgrade_callback(Widget w, XtPointer client_data, XtPointer call_data)
2017 {
2018   char buf[512];
2019   struct unit *punit = player_unit_by_number(client_player(),
2020                                              (size_t) client_data);
2021 
2022   if (!punit) {
2023     return;
2024   }
2025 
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);
2035   }
2036 
2037   destroy_message_dialog(w);
2038 }
2039 
2040 
2041 /****************************************************************
2042 ...
2043 *****************************************************************/
disband_callback(Widget w,XtPointer client_data,XtPointer call_data)2044 void disband_callback(Widget w, XtPointer client_data, XtPointer call_data)
2045 {
2046   struct unit *punit = player_unit_by_number(client_player(),
2047                                              (size_t) client_data);
2048   struct unit_list *punits;
2049 
2050   if (!punit) {
2051     return;
2052   }
2053 
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);
2059 }
2060 
2061 
2062 /****************************************************************
2063   Production change callback
2064 *****************************************************************/
change_to_callback(Widget w,XtPointer client_data,XtPointer call_data)2065 static void change_to_callback(Widget w, XtPointer client_data,
2066                                XtPointer call_data)
2067 {
2068   struct city_dialog *pdialog;
2069   XawListReturnStruct *ret;
2070 
2071   pdialog = (struct city_dialog *)client_data;
2072 
2073   ret = XawListShowCurrent(pdialog->change_list);
2074 
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]);
2080 
2081     city_change_production(pdialog->pcity, &target);
2082   }
2083 
2084   XtDestroyWidget(XtParent(XtParent(w)));
2085   XtSetSensitive(pdialog->shell, TRUE);
2086 }
2087 
2088 /****************************************************************
2089 ...
2090 *****************************************************************/
change_no_callback(Widget w,XtPointer client_data,XtPointer call_data)2091 static void change_no_callback(Widget w, XtPointer client_data,
2092 			       XtPointer call_data)
2093 {
2094   struct city_dialog *pdialog;
2095 
2096   pdialog=(struct city_dialog *)client_data;
2097 
2098   XtDestroyWidget(XtParent(XtParent(w)));
2099   XtSetSensitive(pdialog->shell, TRUE);
2100 }
2101 
2102 /****************************************************************
2103 ...
2104 *****************************************************************/
change_help_callback(Widget w,XtPointer client_data,XtPointer call_data)2105 static void change_help_callback(Widget w, XtPointer client_data,
2106 				 XtPointer call_data)
2107 {
2108   struct city_dialog *pdialog;
2109   XawListReturnStruct *ret;
2110 
2111   pdialog=(struct city_dialog *)client_data;
2112 
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);
2117 
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);
2124     }
2125   }
2126   else
2127     popup_help_dialog_string(HELP_IMPROVEMENTS_ITEM);
2128 }
2129 
2130 
2131 /****************************************************************
2132 ...
2133 *****************************************************************/
change_callback(Widget w,XtPointer client_data,XtPointer call_data)2134 void change_callback(Widget w, XtPointer client_data, XtPointer call_data)
2135 {
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",
2152     0
2153   };
2154 
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;
2161 
2162   pdialog=(struct city_dialog *)client_data;
2163 
2164   I_T(cshell=XtCreatePopupShell("changedialog", transientShellWidgetClass,
2165 				pdialog->shell, NULL, 0));
2166 
2167   cform=XtVaCreateManagedWidget("dform", formWidgetClass, cshell, NULL);
2168 
2169   I_L(clabel=XtVaCreateManagedWidget("dlabel", labelWidgetClass, cform,
2170 				     NULL));
2171 
2172   cview=XtVaCreateManagedWidget("dview", viewportWidgetClass,
2173 				cform,
2174 				XtNfromVert,
2175 				clabel,
2176 				NULL);
2177 
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);
2186 
2187 
2188   button_change = I_L(XtVaCreateManagedWidget("buttonchange",
2189 					commandWidgetClass,
2190 					cform,
2191 					XtNfromVert,
2192 					cview,
2193 					NULL));
2194 
2195   button_cancel = I_L(XtVaCreateManagedWidget("buttoncancel",
2196 				    commandWidgetClass,
2197 				    cform,
2198 				    XtNfromVert,
2199 				    cview,
2200 				    XtNfromHoriz,
2201 				    button_change,
2202 				    NULL));
2203 
2204   button_help = I_L(XtVaCreateManagedWidget("buttonhelp",
2205 				    commandWidgetClass,
2206 				    cform,
2207 				    XtNfromVert,
2208 				    cview,
2209 				    XtNfromHoriz,
2210 				    button_cancel,
2211 				    NULL));
2212 
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);
2219 
2220 
2221 
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);
2226 
2227   XtPopup(cshell, XtGrabNone);
2228 
2229   XtSetSensitive(pdialog->shell, FALSE);
2230 
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);
2241     }
2242   } improvement_iterate_end;
2243 
2244   pdialog->change_list_num_improvements = n;
2245 
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);
2255     }
2256   } unit_type_iterate_end;
2257 
2258   pdialog->change_list_names_ptrs[n] = 0;
2259 
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);
2265 }
2266 
2267 
2268 /****************************************************************
2269   Display the city's worklist.
2270 *****************************************************************/
worklist_callback(Widget w,XtPointer client_data,XtPointer call_data)2271 void worklist_callback(Widget w, XtPointer client_data, XtPointer call_data)
2272 {
2273   struct city_dialog *pdialog;
2274 
2275   pdialog = (struct city_dialog *)client_data;
2276 
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);
2284   }
2285 }
2286 
2287 /****************************************************************
2288   Commit the changes to the worklist for the city.
2289 *****************************************************************/
commit_city_worklist(struct worklist * pwl,void * data)2290 void commit_city_worklist(struct worklist *pwl, void *data)
2291 {
2292   struct city_dialog *pdialog = data;
2293 
2294   city_worklist_commit(pdialog->pcity, pwl);
2295 }
2296 
cancel_city_worklist(void * data)2297 void cancel_city_worklist(void *data) {
2298   struct city_dialog *pdialog = (struct city_dialog *)data;
2299   pdialog->worklist_shell = NULL;
2300 }
2301 
2302 /****************************************************************
2303 ...
2304 *****************************************************************/
sell_callback_yes(Widget w,XtPointer client_data,XtPointer call_data)2305 static void sell_callback_yes(Widget w, XtPointer client_data,
2306 			      XtPointer call_data)
2307 {
2308   struct city_dialog *pdialog = client_data;
2309 
2310   city_sell_improvement(pdialog->pcity, pdialog->sell_id);
2311 
2312   destroy_message_dialog(w);
2313 }
2314 
2315 
2316 /****************************************************************
2317 ...
2318 *****************************************************************/
sell_callback_no(Widget w,XtPointer client_data,XtPointer call_data)2319 static void sell_callback_no(Widget w, XtPointer client_data,
2320 			     XtPointer call_data)
2321 {
2322   destroy_message_dialog(w);
2323 }
2324 
2325 
2326 /****************************************************************
2327 ...
2328 *****************************************************************/
sell_callback(Widget w,XtPointer client_data,XtPointer call_data)2329 void sell_callback(Widget w, XtPointer client_data, XtPointer call_data)
2330 {
2331   struct city_dialog *pdialog;
2332   XawListReturnStruct *ret;
2333 
2334   pdialog=(struct city_dialog *)client_data;
2335 
2336   ret=XawListShowCurrent(pdialog->improvement_list);
2337 
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;
2344 
2345 	if (!can_city_sell_building(pdialog->pcity, pimprove)) {
2346 	  return;
2347 	}
2348 
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);
2355 
2356 	popup_message_dialog(pdialog->shell, "selldialog", buf,
2357 			     sell_callback_yes, pdialog, 0,
2358 			     sell_callback_no, pdialog, 0, NULL);
2359 
2360 	return;
2361       }
2362       n++;
2363     } city_built_iterate_end;
2364   }
2365 }
2366 
2367 /****************************************************************
2368 ...
2369 *****************************************************************/
close_city_dialog(struct city_dialog * pdialog)2370 void close_city_dialog(struct city_dialog *pdialog)
2371 {
2372   if (pdialog->worklist_shell)
2373     XtDestroyWidget(pdialog->worklist_shell);
2374 
2375   XtDestroyWidget(pdialog->shell);
2376   dialog_list_remove(dialog_list, pdialog);
2377 
2378   free(pdialog->citizen_labels);
2379 
2380   free(pdialog->support_unit_pixcomms);
2381   free(pdialog->present_unit_pixcomms);
2382 
2383 /*
2384   if(pdialog->is_modal)
2385     XtSetSensitive(toplevel, TRUE);
2386 */
2387   free(pdialog);
2388   popdown_cma_dialog();
2389 }
2390 
2391 /****************************************************************
2392 ...
2393 *****************************************************************/
citydlg_key_close(Widget w)2394 void citydlg_key_close(Widget w)
2395 {
2396   citydlg_msg_close(XtParent(XtParent(w)));
2397 }
2398 
2399 /****************************************************************
2400 ...
2401 *****************************************************************/
citydlg_msg_close(Widget w)2402 void citydlg_msg_close(Widget w)
2403 {
2404   dialog_list_iterate(dialog_list, pdialog) {
2405     if (pdialog->shell == w) {
2406       close_city_dialog(pdialog);
2407       return;
2408     }
2409   } dialog_list_iterate_end;
2410 }
2411 
2412 /****************************************************************
2413 ...
2414 *****************************************************************/
close_callback(Widget w,XtPointer client_data,XtPointer call_data)2415 void close_callback(Widget w, XtPointer client_data, XtPointer call_data)
2416 {
2417   close_city_dialog((struct city_dialog *)client_data);
2418 }
2419 
2420 
2421 /****************************************************************
2422 
2423  City Options dialog:  (current only auto-attack options)
2424 
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.
2428 
2429 triggle = tri_toggle (three way toggle button)
2430 
2431 *****************************************************************/
2432 
2433 #define NUM_CITYOPT_TOGGLES 5
2434 
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);
2442 
2443 char *newcitizen_labels[] = {
2444   N_("Workers"),
2445   N_("Scientists"),
2446   N_("Taxmen")
2447 };
2448 
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;
2454 
2455 /****************************************************************
2456 ...
2457 *****************************************************************/
cityopt_callback(Widget w,XtPointer client_data,XtPointer call_data)2458 void cityopt_callback(Widget w, XtPointer client_data,
2459                         XtPointer call_data)
2460 {
2461   struct city_dialog *pdialog = (struct city_dialog *)client_data;
2462   struct city *pcity = pdialog->pcity;
2463   int i;
2464 
2465   if (cityopt_shell) {
2466     XtDestroyWidget(cityopt_shell);
2467   }
2468 
2469   cityopt_shell = create_cityopt_dialog(city_name_get(pcity));
2470 
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);
2474 
2475     XtVaSetValues(cityopt_toggles[i], XtNstate, state,
2476                   XtNlabel, state?_("Yes"):_("No"), NULL);
2477   }
2478 
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;
2485   }
2486 
2487   XtVaSetValues(cityopt_triggle, XtNstate, 1,
2488                 XtNlabel, _(newcitizen_labels[newcitizen_index]),
2489                 NULL);
2490 
2491   cityopt_city_id = pcity->id;
2492 
2493   xaw_set_relative_position(pdialog->shell, cityopt_shell, 15, 15);
2494   XtPopup(cityopt_shell, XtGrabNone);
2495 }
2496 
2497 
2498 /**************************************************************************
2499 ...
2500 **************************************************************************/
create_cityopt_dialog(const char * cityname)2501 Widget create_cityopt_dialog(const char *cityname)
2502 {
2503   Widget shell, form, label, ok, cancel;
2504   int i;
2505 
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);
2514 
2515 
2516   I_L(XtVaCreateManagedWidget("cityoptnewcitlabel", labelWidgetClass,
2517 			      form, NULL));
2518 
2519   cityopt_triggle = XtVaCreateManagedWidget("cityoptnewcittriggle",
2520 					    toggleWidgetClass,
2521 					    form, NULL);
2522 
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
2528   */
2529 
2530   I_L(XtVaCreateManagedWidget("cityoptdisbandlabel", labelWidgetClass,
2531 			      form, NULL));
2532 
2533   cityopt_toggles[4] = XtVaCreateManagedWidget("cityoptdisbandtoggle",
2534 					      toggleWidgetClass,
2535 					      form, NULL);
2536 
2537   I_L(XtVaCreateManagedWidget("cityoptvlandlabel", labelWidgetClass,
2538 			      form, NULL));
2539 
2540   cityopt_toggles[0] = XtVaCreateManagedWidget("cityoptvlandtoggle",
2541 					      toggleWidgetClass,
2542 					      form, NULL);
2543 
2544   I_L(XtVaCreateManagedWidget("cityoptvsealabel", labelWidgetClass,
2545 			      form, NULL));
2546 
2547   cityopt_toggles[1] = XtVaCreateManagedWidget("cityoptvseatoggle",
2548 					      toggleWidgetClass,
2549 					      form, NULL);
2550 
2551   I_L(XtVaCreateManagedWidget("cityoptvairlabel", labelWidgetClass,
2552 			      form, NULL));
2553 
2554   cityopt_toggles[3] = XtVaCreateManagedWidget("cityoptvairtoggle",
2555 					      toggleWidgetClass,
2556 					      form, NULL);
2557 
2558   I_L(XtVaCreateManagedWidget("cityoptvhelilabel", labelWidgetClass,
2559 			      form, NULL));
2560 
2561   cityopt_toggles[2] = XtVaCreateManagedWidget("cityoptvhelitoggle",
2562 					      toggleWidgetClass,
2563 					      form, NULL);
2564 
2565   ok = I_L(XtVaCreateManagedWidget("cityoptokcommand",
2566 				   commandWidgetClass,
2567 				   form, NULL));
2568 
2569   cancel = I_L(XtVaCreateManagedWidget("cityoptcancelcommand",
2570 				       commandWidgetClass,
2571 				       form, NULL));
2572 
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);
2579   }
2580   XtAddCallback(cityopt_triggle, XtNcallback,
2581 		cityopt_newcit_triggle_callback, NULL);
2582 
2583   XtRealizeWidget(shell);
2584 
2585   xaw_horiz_center(label);
2586   return shell;
2587 }
2588 
2589 /**************************************************************************
2590 ...
2591 **************************************************************************/
cityopt_cancel_command_callback(Widget w,XtPointer client_data,XtPointer call_data)2592 void cityopt_cancel_command_callback(Widget w, XtPointer client_data,
2593 				    XtPointer call_data)
2594 {
2595   XtDestroyWidget(cityopt_shell);
2596   cityopt_shell = 0;
2597 }
2598 
2599 /**************************************************************************
2600 ...
2601 **************************************************************************/
cityopt_ok_command_callback(Widget w,XtPointer client_data,XtPointer call_data)2602 void cityopt_ok_command_callback(Widget w, XtPointer client_data,
2603 				XtPointer call_data)
2604 {
2605   struct city *pcity = game_city_by_number(cityopt_city_id);
2606 
2607   if (pcity) {
2608 /*    int i; */
2609     bv_city_options new_options;
2610     Boolean b;
2611 
2612     fc_assert(CITYO_LAST == 3);
2613 
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);
2618     }
2619 */
2620     XtVaGetValues(cityopt_toggles[4], XtNstate, &b, NULL);
2621     if (b) {
2622       BV_SET(new_options, CITYO_DISBAND);
2623     }
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);
2628     }
2629     dsend_packet_city_options_req(&client.conn, cityopt_city_id,new_options);
2630   }
2631   XtDestroyWidget(cityopt_shell);
2632   cityopt_shell = 0;
2633 }
2634 
2635 /**************************************************************************
2636  Changes the label of the toggle widget to between newcitizen_labels
2637  and increments (mod 3) newcitizen_index.
2638 **************************************************************************/
cityopt_newcit_triggle_callback(Widget w,XtPointer client_data,XtPointer call_data)2639 void cityopt_newcit_triggle_callback(Widget w, XtPointer client_data,
2640 					XtPointer call_data)
2641 {
2642   newcitizen_index++;
2643   if (newcitizen_index>=3) {
2644     newcitizen_index = 0;
2645   }
2646   XtVaSetValues(cityopt_triggle, XtNstate, 1,
2647 		XtNlabel, _(newcitizen_labels[newcitizen_index]),
2648 		NULL);
2649 }
2650 
2651 /**************************************************************************
2652 ...
2653 **************************************************************************/
popdown_cityopt_dialog(void)2654 void popdown_cityopt_dialog(void)
2655 {
2656   if(cityopt_shell) {
2657     XtDestroyWidget(cityopt_shell);
2658     cityopt_shell = 0;
2659   }
2660 }
2661 
2662 /****************************************************************
2663   The user clicked on the "CMA..." button in the citydialog.
2664 *****************************************************************/
cma_callback(Widget w,XtPointer client_data,XtPointer call_data)2665 void cma_callback(Widget w, XtPointer client_data,
2666                   XtPointer call_data)
2667 {
2668   struct city_dialog *pdialog = (struct city_dialog *)client_data;
2669 
2670   popdown_cma_dialog();
2671   show_cma_dialog(pdialog->pcity, pdialog->shell);
2672 }
2673 
2674 /**************************************************************************
2675   City is about to disappear from client
2676 **************************************************************************/
city_to_disappear(struct city * pcity)2677 void city_to_disappear(struct city *pcity)
2678 {
2679 }
2680