1 /***********************************************************************
2  Freeciv - Copyright (C) 2003 - The Freeciv Project
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/Scrollbar.h>
28 #include <X11/Xaw/SimpleMenu.h>
29 #include <X11/Xaw/SmeBSB.h>
30 #include <X11/Xaw/List.h>
31 #include <X11/Xaw/Viewport.h>
32 #include <X11/Xaw/AsciiText.h>
33 #include <X11/Xaw/Toggle.h>
34 #include <X11/IntrinsicP.h>
35 
36 #include "pixcomm.h"
37 #include "canvas.h"
38 
39 /* utility */
40 #include "fcintl.h"
41 #include "genlist.h"
42 #include "log.h"
43 #include "mem.h"
44 #include "shared.h"
45 #include "support.h"
46 
47 /* common */
48 #include "city.h"
49 #include "game.h"
50 #include "map.h"
51 #include "packets.h"
52 #include "player.h"
53 
54 /* client */
55 #include "client_main.h"
56 #include "cma_fec.h"
57 
58 #include "cityrep.h"
59 #include "citydlg.h"
60 #include "cma_fe.h"
61 #include "colors.h"
62 #include "control.h"
63 #include "dialogs.h"
64 #include "graphics.h"
65 #include "gui_main.h"
66 #include "gui_stuff.h"
67 #include "helpdlg.h"
68 #include "inputdlg.h"
69 #include "mapctrl.h"
70 #include "mapview.h"
71 #include "optiondlg.h"
72 #include "repodlgs.h"
73 #include "wldlg.h"
74 
75 Widget *stat_surplus_label, *stat_factor_label;
76 Widget control_button, change_button, preset_list, cma_dialog;
77 Widget celebrate_toggle, result_label, release_button;
78 Widget surplus_slider[O_LAST], factor_slider[O_LAST + 1];
79 
80 int minimal_surplus[O_LAST], factors[O_LAST + 1];
81 struct city *current_city;
82 CONST_FOR_XAW_LIST_CHANGE char *initial_preset_list[] = {
83 	N_("For information on\n"
84            "the citizen governor and governor presets,\n"
85            "including sample presets,\n"
86            "see README.governor."),
87 	NULL};
88 
89 
90 static void update_cma_preset_list(void);
91 static void control_city(Widget w, XtPointer client_data,
92                          XtPointer call_data);
93 static void release_city(Widget w, XtPointer client_data,
94                          XtPointer call_data);
95 
96 static void add_preset(Widget w, XtPointer client_data,
97                        XtPointer call_data);
98 static void remove_preset(Widget w, XtPointer client_data,
99                           XtPointer call_data);
100 static void remove_preset_yes(Widget w, XtPointer client_data,
101                               XtPointer call_data);
102 static void remove_preset_no(Widget w, XtPointer client_data,
103                              XtPointer call_data);
104 static void select_preset(Widget w, XtPointer client_data,
105                           XtPointer call_data);
106 static void cma_help(Widget w, XtPointer client_data,
107                      XtPointer call_data);
108 static void set_slider_values(void);
109 static void sliders_jump_callback(Widget w, XtPointer client_data,
110                                   XtPointer position_val);
111 static void sliders_scroll_callback(Widget w, XtPointer client_data,
112                                     XtPointer position_val);
113 static void update_stat_labels(bool is_valid);
114 static void new_preset_callback(Widget w, XtPointer client_data,
115                                 XtPointer call_data);
116 static void celebrate_callback(Widget w, XtPointer client_data,
117                                XtPointer position_val);
118 static void close_callback(Widget w, XtPointer client_data,
119                            XtPointer call_data);
120 static void change_callback(Widget w, XtPointer client_data,
121                             XtPointer call_data);
122 
123 
124 /**************************************************************************
125  Show the Citizen Management Agent Dialog for the current city.
126 **************************************************************************/
show_cma_dialog(struct city * pcity,Widget citydlg)127 void show_cma_dialog(struct city *pcity, Widget citydlg)
128 {
129   Widget add_button, remove_button, help_button;
130   Widget form, preset_viewport, close_button;
131   Widget surplus_header, factor_header, prev;
132   struct cm_parameter parameter;
133   struct cm_result *result = cm_result_new(pcity);
134   int i;
135 
136   current_city = pcity;
137   stat_surplus_label = fc_malloc((O_LAST + 1) * sizeof(Widget));
138   stat_factor_label = fc_malloc((O_LAST + 1) * sizeof(Widget));
139 
140   cma_dialog =
141     I_T(XtCreatePopupShell("cmapopup",
142                            topLevelShellWidgetClass,
143                            citydlg, NULL, 0));
144 
145   form =
146     XtVaCreateManagedWidget("cmaform",
147                             formWidgetClass,
148                             cma_dialog, NULL);
149 
150   preset_viewport =
151     XtVaCreateManagedWidget("cmapresetviewport",
152                             viewportWidgetClass, form,
153                             NULL);
154 
155   preset_list =
156     XtVaCreateManagedWidget("cmapresetlist",
157                             listWidgetClass, preset_viewport,
158                             XtNlist, (XtArgVal)initial_preset_list,
159                             NULL);
160 
161   result_label =
162     I_L(XtVaCreateManagedWidget("cmaresultlabel",
163                                 labelWidgetClass, form,
164                                 XtNfromHoriz, preset_viewport,
165                                 NULL));
166 
167   surplus_header =
168     I_L(XtVaCreateManagedWidget("cmasurpluslabel",
169                                 labelWidgetClass, form,
170                                 XtNfromHoriz, preset_viewport,
171                                 XtNfromVert, result_label,
172                                 NULL));
173 
174   /* Create labels in the minimal surplus column. */
175   prev = surplus_header;
176   for (i = 0; i < (O_LAST + 1); i++) {
177     I_L(stat_surplus_label[i] =
178         XtVaCreateManagedWidget("cmastatlabel",
179                                 labelWidgetClass, form,
180                                 XtNfromHoriz, preset_viewport,
181                                 XtNfromVert, prev,
182                                 XtNvertDistance, 1,
183                                 XtNlabel, (i == O_LAST) ?
184                                   _("Celebrate") : get_output_name(i),
185                                 NULL));
186     prev = stat_surplus_label[i];
187   }
188 
189   /* Create scrollbars in the minimal surplus column. */
190   prev = surplus_header;
191   output_type_iterate(o) {
192     surplus_slider[o] =
193       XtVaCreateManagedWidget("cmapresetscroll",
194                               scrollbarWidgetClass, form,
195                               XtNfromHoriz, stat_surplus_label[o],
196                               XtNfromVert, prev,
197                               NULL);
198     prev = stat_surplus_label[o];
199   } output_type_iterate_end;
200 
201   celebrate_toggle =
202     I_L(XtVaCreateManagedWidget("cmapresettoggle",
203                                 toggleWidgetClass,form,
204                                 XtNfromHoriz, stat_surplus_label[0],
205                                 XtNfromVert, stat_surplus_label[O_LAST - 1],
206                                 NULL));
207 
208   /* Create header label in the factor column. */
209   factor_header =
210     I_L(XtVaCreateManagedWidget("cmafactorlabel",
211                                 labelWidgetClass, form,
212                                 XtNfromHoriz, surplus_slider[0],
213                                 XtNfromVert, result_label,
214                                 NULL));
215 
216   /* Create stat labels in the factor column. */
217   prev = factor_header;
218   for (i = 0; i < (O_LAST + 1); i++) {
219     I_L(stat_factor_label[i] =
220         XtVaCreateManagedWidget("cmastatlabel",
221                                 labelWidgetClass, form,
222                                 XtNfromHoriz, surplus_slider[0],
223                                 XtNfromVert, prev,
224                                 XtNvertDistance, 1,
225                                 XtNlabel, (i == O_LAST) ?
226                                   _("Celebrate") : get_output_name(i),
227                                 NULL));
228     prev = stat_factor_label[i];
229   }
230 
231   /* Create scrollbars in the factor column. */
232   prev = factor_header;
233   for (i = 0; i < (O_LAST + 1); i++) {
234     factor_slider[i] =
235       XtVaCreateManagedWidget("cmapresetscroll",
236                                   scrollbarWidgetClass, form,
237                                   XtNfromHoriz, stat_factor_label[i],
238                                   XtNfromVert, prev,
239                                   NULL);
240     prev = stat_factor_label[i];
241   }
242 
243   close_button =
244     I_L(XtVaCreateManagedWidget("cmaclosebutton",
245                                 commandWidgetClass, form,
246                                 XtNfromVert, preset_viewport,
247                                 NULL));
248 
249   control_button =
250     I_L(XtVaCreateManagedWidget("cmacontrolbutton",
251                                 commandWidgetClass, form,
252                                 XtNfromVert, preset_viewport,
253                                 XtNfromHoriz, close_button,
254                                 NULL));
255 
256   release_button =
257     I_L(XtVaCreateManagedWidget("cmareleasebutton",
258                                 commandWidgetClass, form,
259                                 XtNfromVert, preset_viewport,
260                                 XtNfromHoriz, control_button,
261                                 NULL));
262 
263   change_button =
264     I_L(XtVaCreateManagedWidget("cmachangebutton",
265                                 commandWidgetClass, form,
266                                 XtNfromVert, preset_viewport,
267                                 XtNfromHoriz, release_button,
268                                 NULL));
269 
270   add_button =
271    I_L(XtVaCreateManagedWidget("cmaaddbutton",
272                                commandWidgetClass, form,
273                                XtNfromVert, preset_viewport,
274                                XtNfromHoriz, change_button,
275                                NULL));
276 
277   remove_button =
278      I_L(XtVaCreateManagedWidget("cmaremovebutton",
279                                  commandWidgetClass, form,
280                                  XtNfromVert, preset_viewport,
281                                  XtNfromHoriz, add_button,
282                                  NULL));
283 
284   help_button =
285      I_L(XtVaCreateManagedWidget("cmahelpbutton",
286                                  commandWidgetClass, form,
287                                  XtNfromVert, preset_viewport,
288                                  XtNfromHoriz, remove_button,
289                                  NULL));
290 
291   XtAddCallback(control_button, XtNcallback, control_city,
292                 (XtPointer)preset_list);
293   XtAddCallback(release_button, XtNcallback, release_city,
294                 (XtPointer)preset_list);
295   XtAddCallback(change_button, XtNcallback, change_callback,
296                 (XtPointer)preset_list);
297   XtAddCallback(add_button, XtNcallback, add_preset,
298                 (XtPointer)preset_list);
299   XtAddCallback(remove_button, XtNcallback, remove_preset,
300                 (XtPointer)preset_list);
301   XtAddCallback(preset_list, XtNcallback, select_preset,
302                 (XtPointer)preset_list);
303   XtAddCallback(help_button, XtNcallback, cma_help,
304                 (XtPointer)preset_list);
305   XtAddCallback(celebrate_toggle, XtNcallback,
306                 celebrate_callback, NULL);
307   XtAddCallback(close_button, XtNcallback,
308                 close_callback, NULL);
309 
310   output_type_iterate(o) {
311     XtAddCallback(surplus_slider[o], XtNscrollProc,
312                   sliders_scroll_callback, NULL);
313     XtAddCallback(surplus_slider[o], XtNjumpProc,
314                   sliders_jump_callback, NULL);
315   } output_type_iterate_end;
316 
317   for (i = 0; i < (O_LAST + 1); i++) {
318     XtAddCallback(factor_slider[i], XtNscrollProc,
319                   sliders_scroll_callback, NULL);
320     XtAddCallback(factor_slider[i], XtNjumpProc,
321                   sliders_jump_callback, NULL);
322   }
323 
324   /* Update dialog with CMA parameters from city.  */
325   cmafec_get_fe_parameter(current_city, &parameter);
326 
327   output_type_iterate(o) {
328     minimal_surplus[o] = parameter.minimal_surplus[o];
329   } output_type_iterate_end;
330 
331   XtVaSetValues(celebrate_toggle,
332          XtNlabel, parameter.require_happy ? _("Yes") : _("No"),
333          XtNstate, parameter.require_happy, NULL);
334 
335   if (parameter.happy_factor > 0) {
336     factors[O_LAST] = parameter.happy_factor;
337   } else {
338     factors[O_LAST] = 1;
339   }
340 
341   output_type_iterate(o) {
342     factors[o] = parameter.factor[o];
343   } output_type_iterate_end;
344 
345   set_slider_values();
346   update_cma_preset_list();
347 
348   XtVaSetValues(preset_list, XtNwidth, 200, NULL);
349   XtVaSetValues(preset_list, XtNheight, 300, NULL);
350   XtVaSetValues(celebrate_toggle, XtNwidth, 30, NULL);
351   XtVaSetValues(result_label, XtNwidth, 360, NULL);
352   XtVaSetValues(result_label, XtNheight, 110, NULL);
353 
354   output_type_iterate(o) {
355     XtVaSetValues(stat_surplus_label[o], XtNwidth, 90, NULL);
356     XtVaSetValues(stat_factor_label[o], XtNwidth, 90, NULL);
357   } output_type_iterate_end;
358   /* FIXME! Now we assume that output_type_iterate ends with O_LAST. */
359   XtVaSetValues(stat_factor_label[O_LAST], XtNwidth, 90, NULL);
360 
361   XtRealizeWidget(cma_dialog);
362 
363   update_stat_labels(True);
364   cm_result_from_main_map(result, pcity);
365   xaw_set_label(result_label,
366        (char *) cmafec_get_result_descr(current_city, result, &parameter));
367 
368   XSetWMProtocols(display, XtWindow(cma_dialog),
369                   &wm_delete_window, 1);
370   XtVaSetValues(preset_viewport, XtNforceBars, True, NULL);
371   xaw_set_relative_position(citydlg, cma_dialog, 5, 5);
372   XtPopup(cma_dialog, XtGrabNone);
373 
374   cm_result_destroy(result);
375 }
376 
377 /**************************************************************************
378  Fills in the preset list.
379 **************************************************************************/
update_cma_preset_list(void)380 static void update_cma_preset_list(void)
381 {
382   static CONST_FOR_XAW_LIST_CHANGE char *preset_lines[256];
383   static char preset_text[256][256];
384   int i;
385 
386   if (cmafec_preset_num()) {
387     /* Add all CMA presets to the list. */
388     for (i = 0; i < cmafec_preset_num(); i++) {
389       fc_strlcpy(preset_text[i], cmafec_preset_get_descr(i),
390 		sizeof(preset_text[i]));
391       preset_lines[i] = preset_text[i];
392     }
393     XawListChange(preset_list, preset_lines, cmafec_preset_num(), 0, True);
394   } else {
395     /* Show intro message in the preset list. */
396     XawListChange(preset_list, initial_preset_list, 8, 0, True);
397   }
398 }
399 
400 /****************************************************************
401  Enable CMA control over the city.
402 *****************************************************************/
control_city(Widget w,XtPointer list,XtPointer call_data)403 static void control_city(Widget w, XtPointer list,
404                          XtPointer call_data)
405 {
406   struct cm_parameter param;
407 
408   cmafec_get_fe_parameter(current_city, &param);
409   cma_put_city_under_agent(current_city, &param);
410   refresh_city_dialog(current_city);
411 
412   XtSetSensitive(control_button, FALSE);
413   XtSetSensitive(release_button, TRUE);
414   XtSetSensitive(change_button, FALSE);
415 }
416 
417 /****************************************************************
418  Disables CMA control over the city.
419 *****************************************************************/
release_city(Widget w,XtPointer list,XtPointer call_data)420 static void release_city(Widget w, XtPointer list,
421                          XtPointer call_data)
422 {
423   cma_release_city(current_city);
424   refresh_city_dialog(current_city);
425 
426   XtSetSensitive(control_button, TRUE);
427   XtSetSensitive(release_button, FALSE);
428   XtSetSensitive(change_button, TRUE);
429 }
430 
431 /****************************************************************
432  Create a new preset, first asking for the presets name.
433 *****************************************************************/
add_preset(Widget w,XtPointer client_data,XtPointer call_data)434 static void add_preset(Widget w, XtPointer client_data,
435                        XtPointer call_data)
436 {
437   input_dialog_create(cma_dialog, "cmapresetname",
438                       _("What should we name the new preset?"),
439                       _("new preset"),
440                       new_preset_callback, INT_TO_XTPOINTER(TRUE),
441                       new_preset_callback, INT_TO_XTPOINTER(FALSE));
442 }
443 
444 /****************************************************************
445  Confirm that the user wants to remove the selected preset.
446 *****************************************************************/
remove_preset(Widget w,XtPointer list,XtPointer call_data)447 static void remove_preset(Widget w, XtPointer list,
448                           XtPointer call_data)
449 {
450   XawListReturnStruct *ret = XawListShowCurrent(preset_list);
451   char buf[256];
452 
453   if (ret->list_index != XAW_LIST_NONE && cmafec_preset_num()) {
454     fc_snprintf(buf, sizeof(buf),
455                 _("Do you really want to remove %s?"),
456                 cmafec_preset_get_descr(ret->list_index));
457 
458     popup_message_dialog(cma_dialog, "cmaremovepreset",
459                          buf, remove_preset_yes,
460                          INT_TO_XTPOINTER(ret->list_index), 0,
461                          remove_preset_no, 0, 0,
462                          NULL);
463   }
464 }
465 
466 /****************************************************************
467  Remove the preset selected in the preset list.
468 *****************************************************************/
remove_preset_yes(Widget w,XtPointer row,XtPointer call_data)469 static void remove_preset_yes(Widget w, XtPointer row,
470                               XtPointer call_data)
471 {
472   cmafec_preset_remove(XTPOINTER_TO_INT(row));
473   update_cma_preset_list();
474   destroy_message_dialog(w);
475 }
476 
477 /****************************************************************
478  Close the remove preset dialog, without removing a preset.
479 *****************************************************************/
remove_preset_no(Widget w,XtPointer client_data,XtPointer call_data)480 static void remove_preset_no(Widget w, XtPointer client_data,
481                              XtPointer call_data)
482 {
483   destroy_message_dialog(w);
484 }
485 
486 /****************************************************************
487  Callback for CMA the preset list.
488 *****************************************************************/
select_preset(Widget w,XtPointer list,XtPointer call_data)489 static void select_preset(Widget w, XtPointer list,
490                           XtPointer call_data)
491 {
492   XawListReturnStruct *ret;
493   const struct cm_parameter *param;
494   struct cm_parameter parameter;
495   struct cm_result *result;
496 
497   /* check gloabl variable current_city */
498   fc_assert_ret(current_city != NULL);
499 
500   result = cm_result_new(current_city);
501   ret = XawListShowCurrent(list);
502 
503   if (ret->list_index != XAW_LIST_NONE && cmafec_preset_num()) {
504     param = cmafec_preset_get_parameter(ret->list_index);
505     cmafec_set_fe_parameter(current_city, param);
506 
507     if (cma_is_city_under_agent(current_city, NULL)) {
508       cma_release_city(current_city);
509       cma_put_city_under_agent(current_city, param);
510     }
511 
512     cmafec_get_fe_parameter(current_city, &parameter);
513     cm_result_from_main_map(result, current_city);
514     xaw_set_label(result_label,
515         (char *) cmafec_get_result_descr(current_city, result, &parameter));
516 
517     output_type_iterate(i) {
518       minimal_surplus[i] = param->minimal_surplus[i];
519     } output_type_iterate_end;
520 
521     XtVaSetValues(celebrate_toggle, XtNlabel,
522             param->require_happy ? _("Yes") : _("No"),
523             XtNstate, parameter.require_happy, NULL);
524 
525     factors[O_LAST] = param->happy_factor;
526 
527     output_type_iterate(i) {
528       factors[i] = param->factor[i];
529     } output_type_iterate_end;
530   }
531 
532   update_stat_labels(result->found_a_valid);
533   cm_result_destroy(result);
534 }
535 
536 /****************************************************************
537  Show the CMA help page.
538 *****************************************************************/
cma_help(Widget w,XtPointer list,XtPointer call_data)539 static void cma_help(Widget w, XtPointer list,
540                      XtPointer call_data)
541 {
542   popup_help_dialog_string(HELP_CMA_ITEM);
543 }
544 
545 /****************************************************************
546  Sets the position for all sliders.
547 *****************************************************************/
set_slider_values(void)548 static void set_slider_values(void)
549 {
550   int i;
551 
552   output_type_iterate(o) {
553     XawScrollbarSetThumb(surplus_slider[o],
554                          (((20 + minimal_surplus[o])))*1/41.0f, 1/41.0f);
555   } output_type_iterate_end;
556 
557   for (i = 0; i < (O_LAST + 1); i++) {
558     XawScrollbarSetThumb(factor_slider[i],
559                      (((factors[i])))*1/25.0f, 1/25.0f);
560   }
561 }
562 
563 /**************************************************************************
564  Callback to update parameters if slider was scrolled. (Xaw)
565 **************************************************************************/
sliders_scroll_callback(Widget w,XtPointer client_data,XtPointer position_val)566 static void sliders_scroll_callback(Widget w, XtPointer client_data,
567                                     XtPointer position_val)
568 {
569   int pos = XTPOINTER_TO_INT(position_val);
570   struct cm_parameter parameter;
571   struct cm_result *result;
572   int i, preset_index;
573 
574   /* check gloabl variable current_city */
575   fc_assert_ret(current_city != NULL);
576 
577   result = cm_result_new(current_city);
578 
579   output_type_iterate(o) {
580     if (w == surplus_slider[o]) {
581       if (pos > 0 ) {
582         minimal_surplus[o]++;
583         if (minimal_surplus[o] == 21) {
584           minimal_surplus[o]--;
585         }
586       } else {
587         minimal_surplus[o]--;
588         if (minimal_surplus[o] == -21) {
589           minimal_surplus[o]++;
590         }
591       }
592     }
593   } output_type_iterate_end;
594 
595   for (i = 0; i < (O_LAST + 1); i++) {
596     if (w == factor_slider[i]) {
597       if (pos > 0 ) {
598         factors[i]++;
599         if (factors[i] == 26) {
600           factors[i]--;
601         }
602       } else {
603         factors[i]--;
604         if (factors[i] == 0) {
605           factors[i]++;
606         }
607       }
608     }
609   }
610 
611   cmafec_get_fe_parameter(current_city, &parameter);
612 
613   output_type_iterate(o) {
614     parameter.minimal_surplus[o] = minimal_surplus[o];
615     parameter.factor[o] = factors[o];
616   } output_type_iterate_end;
617 
618   XtVaGetValues(celebrate_toggle, XtNstate, &parameter.require_happy, NULL);
619   parameter.happy_factor = factors[O_LAST];
620 
621   cmafec_set_fe_parameter(current_city, &parameter);
622 
623   if (cma_is_city_under_agent(current_city, NULL)) {
624     cma_release_city(current_city);
625     cma_put_city_under_agent(current_city, &parameter);
626   }
627 
628   cmafec_get_fe_parameter(current_city, &parameter);
629   cm_result_from_main_map(result, current_city);
630   xaw_set_label(result_label,
631         (char *) cmafec_get_result_descr(current_city, result, &parameter));
632 
633   update_stat_labels(result->found_a_valid);
634   update_cma_preset_list();
635 
636   /* highlight preset if parameter matches */
637   preset_index = cmafec_preset_get_index_of_parameter(&parameter);
638   if (preset_index != -1) {
639     XawListHighlight(preset_list, preset_index);
640   }
641 
642   cm_result_destroy(result);
643 }
644 
645 /**************************************************************************
646  Callback to update parameters if slider was jumped. (Xaw3D)
647 **************************************************************************/
sliders_jump_callback(Widget w,XtPointer client_data,XtPointer percent_ptr)648 void sliders_jump_callback(Widget w, XtPointer client_data,
649                            XtPointer percent_ptr)
650 {
651   float percent=*(float*)percent_ptr;
652   struct cm_parameter parameter;
653   struct cm_result *result;
654   int i, preset_index;
655 
656   /* check gloabl variable current_city */
657   fc_assert_ret(current_city != NULL);
658 
659   result = cm_result_new(current_city);
660 
661   output_type_iterate(o) {
662     if (w == surplus_slider[o]) {
663       /* convert from percent to [-20..20] */
664       minimal_surplus[o] = (int)(percent * 41) - 20;
665     }
666   } output_type_iterate_end;
667 
668   for (i = 0; i < (O_LAST + 1); i++) {
669     if (w == factor_slider[i]) {
670       /* convert from percent to [1..25] */
671       factors[i] = (int)(percent * 25) + 1;
672     }
673   }
674 
675   cmafec_get_fe_parameter(current_city, &parameter);
676 
677   output_type_iterate(o) {
678     parameter.minimal_surplus[o] = minimal_surplus[o];
679     parameter.factor[o] = factors[o];
680   } output_type_iterate_end;
681 
682   XtVaGetValues(celebrate_toggle, XtNstate, &parameter.require_happy, NULL);
683   parameter.happy_factor = factors[O_LAST];
684 
685   cmafec_set_fe_parameter(current_city, &parameter);
686 
687   if (cma_is_city_under_agent(current_city, NULL)) {
688     cma_release_city(current_city);
689     cma_put_city_under_agent(current_city, &parameter);
690   }
691 
692   cmafec_get_fe_parameter(current_city, &parameter);
693   cm_result_from_main_map(result, current_city);
694   xaw_set_label(result_label,
695         (char *) cmafec_get_result_descr(current_city, result, &parameter));
696 
697   update_cma_preset_list();
698   update_stat_labels(result->found_a_valid);
699 
700   /* highlight preset if parameter matches */
701   preset_index = cmafec_preset_get_index_of_parameter(&parameter);
702   if (preset_index != -1) {
703     XawListHighlight(preset_list, preset_index);
704   }
705 
706   cm_result_destroy(result);
707 }
708 
709 /**************************************************************************
710  Update CMA stat labels, set sensitivity on buttons, refresh city dialog.
711 **************************************************************************/
update_stat_labels(bool is_valid)712 static void update_stat_labels(bool is_valid)
713 {
714   char buf[256];
715 
716   output_type_iterate(i) {
717     fc_snprintf(buf, sizeof(buf), "%-9s%3d",
718                 get_output_name(i),
719                 minimal_surplus[i]);
720     xaw_set_label(stat_surplus_label[i], buf);
721   } output_type_iterate_end;
722 
723   output_type_iterate(i) {
724     fc_snprintf(buf, sizeof(buf), "%-9s%3d",
725                 get_output_name(i),
726                 factors[i]);
727     xaw_set_label(stat_factor_label[i], buf);
728   } output_type_iterate_end;
729   fc_snprintf(buf, sizeof(buf), "%-9s%3d",
730               "Celebrate",
731               factors[O_LAST]);
732   xaw_set_label(stat_factor_label[O_LAST], buf);
733 
734   XtSetSensitive(release_button,
735        (cma_is_city_under_agent(current_city, NULL)
736         && can_client_issue_orders()));
737 
738   XtSetSensitive(control_button,
739        (!cma_is_city_under_agent(current_city, NULL)
740         && is_valid
741         && can_client_issue_orders()));
742 
743   XtSetSensitive(change_button,
744        (!cma_is_city_under_agent(current_city, NULL)
745         && is_valid
746         && can_client_issue_orders()));
747   set_slider_values();
748   refresh_city_dialog(current_city);
749 }
750 
751 /**************************************************************************
752  Callback to save the new CMA preset after a name has been typed.
753 **************************************************************************/
new_preset_callback(Widget w,XtPointer save_preset,XtPointer call_data)754 static void new_preset_callback(Widget w, XtPointer save_preset,
755                                      XtPointer call_data)
756 {
757   Boolean celebrate_setting;
758   struct cm_parameter parameter;
759 
760   if (save_preset) {
761     /* The user entered a preset name and clicked OK  */
762     XtVaGetValues(celebrate_toggle, XtNstate, &celebrate_setting, NULL);
763     cmafec_get_fe_parameter(current_city, &parameter);
764 
765     output_type_iterate(i) {
766       parameter.minimal_surplus[i] = minimal_surplus[i];
767       parameter.factor[i] = factors[i];
768     } output_type_iterate_end;
769 
770     parameter.happy_factor = factors[O_LAST];
771     parameter.require_happy = celebrate_setting;
772 
773     cmafec_preset_add(input_dialog_get_input(w), &parameter);
774 
775     update_cma_preset_list();
776   }
777   input_dialog_destroy(w);
778 }
779 
780 /**************************************************************************
781  Callback to handle changes to the celebrate toggle.
782 **************************************************************************/
celebrate_callback(Widget w,XtPointer client_data,XtPointer call_data)783 void celebrate_callback(Widget w, XtPointer client_data, XtPointer call_data)
784 {
785   Boolean celebrate;
786   struct cm_parameter parameter;
787   struct cm_result *result;
788 
789   /* check gloabl variable current_city */
790   fc_assert_ret(current_city != NULL);
791 
792   /* Change label on celebrate toggle. */
793   XtVaGetValues(w, XtNstate, &celebrate, NULL);
794   XtVaSetValues(w, XtNlabel, celebrate ? _("Yes") : _("No"), NULL);
795 
796   /* Update parameters with new celebrate setting. */
797   cmafec_get_fe_parameter(current_city, &parameter);
798   output_type_iterate(i) {
799     parameter.minimal_surplus[i] = minimal_surplus[i];
800     parameter.factor[i] = factors[i];
801   } output_type_iterate_end;
802 
803   XtVaGetValues(celebrate_toggle, XtNstate, &parameter.require_happy, NULL);
804   parameter.happy_factor = factors[O_LAST];
805 
806   cmafec_set_fe_parameter(current_city, &parameter);
807 
808   if (cma_is_city_under_agent(current_city, NULL)) {
809     cma_release_city(current_city);
810     cma_put_city_under_agent(current_city, &parameter);
811   }
812 
813   result = cm_result_new(current_city);
814   cmafec_get_fe_parameter(current_city, &parameter);
815   cm_result_from_main_map(result, current_city);
816   xaw_set_label(result_label,
817         (char *) cmafec_get_result_descr(current_city, result, &parameter));
818 
819   update_stat_labels(result->found_a_valid);
820   update_cma_preset_list();
821 
822   cm_result_destroy(result);
823 }
824 
825 /**************************************************************************
826  Close the CMA dialog. Also called when the citydialog closes.
827 **************************************************************************/
popdown_cma_dialog(void)828 void popdown_cma_dialog(void)
829 {
830   if (cma_dialog) {
831     city_report_dialog_update_city(current_city);
832     XtDestroyWidget(cma_dialog);
833     cma_dialog = 0;
834   }
835 }
836 
837 /**************************************************************************
838   Callback to close the CMA dialog when the user clicks on Close.
839 **************************************************************************/
close_callback(Widget w,XtPointer client_data,XtPointer call_data)840 static void close_callback(Widget w, XtPointer client_data,
841                            XtPointer call_data)
842 {
843   popdown_cma_dialog();
844 }
845 
846 /**************************************************************************
847   Callback to apply CMA preset to city once.
848 **************************************************************************/
change_callback(Widget w,XtPointer client_data,XtPointer call_data)849 static void change_callback(Widget w, XtPointer client_data,
850                             XtPointer call_data)
851 {
852   struct cm_result *result;
853   struct cm_parameter param;
854 
855   /* check gloabl variable current_city */
856   fc_assert_ret(current_city != NULL);
857 
858   result = cm_result_new(current_city);
859   cmafec_get_fe_parameter(current_city, &param);
860   cm_query_result(current_city, &param, result, FALSE);
861   cma_apply_result(current_city, result);
862   refresh_city_dialog(current_city);
863 
864   cm_result_destroy(result);
865 }
866