Removed silencing of gtk warning logs from gtk3.22-client.
[freeciv.git] / client / gui-xaw / wldlg.c
blobe1650112e08bac6871041d49329e62ad1f9ff50f
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
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>
36 /* utility */
37 #include "fcintl.h"
38 #include "log.h"
39 #include "mem.h"
41 /* common */
42 #include "city.h"
43 #include "packets.h"
44 #include "worklist.h"
46 /* client */
47 #include "client_main.h"
48 #include "climisc.h"
50 #include "gui_main.h"
51 #include "gui_stuff.h"
52 #include "helpdlg.h"
53 #include "inputdlg.h"
55 #include "wldlg.h"
57 #define WORKLIST_ADVANCED_TARGETS 1
58 #define WORKLIST_CURRENT_TARGETS 0
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.
65 struct worklist_report_dialog {
66 Widget list;
67 struct player *pplr;
68 char worklist_names[MAX_NUM_WORKLISTS][MAX_LEN_NAME];
69 char *worklist_names_ptrs[MAX_NUM_WORKLISTS+1];
70 struct global_worklist *worklist_ptr[MAX_NUM_WORKLISTS];
71 int wl_idx;
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.
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;
84 Widget shell;
86 struct city *pcity;
87 int global_worklist_id;
89 void *parent_data;
90 WorklistOkCallback ok_callback;
91 WorklistCancelCallback cancel_callback;
93 char *worklist_names_ptrs[MAX_LEN_WORKLIST+1];
94 char worklist_names[MAX_LEN_WORKLIST][200];
95 int worklist_ids[MAX_LEN_WORKLIST];
96 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;
102 #define WORKLIST_END (-1)
105 static Widget worklist_report_shell = NULL;
106 static struct worklist_report_dialog *report_dialog;
109 static int uni_id(const struct worklist *pwl, int wlinx);
111 static void worklist_id_to_name(char buf[],
112 struct universal production,
113 struct city *pcity);
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);
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);
168 /****************************************************************
169 Bring up the worklist report.
170 *****************************************************************/
171 void popup_worklists_dialog(struct player *pplr)
173 Widget wshell, wform, wlabel, wview, button_edit, button_close,
174 button_rename, button_insert, button_delete;
176 Position x, y;
177 Dimension width, height;
179 struct worklist_report_dialog *pdialog;
181 char *dummy_worklist_list[]={
182 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
183 "2",
184 "3",
185 "4",
186 "5",
187 "6",
188 "7",
189 "8",
194 pdialog = fc_malloc(sizeof(struct worklist_report_dialog));
195 pdialog->pplr = pplr;
197 /* Report window already open */
198 if (worklist_report_shell)
199 return;
201 I_T(wshell=XtCreatePopupShell("worklistreportdialog",
202 topLevelShellWidgetClass,
203 toplevel, NULL, 0));
205 wform=XtVaCreateManagedWidget("dform", formWidgetClass, wshell, NULL);
207 I_L(wlabel=XtVaCreateManagedWidget("dlabel", labelWidgetClass, wform,
208 NULL));
210 wview=XtVaCreateManagedWidget("dview", viewportWidgetClass,
211 wform,
212 XtNfromVert,
213 wlabel,
214 NULL);
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);
225 button_rename = I_L(XtVaCreateManagedWidget("buttonrename",
226 commandWidgetClass,
227 wform,
228 XtNfromVert,
229 wlabel,
230 XtNfromHoriz,
231 wview,
232 NULL));
234 button_insert = I_L(XtVaCreateManagedWidget("buttoninsertwl",
235 commandWidgetClass,
236 wform,
237 XtNfromVert,
238 button_rename,
239 XtNfromHoriz,
240 wview,
241 NULL));
244 button_delete = I_L(XtVaCreateManagedWidget("buttondeletewl",
245 commandWidgetClass,
246 wform,
247 XtNfromVert,
248 button_insert,
249 XtNfromHoriz,
250 wview,
251 NULL));
254 button_close = I_L(XtVaCreateManagedWidget("buttonclose",
255 commandWidgetClass,
256 wform,
257 XtNfromVert,
258 wview,
259 NULL));
261 button_edit = I_L(XtVaCreateManagedWidget("buttonedit",
262 commandWidgetClass,
263 wform,
264 XtNfromVert,
265 wview,
266 XtNfromHoriz,
267 button_close,
268 NULL));
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);
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);
288 xaw_set_relative_position(toplevel, wshell, 10, 10);
289 XtPopup(wshell, XtGrabNone);
291 populate_worklist_report_list(pdialog);
293 XawListChange(pdialog->list, pdialog->worklist_names_ptrs, 0, 0, False);
295 /* force refresh of viewport so the scrollbar is added.
296 * Buggy sun athena requires this */
297 XtVaSetValues(wview, XtNforceBars, True, NULL);
299 worklist_report_shell = wshell;
300 report_dialog = pdialog;
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 *************************************************************************/
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)
316 struct worklist_dialog *pdialog;
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;
325 char *dummy_worklist[]={
326 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
327 "2",
328 "3",
329 "4",
330 "5",
331 "6",
332 "7",
333 "8",
334 "9",
339 pdialog = fc_malloc(sizeof(struct worklist_dialog));
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;
348 XtSetSensitive(parent, False);
349 I_T(cshell=XtCreatePopupShell("worklistdialog", transientShellWidgetClass,
350 parent, NULL, 0));
352 cform=XtVaCreateManagedWidget("cform", formWidgetClass, cshell, NULL);
354 I_L(worklist_label=XtVaCreateManagedWidget("worklistlabel",
355 labelWidgetClass,
356 cform,
357 NULL));
359 worklist_view=XtVaCreateManagedWidget("wview", viewportWidgetClass,
360 cform,
361 XtNfromVert,
362 worklist_label,
363 NULL);
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);
376 button_form=XtVaCreateManagedWidget("dform", formWidgetClass,
377 cform,
378 XtNborderWidth, 0,
379 XtNfromVert, worklist_label,
380 XtNfromHoriz, pdialog->worklist,
381 NULL);
383 pdialog->btn_prepend = I_L(XtVaCreateManagedWidget("buttonprepend",
384 commandWidgetClass,
385 button_form,
386 NULL));
389 pdialog->btn_insert = I_L(XtVaCreateManagedWidget("buttoninsert",
390 commandWidgetClass,
391 button_form,
392 XtNfromVert,
393 pdialog->btn_prepend,
394 NULL));
397 pdialog->btn_delete = I_L(XtVaCreateManagedWidget("buttondelete",
398 commandWidgetClass,
399 button_form,
400 XtNfromVert,
401 pdialog->btn_insert,
402 NULL));
405 pdialog->btn_up = I_L(XtVaCreateManagedWidget("buttonup",
406 commandWidgetClass,
407 button_form,
408 XtNfromVert,
409 pdialog->btn_delete,
410 NULL));
413 pdialog->btn_down = I_L(XtVaCreateManagedWidget("buttondown",
414 commandWidgetClass,
415 button_form,
416 XtNfromVert,
417 pdialog->btn_up,
418 NULL));
420 aform = XtVaCreateManagedWidget("aform", formWidgetClass,
421 cform,
422 XtNborderWidth, 0,
423 XtNfromHoriz, button_form,
424 NULL);
426 I_L(avail_label=XtVaCreateManagedWidget("availlabel", labelWidgetClass,
427 aform,
428 NULL));
430 avail_view=XtVaCreateManagedWidget("aview", viewportWidgetClass,
431 aform,
432 XtNfromVert,
433 avail_label,
434 NULL);
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);
447 button_ok = I_L(XtVaCreateManagedWidget("buttonok",
448 commandWidgetClass,
449 cform,
450 XtNfromVert,
451 worklist_view,
452 XtNfromHoriz,
453 False,
454 NULL));
456 button_cancel = I_L(XtVaCreateManagedWidget("buttoncancel",
457 commandWidgetClass,
458 cform,
459 XtNfromVert,
460 worklist_view,
461 XtNfromHoriz,
462 button_ok,
463 NULL));
465 button_worklist_help = I_L(XtVaCreateManagedWidget("buttonworklisthelp",
466 commandWidgetClass,
467 cform,
468 XtNfromVert,
469 worklist_view,
470 XtNfromHoriz,
471 button_cancel,
472 NULL));
474 button_avail_help = I_L(XtVaCreateManagedWidget("buttonavailhelp",
475 commandWidgetClass,
476 aform,
477 XtNfromVert,
478 avail_view,
479 NULL));
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));
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));
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);
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);
532 xaw_set_relative_position(parent, cshell, 0, 50);
533 XtPopup(cshell, XtGrabNone);
535 worklist_populate_worklist(pdialog);
537 /* Update the list with the actual data */
538 XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
539 0, 0, False);
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);
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);
551 return cshell;
555 /****************************************************************
557 *****************************************************************/
558 void update_worklist_report_dialog(void)
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);
569 /****************************************************************
570 Returns an unique id for element in units + buildings sequence
571 *****************************************************************/
572 int uni_id(const struct worklist *pwl, int inx)
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);
583 /****************************************************************
585 *****************************************************************/
586 void worklist_id_to_name(char buf[],
587 struct universal production,
588 struct city *pcity)
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));
606 /****************************************************************
608 *****************************************************************/
609 void rename_worklist_callback(Widget w, XtPointer client_data,
610 XtPointer call_data)
612 struct worklist_report_dialog *pdialog;
613 XawListReturnStruct *retList;
615 pdialog = (struct worklist_report_dialog *)client_data;
616 retList = XawListShowCurrent(pdialog->list);
618 if (retList->list_index == XAW_LIST_NONE) {
619 return;
622 pdialog->wl_idx = retList->list_index;
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);
634 /****************************************************************
636 *****************************************************************/
637 void rename_worklist_sub_callback(Widget w, XtPointer client_data,
638 XtPointer call_data)
640 struct worklist_report_dialog *pdialog;
642 pdialog = (struct worklist_report_dialog *)client_data;
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();
650 input_dialog_destroy(w);
653 /****************************************************************
654 Create a new worklist.
655 *****************************************************************/
656 void insert_worklist_callback(Widget w, XtPointer client_data,
657 XtPointer call_data)
659 (void) global_worklist_new(_("empty worklist"));
660 update_worklist_report_dialog();
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 *****************************************************************/
667 void delete_worklist_callback(Widget w, XtPointer client_data,
668 XtPointer call_data)
670 struct worklist_report_dialog *pdialog;
671 XawListReturnStruct *retList;
673 pdialog = (struct worklist_report_dialog *)client_data;
674 retList = XawListShowCurrent(pdialog->list);
676 if (retList->list_index == XAW_LIST_NONE) {
677 return;
680 global_worklist_destroy(pdialog->worklist_ptr[pdialog->wl_idx]);
681 update_worklist_report_dialog();
684 /****************************************************************
686 *****************************************************************/
687 void edit_worklist_callback(Widget w, XtPointer client_data,
688 XtPointer call_data)
690 struct worklist_report_dialog *pdialog;
691 XawListReturnStruct *retList;
693 pdialog = (struct worklist_report_dialog *)client_data;
694 retList = XawListShowCurrent(pdialog->list);
696 if (retList->list_index == XAW_LIST_NONE) {
697 return;
700 pdialog->wl_idx = retList->list_index;
702 popup_worklist(NULL, pdialog->worklist_ptr[pdialog->wl_idx],
703 worklist_report_shell,
704 pdialog, commit_player_worklist, NULL);
707 /****************************************************************
708 Commit the changes to the worklist for this player.
709 *****************************************************************/
710 void commit_player_worklist(struct worklist *pwl, void *data)
712 struct worklist_report_dialog *pdialog;
714 pdialog = (struct worklist_report_dialog *)data;
716 global_worklist_set(pdialog->worklist_ptr[pdialog->wl_idx], pwl);
719 /****************************************************************
721 *****************************************************************/
722 void close_worklistreport_callback(Widget w, XtPointer client_data,
723 XtPointer call_data)
725 XtDestroyWidget(XtParent(XtParent(w)));
726 free(report_dialog);
727 worklist_report_shell = NULL;
728 report_dialog = NULL;
731 /****************************************************************
732 Fill in the worklist arrays in the pdialog.
733 *****************************************************************/
734 void populate_worklist_report_list(struct worklist_report_dialog *pdialog)
736 int n = 0;
738 global_worklists_iterate(pgwl) {
739 if (n >= MAX_NUM_WORKLISTS) {
740 break;
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;
748 /* Terminators */
749 pdialog->worklist_names_ptrs[n] = NULL;
754 /****************************************************************
755 User selected one of the worklist items
756 *****************************************************************/
757 void worklist_list_callback(Widget w, XtPointer client_data,
758 XtPointer call_data)
760 XawListReturnStruct *ret;
761 struct worklist_dialog *pdialog;
763 pdialog=(struct worklist_dialog *)client_data;
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);
778 /****************************************************************
779 User selected one of the available items
780 *****************************************************************/
781 void worklist_avail_callback(Widget w, XtPointer client_data,
782 XtPointer call_data)
784 XawListReturnStruct *ret;
785 struct worklist_dialog *pdialog;
787 pdialog=(struct worklist_dialog *)client_data;
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);
800 /****************************************************************
802 *****************************************************************/
803 void insert_into_worklist(struct worklist_dialog *pdialog,
804 int before, cid id)
806 int i, first_free;
807 struct universal target = cid_decode(id);
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;
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;
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;
833 if (first_free < before && before != MAX_LEN_WORKLIST) {
834 /* True weirdness. */
835 return;
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];
845 } else {
846 /* Append the new id, not insert. */
847 before = first_free;
850 first_free++;
851 pdialog->worklist_ids[first_free] = WORKLIST_END;
852 pdialog->worklist_names_ptrs[first_free] = NULL;
854 pdialog->worklist_ids[before] = id;
856 worklist_id_to_name(pdialog->worklist_names[before],
857 target, pdialog->pcity);
858 pdialog->worklist_names_ptrs[before] = pdialog->worklist_names[before];
861 /****************************************************************
862 Insert the selected build target at the head of the worklist.
863 *****************************************************************/
864 void worklist_prepend_callback(Widget w, XtPointer client_data,
865 XtPointer call_data)
867 struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
868 XawListReturnStruct *retAvail = XawListShowCurrent(pdialog->avail);
870 worklist_insert_common_callback(pdialog, retAvail, 0);
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);
879 /****************************************************************
880 Insert the selected build target into the worklist.
881 *****************************************************************/
882 void worklist_insert_callback(Widget w, XtPointer client_data,
883 XtPointer call_data)
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;
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;
896 worklist_insert_common_callback(pdialog, retAvail, where);
899 /****************************************************************
900 Do the actual UI work of inserting a target into the worklist.
901 *****************************************************************/
902 void worklist_insert_common_callback(struct worklist_dialog *pdialog,
903 XawListReturnStruct *retAvail,
904 int where)
906 int target;
907 int i, len;
908 struct universal production;
910 /* Is there anything selected to insert? */
911 if (retAvail->list_index == XAW_LIST_NONE)
912 return;
914 /* Pick out the target and its type. */
915 target = pdialog->worklist_avail_ids[retAvail->list_index];
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);
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++;
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++;
944 /* Update the list with the actual data */
945 XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
946 0, 0, False);
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;
953 if (where < len)
954 XawListHighlight(pdialog->worklist, where);
957 /****************************************************************
958 Remove the selected target in the worklist.
959 *****************************************************************/
960 void worklist_delete_callback(Widget w, XtPointer client_data,
961 XtPointer call_data)
963 struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
964 XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist);
965 int i, j, k;
967 if (retList->list_index == XAW_LIST_NONE)
968 return;
970 k = retList->list_index;
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;
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];
984 i--;
985 pdialog->worklist_ids[i] = WORKLIST_END;
986 pdialog->worklist_names_ptrs[i] = 0;
988 if (i == 0 || k >= i) {
989 XtSetSensitive(pdialog->btn_delete, False);
990 XtSetSensitive(pdialog->btn_up, False);
991 XtSetSensitive(pdialog->btn_down, False);
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);
1002 /****************************************************************
1004 *****************************************************************/
1005 void worklist_swap_entries(int i, int j, struct worklist_dialog *pdialog)
1007 int id;
1008 char name[200];
1010 id = pdialog->worklist_ids[i];
1011 strcpy(name, pdialog->worklist_names[i]);
1013 pdialog->worklist_ids[i] = pdialog->worklist_ids[j];
1014 strcpy(pdialog->worklist_names[i], pdialog->worklist_names[j]);
1015 pdialog->worklist_names_ptrs[i] = pdialog->worklist_names[i];
1017 pdialog->worklist_ids[j] = id;
1018 strcpy(pdialog->worklist_names[j], name);
1019 pdialog->worklist_names_ptrs[j] = pdialog->worklist_names[j];
1022 /****************************************************************
1023 Swap the selected element with its upward neighbor
1024 *****************************************************************/
1025 void worklist_up_callback(Widget w, XtPointer client_data, XtPointer call_data)
1027 struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
1028 XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist);
1030 if (retList->list_index == XAW_LIST_NONE)
1031 return;
1033 if (retList->list_index == 0)
1034 return;
1036 worklist_swap_entries(retList->list_index, retList->list_index-1, pdialog);
1038 XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
1039 0, 0, False);
1040 XawListHighlight(pdialog->worklist, retList->list_index-1);
1043 /****************************************************************
1044 Swap the selected element with its downward neighbor
1045 *****************************************************************/
1046 void worklist_down_callback(Widget w, XtPointer client_data,
1047 XtPointer call_data)
1049 struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
1050 XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist);
1052 if (retList->list_index == XAW_LIST_NONE)
1053 return;
1055 if (retList->list_index == MAX_LEN_WORKLIST-1 ||
1056 pdialog->worklist_ids[retList->list_index+1] == WORKLIST_END)
1057 return;
1059 worklist_swap_entries(retList->list_index, retList->list_index+1, pdialog);
1061 XawListChange(pdialog->worklist, pdialog->worklist_names_ptrs,
1062 0, 0, False);
1063 XawListHighlight(pdialog->worklist, retList->list_index+1);
1066 /****************************************************************
1067 User wants to save the worklist.
1068 *****************************************************************/
1069 void worklist_ok_callback(Widget w, XtPointer client_data, XtPointer call_data)
1071 struct worklist_dialog *pdialog;
1072 struct worklist wl;
1073 struct universal production;
1074 int i;
1076 pdialog = (struct worklist_dialog *)client_data;
1078 /* Fill in this worklist with the parameters set in the worklist
1079 dialog. */
1080 worklist_init(&wl);
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;
1098 /* Invoke the dialog's parent-specified callback */
1099 if (pdialog->ok_callback) {
1100 (*pdialog->ok_callback)(&wl, pdialog->parent_data);
1103 /* Cleanup. */
1104 XtDestroyWidget(XtParent(XtParent(w)));
1105 XtSetSensitive(pdialog->shell, TRUE);
1106 free(pdialog);
1109 /****************************************************************
1110 User cancelled from the Worklist dialog.
1111 *****************************************************************/
1112 void worklist_no_callback(Widget w, XtPointer client_data, XtPointer call_data)
1114 struct worklist_dialog *pdialog;
1116 pdialog=(struct worklist_dialog *)client_data;
1118 /* Invoke the dialog's parent-specified callback */
1119 if (pdialog->cancel_callback)
1120 (*pdialog->cancel_callback)(pdialog->parent_data);
1122 pdialog->worklist = NULL;
1123 XtDestroyWidget(XtParent(XtParent(w)));
1124 XtSetSensitive(pdialog->shell, TRUE);
1125 free(pdialog);
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 *****************************************************************/
1133 void worklist_worklist_help_callback(Widget w, XtPointer client_data,
1134 XtPointer call_data)
1136 struct worklist_dialog *pdialog;
1137 XawListReturnStruct *ret;
1138 struct universal production;
1140 pdialog=(struct worklist_dialog *)client_data;
1142 ret = XawListShowCurrent(pdialog->worklist);
1143 if (ret->list_index != XAW_LIST_NONE) {
1144 cid id = pdialog->worklist_ids[ret->list_index];
1146 production = cid_decode(id);
1147 } else {
1148 production.kind = VUT_NONE;
1149 production.value.building = NULL;
1152 worklist_help(production);
1155 void worklist_avail_help_callback(Widget w, XtPointer client_data,
1156 XtPointer call_data)
1158 struct worklist_dialog *pdialog;
1159 XawListReturnStruct *ret;
1160 struct universal production;
1162 pdialog=(struct worklist_dialog *)client_data;
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]);
1176 } else {
1177 production.kind = VUT_NONE;
1178 production.value.building = NULL;
1181 worklist_help(production);
1185 void worklist_help(struct universal production)
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);
1199 else
1200 popup_help_dialog_string(HELP_IMPROVEMENTS_ITEM);
1203 /**************************************************************************
1204 Change the label of the Show Advanced toggle. Also updates the list
1205 of available targets.
1206 **************************************************************************/
1207 void worklist_show_advanced_callback(Widget w, XtPointer client_data,
1208 XtPointer call_data)
1210 Boolean b;
1211 struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data;
1213 XtVaGetValues(w, XtNstate, &b, NULL);
1214 XtVaSetValues(w, XtNlabel,
1215 b==WORKLIST_ADVANCED_TARGETS ?
1216 _("Yes") : _("No"),
1217 NULL);
1219 worklist_populate_targets(pdialog);
1220 XawListChange(pdialog->avail, pdialog->worklist_avail_names_ptrs,
1221 0, 0, False);
1226 /****************************************************************
1227 Fill in the worklist arrays in the pdialog.
1228 *****************************************************************/
1229 void worklist_populate_worklist(struct worklist_dialog *pdialog)
1231 int i, n;
1232 int id;
1233 struct universal target;
1234 const struct worklist *pwl;
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);
1241 worklist_id_to_name(pdialog->worklist_names[n],
1242 pdialog->pcity->production, pdialog->pcity);
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);
1254 fc_assert(NULL != pgwl);
1256 pwl = global_worklist_get(pgwl);
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);
1265 worklist_id_to_name(pdialog->worklist_names[n],
1266 target, pdialog->pcity);
1268 pdialog->worklist_names_ptrs[n] = pdialog->worklist_names[n];
1269 pdialog->worklist_ids[n] = id;
1272 /* Terminators */
1273 pdialog->worklist_names_ptrs[n] = NULL;
1274 while (n != MAX_LEN_WORKLIST)
1275 pdialog->worklist_ids[n++] = WORKLIST_END;
1278 /****************************************************************
1279 Fill in the target arrays in the pdialog.
1280 *****************************************************************/
1281 void worklist_populate_targets(struct worklist_dialog *pdialog)
1283 int n;
1284 Boolean b;
1285 int advanced_tech;
1286 int can_build, can_eventually_build;
1287 struct universal production;
1289 if (!can_client_issue_orders()) {
1290 return;
1293 n = 0;
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;
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);
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);
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);
1325 } improvement_iterate_end;
1326 pdialog->worklist_avail_num_improvements=n;
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);
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);
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);
1350 } unit_type_iterate_end;
1352 pdialog->worklist_avail_num_targets=n;
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;
1366 pdialog->worklist_avail_names_ptrs[n] = NULL;