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 <stdlib.h>
19 
20 #include <gtk/gtk.h>
21 
22 /* utility */
23 #include "fcintl.h"
24 #include "log.h"
25 #include "shared.h"
26 #include "support.h"
27 
28 /* common */
29 #include "game.h"
30 #include "government.h"
31 #include "road.h"
32 #include "unit.h"
33 
34 /* client */
35 #include "client_main.h"
36 #include "clinet.h"
37 #include "connectdlg_common.h"
38 #include "control.h"
39 #include "mapview_common.h"
40 #include "options.h"
41 #include "tilespec.h"
42 
43 /* client/gui-gtk-2.0 */
44 #include "chatline.h"
45 #include "cityrep.h"
46 #include "dialogs.h"
47 #include "editgui.h"
48 #include "editprop.h"
49 #include "finddlg.h"
50 #include "gamedlgs.h"
51 #include "gotodlg.h"
52 #include "gui_main.h"
53 #include "gui_stuff.h"
54 #include "helpdlg.h"
55 #include "mapctrl.h"            /* center_on_unit(). */
56 #include "messagedlg.h"
57 #include "messagewin.h"
58 #include "optiondlg.h"
59 #include "pages.h"
60 #include "plrdlg.h"
61 #include "ratesdlg.h"
62 #include "repodlgs.h"
63 #include "luaconsole.h"
64 #include "spaceshipdlg.h"
65 #include "unitselect.h"
66 #include "wldlg.h"
67 
68 #include "menu.h"
69 
70 #ifndef GTK_STOCK_EDIT
71 #define GTK_STOCK_EDIT NULL
72 #endif
73 
74 static GtkUIManager *ui_manager = NULL;
75 
76 static GtkActionGroup *get_safe_group(void);
77 static GtkActionGroup *get_edit_group(void);
78 static GtkActionGroup *get_unit_group(void);
79 static GtkActionGroup *get_playing_group(void);
80 static GtkActionGroup *get_player_group(void);
81 
82 static void menus_set_active(GtkActionGroup *group,
83                              const gchar *action_name,
84                              gboolean is_active);
85 static void menus_set_sensitive(GtkActionGroup *group,
86                                 const gchar *action_name,
87                                 gboolean is_sensitive);
88 static void menus_set_visible(GtkActionGroup *group,
89                               const gchar *action_name,
90                               gboolean is_visible,
91                               gboolean is_sensitive);
92 
93 static void view_menu_update_sensitivity(void);
94 
95 /****************************************************************
96   Action "CLEAR_CHAT_LOGS" callback.
97 *****************************************************************/
clear_chat_logs_callback(GtkAction * action,gpointer data)98 static void clear_chat_logs_callback(GtkAction *action, gpointer data)
99 {
100   clear_output_window();
101 }
102 
103 /****************************************************************
104   Action "SAVE_CHAT_LOGS" callback.
105 *****************************************************************/
save_chat_logs_callback(GtkAction * action,gpointer data)106 static void save_chat_logs_callback(GtkAction *action, gpointer data)
107 {
108   log_output_window();
109 }
110 
111 /****************************************************************
112   Action "LOCAL_OPTIONS" callback.
113 *****************************************************************/
local_options_callback(GtkAction * action,gpointer data)114 static void local_options_callback(GtkAction *action, gpointer data)
115 {
116   option_dialog_popup(_("Set local options"), client_optset);
117 }
118 
119 /****************************************************************
120   Action "MESSAGE_OPTIONS" callback.
121 *****************************************************************/
message_options_callback(GtkAction * action,gpointer data)122 static void message_options_callback(GtkAction *action, gpointer data)
123 {
124   popup_messageopt_dialog();
125 }
126 
127 /****************************************************************
128   Action "SERVER_OPTIONS" callback.
129 *****************************************************************/
server_options_callback(GtkAction * action,gpointer data)130 static void server_options_callback(GtkAction *action, gpointer data)
131 {
132   option_dialog_popup(_("Game Settings"), server_optset);
133 }
134 
135 /****************************************************************
136   Action "SAVE_OPTIONS" callback.
137 *****************************************************************/
save_options_callback(GtkAction * action,gpointer data)138 static void save_options_callback(GtkAction *action, gpointer data)
139 {
140   options_save(NULL);
141 }
142 
143 /****************************************************************
144   Action "RELOAD_TILESET" callback.
145 *****************************************************************/
reload_tileset_callback(GtkAction * action,gpointer data)146 static void reload_tileset_callback(GtkAction *action, gpointer data)
147 {
148   tilespec_reread(NULL, TRUE, 1.0f);
149 }
150 
151 /****************************************************************
152   Action "SAVE_GAME" callback.
153 *****************************************************************/
save_game_callback(GtkAction * action,gpointer data)154 static void save_game_callback(GtkAction *action, gpointer data)
155 {
156   send_save_game(NULL);
157 }
158 
159 /****************************************************************
160   Action "SAVE_GAME_AS" callback.
161 *****************************************************************/
save_game_as_callback(GtkAction * action,gpointer data)162 static void save_game_as_callback(GtkAction *action, gpointer data)
163 {
164   save_game_dialog_popup();
165 }
166 
167 /****************************************************************************
168   Action "SAVE_MAPIMG" callback.
169 ****************************************************************************/
save_mapimg_callback(GtkAction * action,gpointer data)170 static void save_mapimg_callback(GtkAction *action, gpointer data)
171 {
172   mapimg_client_save(NULL);
173 }
174 
175 /****************************************************************************
176   Action "SAVE_MAPIMG_AS" callback.
177 ****************************************************************************/
save_mapimg_as_callback(GtkAction * action,gpointer data)178 static void save_mapimg_as_callback(GtkAction *action, gpointer data)
179 {
180   save_mapimg_dialog_popup();
181 }
182 
183 /****************************************************************
184   This is the response callback for the dialog with the message:
185   Leaving a local game will end it!
186 ****************************************************************/
leave_local_game_response(GtkWidget * dialog,gint response)187 static void leave_local_game_response(GtkWidget *dialog, gint response)
188 {
189   gtk_widget_destroy(dialog);
190   if (response == GTK_RESPONSE_OK) {
191     /* It might be killed already */
192     if (client.conn.used) {
193       /* It will also kill the server */
194       disconnect_from_server();
195     }
196   }
197 }
198 
199 /****************************************************************
200   Action "LEAVE" callback.
201 *****************************************************************/
leave_callback(GtkAction * action,gpointer data)202 static void leave_callback(GtkAction *action, gpointer data)
203 {
204   if (is_server_running()) {
205     GtkWidget* dialog =
206         gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_WARNING,
207                                GTK_BUTTONS_OK_CANCEL,
208                                _("Leaving a local game will end it!"));
209     setup_dialog(dialog, toplevel);
210     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
211     g_signal_connect(dialog, "response",
212                      G_CALLBACK(leave_local_game_response), NULL);
213     gtk_window_present(GTK_WINDOW(dialog));
214   } else {
215     disconnect_from_server();
216   }
217 }
218 
219 /****************************************************************
220   Action "QUIT" callback.
221 *****************************************************************/
quit_callback(GtkAction * action,gpointer data)222 static void quit_callback(GtkAction *action, gpointer data)
223 {
224   popup_quit_dialog();
225 }
226 
227 /****************************************************************
228   Action "FIND_CITY" callback.
229 *****************************************************************/
find_city_callback(GtkAction * action,gpointer data)230 static void find_city_callback(GtkAction *action, gpointer data)
231 {
232   popup_find_dialog();
233 }
234 
235 /****************************************************************
236   Action "WORKLISTS" callback.
237 *****************************************************************/
worklists_callback(GtkAction * action,gpointer data)238 static void worklists_callback(GtkAction *action, gpointer data)
239 {
240   popup_worklists_report();
241 }
242 
243 /****************************************************************
244   Action "MAP_VIEW" callback.
245 *****************************************************************/
map_view_callback(GtkAction * action,gpointer data)246 static void map_view_callback(GtkAction *action, gpointer data)
247 {
248   map_canvas_focus();
249 }
250 
251 /****************************************************************
252   Action "REPORT_NATIONS" callback.
253 *****************************************************************/
report_nations_callback(GtkAction * action,gpointer data)254 static void report_nations_callback(GtkAction *action, gpointer data)
255 {
256   popup_players_dialog(TRUE);
257 }
258 
259 /****************************************************************
260   Action "REPORT_WOW" callback.
261 *****************************************************************/
report_wow_callback(GtkAction * action,gpointer data)262 static void report_wow_callback(GtkAction *action, gpointer data)
263 {
264   send_report_request(REPORT_WONDERS_OF_THE_WORLD);
265 }
266 
267 /****************************************************************
268   Action "REPORT_TOP_CITIES" callback.
269 *****************************************************************/
report_top_cities_callback(GtkAction * action,gpointer data)270 static void report_top_cities_callback(GtkAction *action, gpointer data)
271 {
272   send_report_request(REPORT_TOP_5_CITIES);
273 }
274 
275 /****************************************************************
276   Action "REPORT_MESSAGES" callback.
277 *****************************************************************/
report_messages_callback(GtkAction * action,gpointer data)278 static void report_messages_callback(GtkAction *action, gpointer data)
279 {
280   meswin_dialog_popup(TRUE);
281 }
282 
283 /****************************************************************
284   Action "CLIENT_LUA_SCRIPT" callback.
285 *****************************************************************/
client_lua_script_callback(GtkAction * action,gpointer data)286 static void client_lua_script_callback(GtkAction *action, gpointer data)
287 {
288   luaconsole_dialog_popup(TRUE);
289 }
290 
291 /****************************************************************
292   Action "REPORT_DEMOGRAPHIC" callback.
293 *****************************************************************/
report_demographic_callback(GtkAction * action,gpointer data)294 static void report_demographic_callback(GtkAction *action, gpointer data)
295 {
296   send_report_request(REPORT_DEMOGRAPHIC);
297 }
298 
299 /****************************************************************
300   Action "REPORT_ACHIEVEMENTS" callback.
301 *****************************************************************/
report_achievements_callback(GtkAction * action,gpointer data)302 static void report_achievements_callback(GtkAction *action, gpointer data)
303 {
304   send_report_request(REPORT_ACHIEVEMENTS);
305 }
306 
307 /****************************************************************
308   Action "HELP_LANGUAGE" callback.
309 *****************************************************************/
help_language_callback(GtkAction * action,gpointer data)310 static void help_language_callback(GtkAction *action, gpointer data)
311 {
312   popup_help_dialog_string(HELP_LANGUAGES_ITEM);
313 }
314 
315 /****************************************************************
316   Action "HELP_POLICIES" callback.
317 *****************************************************************/
help_policies_callback(GtkAction * action,gpointer data)318 static void help_policies_callback(GtkAction *action, gpointer data)
319 {
320   popup_help_dialog_string(HELP_MULTIPLIER_ITEM);
321 }
322 
323 /****************************************************************
324   Action "HELP_CONNECTING" callback.
325 *****************************************************************/
help_connecting_callback(GtkAction * action,gpointer data)326 static void help_connecting_callback(GtkAction *action, gpointer data)
327 {
328   popup_help_dialog_string(HELP_CONNECTING_ITEM);
329 }
330 
331 /****************************************************************
332   Action "HELP_CONTROLS" callback.
333 *****************************************************************/
help_controls_callback(GtkAction * action,gpointer data)334 static void help_controls_callback(GtkAction *action, gpointer data)
335 {
336   popup_help_dialog_string(HELP_CONTROLS_ITEM);
337 }
338 
339 /****************************************************************
340   Action "HELP_CHATLINE" callback.
341 *****************************************************************/
help_chatline_callback(GtkAction * action,gpointer data)342 static void help_chatline_callback(GtkAction *action, gpointer data)
343 {
344   popup_help_dialog_string(HELP_CHATLINE_ITEM);
345 }
346 
347 /****************************************************************
348   Action "HELP_WORKLIST_EDITOR" callback.
349 *****************************************************************/
help_worklist_editor_callback(GtkAction * action,gpointer data)350 static void help_worklist_editor_callback(GtkAction *action, gpointer data)
351 {
352   popup_help_dialog_string(HELP_WORKLIST_EDITOR_ITEM);
353 }
354 
355 /****************************************************************
356   Action "HELP_CMA" callback.
357 *****************************************************************/
help_cma_callback(GtkAction * action,gpointer data)358 static void help_cma_callback(GtkAction *action, gpointer data)
359 {
360   popup_help_dialog_string(HELP_CMA_ITEM);
361 }
362 
363 /****************************************************************
364   Action "HELP_OVERVIEW" callback.
365 *****************************************************************/
help_overview_callback(GtkAction * action,gpointer data)366 static void help_overview_callback(GtkAction *action, gpointer data)
367 {
368   popup_help_dialog_string(HELP_OVERVIEW_ITEM);
369 }
370 
371 /****************************************************************
372   Action "HELP_PLAYING" callback.
373 *****************************************************************/
help_playing_callback(GtkAction * action,gpointer data)374 static void help_playing_callback(GtkAction *action, gpointer data)
375 {
376   popup_help_dialog_string(HELP_PLAYING_ITEM);
377 }
378 
379 /****************************************************************
380   Action "HELP_RULESET" callback.
381 *****************************************************************/
help_ruleset_callback(GtkAction * action,gpointer data)382 static void help_ruleset_callback(GtkAction *action, gpointer data)
383 {
384   popup_help_dialog_string(HELP_RULESET_ITEM);
385 }
386 
387 /****************************************************************
388   Action "HELP_TILESET" callback.
389 *****************************************************************/
help_tileset_callback(GtkAction * action,gpointer data)390 static void help_tileset_callback(GtkAction *action, gpointer data)
391 {
392   popup_help_dialog_string(HELP_TILESET_ITEM);
393 }
394 
395 /****************************************************************
396   Action "HELP_ECONOMY" callback.
397 *****************************************************************/
help_economy_callback(GtkAction * action,gpointer data)398 static void help_economy_callback(GtkAction *action, gpointer data)
399 {
400   popup_help_dialog_string(HELP_ECONOMY_ITEM);
401 }
402 
403 /****************************************************************
404   Action "HELP_CITIES" callback.
405 *****************************************************************/
help_cities_callback(GtkAction * action,gpointer data)406 static void help_cities_callback(GtkAction *action, gpointer data)
407 {
408   popup_help_dialog_string(HELP_CITIES_ITEM);
409 }
410 
411 /****************************************************************
412   Action "HELP_IMPROVEMENTS" callback.
413 *****************************************************************/
help_improvements_callback(GtkAction * action,gpointer data)414 static void help_improvements_callback(GtkAction *action, gpointer data)
415 {
416   popup_help_dialog_string(HELP_IMPROVEMENTS_ITEM);
417 }
418 
419 /****************************************************************
420   Action "HELP_UNITS" callback.
421 *****************************************************************/
help_units_callback(GtkAction * action,gpointer data)422 static void help_units_callback(GtkAction *action, gpointer data)
423 {
424   popup_help_dialog_string(HELP_UNITS_ITEM);
425 }
426 
427 /****************************************************************
428   Action "HELP_COMBAT" callback.
429 *****************************************************************/
help_combat_callback(GtkAction * action,gpointer data)430 static void help_combat_callback(GtkAction *action, gpointer data)
431 {
432   popup_help_dialog_string(HELP_COMBAT_ITEM);
433 }
434 
435 /****************************************************************
436   Action "HELP_ZOC" callback.
437 *****************************************************************/
help_zoc_callback(GtkAction * action,gpointer data)438 static void help_zoc_callback(GtkAction *action, gpointer data)
439 {
440   popup_help_dialog_string(HELP_ZOC_ITEM);
441 }
442 
443 /****************************************************************
444   Action "HELP_TECH" callback.
445 *****************************************************************/
help_tech_callback(GtkAction * action,gpointer data)446 static void help_tech_callback(GtkAction *action, gpointer data)
447 {
448   popup_help_dialog_string(HELP_TECHS_ITEM);
449 }
450 
451 /****************************************************************
452   Action "HELP_TERRAIN" callback.
453 *****************************************************************/
help_terrain_callback(GtkAction * action,gpointer data)454 static void help_terrain_callback(GtkAction *action, gpointer data)
455 {
456   popup_help_dialog_string(HELP_TERRAIN_ITEM);
457 }
458 
459 /****************************************************************
460   Action "HELP_WONDERS" callback.
461 *****************************************************************/
help_wonders_callback(GtkAction * action,gpointer data)462 static void help_wonders_callback(GtkAction *action, gpointer data)
463 {
464   popup_help_dialog_string(HELP_WONDERS_ITEM);
465 }
466 
467 /****************************************************************
468   Action "HELP_GOVERNMENT" callback.
469 *****************************************************************/
help_government_callback(GtkAction * action,gpointer data)470 static void help_government_callback(GtkAction *action, gpointer data)
471 {
472   popup_help_dialog_string(HELP_GOVERNMENT_ITEM);
473 }
474 
475 /****************************************************************
476   Action "HELP_DIPLOMACY" callback.
477 *****************************************************************/
help_diplomacy_callback(GtkAction * action,gpointer data)478 static void help_diplomacy_callback(GtkAction *action, gpointer data)
479 {
480   popup_help_dialog_string(HELP_DIPLOMACY_ITEM);
481 }
482 
483 /****************************************************************
484   Action "HELP_SPACE_RACE" callback.
485 *****************************************************************/
help_space_rate_callback(GtkAction * action,gpointer data)486 static void help_space_rate_callback(GtkAction *action, gpointer data)
487 {
488   popup_help_dialog_string(HELP_SPACE_RACE_ITEM);
489 }
490 
491 /****************************************************************
492   Action "HELP_NATIONS" callback.
493 *****************************************************************/
help_nations_callback(GtkAction * action,gpointer data)494 static void help_nations_callback(GtkAction *action, gpointer data)
495 {
496   popup_help_dialog_string(HELP_NATIONS_ITEM);
497 }
498 
499 /****************************************************************
500   Action "HELP_COPYING" callback.
501 *****************************************************************/
help_copying_callback(GtkAction * action,gpointer data)502 static void help_copying_callback(GtkAction *action, gpointer data)
503 {
504   popup_help_dialog_string(HELP_COPYING_ITEM);
505 }
506 
507 /****************************************************************
508   Action "HELP_ABOUT" callback.
509 *****************************************************************/
help_about_callback(GtkAction * action,gpointer data)510 static void help_about_callback(GtkAction *action, gpointer data)
511 {
512   popup_help_dialog_string(HELP_ABOUT_ITEM);
513 }
514 
515 /****************************************************************
516   Action "SAVE_OPTIONS_ON_EXIT" callback.
517 *****************************************************************/
save_options_on_exit_callback(GtkToggleAction * action,gpointer data)518 static void save_options_on_exit_callback(GtkToggleAction *action,
519                                           gpointer data)
520 {
521   gui_options.save_options_on_exit = gtk_toggle_action_get_active(action);
522 }
523 
524 /****************************************************************
525   Action "EDIT_MODE" callback.
526 *****************************************************************/
edit_mode_callback(GtkToggleAction * action,gpointer data)527 static void edit_mode_callback(GtkToggleAction *action, gpointer data)
528 {
529   if (game.info.is_edit_mode ^ gtk_toggle_action_get_active(action)) {
530     key_editor_toggle();
531     /* Unreachbale techs in reqtree on/off */
532     science_report_dialog_popdown();
533   }
534 }
535 
536 /****************************************************************
537   Action "SHOW_CITY_OUTLINES" callback.
538 *****************************************************************/
show_city_outlines_callback(GtkToggleAction * action,gpointer data)539 static void show_city_outlines_callback(GtkToggleAction *action,
540                                         gpointer data)
541 {
542   if (gui_options.draw_city_outlines ^ gtk_toggle_action_get_active(action)) {
543     key_city_outlines_toggle();
544   }
545 }
546 
547 /****************************************************************
548   Action "SHOW_CITY_OUTPUT" callback.
549 *****************************************************************/
show_city_output_callback(GtkToggleAction * action,gpointer data)550 static void show_city_output_callback(GtkToggleAction *action, gpointer data)
551 {
552   if (gui_options.draw_city_output ^ gtk_toggle_action_get_active(action)) {
553     key_city_output_toggle();
554   }
555 }
556 
557 /****************************************************************
558   Action "SHOW_MAP_GRID" callback.
559 *****************************************************************/
show_map_grid_callback(GtkToggleAction * action,gpointer data)560 static void show_map_grid_callback(GtkToggleAction *action, gpointer data)
561 {
562   if (gui_options.draw_map_grid ^ gtk_toggle_action_get_active(action)) {
563     key_map_grid_toggle();
564   }
565 }
566 
567 /****************************************************************
568   Action "SHOW_NATIONAL_BORDERS" callback.
569 *****************************************************************/
show_national_borders_callback(GtkToggleAction * action,gpointer data)570 static void show_national_borders_callback(GtkToggleAction *action,
571                                            gpointer data)
572 {
573   if (gui_options.draw_borders ^ gtk_toggle_action_get_active(action)) {
574     key_map_borders_toggle();
575   }
576 }
577 
578 /****************************************************************
579   Action "SHOW_NATIVE_TILES" callback.
580 *****************************************************************/
show_native_tiles_callback(GtkToggleAction * action,gpointer data)581 static void show_native_tiles_callback(GtkToggleAction *action,
582                                        gpointer data)
583 {
584   if (gui_options.draw_native ^ gtk_toggle_action_get_active(action)) {
585     key_map_native_toggle();
586   }
587 }
588 
589 /****************************************************************
590   Action "SHOW_CITY_FULL_BAR" callback.
591 *****************************************************************/
show_city_full_bar_callback(GtkToggleAction * action,gpointer data)592 static void show_city_full_bar_callback(GtkToggleAction *action,
593                                         gpointer data)
594 {
595   if (gui_options.draw_full_citybar ^ gtk_toggle_action_get_active(action)) {
596     key_city_full_bar_toggle();
597     view_menu_update_sensitivity();
598   }
599 }
600 
601 /****************************************************************
602   Action "SHOW_CITY_NAMES" callback.
603 *****************************************************************/
show_city_names_callback(GtkToggleAction * action,gpointer data)604 static void show_city_names_callback(GtkToggleAction *action, gpointer data)
605 {
606   if (gui_options.draw_city_names ^ gtk_toggle_action_get_active(action)) {
607     key_city_names_toggle();
608     view_menu_update_sensitivity();
609   }
610 }
611 
612 /****************************************************************
613   Action "SHOW_CITY_GROWTH" callback.
614 *****************************************************************/
show_city_growth_callback(GtkToggleAction * action,gpointer data)615 static void show_city_growth_callback(GtkToggleAction *action, gpointer data)
616 {
617   if (gui_options.draw_city_growth ^ gtk_toggle_action_get_active(action)) {
618     key_city_growth_toggle();
619   }
620 }
621 
622 /****************************************************************
623   Action "SHOW_CITY_PRODUCTIONS" callback.
624 *****************************************************************/
show_city_productions_callback(GtkToggleAction * action,gpointer data)625 static void show_city_productions_callback(GtkToggleAction *action,
626                                            gpointer data)
627 {
628   if (gui_options.draw_city_productions ^ gtk_toggle_action_get_active(action)) {
629     key_city_productions_toggle();
630     view_menu_update_sensitivity();
631   }
632 }
633 
634 /****************************************************************
635   Action "SHOW_CITY_BUY_COST" callback.
636 *****************************************************************/
show_city_buy_cost_callback(GtkToggleAction * action,gpointer data)637 static void show_city_buy_cost_callback(GtkToggleAction *action,
638                                         gpointer data)
639 {
640   if (gui_options.draw_city_buycost ^ gtk_toggle_action_get_active(action)) {
641     key_city_buycost_toggle();
642   }
643 }
644 
645 /****************************************************************
646   Action "SHOW_CITY_TRADE_ROUTES" callback.
647 *****************************************************************/
show_city_trade_routes_callback(GtkToggleAction * action,gpointer data)648 static void show_city_trade_routes_callback(GtkToggleAction *action,
649                                             gpointer data)
650 {
651   if (gui_options.draw_city_trade_routes ^ gtk_toggle_action_get_active(action)) {
652     key_city_trade_routes_toggle();
653   }
654 }
655 
656 /****************************************************************
657   Action "SHOW_TERRAIN" callback.
658 *****************************************************************/
show_terrain_callback(GtkToggleAction * action,gpointer data)659 static void show_terrain_callback(GtkToggleAction *action, gpointer data)
660 {
661   if (gui_options.draw_terrain ^ gtk_toggle_action_get_active(action)) {
662     key_terrain_toggle();
663     view_menu_update_sensitivity();
664   }
665 }
666 
667 /****************************************************************
668   Action "SHOW_COASTLINE" callback.
669 *****************************************************************/
show_coastline_callback(GtkToggleAction * action,gpointer data)670 static void show_coastline_callback(GtkToggleAction *action, gpointer data)
671 {
672   if (gui_options.draw_coastline ^ gtk_toggle_action_get_active(action)) {
673     key_coastline_toggle();
674   }
675 }
676 
677 /****************************************************************
678   Action "SHOW_ROAD_RAILS" callback.
679 *****************************************************************/
show_road_rails_callback(GtkToggleAction * action,gpointer data)680 static void show_road_rails_callback(GtkToggleAction *action, gpointer data)
681 {
682   if (gui_options.draw_roads_rails ^ gtk_toggle_action_get_active(action)) {
683     key_roads_rails_toggle();
684   }
685 }
686 
687 /****************************************************************
688   Action "SHOW_IRRIGATION" callback.
689 *****************************************************************/
show_irrigation_callback(GtkToggleAction * action,gpointer data)690 static void show_irrigation_callback(GtkToggleAction *action, gpointer data)
691 {
692   if (gui_options.draw_irrigation ^ gtk_toggle_action_get_active(action)) {
693     key_irrigation_toggle();
694   }
695 }
696 
697 /****************************************************************
698   Action "SHOW_MINE" callback.
699 *****************************************************************/
show_mine_callback(GtkToggleAction * action,gpointer data)700 static void show_mine_callback(GtkToggleAction *action, gpointer data)
701 {
702   if (gui_options.draw_mines ^ gtk_toggle_action_get_active(action)) {
703     key_mines_toggle();
704   }
705 }
706 
707 /****************************************************************
708   Action "SHOW_BASES" callback.
709 *****************************************************************/
show_bases_callback(GtkToggleAction * action,gpointer data)710 static void show_bases_callback(GtkToggleAction *action, gpointer data)
711 {
712   if (gui_options.draw_fortress_airbase ^ gtk_toggle_action_get_active(action)) {
713     key_bases_toggle();
714   }
715 }
716 
717 /****************************************************************
718   Action "SHOW_RESOURCES" callback.
719 *****************************************************************/
show_resources_callback(GtkToggleAction * action,gpointer data)720 static void show_resources_callback(GtkToggleAction *action, gpointer data)
721 {
722   if (gui_options.draw_specials ^ gtk_toggle_action_get_active(action)) {
723     key_resources_toggle();
724   }
725 }
726 
727 /****************************************************************
728   Action "SHOW_HUTS" callback.
729 *****************************************************************/
show_huts_callback(GtkToggleAction * action,gpointer data)730 static void show_huts_callback(GtkToggleAction *action, gpointer data)
731 {
732   if (gui_options.draw_huts ^ gtk_toggle_action_get_active(action)) {
733     key_huts_toggle();
734   }
735 }
736 
737 /****************************************************************
738   Action "SHOW_POLLUTION" callback.
739 *****************************************************************/
show_pollution_callback(GtkToggleAction * action,gpointer data)740 static void show_pollution_callback(GtkToggleAction *action, gpointer data)
741 {
742   if (gui_options.draw_pollution ^ gtk_toggle_action_get_active(action)) {
743     key_pollution_toggle();
744   }
745 }
746 
747 /****************************************************************
748   Action "SHOW_CITIES" callback.
749 *****************************************************************/
show_cities_callback(GtkToggleAction * action,gpointer data)750 static void show_cities_callback(GtkToggleAction *action, gpointer data)
751 {
752   if (gui_options.draw_cities ^ gtk_toggle_action_get_active(action)) {
753     key_cities_toggle();
754   }
755 }
756 
757 /****************************************************************
758   Action "SHOW_UNITS" callback.
759 *****************************************************************/
show_units_callback(GtkToggleAction * action,gpointer data)760 static void show_units_callback(GtkToggleAction *action, gpointer data)
761 {
762   if (gui_options.draw_units ^ gtk_toggle_action_get_active(action)) {
763     key_units_toggle();
764     view_menu_update_sensitivity();
765   }
766 }
767 
768 /****************************************************************
769   Action "SHOW_UNIT_SOLID_BG" callback.
770 *****************************************************************/
show_unit_solid_bg_callback(GtkToggleAction * action,gpointer data)771 static void show_unit_solid_bg_callback(GtkToggleAction *action,
772                                         gpointer data)
773 {
774   if (gui_options.solid_color_behind_units ^ gtk_toggle_action_get_active(action)) {
775     key_unit_solid_bg_toggle();
776   }
777 }
778 
779 /****************************************************************
780   Action "SHOW_UNIT_SHIELDS" callback.
781 *****************************************************************/
show_unit_shields_callback(GtkToggleAction * action,gpointer data)782 static void show_unit_shields_callback(GtkToggleAction *action,
783                                        gpointer data)
784 {
785   if (gui_options.draw_unit_shields ^ gtk_toggle_action_get_active(action)) {
786     key_unit_shields_toggle();
787   }
788 }
789 
790 /****************************************************************
791   Action "SHOW_FOCUS_UNIT" callback.
792 *****************************************************************/
show_focus_unit_callback(GtkToggleAction * action,gpointer data)793 static void show_focus_unit_callback(GtkToggleAction *action, gpointer data)
794 {
795   if (gui_options.draw_focus_unit ^ gtk_toggle_action_get_active(action)) {
796     key_focus_unit_toggle();
797     view_menu_update_sensitivity();
798   }
799 }
800 
801 /****************************************************************
802   Action "SHOW_FOG_OF_WAR" callback.
803 *****************************************************************/
show_fog_of_war_callback(GtkToggleAction * action,gpointer data)804 static void show_fog_of_war_callback(GtkToggleAction *action, gpointer data)
805 {
806   if (gui_options.draw_fog_of_war ^ gtk_toggle_action_get_active(action)) {
807     key_fog_of_war_toggle();
808     view_menu_update_sensitivity();
809   }
810 }
811 
812 /****************************************************************
813   Action "SHOW_BETTER_FOG_OF_WAR" callback.
814 *****************************************************************/
show_better_fog_of_war_callback(GtkToggleAction * action,gpointer data)815 static void show_better_fog_of_war_callback(GtkToggleAction *action,
816                                             gpointer data)
817 {
818   if (gui_options.gui_gtk2_better_fog ^ gtk_toggle_action_get_active(action)) {
819     gui_options.gui_gtk2_better_fog ^= 1;
820     update_map_canvas_visible();
821   }
822 }
823 
824 /****************************************************************
825   Action "FULL_SCREEN" callback.
826 *****************************************************************/
full_screen_callback(GtkToggleAction * action,gpointer data)827 static void full_screen_callback(GtkToggleAction *action, gpointer data)
828 {
829   if (gui_options.gui_gtk2_fullscreen ^ gtk_toggle_action_get_active(action)) {
830     gui_options.gui_gtk2_fullscreen ^= 1;
831 
832     if (gui_options.gui_gtk2_fullscreen) {
833       gtk_window_fullscreen(GTK_WINDOW(toplevel));
834     } else {
835       gtk_window_unfullscreen(GTK_WINDOW(toplevel));
836     }
837   }
838 }
839 
840 /****************************************************************
841   Action "RECALC_BORDERS" callback.
842 *****************************************************************/
recalc_borders_callback(GtkAction * action,gpointer data)843 static void recalc_borders_callback(GtkAction *action, gpointer data)
844 {
845   key_editor_recalculate_borders();
846 }
847 
848 /****************************************************************
849   Action "TOGGLE_FOG" callback.
850 *****************************************************************/
toggle_fog_callback(GtkAction * action,gpointer data)851 static void toggle_fog_callback(GtkAction *action, gpointer data)
852 {
853   key_editor_toggle_fogofwar();
854 }
855 
856 /****************************************************************
857   Action "SCENARIO_PROPERTIES" callback.
858 *****************************************************************/
scenario_properties_callback(GtkAction * action,gpointer data)859 static void scenario_properties_callback(GtkAction *action, gpointer data)
860 {
861   struct property_editor *pe;
862 
863   pe = editprop_get_property_editor();
864   property_editor_reload(pe, OBJTYPE_GAME);
865   property_editor_popup(pe, OBJTYPE_GAME);
866 }
867 
868 /****************************************************************
869   Action "SAVE_SCENARIO" callback.
870 *****************************************************************/
save_scenario_callback(GtkAction * action,gpointer data)871 static void save_scenario_callback(GtkAction *action, gpointer data)
872 {
873   save_scenario_dialog_popup();
874 }
875 
876 /****************************************************************
877   Action "SELECT_SINGLE" callback.
878 *****************************************************************/
select_single_callback(GtkAction * action,gpointer data)879 static void select_single_callback(GtkAction *action, gpointer data)
880 {
881   request_unit_select(get_units_in_focus(), SELTYPE_SINGLE, SELLOC_TILE);
882 }
883 
884 /****************************************************************
885   Action "SELECT_ALL_ON_TILE" callback.
886 *****************************************************************/
select_all_on_tile_callback(GtkAction * action,gpointer data)887 static void select_all_on_tile_callback(GtkAction *action, gpointer data)
888 {
889   request_unit_select(get_units_in_focus(), SELTYPE_ALL, SELLOC_TILE);
890 }
891 
892 /****************************************************************
893   Action "SELECT_SAME_TYPE_TILE" callback.
894 *****************************************************************/
select_same_type_tile_callback(GtkAction * action,gpointer data)895 static void select_same_type_tile_callback(GtkAction *action, gpointer data)
896 {
897   request_unit_select(get_units_in_focus(), SELTYPE_SAME, SELLOC_TILE);
898 }
899 
900 /****************************************************************
901   Action "SELECT_SAME_TYPE_CONT" callback.
902 *****************************************************************/
select_same_type_cont_callback(GtkAction * action,gpointer data)903 static void select_same_type_cont_callback(GtkAction *action, gpointer data)
904 {
905   request_unit_select(get_units_in_focus(), SELTYPE_SAME, SELLOC_CONT);
906 }
907 
908 /****************************************************************
909   Action "SELECT_SAME_TYPE" callback.
910 *****************************************************************/
select_same_type_callback(GtkAction * action,gpointer data)911 static void select_same_type_callback(GtkAction *action, gpointer data)
912 {
913   request_unit_select(get_units_in_focus(), SELTYPE_SAME, SELLOC_WORLD);
914 }
915 
916 /*****************************************************************************
917   Open unit selection dialog.
918 *****************************************************************************/
select_dialog_callback(GtkAction * action,gpointer data)919 static void select_dialog_callback(GtkAction *action, gpointer data)
920 {
921   unit_select_dialog_popup(NULL);
922 }
923 
924 /****************************************************************
925   Action "UNIT_WAIT" callback.
926 *****************************************************************/
unit_wait_callback(GtkAction * action,gpointer data)927 static void unit_wait_callback(GtkAction *action, gpointer data)
928 {
929   key_unit_wait();
930 }
931 
932 /****************************************************************
933   Action "UNIT_DONE" callback.
934 *****************************************************************/
unit_done_callback(GtkAction * action,gpointer data)935 static void unit_done_callback(GtkAction *action, gpointer data)
936 {
937   key_unit_done();
938 }
939 
940 /****************************************************************
941   Action "UNIT_GOTO" callback.
942 *****************************************************************/
unit_goto_callback(GtkAction * action,gpointer data)943 static void unit_goto_callback(GtkAction *action, gpointer data)
944 {
945   key_unit_goto();
946 }
947 
948 /****************************************************************
949   Action "UNIT_GOTO_CITY" callback.
950 *****************************************************************/
unit_goto_city_callback(GtkAction * action,gpointer data)951 static void unit_goto_city_callback(GtkAction *action, gpointer data)
952 {
953   if (get_num_units_in_focus() > 0) {
954     popup_goto_dialog();
955   }
956 }
957 
958 /****************************************************************
959   Action "UNIT_RETURN" callback.
960 *****************************************************************/
unit_return_callback(GtkAction * action,gpointer data)961 static void unit_return_callback(GtkAction *action, gpointer data)
962 {
963   unit_list_iterate(get_units_in_focus(), punit) {
964     request_unit_return(punit);
965   } unit_list_iterate_end;
966 }
967 
968 /****************************************************************
969   Action "UNIT_EXPLORE" callback.
970 *****************************************************************/
unit_explore_callback(GtkAction * action,gpointer data)971 static void unit_explore_callback(GtkAction *action, gpointer data)
972 {
973   key_unit_auto_explore();
974 }
975 
976 /****************************************************************
977   Action "UNIT_PATROL" callback.
978 *****************************************************************/
unit_patrol_callback(GtkAction * action,gpointer data)979 static void unit_patrol_callback(GtkAction *action, gpointer data)
980 {
981   key_unit_patrol();
982 }
983 
984 /****************************************************************
985   Action "UNIT_SENTRY" callback.
986 *****************************************************************/
unit_sentry_callback(GtkAction * action,gpointer data)987 static void unit_sentry_callback(GtkAction *action, gpointer data)
988 {
989   key_unit_sentry();
990 }
991 
992 /****************************************************************
993   Action "UNIT_UNSENTRY" callback.
994 *****************************************************************/
unit_unsentry_callback(GtkAction * action,gpointer data)995 static void unit_unsentry_callback(GtkAction *action, gpointer data)
996 {
997   key_unit_wakeup_others();
998 }
999 
1000 /****************************************************************
1001   Action "UNIT_LOAD" callback.
1002 *****************************************************************/
unit_load_callback(GtkAction * action,gpointer data)1003 static void unit_load_callback(GtkAction *action, gpointer data)
1004 {
1005   unit_list_iterate(get_units_in_focus(), punit) {
1006     request_unit_load(punit, NULL, unit_tile(punit));
1007   } unit_list_iterate_end;
1008 }
1009 
1010 /****************************************************************
1011   Action "UNIT_UNLOAD" callback.
1012 *****************************************************************/
unit_unload_callback(GtkAction * action,gpointer data)1013 static void unit_unload_callback(GtkAction *action, gpointer data)
1014 {
1015   unit_list_iterate(get_units_in_focus(), punit) {
1016     request_unit_unload(punit);
1017   } unit_list_iterate_end;
1018 }
1019 
1020 /****************************************************************
1021   Action "UNIT_UNLOAD_TRANSPORTER" callback.
1022 *****************************************************************/
unit_unload_transporter_callback(GtkAction * action,gpointer data)1023 static void unit_unload_transporter_callback(GtkAction *action,
1024                                              gpointer data)
1025 {
1026   key_unit_unload_all();
1027 }
1028 
1029 /****************************************************************
1030   Action "UNIT_HOMECITY" callback.
1031 *****************************************************************/
unit_homecity_callback(GtkAction * action,gpointer data)1032 static void unit_homecity_callback(GtkAction *action, gpointer data)
1033 {
1034   key_unit_homecity();
1035 }
1036 
1037 /****************************************************************
1038   Action "UNIT_UPGRADE" callback.
1039 *****************************************************************/
unit_upgrade_callback(GtkAction * action,gpointer data)1040 static void unit_upgrade_callback(GtkAction *action, gpointer data)
1041 {
1042   popup_upgrade_dialog(get_units_in_focus());
1043 }
1044 
1045 /****************************************************************
1046   Action "UNIT_CONVERT" callback.
1047 *****************************************************************/
unit_convert_callback(GtkAction * action,gpointer data)1048 static void unit_convert_callback(GtkAction *action, gpointer data)
1049 {
1050   key_unit_convert();
1051 }
1052 
1053 /****************************************************************
1054   Action "UNIT_DISBAND" callback.
1055 *****************************************************************/
unit_disband_callback(GtkAction * action,gpointer data)1056 static void unit_disband_callback(GtkAction *action, gpointer data)
1057 {
1058   popup_disband_dialog(get_units_in_focus());
1059 }
1060 
1061 /****************************************************************
1062   Action "BUILD_CITY" callback.
1063 *****************************************************************/
build_city_callback(GtkAction * action,gpointer data)1064 static void build_city_callback(GtkAction *action, gpointer data)
1065 {
1066   unit_list_iterate(get_units_in_focus(), punit) {
1067     /* FIXME: this can provide different actions for different units...
1068      * not good! */
1069     /* Enable the button for adding to a city in all cases, so we
1070        get an eventual error message from the server if we try. */
1071     if (unit_can_add_or_build_city(punit)) {
1072       request_unit_build_city(punit);
1073     } else if (utype_can_do_action(unit_type_get(punit),
1074                                    ACTION_HELP_WONDER)) {
1075       request_unit_caravan_action(punit, ACTION_HELP_WONDER);
1076     }
1077   } unit_list_iterate_end;
1078 }
1079 
1080 /****************************************************************
1081   Action "GO_BUILD_CITY" callback.
1082 *****************************************************************/
go_build_city_callback(GtkAction * action,gpointer data)1083 static void go_build_city_callback(GtkAction *action, gpointer data)
1084 {
1085   request_unit_goto(ORDER_BUILD_CITY);
1086 }
1087 
1088 /****************************************************************
1089   Action "AUTO_SETTLE" callback.
1090 *****************************************************************/
auto_settle_callback(GtkAction * action,gpointer data)1091 static void auto_settle_callback(GtkAction *action, gpointer data)
1092 {
1093   key_unit_auto_settle();
1094 }
1095 
1096 /****************************************************************
1097   Action "BUILD_ROAD" callback.
1098 *****************************************************************/
build_road_callback(GtkAction * action,gpointer data)1099 static void build_road_callback(GtkAction *action, gpointer data)
1100 {
1101   unit_list_iterate(get_units_in_focus(), punit) {
1102     /* FIXME: this can provide different actions for different units...
1103      * not good! */
1104     struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
1105                                                  EC_ROAD,
1106                                                  unit_owner(punit),
1107                                                  punit);
1108     bool building_road = FALSE;
1109 
1110     if (tgt != NULL
1111         && can_unit_do_activity_targeted(punit, ACTIVITY_GEN_ROAD, tgt)) {
1112       request_new_unit_activity_targeted(punit, ACTIVITY_GEN_ROAD, tgt);
1113       building_road = TRUE;
1114     }
1115 
1116     if (!building_road && unit_can_est_trade_route_here(punit)) {
1117       request_unit_caravan_action(punit, ACTION_TRADE_ROUTE);
1118     }
1119   } unit_list_iterate_end;
1120 }
1121 
1122 /****************************************************************
1123   Action "BUILD_IRRIGATION" callback.
1124 *****************************************************************/
build_irrigation_callback(GtkAction * action,gpointer data)1125 static void build_irrigation_callback(GtkAction *action, gpointer data)
1126 {
1127   key_unit_irrigate();
1128 }
1129 
1130 /****************************************************************
1131   Action "BUILD_MINE" callback.
1132 *****************************************************************/
build_mine_callback(GtkAction * action,gpointer data)1133 static void build_mine_callback(GtkAction *action, gpointer data)
1134 {
1135   key_unit_mine();
1136 }
1137 
1138 /****************************************************************
1139   Action "CONNECT_ROAD" callback.
1140 *****************************************************************/
connect_road_callback(GtkAction * action,gpointer data)1141 static void connect_road_callback(GtkAction *action, gpointer data)
1142 {
1143   struct road_type *proad = road_by_compat_special(ROCO_ROAD);
1144 
1145   if (proad != NULL) {
1146     struct extra_type *tgt;
1147 
1148     tgt = road_extra_get(proad);
1149 
1150     key_unit_connect(ACTIVITY_GEN_ROAD, tgt);
1151   }
1152 }
1153 
1154 /****************************************************************
1155   Action "CONNECT_RAIL" callback.
1156 *****************************************************************/
connect_rail_callback(GtkAction * action,gpointer data)1157 static void connect_rail_callback(GtkAction *action, gpointer data)
1158 {
1159   struct road_type *prail = road_by_compat_special(ROCO_RAILROAD);
1160 
1161   if (prail != NULL) {
1162     struct extra_type *tgt;
1163 
1164     tgt = road_extra_get(prail);
1165 
1166     key_unit_connect(ACTIVITY_GEN_ROAD, tgt);
1167   }
1168 }
1169 
1170 /****************************************************************
1171   Action "CONNECT_IRRIGATION" callback.
1172 *****************************************************************/
connect_irrigation_callback(GtkAction * action,gpointer data)1173 static void connect_irrigation_callback(GtkAction *action, gpointer data)
1174 {
1175   struct extra_type_list *extras = extra_type_list_by_cause(EC_IRRIGATION);
1176 
1177   if (extra_type_list_size(extras) > 0) {
1178     struct extra_type *pextra;
1179 
1180     pextra = extra_type_list_get(extra_type_list_by_cause(EC_IRRIGATION), 0);
1181 
1182     key_unit_connect(ACTIVITY_IRRIGATE, pextra);
1183   }
1184 }
1185 
1186 /****************************************************************
1187   Action "TRANSFORM_TERRAIN" callback.
1188 *****************************************************************/
transform_terrain_callback(GtkAction * action,gpointer data)1189 static void transform_terrain_callback(GtkAction *action, gpointer data)
1190 {
1191   key_unit_transform();
1192 }
1193 
1194 /****************************************************************
1195   Action "CLEAN_POLLUTION" callback.
1196 *****************************************************************/
clean_pollution_callback(GtkAction * action,gpointer data)1197 static void clean_pollution_callback(GtkAction *action, gpointer data)
1198 {
1199   unit_list_iterate(get_units_in_focus(), punit) {
1200     /* FIXME: this can provide different actions for different units...
1201      * not good! */
1202     struct extra_type *pextra;
1203 
1204     pextra = prev_extra_in_tile(unit_tile(punit), ERM_CLEANPOLLUTION,
1205                                 unit_owner(punit), punit);
1206     if (pextra != NULL) {
1207       request_new_unit_activity_targeted(punit, ACTIVITY_POLLUTION, pextra);
1208     } else if (can_unit_paradrop(punit)) {
1209       /* FIXME: This is getting worse, we use a key_unit_*() function
1210        * which assign the order for all units!  Very bad! */
1211       key_unit_paradrop();
1212     }
1213   } unit_list_iterate_end;
1214 }
1215 
1216 /****************************************************************
1217   Action "CLEAN_FALLOUT" callback.
1218 *****************************************************************/
clean_fallout_callback(GtkAction * action,gpointer data)1219 static void clean_fallout_callback(GtkAction *action, gpointer data)
1220 {
1221   key_unit_fallout();
1222 }
1223 
1224 /****************************************************************
1225   Action "BUILD_FORTRESS" callback.
1226 *****************************************************************/
build_fortress_callback(GtkAction * action,gpointer data)1227 static void build_fortress_callback(GtkAction *action, gpointer data)
1228 {
1229   key_unit_fortress();
1230 }
1231 
1232 /****************************************************************
1233   Action "FORTIFY" callback.
1234 *****************************************************************/
fortify_callback(GtkAction * action,gpointer data)1235 static void fortify_callback(GtkAction *action, gpointer data)
1236 {
1237   unit_list_iterate(get_units_in_focus(), punit) {
1238     request_unit_fortify(punit);
1239   } unit_list_iterate_end;
1240 }
1241 
1242 /****************************************************************
1243   Action "BUILD_AIRBASE" callback.
1244 *****************************************************************/
build_airbase_callback(GtkAction * action,gpointer data)1245 static void build_airbase_callback(GtkAction *action, gpointer data)
1246 {
1247   key_unit_airbase();
1248 }
1249 
1250 /****************************************************************
1251   Action "DO_PILLAGE" callback.
1252 *****************************************************************/
do_pillage_callback(GtkAction * action,gpointer data)1253 static void do_pillage_callback(GtkAction *action, gpointer data)
1254 {
1255   key_unit_pillage();
1256 }
1257 
1258 /****************************************************************
1259   Action "DIPLOMAT_ACTION" callback.
1260 *****************************************************************/
diplomat_action_callback(GtkAction * action,gpointer data)1261 static void diplomat_action_callback(GtkAction *action, gpointer data)
1262 {
1263   key_unit_action_select_tgt();
1264 }
1265 
1266 /****************************************************************
1267   Action "EXPLODE_NUKE" callback.
1268 *****************************************************************/
explode_nuke_callback(GtkAction * action,gpointer data)1269 static void explode_nuke_callback(GtkAction *action, gpointer data)
1270 {
1271   key_unit_nuke();
1272 }
1273 
1274 /****************************************************************
1275   Action "TAX_RATE" callback.
1276 *****************************************************************/
tax_rate_callback(GtkAction * action,gpointer data)1277 static void tax_rate_callback(GtkAction *action, gpointer data)
1278 {
1279   popup_rates_dialog();
1280 }
1281 
1282 /****************************************************************
1283   Action "MULTIPLIERS" callback.
1284 *****************************************************************/
multiplier_callback(GtkAction * action,gpointer data)1285 static void multiplier_callback(GtkAction *action, gpointer data)
1286 {
1287   popup_multiplier_dialog();
1288 }
1289 
1290 /****************************************************************
1291   The player has chosen a government from the menu.
1292 *****************************************************************/
government_callback(GtkMenuItem * item,gpointer data)1293 static void government_callback(GtkMenuItem *item, gpointer data)
1294 {
1295   popup_revolution_dialog((struct government *) data);
1296 }
1297 
1298 /****************************************************************************
1299   The player has chosen a base to build from the menu.
1300 ****************************************************************************/
base_callback(GtkMenuItem * item,gpointer data)1301 static void base_callback(GtkMenuItem *item, gpointer data)
1302 {
1303   struct extra_type *pextra = data;
1304 
1305   unit_list_iterate(get_units_in_focus(), punit) {
1306     request_new_unit_activity_targeted(punit, ACTIVITY_BASE, pextra);
1307   } unit_list_iterate_end;
1308 }
1309 
1310 /****************************************************************************
1311   The player has chosen a road to build from the menu.
1312 ****************************************************************************/
road_callback(GtkMenuItem * item,gpointer data)1313 static void road_callback(GtkMenuItem *item, gpointer data)
1314 {
1315   struct extra_type *pextra = data;
1316 
1317   unit_list_iterate(get_units_in_focus(), punit) {
1318     request_new_unit_activity_targeted(punit, ACTIVITY_GEN_ROAD,
1319                                        pextra);
1320   } unit_list_iterate_end;
1321 }
1322 
1323 /****************************************************************
1324   Action "CENTER_VIEW" callback.
1325 *****************************************************************/
center_view_callback(GtkAction * action,gpointer data)1326 static void center_view_callback(GtkAction *action, gpointer data)
1327 {
1328   center_on_unit();
1329 }
1330 
1331 /****************************************************************
1332   Action "REPORT_UNITS" callback.
1333 *****************************************************************/
report_units_callback(GtkAction * action,gpointer data)1334 static void report_units_callback(GtkAction *action, gpointer data)
1335 {
1336   units_report_dialog_popup(TRUE);
1337 }
1338 
1339 /****************************************************************
1340   Action "REPORT_CITIES" callback.
1341 *****************************************************************/
report_cities_callback(GtkAction * action,gpointer data)1342 static void report_cities_callback(GtkAction *action, gpointer data)
1343 {
1344   city_report_dialog_popup(TRUE);
1345 }
1346 
1347 /****************************************************************
1348   Action "REPORT_ECONOMY" callback.
1349 *****************************************************************/
report_economy_callback(GtkAction * action,gpointer data)1350 static void report_economy_callback(GtkAction *action, gpointer data)
1351 {
1352   economy_report_dialog_popup(TRUE);
1353 }
1354 
1355 /****************************************************************
1356   Action "REPORT_RESEARCH" callback.
1357 *****************************************************************/
report_research_callback(GtkAction * action,gpointer data)1358 static void report_research_callback(GtkAction *action, gpointer data)
1359 {
1360   science_report_dialog_popup(TRUE);
1361 }
1362 
1363 /****************************************************************
1364   Action "REPORT_SPACESHIP" callback.
1365 *****************************************************************/
report_spaceship_callback(GtkAction * action,gpointer data)1366 static void report_spaceship_callback(GtkAction *action, gpointer data)
1367 {
1368   if (NULL != client.conn.playing) {
1369     popup_spaceship_dialog(client.conn.playing);
1370   }
1371 }
1372 
1373 /****************************************************************
1374   Returns the group of the actions which are always available for
1375   the user in anycase.  Create it if not existent.
1376 *****************************************************************/
get_safe_group(void)1377 static GtkActionGroup *get_safe_group(void)
1378 {
1379   static GtkActionGroup *group = NULL;
1380 
1381   if (!group) {
1382     const GtkActionEntry menu_entries[] = {
1383       {"MENU_GAME", NULL, _("_Game"), NULL, NULL, NULL},
1384       {"MENU_OPTIONS", NULL, _("_Options"), NULL, NULL, NULL},
1385       {"MENU_EDIT", NULL, _("_Edit"), NULL, NULL, NULL},
1386       {"MENU_VIEW", NULL, Q_("?verb:_View"), NULL, NULL, NULL},
1387       {"MENU_IMPROVEMENTS", NULL, _("_Improvements"), NULL, NULL, NULL},
1388       {"MENU_CIVILIZATION", NULL, _("C_ivilization"), NULL, NULL, NULL},
1389       {"MENU_HELP", NULL, _("_Help"), NULL, NULL, NULL},
1390 
1391       /* A special case to make empty menu. */
1392       {"NULL", NULL, "NULL", NULL, NULL, NULL}
1393     };
1394 
1395     const GtkActionEntry action_entries[] = {
1396       /* Game menu. */
1397       {"CLEAR_CHAT_LOGS", GTK_STOCK_CLEAR, _("_Clear Chat Log"),
1398        NULL, NULL, G_CALLBACK(clear_chat_logs_callback)},
1399       {"SAVE_CHAT_LOGS", GTK_STOCK_SAVE_AS, _("Save Chat _Log"),
1400        NULL, NULL, G_CALLBACK(save_chat_logs_callback)},
1401 
1402       {"LOCAL_OPTIONS", GTK_STOCK_PREFERENCES, _("_Local Client"),
1403        NULL, NULL, G_CALLBACK(local_options_callback)},
1404       {"MESSAGE_OPTIONS", GTK_STOCK_PREFERENCES, _("_Message"),
1405        NULL, NULL, G_CALLBACK(message_options_callback)},
1406       {"SERVER_OPTIONS", GTK_STOCK_PREFERENCES, _("_Remote Server"),
1407        NULL, NULL, G_CALLBACK(server_options_callback)},
1408       {"SAVE_OPTIONS", GTK_STOCK_SAVE_AS, _("Save Options _Now"),
1409        NULL, NULL, G_CALLBACK(save_options_callback)},
1410 
1411       {"RELOAD_TILESET", GTK_STOCK_REVERT_TO_SAVED, _("_Reload Tileset"),
1412        "<Control><Alt>r", NULL, G_CALLBACK(reload_tileset_callback)},
1413       {"GAME_SAVE", GTK_STOCK_SAVE, _("_Save Game"),
1414        NULL, NULL, G_CALLBACK(save_game_callback)},
1415       {"GAME_SAVE_AS", GTK_STOCK_SAVE_AS, _("Save Game _As..."),
1416        NULL, NULL, G_CALLBACK(save_game_as_callback)},
1417       {"MAPIMG_SAVE", NULL, _("Save Map _Image"),
1418        NULL, NULL, G_CALLBACK(save_mapimg_callback)},
1419       {"MAPIMG_SAVE_AS", NULL, _("Save _Map Image As..."),
1420        NULL, NULL, G_CALLBACK(save_mapimg_as_callback)},
1421       {"LEAVE", NULL, _("_Leave"),
1422        NULL, NULL, G_CALLBACK(leave_callback)},
1423       {"QUIT", GTK_STOCK_QUIT, _("_Quit"),
1424        NULL, NULL, G_CALLBACK(quit_callback)},
1425 
1426       /* Edit menu. */
1427       {"FIND_CITY", GTK_STOCK_FIND, _("_Find City"),
1428        "<Control>f", NULL, G_CALLBACK(find_city_callback)},
1429       {"WORKLISTS", NULL, _("Work_lists"),
1430        "<Control>l", NULL, G_CALLBACK(worklists_callback)},
1431 
1432       {"CLIENT_LUA_SCRIPT", NULL, _("Client _Lua Script"),
1433        NULL, NULL, G_CALLBACK(client_lua_script_callback)},
1434 
1435       /* Civilization menu. */
1436       {"MAP_VIEW", NULL, Q_("?noun:_View"),
1437        "F1", NULL, G_CALLBACK(map_view_callback)},
1438       {"REPORT_UNITS", NULL, _("_Units"),
1439        "F2", NULL, G_CALLBACK(report_units_callback)},
1440       {"REPORT_NATIONS", NULL, _("_Nations"),
1441        "F3", NULL, G_CALLBACK(report_nations_callback)},
1442       {"REPORT_CITIES", NULL, _("_Cities"),
1443        "F4", NULL, G_CALLBACK(report_cities_callback)},
1444 
1445       {"REPORT_WOW", NULL, _("_Wonders of the World"),
1446        "F7", NULL, G_CALLBACK(report_wow_callback)},
1447       {"REPORT_TOP_CITIES", NULL, _("Top _Five Cities"),
1448        "F8", NULL, G_CALLBACK(report_top_cities_callback)},
1449       {"REPORT_MESSAGES", NULL, _("_Messages"),
1450        "F9", NULL, G_CALLBACK(report_messages_callback)},
1451       {"REPORT_DEMOGRAPHIC", NULL, _("_Demographics"),
1452        "F11", NULL, G_CALLBACK(report_demographic_callback)},
1453 
1454       /* Help menu. */
1455       /* TRANS: "Overview" topic in built-in help */
1456       {"HELP_OVERVIEW", NULL, Q_("?help:Overview"),
1457        NULL, NULL, G_CALLBACK(help_overview_callback)},
1458       {"HELP_PLAYING", NULL, _("Strategy and Tactics"),
1459        NULL, NULL, G_CALLBACK(help_playing_callback)},
1460       {"HELP_TERRAIN", NULL, _("Terrain"),
1461        NULL, NULL, G_CALLBACK(help_terrain_callback)},
1462       {"HELP_ECONOMY", NULL, _("Economy"),
1463        NULL, NULL, G_CALLBACK(help_economy_callback)},
1464       {"HELP_CITIES", NULL, _("Cities"),
1465        NULL, NULL, G_CALLBACK(help_cities_callback)},
1466       {"HELP_IMPROVEMENTS", NULL, _("City Improvements"),
1467        NULL, NULL, G_CALLBACK(help_improvements_callback)},
1468       {"HELP_WONDERS", NULL, _("Wonders of the World"),
1469        NULL, NULL, G_CALLBACK(help_wonders_callback)},
1470       {"HELP_UNITS", NULL, _("Units"),
1471        NULL, NULL, G_CALLBACK(help_units_callback)},
1472       {"HELP_COMBAT", NULL, _("Combat"),
1473        NULL, NULL, G_CALLBACK(help_combat_callback)},
1474       {"HELP_ZOC", NULL, _("Zones of Control"),
1475        NULL, NULL, G_CALLBACK(help_zoc_callback)},
1476       {"HELP_POLICIES", NULL, _("Policies"),
1477        NULL, NULL, G_CALLBACK(help_policies_callback)},
1478       {"HELP_GOVERNMENT", NULL, _("Government"),
1479        NULL, NULL, G_CALLBACK(help_government_callback)},
1480       {"HELP_DIPLOMACY", NULL, _("Diplomacy"),
1481        NULL, NULL, G_CALLBACK(help_diplomacy_callback)},
1482       {"HELP_TECH", NULL, _("Technology"),
1483        NULL, NULL, G_CALLBACK(help_tech_callback)},
1484       {"HELP_SPACE_RACE", NULL, _("Space Race"),
1485        NULL, NULL, G_CALLBACK(help_space_rate_callback)},
1486       {"HELP_RULESET", NULL, _("About Current Ruleset"),
1487        NULL, NULL, G_CALLBACK(help_ruleset_callback)},
1488       {"HELP_TILESET", NULL, _("About Current Tileset"),
1489        NULL, NULL, G_CALLBACK(help_tileset_callback)},
1490       {"HELP_NATIONS", NULL, _("About Nations"),
1491        NULL, NULL, G_CALLBACK(help_nations_callback)},
1492 
1493       {"HELP_CONNECTING", NULL, _("Connecting"),
1494        NULL, NULL, G_CALLBACK(help_connecting_callback)},
1495       {"HELP_CONTROLS", NULL, _("Controls"),
1496        NULL, NULL, G_CALLBACK(help_controls_callback)},
1497       {"HELP_CMA", NULL, _("Citizen Governor"),
1498        NULL, NULL, G_CALLBACK(help_cma_callback)},
1499       {"HELP_CHATLINE", NULL, _("Chatline"),
1500        NULL, NULL, G_CALLBACK(help_chatline_callback)},
1501       {"HELP_WORKLIST_EDITOR", NULL, _("Worklist Editor"),
1502        NULL, NULL, G_CALLBACK(help_worklist_editor_callback)},
1503 
1504       {"HELP_LANGUAGES", NULL, _("Languages"),
1505        NULL, NULL, G_CALLBACK(help_language_callback)},
1506       {"HELP_COPYING", NULL, _("Copying"),
1507        NULL, NULL, G_CALLBACK(help_copying_callback)},
1508       {"HELP_ABOUT", NULL, _("About Freeciv"),
1509        NULL, NULL, G_CALLBACK(help_about_callback)}
1510     };
1511 
1512     const GtkToggleActionEntry toggle_entries[] = {
1513       /* Game menu. */
1514       {"SAVE_OPTIONS_ON_EXIT", NULL, _("Save Options on _Exit"),
1515        NULL, NULL, G_CALLBACK(save_options_on_exit_callback), TRUE},
1516 
1517       /* Edit menu. */
1518       {"EDIT_MODE", GTK_STOCK_EDIT, _("_Editing Mode"),
1519        "<Control>e", NULL, G_CALLBACK(edit_mode_callback), FALSE},
1520 
1521       /* View menu. */
1522       {"SHOW_CITY_OUTLINES", NULL, _("Cit_y Outlines"),
1523        "<Control>y", NULL, G_CALLBACK(show_city_outlines_callback), FALSE},
1524       {"SHOW_CITY_OUTPUT", NULL, _("City Output"),
1525        "<Control>w", NULL, G_CALLBACK(show_city_output_callback), FALSE},
1526       {"SHOW_MAP_GRID", NULL, _("Map _Grid"),
1527        "<Control>g", NULL, G_CALLBACK(show_map_grid_callback), FALSE},
1528       {"SHOW_NATIONAL_BORDERS", NULL, _("National _Borders"),
1529        "<Control>b", NULL,
1530        G_CALLBACK(show_national_borders_callback), FALSE},
1531       {"SHOW_NATIVE_TILES", NULL, _("Native Tiles"),
1532        "<Shift><Control>n", NULL,
1533        G_CALLBACK(show_native_tiles_callback), FALSE},
1534       {"SHOW_CITY_FULL_BAR", NULL, _("City Full Bar"),
1535        NULL, NULL, G_CALLBACK(show_city_full_bar_callback), FALSE},
1536       {"SHOW_CITY_NAMES", NULL, _("City _Names"),
1537        "<Control>n", NULL, G_CALLBACK(show_city_names_callback), FALSE},
1538       {"SHOW_CITY_GROWTH", NULL, _("City G_rowth"),
1539        "<Control>r", NULL, G_CALLBACK(show_city_growth_callback), FALSE},
1540       {"SHOW_CITY_PRODUCTIONS", NULL, _("City _Production Levels"),
1541        "<Control>p", NULL,
1542        G_CALLBACK(show_city_productions_callback), FALSE},
1543       {"SHOW_CITY_BUY_COST", NULL, _("City Buy Cost"),
1544        NULL, NULL, G_CALLBACK(show_city_buy_cost_callback), FALSE},
1545       {"SHOW_CITY_TRADE_ROUTES", NULL, _("City Tra_deroutes"),
1546        "<Control>d", NULL,
1547        G_CALLBACK(show_city_trade_routes_callback), FALSE},
1548 
1549       {"SHOW_TERRAIN", NULL, _("_Terrain"),
1550        NULL, NULL, G_CALLBACK(show_terrain_callback), FALSE},
1551       {"SHOW_COASTLINE", NULL, _("C_oastline"),
1552        NULL, NULL, G_CALLBACK(show_coastline_callback), FALSE},
1553 
1554       {"SHOW_PATHS", NULL, _("_Paths"),
1555        NULL, NULL, G_CALLBACK(show_road_rails_callback), FALSE},
1556       {"SHOW_IRRIGATION", NULL, _("_Irrigation"),
1557        NULL, NULL, G_CALLBACK(show_irrigation_callback), FALSE},
1558       {"SHOW_MINES", NULL, _("_Mines"),
1559        NULL, NULL, G_CALLBACK(show_mine_callback), FALSE},
1560       {"SHOW_BASES", NULL, _("_Bases"),
1561        NULL, NULL, G_CALLBACK(show_bases_callback), FALSE},
1562 
1563       {"SHOW_RESOURCES", NULL, _("_Resources"),
1564        NULL, NULL, G_CALLBACK(show_resources_callback), FALSE},
1565       {"SHOW_HUTS", NULL, _("_Huts"),
1566        NULL, NULL, G_CALLBACK(show_huts_callback), FALSE},
1567       {"SHOW_POLLUTION", NULL, _("Po_llution & Fallout"),
1568        NULL, NULL, G_CALLBACK(show_pollution_callback), FALSE},
1569       {"SHOW_CITIES", NULL, _("Citi_es"),
1570        NULL, NULL, G_CALLBACK(show_cities_callback), FALSE},
1571       {"SHOW_UNITS", NULL, _("_Units"),
1572        NULL, NULL, G_CALLBACK(show_units_callback), FALSE},
1573       {"SHOW_UNIT_SOLID_BG", NULL, _("Unit Solid Background"),
1574        NULL, NULL, G_CALLBACK(show_unit_solid_bg_callback), FALSE},
1575       {"SHOW_UNIT_SHIELDS", NULL, _("Unit shields"),
1576        NULL, NULL, G_CALLBACK(show_unit_shields_callback), FALSE},
1577       {"SHOW_FOCUS_UNIT", NULL, _("Focu_s Unit"),
1578        NULL, NULL, G_CALLBACK(show_focus_unit_callback), FALSE},
1579       {"SHOW_FOG_OF_WAR", NULL, _("Fog of _War"),
1580        NULL, NULL, G_CALLBACK(show_fog_of_war_callback), FALSE},
1581       {"SHOW_BETTER_FOG_OF_WAR", NULL, _("Better Fog of War"),
1582        NULL, NULL, G_CALLBACK(show_better_fog_of_war_callback), FALSE},
1583 
1584       {"FULL_SCREEN", NULL, _("_Fullscreen"),
1585        "<Alt>Return", NULL, G_CALLBACK(full_screen_callback), FALSE}
1586     };
1587 
1588     group = gtk_action_group_new("SafeGroup");
1589     gtk_action_group_add_actions(group, menu_entries,
1590                                  G_N_ELEMENTS(menu_entries), NULL);
1591     gtk_action_group_add_actions(group, action_entries,
1592                                  G_N_ELEMENTS(action_entries), NULL);
1593     gtk_action_group_add_toggle_actions(group, toggle_entries,
1594                                         G_N_ELEMENTS(toggle_entries), NULL);
1595   }
1596 
1597   return group;
1598 }
1599 
1600 /****************************************************************
1601   Returns the group of the actions which are available only
1602   when the edit mode is enabled.  Create it if not existent.
1603 *****************************************************************/
get_edit_group(void)1604 static GtkActionGroup *get_edit_group(void)
1605 {
1606   static GtkActionGroup *group = NULL;
1607 
1608   if (!group) {
1609     const GtkActionEntry action_entries[] = {
1610       /* Edit menu. */
1611       {"RECALC_BORDERS", NULL, _("Recalculate _Borders"),
1612        NULL, NULL, G_CALLBACK(recalc_borders_callback)},
1613       {"TOGGLE_FOG", NULL, _("Toggle Fog of _War"),
1614        "<Control>m", NULL, G_CALLBACK(toggle_fog_callback)},
1615       {"SCENARIO_PROPERTIES", NULL, _("Game/Scenario Properties"),
1616        NULL, NULL, G_CALLBACK(scenario_properties_callback)},
1617       {"SAVE_SCENARIO", GTK_STOCK_SAVE_AS, _("Save Scenario"),
1618        NULL, NULL, G_CALLBACK(save_scenario_callback)}
1619     };
1620 
1621     group = gtk_action_group_new("EditGroup");
1622     gtk_action_group_add_actions(group, action_entries,
1623                                  G_N_ELEMENTS(action_entries), NULL);
1624   }
1625 
1626   return group;
1627 }
1628 
1629 /****************************************************************
1630   Returns the group of the actions which are available only
1631   when units are selected.  Create it if not existent.
1632 *****************************************************************/
get_unit_group(void)1633 static GtkActionGroup *get_unit_group(void)
1634 {
1635   static GtkActionGroup *group = NULL;
1636 
1637   if (!group) {
1638     const GtkActionEntry menu_entries[] = {
1639       {"MENU_SELECT", NULL, _("_Select"), NULL, NULL, NULL},
1640       {"MENU_UNIT", NULL, _("_Unit"), NULL, NULL, NULL},
1641       {"MENU_WORK", NULL, _("_Work"), NULL, NULL, NULL},
1642       {"MENU_COMBAT", NULL, _("_Combat"), NULL, NULL, NULL},
1643       {"MENU_BUILD_BASE", NULL, _("Build _Base"), NULL, NULL, NULL},
1644       {"MENU_BUILD_PATH", NULL, _("Build _Path"), NULL, NULL, NULL}
1645     };
1646 
1647     const GtkActionEntry action_entries[] = {
1648       /* Select menu. */
1649       {"SELECT_SINGLE", NULL, _("_Single Unit (Unselect Others)"),
1650        "z", NULL, G_CALLBACK(select_single_callback)},
1651       {"SELECT_ALL_ON_TILE", NULL, _("_All On Tile"),
1652        "v", NULL, G_CALLBACK(select_all_on_tile_callback)},
1653 
1654       {"SELECT_SAME_TYPE_TILE", NULL, _("Same Type on _Tile"),
1655        "<shift>v", NULL, G_CALLBACK(select_same_type_tile_callback)},
1656       {"SELECT_SAME_TYPE_CONT", NULL, _("Same Type on _Continent"),
1657        "<shift>c", NULL, G_CALLBACK(select_same_type_cont_callback)},
1658       {"SELECT_SAME_TYPE", NULL, _("Same Type _Everywhere"),
1659        "<shift>x", NULL, G_CALLBACK(select_same_type_callback)},
1660 
1661       {"SELECT_DLG", NULL, _("Unit selection dialog"),
1662        NULL, NULL, G_CALLBACK(select_dialog_callback)},
1663 
1664       {"UNIT_WAIT", NULL, _("_Wait"),
1665        "w", NULL, G_CALLBACK(unit_wait_callback)},
1666       {"UNIT_DONE", NULL, _("_Done"),
1667        "space", NULL, G_CALLBACK(unit_done_callback)},
1668 
1669       /* Unit menu. */
1670       {"UNIT_GOTO", NULL, _("_Go to"),
1671        "g", NULL, G_CALLBACK(unit_goto_callback)},
1672       {"UNIT_GOTO_CITY", NULL, _("Go _to/Airlift to City..."),
1673        "t", NULL, G_CALLBACK(unit_goto_city_callback)},
1674       {"UNIT_RETURN", NULL, _("_Return to Nearest City"),
1675        "<Shift>g", NULL, G_CALLBACK(unit_return_callback)},
1676       {"UNIT_EXPLORE", NULL, _("Auto E_xplore"),
1677        "x", NULL, G_CALLBACK(unit_explore_callback)},
1678       {"UNIT_PATROL", NULL, _("_Patrol"),
1679        "q", NULL, G_CALLBACK(unit_patrol_callback)},
1680 
1681       {"UNIT_SENTRY", NULL, _("_Sentry"),
1682        "s", NULL, G_CALLBACK(unit_sentry_callback)},
1683       {"UNIT_UNSENTRY", NULL, _("Uns_entry All On Tile"),
1684        "<Shift>s", NULL, G_CALLBACK(unit_unsentry_callback)},
1685 
1686       {"UNIT_LOAD", NULL, _("_Load"),
1687        "l", NULL, G_CALLBACK(unit_load_callback)},
1688       {"UNIT_UNLOAD", NULL, _("_Unload"),
1689        "u", NULL, G_CALLBACK(unit_unload_callback)},
1690       {"UNIT_UNLOAD_TRANSPORTER", NULL, _("U_nload All From Transporter"),
1691        "<Shift>t", NULL, G_CALLBACK(unit_unload_transporter_callback)},
1692 
1693       {"UNIT_HOMECITY", NULL, _("Set _Home City"),
1694        "h", NULL, G_CALLBACK(unit_homecity_callback)},
1695       {"UNIT_UPGRADE", NULL, _("Upgr_ade"),
1696        "<Shift>u", NULL, G_CALLBACK(unit_upgrade_callback)},
1697       {"UNIT_CONVERT", NULL, _("C_onvert"),
1698        "<Shift>o", NULL, G_CALLBACK(unit_convert_callback)},
1699       {"UNIT_DISBAND", NULL, _("_Disband"),
1700        "<Shift>d", NULL, G_CALLBACK(unit_disband_callback)},
1701 
1702       /* Work menu. */
1703       {"BUILD_CITY", NULL, _("_Build City"),
1704        "b", NULL, G_CALLBACK(build_city_callback)},
1705       {"GO_BUILD_CITY", NULL, _("Go _to and Build city"),
1706        "<Shift>b", NULL, G_CALLBACK(go_build_city_callback)},
1707       {"AUTO_SETTLER", NULL, _("_Auto Settler"),
1708        "a", NULL, G_CALLBACK(auto_settle_callback)},
1709 
1710       {"BUILD_ROAD", NULL, _("Build _Road"),
1711        "r", NULL, G_CALLBACK(build_road_callback)},
1712       {"BUILD_IRRIGATION", NULL, _("Build _Irrigation"),
1713        "i", NULL, G_CALLBACK(build_irrigation_callback)},
1714       {"BUILD_MINE", NULL, _("Build _Mine"),
1715        "m", NULL, G_CALLBACK(build_mine_callback)},
1716 
1717       {"CONNECT_ROAD", NULL, _("Connect With Roa_d"),
1718        "<Shift>r", NULL, G_CALLBACK(connect_road_callback)},
1719       {"CONNECT_RAIL", NULL, _("Connect With Rai_l"),
1720        "<Shift>l", NULL, G_CALLBACK(connect_rail_callback)},
1721       {"CONNECT_IRRIGATION", NULL, _("Connect With Irri_gation"),
1722        "<Shift>i", NULL, G_CALLBACK(connect_irrigation_callback)},
1723 
1724       {"TRANSFORM_TERRAIN", NULL, _("Transf_orm Terrain"),
1725        "o", NULL, G_CALLBACK(transform_terrain_callback)},
1726       {"CLEAN_POLLUTION", NULL, _("Clean _Pollution"),
1727        "p", NULL, G_CALLBACK(clean_pollution_callback)},
1728       {"CLEAN_FALLOUT", NULL, _("Clean _Nuclear Fallout"),
1729        "n", NULL, G_CALLBACK(clean_fallout_callback)},
1730 
1731       /* Combat menu. */
1732       {"FORTIFY", NULL, _("Fortify"),
1733        "f", NULL, G_CALLBACK(fortify_callback)},
1734       {"BUILD_FORTRESS", NULL, _("Build Fortress"),
1735        "<Shift>f", NULL, G_CALLBACK(build_fortress_callback)},
1736       {"BUILD_AIRBASE", NULL, _("Build Airbase"),
1737        "<Shift>e", NULL, G_CALLBACK(build_airbase_callback)},
1738 
1739       {"DO_PILLAGE", NULL, _("_Pillage"),
1740        "<Shift>p", NULL, G_CALLBACK(do_pillage_callback)},
1741       /* TRANS: Menu item to bring up the action selection dialog. */
1742       {"DIPLOMAT_ACTION", NULL, _("_Do..."),
1743        "d", NULL, G_CALLBACK(diplomat_action_callback)},
1744       {"EXPLODE_NUKE", NULL, _("Explode _Nuclear"),
1745        "<Shift>n", NULL, G_CALLBACK(explode_nuke_callback)},
1746     };
1747 
1748     group = gtk_action_group_new("UnitGroup");
1749     gtk_action_group_add_actions(group, menu_entries,
1750                                  G_N_ELEMENTS(menu_entries), NULL);
1751     gtk_action_group_add_actions(group, action_entries,
1752                                  G_N_ELEMENTS(action_entries), NULL);
1753   }
1754 
1755   return group;
1756 }
1757 
1758 /****************************************************************
1759   Returns the group of the actions which are available only
1760   when the user is really playing, not observing.  Create it
1761   if not existent.
1762 *****************************************************************/
get_playing_group(void)1763 static GtkActionGroup *get_playing_group(void)
1764 {
1765   static GtkActionGroup *group = NULL;
1766 
1767   if (!group) {
1768     const GtkActionEntry menu_entries[] = {
1769       {"MENU_GOVERNMENT", NULL, _("_Government"), NULL, NULL, NULL},
1770     };
1771 
1772     const GtkActionEntry action_entries[] = {
1773       /* Civilization menu. */
1774       {"TAX_RATE", NULL, _("_Tax Rates..."),
1775        "<Control>t", NULL, G_CALLBACK(tax_rate_callback)},
1776       /* Civilization/Government menu. */
1777       {"START_REVOLUTION", NULL, _("_Revolution..."),
1778        "<Shift><Control>r", NULL, G_CALLBACK(government_callback)},
1779     };
1780 
1781     group = gtk_action_group_new("PlayingGroup");
1782     gtk_action_group_add_actions(group, menu_entries,
1783                                  G_N_ELEMENTS(menu_entries), NULL);
1784     /* NULL for user_data parameter is required by government_callback() */
1785     gtk_action_group_add_actions(group, action_entries,
1786                                  G_N_ELEMENTS(action_entries), NULL);
1787   }
1788 
1789   return group;
1790 }
1791 
1792 /****************************************************************
1793   Returns the group of the actions which are available only
1794   when the user is attached to a particular player, playing or
1795   observing (but not global observing).  Create it if not existent.
1796 *****************************************************************/
get_player_group(void)1797 static GtkActionGroup *get_player_group(void)
1798 {
1799   static GtkActionGroup *group = NULL;
1800 
1801   if (!group) {
1802     const GtkActionEntry action_entries[] = {
1803       /* View menu. */
1804       {"CENTER_VIEW", NULL, _("_Center View"),
1805        "c", NULL, G_CALLBACK(center_view_callback)},
1806 
1807       /* Civilization menu. */
1808       {"REPORT_ECONOMY", NULL, _("_Economy"),
1809        "F5", NULL, G_CALLBACK(report_economy_callback)},
1810       {"REPORT_RESEARCH", NULL, _("_Research"),
1811        "F6", NULL, G_CALLBACK(report_research_callback)},
1812 
1813       {"POLICIES", NULL, _("_Policies..."),
1814        "<Shift><Control>p", NULL, G_CALLBACK(multiplier_callback)},
1815 
1816       {"REPORT_SPACESHIP", NULL, _("_Spaceship"),
1817        "F12", NULL, G_CALLBACK(report_spaceship_callback)},
1818       {"REPORT_ACHIEVEMENTS", NULL, _("_Achievements"),
1819        "asterisk", NULL, G_CALLBACK(report_achievements_callback)}
1820     };
1821 
1822     group = gtk_action_group_new("PlayerGroup");
1823     gtk_action_group_add_actions(group, action_entries,
1824                                  G_N_ELEMENTS(action_entries), NULL);
1825   }
1826 
1827   return group;
1828 }
1829 
1830 /****************************************************************
1831   Returns the name of the file readable by the GtkUIManager.
1832 *****************************************************************/
get_ui_filename(void)1833 static const gchar *get_ui_filename(void)
1834 {
1835   static char filename[256];
1836   const char *name;
1837 
1838   if ((name = getenv("FREECIV_MENUS"))
1839       || (name = fileinfoname(get_data_dirs(), "gtk2_menus.xml"))) {
1840     sz_strlcpy(filename, name);
1841   } else {
1842     log_error("Gtk menus: file definition not found");
1843     filename[0] = '\0';
1844   }
1845 
1846   log_verbose("ui menu file is \"%s\".", filename);
1847   return filename;
1848 }
1849 
1850 /****************************************************************
1851   Called when a main widget is added by the GtkUIManager.
1852 *****************************************************************/
add_widget_callback(GtkUIManager * mgr,GtkWidget * widget,gpointer data)1853 static void add_widget_callback(GtkUIManager *mgr, GtkWidget *widget,
1854                                 gpointer data)
1855 {
1856   gtk_box_pack_start(GTK_BOX(data), widget, TRUE, TRUE, 0);
1857   gtk_widget_show(widget);
1858 }
1859 
1860 /****************************************************************
1861   Creates the menu bar.
1862 *****************************************************************/
setup_menus(GtkWidget * window)1863 GtkWidget *setup_menus(GtkWidget *window)
1864 {
1865   GtkWidget *menubar = gtk_hbox_new(FALSE, 0);
1866   GError *error = NULL;
1867 
1868   /* Creates the UI manager. */
1869   ui_manager = gtk_ui_manager_new();
1870   /* FIXME - following line commented out due to Gna bug #17162 */
1871   /* gtk_ui_manager_set_add_tearoffs(ui_manager, TRUE); */
1872   g_signal_connect(ui_manager, "add_widget",
1873                    G_CALLBACK(add_widget_callback), menubar);
1874 
1875   /* Creates the actions. */
1876   gtk_ui_manager_insert_action_group(ui_manager, get_safe_group(), -1);
1877   gtk_ui_manager_insert_action_group(ui_manager, get_edit_group(), -1);
1878   gtk_ui_manager_insert_action_group(ui_manager, get_unit_group(), -1);
1879   gtk_ui_manager_insert_action_group(ui_manager, get_playing_group(), -1);
1880   gtk_ui_manager_insert_action_group(ui_manager, get_player_group(), -1);
1881 
1882   /* Enable shortcuts. */
1883   gtk_window_add_accel_group(GTK_WINDOW(window),
1884                              gtk_ui_manager_get_accel_group(ui_manager));
1885 
1886   /* Load the menus. */
1887   if (0 == gtk_ui_manager_add_ui_from_file(ui_manager,
1888                                            get_ui_filename(), &error)) {
1889     log_error("Gtk menus: %s", error->message);
1890     g_error_free(error);
1891   }
1892 
1893 #ifndef DEBUG
1894   menus_set_visible(get_safe_group(), "RELOAD_TILESET", FALSE, FALSE);
1895 #endif /* DEBUG */
1896 
1897   return menubar;
1898 }
1899 
1900 /****************************************************************
1901   Sets an action active.
1902 *****************************************************************/
menus_set_active(GtkActionGroup * group,const gchar * action_name,gboolean is_active)1903 static void menus_set_active(GtkActionGroup *group,
1904                              const gchar *action_name,
1905                              gboolean is_active)
1906 {
1907   GtkAction *action = gtk_action_group_get_action(group, action_name);
1908 
1909   if (!action) {
1910     log_error("Can't set active for non-existent "
1911               "action \"%s\" in group \"%s\".",
1912               action_name, gtk_action_group_get_name(group));
1913     return;
1914   }
1915 
1916   if (!GTK_IS_TOGGLE_ACTION(action)) {
1917     log_error("Can't set active for non-togglable "
1918               "action \"%s\" in group \"%s\".",
1919               action_name, gtk_action_group_get_name(group));
1920     return;
1921   }
1922 
1923   gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), is_active);
1924 }
1925 
1926 /****************************************************************
1927   Sets an action sensitive.
1928 *****************************************************************/
menus_set_sensitive(GtkActionGroup * group,const gchar * action_name,gboolean is_sensitive)1929 static void menus_set_sensitive(GtkActionGroup *group,
1930                                 const gchar *action_name,
1931                                 gboolean is_sensitive)
1932 {
1933   GtkAction *action = gtk_action_group_get_action(group, action_name);
1934 
1935   if (!action) {
1936     log_error("Can't set active for non-existent "
1937               "action \"%s\" in group \"%s\".",
1938               action_name, gtk_action_group_get_name(group));
1939     return;
1940   }
1941 
1942   gtk_action_set_sensitive(action, is_sensitive);
1943 }
1944 
1945 /****************************************************************
1946   Sets an action visible.
1947 *****************************************************************/
menus_set_visible(GtkActionGroup * group,const gchar * action_name,gboolean is_visible,gboolean is_sensitive)1948 static void menus_set_visible(GtkActionGroup *group,
1949                               const gchar *action_name,
1950                               gboolean is_visible,
1951                               gboolean is_sensitive)
1952 {
1953   GtkAction *action = gtk_action_group_get_action(group, action_name);
1954 
1955   if (!action) {
1956     log_error("Can't set visible for non-existent "
1957               "action \"%s\" in group \"%s\".",
1958               action_name, gtk_action_group_get_name(group));
1959     return;
1960   }
1961 
1962   gtk_action_set_visible(action, is_visible);
1963   gtk_action_set_sensitive(action, is_sensitive);
1964 }
1965 
1966 /****************************************************************
1967   Renames an action.
1968 *****************************************************************/
menus_rename(GtkActionGroup * group,const gchar * action_name,const gchar * new_label)1969 static void menus_rename(GtkActionGroup *group,
1970                          const gchar *action_name,
1971                          const gchar *new_label)
1972 {
1973   GtkAction *action = gtk_action_group_get_action(group, action_name);
1974 
1975   if (!action) {
1976     log_error("Can't rename non-existent "
1977               "action \"%s\" in group \"%s\".",
1978               action_name, gtk_action_group_get_name(group));
1979     return;
1980   }
1981 
1982   /* gtk_action_set_label() was added in Gtk 2.16. */
1983   g_object_set(G_OBJECT(action), "label", new_label, NULL);
1984 }
1985 
1986 /****************************************************************
1987   Find the child menu of an action.
1988 *****************************************************************/
find_action_menu(GtkActionGroup * group,const gchar * action_name)1989 static GtkMenu *find_action_menu(GtkActionGroup *group,
1990                                  const gchar *action_name)
1991 {
1992   GtkAction *action = gtk_action_group_get_action(group, action_name);
1993   GSList *iter;
1994 
1995   if (!action) {
1996     return NULL;
1997   }
1998 
1999   for (iter = gtk_action_get_proxies(action); iter;
2000        iter = g_slist_next(iter)) {
2001     if (GTK_IS_MENU_ITEM(iter->data)) {
2002       return GTK_MENU(gtk_menu_item_get_submenu(GTK_MENU_ITEM(iter->data)));
2003     }
2004   }
2005 
2006   return NULL;
2007 }
2008 
2009 /****************************************************************
2010   Update the sensitivity of the items in the view menu.
2011 *****************************************************************/
view_menu_update_sensitivity(void)2012 static void view_menu_update_sensitivity(void)
2013 {
2014   GtkActionGroup *safe_group = get_safe_group();
2015 
2016   /* The "full" city bar (i.e. the new way of drawing the
2017    * city name), can draw the city growth even without drawing
2018    * the city name. But the old method cannot. */
2019   if (gui_options.draw_full_citybar) {
2020     menus_set_sensitive(safe_group, "SHOW_CITY_GROWTH", TRUE);
2021     menus_set_sensitive(safe_group, "SHOW_CITY_TRADE_ROUTES", TRUE);
2022   } else {
2023     menus_set_sensitive(safe_group, "SHOW_CITY_GROWTH",
2024                         gui_options.draw_city_names);
2025     menus_set_sensitive(safe_group, "SHOW_CITY_TRADE_ROUTES",
2026                         gui_options.draw_city_names);
2027   }
2028 
2029   menus_set_sensitive(safe_group, "SHOW_CITY_BUY_COST",
2030                       gui_options.draw_city_productions);
2031   menus_set_sensitive(safe_group, "SHOW_COASTLINE",
2032                       !gui_options.draw_terrain);
2033   menus_set_sensitive(safe_group, "SHOW_UNIT_SOLID_BG",
2034                       gui_options.draw_units || gui_options.draw_focus_unit);
2035   menus_set_sensitive(safe_group, "SHOW_UNIT_SHIELDS",
2036                       gui_options.draw_units || gui_options.draw_focus_unit);
2037   menus_set_sensitive(safe_group, "SHOW_FOCUS_UNIT",
2038                       !gui_options.draw_units);
2039   menus_set_sensitive(safe_group, "SHOW_BETTER_FOG_OF_WAR",
2040                       gui_options.draw_fog_of_war);
2041 }
2042 
2043 /****************************************************************************
2044   Return the text for the tile, changed by the activity.
2045 
2046   Should only be called for irrigation, mining, or transformation, and
2047   only when the activity changes the base terrain type.
2048 ****************************************************************************/
get_tile_change_menu_text(struct tile * ptile,enum unit_activity activity)2049 static const char *get_tile_change_menu_text(struct tile *ptile,
2050                                              enum unit_activity activity)
2051 {
2052   struct tile *newtile = tile_virtual_new(ptile);
2053   const char *text;
2054 
2055   tile_apply_activity(newtile, activity, NULL);
2056   text = tile_get_info_text(newtile, FALSE, 0);
2057   tile_virtual_destroy(newtile);
2058   return text;
2059 }
2060 
2061 /****************************************************************
2062   Updates the menus.
2063 *****************************************************************/
real_menus_update(void)2064 void real_menus_update(void)
2065 {
2066   GtkActionGroup *safe_group;
2067   GtkActionGroup *edit_group;
2068   GtkActionGroup *unit_group;
2069   GtkActionGroup *playing_group;
2070   struct unit_list *punits = NULL;
2071   bool units_all_same_tile = TRUE, units_all_same_type = TRUE;
2072   GtkMenu *menu;
2073   char acttext[128], irrtext[128], mintext[128], transtext[128];
2074   struct terrain *pterrain;
2075   bool conn_possible;
2076   struct road_type *proad;
2077   struct extra_type_list *extras;
2078 
2079   if (NULL == ui_manager && !can_client_change_view()) {
2080     return;
2081   }
2082 
2083   safe_group = get_safe_group();
2084   edit_group = get_edit_group();
2085   unit_group = get_unit_group();
2086   playing_group = get_playing_group();
2087 
2088   if (get_num_units_in_focus() > 0) {
2089     const struct tile *ptile = NULL;
2090     const struct unit_type *ptype = NULL;
2091     punits = get_units_in_focus();
2092     unit_list_iterate(punits, punit) {
2093       fc_assert((ptile==NULL) == (ptype==NULL));
2094       if (ptile || ptype) {
2095         if (unit_tile(punit) != ptile) {
2096           units_all_same_tile = FALSE;
2097         }
2098         if (unit_type_get(punit) != ptype) {
2099           units_all_same_type = FALSE;
2100         }
2101       } else {
2102         ptile = unit_tile(punit);
2103         ptype = unit_type_get(punit);
2104       }
2105     } unit_list_iterate_end;
2106   }
2107 
2108   gtk_action_group_set_sensitive(edit_group,
2109                                  editor_is_active());
2110   gtk_action_group_set_sensitive(playing_group, can_client_issue_orders()
2111                                  && !editor_is_active());
2112   gtk_action_group_set_sensitive(unit_group, can_client_issue_orders()
2113                                  && !editor_is_active() && punits != NULL);
2114 
2115   menus_set_active(safe_group, "EDIT_MODE", game.info.is_edit_mode);
2116   menus_set_sensitive(safe_group, "EDIT_MODE",
2117                       can_conn_enable_editing(&client.conn));
2118   editgui_refresh();
2119 
2120   {
2121     char road_buf[500];
2122 
2123     proad = road_by_compat_special(ROCO_ROAD);
2124     if (proad != NULL) {
2125       /* TRANS: Connect with some road type (Road/Railroad) */
2126       snprintf(road_buf, sizeof(road_buf), _("Connect With %s"),
2127                extra_name_translation(road_extra_get(proad)));
2128       menus_rename(unit_group, "CONNECT_ROAD", road_buf);
2129     }
2130 
2131     proad = road_by_compat_special(ROCO_RAILROAD);
2132     if (proad != NULL) {
2133       snprintf(road_buf, sizeof(road_buf), _("Connect With %s"),
2134                extra_name_translation(road_extra_get(proad)));
2135       menus_rename(unit_group, "CONNECT_RAIL", road_buf);
2136     }
2137   }
2138 
2139   if (!can_client_issue_orders()) {
2140     return;
2141   }
2142 
2143   /* Set government sensitivity. */
2144   if ((menu = find_action_menu(playing_group, "MENU_GOVERNMENT"))) {
2145     GList *list, *iter;
2146     struct government *pgov;
2147 
2148     list = gtk_container_get_children(GTK_CONTAINER(menu));
2149     for (iter = list; NULL != iter; iter = g_list_next(iter)) {
2150       pgov = g_object_get_data(G_OBJECT(iter->data), "government");
2151       if (NULL != pgov) {
2152         gtk_widget_set_sensitive(GTK_WIDGET(iter->data),
2153                                  can_change_to_government(client_player(),
2154                                                           pgov));
2155       } else {
2156         /* Revolution without target government */
2157         gtk_widget_set_sensitive(GTK_WIDGET(iter->data),
2158                                  untargeted_revolution_allowed());
2159       }
2160     }
2161     g_list_free(list);
2162   }
2163 
2164   if (!punits) {
2165     return;
2166   }
2167 
2168   /* Remaining part of this function: Update Unit, Work, and Combat menus */
2169 
2170   /* Set base sensitivity. */
2171   if ((menu = find_action_menu(unit_group, "MENU_BUILD_BASE"))) {
2172     GList *list, *iter;
2173     struct extra_type *pextra;
2174 
2175     list = gtk_container_get_children(GTK_CONTAINER(menu));
2176     for (iter = list; NULL != iter; iter = g_list_next(iter)) {
2177       pextra = g_object_get_data(G_OBJECT(iter->data), "base");
2178       if (NULL != pextra) {
2179         gtk_widget_set_sensitive(GTK_WIDGET(iter->data),
2180                                  can_units_do_activity_targeted(punits,
2181                                                                 ACTIVITY_BASE,
2182                                                                 pextra));
2183       }
2184     }
2185     g_list_free(list);
2186   }
2187 
2188   /* Set road sensitivity. */
2189   if ((menu = find_action_menu(unit_group, "MENU_BUILD_PATH"))) {
2190     GList *list, *iter;
2191     struct extra_type *pextra;
2192 
2193     list = gtk_container_get_children(GTK_CONTAINER(menu));
2194     for (iter = list; NULL != iter; iter = g_list_next(iter)) {
2195       pextra = g_object_get_data(G_OBJECT(iter->data), "road");
2196       if (NULL != pextra) {
2197         gtk_widget_set_sensitive(GTK_WIDGET(iter->data),
2198                                  can_units_do_activity_targeted(punits,
2199                                                                 ACTIVITY_GEN_ROAD,
2200                                                                 pextra));
2201       }
2202     }
2203     g_list_free(list);
2204   }
2205 
2206   /* Enable the button for adding to a city in all cases, so we
2207    * get an eventual error message from the server if we try. */
2208   menus_set_sensitive(unit_group, "BUILD_CITY",
2209             (can_units_do(punits, unit_can_add_or_build_city)
2210              || can_units_do(punits, unit_can_help_build_wonder_here)));
2211   menus_set_sensitive(unit_group, "GO_BUILD_CITY",
2212                       units_contain_cityfounder(punits));
2213   menus_set_sensitive(unit_group, "BUILD_ROAD",
2214                       (can_units_do_any_road(punits)
2215                        || can_units_do(punits,
2216                                        unit_can_est_trade_route_here)));
2217   menus_set_sensitive(unit_group, "BUILD_IRRIGATION",
2218                       can_units_do_activity(punits, ACTIVITY_IRRIGATE));
2219   menus_set_sensitive(unit_group, "BUILD_MINE",
2220                       can_units_do_activity(punits, ACTIVITY_MINE));
2221   menus_set_sensitive(unit_group, "TRANSFORM_TERRAIN",
2222                       can_units_do_activity(punits, ACTIVITY_TRANSFORM));
2223   menus_set_sensitive(unit_group, "FORTIFY",
2224                       can_units_do_activity(punits,
2225                                             ACTIVITY_FORTIFYING));
2226   menus_set_sensitive(unit_group, "BUILD_FORTRESS",
2227                       can_units_do_base_gui(punits, BASE_GUI_FORTRESS));
2228   menus_set_sensitive(unit_group, "BUILD_AIRBASE",
2229                       can_units_do_base_gui(punits, BASE_GUI_AIRBASE));
2230   menus_set_sensitive(unit_group, "CLEAN_POLLUTION",
2231                       (can_units_do_activity(punits, ACTIVITY_POLLUTION)
2232                        || can_units_do(punits, can_unit_paradrop)));
2233   menus_set_sensitive(unit_group, "CLEAN_FALLOUT",
2234                       can_units_do_activity(punits, ACTIVITY_FALLOUT));
2235   menus_set_sensitive(unit_group, "UNIT_SENTRY",
2236                       can_units_do_activity(punits, ACTIVITY_SENTRY));
2237   /* FIXME: should conditionally rename "Pillage" to "Pillage..." in cases where
2238    * selecting the command results in a dialog box listing options of what to pillage */
2239   menus_set_sensitive(unit_group, "DO_PILLAGE",
2240                       can_units_do_activity(punits, ACTIVITY_PILLAGE));
2241   menus_set_sensitive(unit_group, "UNIT_DISBAND",
2242                       units_have_type_flag(punits, UTYF_UNDISBANDABLE, FALSE));
2243   menus_set_sensitive(unit_group, "UNIT_UPGRADE",
2244                       units_can_upgrade(punits));
2245   /* "UNIT_CONVERT" dealt with below */
2246   menus_set_sensitive(unit_group, "UNIT_HOMECITY",
2247                       can_units_do(punits, can_unit_change_homecity));
2248   menus_set_sensitive(unit_group, "UNIT_UNLOAD_TRANSPORTER",
2249                       units_are_occupied(punits));
2250   menus_set_sensitive(unit_group, "UNIT_LOAD",
2251                       units_can_load(punits));
2252   menus_set_sensitive(unit_group, "UNIT_UNLOAD",
2253                       units_can_unload(punits));
2254   menus_set_sensitive(unit_group, "UNIT_UNSENTRY",
2255                       units_have_activity_on_tile(punits,
2256                                                   ACTIVITY_SENTRY));
2257   menus_set_sensitive(unit_group, "AUTO_SETTLER",
2258                       can_units_do(punits, can_unit_do_autosettlers));
2259   menus_set_sensitive(unit_group, "UNIT_EXPLORE",
2260                       can_units_do_activity(punits, ACTIVITY_EXPLORE));
2261 
2262   proad = road_by_compat_special(ROCO_ROAD);
2263   if (proad != NULL) {
2264     struct extra_type *tgt;
2265 
2266     tgt = road_extra_get(proad);
2267 
2268     conn_possible = can_units_do_connect(punits, ACTIVITY_GEN_ROAD, tgt);
2269   } else {
2270     conn_possible = FALSE;
2271   }
2272   menus_set_sensitive(unit_group, "CONNECT_ROAD", conn_possible);
2273 
2274   proad = road_by_compat_special(ROCO_RAILROAD);
2275   if (proad != NULL) {
2276     struct extra_type *tgt;
2277 
2278     tgt = road_extra_get(proad);
2279 
2280     conn_possible = can_units_do_connect(punits, ACTIVITY_GEN_ROAD, tgt);
2281   } else {
2282     conn_possible = FALSE;
2283   }
2284   menus_set_sensitive(unit_group, "CONNECT_RAIL", conn_possible);
2285 
2286   extras = extra_type_list_by_cause(EC_IRRIGATION);
2287 
2288   if (extra_type_list_size(extras) > 0) {
2289     struct extra_type *tgt;
2290 
2291     tgt = extra_type_list_get(extras, 0);
2292     conn_possible = can_units_do_connect(punits, ACTIVITY_IRRIGATE, tgt);
2293   } else {
2294     conn_possible = FALSE;
2295   }
2296   menus_set_sensitive(unit_group, "CONNECT_IRRIGATION", conn_possible);
2297 
2298   menus_set_sensitive(unit_group, "DIPLOMAT_ACTION",
2299                       units_can_do_action(punits, ACTION_ANY, TRUE));
2300   menus_set_sensitive(unit_group, "EXPLODE_NUKE",
2301                       units_have_type_flag(punits, UTYF_NUCLEAR, TRUE));
2302 
2303   if (units_can_do_action(punits, ACTION_HELP_WONDER, TRUE)) {
2304     menus_rename(unit_group, "BUILD_CITY",
2305                  action_get_ui_name_mnemonic(ACTION_HELP_WONDER, "_"));
2306   } else {
2307     bool city_on_tile = FALSE;
2308 
2309     /* FIXME: this overloading doesn't work well with multiple focus
2310      * units. */
2311     unit_list_iterate(punits, punit) {
2312       if (tile_city(unit_tile(punit))) {
2313         city_on_tile = TRUE;
2314         break;
2315       }
2316     } unit_list_iterate_end;
2317 
2318     if (city_on_tile && units_have_type_flag(punits, UTYF_ADD_TO_CITY, TRUE)) {
2319       menus_rename(unit_group, "BUILD_CITY", _("Add to City"));
2320     } else {
2321       /* refresh default order */
2322       menus_rename(unit_group, "BUILD_CITY", _("_Build City"));
2323     }
2324   }
2325 
2326   if (units_can_do_action(punits, ACTION_TRADE_ROUTE, TRUE)) {
2327     menus_rename(unit_group, "BUILD_ROAD",
2328                  action_get_ui_name_mnemonic(ACTION_TRADE_ROUTE, "_"));
2329   } else if (units_have_type_flag(punits, UTYF_SETTLERS, TRUE)) {
2330     char road_item[500];
2331     struct extra_type *pextra = NULL;
2332 
2333     /* FIXME: this overloading doesn't work well with multiple focus
2334      * units. */
2335     unit_list_iterate(punits, punit) {
2336       pextra = next_extra_for_tile(unit_tile(punit), EC_ROAD,
2337                                    unit_owner(punit), punit);
2338      if (pextra != NULL) {
2339         break;
2340       }
2341     } unit_list_iterate_end;
2342 
2343     if (pextra != NULL) {
2344       /* TRANS: Build road of specific type (Road/Railroad) */
2345       snprintf(road_item, sizeof(road_item), _("Build %s"),
2346                extra_name_translation(pextra));
2347       menus_rename(unit_group, "BUILD_ROAD", road_item);
2348     }
2349   } else {
2350     menus_rename(unit_group, "BUILD_ROAD", _("Build _Road"));
2351   }
2352 
2353   if (units_all_same_type) {
2354     struct unit *punit = unit_list_get(punits, 0);
2355     struct unit_type *to_unittype =
2356       can_upgrade_unittype(client_player(), unit_type_get(punit));
2357     if (to_unittype) {
2358       /* TRANS: %s is a unit type. */
2359       fc_snprintf(acttext, sizeof(acttext), _("Upgr_ade to %s"),
2360                   utype_name_translation(
2361                     can_upgrade_unittype(client_player(),
2362                                          unit_type_get(punit))));
2363     } else {
2364       acttext[0] = '\0';
2365     }
2366   } else {
2367     acttext[0] = '\0';
2368   }
2369   if ('\0' != acttext[0]) {
2370     menus_rename(unit_group, "UNIT_UPGRADE", acttext);
2371   } else {
2372     menus_rename(unit_group, "UNIT_UPGRADE", _("Upgr_ade"));
2373   }
2374 
2375   if (units_can_convert(punits)) {
2376     menus_set_sensitive(unit_group, "UNIT_CONVERT", TRUE);
2377     if (units_all_same_type) {
2378       struct unit *punit = unit_list_get(punits, 0);
2379       /* TRANS: %s is a unit type. */
2380       fc_snprintf(acttext, sizeof(acttext), _("C_onvert to %s"),
2381                   utype_name_translation(unit_type_get(punit)->converted_to));
2382     } else {
2383       acttext[0] = '\0';
2384     }
2385   } else {
2386     menus_set_sensitive(unit_group, "UNIT_CONVERT", FALSE);
2387     acttext[0] = '\0';
2388   }
2389   if ('\0' != acttext[0]) {
2390     menus_rename(unit_group, "UNIT_CONVERT", acttext);
2391   } else {
2392     menus_rename(unit_group, "UNIT_CONVERT", _("C_onvert"));
2393   }
2394 
2395   if (units_all_same_tile) {
2396     struct unit *first = unit_list_get(punits, 0);
2397 
2398     pterrain = tile_terrain(unit_tile(first));
2399     if (pterrain->irrigation_result != T_NONE
2400         && pterrain->irrigation_result != pterrain) {
2401       fc_snprintf(irrtext, sizeof(irrtext), _("Change to %s"),
2402                   get_tile_change_menu_text(unit_tile(first),
2403                                             ACTIVITY_IRRIGATE));
2404     } else if (units_have_type_flag(punits, UTYF_SETTLERS, TRUE)) {
2405       struct extra_type *pextra = NULL;
2406 
2407       /* FIXME: this overloading doesn't work well with multiple focus
2408        * units. */
2409       unit_list_iterate(punits, punit) {
2410         pextra = next_extra_for_tile(unit_tile(punit), EC_IRRIGATION,
2411                                      unit_owner(punit), punit);
2412         if (pextra != NULL) {
2413           break;
2414         }
2415       } unit_list_iterate_end;
2416 
2417       if (pextra != NULL) {
2418         /* TRANS: Build irrigation of specific type */
2419         snprintf(irrtext, sizeof(irrtext), _("Build %s"),
2420                  extra_name_translation(pextra));
2421       } else {
2422         sz_strlcpy(irrtext, _("Build _Irrigation"));
2423       }
2424     } else {
2425       sz_strlcpy(irrtext, _("Build _Irrigation"));
2426     }
2427 
2428     if (pterrain->mining_result != T_NONE
2429         && pterrain->mining_result != pterrain) {
2430       fc_snprintf(mintext, sizeof(mintext), _("Change to %s"),
2431                   get_tile_change_menu_text(unit_tile(first), ACTIVITY_MINE));
2432     } else if (units_have_type_flag(punits, UTYF_SETTLERS, TRUE)) {
2433       struct extra_type *pextra = NULL;
2434 
2435       /* FIXME: this overloading doesn't work well with multiple focus
2436        * units. */
2437       unit_list_iterate(punits, punit) {
2438         pextra = next_extra_for_tile(unit_tile(punit), EC_MINE,
2439                                      unit_owner(punit), punit);
2440         if (pextra != NULL) {
2441           break;
2442         }
2443       } unit_list_iterate_end;
2444 
2445       if (pextra != NULL) {
2446         /* TRANS: Build mine of specific type */
2447         snprintf(mintext, sizeof(mintext), _("Build %s"),
2448                  extra_name_translation(pextra));
2449       } else {
2450         sz_strlcpy(mintext, _("Build _Mine"));
2451       }
2452     } else {
2453       sz_strlcpy(mintext, _("Build _Mine"));
2454     }
2455 
2456     if (pterrain->transform_result != T_NONE
2457         && pterrain->transform_result != pterrain) {
2458       fc_snprintf(transtext, sizeof(transtext), _("Transf_orm to %s"),
2459                   get_tile_change_menu_text(unit_tile(first),
2460                                             ACTIVITY_TRANSFORM));
2461     } else {
2462       sz_strlcpy(transtext, _("Transf_orm Terrain"));
2463     }
2464   } else {
2465     sz_strlcpy(irrtext, _("Build _Irrigation"));
2466     sz_strlcpy(mintext, _("Build _Mine"));
2467     sz_strlcpy(transtext, _("Transf_orm Terrain"));
2468   }
2469 
2470   menus_rename(unit_group, "BUILD_IRRIGATION", irrtext);
2471   menus_rename(unit_group, "BUILD_MINE", mintext);
2472   menus_rename(unit_group, "TRANSFORM_TERRAIN", transtext);
2473 
2474   if (units_have_type_flag(punits, UTYF_PARATROOPERS, TRUE)) {
2475     menus_rename(unit_group, "CLEAN_POLLUTION", _("Drop _Paratrooper"));
2476   } else {
2477     menus_rename(unit_group, "CLEAN_POLLUTION", _("Clean _Pollution"));
2478   }
2479 }
2480 
2481 /**************************************************************************
2482   Initialize menus (sensitivity, name, etc.) based on the
2483   current state and current ruleset, etc.  Call menus_update().
2484 **************************************************************************/
real_menus_init(void)2485 void real_menus_init(void)
2486 {
2487   GtkActionGroup *safe_group;
2488   GtkActionGroup *edit_group;
2489   GtkActionGroup *unit_group;
2490   GtkActionGroup *playing_group;
2491   GtkActionGroup *player_group;
2492   GtkMenu *menu;
2493 
2494   if (NULL == ui_manager) {
2495     return;
2496   }
2497 
2498   safe_group = get_safe_group();
2499   edit_group = get_edit_group();
2500   unit_group = get_unit_group();
2501   playing_group = get_playing_group();
2502   player_group = get_player_group();
2503 
2504   menus_set_sensitive(safe_group, "GAME_SAVE_AS",
2505                       can_client_access_hack()
2506                       && C_S_RUNNING <= client_state());
2507   menus_set_sensitive(safe_group, "GAME_SAVE",
2508                       can_client_access_hack()
2509                       && C_S_RUNNING <= client_state());
2510 
2511   menus_set_active(safe_group, "SAVE_OPTIONS_ON_EXIT",
2512                    gui_options.save_options_on_exit);
2513   menus_set_sensitive(safe_group, "SERVER_OPTIONS", client.conn.established);
2514 
2515   menus_set_sensitive(safe_group, "LEAVE",
2516                       client.conn.established);
2517 
2518   if (!can_client_change_view()) {
2519     gtk_action_group_set_sensitive(safe_group, FALSE);
2520     gtk_action_group_set_sensitive(edit_group, FALSE);
2521     gtk_action_group_set_sensitive(unit_group, FALSE);
2522     gtk_action_group_set_sensitive(player_group, FALSE);
2523     gtk_action_group_set_sensitive(playing_group, FALSE);
2524     return;
2525   }
2526 
2527   menus_rename(unit_group, "BUILD_FORTRESS", Q_(terrain_control.gui_type_base0));
2528   menus_rename(unit_group, "BUILD_AIRBASE", Q_(terrain_control.gui_type_base1));
2529 
2530   if ((menu = find_action_menu(playing_group, "MENU_GOVERNMENT"))) {
2531     GList *list, *iter;
2532     GtkWidget *item;
2533     char buf[256];
2534 
2535     /* Remove previous government entries. */
2536     list = gtk_container_get_children(GTK_CONTAINER(menu));
2537     for (iter = list; NULL != iter; iter = g_list_next(iter)) {
2538       if (g_object_get_data(G_OBJECT(iter->data), "government") != NULL
2539           || GTK_IS_SEPARATOR_MENU_ITEM(iter->data)) {
2540         gtk_widget_destroy(GTK_WIDGET(iter->data));
2541       }
2542     }
2543     g_list_free(list);
2544 
2545     /* Add new government entries. */
2546     item = gtk_separator_menu_item_new();
2547     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2548     gtk_widget_show(item);
2549 
2550     governments_iterate(g) {
2551       if (g != game.government_during_revolution) {
2552         struct sprite *gsprite;
2553 
2554         /* TRANS: %s is a government name */
2555         fc_snprintf(buf, sizeof(buf), _("%s..."),
2556                     government_name_translation(g));
2557         item = gtk_image_menu_item_new_with_label(buf);
2558         g_object_set_data(G_OBJECT(item), "government", g);
2559 
2560         if ((gsprite = get_government_sprite(tileset, g))) {
2561           GtkWidget *image;
2562 
2563           image = gtk_image_new_from_pixbuf(sprite_get_pixbuf(gsprite));
2564           gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
2565           gtk_widget_show(image);
2566         }
2567 
2568         g_signal_connect(item, "activate",
2569                          G_CALLBACK(government_callback), g);
2570         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2571         gtk_widget_show(item);
2572       }
2573     } governments_iterate_end;
2574   }
2575 
2576   if ((menu = find_action_menu(unit_group, "MENU_BUILD_BASE"))) {
2577     GList *list, *iter;
2578     GtkWidget *item;
2579 
2580     /* Remove previous base entries. */
2581     list = gtk_container_get_children(GTK_CONTAINER(menu));
2582     for (iter = list; NULL != iter; iter = g_list_next(iter)) {
2583       gtk_widget_destroy(GTK_WIDGET(iter->data));
2584     }
2585     g_list_free(list);
2586 
2587     /* Add new base entries. */
2588     extra_type_by_cause_iterate(EC_BASE, pextra) {
2589       if (pextra->buildable) {
2590         item = gtk_menu_item_new_with_label(extra_name_translation(pextra));
2591         g_object_set_data(G_OBJECT(item), "base", pextra);
2592         g_signal_connect(item, "activate", G_CALLBACK(base_callback), pextra);
2593         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2594         gtk_widget_show(item);
2595       }
2596     } extra_type_by_cause_iterate_end;
2597   }
2598 
2599   if ((menu = find_action_menu(unit_group, "MENU_BUILD_PATH"))) {
2600     GList *list, *iter;
2601     GtkWidget *item;
2602 
2603     /* Remove previous road entries. */
2604     list = gtk_container_get_children(GTK_CONTAINER(menu));
2605     for (iter = list; NULL != iter; iter = g_list_next(iter)) {
2606       gtk_widget_destroy(GTK_WIDGET(iter->data));
2607     }
2608     g_list_free(list);
2609 
2610     /* Add new road entries. */
2611     extra_type_by_cause_iterate(EC_ROAD, pextra) {
2612       if (pextra->buildable) {
2613         item = gtk_menu_item_new_with_label(extra_name_translation(pextra));
2614         g_object_set_data(G_OBJECT(item), "road", pextra);
2615         g_signal_connect(item, "activate", G_CALLBACK(road_callback), pextra);
2616         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2617         gtk_widget_show(item);
2618       }
2619     } extra_type_by_cause_iterate_end;
2620   }
2621 
2622   gtk_action_group_set_sensitive(safe_group, TRUE);
2623   gtk_action_group_set_sensitive(player_group, client_has_player());
2624 
2625   menus_set_sensitive(playing_group, "TAX_RATE",
2626                       game.info.changable_tax
2627                       && can_client_issue_orders());
2628   menus_set_sensitive(player_group, "POLICIES",
2629                       multiplier_count() > 0);
2630 
2631   menus_set_active(safe_group, "SHOW_CITY_OUTLINES",
2632                    gui_options.draw_city_outlines);
2633   menus_set_active(safe_group, "SHOW_CITY_OUTPUT",
2634                    gui_options.draw_city_output);
2635   menus_set_active(safe_group, "SHOW_MAP_GRID",
2636                    gui_options.draw_map_grid);
2637   menus_set_active(safe_group, "SHOW_NATIONAL_BORDERS",
2638                    gui_options.draw_borders);
2639   menus_set_sensitive(safe_group, "SHOW_NATIONAL_BORDERS",
2640                       BORDERS_DISABLED != game.info.borders);
2641   menus_set_active(safe_group, "SHOW_NATIVE_TILES",
2642                    gui_options.draw_native);
2643   menus_set_active(safe_group, "SHOW_CITY_FULL_BAR",
2644                    gui_options.draw_full_citybar);
2645   menus_set_active(safe_group, "SHOW_CITY_NAMES",
2646                    gui_options.draw_city_names);
2647   menus_set_active(safe_group, "SHOW_CITY_GROWTH",
2648                    gui_options.draw_city_growth);
2649   menus_set_active(safe_group, "SHOW_CITY_PRODUCTIONS",
2650                    gui_options.draw_city_productions);
2651   menus_set_active(safe_group, "SHOW_CITY_BUY_COST",
2652                    gui_options.draw_city_buycost);
2653   menus_set_active(safe_group, "SHOW_CITY_TRADE_ROUTES",
2654                    gui_options.draw_city_trade_routes);
2655   menus_set_active(safe_group, "SHOW_TERRAIN",
2656                    gui_options.draw_terrain);
2657   menus_set_active(safe_group, "SHOW_COASTLINE",
2658                    gui_options.draw_coastline);
2659   menus_set_active(safe_group, "SHOW_PATHS",
2660                    gui_options.draw_roads_rails);
2661   menus_set_active(safe_group, "SHOW_IRRIGATION",
2662                    gui_options.draw_irrigation);
2663   menus_set_active(safe_group, "SHOW_MINES",
2664                    gui_options.draw_mines);
2665   menus_set_active(safe_group, "SHOW_BASES",
2666                    gui_options.draw_fortress_airbase);
2667   menus_set_active(safe_group, "SHOW_RESOURCES",
2668                    gui_options.draw_specials);
2669   menus_set_active(safe_group, "SHOW_HUTS",
2670                    gui_options.draw_huts);
2671   menus_set_active(safe_group, "SHOW_POLLUTION",
2672                    gui_options.draw_pollution);
2673   menus_set_active(safe_group, "SHOW_CITIES",
2674                    gui_options.draw_cities);
2675   menus_set_active(safe_group, "SHOW_UNITS",
2676                    gui_options.draw_units);
2677   menus_set_active(safe_group, "SHOW_UNIT_SOLID_BG",
2678                    gui_options.solid_color_behind_units);
2679   menus_set_active(safe_group, "SHOW_UNIT_SHIELDS",
2680                    gui_options.draw_unit_shields);
2681   menus_set_active(safe_group, "SHOW_FOCUS_UNIT",
2682                    gui_options.draw_focus_unit);
2683   menus_set_active(safe_group, "SHOW_FOG_OF_WAR",
2684                    gui_options.draw_fog_of_war);
2685   if (tileset_use_hard_coded_fog(tileset)) {
2686     menus_set_visible(safe_group, "SHOW_BETTER_FOG_OF_WAR", TRUE, TRUE);
2687     menus_set_active(safe_group, "SHOW_BETTER_FOG_OF_WAR",
2688                      gui_options.gui_gtk2_better_fog);
2689   } else {
2690     menus_set_visible(safe_group, "SHOW_BETTER_FOG_OF_WAR", FALSE, FALSE);
2691   }
2692 
2693   view_menu_update_sensitivity();
2694 
2695   menus_set_active(safe_group, "FULL_SCREEN", gui_options.gui_gtk2_fullscreen);
2696 }
2697