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 
21 #include <X11/Intrinsic.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xaw/Form.h>
24 #include <X11/Xaw/Label.h>
25 #include <X11/Xaw/Command.h>
26 #include <X11/Xaw/SimpleMenu.h>
27 #include <X11/Xaw/List.h>
28 #include <X11/Xaw/Viewport.h>
29 #include <X11/Xaw/AsciiText.h>
30 #include <X11/IntrinsicP.h>
31 
32 #include "canvas.h"
33 #include "pixcomm.h"
34 
35 /* utility */
36 #include "fcintl.h"
37 #include "log.h"
38 #include "mem.h"
39 #include "shared.h"
40 #include "support.h"
41 
42 /* common */
43 #include "game.h"
44 #include "map.h"
45 #include "packets.h"
46 #include "player.h"
47 #include "spaceship.h"
48 #include "victory.h"
49 
50 /* client */
51 #include "client_main.h"
52 #include "climisc.h"
53 #include "colors.h"
54 #include "dialogs.h"
55 #include "graphics.h"
56 #include "gui_main.h"
57 #include "gui_stuff.h"
58 #include "helpdlg.h"
59 #include "inputdlg.h"
60 #include "mapctrl.h"
61 #include "mapview.h"
62 #include "repodlgs.h"
63 #include "text.h"
64 #include "tilespec.h"
65 
66 #include "spaceshipdlg.h"
67 
68 struct spaceship_dialog {
69   struct player *pplayer;
70   Widget shell;
71   Widget main_form;
72   Widget player_label;
73   Widget info_label;
74   Widget image_canvas;
75   Widget launch_command;
76   Widget close_command;
77 };
78 
79 #define SPECLIST_TAG dialog
80 #define SPECLIST_TYPE struct spaceship_dialog
81 #include "speclist.h"
82 
83 #define dialog_list_iterate(dialoglist, pdialog) \
84     TYPED_LIST_ITERATE(struct spaceship_dialog, dialoglist, pdialog)
85 #define dialog_list_iterate_end  LIST_ITERATE_END
86 
87 static struct dialog_list *dialog_list = NULL;
88 static bool dialog_list_has_been_initialised = FALSE;
89 
90 struct spaceship_dialog *get_spaceship_dialog(struct player *pplayer);
91 struct spaceship_dialog *create_spaceship_dialog(struct player *pplayer);
92 void close_spaceship_dialog(struct spaceship_dialog *pdialog);
93 
94 void spaceship_dialog_update_image(struct spaceship_dialog *pdialog);
95 void spaceship_dialog_update_info(struct spaceship_dialog *pdialog);
96 
97 void spaceship_close_callback(Widget w, XtPointer client_data, XtPointer call_data);
98 void spaceship_launch_callback(Widget w, XtPointer client_data, XtPointer call_data);
99 
100 /****************************************************************
101 ...
102 *****************************************************************/
get_spaceship_dialog(struct player * pplayer)103 struct spaceship_dialog *get_spaceship_dialog(struct player *pplayer)
104 {
105   if (!dialog_list_has_been_initialised) {
106     dialog_list = dialog_list_new();
107     dialog_list_has_been_initialised = TRUE;
108   }
109 
110   dialog_list_iterate(dialog_list, pdialog) {
111     if (pdialog->pplayer == pplayer) {
112       return pdialog;
113     }
114   } dialog_list_iterate_end;
115 
116   return NULL;
117 }
118 
119 /****************************************************************
120   Refresh (update) the spaceship dialog for the given player.
121 *****************************************************************/
refresh_spaceship_dialog(struct player * pplayer)122 void refresh_spaceship_dialog(struct player *pplayer)
123 {
124   struct spaceship_dialog *pdialog;
125   struct player_spaceship *pship;
126 
127   if (!(pdialog = get_spaceship_dialog(pplayer))) {
128     return;
129   }
130 
131   pship = &(pdialog->pplayer->spaceship);
132 
133   if (victory_enabled(VC_SPACERACE)
134       && pplayer == client.conn.playing
135       && pship->state == SSHIP_STARTED
136       && pship->success_rate > 0) {
137     XtSetSensitive(pdialog->launch_command, TRUE);
138   } else {
139     XtSetSensitive(pdialog->launch_command, FALSE);
140   }
141 
142   spaceship_dialog_update_info(pdialog);
143   spaceship_dialog_update_image(pdialog);
144 }
145 
146 /****************************************************************
147 popup the dialog 10% inside the main-window
148 *****************************************************************/
popup_spaceship_dialog(struct player * pplayer)149 void popup_spaceship_dialog(struct player *pplayer)
150 {
151   struct spaceship_dialog *pdialog;
152 
153   if(!(pdialog=get_spaceship_dialog(pplayer)))
154     pdialog=create_spaceship_dialog(pplayer);
155 
156   xaw_set_relative_position(toplevel, pdialog->shell, 10, 10);
157   XtPopup(pdialog->shell, XtGrabNone);
158 }
159 
160 /****************************************************************
161 popdown the dialog
162 *****************************************************************/
popdown_spaceship_dialog(struct player * pplayer)163 void popdown_spaceship_dialog(struct player *pplayer)
164 {
165   struct spaceship_dialog *pdialog;
166 
167   if((pdialog=get_spaceship_dialog(pplayer)))
168     close_spaceship_dialog(pdialog);
169 }
170 
171 
172 
173 /****************************************************************
174 ...
175 *****************************************************************/
spaceship_image_canvas_expose(Widget w,XEvent * event,Region exposed,void * client_data)176 static void spaceship_image_canvas_expose(Widget w, XEvent *event,
177 					  Region exposed, void *client_data)
178 {
179   struct spaceship_dialog *pdialog;
180 
181   pdialog=(struct spaceship_dialog *)client_data;
182   spaceship_dialog_update_image(pdialog);
183 }
184 
185 
186 /****************************************************************
187 ...
188 *****************************************************************/
create_spaceship_dialog(struct player * pplayer)189 struct spaceship_dialog *create_spaceship_dialog(struct player *pplayer)
190 {
191   struct spaceship_dialog *pdialog;
192   int ss_w, ss_h;
193 
194   pdialog=fc_malloc(sizeof(struct spaceship_dialog));
195   pdialog->pplayer=pplayer;
196 
197   pdialog->shell=XtVaCreatePopupShell(player_name(pplayer),
198 				      topLevelShellWidgetClass,
199 				      toplevel,
200 				      XtNallowShellResize, True,
201 				      NULL);
202 
203   pdialog->main_form=
204     XtVaCreateManagedWidget("spaceshipmainform",
205 			    formWidgetClass,
206 			    pdialog->shell,
207 			    NULL);
208   pdialog->player_label=
209     XtVaCreateManagedWidget("spaceshipplayerlabel",
210 			    labelWidgetClass,
211 			    pdialog->main_form,
212 			    NULL);
213 
214   XtVaSetValues(pdialog->player_label, XtNlabel, (XtArgVal)player_name(pplayer), NULL);
215 
216   get_spaceship_dimensions(&ss_w, &ss_h);
217   pdialog->image_canvas=
218     XtVaCreateManagedWidget("spaceshipimagecanvas",
219 			    xfwfcanvasWidgetClass,
220 			    pdialog->main_form,
221 			    "exposeProc", (XtArgVal)spaceship_image_canvas_expose,
222 			    "exposeProcData", (XtArgVal)pdialog,
223 			    XtNwidth, ss_w,
224 			    XtNheight, ss_h,
225 			    NULL);
226 
227   pdialog->info_label=
228     XtVaCreateManagedWidget("spaceshipinfolabel",
229 			    labelWidgetClass,
230 			    pdialog->main_form,
231 			    NULL);
232 
233 
234   pdialog->close_command=
235     I_L(XtVaCreateManagedWidget("spaceshipclosecommand", commandWidgetClass,
236 				pdialog->main_form, NULL));
237 
238   pdialog->launch_command=
239     I_L(XtVaCreateManagedWidget("spaceshiplaunchcommand", commandWidgetClass,
240 				pdialog->main_form, NULL));
241 
242   XtAddCallback(pdialog->launch_command, XtNcallback, spaceship_launch_callback,
243 		(XtPointer)pdialog);
244 
245   XtAddCallback(pdialog->close_command, XtNcallback, spaceship_close_callback,
246 		(XtPointer)pdialog);
247 
248   dialog_list_prepend(dialog_list, pdialog);
249 
250   XtRealizeWidget(pdialog->shell);
251 
252   refresh_spaceship_dialog(pdialog->pplayer);
253 
254   XSetWMProtocols(display, XtWindow(pdialog->shell), &wm_delete_window, 1);
255   XtOverrideTranslations(pdialog->shell,
256     XtParseTranslationTable ("<Message>WM_PROTOCOLS: msg-close-spaceship()"));
257 
258   XtSetKeyboardFocus(pdialog->shell, pdialog->close_command);
259 
260   return pdialog;
261 }
262 
263 /****************************************************************
264 ...
265 *****************************************************************/
spaceship_dialog_update_info(struct spaceship_dialog * pdialog)266 void spaceship_dialog_update_info(struct spaceship_dialog *pdialog)
267 {
268   xaw_set_label(pdialog->info_label,
269 		get_spaceship_descr(&pdialog->pplayer->spaceship));
270 }
271 
272 /****************************************************************
273 ...
274 Should also check connectedness, and show non-connected
275 parts differently.
276 *****************************************************************/
spaceship_dialog_update_image(struct spaceship_dialog * pdialog)277 void spaceship_dialog_update_image(struct spaceship_dialog *pdialog)
278 {
279   struct canvas canvas = {.pixmap = XtWindow(pdialog->image_canvas)};
280 
281   put_spaceship(&canvas, 0, 0, pdialog->pplayer);
282 }
283 
284 
285 /****************************************************************
286 ...
287 *****************************************************************/
close_spaceship_dialog(struct spaceship_dialog * pdialog)288 void close_spaceship_dialog(struct spaceship_dialog *pdialog)
289 {
290   XtDestroyWidget(pdialog->shell);
291   dialog_list_remove(dialog_list, pdialog);
292 
293   free(pdialog);
294 }
295 
296 /****************************************************************
297 ...
298 *****************************************************************/
spaceshipdlg_key_close(Widget w)299 void spaceshipdlg_key_close(Widget w)
300 {
301   spaceshipdlg_msg_close(XtParent(XtParent(w)));
302 }
303 
304 /****************************************************************
305 ...
306 *****************************************************************/
spaceshipdlg_msg_close(Widget w)307 void spaceshipdlg_msg_close(Widget w)
308 {
309   dialog_list_iterate(dialog_list, pdialog) {
310     if (pdialog->shell == w) {
311       close_spaceship_dialog(pdialog);
312       return;
313     }
314   } dialog_list_iterate_end;
315 }
316 
317 
318 /****************************************************************
319 ...
320 *****************************************************************/
spaceship_close_callback(Widget w,XtPointer client_data,XtPointer call_data)321 void spaceship_close_callback(Widget w, XtPointer client_data, XtPointer call_data)
322 {
323   close_spaceship_dialog((struct spaceship_dialog *)client_data);
324 }
325 
326 
327 /****************************************************************
328 ...
329 *****************************************************************/
spaceship_launch_callback(Widget w,XtPointer client_data,XtPointer call_data)330 void spaceship_launch_callback(Widget w, XtPointer client_data,
331 			       XtPointer call_data)
332 {
333   send_packet_spaceship_launch(&client.conn);
334   /* close_spaceship_dialog((struct spaceship_dialog *)client_data); */
335 }
336