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 
15 #ifdef HAVE_CONFIG_H
16 #include <fc_config.h>
17 #endif
18 
19 #ifdef AUDIO_SDL
20 /* Though it would happily compile without this include,
21  * it is needed for sound to work.
22  * It defines "main" macro to rename our main() so that
23  * it can install SDL's own. */
24 #ifdef SDL2_PLAIN_INCLUDE
25 #include <SDL.h>
26 #elif AUDIO_SDL1_2
27 /* SDL */
28 #include <SDL/SDL.h>
29 #else  /* AUDIO_SDL1_2 */
30 /* SDL2 */
31 #include <SDL2/SDL.h>
32 #endif /* AUDIO_SDL1_2 */
33 #endif
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 #include <X11/Intrinsic.h>
39 #include <X11/StringDefs.h>
40 
41 #include <X11/Xaw/Command.h>
42 #include <X11/Xaw/Form.h>
43 #include <X11/Xaw/Box.h>
44 #include <X11/Xaw/Label.h>
45 #include <X11/Xaw/AsciiText.h>
46 #include <X11/Xaw/Scrollbar.h>
47 #include <X11/Xaw/MenuButton.h>
48 #include <X11/Xaw/SimpleMenu.h>
49 #include <X11/Xaw/Paned.h>
50 #include <X11/Xatom.h>
51 
52 #include "canvas.h"
53 #include "pixcomm.h"
54 
55 /* utility */
56 #include "fc_cmdline.h"
57 #include "fciconv.h"
58 #include "fcintl.h"
59 #include "log.h"
60 #include "support.h"
61 
62 /* common */
63 #include "game.h"
64 #include "government.h"
65 #include "map.h"
66 #include "unitlist.h"
67 #include "version.h"
68 
69 /* client */
70 #include "chatline_common.h"
71 #include "client_main.h"
72 #include "climisc.h"
73 #include "clinet.h"
74 #include "control.h"
75 #include "editgui_g.h"
76 #include "options.h"
77 #include "text.h"
78 #include "tilespec.h"
79 
80 /* gui-xaw */
81 #include "xaw_actions.h"
82 #include "colors.h"
83 #include "dialogs.h"
84 #include "graphics.h"
85 #include "gui_stuff.h"		/* I_SW() */
86 #include "mapview.h"
87 #include "menu.h"
88 #include "optiondlg.h"
89 #include "pages.h"
90 #include "resources.h"
91 
92 #include "gui_main.h"
93 
94 const char *client_string = "gui-xaw";
95 
96 const char * const gui_character_encoding = NULL;
97 const bool gui_use_transliteration = TRUE;
98 
99 static AppResources appResources;
100 
101 /* ids of the units icons in information display: (or 0) */
102 static int unit_ids[MAX_NUM_UNITS_BELOW];
103 
104 static void setup_widgets(void);
105 
106 void fill_econ_label_pixmaps(void);
107 void fill_unit_below_pixmaps(void);
108 
109 /**************************************************************************
110 ...
111 **************************************************************************/
112 XtResource resources[] = {
113     { "GotAppDefFile", "gotAppDefFile", XtRBoolean, sizeof(Boolean),
114       XtOffset(AppResources *,gotAppDefFile), XtRImmediate, (XtPointer)False},
115     { "version", "Version", XtRString, sizeof(String),
116       XtOffset(AppResources *,version), XtRImmediate, (XtPointer)False},
117 #ifdef UNUSED
118     { "log", "Log", XtRString, sizeof(String),
119       XtOffset(AppResources *,logfile), XtRImmediate, (XtPointer)False},
120     { "name", "name", XtRString, sizeof(String),
121       XtOffset(AppResources *,name), XtRImmediate, (XtPointer)False},
122     { "port", "Port", XtRInt, sizeof(int),
123       XtOffset(AppResources *,port), XtRImmediate, (XtPointer)False},
124     { "server", "Server", XtRString, sizeof(String),
125       XtOffset(AppResources *,server), XtRImmediate, (XtPointer)False},
126     { "metaserver", "Metaserver", XtRString, sizeof(String),
127       XtOffset(AppResources *,metaserver), XtRImmediate, (XtPointer)False},
128     { "logLevel", "LogLevel", XtRString, sizeof(String),
129       XtOffset(AppResources *,loglevel_str), XtRImmediate, (XtPointer)False},
130     { "showHelp", "ShowHelp", XtRBoolean, sizeof(Boolean),
131       XtOffset(AppResources *,showHelp), XtRImmediate, (XtPointer)False},
132     { "showVersion", "ShowVersion", XtRBoolean, sizeof(Boolean),
133       XtOffset(AppResources *,showVersion), XtRImmediate, (XtPointer)False},
134     { "tileset", "TileSet", XtRString, sizeof(String),
135       XtOffset(AppResources *,tileset), XtRImmediate, (XtPointer)False},
136 #endif
137 };
138 
139 /**************************************************************************
140 ...
141 **************************************************************************/
142 #ifdef UNUSED
143 static XrmOptionDescRec cmd_options[] = {
144 /* { "-help",    ".showHelp",    XrmoptionNoArg,  (XPointer)"True" },*/
145  { "-log",     ".log",         XrmoptionSepArg, (XPointer)"True" },
146  { "-name",    ".name",        XrmoptionSepArg, (XPointer)"True" },
147  { "-port",    ".port",        XrmoptionSepArg, (XPointer)"True" },
148  { "-server",  ".server",      XrmoptionSepArg, (XPointer)"True" },
149  { "-metaserver",".metaserver",XrmoptionSepArg, (XPointer)"True" },
150  { "-debug",   ".logLevel",    XrmoptionSepArg, (XPointer)"True" },
151  { "-tiles",   ".tileset",     XrmoptionSepArg, (XPointer)"True" },
152 /* { "-version", ".showVersion", XrmoptionNoArg,  (XPointer)"True" },*/
153 /* { "--help",    ".showHelp",    XrmoptionNoArg,  (XPointer)"True" },*/
154  { "--log",     ".log",         XrmoptionSepArg, (XPointer)"True" },
155  { "--name",    ".name",        XrmoptionSepArg, (XPointer)"True" },
156  { "--port",    ".port",        XrmoptionSepArg, (XPointer)"True" },
157  { "--debug",   ".logLevel",    XrmoptionSepArg, (XPointer)"True" },
158  { "--server",  ".server",      XrmoptionSepArg, (XPointer)"True" },
159  { "--metaserver",".metaserver",XrmoptionSepArg, (XPointer)"True" },
160  { "--tiles",   ".tileset",     XrmoptionSepArg, (XPointer)"True" }
161 /* { "--version", ".showVersion", XrmoptionNoArg,  (XPointer)"True" }*/
162 };
163 #endif
164 
165 /**************************************************************************/
166 
167 static void end_turn_callback(Widget w, XtPointer client_data,
168 			      XtPointer call_data);
169 
170 static void timer_callback(XtPointer client_data, XtIntervalId *id);
171 
172 /**************************************************************************/
173 
174 struct game_data {
175   int year;
176   int population;
177   int researchedpoints;
178   int money;
179   int tax, luxurary, research;
180 };
181 
182 /**************************************************************************/
183 
184 Display	*display;
185 int display_depth;
186 int screen_number;
187 enum Display_color_type display_color_type;
188 XtAppContext app_context;
189 
190 /* this GC will be the default one all thru freeciv */
191 GC civ_gc;
192 
193 /* This is for drawing border lines */
194 GC border_line_gc;
195 
196 /* and this one is used for filling with the bg color */
197 GC fill_bg_gc;
198 GC fill_tile_gc;
199 Pixmap gray50,gray25;
200 
201 /* overall font GC                                    */
202 GC font_gc;
203 XFontSet main_font_set;
204 /* productions font GC                                */
205 GC prod_font_gc;
206 XFontSet prod_font_set;
207 
208 Widget toplevel, main_form, menu_form, below_menu_form, left_column_form;
209 Widget bottom_form;
210 Widget map_form;
211 Widget map_canvas;
212 Widget overview_canvas;
213 Widget map_vertical_scrollbar, map_horizontal_scrollbar;
214 Widget inputline_text, outputwindow_text;
215 Widget econ_label[10];
216 Widget turn_done_button;
217 Widget info_command;
218 Widget bulb_label, sun_label, flake_label, government_label, timeout_label;
219 Widget unit_info_label;
220 Widget unit_pix_canvas;
221 Widget unit_below_canvas[MAX_NUM_UNITS_BELOW];
222 Widget main_vpane;
223 Pixmap unit_below_pixmap[MAX_NUM_UNITS_BELOW];
224 Widget more_arrow_label;
225 Window root_window;
226 
227 XtInputId x_input_id;
228 XtIntervalId x_interval_id;
229 Atom wm_delete_window;
230 
231 /****************************************************************************
232   Called by the tileset code to set the font size that should be used to
233   draw the city names and productions.
234 ****************************************************************************/
set_city_names_font_sizes(int my_city_names_font_size,int my_city_productions_font_size)235 void set_city_names_font_sizes(int my_city_names_font_size,
236 			       int my_city_productions_font_size)
237 {
238   log_error("Unimplemented set_city_names_font_sizes.");
239   /* PORTME */
240 }
241 
242 #ifdef UNUSED
243 /**************************************************************************
244 ...
245 **************************************************************************/
246 /* This is used below in ui_main(), in commented out code. */
myerr(Display * p,XErrorEvent * e)247 static int myerr(Display *p, XErrorEvent *e)
248 {
249   puts("error");
250   return 0;
251 }
252 #endif
253 
254 /**************************************************************************
255   Print extra usage information, including one line help on each option,
256   to stderr.
257 **************************************************************************/
print_usage(void)258 static void print_usage(void)
259 {
260   /* add client-specific usage information here */
261   fc_fprintf(stderr,
262             _("This client accepts the standard X toolkit command-line options\n"
263               "after '--'. See the X(7) man page.\n\n"));
264 
265 
266   /* TRANS: No full stop after the URL, could cause confusion. */
267   fc_fprintf(stderr, _("Report bugs at %s\n"), BUG_URL);
268 }
269 
270 /**************************************************************************
271   Handle commandline options specific to this gui
272 **************************************************************************/
parse_options(int argc,char ** argv)273 static void parse_options(int argc, char **argv)
274 {
275   int i = 1;
276 
277   while (i < argc) {
278     if (is_option("--help", argv[i])) {
279       print_usage();
280       exit(EXIT_SUCCESS);
281     } else {
282       fc_fprintf(stderr, _("Unrecognized option: \"%s\"\n"), argv[i]);
283       exit(EXIT_FAILURE);
284     }
285 
286     i++;
287   }
288 }
289 
290 /**************************************************************************
291 ...
292 **************************************************************************/
toplevel_work_proc(XtPointer client_data)293 static Boolean toplevel_work_proc(XtPointer client_data)
294 {
295   /* This will cause the connect dialog to pop-up.
296      We do it here so that the main window exists when that happens,
297      so that the connect dialog can position itself relative to it. */
298   set_client_state(C_S_DISCONNECTED);
299   return (True);
300 }
301 
302 /**************************************************************************
303 ...
304 **************************************************************************/
ui_init(void)305 void ui_init(void)
306 {
307 
308 }
309 
310 /****************************************************************************
311   Extra initializers for client options.
312 ****************************************************************************/
options_extra_init(void)313 void options_extra_init(void)
314 {
315   /* Nothing to do. */
316 }
317 
318 /**************************************************************************
319   Entry point for whole freeciv client program.
320 **************************************************************************/
main(int argc,char ** argv)321 int main(int argc, char **argv)
322 {
323   return client_main(argc, argv);
324 }
325 
326 /**************************************************************************
327   Entry point for GUI specific portion. Called from client_main()
328 **************************************************************************/
ui_main(int argc,char * argv[])329 void ui_main(int argc, char *argv[])
330 {
331   int i;
332   struct sprite *icon;
333   const char *rev_ver;
334 
335   parse_options(argc, argv);
336 
337   /* include later - pain to see the warning at every run */
338   XtSetLanguageProc(NULL, NULL, NULL);
339 
340   toplevel = XtVaAppInitialize(
341 	       &app_context,               /* Application context */
342 	       "Freeciv",                  /* application class name */
343 #ifdef UNUSED
344 	       cmd_options, XtNumber(cmd_options),
345 #else
346 	       NULL, 0,
347 #endif
348 	                                   /* command line option list */
349 	       &argc, argv,                /* command line args */
350 	       &fallback_resources[1],     /* for missing app-defaults file */
351 	       XtNallowShellResize, True,
352 	       NULL);
353 
354   XtGetApplicationResources(toplevel, &appResources, resources,
355                             XtNumber(resources), NULL, 0);
356 
357 /*  XSynchronize(display, 1);
358   XSetErrorHandler(myerr);*/
359 
360   if (appResources.version == NULL)  {
361     log_fatal(_("No version number in resources."));
362     log_fatal(_("You probably have an old (circa V1.0)"
363                 " Freeciv resource file somewhere."));
364     exit(EXIT_FAILURE);
365   }
366 
367   /* TODO: Use capabilities here instead of version numbers */
368   if (0 != strncmp(appResources.version, VERSION_STRING,
369                    strlen(appResources.version))) {
370     log_fatal(_("Game version does not match Resource version."));
371     log_fatal(_("Game version: %s - Resource version: %s"),
372               VERSION_STRING, appResources.version);
373     log_fatal(_("You might have an old Freeciv resourcefile"
374                 " in /usr/lib/X11/app-defaults"));
375     exit(EXIT_FAILURE);
376   }
377 
378   if (!appResources.gotAppDefFile) {
379     log_normal(_("Using fallback resources - which is OK"));
380   }
381 
382   display = XtDisplay(toplevel);
383   screen_number = XScreenNumberOfScreen(XtScreen(toplevel));
384   display_depth = DefaultDepth(display, screen_number);
385   root_window = DefaultRootWindow(display);
386 
387   display_color_type = get_visual();
388 
389   if (display_color_type != COLOR_DISPLAY) {
390     log_fatal(_("Only color displays are supported for now..."));
391     /*    exit(EXIT_FAILURE); */
392   }
393 
394   {
395     XGCValues values;
396     char **missing_charset_list_return;
397     int missing_charset_count_return;
398     char *def_string_return;
399     char *city_names_font, *city_productions_font_name;
400 
401     values.graphics_exposures = False;
402     civ_gc = XCreateGC(display, root_window, GCGraphicsExposures, &values);
403 
404     city_names_font = fc_strdup("-*-*-*-*-*-*-14-*");
405 
406     city_productions_font_name = fc_strdup("-*-*-*-*-*-*-14-*");
407 
408     main_font_set = XCreateFontSet(display, city_names_font,
409 	&missing_charset_list_return,
410 	&missing_charset_count_return,
411 	&def_string_return);
412     if (!main_font_set) {
413       log_fatal(_("Unable to open fontset: %s"), city_names_font);
414       log_fatal(_("Doing 'xset fp rehash' may temporarily solve a problem."));
415       exit(EXIT_FAILURE);
416     }
417     for (i = 0; i < missing_charset_count_return; i++) {
418       log_error(_("Font for charset %s is lacking"),
419                 missing_charset_list_return[i]);
420     }
421     values.foreground = get_color(tileset, COLOR_MAPVIEW_CITYTEXT)->color.pixel;
422     values.background = get_color(tileset, COLOR_MAPVIEW_UNKNOWN)->color.pixel;
423     font_gc= XCreateGC(display, root_window,
424                        GCForeground|GCBackground|GCGraphicsExposures,
425                        &values);
426 
427     prod_font_set = XCreateFontSet(display, city_productions_font_name,
428 	&missing_charset_list_return,
429 	&missing_charset_count_return,
430 	&def_string_return);
431     if (!prod_font_set) {
432       log_fatal(_("Unable to open fontset: %s"), city_productions_font_name);
433       log_fatal(_("Doing 'xset fp rehash' may temporarily solve a problem."));
434       exit(EXIT_FAILURE);
435     }
436     for (i = 0; i < missing_charset_count_return; i++) {
437       log_error(_("Font for charset %s is lacking"),
438                 missing_charset_list_return[i]);
439     }
440     values.foreground = get_color(tileset, COLOR_MAPVIEW_CITYTEXT)->color.pixel;
441     values.background = get_color(tileset, COLOR_MAPVIEW_UNKNOWN)->color.pixel;
442     prod_font_gc= XCreateGC(display, root_window,
443                             GCForeground|GCBackground|GCGraphicsExposures,
444                             &values);
445 
446     values.line_width = BORDER_WIDTH;
447     values.line_style = LineOnOffDash;
448     values.cap_style = CapNotLast;
449     values.join_style = JoinMiter;
450     values.fill_style = FillSolid;
451     border_line_gc = XCreateGC(display, root_window,
452                                GCGraphicsExposures|GCLineWidth|GCLineStyle
453                                |GCCapStyle|GCJoinStyle|GCFillStyle, &values);
454 
455     values.foreground = 0;
456     values.background = 0;
457     fill_bg_gc= XCreateGC(display, root_window,
458                           GCForeground|GCBackground|GCGraphicsExposures,
459                           &values);
460 
461     values.fill_style = FillStippled;
462     fill_tile_gc = XCreateGC(display, root_window,
463                              GCForeground|GCBackground|GCFillStyle|GCGraphicsExposures,
464                              &values);
465   }
466 
467   {
468     char d1[] = {0x03,0x0c,0x03,0x0c};
469     char d2[] = {0x08,0x02,0x08,0x02};
470     gray50 = XCreateBitmapFromData(display, root_window, d1, 4, 4);
471     gray25 = XCreateBitmapFromData(display, root_window, d2, 4, 4);
472   }
473 
474   /* 135 below is rough value (could be more intelligent) --dwp */
475   num_units_below = 135 / tileset_full_tile_width(tileset);
476   num_units_below = MIN(num_units_below, MAX_NUM_UNITS_BELOW);
477   num_units_below = MAX(num_units_below, 1);
478 
479   /* do setup_widgets before loading the rest of graphics to ensure that
480      setup_widgets() has enough colors available:  (on 256-colour systems)
481   */
482   setup_widgets();
483   tileset_init(tileset);
484   tileset_load_tiles(tileset);
485   load_intro_gfx();
486   load_cursors();
487 
488   /* FIXME: what about the mask? */
489   icon = get_icon_sprite(tileset, ICON_FREECIV);
490   XtVaSetValues(toplevel, XtNiconPixmap, icon->pixmap, NULL);
491 
492   XtSetKeyboardFocus(bottom_form, inputline_text);
493   XtSetKeyboardFocus(below_menu_form, map_canvas);
494 
495   InitializeActions(app_context);
496 
497   /* Do this outside setup_widgets() so after tiles are loaded */
498   fill_econ_label_pixmaps();
499 
500   XtAddCallback(map_horizontal_scrollbar, XtNjumpProc,
501                 scrollbar_jump_callback, NULL);
502   XtAddCallback(map_vertical_scrollbar, XtNjumpProc,
503                 scrollbar_jump_callback, NULL);
504   XtAddCallback(map_horizontal_scrollbar, XtNscrollProc,
505                 scrollbar_scroll_callback, NULL);
506   XtAddCallback(map_vertical_scrollbar, XtNscrollProc,
507                 scrollbar_scroll_callback, NULL);
508   XtAddCallback(turn_done_button, XtNcallback, end_turn_callback, NULL);
509 
510   XtAppAddWorkProc(app_context, toplevel_work_proc, NULL);
511 
512   XtRealizeWidget(toplevel);
513 
514   x_interval_id = XtAppAddTimeOut(app_context, TIMER_INTERVAL,
515                                   timer_callback, NULL);
516 
517   init_mapcanvas_and_overview();
518 
519   fill_unit_below_pixmaps();
520 
521   set_indicator_icons(client_research_sprite(),
522                       client_warming_sprite(),
523                       client_cooling_sprite(),
524                       client_government_sprite());
525 
526   wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", 0);
527   XSetWMProtocols(display, XtWindow(toplevel), &wm_delete_window, 1);
528   XtOverrideTranslations(toplevel,
529     XtParseTranslationTable ("<Message>WM_PROTOCOLS: msg-quit-freeciv()"));
530 
531   XtSetSensitive(toplevel, FALSE);
532 
533   rev_ver = fc_git_revision();
534   if (rev_ver != NULL) {
535     char buffer[512];
536 
537     fc_snprintf(buffer, sizeof(buffer), _("Commit: %s"), rev_ver);
538     output_window_append(ftc_client, buffer);
539   }
540 
541   XtAppMainLoop(app_context);
542 
543   start_quitting();
544 }
545 
546 /**************************************************************************
547   Do any necessary UI-specific cleanup
548 **************************************************************************/
ui_exit(void)549 void ui_exit(void)
550 {
551 }
552 
553 /**************************************************************************
554   Return our GUI type
555 **************************************************************************/
get_gui_type(void)556 enum gui_type get_gui_type(void)
557 {
558   return GUI_XAW;
559 }
560 
561 /**************************************************************************
562   Callack for when user clicks one of the unit icons on left hand side
563   (units on same square as current unit).  Use unit_ids[] data and change
564   focus to clicked unit.
565 **************************************************************************/
unit_icon_callback(Widget w,XtPointer client_data,XtPointer call_data)566 static void unit_icon_callback(Widget w, XtPointer client_data,
567 			       XtPointer call_data)
568 {
569   struct unit *punit;
570   int i = (size_t)client_data;
571 
572   fc_assert_ret(i >= 0 && i < num_units_below);
573   if (unit_ids[i] == 0) { /* no unit displayed at this place */
574     return;
575   }
576   punit = game_unit_by_number(unit_ids[i]);
577   if (punit) { /* should always be true at this point */
578     if (unit_owner(punit) == client.conn.playing) {
579       /* may be non-true if alliance */
580       unit_focus_set(punit);
581     }
582   }
583 }
584 
585 /**************************************************************************
586 ...
587 **************************************************************************/
setup_widgets(void)588 void setup_widgets(void)
589 {
590   long i;
591   int econ_label_count=10, econ_label_space=1;
592 
593   main_form = XtVaCreateManagedWidget("mainform", formWidgetClass,
594 				      toplevel,
595 				      NULL);
596 
597   menu_form = XtVaCreateManagedWidget("menuform", formWidgetClass,
598 				      main_form,
599 				      NULL);
600   setup_menus(menu_form);
601 
602 /*
603  main_vpane= XtVaCreateManagedWidget("mainvpane",
604 				      panedWidgetClass,
605 				      main_form,
606 				      NULL);
607 
608   below_menu_form = XtVaCreateManagedWidget("belowmenuform",
609 					    formWidgetClass,
610 					    main_vpane,
611 					    NULL);
612 */
613   below_menu_form = XtVaCreateManagedWidget("belowmenuform",
614 					    formWidgetClass,
615 					    main_form,
616 					    NULL);
617 
618   left_column_form = XtVaCreateManagedWidget("leftcolumnform",
619 					     formWidgetClass,
620 					     below_menu_form,
621 					     NULL);
622 
623   map_form = XtVaCreateManagedWidget("mapform",
624 				     formWidgetClass,
625 				     below_menu_form,
626 				     NULL);
627 
628   bottom_form = XtVaCreateManagedWidget("bottomform",
629 					formWidgetClass,
630 					/*main_vpane,*/ main_form,
631 					NULL);
632 
633   overview_canvas = XtVaCreateManagedWidget("overviewcanvas",
634 					    xfwfcanvasWidgetClass,
635 					    left_column_form,
636 					    "exposeProc",
637 					    (XtArgVal)overview_canvas_expose,
638 					    "exposeProcData",
639 					    (XtArgVal)NULL,
640 					    NULL);
641 
642   info_command = XtVaCreateManagedWidget("infocommand",
643 				       commandWidgetClass,
644 				       left_column_form,
645 				       XtNfromVert,
646 				       (XtArgVal)overview_canvas,
647 				       NULL);
648 
649 
650   /* Don't put the citizens in here yet because not loaded yet */
651   for(i=0;i<econ_label_count;i++)  {
652     econ_label[i] = XtVaCreateManagedWidget("econlabels",
653 					    commandWidgetClass,
654 					    left_column_form,
655 					    XtNwidth, tileset_small_sprite_width(tileset),
656 					    XtNheight, tileset_small_sprite_height(tileset),
657 					    i?XtNfromHoriz:NULL,
658 					    i?econ_label[i-1]:NULL,
659 					    XtNhorizDistance, econ_label_space,
660 					    NULL);
661   }
662 
663   bulb_label = XtVaCreateManagedWidget("bulblabel",
664 				       labelWidgetClass,
665 				       left_column_form,
666 				       NULL);
667 
668   sun_label = XtVaCreateManagedWidget("sunlabel",
669 				      labelWidgetClass,
670 				      left_column_form,
671 				      NULL);
672 
673   flake_label = XtVaCreateManagedWidget("flakelabel",
674 					labelWidgetClass,
675 					left_column_form,
676 					NULL);
677 
678   government_label = XtVaCreateManagedWidget("governmentlabel",
679 					    labelWidgetClass,
680 					    left_column_form,
681 					    NULL);
682 
683   timeout_label = XtVaCreateManagedWidget("timeoutlabel",
684 					  labelWidgetClass,
685 					  left_column_form,
686 					  NULL);
687 
688 
689   turn_done_button =
690     I_LW(XtVaCreateManagedWidget("turndonebutton",
691 				 commandWidgetClass,
692 				 left_column_form,
693 				 XtNwidth, econ_label_count*
694 						(tileset_small_sprite_width(tileset)+econ_label_space),
695 				 NULL));
696 
697 
698   unit_info_label = XtVaCreateManagedWidget("unitinfolabel",
699 					    labelWidgetClass,
700 					    left_column_form,
701 					    NULL);
702 
703   unit_pix_canvas = XtVaCreateManagedWidget("unitpixcanvas",
704 					   pixcommWidgetClass,
705 					   left_column_form,
706 					   XtNwidth, tileset_full_tile_width(tileset),
707 					   XtNheight, tileset_full_tile_height(tileset),
708 					   NULL);
709 
710   for(i=0; i<num_units_below; i++) {
711     char unit_below_name[32];
712     fc_snprintf(unit_below_name, sizeof(unit_below_name),
713 		"unitbelowcanvas%ld", i);
714     unit_below_canvas[i] = XtVaCreateManagedWidget(unit_below_name,
715 						   pixcommWidgetClass,
716 						   left_column_form,
717 						   XtNwidth,
718 						   tileset_full_tile_width(tileset),
719 						   XtNheight,
720 						   tileset_full_tile_height(tileset),
721 						   NULL);
722     XtAddCallback(unit_below_canvas[i], XtNcallback, unit_icon_callback,
723 		  (XtPointer)i);
724   }
725 
726   more_arrow_label =
727     XtVaCreateManagedWidget("morearrowlabel",
728 			    labelWidgetClass,
729 			    left_column_form,
730 			    XtNfromHoriz,
731 			    (XtArgVal)unit_below_canvas[num_units_below-1],
732 			    NULL);
733 
734   map_vertical_scrollbar = XtVaCreateManagedWidget("mapvertiscrbar",
735 						   scrollbarWidgetClass,
736 						   map_form,
737 						   NULL);
738 
739   map_canvas = XtVaCreateManagedWidget("mapcanvas",
740 				       xfwfcanvasWidgetClass,
741 				       map_form,
742 				       "exposeProc",
743 				       (XtArgVal)map_canvas_expose,
744 				       "exposeProcData",
745 				       (XtArgVal)NULL,
746 				       NULL);
747 
748   map_horizontal_scrollbar = XtVaCreateManagedWidget("maphorizscrbar",
749 						     scrollbarWidgetClass,
750 						     map_form,
751 						     NULL);
752 
753 
754 
755   outputwindow_text = I_SW(XtVaCreateManagedWidget("outputwindowtext",
756                                                    asciiTextWidgetClass,
757                                                    bottom_form,
758                                                    NULL));
759 
760 
761   inputline_text= XtVaCreateManagedWidget("inputlinetext",
762 					  asciiTextWidgetClass,
763 					  bottom_form,
764 					  NULL);
765 
766 }
767 
768 /**************************************************************************
769 ...
770 **************************************************************************/
xaw_ui_exit(void)771 void xaw_ui_exit(void)
772 {
773   free_mapcanvas_and_overview();
774   tileset_free_tiles(tileset);
775   client_exit();
776 }
777 
778 /**************************************************************************
779 ...
780 **************************************************************************/
main_show_info_popup(XEvent * event)781 void main_show_info_popup(XEvent *event)
782 {
783   XButtonEvent *ev = (XButtonEvent *)event;
784 
785   if (ev->button == Button1) {
786     Widget  p;
787     Position x, y;
788     Dimension w, h;
789 
790     p = XtCreatePopupShell("popupinfo",
791 			   overrideShellWidgetClass,
792 			   info_command, NULL, 0);
793 
794     XtAddCallback(p, XtNpopdownCallback, destroy_me_callback, NULL);
795 
796     XtVaCreateManagedWidget("fullinfopopuplabel",
797 			    labelWidgetClass,
798 			    p,
799 			    XtNlabel, get_info_label_text_popup(),
800 			    NULL);
801 
802     XtRealizeWidget(p);
803 
804     XtVaGetValues(p, XtNwidth, &w, XtNheight, &h,  NULL);
805     XtTranslateCoords(info_command, ev->x, ev->y, &x, &y);
806     XtVaSetValues(p, XtNx, MAX(0, x - w / 2), XtNy, MAX(0, y - h / 2), NULL);
807     XtPopupSpringLoaded(p);
808   }
809 }
810 
811 /**************************************************************************
812  Update the connected users list at pregame state.
813 **************************************************************************/
real_conn_list_dialog_update(void * unused)814 void real_conn_list_dialog_update(void *unused)
815 {
816   real_update_start_page();
817 }
818 
819 /**************************************************************************
820 ...
821 **************************************************************************/
sound_bell(void)822 void sound_bell(void)
823 {
824   XBell(display, 100);
825 }
826 
827 /**************************************************************************
828 ...
829 **************************************************************************/
get_net_input(XtPointer client_data,int * fid,XtInputId * id)830 static void get_net_input(XtPointer client_data, int *fid, XtInputId *id)
831 {
832   input_from_server(*fid);
833 }
834 
835 /**************************************************************************
836 ...
837 **************************************************************************/
set_wait_for_writable_socket(struct connection * pc,bool socket_writable)838 static void set_wait_for_writable_socket(struct connection *pc,
839 					 bool socket_writable)
840 {
841   static bool previous_state = FALSE;
842 
843   if (previous_state == socket_writable)
844     return;
845   log_debug("set_wait_for_writable_socket(%d)", socket_writable);
846   XtRemoveInput(x_input_id);
847   x_input_id = XtAppAddInput(app_context, client.conn.sock,
848 			     (XtPointer) (XtInputReadMask |
849 					  (socket_writable ?
850 					   XtInputWriteMask : 0) |
851 					  XtInputExceptMask),
852 			     (XtInputCallbackProc) get_net_input, NULL);
853   previous_state = socket_writable;
854 }
855 
856 /**************************************************************************
857  This function is called after the client succesfully
858  has connected to the server
859 **************************************************************************/
add_net_input(int sock)860 void add_net_input(int sock)
861 {
862   x_input_id = XtAppAddInput(app_context, sock,
863 			     (XtPointer) (XtInputReadMask |
864 					  XtInputExceptMask),
865 			     (XtInputCallbackProc) get_net_input, NULL);
866   client.conn.notify_of_writable_data = set_wait_for_writable_socket;
867 }
868 
869 /**************************************************************************
870  This function is called if the client disconnects
871  from the server
872 **************************************************************************/
remove_net_input(void)873 void remove_net_input(void)
874 {
875   XtRemoveInput(x_input_id);
876   XUndefineCursor(display, XtWindow(map_canvas));
877 }
878 
879 /**************************************************************************
880 ...
881 **************************************************************************/
end_turn_callback(Widget w,XtPointer client_data,XtPointer call_data)882 void end_turn_callback(Widget w, XtPointer client_data, XtPointer call_data)
883 {
884   XtSetSensitive(turn_done_button, FALSE);
885 
886   user_ended_turn();
887 }
888 
889 /**************************************************************************
890 ...
891 **************************************************************************/
timer_callback(XtPointer client_data,XtIntervalId * id)892 void timer_callback(XtPointer client_data, XtIntervalId * id)
893 {
894   int msec = real_timer_callback() * 1000;
895 
896   x_interval_id = XtAppAddTimeOut(app_context, msec,
897 				  timer_callback, NULL);
898 }
899 
900 /**************************************************************************
901   Set one of the unit icons in information area based on punit.
902   Use punit==NULL to clear icon.
903   Index 'idx' is -1 for "active unit", or 0 to (num_units_below-1) for
904   units below.  Also updates unit_ids[idx] for idx>=0.
905 **************************************************************************/
set_unit_icon(int idx,struct unit * punit)906 void set_unit_icon(int idx, struct unit *punit)
907 {
908   Widget w;
909 
910   fc_assert_ret(idx >= -1 && idx < num_units_below);
911   if (idx == -1) {
912     w = unit_pix_canvas;
913   } else {
914     w = unit_below_canvas[idx];
915     unit_ids[idx] = punit ? punit->id : 0;
916   }
917 
918   XawPixcommClear(w);
919   if (punit) {
920     struct canvas store = {XawPixcommPixmap(w)};
921 
922     put_unit(punit, &store, 1.0, 0, 0);
923     xaw_expose_now(w);
924   }
925 }
926 
927 /**************************************************************************
928   Set the "more arrow" for the unit icons to on(1) or off(0).
929   Maintains a static record of current state to avoid unnecessary redraws.
930   Note initial state should match initial gui setup (off).
931 **************************************************************************/
set_unit_icons_more_arrow(bool onoff)932 void set_unit_icons_more_arrow(bool onoff)
933 {
934   static bool showing = FALSE;
935 
936   if (onoff && !showing) {
937     /* FIXME: what about the mask? */
938     xaw_set_bitmap(more_arrow_label,
939 		   get_arrow_sprite(tileset, ARROW_RIGHT)->pixmap);
940     showing = TRUE;
941   }
942   else if(!onoff && showing) {
943     xaw_set_bitmap(more_arrow_label, None);
944     showing = FALSE;
945   }
946 }
947 
948 /****************************************************************************
949   Called when the set of units in focus (get_units_in_focus()) changes.
950   Standard updates like update_unit_info_label() are handled in the platform-
951   independent code, so some clients will not need to do anything here.
952 ****************************************************************************/
real_focus_units_changed(void)953 void real_focus_units_changed(void)
954 {
955   /* Nothing to do */
956 }
957 
958 struct callback {
959   void (*callback)(void *data);
960   void *data;
961 };
962 
963 /****************************************************************************
964   A wrapper for the callback called through add_idle_callback.
965 ****************************************************************************/
idle_callback_wrapper(XtPointer data)966 static Boolean idle_callback_wrapper(XtPointer data)
967 {
968   struct callback *cb = data;
969 
970   (cb->callback)(cb->data);
971   free(cb);
972   /* return True if we want to remove WorkProc */
973   return True;
974 }
975 
976 /****************************************************************************
977   Enqueue a callback to be called during an idle moment.  The 'callback'
978   function should be called sometimes soon, and passed the 'data' pointer
979   as its data.
980 ****************************************************************************/
add_idle_callback(void (callback)(void *),void * data)981 void add_idle_callback(void (callback)(void *), void *data)
982 {
983   struct callback *cb = fc_malloc(sizeof(*cb));
984 
985   cb->callback = callback;
986   cb->data = data;
987   XtAppAddWorkProc(app_context, idle_callback_wrapper, cb);
988 }
989 
990 /**************************************************************************
991   Called to fill econ_label pixmaps (showing tax/lux/sci rates).
992 
993   It may be called again if the tileset changes.
994 **************************************************************************/
fill_econ_label_pixmaps(void)995 void fill_econ_label_pixmaps(void)
996 {
997   int i;
998   int econ_label_count = 10;
999 
1000   for(i = 0; i < econ_label_count; i++) {
1001     struct sprite *s = i < 5 ? get_tax_sprite(tileset, O_SCIENCE)
1002 			     : get_tax_sprite(tileset, O_GOLD);
1003 
1004     XtVaSetValues(econ_label[i], XtNbitmap,
1005 		  s->pixmap, NULL);
1006     XtAddCallback(econ_label[i], XtNcallback, taxrates_callback,
1007 		  INT_TO_XTPOINTER(i));
1008   }
1009 }
1010 
1011 /**************************************************************************
1012   Called to fill unit_below pixmaps. They are on the left of the
1013   screen that shows all of the inactive units in the current tile.
1014 
1015   It may be called again if the tileset changes.
1016 **************************************************************************/
fill_unit_below_pixmaps(void)1017 void fill_unit_below_pixmaps(void)
1018 {
1019   long i;
1020 
1021   for (i = 0; i < num_units_below; i++) {
1022 /*    XtVaSetValues(unit_below_canvas[i],
1023 		  XtNwidth, tileset_full_tile_width(tileset),
1024 		  XtNheight, tileset_full_tile_height(tileset),
1025 		  NULL);
1026 */    unit_below_pixmap[i] = XCreatePixmap(display, XtWindow(overview_canvas),
1027 					 tileset_full_tile_width(tileset),
1028 					 tileset_full_tile_height(tileset),
1029 					 display_depth);
1030   }
1031 }
1032 
1033 /**************************************************************************
1034   Called when the tileset is changed to reset indicators pixmaps.
1035 **************************************************************************/
reset_econ_label_pixmaps(void)1036 void reset_econ_label_pixmaps(void)
1037 {
1038   fill_econ_label_pixmaps();
1039 }
1040 
1041 /**************************************************************************
1042   Called when the tileset is changed to reset unit pixmaps.
1043 **************************************************************************/
reset_unit_below_pixmaps(void)1044 void reset_unit_below_pixmaps(void)
1045 {
1046   long i;
1047 
1048   for (i = 0; i < num_units_below; i++) {
1049     XFreePixmap(display, unit_below_pixmap[i]);
1050   }
1051   xaw_set_bitmap(more_arrow_label, None);
1052   fill_unit_below_pixmaps();
1053 
1054   set_unit_icons_more_arrow(FALSE);
1055   if (get_num_units_in_focus() == 1) {
1056     set_unit_icon(-1, head_of_units_in_focus());
1057   } else {
1058     set_unit_icon(-1, NULL);
1059   }
1060   update_unit_pix_label(get_units_in_focus());
1061 }
1062 
1063 /****************************************************************************
1064   Assigns focus units to given battlegroup.
1065 ****************************************************************************/
assign_battlegroup(int battlegroup)1066 void assign_battlegroup(int battlegroup)
1067 {
1068   key_unit_assign_battlegroup(battlegroup, FALSE);
1069 }
1070 
1071 /****************************************************************************
1072   Brings given battlegroup into focus.
1073 ****************************************************************************/
select_battlegroup(int battlegroup)1074 void select_battlegroup(int battlegroup)
1075 {
1076   key_unit_select_battlegroup(battlegroup, FALSE);
1077 }
1078 
1079 /****************************************************************************
1080   Adds focus units to given battlegroup
1081   (or removes unit from battlegoup if battlegroup is the same that unit has).
1082 ****************************************************************************/
add_unit_to_battlegroup(int battlegroup)1083 void add_unit_to_battlegroup(int battlegroup)
1084 {
1085   if (NULL != client.conn.playing && can_client_issue_orders()) {
1086     struct unit *punit;
1087 
1088     punit = head_of_units_in_focus();
1089     if (punit && punit->battlegroup == battlegroup) {
1090       /* If top unit already in the same battlegroup, detach it */
1091       unit_change_battlegroup(punit, BATTLEGROUP_NONE);
1092       refresh_unit_mapcanvas(punit, unit_tile(punit), TRUE, FALSE);
1093     } else {
1094       key_unit_assign_battlegroup(battlegroup, TRUE);
1095     }
1096   }
1097 }
1098 
1099 /****************************************************************************
1100   Stub for editor function
1101 ****************************************************************************/
editgui_tileset_changed(void)1102 void editgui_tileset_changed(void)
1103 {}
1104 
1105 /****************************************************************************
1106   Stub for editor function
1107 ****************************************************************************/
editgui_refresh(void)1108 void editgui_refresh(void)
1109 {}
1110 
1111 /****************************************************************************
1112   Stub for editor function
1113 ****************************************************************************/
editgui_popup_properties(const struct tile_list * tiles,int objtype)1114 void editgui_popup_properties(const struct tile_list *tiles, int objtype)
1115 {}
1116 
1117 /****************************************************************************
1118   Stub for editor function
1119 ****************************************************************************/
editgui_popdown_all(void)1120 void editgui_popdown_all(void)
1121 {}
1122 
1123 /****************************************************************************
1124   Stub for editor function
1125 ****************************************************************************/
editgui_notify_object_changed(int objtype,int object_id,bool removal)1126 void editgui_notify_object_changed(int objtype, int object_id, bool removal)
1127 {}
1128 
1129 /****************************************************************************
1130   Stub for editor function
1131 ****************************************************************************/
editgui_notify_object_created(int tag,int id)1132 void editgui_notify_object_created(int tag, int id)
1133 {}
1134 
1135 /**************************************************************************
1136   Updates a gui font style.
1137 **************************************************************************/
gui_update_font(const char * font_name,const char * font_value)1138 void gui_update_font(const char *font_name, const char *font_value)
1139 {
1140   /* PORTME */
1141 }
1142 
1143 /**************************************************************************
1144   Insert build information to help
1145 **************************************************************************/
insert_client_build_info(char * outbuf,size_t outlen)1146 void insert_client_build_info(char *outbuf, size_t outlen)
1147 {
1148   /* PORTME */
1149 }
1150