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)
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 ***********************************************************************/
15 #include <fc_config.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>
47 #include "client_main.h"
51 #include "gui_stuff.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
65 struct worklist_report_dialog
{
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
];
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
;
87 int global_worklist_id
;
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
,
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
,
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
,
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
;
177 Dimension width, height;
179 struct worklist_report_dialog
*pdialog
;
181 char *dummy_worklist_list
[]={
182 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
194 pdialog
= fc_malloc(sizeof(struct worklist_report_dialog
));
195 pdialog
->pplr
= pplr
;
197 /* Report window already open */
198 if (worklist_report_shell
)
201 I_T(wshell
=XtCreatePopupShell("worklistreportdialog",
202 topLevelShellWidgetClass
,
205 wform
=XtVaCreateManagedWidget("dform", formWidgetClass
, wshell
, NULL
);
207 I_L(wlabel
=XtVaCreateManagedWidget("dlabel", labelWidgetClass
, wform
,
210 wview
=XtVaCreateManagedWidget("dview", viewportWidgetClass
,
216 pdialog
->list
=XtVaCreateManagedWidget("dlist", listWidgetClass
,
221 (XtArgVal
)dummy_worklist_list
,
222 XtNverticalList
, False
,
225 button_rename
= I_L(XtVaCreateManagedWidget("buttonrename",
234 button_insert
= I_L(XtVaCreateManagedWidget("buttoninsertwl",
244 button_delete
= I_L(XtVaCreateManagedWidget("buttondeletewl",
254 button_close
= I_L(XtVaCreateManagedWidget("buttonclose",
261 button_edit
= I_L(XtVaCreateManagedWidget("buttonedit",
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,
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
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
;
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
,
325 char *dummy_worklist
[]={
326 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
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
,
352 cform
=XtVaCreateManagedWidget("cform", formWidgetClass
, cshell
, NULL
);
354 I_L(worklist_label
=XtVaCreateManagedWidget("worklistlabel",
359 worklist_view
=XtVaCreateManagedWidget("wview", viewportWidgetClass
,
365 pdialog
->worklist
=XtVaCreateManagedWidget("wlist", listWidgetClass
,
372 (XtArgVal
)dummy_worklist
,
373 XtNverticalList
, False
,
376 button_form
=XtVaCreateManagedWidget("dform", formWidgetClass
,
379 XtNfromVert
, worklist_label
,
380 XtNfromHoriz
, pdialog
->worklist
,
383 pdialog
->btn_prepend
= I_L(XtVaCreateManagedWidget("buttonprepend",
389 pdialog
->btn_insert
= I_L(XtVaCreateManagedWidget("buttoninsert",
393 pdialog
->btn_prepend
,
397 pdialog
->btn_delete
= I_L(XtVaCreateManagedWidget("buttondelete",
405 pdialog
->btn_up
= I_L(XtVaCreateManagedWidget("buttonup",
413 pdialog
->btn_down
= I_L(XtVaCreateManagedWidget("buttondown",
420 aform
= XtVaCreateManagedWidget("aform", formWidgetClass
,
423 XtNfromHoriz
, button_form
,
426 I_L(avail_label
=XtVaCreateManagedWidget("availlabel", labelWidgetClass
,
430 avail_view
=XtVaCreateManagedWidget("aview", viewportWidgetClass
,
436 pdialog
->avail
=XtVaCreateManagedWidget("alist", listWidgetClass
,
441 (XtArgVal
)dummy_worklist
,
442 XtNverticalList
, False
,
447 button_ok
= I_L(XtVaCreateManagedWidget("buttonok",
456 button_cancel
= I_L(XtVaCreateManagedWidget("buttoncancel",
465 button_worklist_help
= I_L(XtVaCreateManagedWidget("buttonworklisthelp",
474 button_avail_help
= I_L(XtVaCreateManagedWidget("buttonavailhelp",
481 show_advanced_label
= I_L(XtVaCreateManagedWidget("showadvancedlabel",
490 pdialog
->toggle_show_advanced
= I_L(XtVaCreateManagedWidget("buttonshowadvanced",
498 WORKLIST_CURRENT_TARGETS
,
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
,
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
);
555 /****************************************************************
557 *****************************************************************/
558 void update_worklist_report_dialog(void)
560 /* If the worklist report is open, force its contents to be
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
))) {
576 } else if (VUT_UTYPE
== pwl
->entries
[inx
].kind
) {
577 return utype_number(pwl
->entries
[inx
].value
.utype
) + B_LAST
;
579 return improvement_number(pwl
->entries
[inx
].value
.building
);
583 /****************************************************************
585 *****************************************************************/
586 void worklist_id_to_name(char buf
[],
587 struct universal production
,
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
));
595 sprintf(buf
, "%s (%d)",
596 city_improvement_name_translation(pcity
, production
.value
.building
),
597 impr_build_shield_cost(production
.value
.building
));
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
,
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
) {
622 pdialog
->wl_idx
= retList
->list_index
;
624 input_dialog_create(worklist_report_shell
,
626 _("What should the new name be?"),
627 global_worklist_name(pdialog
->worklist_ptr
[pdialog
->wl_idx
]),
628 rename_worklist_sub_callback
,
630 rename_worklist_sub_callback
,
634 /****************************************************************
636 *****************************************************************/
637 void rename_worklist_sub_callback(Widget w
, XtPointer client_data
,
640 struct worklist_report_dialog
*pdialog
;
642 pdialog
= (struct worklist_report_dialog
*)client_data
;
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
,
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
,
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
) {
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
,
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
) {
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
,
725 XtDestroyWidget(XtParent(XtParent(w
)));
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
)
738 global_worklists_iterate(pgwl
) {
739 if (n
>= MAX_NUM_WORKLISTS
) {
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
;
746 } global_worklists_iterate_end
;
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
,
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
) {
768 XtSetSensitive(pdialog
->btn_delete
, False
);
769 XtSetSensitive(pdialog
->btn_up
, False
);
770 XtSetSensitive(pdialog
->btn_down
, False
);
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
,
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
) {
792 XtSetSensitive(pdialog
->btn_prepend
, False
);
793 XtSetSensitive(pdialog
->btn_insert
, False
);
795 XtSetSensitive(pdialog
->btn_prepend
, True
);
796 XtSetSensitive(pdialog
->btn_insert
, True
);
800 /****************************************************************
802 *****************************************************************/
803 void insert_into_worklist(struct worklist_dialog
*pdialog
,
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. */
814 && !can_city_build_later(pdialog
->pcity
, &target
)) {
815 /* Nope, this city can't build this target, ever. Don't put it into
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
) {
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.) */
833 if (first_free
< before
&& before
!= MAX_LEN_WORKLIST
) {
834 /* True weirdness. */
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
];
846 /* Append the new id, not insert. */
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
,
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
,
885 struct worklist_dialog
*pdialog
= (struct worklist_dialog
*)client_data
;
886 XawListReturnStruct
*retList
= XawListShowCurrent(pdialog
->worklist
);
887 XawListReturnStruct
*retAvail
= XawListShowCurrent(pdialog
->avail
);
890 /* Insert before some element, or at end? */
891 if (retList
->list_index
== XAW_LIST_NONE
)
892 where
= MAX_LEN_WORKLIST
;
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
,
908 struct universal production
;
910 /* Is there anything selected to insert? */
911 if (retAvail
->list_index
== XAW_LIST_NONE
)
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
)
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
));
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
));
944 /* Update the list with the actual data */
945 XawListChange(pdialog
->worklist
, pdialog
->worklist_names_ptrs
,
948 /* How long is the new worklist? */
949 for (len
= 0; len
< MAX_LEN_WORKLIST
; len
++)
950 if (pdialog
->worklist_ids
[len
] == WORKLIST_END
)
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
,
963 struct worklist_dialog
*pdialog
= (struct worklist_dialog
*)client_data
;
964 XawListReturnStruct
*retList
= XawListShowCurrent(pdialog
->worklist
);
967 if (retList
->list_index
== XAW_LIST_NONE
)
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
)
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
];
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
,
998 XawListHighlight(pdialog
->worklist
, k
);
1002 /****************************************************************
1004 *****************************************************************/
1005 void worklist_swap_entries(int i
, int j
, struct worklist_dialog
*pdialog
)
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
)
1033 if (retList
->list_index
== 0)
1036 worklist_swap_entries(retList
->list_index
, retList
->list_index
-1, pdialog
);
1038 XawListChange(pdialog
->worklist
, pdialog
->worklist_names_ptrs
,
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
)
1055 if (retList
->list_index
== MAX_LEN_WORKLIST
-1 ||
1056 pdialog
->worklist_ids
[retList
->list_index
+1] == WORKLIST_END
)
1059 worklist_swap_entries(retList
->list_index
, retList
->list_index
+1, pdialog
);
1061 XawListChange(pdialog
->worklist
, pdialog
->worklist_names_ptrs
,
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
;
1073 struct universal production
;
1076 pdialog
= (struct worklist_dialog
*)client_data
;
1078 /* Fill in this worklist with the parameters set in the worklist
1082 for (i
= 0; i
< MAX_LEN_WORKLIST
; i
++) {
1083 if (pdialog
->worklist_ids
[i
] == WORKLIST_END
) {
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
);
1098 /* Invoke the dialog's parent-specified callback */
1099 if (pdialog
->ok_callback
) {
1100 (*pdialog
->ok_callback
)(&wl
, pdialog
->parent_data
);
1104 XtDestroyWidget(XtParent(XtParent(w
)));
1105 XtSetSensitive(pdialog
->shell
, TRUE
);
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
);
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
);
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
;
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
]);
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
),
1191 } else if (is_great_wonder(production
.value
.building
)) {
1192 popup_help_dialog_typed(improvement_name_translation(production
.value
.building
),
1195 popup_help_dialog_typed(improvement_name_translation(production
.value
.building
),
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
)
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
?
1219 worklist_populate_targets(pdialog
);
1220 XawListChange(pdialog
->avail
, pdialog
->worklist_avail_names_ptrs
,
1226 /****************************************************************
1227 Fill in the worklist arrays in the pdialog.
1228 *****************************************************************/
1229 void worklist_populate_worklist(struct worklist_dialog
*pdialog
)
1233 struct universal target
;
1234 const struct worklist
*pwl
;
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
)
1246 pdialog
->worklist_names_ptrs
[n
] = pdialog
->worklist_names
[n
];
1247 pdialog
->worklist_ids
[n
] = id
;
1249 pwl
= &pdialog
->pcity
->worklist
;
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
;
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
)
1286 int can_build
, can_eventually_build
;
1287 struct universal production
;
1289 if (!can_client_issue_orders()) {
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
;
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
;