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 #include <string.h>
21 
22 #include <X11/Intrinsic.h>
23 #include <X11/IntrinsicP.h>
24 #include <X11/StringDefs.h>
25 #include <X11/Xaw/AsciiText.h>
26 #include <X11/Xaw/Command.h>
27 #include <X11/Xaw/Form.h>
28 #include <X11/Xaw/Label.h>
29 #include <X11/Xaw/List.h>
30 #include <X11/Xaw/MenuButton.h>
31 #include <X11/Xaw/SimpleMenu.h>
32 #include <X11/Xaw/SmeBSB.h>
33 #include <X11/Xaw/Toggle.h>
34 #include <X11/Xaw/Viewport.h>
35 
36 /* utility */
37 #include "fcintl.h"
38 #include "log.h"
39 #include "mem.h"
40 
41 /* common */
42 #include "city.h"
43 #include "packets.h"
44 #include "worklist.h"
45 
46 /* client */
47 #include "client_main.h"
48 #include "climisc.h"
49 
50 #include "gui_main.h"
51 #include "gui_stuff.h"
52 #include "helpdlg.h"
53 #include "inputdlg.h"
54 
55 #include "wldlg.h"
56 
57 #define WORKLIST_ADVANCED_TARGETS  1
58 #define WORKLIST_CURRENT_TARGETS   0
59 
60 /*
61   The Worklist Report dialog shows all the global worklists that the
62   player has defined.  There can be at most MAX_NUM_WORKLISTS global
63   worklists.
64   */
65 struct worklist_report_dialog {
66   Widget list;
67   struct player *pplr;
68   char worklist_names[MAX_NUM_WORKLISTS][MAX_LEN_NAME];
69   CONST_FOR_XAW_LIST_CHANGE char *worklist_names_ptrs[MAX_NUM_WORKLISTS+1];
70   struct global_worklist *worklist_ptr[MAX_NUM_WORKLISTS];
71   int wl_idx;
72 };
73 
74 /*
75   The Worklist dialog is the dialog with which the player edits a
76   particular worklist.  The worklist dialog is popped-up from either
77   the Worklist Report dialog or from a City dialog.
78   */
79 struct worklist_dialog {
80   Widget worklist, avail;
81   Widget btn_prepend, btn_insert, btn_delete, btn_up, btn_down;
82   Widget toggle_show_advanced;
83 
84   Widget shell;
85 
86   struct city *pcity;
87   int global_worklist_id;
88 
89   void *parent_data;
90   WorklistOkCallback ok_callback;
91   WorklistCancelCallback cancel_callback;
92 
93   CONST_FOR_XAW_LIST_CHANGE char *worklist_names_ptrs[MAX_LEN_WORKLIST+1];
94   char worklist_names[MAX_LEN_WORKLIST][200];
95   int worklist_ids[MAX_LEN_WORKLIST];
96   CONST_FOR_XAW_LIST_CHANGE char *worklist_avail_names_ptrs[B_LAST + 1 +U_LAST + 1 + MAX_NUM_WORKLISTS + 1 + 1];
97   char worklist_avail_names[B_LAST+1+U_LAST+1+MAX_NUM_WORKLISTS+1][200];
98   int worklist_avail_ids[B_LAST+1+U_LAST+1+MAX_NUM_WORKLISTS+1];
99   int worklist_avail_num_improvements;
100   int worklist_avail_num_targets;
101 };
102 #define WORKLIST_END (-1)
103 
104 
105 static Widget worklist_report_shell = NULL;
106 static struct worklist_report_dialog *report_dialog;
107 
108 
109 static int uni_id(const struct worklist *pwl, int wlinx);
110 
111 static void worklist_id_to_name(char buf[],
112 				struct universal production,
113 				struct city *pcity);
114 
115 static void rename_worklist_callback(Widget w, XtPointer client_data,
116 				     XtPointer call_data);
117 static void rename_worklist_sub_callback(Widget w, XtPointer client_data,
118 					 XtPointer call_data);
119 static void insert_worklist_callback(Widget w, XtPointer client_data,
120 				     XtPointer call_data);
121 static void delete_worklist_callback(Widget w, XtPointer client_data,
122 				     XtPointer call_data);
123 static void edit_worklist_callback(Widget w, XtPointer client_data,
124 				   XtPointer call_data);
125 static void commit_player_worklist(struct worklist *pwl, void *data);
126 static void close_worklistreport_callback(Widget w, XtPointer client_data,
127 					  XtPointer call_data);
128 static void populate_worklist_report_list(struct worklist_report_dialog *pdialog);
129 
130 /* Callbacks for the worklist dialog */
131 static void worklist_list_callback(Widget w, XtPointer client_data,
132 				   XtPointer call_data);
133 static void worklist_avail_callback(Widget w, XtPointer client_data,
134 				    XtPointer call_data);
135 static void insert_into_worklist(struct worklist_dialog *pdialog,
136 				 int before, int id);
137 static void worklist_prepend_callback(Widget w, XtPointer client_data,
138 				     XtPointer call_data);
139 static void worklist_insert_callback(Widget w, XtPointer client_data,
140 				     XtPointer call_data);
141 static void worklist_insert_common_callback(struct worklist_dialog *pdialog,
142 					    XawListReturnStruct *retAvail,
143 					    int where);
144 static void worklist_delete_callback(Widget w, XtPointer client_data,
145 				     XtPointer call_data);
146 static void worklist_swap_entries(int i, int j,
147                                   struct worklist_dialog *pdialog);
148 static void worklist_up_callback(Widget w, XtPointer client_data,
149 				 XtPointer call_data);
150 static void worklist_down_callback(Widget w, XtPointer client_data,
151 				   XtPointer call_data);
152 static void worklist_ok_callback(Widget w, XtPointer client_data,
153 				 XtPointer call_data);
154 static void worklist_no_callback(Widget w, XtPointer client_data,
155 				 XtPointer call_data);
156 static void worklist_worklist_help_callback(Widget w, XtPointer client_data,
157 					  XtPointer call_data);
158 static void worklist_avail_help_callback(Widget w, XtPointer client_data,
159 					  XtPointer call_data);
160 static void worklist_show_advanced_callback(Widget w, XtPointer client_data,
161 					  XtPointer call_data);
162 static void worklist_help(struct universal production);
163 static void worklist_populate_worklist(struct worklist_dialog *pdialog);
164 static void worklist_populate_targets(struct worklist_dialog *pdialog);
165 
166 
167 
168 /****************************************************************
169   Bring up the worklist report.
170 *****************************************************************/
popup_worklists_dialog(struct player * pplr)171 void popup_worklists_dialog(struct player *pplr)
172 {
173   Widget wshell, wform, wlabel, wview, button_edit, button_close,
174     button_rename, button_insert, button_delete;
175 /*
176   Position x, y;
177   Dimension width, height;
178 */
179   struct worklist_report_dialog *pdialog;
180 
181   char *dummy_worklist_list[]={
182     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
183     "2",
184     "3",
185     "4",
186     "5",
187     "6",
188     "7",
189     "8",
190     0
191   };
192 
193 
194   pdialog = fc_malloc(sizeof(struct worklist_report_dialog));
195   pdialog->pplr = pplr;
196 
197   /* Report window already open */
198   if (worklist_report_shell)
199     return;
200 
201   I_T(wshell=XtCreatePopupShell("worklistreportdialog",
202 				topLevelShellWidgetClass,
203 				toplevel, NULL, 0));
204 
205   wform=XtVaCreateManagedWidget("dform", formWidgetClass, wshell, NULL);
206 
207   I_L(wlabel=XtVaCreateManagedWidget("dlabel", labelWidgetClass, wform,
208 				     NULL));
209 
210   wview=XtVaCreateManagedWidget("dview", viewportWidgetClass,
211 				wform,
212 				XtNfromVert,
213 				wlabel,
214 				NULL);
215 
216   pdialog->list=XtVaCreateManagedWidget("dlist", listWidgetClass,
217 					wview,
218 					XtNforceColumns, 1,
219 					XtNdefaultColumns,1,
220 					XtNlist,
221 					(XtArgVal)dummy_worklist_list,
222 					XtNverticalList, False,
223 					NULL);
224 
225   button_rename = I_L(XtVaCreateManagedWidget("buttonrename",
226 					      commandWidgetClass,
227 					      wform,
228 					      XtNfromVert,
229 					      wlabel,
230 					      XtNfromHoriz,
231 					      wview,
232 					      NULL));
233 
234   button_insert = I_L(XtVaCreateManagedWidget("buttoninsertwl",
235 					      commandWidgetClass,
236 					      wform,
237 					      XtNfromVert,
238 					      button_rename,
239 					      XtNfromHoriz,
240 					      wview,
241 					      NULL));
242 
243 
244   button_delete = I_L(XtVaCreateManagedWidget("buttondeletewl",
245 					      commandWidgetClass,
246 					      wform,
247 					      XtNfromVert,
248 					      button_insert,
249 					      XtNfromHoriz,
250 					      wview,
251 					      NULL));
252 
253 
254   button_close = I_L(XtVaCreateManagedWidget("buttonclose",
255 					     commandWidgetClass,
256 					     wform,
257 					     XtNfromVert,
258 					     wview,
259 					     NULL));
260 
261   button_edit = I_L(XtVaCreateManagedWidget("buttonedit",
262 					    commandWidgetClass,
263 					    wform,
264 					    XtNfromVert,
265 					    wview,
266 					    XtNfromHoriz,
267 					    button_close,
268 					    NULL));
269 
270   XtAddCallback(button_rename, XtNcallback,
271 		rename_worklist_callback, (XtPointer)pdialog);
272   XtAddCallback(button_insert, XtNcallback,
273 		insert_worklist_callback, (XtPointer)pdialog);
274   XtAddCallback(button_delete, XtNcallback,
275 		delete_worklist_callback, (XtPointer)pdialog);
276   XtAddCallback(button_edit, XtNcallback,
277 		edit_worklist_callback, (XtPointer)pdialog);
278   XtAddCallback(button_close, XtNcallback,
279 		close_worklistreport_callback, (XtPointer)pdialog);
280 
281 /*
282   XtVaGetValues(toplevel, XtNwidth, &width, XtNheight, &height, NULL);
283   XtTranslateCoords(toplevel, (Position) width/8, (Position) height/8,
284 		    &x, &y);
285   XtVaSetValues(wshell, XtNx, x, XtNy, y, NULL);
286 */
287 
288   xaw_set_relative_position(toplevel, wshell, 10, 10);
289   XtPopup(wshell, XtGrabNone);
290 
291   populate_worklist_report_list(pdialog);
292 
293   XawListChange(pdialog->list, pdialog->worklist_names_ptrs, 0, 0, False);
294 
295   /* force refresh of viewport so the scrollbar is added.
296    * Buggy sun athena requires this */
297   XtVaSetValues(wview, XtNforceBars, True, NULL);
298 
299   worklist_report_shell = wshell;
300   report_dialog = pdialog;
301 }
302 
303 
304 
305 /*************************************************************************
306   Bring up a dialog box to edit the given worklist.  If pcity is
307   non-NULL, then use pcity to determine the set of units and improvements
308   that can be made.  Otherwise, just list everything that technology
309   will allow.
310 *************************************************************************/
popup_worklist(struct city * pcity,struct global_worklist * pgwl,Widget parent,void * parent_data,WorklistOkCallback ok_cb,WorklistCancelCallback cancel_cb)311 Widget popup_worklist(struct city *pcity, struct global_worklist *pgwl,
312 		      Widget parent, void *parent_data,
313 		      WorklistOkCallback ok_cb,
314 		      WorklistCancelCallback cancel_cb)
315 {
316   struct worklist_dialog *pdialog;
317 
318   Widget cshell, cform;
319   Widget aform;
320   Widget worklist_label, avail_label, show_advanced_label;
321   Widget worklist_view, avail_view;
322   Widget button_form, button_ok, button_cancel, button_worklist_help,
323     button_avail_help;
324 
325   char *dummy_worklist[]={
326     "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
327     "2",
328     "3",
329     "4",
330     "5",
331     "6",
332     "7",
333     "8",
334     "9",
335     0
336   };
337 
338 
339   pdialog = fc_malloc(sizeof(struct worklist_dialog));
340 
341   pdialog->pcity = pcity;
342   pdialog->global_worklist_id = pgwl ? global_worklist_id(pgwl) : -1;
343   pdialog->shell = parent;
344   pdialog->parent_data = parent_data;
345   pdialog->ok_callback = ok_cb;
346   pdialog->cancel_callback = cancel_cb;
347 
348   XtSetSensitive(parent, False);
349   I_T(cshell=XtCreatePopupShell("worklistdialog", transientShellWidgetClass,
350 				parent, NULL, 0));
351 
352   cform=XtVaCreateManagedWidget("cform", formWidgetClass, cshell, NULL);
353 
354   I_L(worklist_label=XtVaCreateManagedWidget("worklistlabel",
355 					     labelWidgetClass,
356 					     cform,
357 					     NULL));
358 
359   worklist_view=XtVaCreateManagedWidget("wview", viewportWidgetClass,
360 					cform,
361 					XtNfromVert,
362 					worklist_label,
363 					NULL);
364 
365   pdialog->worklist=XtVaCreateManagedWidget("wlist", listWidgetClass,
366 					    worklist_view,
367 					    XtNfromHoriz, NULL,
368 					    XtNfromVert, NULL,
369 					    XtNforceColumns, 1,
370 					    XtNdefaultColumns,1,
371 					    XtNlist,
372 					    (XtArgVal)dummy_worklist,
373 					    XtNverticalList, False,
374 					    NULL);
375 
376   button_form=XtVaCreateManagedWidget("dform", formWidgetClass,
377 				      cform,
378 				      XtNborderWidth, 0,
379 				      XtNfromVert, worklist_label,
380 				      XtNfromHoriz, pdialog->worklist,
381 				      NULL);
382 
383   pdialog->btn_prepend = I_L(XtVaCreateManagedWidget("buttonprepend",
384 						    commandWidgetClass,
385 						    button_form,
386 						    NULL));
387 
388 
389   pdialog->btn_insert = I_L(XtVaCreateManagedWidget("buttoninsert",
390 						    commandWidgetClass,
391 						    button_form,
392 						    XtNfromVert,
393 						    pdialog->btn_prepend,
394 						    NULL));
395 
396 
397   pdialog->btn_delete = I_L(XtVaCreateManagedWidget("buttondelete",
398 						    commandWidgetClass,
399 						    button_form,
400 						    XtNfromVert,
401 						    pdialog->btn_insert,
402 						    NULL));
403 
404 
405   pdialog->btn_up = I_L(XtVaCreateManagedWidget("buttonup",
406 						commandWidgetClass,
407 						button_form,
408 						XtNfromVert,
409 						pdialog->btn_delete,
410 						NULL));
411 
412 
413   pdialog->btn_down = I_L(XtVaCreateManagedWidget("buttondown",
414 						  commandWidgetClass,
415 						  button_form,
416 						  XtNfromVert,
417 						  pdialog->btn_up,
418 						  NULL));
419 
420   aform = XtVaCreateManagedWidget("aform", formWidgetClass,
421 				  cform,
422 				  XtNborderWidth, 0,
423 				  XtNfromHoriz, button_form,
424 				  NULL);
425 
426   I_L(avail_label=XtVaCreateManagedWidget("availlabel", labelWidgetClass,
427 					  aform,
428 					  NULL));
429 
430   avail_view=XtVaCreateManagedWidget("aview", viewportWidgetClass,
431 				aform,
432 				XtNfromVert,
433 				avail_label,
434 				NULL);
435 
436   pdialog->avail=XtVaCreateManagedWidget("alist", listWidgetClass,
437 					 avail_view,
438 					 XtNforceColumns, 1,
439 					 XtNdefaultColumns,1,
440 					 XtNlist,
441 					 (XtArgVal)dummy_worklist,
442 					 XtNverticalList, False,
443 					 NULL);
444 
445 
446 
447   button_ok = I_L(XtVaCreateManagedWidget("buttonok",
448 					  commandWidgetClass,
449 					  cform,
450 					  XtNfromVert,
451 					  worklist_view,
452 					  XtNfromHoriz,
453 					  False,
454 					  NULL));
455 
456   button_cancel = I_L(XtVaCreateManagedWidget("buttoncancel",
457 					      commandWidgetClass,
458 					      cform,
459 					      XtNfromVert,
460 					      worklist_view,
461 					      XtNfromHoriz,
462 					      button_ok,
463 					      NULL));
464 
465   button_worklist_help = I_L(XtVaCreateManagedWidget("buttonworklisthelp",
466 						     commandWidgetClass,
467 						     cform,
468 						     XtNfromVert,
469 						     worklist_view,
470 						     XtNfromHoriz,
471 						     button_cancel,
472 						     NULL));
473 
474   button_avail_help = I_L(XtVaCreateManagedWidget("buttonavailhelp",
475 						   commandWidgetClass,
476 						   aform,
477 						   XtNfromVert,
478 						   avail_view,
479 						   NULL));
480 
481   show_advanced_label = I_L(XtVaCreateManagedWidget("showadvancedlabel",
482 						    labelWidgetClass,
483 						    aform,
484 						    XtNfromVert,
485 						    avail_view,
486 						    XtNfromHoriz,
487 						    button_avail_help,
488 						    NULL));
489 
490   pdialog->toggle_show_advanced = I_L(XtVaCreateManagedWidget("buttonshowadvanced",
491 						     toggleWidgetClass,
492 						     aform,
493 						     XtNfromVert,
494 						     avail_view,
495 						     XtNfromHoriz,
496 						     show_advanced_label,
497 						     XtNstate,
498 						     WORKLIST_CURRENT_TARGETS,
499 						     NULL));
500 
501   XtAddCallback(pdialog->worklist, XtNcallback,
502 		worklist_list_callback, (XtPointer)pdialog);
503   XtAddCallback(pdialog->avail, XtNcallback,
504 		worklist_avail_callback, (XtPointer)pdialog);
505   XtAddCallback(pdialog->btn_prepend, XtNcallback,
506 		worklist_prepend_callback, (XtPointer)pdialog);
507   XtAddCallback(pdialog->btn_insert, XtNcallback,
508 		worklist_insert_callback, (XtPointer)pdialog);
509   XtAddCallback(pdialog->btn_delete, XtNcallback,
510 		worklist_delete_callback, (XtPointer)pdialog);
511   XtAddCallback(pdialog->btn_up, XtNcallback,
512 		worklist_up_callback, (XtPointer)pdialog);
513   XtAddCallback(pdialog->btn_down, XtNcallback,
514 		worklist_down_callback, (XtPointer)pdialog);
515   XtAddCallback(button_ok, XtNcallback,
516 		worklist_ok_callback, (XtPointer)pdialog);
517   XtAddCallback(button_cancel, XtNcallback,
518 		worklist_no_callback, (XtPointer)pdialog);
519   XtAddCallback(button_worklist_help, XtNcallback,
520 		worklist_worklist_help_callback, (XtPointer)pdialog);
521   XtAddCallback(button_avail_help, XtNcallback,
522 		worklist_avail_help_callback, (XtPointer)pdialog);
523   XtAddCallback(pdialog->toggle_show_advanced, XtNcallback,
524 		worklist_show_advanced_callback, (XtPointer)pdialog);
525 
526   XtSetSensitive(pdialog->btn_prepend, False);
527   XtSetSensitive(pdialog->btn_insert, False);
528   XtSetSensitive(pdialog->btn_delete, False);
529   XtSetSensitive(pdialog->btn_up, False);
530   XtSetSensitive(pdialog->btn_down, False);
531 
532   xaw_set_relative_position(parent, cshell, 0, 50);
533   XtPopup(cshell, XtGrabNone);
534 
535   worklist_populate_worklist(pdialog);
536 
537   /* Update the list with the actual data */
538   XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
539 		0, 0, False);
540 
541   /* Fill in the list of available build targets,
542      and set correct label in show-advanced toggle. */
543   worklist_show_advanced_callback(pdialog->toggle_show_advanced,
544 				  (XtPointer)pdialog, NULL);
545 
546   /* force refresh of viewport so the scrollbar is added.
547    * Buggy sun athena requires this */
548   XtVaSetValues(worklist_view, XtNforceBars, True, NULL);
549   XtVaSetValues(avail_view, XtNforceBars, True, NULL);
550 
551   return cshell;
552 }
553 
554 
555 /****************************************************************
556 
557 *****************************************************************/
update_worklist_report_dialog(void)558 void update_worklist_report_dialog(void)
559 {
560   /* If the worklist report is open, force its contents to be
561      update. */
562   if (report_dialog) {
563     populate_worklist_report_list(report_dialog);
564     XawListChange(report_dialog->list,
565 		  report_dialog->worklist_names_ptrs, 0, 0, False);
566   }
567 }
568 
569 /****************************************************************
570   Returns an unique id for element in units + buildings sequence
571 *****************************************************************/
uni_id(const struct worklist * pwl,int inx)572 int uni_id(const struct worklist *pwl, int inx)
573 {
574   if ((inx < 0) || (inx >= worklist_length(pwl))) {
575     return WORKLIST_END;
576   } else if (VUT_UTYPE == pwl->entries[inx].kind) {
577     return utype_number(pwl->entries[inx].value.utype) + B_LAST;
578   } else {
579     return improvement_number(pwl->entries[inx].value.building);
580   }
581 }
582 
583 /****************************************************************
584 
585 *****************************************************************/
worklist_id_to_name(char buf[],struct universal production,struct city * pcity)586 void worklist_id_to_name(char buf[],
587 			 struct universal production,
588 			 struct city *pcity)
589 {
590   if (VUT_UTYPE == production.kind)
591     sprintf(buf, "%s (%d)",
592 	    utype_values_translation(production.value.utype),
593 	    utype_build_shield_cost(production.value.utype));
594   else if (pcity)
595     sprintf(buf, "%s (%d)",
596 	    city_improvement_name_translation(pcity, production.value.building),
597 	    impr_build_shield_cost(production.value.building));
598   else
599     sprintf(buf, "%s (%d)",
600 	    improvement_name_translation(production.value.building),
601 	    impr_build_shield_cost(production.value.building));
602 }
603 
604 
605 
606 /****************************************************************
607 
608 *****************************************************************/
rename_worklist_callback(Widget w,XtPointer client_data,XtPointer call_data)609 void rename_worklist_callback(Widget w, XtPointer client_data,
610 			      XtPointer call_data)
611 {
612   struct worklist_report_dialog *pdialog;
613   XawListReturnStruct *retList;
614 
615   pdialog = (struct worklist_report_dialog *)client_data;
616   retList = XawListShowCurrent(pdialog->list);
617 
618   if (retList->list_index == XAW_LIST_NONE) {
619     return;
620   }
621 
622   pdialog->wl_idx = retList->list_index;
623 
624   input_dialog_create(worklist_report_shell,
625                       "renameworklist",
626                       _("What should the new name be?"),
627                       global_worklist_name(pdialog->worklist_ptr[pdialog->wl_idx]),
628                       rename_worklist_sub_callback,
629                       (XtPointer)pdialog,
630                       rename_worklist_sub_callback,
631                       (XtPointer)NULL);
632 }
633 
634 /****************************************************************
635 
636 *****************************************************************/
rename_worklist_sub_callback(Widget w,XtPointer client_data,XtPointer call_data)637 void rename_worklist_sub_callback(Widget w, XtPointer client_data,
638 				  XtPointer call_data)
639 {
640   struct worklist_report_dialog *pdialog;
641 
642   pdialog = (struct worklist_report_dialog *)client_data;
643 
644   if (pdialog) {
645       global_worklist_set_name(pdialog->worklist_ptr[pdialog->wl_idx],
646                                input_dialog_get_input(w));
647       update_worklist_report_dialog();
648   }
649 
650   input_dialog_destroy(w);
651 }
652 
653 /****************************************************************
654   Create a new worklist.
655 *****************************************************************/
insert_worklist_callback(Widget w,XtPointer client_data,XtPointer call_data)656 void insert_worklist_callback(Widget w, XtPointer client_data,
657 			      XtPointer call_data)
658 {
659   (void) global_worklist_new(_("empty worklist"));
660   update_worklist_report_dialog();
661 }
662 
663 /****************************************************************
664   Remove the current worklist.  This request is made by sliding
665   up all lower worklists to fill in the slot that's being deleted.
666 *****************************************************************/
delete_worklist_callback(Widget w,XtPointer client_data,XtPointer call_data)667 void delete_worklist_callback(Widget w, XtPointer client_data,
668 			      XtPointer call_data)
669 {
670   struct worklist_report_dialog *pdialog;
671   XawListReturnStruct *retList;
672 
673   pdialog = (struct worklist_report_dialog *)client_data;
674   retList = XawListShowCurrent(pdialog->list);
675 
676   if (retList->list_index == XAW_LIST_NONE) {
677     return;
678   }
679 
680   global_worklist_destroy(pdialog->worklist_ptr[pdialog->wl_idx]);
681   update_worklist_report_dialog();
682 }
683 
684 /****************************************************************
685 
686 *****************************************************************/
edit_worklist_callback(Widget w,XtPointer client_data,XtPointer call_data)687 void edit_worklist_callback(Widget w, XtPointer client_data,
688 			    XtPointer call_data)
689 {
690   struct worklist_report_dialog *pdialog;
691   XawListReturnStruct *retList;
692 
693   pdialog = (struct worklist_report_dialog *)client_data;
694   retList = XawListShowCurrent(pdialog->list);
695 
696   if (retList->list_index == XAW_LIST_NONE) {
697     return;
698   }
699 
700   pdialog->wl_idx = retList->list_index;
701 
702   popup_worklist(NULL, pdialog->worklist_ptr[pdialog->wl_idx],
703                  worklist_report_shell,
704                  pdialog, commit_player_worklist, NULL);
705 }
706 
707 /****************************************************************
708   Commit the changes to the worklist for this player.
709 *****************************************************************/
commit_player_worklist(struct worklist * pwl,void * data)710 void commit_player_worklist(struct worklist *pwl, void *data)
711 {
712   struct worklist_report_dialog *pdialog;
713 
714   pdialog = (struct worklist_report_dialog *)data;
715 
716   global_worklist_set(pdialog->worklist_ptr[pdialog->wl_idx], pwl);
717 }
718 
719 /****************************************************************
720 
721 *****************************************************************/
close_worklistreport_callback(Widget w,XtPointer client_data,XtPointer call_data)722 void close_worklistreport_callback(Widget w, XtPointer client_data,
723 				   XtPointer call_data)
724 {
725   XtDestroyWidget(XtParent(XtParent(w)));
726   free(report_dialog);
727   worklist_report_shell = NULL;
728   report_dialog = NULL;
729 }
730 
731 /****************************************************************
732   Fill in the worklist arrays in the pdialog.
733 *****************************************************************/
populate_worklist_report_list(struct worklist_report_dialog * pdialog)734 void populate_worklist_report_list(struct worklist_report_dialog *pdialog)
735 {
736   int n = 0;
737 
738   global_worklists_iterate(pgwl) {
739     if (n >= MAX_NUM_WORKLISTS) {
740       break;
741     }
742     strcpy(pdialog->worklist_names[n], global_worklist_name(pgwl));
743     pdialog->worklist_names_ptrs[n] = pdialog->worklist_names[n];
744     pdialog->worklist_ptr[n] = pgwl;
745     n++;
746   } global_worklists_iterate_end;
747 
748   /* Terminators */
749   pdialog->worklist_names_ptrs[n] = NULL;
750 }
751 
752 
753 
754 /****************************************************************
755   User selected one of the worklist items
756 *****************************************************************/
worklist_list_callback(Widget w,XtPointer client_data,XtPointer call_data)757 void worklist_list_callback(Widget w, XtPointer client_data,
758 			    XtPointer call_data)
759 {
760   XawListReturnStruct *ret;
761   struct worklist_dialog *pdialog;
762 
763   pdialog=(struct worklist_dialog *)client_data;
764 
765   ret = XawListShowCurrent(pdialog->worklist);
766   if (ret->list_index == XAW_LIST_NONE) {
767     /* Deselected */
768     XtSetSensitive(pdialog->btn_delete, False);
769     XtSetSensitive(pdialog->btn_up, False);
770     XtSetSensitive(pdialog->btn_down, False);
771   } else {
772     XtSetSensitive(pdialog->btn_delete, True);
773     XtSetSensitive(pdialog->btn_up, True);
774     XtSetSensitive(pdialog->btn_down, True);
775   }
776 }
777 
778 /****************************************************************
779   User selected one of the available items
780 *****************************************************************/
worklist_avail_callback(Widget w,XtPointer client_data,XtPointer call_data)781 void worklist_avail_callback(Widget w, XtPointer client_data,
782 			    XtPointer call_data)
783 {
784   XawListReturnStruct *ret;
785   struct worklist_dialog *pdialog;
786 
787   pdialog=(struct worklist_dialog *)client_data;
788 
789   ret = XawListShowCurrent(pdialog->avail);
790   if (ret->list_index == XAW_LIST_NONE) {
791     /* Deselected */
792     XtSetSensitive(pdialog->btn_prepend, False);
793     XtSetSensitive(pdialog->btn_insert, False);
794   } else {
795     XtSetSensitive(pdialog->btn_prepend, True);
796     XtSetSensitive(pdialog->btn_insert, True);
797   }
798 }
799 
800 /****************************************************************
801 
802 *****************************************************************/
insert_into_worklist(struct worklist_dialog * pdialog,int before,cid id)803 void insert_into_worklist(struct worklist_dialog *pdialog,
804                           int before, cid id)
805 {
806   int i, first_free;
807   struct universal target = cid_decode(id);
808 
809   /* If this worklist is a city worklist, double check that the city
810      really can (eventually) build the target.  We've made sure that
811      the list of available targets is okay for this city, but a global
812      worklist may try to insert an odd-ball unit or target. */
813   if (pdialog->pcity
814       && !can_city_build_later(pdialog->pcity, &target)) {
815     /* Nope, this city can't build this target, ever.  Don't put it into
816        the worklist. */
817     return;
818   }
819 
820   /* Find the first free element in the worklist */
821   for (first_free = 0; first_free < MAX_LEN_WORKLIST; first_free++) {
822     if (pdialog->worklist_ids[first_free] == WORKLIST_END) {
823       break;
824     }
825   }
826 
827   if (first_free >= MAX_LEN_WORKLIST-1) {
828     /* No room left in the worklist! (remember, we need to keep space
829        open for the WORKLIST_END sentinel.) */
830     return;
831   }
832 
833   if (first_free < before && before != MAX_LEN_WORKLIST) {
834     /* True weirdness. */
835     return;
836   }
837 
838   if (before < MAX_LEN_WORKLIST) {
839     /* Slide all the later elements in the worklist down. */
840     for (i = first_free; i > before; i--) {
841       pdialog->worklist_ids[i] = pdialog->worklist_ids[i-1];
842       strcpy(pdialog->worklist_names[i], pdialog->worklist_names[i-1]);
843       pdialog->worklist_names_ptrs[i] = pdialog->worklist_names[i];
844     }
845   } else {
846     /* Append the new id, not insert. */
847     before = first_free;
848   }
849 
850   first_free++;
851   pdialog->worklist_ids[first_free] = WORKLIST_END;
852   pdialog->worklist_names_ptrs[first_free] = NULL;
853 
854   pdialog->worklist_ids[before] = id;
855 
856   worklist_id_to_name(pdialog->worklist_names[before],
857 		      target, pdialog->pcity);
858   pdialog->worklist_names_ptrs[before] = pdialog->worklist_names[before];
859 }
860 
861 /****************************************************************
862   Insert the selected build target at the head of the worklist.
863 *****************************************************************/
worklist_prepend_callback(Widget w,XtPointer client_data,XtPointer call_data)864 void worklist_prepend_callback(Widget w, XtPointer client_data,
865 			       XtPointer call_data)
866 {
867   struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
868   XawListReturnStruct *retAvail = XawListShowCurrent(pdialog->avail);
869 
870   worklist_insert_common_callback(pdialog, retAvail, 0);
871 
872   if (pdialog->worklist_ids[1] != WORKLIST_END) {
873     XtSetSensitive(pdialog->btn_delete, True);
874     XtSetSensitive(pdialog->btn_up, True);
875     XtSetSensitive(pdialog->btn_down, True);
876   }
877 }
878 
879 /****************************************************************
880   Insert the selected build target into the worklist.
881 *****************************************************************/
worklist_insert_callback(Widget w,XtPointer client_data,XtPointer call_data)882 void worklist_insert_callback(Widget w, XtPointer client_data,
883 			      XtPointer call_data)
884 {
885   struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
886   XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist);
887   XawListReturnStruct *retAvail = XawListShowCurrent(pdialog->avail);
888   int where;
889 
890   /* Insert before some element, or at end? */
891   if (retList->list_index == XAW_LIST_NONE)
892     where = MAX_LEN_WORKLIST;
893   else
894     where = retList->list_index;
895 
896   worklist_insert_common_callback(pdialog, retAvail, where);
897 }
898 
899 /****************************************************************
900   Do the actual UI work of inserting a target into the worklist.
901 *****************************************************************/
worklist_insert_common_callback(struct worklist_dialog * pdialog,XawListReturnStruct * retAvail,int where)902 void worklist_insert_common_callback(struct worklist_dialog *pdialog,
903 				     XawListReturnStruct *retAvail,
904 				     int where)
905 {
906   int target;
907   int i, len;
908   struct universal production;
909 
910   /* Is there anything selected to insert? */
911   if (retAvail->list_index == XAW_LIST_NONE)
912     return;
913 
914   /* Pick out the target and its type. */
915   target = pdialog->worklist_avail_ids[retAvail->list_index];
916 
917   if (retAvail->list_index >= pdialog->worklist_avail_num_targets) {
918     /* target is a global worklist id */
919     /* struct player *pplr = city_owner(pdialog->pcity); */
920     int wl_idx = pdialog->worklist_avail_ids[retAvail->list_index];
921     const struct global_worklist *pgwl = global_worklist_by_id(wl_idx);
922     const struct worklist *pwl = global_worklist_get(pgwl);
923 
924     for (i = 0; i < MAX_LEN_WORKLIST && uni_id(pwl, i) != WORKLIST_END; i++) {
925       insert_into_worklist(pdialog, where, uni_id(pwl, i));
926       if (where < MAX_LEN_WORKLIST)
927 	where++;
928     }
929   } else if (retAvail->list_index >=
930 	     pdialog->worklist_avail_num_improvements) {
931     /* target is a unit */
932     production.kind = VUT_UTYPE;
933     production.value.utype = utype_by_number(target);
934     insert_into_worklist(pdialog, where, cid_encode(production));
935     where++;
936   } else {
937     /* target is an improvement or wonder */
938     production.kind = VUT_IMPROVEMENT;
939     production.value.building = improvement_by_number(target);
940     insert_into_worklist(pdialog, where, cid_encode(production));
941     where++;
942   }
943 
944   /* Update the list with the actual data */
945   XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
946 		0, 0, False);
947 
948   /* How long is the new worklist? */
949   for (len = 0; len < MAX_LEN_WORKLIST; len++)
950     if (pdialog->worklist_ids[len] == WORKLIST_END)
951       break;
952 
953   if (where < len)
954     XawListHighlight(pdialog->worklist, where);
955 }
956 
957 /****************************************************************
958   Remove the selected target in the worklist.
959 *****************************************************************/
worklist_delete_callback(Widget w,XtPointer client_data,XtPointer call_data)960 void worklist_delete_callback(Widget w, XtPointer client_data,
961 			      XtPointer call_data)
962 {
963   struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
964   XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist);
965   int i, j, k;
966 
967   if (retList->list_index == XAW_LIST_NONE)
968     return;
969 
970   k = retList->list_index;
971 
972   /* Find the last element in the worklist */
973   for (i = 0; i < MAX_LEN_WORKLIST; i++)
974     if (pdialog->worklist_ids[i] == WORKLIST_END)
975       break;
976 
977   /* Slide all the later elements in the worklist up. */
978   for (j = k; j < i; j++) {
979     pdialog->worklist_ids[j] = pdialog->worklist_ids[j+1];
980     strcpy(pdialog->worklist_names[j], pdialog->worklist_names[j+1]);
981     pdialog->worklist_names_ptrs[j] = pdialog->worklist_names[j];
982   }
983 
984   i--;
985   pdialog->worklist_ids[i] = WORKLIST_END;
986   pdialog->worklist_names_ptrs[i] = 0;
987 
988   if (i == 0 || k >= i) {
989     XtSetSensitive(pdialog->btn_delete, False);
990     XtSetSensitive(pdialog->btn_up, False);
991     XtSetSensitive(pdialog->btn_down, False);
992   }
993 
994   /* Update the list with the actual data */
995   XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
996 		0, 0, False);
997   if (k < i)
998     XawListHighlight(pdialog->worklist, k);
999 }
1000 
1001 
1002 /****************************************************************
1003   Swap entries at indices i and j with each other
1004 *****************************************************************/
worklist_swap_entries(int i,int j,struct worklist_dialog * pdialog)1005 void worklist_swap_entries(int i, int j, struct worklist_dialog *pdialog)
1006 {
1007   int id;
1008   char name[200];
1009 
1010   id = pdialog->worklist_ids[i];
1011   fc_strlcpy(name, pdialog->worklist_names[i], 200);
1012 
1013   pdialog->worklist_ids[i] = pdialog->worklist_ids[j];
1014   fc_strlcpy(pdialog->worklist_names[i], pdialog->worklist_names[j], 200);
1015   pdialog->worklist_names_ptrs[i] = pdialog->worklist_names[i];
1016 
1017   pdialog->worklist_ids[j] = id;
1018   fc_strlcpy(pdialog->worklist_names[j], name, 200);
1019   pdialog->worklist_names_ptrs[j] = pdialog->worklist_names[j];
1020 }
1021 
1022 /****************************************************************
1023   Swap the selected element with its upward neighbor
1024 *****************************************************************/
worklist_up_callback(Widget w,XtPointer client_data,XtPointer call_data)1025 void worklist_up_callback(Widget w, XtPointer client_data, XtPointer call_data)
1026 {
1027   struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
1028   XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist);
1029 
1030   if (retList->list_index == XAW_LIST_NONE)
1031     return;
1032 
1033   if (retList->list_index == 0)
1034     return;
1035 
1036   worklist_swap_entries(retList->list_index, retList->list_index-1, pdialog);
1037 
1038   XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
1039 		0, 0, False);
1040   XawListHighlight(pdialog->worklist, retList->list_index-1);
1041 }
1042 
1043 /****************************************************************
1044  Swap the selected element with its downward neighbor
1045 *****************************************************************/
worklist_down_callback(Widget w,XtPointer client_data,XtPointer call_data)1046 void worklist_down_callback(Widget w, XtPointer client_data,
1047 			    XtPointer call_data)
1048 {
1049   struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
1050   XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist);
1051 
1052   if (retList->list_index == XAW_LIST_NONE)
1053     return;
1054 
1055   if (retList->list_index == MAX_LEN_WORKLIST-1 ||
1056       pdialog->worklist_ids[retList->list_index+1] == WORKLIST_END)
1057     return;
1058 
1059   worklist_swap_entries(retList->list_index, retList->list_index+1, pdialog);
1060 
1061   XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
1062 		0, 0, False);
1063   XawListHighlight(pdialog->worklist, retList->list_index+1);
1064 }
1065 
1066 /****************************************************************
1067   User wants to save the worklist.
1068 *****************************************************************/
worklist_ok_callback(Widget w,XtPointer client_data,XtPointer call_data)1069 void worklist_ok_callback(Widget w, XtPointer client_data, XtPointer call_data)
1070 {
1071   struct worklist_dialog *pdialog;
1072   struct worklist wl;
1073   struct universal production;
1074   int i;
1075 
1076   pdialog = (struct worklist_dialog *)client_data;
1077 
1078   /* Fill in this worklist with the parameters set in the worklist
1079      dialog. */
1080   worklist_init(&wl);
1081 
1082   for (i = 0; i < MAX_LEN_WORKLIST; i++) {
1083     if (pdialog->worklist_ids[i] == WORKLIST_END) {
1084       continue;
1085     } else if (pdialog->worklist_ids[i] >= B_LAST) {
1086       production.kind = VUT_UTYPE;
1087       production.value.utype = utype_by_number(pdialog->worklist_ids[i] - B_LAST);
1088       worklist_append(&wl, &production);
1089     } else if (pdialog->worklist_ids[i] >= 0) {
1090       production.kind = VUT_IMPROVEMENT;
1091       production.value.building = improvement_by_number(pdialog->worklist_ids[i]);
1092       worklist_append(&wl, &production);
1093     } else {
1094       continue;
1095     }
1096   }
1097 
1098   /* Invoke the dialog's parent-specified callback */
1099   if (pdialog->ok_callback) {
1100     (*pdialog->ok_callback)(&wl, pdialog->parent_data);
1101   }
1102 
1103   /* Cleanup. */
1104   XtDestroyWidget(XtParent(XtParent(w)));
1105   XtSetSensitive(pdialog->shell, TRUE);
1106   free(pdialog);
1107 }
1108 
1109 /****************************************************************
1110   User cancelled from the Worklist dialog.
1111 *****************************************************************/
worklist_no_callback(Widget w,XtPointer client_data,XtPointer call_data)1112 void worklist_no_callback(Widget w, XtPointer client_data, XtPointer call_data)
1113 {
1114   struct worklist_dialog *pdialog;
1115 
1116   pdialog=(struct worklist_dialog *)client_data;
1117 
1118   /* Invoke the dialog's parent-specified callback */
1119   if (pdialog->cancel_callback)
1120     (*pdialog->cancel_callback)(pdialog->parent_data);
1121 
1122   pdialog->worklist = NULL;
1123   XtDestroyWidget(XtParent(XtParent(w)));
1124   XtSetSensitive(pdialog->shell, TRUE);
1125   free(pdialog);
1126 }
1127 
1128 /****************************************************************
1129   User asked for help from the Worklist dialog.  If there's
1130   something highlighted, bring up the help for that item.  Else,
1131   bring up help for improvements.
1132 *****************************************************************/
worklist_worklist_help_callback(Widget w,XtPointer client_data,XtPointer call_data)1133 void worklist_worklist_help_callback(Widget w, XtPointer client_data,
1134 					    XtPointer call_data)
1135 {
1136   struct worklist_dialog *pdialog;
1137   XawListReturnStruct *ret;
1138   struct universal production;
1139 
1140   pdialog=(struct worklist_dialog *)client_data;
1141 
1142   ret = XawListShowCurrent(pdialog->worklist);
1143   if (ret->list_index != XAW_LIST_NONE) {
1144     cid id = pdialog->worklist_ids[ret->list_index];
1145 
1146     production = cid_decode(id);
1147   } else {
1148     production.kind = VUT_NONE;
1149     production.value.building = NULL;
1150   }
1151 
1152   worklist_help(production);
1153 }
1154 
worklist_avail_help_callback(Widget w,XtPointer client_data,XtPointer call_data)1155 void worklist_avail_help_callback(Widget w, XtPointer client_data,
1156 					  XtPointer call_data)
1157 {
1158   struct worklist_dialog *pdialog;
1159   XawListReturnStruct *ret;
1160   struct universal production;
1161 
1162   pdialog=(struct worklist_dialog *)client_data;
1163 
1164   ret = XawListShowCurrent(pdialog->avail);
1165   if(ret->list_index!=XAW_LIST_NONE) {
1166     if (ret->list_index >= pdialog->worklist_avail_num_targets) {
1167       /* target is a global worklist id */
1168       production.kind = VUT_NONE;
1169       production.value.building = NULL;
1170     } else {
1171       production =
1172         universal_by_number((ret->list_index >= pdialog->worklist_avail_num_improvements)
1173                                ? VUT_UTYPE : VUT_IMPROVEMENT,
1174                                pdialog->worklist_avail_ids[ret->list_index]);
1175     }
1176   } else {
1177     production.kind = VUT_NONE;
1178     production.value.building = NULL;
1179   }
1180 
1181   worklist_help(production);
1182 }
1183 
1184 
worklist_help(struct universal production)1185 void worklist_help(struct universal production)
1186 {
1187   if (production.value.building) {
1188     if (VUT_UTYPE == production.kind) {
1189       popup_help_dialog_typed(utype_name_translation(production.value.utype),
1190 					    HELP_UNIT);
1191     } else if (is_great_wonder(production.value.building)) {
1192       popup_help_dialog_typed(improvement_name_translation(production.value.building),
1193 						   HELP_WONDER);
1194     } else {
1195       popup_help_dialog_typed(improvement_name_translation(production.value.building),
1196 						   HELP_IMPROVEMENT);
1197     }
1198   }
1199   else
1200     popup_help_dialog_string(HELP_IMPROVEMENTS_ITEM);
1201 }
1202 
1203 /**************************************************************************
1204   Change the label of the Show Advanced toggle.  Also updates the list
1205   of available targets.
1206 **************************************************************************/
worklist_show_advanced_callback(Widget w,XtPointer client_data,XtPointer call_data)1207 void worklist_show_advanced_callback(Widget w, XtPointer client_data,
1208 					  XtPointer call_data)
1209 {
1210   Boolean b;
1211   struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
1212 
1213   XtVaGetValues(w, XtNstate, &b, NULL);
1214   XtVaSetValues(w, XtNlabel,
1215 		b==WORKLIST_ADVANCED_TARGETS ?
1216 		_("Yes") : _("No"),
1217 		NULL);
1218 
1219   worklist_populate_targets(pdialog);
1220   XawListChange(pdialog->avail, pdialog->worklist_avail_names_ptrs,
1221 		0, 0, False);
1222 }
1223 
1224 
1225 
1226 /****************************************************************
1227   Fill in the worklist arrays in the pdialog.
1228 *****************************************************************/
worklist_populate_worklist(struct worklist_dialog * pdialog)1229 void worklist_populate_worklist(struct worklist_dialog *pdialog)
1230 {
1231   int i, n;
1232   int id;
1233   struct universal target;
1234   const struct worklist *pwl;
1235 
1236   n = 0;
1237   if (pdialog->pcity) {
1238     /* First element is the current build target of the city. */
1239     id = universal_number(&pdialog->pcity->production);
1240 
1241     worklist_id_to_name(pdialog->worklist_names[n],
1242 			pdialog->pcity->production, pdialog->pcity);
1243 
1244     if (VUT_UTYPE == pdialog->pcity->production.kind)
1245       id += B_LAST;
1246     pdialog->worklist_names_ptrs[n] = pdialog->worklist_names[n];
1247     pdialog->worklist_ids[n] = id;
1248     n++;
1249     pwl = &pdialog->pcity->worklist;
1250   } else {
1251     const struct global_worklist *pgwl =
1252       global_worklist_by_id(pdialog->global_worklist_id);
1253 
1254     fc_assert(NULL != pgwl);
1255 
1256     pwl = global_worklist_get(pgwl);
1257   }
1258 
1259   /* Fill in the rest of the worklist list */
1260   for (i = 0; n < MAX_LEN_WORKLIST &&
1261 	 uni_id(pwl, i) != WORKLIST_END; i++, n++) {
1262     worklist_peek_ith(pwl, &target, i);
1263     id = uni_id(pwl, i);
1264 
1265     worklist_id_to_name(pdialog->worklist_names[n],
1266 			target, pdialog->pcity);
1267 
1268     pdialog->worklist_names_ptrs[n] = pdialog->worklist_names[n];
1269     pdialog->worklist_ids[n] = id;
1270   }
1271 
1272   /* Terminators */
1273   pdialog->worklist_names_ptrs[n] = NULL;
1274   while (n != MAX_LEN_WORKLIST)
1275     pdialog->worklist_ids[n++] = WORKLIST_END;
1276 }
1277 
1278 /****************************************************************
1279   Fill in the target arrays in the pdialog.
1280 *****************************************************************/
worklist_populate_targets(struct worklist_dialog * pdialog)1281 void worklist_populate_targets(struct worklist_dialog *pdialog)
1282 {
1283   int n;
1284   Boolean b;
1285   int advanced_tech;
1286   int can_build, can_eventually_build;
1287   struct universal production;
1288 
1289   if (!can_client_issue_orders()) {
1290     return;
1291   }
1292 
1293   n = 0;
1294 
1295   /* Is the worklist limited to just the current targets, or
1296      to any available and future targets? */
1297   XtVaGetValues(pdialog->toggle_show_advanced, XtNstate, &b, NULL);
1298   if (b == WORKLIST_ADVANCED_TARGETS)
1299     advanced_tech = True;
1300   else
1301     advanced_tech = False;
1302 
1303   /*     + First, improvements and Wonders. */
1304   improvement_iterate(pimprove) {
1305     /* Can the player (eventually) build this improvement? */
1306     can_build = can_player_build_improvement_now(client.conn.playing, pimprove);
1307     can_eventually_build = can_player_build_improvement_later(client.conn.playing, pimprove);
1308 
1309     /* If there's a city, can the city build the improvement? */
1310     if (pdialog->pcity) {
1311       can_build = can_build && can_city_build_improvement_now(pdialog->pcity, pimprove);
1312       can_eventually_build = can_eventually_build &&
1313 	can_city_build_improvement_later(pdialog->pcity, pimprove);
1314     }
1315 
1316     if (( advanced_tech && can_eventually_build) ||
1317 	(!advanced_tech && can_build)) {
1318       production.kind = VUT_IMPROVEMENT;
1319       production.value.building = pimprove;
1320       worklist_id_to_name(pdialog->worklist_avail_names[n],
1321 			  production, pdialog->pcity);
1322       pdialog->worklist_avail_names_ptrs[n]=pdialog->worklist_avail_names[n];
1323       pdialog->worklist_avail_ids[n++] = improvement_number(pimprove);
1324     }
1325   } improvement_iterate_end;
1326   pdialog->worklist_avail_num_improvements=n;
1327 
1328   /*     + Second, units. */
1329   unit_type_iterate(punittype) {
1330     /* Can the player (eventually) build this improvement? */
1331     can_build = can_player_build_unit_now(client.conn.playing, punittype);
1332     can_eventually_build = can_player_build_unit_later(client.conn.playing, punittype);
1333 
1334     /* If there's a city, can the city build the improvement? */
1335     if (pdialog->pcity) {
1336       can_build = can_build && can_city_build_unit_now(pdialog->pcity, punittype);
1337       can_eventually_build = can_eventually_build &&
1338 	can_city_build_unit_later(pdialog->pcity, punittype);
1339     }
1340 
1341     if (( advanced_tech && can_eventually_build) ||
1342 	(!advanced_tech && can_build)) {
1343       production.kind = VUT_UTYPE;
1344       production.value.utype = punittype;
1345       worklist_id_to_name(pdialog->worklist_avail_names[n],
1346 			  production, pdialog->pcity);
1347       pdialog->worklist_avail_names_ptrs[n]=pdialog->worklist_avail_names[n];
1348       pdialog->worklist_avail_ids[n++] = utype_number(punittype);
1349     }
1350   } unit_type_iterate_end;
1351 
1352   pdialog->worklist_avail_num_targets=n;
1353 
1354   /*     + Finally, the global worklists. */
1355   if (pdialog->pcity) {
1356     /* Now fill in the global worklists. */
1357     global_worklists_iterate(pgwl) {
1358       sz_strlcpy(pdialog->worklist_avail_names[n],
1359                  global_worklist_name(pgwl));
1360       pdialog->worklist_avail_names_ptrs[n] =
1361         pdialog->worklist_avail_names[n];
1362       pdialog->worklist_avail_ids[n++] = global_worklist_id(pgwl);
1363     } global_worklists_iterate_end;
1364   }
1365 
1366   pdialog->worklist_avail_names_ptrs[n] = NULL;
1367 }
1368