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/StringDefs.h>
24 #include <X11/Xaw/Form.h>
25 #include <X11/Xaw/Label.h>
26 #include <X11/Xaw/SimpleMenu.h>
27 #include <X11/Xaw/Command.h>
28 #include <X11/Xaw/List.h>
29 #include <X11/Xaw/Viewport.h>
30 #include <X11/Xaw/Toggle.h>
31
32 /* utility */
33 #include "log.h"
34 #include "mem.h"
35 #include "support.h"
36
37 /* common */
38 #include "game.h"
39 #include "map.h"
40 #include "packets.h"
41 #include "player.h"
42 #include "unit.h"
43 #include "unitlist.h"
44
45 /* client */
46 #include "client_main.h"
47 #include "control.h"
48 #include "goto.h"
49
50 /* gui-xaw */
51 #include "gui_main.h"
52 #include "gui_stuff.h"
53 #include "mapctrl.h"
54 #include "mapview.h"
55
56 #include "gotodlg.h"
57
58 static Widget goto_dialog_shell;
59 static Widget goto_form;
60 static Widget goto_label;
61 static Widget goto_viewport;
62 static Widget goto_list;
63 static Widget goto_center_command;
64 static Widget goto_airlift_command;
65 static Widget goto_all_toggle;
66 static Widget goto_cancel_command;
67
68 void update_goto_dialog(Widget goto_list);
69
70 void goto_cancel_command_callback(Widget w, XtPointer client_data,
71 XtPointer call_data);
72 void goto_goto_command_callback(Widget w, XtPointer client_data,
73 XtPointer call_data);
74 void goto_airlift_command_callback(Widget w, XtPointer client_data,
75 XtPointer call_data);
76 void goto_all_toggle_callback(Widget w, XtPointer client_data,
77 XtPointer call_data);
78 void goto_list_callback(Widget w, XtPointer client_data, XtPointer call_data);
79
80 static void cleanup_goto_list(void);
81
82 static CONST_FOR_XAW_LIST_CHANGE char *dummy_city_list[] = {
83 " ",
84 " ",
85 " ",
86 " ",
87 " ",
88 " ",
89 " ",
90 " ",
91 " ",
92 0
93 };
94
95 static int ncities_total = 0;
96 static char **city_name_ptrs = NULL;
97 static struct tile *original_tile;
98
99
100 /****************************************************************
101 popup the dialog 10% inside the main-window
102 *****************************************************************/
popup_goto_dialog(void)103 void popup_goto_dialog(void)
104 {
105 Position x, y;
106 Dimension width, height;
107 Boolean no_player_cities;
108
109 if (!can_client_issue_orders() || get_num_units_in_focus() == 0) {
110 return;
111 }
112
113 no_player_cities = !(city_list_size(client.conn.playing->cities));
114
115 original_tile = get_center_tile_mapcanvas();
116
117 XtSetSensitive(main_form, FALSE);
118
119 goto_dialog_shell =
120 I_T(XtCreatePopupShell("gotodialog", transientShellWidgetClass,
121 toplevel, NULL, 0));
122
123 goto_form = XtVaCreateManagedWidget("gotoform",
124 formWidgetClass,
125 goto_dialog_shell, NULL);
126
127 goto_label =
128 I_L(XtVaCreateManagedWidget("gotolabel", labelWidgetClass,
129 goto_form, NULL));
130
131 goto_viewport = XtVaCreateManagedWidget("gotoviewport",
132 viewportWidgetClass,
133 goto_form,
134 NULL);
135
136 goto_list = XtVaCreateManagedWidget("gotolist",
137 listWidgetClass,
138 goto_viewport,
139 XtNlist,
140 (XtArgVal)dummy_city_list,
141 NULL);
142
143 goto_center_command =
144 I_L(XtVaCreateManagedWidget("gotocentercommand", commandWidgetClass,
145 goto_form, NULL));
146
147 goto_airlift_command =
148 I_L(XtVaCreateManagedWidget("gotoairliftcommand", commandWidgetClass,
149 goto_form, NULL));
150
151 goto_all_toggle =
152 I_L(XtVaCreateManagedWidget("gotoalltoggle", toggleWidgetClass,
153 goto_form,
154 XtNstate, no_player_cities,
155 XtNsensitive, !no_player_cities,
156 NULL));
157
158 goto_cancel_command =
159 I_L(XtVaCreateManagedWidget("gotocancelcommand", commandWidgetClass,
160 goto_form, NULL));
161
162 XtAddCallback(goto_list, XtNcallback, goto_list_callback, NULL);
163 XtAddCallback(goto_center_command, XtNcallback,
164 goto_goto_command_callback, NULL);
165 XtAddCallback(goto_airlift_command, XtNcallback,
166 goto_airlift_command_callback, NULL);
167 XtAddCallback(goto_all_toggle, XtNcallback,
168 goto_all_toggle_callback, NULL);
169 XtAddCallback(goto_cancel_command, XtNcallback,
170 goto_cancel_command_callback, NULL);
171
172 XtRealizeWidget(goto_dialog_shell);
173
174 update_goto_dialog(goto_list);
175
176 XtVaGetValues(toplevel, XtNwidth, &width, XtNheight, &height, NULL);
177
178 XtTranslateCoords(toplevel, (Position) width/10, (Position) height/10,
179 &x, &y);
180 XtVaSetValues(goto_dialog_shell, XtNx, x, XtNy, y, NULL);
181
182 XtPopup(goto_dialog_shell, XtGrabNone);
183
184 /* force refresh of viewport so the scrollbar is added.
185 * Buggy sun athena requires this */
186 XtVaSetValues(goto_viewport, XtNforceBars, True, NULL);
187 }
188
get_selected_city(void)189 static struct city *get_selected_city(void)
190 {
191 XawListReturnStruct *ret;
192 int len;
193
194 ret=XawListShowCurrent(goto_list);
195 if(ret->list_index==XAW_LIST_NONE)
196 return 0;
197
198 len = strlen(ret->string);
199 if(len>3 && strcmp(ret->string+len-3, "(A)")==0) {
200 char name[MAX_LEN_NAME];
201 fc_strlcpy(name, ret->string, MIN(sizeof(name),len-2));
202 return game_city_by_name(name);
203 }
204 return game_city_by_name(ret->string);
205 }
206
207 /**************************************************************************
208 ...
209 **************************************************************************/
update_goto_dialog(Widget goto_cities)210 void update_goto_dialog(Widget goto_cities)
211 {
212 int j = 0;
213 Boolean all_cities;
214
215 if (!can_client_issue_orders()) {
216 return;
217 }
218
219 XtVaGetValues(goto_all_toggle, XtNstate, &all_cities, NULL);
220
221 cleanup_goto_list();
222
223 if (all_cities) {
224 ncities_total = 0;
225 players_iterate(pplayer) {
226 ncities_total += city_list_size(pplayer->cities);
227 } players_iterate_end;
228 } else {
229 ncities_total = city_list_size(client.conn.playing->cities);
230 }
231
232 city_name_ptrs = fc_malloc(ncities_total*sizeof(char*));
233
234 players_iterate(pplayer) {
235 if (!all_cities && pplayer != client.conn.playing) {
236 continue;
237 }
238 city_list_iterate(pplayer->cities, pcity) {
239 char name[MAX_LEN_NAME+3];
240
241 sz_strlcpy(name, city_name_get(pcity));
242 /* FIXME: should use unit_can_airlift_to(). */
243 if (pcity->airlift) {
244 sz_strlcat(name, "(A)");
245 }
246 city_name_ptrs[j++] = fc_strdup(name);
247 } city_list_iterate_end;
248 } players_iterate_end;
249
250 if (ncities_total) {
251 qsort(city_name_ptrs, ncities_total, sizeof(char *), compare_strings_ptrs);
252 XawListChange(goto_cities, (CONST_FOR_XAW_LIST_CHANGE char **) city_name_ptrs,
253 ncities_total, 0, True);
254 }
255 }
256
257 /**************************************************************************
258 ...
259 **************************************************************************/
popdown_goto_dialog(void)260 static void popdown_goto_dialog(void)
261 {
262 cleanup_goto_list();
263
264 XtDestroyWidget(goto_dialog_shell);
265 XtSetSensitive(main_form, TRUE);
266 }
267
268 /**************************************************************************
269 ...
270 **************************************************************************/
goto_list_callback(Widget w,XtPointer client_data,XtPointer call_data)271 void goto_list_callback(Widget w, XtPointer client_data, XtPointer call_data)
272 {
273 XawListReturnStruct *ret;
274
275 ret = XawListShowCurrent(goto_list);
276
277 if (ret->list_index != XAW_LIST_NONE) {
278 struct city *pdestcity;
279
280 if ((pdestcity = get_selected_city())) {
281 bool can_airlift = FALSE;
282
283 unit_list_iterate(get_units_in_focus(), punit) {
284 if (unit_can_airlift_to(punit, pdestcity)) {
285 can_airlift = TRUE;
286 break;
287 }
288 } unit_list_iterate_end;
289
290 center_tile_mapcanvas(pdestcity->tile);
291 if (can_airlift) {
292 XtSetSensitive(goto_airlift_command, True);
293 return;
294 }
295 }
296 }
297 XtSetSensitive(goto_airlift_command, False);
298 }
299
300 /**************************************************************************
301 ...
302 **************************************************************************/
goto_airlift_command_callback(Widget w,XtPointer client_data,XtPointer call_data)303 void goto_airlift_command_callback(Widget w, XtPointer client_data,
304 XtPointer call_data)
305 {
306 struct city *pdestcity=get_selected_city();
307 if (pdestcity) {
308 unit_list_iterate(get_units_in_focus(), punit) {
309 request_unit_airlift(punit, pdestcity);
310 } unit_list_iterate_end;
311 }
312 popdown_goto_dialog();
313 }
314
315 /**************************************************************************
316 ...
317 **************************************************************************/
goto_all_toggle_callback(Widget w,XtPointer client_data,XtPointer call_data)318 void goto_all_toggle_callback(Widget w, XtPointer client_data,
319 XtPointer call_data)
320 {
321 update_goto_dialog(goto_list);
322 }
323
324 /**************************************************************************
325 ...
326 **************************************************************************/
goto_goto_command_callback(Widget w,XtPointer client_data,XtPointer call_data)327 void goto_goto_command_callback(Widget w, XtPointer client_data,
328 XtPointer call_data)
329 {
330 struct city *pdestcity = get_selected_city();
331 if (pdestcity) {
332 unit_list_iterate(get_units_in_focus(), punit) {
333 send_goto_tile(punit, pdestcity->tile);
334 } unit_list_iterate_end;
335 }
336 popdown_goto_dialog();
337 }
338
339 /**************************************************************************
340 ...
341 **************************************************************************/
goto_cancel_command_callback(Widget w,XtPointer client_data,XtPointer call_data)342 void goto_cancel_command_callback(Widget w, XtPointer client_data,
343 XtPointer call_data)
344 {
345 center_tile_mapcanvas(original_tile);
346 popdown_goto_dialog();
347 }
348
349 /**************************************************************************
350 ...
351 **************************************************************************/
cleanup_goto_list(void)352 static void cleanup_goto_list(void)
353 {
354 int i;
355
356 XawListChange(goto_list, dummy_city_list, 0, 0, FALSE);
357
358 XtSetSensitive(goto_airlift_command, False);
359
360 if(city_name_ptrs) {
361 for(i=0; i<ncities_total; i++) {
362 free(city_name_ptrs[i]);
363 }
364 free(city_name_ptrs);
365 }
366 ncities_total = 0;
367 city_name_ptrs = NULL;
368 }
369