initial commit, lordsawar source, slightly modified
[lordsawar] / src / gui / game-window.cpp
1 //  Copyright (C) 2007, 2008, Ole Laursen
2 //  Copyright (C) 2007, 2008, 2009 Ben Asselstine
3 //
4 //  This program is free software; you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation; either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU Library General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
17 //  02110-1301, USA.
18
19 #include <config.h>
20
21 #include <iomanip>
22 #include <queue>
23 #include <assert.h>
24 #include <string.h>
25
26 #include <sigc++/functors/mem_fun.h>
27 #include <sigc++/functors/ptr_fun.h>
28 #include <sigc++/adaptors/hide.h>
29
30 #include <gtkmm.h>
31 #include <glib.h>
32
33 #include "game-window.h"
34
35 #include "glade-helpers.h"
36 #include "image-helpers.h"
37 #include "input-helpers.h"
38 #include "error-utils.h"
39
40 #include "driver.h"
41
42 #include "fight-window.h"
43 #include "city-window.h"
44 #include "army-gains-level-dialog.h"
45 #include "hero-dialog.h"
46 #include "sage-dialog.h"
47 #include "ruin-rewarded-dialog.h"
48 #include "hero-offer-dialog.h"
49 #include "surrender-dialog.h"
50 #include "surrender-refused-dialog.h"
51 #include "quest-report-dialog.h"
52 #include "quest-assigned-dialog.h"
53 #include "quest-completed-dialog.h"
54 #include "preferences-dialog.h"
55 #include "fight-order-dialog.h"
56 #include "hero-levels-dialog.h"
57 #include "ruin-report-dialog.h"
58 #include "army-bonus-dialog.h"
59 #include "item-bonus-dialog.h"
60 #include "history-report-dialog.h"
61 #include "report-dialog.h"
62 #include "triumphs-dialog.h"
63 #include "diplomacy-report-dialog.h"
64 #include "diplomacy-dialog.h"
65 #include "stack-info-dialog.h"
66 #include "timed-message-dialog.h"
67 #include "destination-dialog.h"
68 #include "decorated.h"
69
70 #include "ucompose.hpp"
71 #include "defs.h"
72 #include "sound.h"
73 #include "File.h"
74 #include "game.h"
75 #include "gamebigmap.h"
76 #include "smallmap.h"
77 #include "GameScenarioOptions.h"
78 #include "army.h"
79 #include "ruin.h"
80 #include "ruinlist.h"
81 #include "path.h"
82 #include "player.h"
83 #include "signpostlist.h"
84 #include "playerlist.h"
85 #include "citylist.h"
86 #include "hero.h"
87 #include "heroproto.h"
88 #include "temple.h"
89 #include "templelist.h"
90 #include "city.h"
91 #include "Quest.h"
92 #include "QuestsManager.h"
93 #include "stack.h"
94 #include "GraphicsCache.h"
95 #include "QuestsManager.h"
96 #include "Quest.h"
97 #include "QCitySack.h"
98 #include "QCityRaze.h"
99 #include "QCityOccupy.h"
100 #include "QPillageGold.h"
101 #include "counter.h"
102 #include "armysetlist.h"
103 #include "tilesetlist.h"
104 #include "CreateScenario.h"
105 #include "reward.h"
106 #include "Configuration.h"
107 #include "GameMap.h"
108 #include "Item.h"
109 #include "shieldsetlist.h"
110 #include "game-server.h"
111 #include "game-client.h"
112 #include "NextTurnHotseat.h"
113 #include "NextTurnPbm.h"
114 #include "NextTurnNetworked.h"
115 #include "pbm-game-server.h"
116 #include "network_player.h"
117 #include "stacktile.h"
118
119
120 GameWindow::GameWindow()
121 {
122   stack_info_button_table = NULL;
123   game_winner = NULL;
124   stack_info_tip = NULL;
125   army_info_tip = NULL;
126   city_info_tip = NULL;
127   map_tip = NULL;
128   stack_tip = NULL;
129   game = NULL;
130     sdl_inited = false;
131     
132     Glib::RefPtr<Gtk::Builder> xml
133         = Gtk::Builder::create_from_file(get_glade_path() + "/game-window.ui");
134
135     Gtk::Window *w = 0;
136     xml->get_widget("window", w);
137     window = w;
138     w->set_icon_from_file(File::getMiscFile("various/castle_icon.png"));
139     decorate(window, File::getMiscFile("various/back.bmp"));
140     
141     window_closed.connect
142       (sigc::mem_fun(*this, &GameWindow::on_quit_activated));
143
144     w->signal_delete_event().connect
145       (sigc::mem_fun(*this, &GameWindow::on_delete_event));
146
147     xml->get_widget("menubar", menubar);
148     xml->get_widget("bigmap_drawingarea", bigmap_drawingarea);
149     //bigmap_drawingarea->set_double_buffered(false);
150     bigmap_drawingarea->signal_expose_event().connect
151       (sigc::mem_fun(*this, &GameWindow::on_bigmap_exposed));
152     bigmap_drawingarea->signal_size_allocate().connect
153       (sigc::mem_fun(*this, &GameWindow::on_bigmap_surface_changed));
154     bigmap_drawingarea->grab_focus();
155     xml->get_widget("bigmap_eventbox", bigmap_eventbox);
156     bigmap_eventbox->add_events(Gdk::KEY_PRESS_MASK | 
157                   Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
158                   Gdk::POINTER_MOTION_MASK);
159     bigmap_eventbox->signal_key_press_event().connect(
160         sigc::mem_fun(*this, &GameWindow::on_bigmap_key_event));
161     bigmap_eventbox->signal_key_release_event().connect(
162         sigc::mem_fun(*this, &GameWindow::on_bigmap_key_event));
163     bigmap_eventbox->signal_button_press_event().connect
164      (sigc::mem_fun(*this, &GameWindow::on_bigmap_mouse_button_event));
165     bigmap_eventbox->signal_button_release_event().connect
166      (sigc::mem_fun(*this, &GameWindow::on_bigmap_mouse_button_event));
167     bigmap_eventbox->signal_motion_notify_event().connect
168      (sigc::mem_fun(*this, &GameWindow::on_bigmap_mouse_motion_event));
169     bigmap_eventbox->signal_scroll_event().connect
170        (sigc::mem_fun(*this, &GameWindow::on_bigmap_scroll_event));
171     xml->get_widget("stack_info_box", stack_info_box);
172     xml->get_widget("stack_info_container", stack_info_container);
173     Gtk::Viewport *vp;
174     xml->get_widget("bigmap_viewport", vp);
175     decorate_border(vp, 175);
176     xml->get_widget("group_moves_label", group_moves_label);
177     xml->get_widget("group_togglebutton", group_ungroup_toggle);
178     group_ungroup_toggle->signal_toggled().connect
179       (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_group_toggled),
180                   group_ungroup_toggle));
181     xml->get_widget("terrain_image", terrain_image);
182     xml->get_widget("stats_box", stats_box);
183     xml->get_widget("progress_box", progress_box);
184     xml->get_widget("turn_progressbar", turn_progressbar);
185     xml->get_widget("progress_status_label", progress_status_label);
186     stack_info_box->hide();
187     stats_box->hide();
188     progress_box->show();
189
190     // the map image
191     xml->get_widget("map_drawingarea", map_drawingarea);
192     //map_drawingarea->set_double_buffered(false);
193     map_drawingarea->signal_expose_event().connect
194       (sigc::mem_fun(*this, &GameWindow::on_smallmap_exposed));
195     xml->get_widget("map_eventbox", map_eventbox);
196     xml->get_widget("map_container", map_container);
197     map_eventbox->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
198                              Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK);
199       map_eventbox->signal_button_press_event().connect
200        (sigc::mem_fun(*this, &GameWindow::on_smallmap_mouse_button_event));
201       map_eventbox->signal_button_release_event().connect
202        (sigc::mem_fun(*this, &GameWindow::on_smallmap_mouse_button_event));
203       map_eventbox->signal_motion_notify_event().connect
204        (sigc::mem_fun(*this, &GameWindow::on_smallmap_mouse_motion_event));
205     Gtk::Viewport *mvp;
206     xml->get_widget("map_viewport", mvp);
207     decorate_border(mvp, 175);
208     xml->get_widget("control_panel_viewport", vp);
209     decorate_border(vp, 175);
210
211     // the stats
212     xml->get_widget("cities_stats_image", cities_stats_image);
213     cities_stats_image->property_file() = File::getMiscFile("various/smallcity.png");
214     xml->get_widget("gold_stats_image", gold_stats_image);
215     gold_stats_image->property_file() = File::getMiscFile("various/smalltreasury.png");
216     xml->get_widget("income_stats_image", income_stats_image);
217     income_stats_image->property_file() = File::getMiscFile("various/smallincome.png");
218     xml->get_widget("upkeep_stats_image", upkeep_stats_image);
219     upkeep_stats_image->property_file() = File::getMiscFile("various/smallupkeep.png");
220     
221     xml->get_widget("cities_stats_label", cities_stats_label);
222     xml->get_widget("gold_stats_label", gold_stats_label);
223     xml->get_widget("income_stats_label", income_stats_label);
224     xml->get_widget("upkeep_stats_label", upkeep_stats_label);
225     xml->get_widget("turn_label", turn_label);
226     xml->get_widget("turn_hbox", turn_hbox);
227     xml->get_widget("shield_image_0", shield_image[0]);
228     xml->get_widget("shield_image_1", shield_image[1]);
229     xml->get_widget("shield_image_2", shield_image[2]);
230     xml->get_widget("shield_image_3", shield_image[3]);
231     xml->get_widget("shield_image_4", shield_image[4]);
232     xml->get_widget("shield_image_5", shield_image[5]);
233     xml->get_widget("shield_image_6", shield_image[6]);
234     xml->get_widget("shield_image_7", shield_image[7]);
235
236     // the control panel
237     xml->get_widget("next_movable_button", next_movable_button);
238     xml->get_widget("center_button", center_button);
239     xml->get_widget("diplomacy_button", diplomacy_button);
240     xml->get_widget("defend_button", defend_button);
241     xml->get_widget("park_button", park_button);
242     xml->get_widget("deselect_button", deselect_button);
243     xml->get_widget("search_button", search_button);
244     xml->get_widget("move_button", move_button);
245     xml->get_widget("move_all_button", move_all_button);
246     xml->get_widget("end_turn_button", end_turn_button);
247 /*    xml->get_widget("nw_keypad_button", nw_keypad_button);
248     xml->get_widget("n_keypad_button", n_keypad_button);
249     xml->get_widget("ne_keypad_button", ne_keypad_button);
250     xml->get_widget("e_keypad_button", e_keypad_button);
251     xml->get_widget("w_keypad_button", w_keypad_button);
252     xml->get_widget("sw_keypad_button", sw_keypad_button);
253     xml->get_widget("s_keypad_button", s_keypad_button);
254     xml->get_widget("se_keypad_button", se_keypad_button); */
255
256     // fill in imagery
257     d_button_images = disassemble_row(File::getMiscFile("various/buttons.png"), 11);
258     Gtk::Image *button_image2 = new Gtk::Image();
259     button_image2->property_pixbuf() = d_button_images[2]->to_pixbuf();
260     next_movable_button->add(*manage(button_image2));
261     Gtk::Image *button_image5 = new Gtk::Image();
262     button_image5->property_pixbuf() = d_button_images[5]->to_pixbuf();
263     center_button->add(*manage(button_image5));
264     Gtk::Image *button_image0 = new Gtk::Image();
265     button_image0->property_pixbuf() = d_button_images[0]->to_pixbuf();
266     diplomacy_button->add(*manage(button_image0));
267     Gtk::Image *button_image6 = new Gtk::Image();
268     button_image6->property_pixbuf() = d_button_images[6]->to_pixbuf();
269     defend_button->add(*manage(button_image6));
270     Gtk::Image * button_image1 = new Gtk::Image();
271     button_image1->property_pixbuf() = d_button_images[1]->to_pixbuf();
272     park_button->add(*manage(button_image1));
273     Gtk::Image * button_image7 = new Gtk::Image();
274     button_image7->property_pixbuf() = d_button_images[7]->to_pixbuf();
275     deselect_button->add(*manage(button_image7));
276     Gtk::Image * button_image9 = new Gtk::Image();
277     button_image9->property_pixbuf() = d_button_images[9]->to_pixbuf();
278     search_button->add(*manage(button_image9));
279     Gtk::Image * button_image3 = new Gtk::Image();
280     button_image3->property_pixbuf() = d_button_images[3]->to_pixbuf();
281     move_button->add(*manage(button_image3));
282     Gtk::Image * button_image4 = new Gtk::Image();
283     button_image4->property_pixbuf() = d_button_images[4]->to_pixbuf();
284     move_all_button->add(*manage(button_image4));
285     Gtk::Image * button_image10 = new Gtk::Image();
286     button_image10->property_pixbuf() = d_button_images[10]->to_pixbuf();
287     end_turn_button->add(*manage(button_image10));
288     
289 /*    d_arrow_images = disassemble_row(File::getMiscFile("various/arrows.png"), 
290                                      8);
291     Gtk::Image * arrow_image0 = new Gtk::Image();
292     arrow_image0->property_pixbuf() = d_arrow_images[0]->to_pixbuf();
293     nw_keypad_button->add(*manage(arrow_image0));
294     Gtk::Image * arrow_image1 = new Gtk::Image();
295     arrow_image1->property_pixbuf() = d_arrow_images[1]->to_pixbuf();
296     n_keypad_button->add(*manage(arrow_image1));
297     Gtk::Image * arrow_image2 = new Gtk::Image();
298     arrow_image2->property_pixbuf() = d_arrow_images[2]->to_pixbuf();
299     ne_keypad_button->add(*manage(arrow_image2));
300     Gtk::Image * arrow_image3 = new Gtk::Image();
301     arrow_image3->property_pixbuf() = d_arrow_images[3]->to_pixbuf();
302     e_keypad_button->add(*manage(arrow_image3));
303     Gtk::Image * arrow_image4 = new Gtk::Image();
304     arrow_image4->property_pixbuf() = d_arrow_images[4]->to_pixbuf();
305     w_keypad_button->add(*manage(arrow_image4));
306     Gtk::Image * arrow_image5 = new Gtk::Image();
307     arrow_image5->property_pixbuf() = d_arrow_images[5]->to_pixbuf();
308     sw_keypad_button->add(*manage(arrow_image5));
309     Gtk::Image * arrow_image6 = new Gtk::Image();
310     arrow_image6->property_pixbuf() = d_arrow_images[6]->to_pixbuf();
311     s_keypad_button->add(*manage(arrow_image6));
312     Gtk::Image * arrow_image7 = new Gtk::Image();
313     arrow_image7->property_pixbuf() = d_arrow_images[7]->to_pixbuf();
314     se_keypad_button->add(*manage(arrow_image7)); */
315
316     // connect callbacks for the menu
317     xml->get_widget("new_game_menuitem", new_game_menuitem);
318     new_game_menuitem->signal_activate().connect
319       (sigc::mem_fun(*this, &GameWindow::on_quit_activated));
320     xml->get_widget("load_game_menuitem", load_game_menuitem);
321     load_game_menuitem->signal_activate().connect
322       (sigc::mem_fun(*this, &GameWindow::on_load_game_activated));
323     xml->get_widget("save_game_menuitem", save_game_menuitem);
324     save_game_menuitem->signal_activate().connect
325       (sigc::mem_fun(*this, &GameWindow::on_save_game_activated));
326     xml->get_widget("save_game_as_menuitem", save_game_as_menuitem);
327     save_game_as_menuitem->signal_activate().connect
328       (sigc::mem_fun(*this, &GameWindow::on_save_game_as_activated));
329     xml->get_widget("quit_menuitem", quit_menuitem);
330     quit_menuitem->signal_activate().connect
331       (sigc::mem_fun(*this, &GameWindow::on_quit_activated));
332     xml->get_widget("toggle_grid_menuitem", toggle_grid_menuitem);
333     toggle_grid_menuitem->signal_activate().connect
334       (sigc::mem_fun(*this, &GameWindow::on_grid_toggled));
335     xml->get_widget("army_report_menuitem", army_report_menuitem);
336     army_report_menuitem->signal_activate().connect
337       (sigc::mem_fun(*this, &GameWindow::on_army_report_activated));
338     xml->get_widget("city_report_menuitem", city_report_menuitem);
339     city_report_menuitem->signal_activate().connect
340       (sigc::mem_fun(*this, &GameWindow::on_city_report_activated));
341     xml->get_widget("gold_report_menuitem", gold_report_menuitem);
342     gold_report_menuitem->signal_activate().connect
343       (sigc::mem_fun(*this, &GameWindow::on_gold_report_activated));
344     xml->get_widget("winning_report_menuitem", winning_report_menuitem);
345     winning_report_menuitem->signal_activate().connect
346       (sigc::mem_fun(*this, &GameWindow::on_winning_report_activated));
347     xml->get_widget("diplomacy_report_menuitem", diplomacy_report_menuitem);
348     xml->get_widget("quests_menuitem", quests_menuitem);
349     quests_menuitem->signal_activate().connect
350       (sigc::mem_fun(*this, &GameWindow::on_quests_activated));
351     xml->get_widget("fullscreen_menuitem", fullscreen_menuitem);
352     fullscreen_menuitem->signal_activate().connect
353       (sigc::mem_fun(*this, &GameWindow::on_fullscreen_activated));
354     xml->get_widget("preferences_menuitem", preferences_menuitem);
355     preferences_menuitem->signal_activate().connect
356       (sigc::mem_fun(*this, &GameWindow::on_preferences_activated));
357
358     xml->get_widget("show_lobby_menuitem", show_lobby_menuitem);
359     show_lobby_menuitem->signal_activate().connect
360       (sigc::mem_fun(*this, &GameWindow::on_show_lobby_activated));
361     xml->get_widget("end_turn_menuitem", end_turn_menuitem);
362     xml->get_widget("move_all_menuitem", move_all_menuitem);
363     xml->get_widget("disband_menuitem", disband_menuitem);
364     xml->get_widget("stack_info_menuitem", stack_info_menuitem);
365     xml->get_widget("signpost_menuitem", signpost_menuitem);
366     xml->get_widget("search_menuitem", search_menuitem);
367     xml->get_widget("inspect_menuitem", inspect_menuitem);
368     xml->get_widget("plant_standard_menuitem", plant_standard_menuitem);
369     xml->get_widget("city_history_menuitem", city_history_menuitem);
370     xml->get_widget("ruin_history_menuitem", ruin_history_menuitem);
371     xml->get_widget("event_history_menuitem", event_history_menuitem);
372     xml->get_widget("gold_history_menuitem", gold_history_menuitem);
373     xml->get_widget("winner_history_menuitem", winner_history_menuitem);
374     xml->get_widget("group_ungroup_menuitem", group_ungroup_menuitem);
375     xml->get_widget("leave_menuitem", leave_menuitem);
376     xml->get_widget("next_menuitem", next_menuitem);
377
378     xml->get_widget("fight_order_menuitem", fight_order_menuitem);
379     fight_order_menuitem->signal_activate().connect
380       (sigc::mem_fun(*this, &GameWindow::on_fight_order_activated));
381     xml->get_widget("resign_menuitem", resign_menuitem);
382     resign_menuitem->signal_activate().connect
383       (sigc::mem_fun(*this, &GameWindow::on_resign_activated));
384     xml->get_widget("production_menuitem", production_menuitem);
385     production_menuitem->signal_activate().connect
386       (sigc::mem_fun(*this, &GameWindow::on_production_activated));
387     xml->get_widget("cities_menuitem", cities_menuitem);
388     cities_menuitem->signal_activate().connect
389       (sigc::mem_fun(*this, &GameWindow::on_production_activated));
390     xml->get_widget("build_menuitem", build_menuitem);
391     build_menuitem->signal_activate().connect
392       (sigc::mem_fun(*this, &GameWindow::on_production_activated));
393     xml->get_widget("vectoring_menuitem", vectoring_menuitem);
394     vectoring_menuitem->signal_activate().connect
395       (sigc::mem_fun(*this, &GameWindow::on_vectoring_activated));
396     xml->get_widget("levels_menuitem", levels_menuitem);
397     levels_menuitem->signal_activate().connect
398       (sigc::mem_fun(*this, &GameWindow::on_levels_activated));
399     xml->get_widget("inspect_menuitem", inspect_menuitem);
400     inspect_menuitem->signal_activate().connect
401       (sigc::mem_fun(*this, &GameWindow::on_inspect_activated));
402     xml->get_widget("ruin_report_menuitem", ruin_report_menuitem);
403     ruin_report_menuitem->signal_activate().connect
404       (sigc::mem_fun(*this, &GameWindow::on_ruin_report_activated));
405     xml->get_widget("army_bonus_menuitem", army_bonus_menuitem);
406     army_bonus_menuitem->signal_activate().connect
407       (sigc::mem_fun(*this, &GameWindow::on_army_bonus_activated));
408     xml->get_widget("item_bonus_menuitem", item_bonus_menuitem);
409     item_bonus_menuitem->signal_activate().connect
410       (sigc::mem_fun(*this, &GameWindow::on_item_bonus_activated));
411     xml->get_widget("production_report_menuitem", production_report_menuitem);
412     production_report_menuitem->signal_activate().connect
413       (sigc::mem_fun(*this, &GameWindow::on_production_report_activated));
414     xml->get_widget("triumphs_menuitem", triumphs_menuitem);
415     triumphs_menuitem->signal_activate().connect
416       (sigc::mem_fun(*this, &GameWindow::on_triumphs_activated));
417     xml->get_widget("help_about_menuitem", help_about_menuitem);
418     help_about_menuitem->signal_activate().connect
419       (sigc::mem_fun(*this, &GameWindow::on_help_about_activated));
420     xml->get_widget("online_help_menuitem", online_help_menuitem);
421     online_help_menuitem->signal_activate().connect
422       (sigc::mem_fun(*this, &GameWindow::on_online_help_activated));
423     d_quick_fights = false;
424
425     if (Configuration::s_decorated == true)
426       {
427         //colour the menubar
428         Glib::RefPtr<Gtk::Style> copy;
429         Glib::RefPtr<Gdk::Pixbuf> back;
430         Glib::RefPtr<Gdk::Pixmap> pixmap;
431         Glib::RefPtr<Gdk::Bitmap> bitmap;
432         copy = menubar->get_style()->copy();
433         back = Gdk::Pixbuf::create_from_file(File::getMiscFile("various/back.bmp"));
434         pixmap = Gdk::Pixmap::create
435           (window->get_window(), back->get_width(), back->get_height());
436         back->composite_color(back, 0, 0, 
437                               back->get_width(), back->get_height(), 
438                               0.0, 0.0, 1.0, 1.0, Gdk::INTERP_NEAREST, 127, 
439                               0, 0, 64, 0, 0);
440         back->render_pixmap_and_mask(pixmap, bitmap, 10);
441         copy->set_bg_pixmap(Gtk::STATE_NORMAL, pixmap);
442         menubar->set_style(copy);
443       }
444
445 }
446
447 GameWindow::~GameWindow()
448 {
449   std::list<sigc::connection>::iterator it = connections.begin();
450   for (; it != connections.end(); it++) 
451     (*it).disconnect();
452   connections.clear();
453   clear_army_buttons();
454     if (army_info_tip)
455       {
456         delete army_info_tip;
457         army_info_tip = NULL;
458       }
459     if (city_info_tip)
460       {
461         delete city_info_tip;
462         city_info_tip = NULL;
463       }
464     if (stack_info_tip)
465       {
466         delete stack_info_tip;
467         stack_info_tip = NULL;
468       }
469     if (game)
470       {
471         delete game;
472         game = NULL;
473       }
474   if (stack_info_button_table != NULL)
475     delete stack_info_button_table;
476   delete window;
477 }
478
479 void GameWindow::show()
480 {
481     next_movable_button->show_all();
482     center_button->show_all();
483     diplomacy_button->show_all();
484     defend_button->show_all();
485     park_button->show_all();
486     deselect_button->show_all();
487     search_button->show_all();
488     move_button->show_all();
489     move_all_button->show_all();
490     end_turn_button->show_all();
491 /*    nw_keypad_button->show_all();
492     n_keypad_button->show_all();
493     ne_keypad_button->show_all();
494     e_keypad_button->show_all();
495     w_keypad_button->show_all();
496     sw_keypad_button->show_all();
497     s_keypad_button->show_all();
498     se_keypad_button->show_all(); */
499     
500     bigmap_drawingarea->show_all();
501     window->show();
502       
503     //seems unnecessary, but this is for starting up a second game after
504     //closing the first game window.
505     //fixme: find out why this line is necessary
506     on_bigmap_surface_changed(bigmap_drawingarea->get_allocation());
507 }
508
509 void GameWindow::hide()
510 {
511     window->hide();
512 }
513
514 void GameWindow::init(int width, int height)
515 {
516 }
517
518 void GameWindow::new_network_game(GameScenario *game_scenario, NextTurn *next_turn)
519 {
520   if (GameServer::getInstance()->isListening() == true)
521     GameServer::getInstance()->round_begins.connect(sigc::mem_fun(this, &GameWindow::on_remote_next_player_turn));
522   else
523       GameClient::getInstance()->round_begins.connect(sigc::mem_fun(this, &GameWindow::on_remote_next_player_turn));
524   bool success = false;
525   //stop_game();
526   success = setup_game(game_scenario, next_turn);
527   if (!success)
528     return;
529   setup_signals(game_scenario);
530   game->redraw();
531   game->startGame();
532 }
533
534 void GameWindow::continue_network_game(NextTurn *next_turn)
535 {
536   next_turn->start();
537 }
538
539 void GameWindow::new_game(GameScenario *game_scenario, NextTurn *next_turn)
540 {
541   bool success = false;
542   success = setup_game(game_scenario, next_turn);
543   if (!success)
544     return;
545   setup_signals(game_scenario);
546   game->startGame();
547   //we don't get here until the game ends.
548 }
549
550 void GameWindow::load_game(GameScenario *game_scenario, NextTurn *next_turn)
551 {
552   bool success = false;
553   success = setup_game(game_scenario, next_turn);
554   if (!success)
555     return;
556
557   game->get_bigmap().screen_size_changed(bigmap_drawingarea->get_allocation());
558   setup_signals(game_scenario);
559   game->loadGame();
560   //we don't get here until the game ends, or a human player ends a turn.
561   if (Playerlist::getInstance()->countPlayersAlive())
562     game->redraw();
563 }
564
565 void GameWindow::setup_button(Gtk::Button *button,
566                               sigc::slot<void> slot,
567                               sigc::signal<void, bool> &game_signal)
568 {
569   connections.push_back (button->signal_clicked().connect(slot));
570   connections.push_back 
571     (game_signal.connect(sigc::mem_fun(button, &Gtk::Widget::set_sensitive)));
572 }
573
574 void GameWindow::setup_menuitem(Gtk::MenuItem *item,
575                                 sigc::slot<void> slot,
576                                 sigc::signal<void, bool> &game_signal)
577 {
578   connections.push_back (item->signal_activate().connect(slot));
579   connections.push_back 
580     (game_signal.connect(sigc::mem_fun(item, &Gtk::Widget::set_sensitive)));
581 }
582
583 void GameWindow::setup_signals(GameScenario *game_scenario)
584 {
585   // get rid of the connections that might be still around from last time
586   std::list<sigc::connection>::iterator it = connections.begin();
587   for (; it != connections.end(); it++) 
588     (*it).disconnect();
589   connections.clear();
590
591   setup_button(next_movable_button,
592                sigc::mem_fun(game, &Game::select_next_movable_stack),
593                game->can_select_next_movable_stack);
594   setup_button(center_button,
595                sigc::mem_fun(game, &Game::center_selected_stack),
596                game->can_center_selected_stack);
597                
598   connections.push_back (diplomacy_button->signal_clicked().connect
599    (sigc::mem_fun (*this, &GameWindow::on_diplomacy_button_clicked)));
600   connections.push_back 
601     (game->received_diplomatic_proposal.connect 
602      (sigc::mem_fun(*this, &GameWindow::change_diplomacy_button_image)));
603   connections.push_back 
604     (game->city_too_poor_to_produce.connect 
605      (sigc::mem_fun(*this, &GameWindow::show_city_production_report)));
606   connections.push_back
607     (game->commentator_comments.connect
608      (sigc::mem_fun(*this, &GameWindow::on_commentator_comments)));
609   connections.push_back 
610     (game->can_end_turn.connect 
611      (sigc::mem_fun(*this, &GameWindow::update_diplomacy_button)));
612
613   setup_button(defend_button,
614                sigc::mem_fun(game, &Game::defend_selected_stack),
615                game->can_defend_selected_stack);
616   setup_button(park_button,
617                sigc::mem_fun(game, &Game::park_selected_stack),
618                game->can_park_selected_stack);
619   setup_button(deselect_button,
620                sigc::mem_fun(game, &Game::deselect_selected_stack),
621                game->can_deselect_selected_stack);
622   setup_button(search_button,
623                sigc::mem_fun(game, &Game::search_selected_stack),
624                game->can_search_selected_stack);
625   setup_button(move_button,
626                sigc::mem_fun(game, &Game::move_selected_stack_along_path),
627                game->can_move_selected_stack_along_path);
628   setup_button(move_all_button,
629                sigc::mem_fun(game, &Game::move_all_stacks),
630                game->can_move_all_stacks);
631   setup_button(end_turn_button,
632                sigc::mem_fun(game, &Game::end_turn),
633                game->can_end_turn);
634   if (game_scenario->getPlayMode() ==  GameScenario::PLAY_BY_MAIL)
635     setup_button(end_turn_button,
636                  sigc::mem_fun(*this, &GameWindow::end_turn_play_by_mail),
637                  game->can_end_turn);
638 /*  setup_button(nw_keypad_button,
639                sigc::mem_fun(game, &Game::move_selected_stack_northwest),
640                game->can_end_turn);
641   setup_button(n_keypad_button,
642                sigc::mem_fun(game, &Game::move_selected_stack_north),
643                game->can_end_turn);
644   setup_button(ne_keypad_button,
645                sigc::mem_fun(game, &Game::move_selected_stack_northeast),
646                game->can_end_turn);
647   setup_button(e_keypad_button,
648                sigc::mem_fun(game, &Game::move_selected_stack_east),
649                game->can_end_turn);
650   setup_button(w_keypad_button,
651                sigc::mem_fun(game, &Game::move_selected_stack_west),
652                game->can_end_turn);
653   setup_button(sw_keypad_button,
654                sigc::mem_fun(game, &Game::move_selected_stack_southwest),
655                game->can_end_turn);
656   setup_button(s_keypad_button,
657                sigc::mem_fun(game, &Game::move_selected_stack_south),
658                game->can_end_turn);
659   setup_button(se_keypad_button,
660                sigc::mem_fun(game, &Game::move_selected_stack_southeast),
661                game->can_end_turn); */
662   setup_menuitem(move_all_menuitem,
663                  sigc::mem_fun(game, &Game::move_all_stacks),
664                  game->can_move_all_stacks);
665   setup_menuitem(end_turn_menuitem,
666                  sigc::mem_fun(game, &Game::end_turn),
667                  game->can_end_turn);
668   if (game_scenario->getPlayMode() == GameScenario::PLAY_BY_MAIL)
669     setup_menuitem(end_turn_menuitem,
670                    sigc::mem_fun(*this, &GameWindow::end_turn_play_by_mail),
671                    game->can_end_turn);
672   if (game_scenario->getPlayMode() == GameScenario::NETWORKED)
673     {
674       load_game_menuitem->set_sensitive(false);
675       if (GameServer::getInstance()->isListening() == false)
676         {
677           save_game_menuitem->set_sensitive(false);
678           save_game_as_menuitem->set_sensitive(false);
679         }
680     }
681   else
682     show_lobby_menuitem->set_sensitive(false);
683
684   setup_menuitem(disband_menuitem,
685                  sigc::mem_fun(*this, &GameWindow::on_disband_activated),
686                  game->can_disband_stack);
687   setup_menuitem(stack_info_menuitem,
688                  sigc::mem_fun(*this, &GameWindow::on_stack_info_activated),
689                  game->can_deselect_selected_stack);
690   setup_menuitem(signpost_menuitem,
691                  sigc::mem_fun(*this, &GameWindow::on_signpost_activated),
692                  game->can_change_signpost);
693   setup_menuitem(search_menuitem,
694                  sigc::mem_fun(game, &Game::search_selected_stack),
695                  game->can_search_selected_stack);
696   setup_menuitem(plant_standard_menuitem,
697                  sigc::mem_fun(*this, 
698                                &GameWindow::on_plant_standard_activated),
699                  game->can_plant_standard_selected_stack);
700   setup_menuitem(city_history_menuitem,
701                  sigc::mem_fun(*this, &GameWindow::on_city_history_activated),
702                  game->can_see_history);
703   setup_menuitem(ruin_history_menuitem,
704                  sigc::mem_fun(*this, &GameWindow::on_ruin_history_activated),
705                  game->can_see_history);
706   setup_menuitem(gold_history_menuitem,
707                  sigc::mem_fun(*this, &GameWindow::on_gold_history_activated),
708                  game->can_see_history);
709   setup_menuitem(event_history_menuitem,
710                  sigc::mem_fun(*this, &GameWindow::on_event_history_activated),
711                  game->can_see_history);
712   setup_menuitem(winner_history_menuitem,
713                  sigc::mem_fun(*this, &GameWindow::on_winner_history_activated),
714                  game->can_see_history);
715   setup_menuitem(diplomacy_report_menuitem,
716                  sigc::mem_fun(*this, 
717                                &GameWindow::on_diplomacy_report_activated),
718                  game->can_see_diplomacy); 
719   setup_menuitem(group_ungroup_menuitem,
720                  sigc::mem_fun(*this, &GameWindow::on_group_ungroup_activated),
721                  game->can_group_ungroup_selected_stack);
722   setup_menuitem(leave_menuitem,
723                  sigc::mem_fun(game, &Game::park_selected_stack),
724                  game->can_park_selected_stack);
725   setup_menuitem(next_menuitem,
726                  sigc::mem_fun(game, &Game::select_next_movable_stack),
727                  game->can_select_next_movable_stack);
728
729   // setup game callbacks
730   connections.push_back
731     (game->game_stopped.connect
732      (sigc::mem_fun(*this, &GameWindow::on_game_stopped)));
733   connections.push_back 
734     (game->sidebar_stats_changed.connect
735      (sigc::mem_fun(*this, &GameWindow::on_sidebar_stats_changed)));
736   connections.push_back 
737     (game->progress_status_changed.connect
738      (sigc::mem_fun(*this, &GameWindow::on_progress_status_changed)));
739   connections.push_back 
740     (game->progress_changed.connect
741      (sigc::mem_fun(*this, &GameWindow::on_progress_changed)));
742   connections.push_back
743     (game->bigmap_changed.connect
744      (sigc::mem_fun(*this, &GameWindow::on_bigmap_changed)));
745   connections.push_back
746     (game->smallmap_changed.connect
747      (sigc::mem_fun(*this, &GameWindow::on_smallmap_changed)));
748   connections.push_back
749     (game->get_smallmap().view_slid.connect
750      (sigc::mem_fun(*this, &GameWindow::on_smallmap_slid)));
751   connections.push_back
752     (game->stack_info_changed.connect
753      (sigc::mem_fun(*this, &GameWindow::on_stack_info_changed)));
754   connections.push_back
755     (game->map_tip_changed.connect
756      (sigc::mem_fun(*this, &GameWindow::on_bigmap_tip_changed)));
757   connections.push_back
758     (game->stack_tip_changed.connect
759      (sigc::mem_fun(*this, &GameWindow::on_stack_tip_changed)));
760   connections.push_back
761     (game->city_tip_changed.connect
762      (sigc::mem_fun(*this, &GameWindow::on_city_tip_changed)));
763   connections.push_back
764     (game->ruin_searched.connect
765      (sigc::mem_fun(*this, &GameWindow::on_ruin_searched)));
766   connections.push_back
767     (game->sage_visited.connect
768      (sigc::mem_fun(*this, &GameWindow::on_sage_visited)));
769   connections.push_back
770     (game->fight_started.connect
771      (sigc::mem_fun(*this, &GameWindow::on_fight_started)));
772   connections.push_back
773     (game->abbreviated_fight_started.connect
774      (sigc::mem_fun(*this, &GameWindow::on_abbreviated_fight_started)));
775   connections.push_back
776     (game->ruinfight_started.connect
777      (sigc::mem_fun(*this, &GameWindow::on_ruinfight_started)));
778   connections.push_back
779     (game->ruinfight_finished.connect
780      (sigc::mem_fun(*this, &GameWindow::on_ruinfight_finished)));
781   connections.push_back
782     (game->hero_offers_service.connect
783      (sigc::mem_fun(*this, &GameWindow::on_hero_offers_service)));
784   connections.push_back
785     (game->enemy_offers_surrender.connect
786      (sigc::mem_fun(*this, &GameWindow::on_enemy_offers_surrender)));
787   connections.push_back
788     (game->surrender_answered.connect
789      (sigc::mem_fun(*this, &GameWindow::on_surrender_answered)));
790   connections.push_back
791     (game->stack_considers_treachery.connect
792      (sigc::mem_fun(*this, &GameWindow::on_stack_considers_treachery)));
793   connections.push_back
794     (game->temple_searched.connect
795      (sigc::mem_fun(*this, &GameWindow::on_temple_searched)));
796   connections.push_back
797     (game->quest_assigned.connect
798      (sigc::mem_fun(*this, &GameWindow::on_quest_assigned)));
799   connections.push_back
800     (game->city_defeated.connect
801      (sigc::mem_fun(*this, &GameWindow::on_city_defeated)));
802   connections.push_back
803     (game->city_pillaged.connect
804      (sigc::mem_fun(*this, &GameWindow::on_city_pillaged)));
805   connections.push_back
806     (game->city_sacked.connect
807      (sigc::mem_fun(*this, &GameWindow::on_city_sacked)));
808   connections.push_back
809     (game->city_razed.connect
810      (sigc::mem_fun(*this, &GameWindow::on_city_razed)));
811   connections.push_back
812     (game->city_visited.connect
813      (sigc::mem_fun(*this, &GameWindow::on_city_visited)));
814   connections.push_back
815     (game->ruin_visited.connect
816      (sigc::mem_fun(*this, &GameWindow::on_ruin_visited)));
817   connections.push_back
818     (game->temple_visited.connect
819      (sigc::mem_fun(*this, &GameWindow::on_temple_visited)));
820   connections.push_back
821     (game->next_player_turn.connect
822      (sigc::mem_fun(*this, &GameWindow::on_next_player_turn)));
823   connections.push_back
824     (game->hero_arrives.connect
825      (sigc::mem_fun(*this, &GameWindow::on_hero_brings_allies)));
826   connections.push_back
827     (game->medal_awarded_to_army.connect
828      (sigc::mem_fun(*this, &GameWindow::on_medal_awarded_to_army)));
829   connections.push_back
830     (game->hero_gains_level.connect
831      (sigc::mem_fun(*this, &GameWindow::on_hero_gains_level)));
832   connections.push_back
833     (game->game_loaded.connect
834      (sigc::mem_fun(*this, &GameWindow::on_game_loaded)));
835   connections.push_back
836     (game->game_over.connect
837      (sigc::mem_fun(*this, &GameWindow::on_game_over)));
838   connections.push_back
839     (game->player_died.connect
840      (sigc::mem_fun(*this, &GameWindow::on_player_died)));
841   connections.push_back
842     (game->advice_asked.connect
843      (sigc::mem_fun(*this, &GameWindow::on_advice_asked)));
844   connections.push_back
845     (game->stack_moves.connect
846      (sigc::mem_fun(*this, &GameWindow::on_stack_moves)));
847
848   // misc callbacks
849   QuestsManager *q = QuestsManager::getInstance();
850   connections.push_back
851     (q->quest_completed.connect
852      (sigc::mem_fun(this, &GameWindow::on_quest_completed)));
853   connections.push_back
854     (q->quest_expired.connect
855      (sigc::mem_fun(this, &GameWindow::on_quest_expired)));
856   if (game)
857     {
858       connections.push_back
859         (game->get_bigmap().cursor_changed.connect
860          (sigc::mem_fun(*this, &GameWindow::on_bigmap_cursor_changed)));
861     }
862
863   connections.push_back
864     (game->remote_next_player_turn.connect
865      (sigc::mem_fun(*this, &GameWindow::on_remote_next_player_turn)));
866 }
867
868 void GameWindow::show_city_production_report (bool destitute)
869 {
870   if (!destitute)
871     return;
872   ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::PRODUCTION);
873   d.set_parent_window(*window);
874   d.run();
875   d.hide();
876 }
877
878 void GameWindow::change_diplomacy_button_image (bool proposals_present)
879 {
880   /* switch up the image. */
881   if (proposals_present)
882     {
883       Gtk::Image *proposals_present_image = new Gtk::Image();
884       proposals_present_image->property_pixbuf() = d_button_images[8]->to_pixbuf();
885       diplomacy_button->property_image() = proposals_present_image;
886     }
887   else
888     {
889       Gtk::Image *proposals_not_present_image = new Gtk::Image();
890       proposals_not_present_image->property_pixbuf() = d_button_images[0]->to_pixbuf();
891       diplomacy_button->property_image() = proposals_not_present_image;
892     }
893 }
894
895 void GameWindow::end_turn_play_by_mail ()
896 {
897   //prompt to save the turn file!
898   Gtk::FileChooserDialog chooser(*window, _("Save your Turn file and mail it back"),
899                                  Gtk::FILE_CHOOSER_ACTION_SAVE);
900   Gtk::FileFilter trn_filter;
901   trn_filter.add_pattern("*.trn");
902   chooser.set_filter(trn_filter);
903   chooser.set_current_folder(Glib::get_home_dir());
904
905   chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
906   chooser.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
907   chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
908
909   chooser.show_all();
910   int res = chooser.run();
911   chooser.hide();
912
913   if (res == Gtk::RESPONSE_ACCEPT)
914     {
915       std::string filename = chooser.get_filename();
916
917       game->saveTurnFile(filename);
918       TimedMessageDialog dialog
919         (*window, ("Now send the turn file back to the game master."), 0);
920       dialog.run();
921       dialog.hide();
922     }
923   game_ended.emit();
924 }
925
926 void GameWindow::update_diplomacy_button (bool sensitive)
927 {
928   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
929     {
930       diplomacy_button->set_sensitive (false);
931       return;
932     }
933   if (GameScenario::s_diplomacy == false)
934     {
935       diplomacy_button->set_sensitive (false);
936       return;
937     }
938   diplomacy_button->set_sensitive(sensitive);
939 }
940
941 bool GameWindow::setup_game(GameScenario *game_scenario, NextTurn *nextTurn)
942 {
943   currently_selected_stack = NULL;
944   /*
945    * this is done in GameScenario now.
946   Playerlist *pl = Playerlist::getInstance();
947   Armysetlist *al = Armysetlist::getInstance();
948   for (Playerlist::iterator i = pl->begin(); i != pl->end(); i++)
949     if ((*i)->getType() != Player::NETWORKED)
950       al->getArmyset((*i)->getArmyset())->instantiateImages();
951
952   GameMap::getInstance()->getTileset()->instantiateImages();
953   GameMap::getInstance()->getShieldset()->instantiateImages();
954   GameMap::getInstance()->getCityset()->instantiateImages();
955   */
956
957   Sound::getInstance()->haltMusic(false);
958   Sound::getInstance()->enableBackground();
959
960   if (game)
961     delete game;
962   game = new Game(game_scenario, nextTurn);
963
964   show_shield_turn();
965   return true;
966 }
967
968 bool GameWindow::on_delete_event(GdkEventAny *e)
969 {
970   on_quit_activated();
971
972   return true;
973 }
974
975 bool GameWindow::on_bigmap_mouse_button_event(GdkEventButton *e)
976 {
977   if (e->type != GDK_BUTTON_PRESS && e->type != GDK_BUTTON_RELEASE)
978     return true;        // useless event
979
980   if (game)
981     game->get_bigmap().mouse_button_event(to_input_event(e));
982
983   return true;
984 }
985
986 bool GameWindow::on_bigmap_mouse_motion_event(GdkEventMotion *e)
987 {
988   static guint prev = 0;
989   if (game)
990     {
991       guint delta = e->time - prev;
992       if (delta > 40 || delta < 0)
993         {
994           game->get_bigmap().mouse_motion_event(to_input_event(e));
995           bigmap_drawingarea->grab_focus();
996           prev = e->time;
997         }
998     }
999   return true;
1000 }
1001     
1002 bool GameWindow::on_bigmap_scroll_event(GdkEventScroll* event)
1003 {
1004   switch (event->direction) 
1005     {
1006     case GDK_SCROLL_LEFT:
1007     case GDK_SCROLL_RIGHT:
1008       break;
1009     case GDK_SCROLL_UP:
1010       //game->get_bigmap().zoom_in();
1011       break;
1012     case GDK_SCROLL_DOWN:
1013       //game->get_bigmap().zoom_out();
1014       break;
1015     }
1016   return true;
1017 }
1018
1019 void GameWindow::on_bigmap_cursor_changed(GraphicsCache::CursorType cursor)
1020 {
1021   bigmap_drawingarea->get_window()->set_cursor 
1022     (Gdk::Cursor
1023      (Gdk::Display::get_default(), 
1024       GraphicsCache::getInstance()->getCursorPic (cursor)->to_pixbuf(), 4, 4));
1025 }
1026
1027 bool GameWindow::on_bigmap_key_event(GdkEventKey *e)
1028 {
1029   if (e->keyval == GDK_Shift_L || e->keyval == GDK_Shift_R)
1030     game->get_bigmap().set_shift_key_down (e->type == GDK_KEY_PRESS);
1031   if (e->keyval == GDK_Control_L || e->keyval == GDK_Control_R)
1032     game->get_bigmap().set_control_key_down (e->type == GDK_KEY_PRESS);
1033
1034   return true;
1035 }
1036
1037 bool GameWindow::on_smallmap_mouse_button_event(GdkEventButton *e)
1038 {
1039   if (e->type != GDK_BUTTON_PRESS && e->type != GDK_BUTTON_RELEASE)
1040     return true;        // useless event
1041
1042   if (game)
1043     game->get_smallmap().mouse_button_event(to_input_event(e));
1044
1045   return true;
1046 }
1047
1048 bool GameWindow::on_smallmap_mouse_motion_event(GdkEventMotion *e)
1049 {
1050   static guint prev = 0;
1051   if (game)
1052     {
1053       guint delta = e->time - prev;
1054       if (delta > 100 || delta < 0)
1055         {
1056           game->get_smallmap().mouse_motion_event(to_input_event(e));
1057           prev = e->time;
1058         }
1059
1060       map_eventbox->get_window()->set_cursor 
1061         (Gdk::Cursor
1062          (Gdk::Display::get_default(), 
1063           GraphicsCache::getInstance()->getCursorPic
1064                       (GraphicsCache::MAGNIFYING_GLASS)->to_pixbuf(), 8, 5));
1065     }
1066
1067   return true;
1068 }
1069
1070 bool GameWindow::on_smallmap_exposed(GdkEventExpose *event)
1071 {
1072   Glib::RefPtr<Gdk::Window> window = map_drawingarea->get_window();
1073   if (window)
1074     {
1075       Glib::RefPtr<Gdk::Pixmap> surface = game->get_smallmap().get_surface();
1076       window->draw_drawable(map_drawingarea->get_style()->get_white_gc(),
1077                             surface, event->area.x, event->area.y, 
1078                             event->area.x, event->area.y, 
1079                             event->area.width, event->area.height);
1080     }
1081   return true;
1082 }
1083 bool GameWindow::on_bigmap_exposed(GdkEventExpose *event)
1084 {
1085   Glib::RefPtr<Gdk::Window> window = bigmap_drawingarea->get_window();
1086   if (window)
1087     {
1088       Glib::RefPtr<Gdk::Pixmap> surface = game->get_bigmap().get_surface();
1089       int width = 0, height = 0;
1090       surface->get_size(width, height);
1091
1092       window->draw_drawable(bigmap_drawingarea->get_style()->get_white_gc(),
1093                              surface, event->area.x, event->area.y, 
1094                              event->area.x, event->area.y, 
1095                              event->area.width, event->area.height);
1096     }
1097   return true;
1098 }
1099 void GameWindow::on_bigmap_surface_changed(Gtk::Allocation box)
1100 {
1101   static Gtk::Allocation last_box = Gtk::Allocation(0,0,1,1);
1102   if (!sdl_inited) {
1103     sdl_inited = true;
1104     sdl_initialized.emit();
1105   }
1106
1107   if (game) {
1108     if (box.get_width() != last_box.get_width() || box.get_height() != last_box.get_height())
1109       {
1110         //bigmap_drawingarea->set_allocation(box);
1111         game->get_bigmap().screen_size_changed(bigmap_drawingarea->get_allocation());
1112         game->redraw();
1113       }
1114   }
1115   last_box = box;
1116 }
1117
1118 void GameWindow::on_load_game_activated()
1119 {
1120   Gtk::FileChooserDialog chooser(*window, _("Choose Game to Load"));
1121   Gtk::FileFilter sav_filter;
1122   sav_filter.add_pattern("*.sav");
1123   chooser.set_filter(sav_filter);
1124   chooser.set_current_folder(Configuration::s_savePath);
1125
1126   chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1127   chooser.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1128   chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
1129
1130   chooser.show_all();
1131   int res = chooser.run();
1132   chooser.hide();
1133
1134   if (res == Gtk::RESPONSE_ACCEPT)
1135     {
1136       std::string filename = chooser.get_filename();
1137       current_save_filename = filename;
1138       if (filename ==  (File::getSavePath() + "autosave.sav"))
1139         game->inhibitAutosaveRemoval(true);
1140       d_load_filename = filename;
1141       stop_game("load-game");
1142       //now look at on_game_stopped.
1143     }
1144 }
1145
1146 void GameWindow::on_save_game_activated()
1147 {
1148   if (current_save_filename.empty())
1149     on_save_game_as_activated();
1150   else
1151     {
1152       if (game)
1153         {
1154           bool success = game->saveGame(current_save_filename);
1155           if (!success)
1156             show_error(_("Game was not saved!"));
1157         }
1158     }
1159 }
1160
1161 void GameWindow::on_save_game_as_activated()
1162 {
1163   Gtk::FileChooserDialog chooser(*window, _("Choose a Name"),
1164                                  Gtk::FILE_CHOOSER_ACTION_SAVE);
1165   Gtk::FileFilter sav_filter;
1166   sav_filter.add_pattern("*.sav");
1167   chooser.set_filter(sav_filter);
1168   chooser.set_current_folder(Configuration::s_savePath);
1169
1170   chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1171   chooser.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1172   chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
1173
1174   chooser.show_all();
1175   int res = chooser.run();
1176   chooser.hide();
1177
1178   if (res == Gtk::RESPONSE_ACCEPT)
1179     {
1180       std::string filename = chooser.get_filename();
1181
1182       current_save_filename = filename;
1183
1184       if (game)
1185         {
1186           bool success = game->saveGame(current_save_filename);
1187           if (!success)
1188             show_error(_("Error saving game!"));
1189         }
1190     }
1191 }
1192
1193 void GameWindow::on_quit_activated()
1194 {
1195   Gtk::Dialog* dialog;
1196   Glib::RefPtr<Gtk::Builder> xml
1197     = Gtk::Builder::create_from_file(get_glade_path() + "/game-quit-dialog.ui");
1198   xml->get_widget("dialog", dialog);
1199   Decorated decorator;
1200   decorator.decorate(dialog);
1201   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1202
1203   dialog->set_transient_for(*window);
1204
1205   int response = dialog->run();
1206   dialog->hide();
1207
1208   if (response == Gtk::RESPONSE_ACCEPT) //end the game
1209     {
1210       stop_game("quit");
1211     }
1212   delete dialog;
1213 }
1214
1215 void GameWindow::on_game_stopped()
1216 {
1217   if (stop_action == "quit")
1218     {
1219       if (game)
1220         {
1221           delete game;
1222           game = NULL;
1223         }
1224       game_ended.emit();
1225     }
1226   else if (stop_action == "game-over")
1227     {
1228       if (game_winner)
1229         {
1230           if (game_winner->getType() != Player::HUMAN)
1231             {
1232               if (game)
1233                 {
1234                   delete game;
1235                   game = NULL;
1236                 }
1237               game_ended.emit();
1238             }
1239           else
1240             {
1241               //we need to keep the game object around
1242               //so that we can give out some cheese
1243               give_some_cheese(game_winner);
1244             }
1245         }
1246       else
1247         {
1248           if (game)
1249             {
1250               delete game;
1251               game = NULL;
1252             }
1253           game_ended.emit();
1254         }
1255     }
1256   else if (stop_action == "load-game")
1257     {
1258       if (game)
1259         {
1260           delete game;
1261           game = NULL;
1262         }
1263       bool broken = false;
1264       GameScenario* game_scenario = new GameScenario(d_load_filename, broken);
1265
1266       if (broken)
1267         {
1268           on_message_requested(_("Corrupted saved game file."));
1269           game_ended.emit();
1270           return;
1271         }
1272       if (game_scenario->getPlayMode() == GameScenario::HOTSEAT)
1273         load_game(game_scenario, 
1274                   new NextTurnHotseat(game_scenario->getTurnmode(),
1275                                       game_scenario->s_random_turns));
1276       else if (game_scenario->getPlayMode() == GameScenario::PLAY_BY_MAIL)
1277         {
1278           PbmGameServer::getInstance()->start();
1279           load_game(game_scenario, 
1280                     new NextTurnPbm(game_scenario->getTurnmode(),
1281                                     game_scenario->s_random_turns));
1282         }
1283       else if (game_scenario->getPlayMode() == GameScenario::NETWORKED)
1284         load_game(game_scenario, 
1285                   new NextTurnNetworked(game_scenario->getTurnmode(),
1286                                         game_scenario->s_random_turns));
1287     }
1288 }
1289
1290 void GameWindow::on_quests_activated()
1291 {
1292   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1293     return;
1294   Player *player = Playerlist::getActiveplayer();
1295   std::vector<Quest*> quests
1296     = QuestsManager::getInstance()->getPlayerQuests(player);
1297   Stack *s = player->getActivestack();
1298   Hero *hero = NULL;
1299   if (s)
1300     hero = s->getFirstHeroWithAQuest();
1301   QuestReportDialog d(quests, hero);
1302   d.set_parent_window(*window);
1303   d.run();
1304   d.hide();
1305   return;
1306 }
1307
1308 void GameWindow::on_fullscreen_activated()
1309 {
1310   if (fullscreen_menuitem->get_active())
1311     window->fullscreen();
1312   else
1313     window->unfullscreen();
1314 }
1315
1316 void GameWindow::on_signpost_activated()
1317 {
1318   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1319     return;
1320   Gtk::Dialog* dialog;
1321
1322   Glib::RefPtr<Gtk::Builder> xml
1323     = Gtk::Builder::create_from_file(get_glade_path() + "/signpost-change-dialog.ui");
1324
1325   xml->get_widget("dialog", dialog);
1326   Decorated decorator;
1327   decorator.decorate(dialog);
1328   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1329   dialog->set_transient_for(*window);
1330
1331   decorator.set_title(_("Signpost"));
1332
1333   Stack *stack = Playerlist::getActiveplayer()->getActivestack();
1334   if (!stack)
1335     return;
1336   Signpost *s = GameMap::getSignpost(stack->getPos());
1337   if (!s)
1338     return;
1339   Gtk::Label *l;
1340   xml->get_widget("label", l);
1341   l->set_text(_("Change the message on this sign:"));
1342   Gtk::Entry *e;
1343   xml->get_widget("message_entry", e);
1344   e->set_text(s->getName());
1345   e->set_activates_default(true);
1346   dialog->show_all();
1347   int response = dialog->run();
1348   dialog->hide();
1349
1350   if (response == Gtk::RESPONSE_ACCEPT)
1351     Playerlist::getActiveplayer()->signpostChange(s, e->get_text());
1352
1353   delete dialog;
1354   return;
1355 }
1356
1357   
1358 void GameWindow::on_stack_info_activated()
1359 {
1360   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1361     return;
1362   StackInfoDialog d(currently_selected_stack->getPos());
1363   d.set_parent_window(*window);
1364   d.run();
1365   Stack *s = d.get_selected_stack();
1366   d.hide();
1367   on_stack_info_changed(s);
1368   //FIXME, armies don't stay selected in the right way.  to reproduce:
1369   //go in with all three selected.  deselect middle one in stackinfodialog,
1370   //then return.
1371 }
1372
1373 void GameWindow::on_disband_activated()
1374 {
1375   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1376     return;
1377   Stack *stack = Playerlist::getActiveplayer()->getActivestack();
1378   Gtk::Dialog* dialog;
1379
1380   Glib::RefPtr<Gtk::Builder> xml
1381     = Gtk::Builder::create_from_file(get_glade_path() + "/disband-stack-dialog.ui");
1382
1383   xml->get_widget("dialog", dialog);
1384   Decorated decorator;
1385   decorator.decorate(dialog);
1386   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1387   dialog->set_transient_for(*window);
1388
1389   decorator.set_title(_("Disband"));
1390
1391   Gtk::Label *l;
1392   xml->get_widget("label", l);
1393
1394   std::vector<guint32> heroes;
1395   stack->getHeroes(heroes);
1396   Glib::ustring s = _("Are you sure you want to disband this group?");
1397   if (heroes.size() > 0)
1398     {
1399       s += "\n";
1400       s += String::ucompose( ngettext("(It contains %1 hero).",
1401                                       "(It contains %1 heroes).", 
1402                                       heroes.size()), heroes.size());
1403     }
1404   l->set_text(s);
1405   dialog->show_all();
1406   int response = dialog->run();
1407   dialog->hide();
1408
1409   if (response == Gtk::RESPONSE_ACCEPT) //disband the active stack
1410     Playerlist::getActiveplayer()->stackDisband(NULL);
1411
1412   return;
1413 }
1414
1415 void GameWindow::on_resignation_completed()
1416 {
1417   Gtk::Dialog* dialog;
1418
1419   Glib::RefPtr<Gtk::Builder> xml
1420     = Gtk::Builder::create_from_file(get_glade_path() + 
1421                                 "/player-resign-completed-dialog.ui");
1422
1423   xml->get_widget("dialog", dialog);
1424   Decorated decorator;
1425   decorator.decorate(dialog);
1426   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1427   dialog->set_transient_for(*window);
1428
1429   dialog->show_all();
1430   dialog->run();
1431   dialog->hide();
1432   delete dialog;
1433
1434   return;
1435 }
1436
1437 void GameWindow::on_resign_activated()
1438 {
1439   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1440     return;
1441
1442   Gtk::Dialog* dialog;
1443
1444   Glib::RefPtr<Gtk::Builder> xml
1445     = Gtk::Builder::create_from_file(get_glade_path() + "/player-resign-dialog.ui");
1446
1447   xml->get_widget("dialog", dialog);
1448   Decorated decorator;
1449   decorator.decorate(dialog);
1450   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1451   dialog->set_transient_for(*window);
1452
1453   decorator.set_title(_("Resign"));
1454
1455   Gtk::Label *l;
1456   xml->get_widget("label", l);
1457
1458   l->set_text(_("Are you sure you want to resign?"));
1459   dialog->show_all();
1460   int response = dialog->run();
1461
1462   if (response == Gtk::RESPONSE_ACCEPT) //disband all stacks, raze all cities
1463     {
1464       Playerlist::getActiveplayer()->resign();
1465       dialog->hide();
1466       on_resignation_completed();
1467     }
1468
1469   delete dialog;
1470   return;
1471 }
1472
1473 void GameWindow::on_vectoring_activated()
1474 {
1475   City *city;
1476   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1477     return;
1478
1479   if (currently_selected_stack)
1480     {
1481       Vector<int> pos = currently_selected_stack->getPos();
1482       city = Citylist::getInstance()->getNearestVisibleFriendlyCity(pos);
1483     }
1484   else
1485     city = Citylist::getInstance()->getFirstCity(Playerlist::getActiveplayer());
1486
1487   if (!city)
1488     return;
1489   bool see_all = true;
1490   DestinationDialog d(city, &see_all);
1491
1492   d.set_parent_window(*window);
1493   d.run();
1494   d.hide();
1495   return;
1496 }
1497
1498 void GameWindow::on_production_activated()
1499 {
1500   City *city;
1501   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1502     return;
1503
1504   if (currently_selected_stack)
1505     {
1506       Vector<int> pos = currently_selected_stack->getPos();
1507       city = Citylist::getInstance()->getNearestVisibleFriendlyCity(pos);
1508     }
1509   else
1510     city = Citylist::getInstance()->getFirstCity(Playerlist::getActiveplayer());
1511
1512   if (!city)
1513     return;
1514
1515   on_city_visited(city);
1516   return;
1517 }
1518
1519 void GameWindow::on_preferences_activated()
1520 {
1521   Player *current = Playerlist::getInstance()->getActiveplayer();
1522   PreferencesDialog d(false);
1523   d.set_parent_window(*window);
1524   d.run(game);
1525   d.hide();
1526   game->get_bigmap().set_control_key_down (false);
1527   if (current != Playerlist::getInstance()->getActiveplayer())
1528     game->end_turn();
1529 }
1530
1531 void GameWindow::on_group_ungroup_activated()
1532 {
1533   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1534     return;
1535   group_ungroup_toggle->set_active(!group_ungroup_toggle->get_active());
1536 }
1537
1538 void GameWindow::on_fight_order_activated()
1539 {
1540   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1541     return;
1542   FightOrderDialog d(Playerlist::getActiveplayer());
1543   d.set_parent_window(*window);
1544   d.run();
1545   d.hide();
1546 }
1547
1548 void GameWindow::on_levels_activated()
1549 {
1550   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1551     return;
1552   HeroLevelsDialog d(Playerlist::getActiveplayer());
1553   d.set_parent_window(*window);
1554   d.run();
1555   d.hide();
1556 }
1557
1558 void GameWindow::on_ruin_report_activated()
1559 {
1560   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1561     return;
1562   Vector<int> pos;
1563   pos.x = 0;
1564   pos.y = 0;
1565   if (currently_selected_stack)
1566     pos = currently_selected_stack->getPos();
1567
1568   if (Templelist::getInstance()->size() == 0 &&
1569       Ruinlist::getInstance()->size() == 0)
1570     {
1571       std::string s = _("No ruins or temples to show!");
1572       TimedMessageDialog dialog(*window, s, 30);
1573
1574       dialog.show_all();
1575       dialog.run();
1576       dialog.hide();
1577       return;
1578     }
1579   RuinReportDialog d(pos);
1580   d.set_parent_window(*window);
1581   d.run();
1582   d.hide();
1583 }
1584
1585 void GameWindow::on_army_bonus_activated()
1586 {
1587   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1588     return;
1589   ArmyBonusDialog d(Playerlist::getActiveplayer());
1590   d.set_parent_window(*window);
1591   d.run();
1592   d.hide();
1593 }
1594
1595 void GameWindow::on_item_bonus_activated()
1596 {
1597   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1598     return;
1599   ItemBonusDialog d;
1600   d.set_parent_window(*window);
1601   d.run();
1602   d.hide();
1603 }
1604
1605 void GameWindow::on_army_report_activated()
1606 {
1607   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1608     return;
1609   ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::ARMY);
1610   d.set_parent_window(*window);
1611   d.run();
1612   d.hide();
1613 }
1614
1615 void GameWindow::on_city_report_activated()
1616 {
1617   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1618     return;
1619   ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::CITY);
1620   d.set_parent_window(*window);
1621   d.run();
1622   d.hide();
1623 }
1624
1625 void GameWindow::on_gold_report_activated()
1626 {
1627   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1628     return;
1629   ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::GOLD);
1630   d.set_parent_window(*window);
1631   d.run();
1632   d.hide();
1633 }
1634
1635 void GameWindow::on_production_report_activated()
1636 {
1637   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1638     return;
1639   ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::PRODUCTION);
1640   d.set_parent_window(*window);
1641   d.run();
1642   d.hide();
1643 }
1644
1645 void GameWindow::on_winning_report_activated()
1646 {
1647   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1648     return;
1649   ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::WINNING);
1650   d.set_parent_window(*window);
1651   d.run();
1652   d.hide();
1653 }
1654
1655 void GameWindow::on_city_history_activated()
1656 {
1657   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1658     return;
1659   HistoryReportDialog d(Playerlist::getActiveplayer(), 
1660                         HistoryReportDialog::CITY);
1661   d.set_parent_window(*window);
1662   d.run();
1663   d.hide();
1664 }
1665
1666 void GameWindow::on_ruin_history_activated()
1667 {
1668   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1669     return;
1670   HistoryReportDialog d(Playerlist::getActiveplayer(), 
1671                         HistoryReportDialog::RUIN);
1672   d.set_parent_window(*window);
1673   d.run();
1674   d.hide();
1675 }
1676
1677 void GameWindow::on_event_history_activated()
1678 {
1679   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1680     return;
1681   HistoryReportDialog d(Playerlist::getActiveplayer(),
1682                         HistoryReportDialog::EVENTS);
1683   d.set_parent_window(*window);
1684   d.run();
1685   d.hide();
1686 }
1687
1688 void GameWindow::on_gold_history_activated()
1689 {
1690   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1691     return;
1692   HistoryReportDialog d(Playerlist::getActiveplayer(),
1693                         HistoryReportDialog::GOLD);
1694   d.set_parent_window(*window);
1695   d.run();
1696   d.hide();
1697 }
1698
1699 void GameWindow::on_winner_history_activated()
1700 {
1701   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1702     return;
1703   HistoryReportDialog d(Playerlist::getActiveplayer(),
1704                         HistoryReportDialog::WINNING);
1705   d.set_parent_window(*window);
1706   d.run();
1707   d.hide();
1708 }
1709
1710 void GameWindow::on_triumphs_activated()
1711 {
1712   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1713     return;
1714   TriumphsDialog d(Playerlist::getActiveplayer());
1715   d.set_parent_window(*window);
1716   d.run();
1717   d.hide();
1718 }
1719
1720 void GameWindow::on_help_about_activated()
1721 {
1722   Gtk::AboutDialog* dialog;
1723
1724   Glib::RefPtr<Gtk::Builder> xml
1725     = Gtk::Builder::create_from_file(get_glade_path() + "/about-dialog.ui");
1726
1727   xml->get_widget("dialog", dialog);
1728   dialog->set_icon_from_file(File::getMiscFile("various/castle_icon.png"));
1729   Decorated decorator;
1730   decorator.decorate(dialog);
1731   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1732   dialog->set_transient_for(*window);
1733
1734   dialog->set_version(PACKAGE_VERSION);
1735   dialog->set_logo(GraphicsCache::getMiscPicture("castle_icon.png")->to_pixbuf());
1736   dialog->show_all();
1737   dialog->run();
1738   dialog->hide();
1739   delete dialog;
1740
1741   return;
1742 }
1743
1744 void GameWindow::on_diplomacy_report_activated()
1745 {
1746   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1747     return;
1748   if (GameScenario::s_diplomacy == false)
1749     return;
1750   DiplomacyReportDialog d(Playerlist::getActiveplayer());
1751   d.set_parent_window(*window);
1752   d.run();
1753   d.hide();
1754 }
1755
1756 void GameWindow::on_diplomacy_button_clicked()
1757 {
1758   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1759     return;
1760   DiplomacyDialog d(Playerlist::getActiveplayer());
1761   d.set_parent_window(*window);
1762   d.run();
1763   d.hide();
1764 }
1765
1766 void GameWindow::stop_game(std::string action)
1767 {
1768   stop_action = action;
1769   Sound::getInstance()->disableBackground();
1770   if (game)
1771     {
1772       game->stopGame();
1773       current_save_filename = "";
1774     }
1775 }
1776
1777 void GameWindow::on_game_over(Player *winner)
1778 {
1779
1780   Gtk::Dialog* dialog;
1781
1782   Glib::RefPtr<Gtk::Builder> xml
1783     = Gtk::Builder::create_from_file(get_glade_path() + "/game-over-dialog.ui");
1784
1785   xml->get_widget("dialog", dialog);
1786   Decorated decorator;
1787   decorator.decorate(dialog);
1788   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1789   dialog->set_transient_for(*window);
1790
1791   Gtk::Image *image;
1792   xml->get_widget("image", image);
1793
1794   image->property_pixbuf() = GraphicsCache::getMiscPicture("win.png", false)->to_pixbuf();
1795
1796   Gtk::Label *label;
1797   xml->get_widget("label", label);
1798   Glib::ustring s;
1799   s += String::ucompose(_("Congratulations to %1 for conquering the world!"), 
1800         winner->getName());
1801   label->set_markup("<b>" + s + "</b>");
1802
1803   dialog->show_all();
1804   dialog->run();
1805   dialog->hide();
1806
1807   game_winner = winner;
1808   stop_game("game-over");
1809   delete dialog;
1810 }
1811
1812 void GameWindow::on_player_died(Player *player)
1813 {
1814   assert(player);
1815
1816   Glib::ustring s;
1817   s += String::ucompose(_("The rule of %1 has permanently ended!"),
1818                         player->getName());
1819   if (Playerlist::getInstance()->countHumanPlayersAlive() == 0 &&
1820       player->getType() == Player::HUMAN)
1821     {
1822       s += "\n";
1823       s += _("No further human resistance is possible\nbut the battle will continue!");
1824       s += "\n";
1825       s += _("Press `CTRL-P' to stop the war\nand visit the sites of thy old battles.");
1826     }
1827
1828   TimedMessageDialog dialog(*window, s, 30);
1829
1830   dialog.show_all();
1831   dialog.run();
1832   dialog.hide();
1833 }
1834
1835 void GameWindow::on_message_requested(std::string msg)
1836 {
1837   // FIXME: this is a bit crude, maybe beef it up
1838   Gtk::MessageDialog dialog(*window, msg);
1839   Decorated decorator;
1840   decorator.decorate(dynamic_cast<Gtk::Dialog*>(&dialog));
1841   //TimedMessageDialog dialog(*window, msg, 30, 5);
1842   dialog.show_all();
1843   dialog.run();
1844   dialog.hide();
1845 }
1846
1847 void GameWindow::on_stack_toggled(Gtk::RadioButton *radio, Stack *stack)
1848 {
1849   if (radio->get_active() == true)
1850     {
1851       if (stack == currently_selected_stack)
1852         return;
1853       currently_selected_stack = stack;
1854       Playerlist::getActiveplayer()->setActivestack(stack);
1855       on_stack_info_changed(stack);
1856       game->recalculate_moves_for_stack(stack);
1857     }
1858 }
1859
1860 void GameWindow::on_army_toggled(Gtk::ToggleButton *toggle, Stack *stack, Army *army)
1861 {
1862   Player *p = Playerlist::getActiveplayer();
1863   Stack *s = p->getActivestack();
1864   group_ungroup_toggle->set_sensitive(false);
1865   if (toggle->get_active() == true)
1866     {
1867       printf("split army %d from stack %d, and put it into current stack %d.\n", army->getId(), stack->getId(), currently_selected_stack->getId());
1868
1869       if (stack->size() > 1)
1870         {
1871           Stack *new_stack = p->stackSplitArmy(stack, army);
1872           if (new_stack)
1873             p->stackJoin(currently_selected_stack, new_stack);
1874         }
1875       else
1876         p->stackJoin(currently_selected_stack, stack);
1877       currently_selected_stack->sortForViewing(true);
1878     }
1879   else
1880     {
1881       //printf("split army %d from stack %d, and make a new stack.\n", army->getId(), stack->getId());
1882       p->stackSplitArmy(stack, army);
1883       stack->sortForViewing(true);
1884     }
1885   on_stack_info_changed(s);
1886   group_ungroup_toggle->set_sensitive(true);
1887   game->recalculate_moves_for_stack(s);
1888 }
1889
1890 void GameWindow::on_group_toggled(Gtk::ToggleButton *toggle)
1891 {
1892   if (toggle->sensitive() == false)
1893     return;
1894   printf("group/ungroup was clicked\n");
1895   bool active = toggle->get_active();
1896       
1897   printf("active is %d so it means we are %s\n",
1898          active, active ? "grouped, and going to ungrouped"  :
1899          "ungrouped, and going to group");
1900   clear_army_buttons();
1901       
1902   StackTile *s = GameMap::getStacks(currently_selected_stack->getPos());
1903   if (active)
1904     {
1905       s->group(Playerlist::getActiveplayer(), currently_selected_stack);
1906       currently_selected_stack->sortForViewing(true);
1907     }
1908   else
1909     s->ungroup(Playerlist::getActiveplayer());
1910   //Stack *stack = s->getFriendlyStacks(Playerlist::getActiveplayer()).front();
1911   //currently_selected_stack = stack;
1912   //Playerlist::getActiveplayer()->setActivestack(stack);
1913
1914   on_stack_info_changed(currently_selected_stack);
1915   game->recalculate_moves_for_stack(currently_selected_stack);
1916 }
1917
1918 bool GameWindow::on_army_button_event(GdkEventButton *e,
1919                                       Gtk::ToggleButton *toggle, Army *army)
1920 {
1921   // if a hero is right-clicked, pop up the hero dialog, otherwise show the
1922   // army info tip
1923   MouseButtonEvent event = to_input_event(e);
1924   if (event.button == MouseButtonEvent::RIGHT_BUTTON
1925       && event.state == MouseButtonEvent::PRESSED) {
1926
1927     if (army_info_tip)
1928       delete army_info_tip;
1929     army_info_tip = new ArmyInfoTip(toggle, army);
1930
1931     return true;
1932   }
1933   else if (event.button == MouseButtonEvent::RIGHT_BUTTON
1934            && event.state == MouseButtonEvent::RELEASED) {
1935       {
1936         if (army_info_tip)
1937           {
1938             delete army_info_tip;
1939             army_info_tip = NULL;
1940           }
1941       }
1942     return true;
1943   }
1944
1945   return false;
1946 }
1947
1948 void GameWindow::clear_army_buttons()
1949 {
1950   for (army_buttons_type::iterator i = army_buttons.begin(),
1951        end = army_buttons.end(); i != end; ++i)
1952     delete *i;
1953   army_buttons.clear();
1954   for (stack_buttons_type::iterator i = stack_buttons.begin(),
1955        end = stack_buttons.end(); i != end; ++i)
1956     delete *i;
1957   stack_buttons.clear();
1958   delete stack_info_button_table;
1959   stack_info_button_table = NULL;
1960 }
1961
1962 void GameWindow::on_progress_status_changed(std::string string)
1963 {
1964   progress_status_label->set_markup("<b>" + string + "</b>");
1965 }
1966
1967 void GameWindow::on_progress_changed()
1968 {
1969   turn_progressbar->pulse();
1970 }
1971
1972 void GameWindow::on_sidebar_stats_changed(SidebarStats s)
1973 {
1974   if (Configuration::s_decorated)
1975     {
1976       cities_stats_label->set_markup(String::ucompose("<b>%1</b>", s.cities));
1977       gold_stats_label->set_markup(String::ucompose("<b>%1</b>", s.gold));
1978       income_stats_label->set_markup(String::ucompose("<b>%1</b>", s.income));
1979       upkeep_stats_label->set_markup(String::ucompose("<b>%1</b>", s.upkeep));
1980       turn_label->set_markup(String::ucompose("<b>Turn %1</b>", s.turns));
1981     }
1982   else
1983     {
1984       cities_stats_label->set_markup(String::ucompose("%1", s.cities));
1985       gold_stats_label->set_markup(String::ucompose("%1", s.gold));
1986       income_stats_label->set_markup(String::ucompose("%1", s.income));
1987       upkeep_stats_label->set_markup(String::ucompose("%1", s.upkeep));
1988       turn_label->set_markup(String::ucompose("Turn %1", s.turns));
1989     }
1990   Glib::ustring tip;
1991   tip = String::ucompose(
1992                          ngettext("You have %1 city!",
1993                                   "You have %1 cities!", s.cities), s.cities);
1994   cities_stats_image->set_tooltip_text(tip);
1995   cities_stats_label->set_tooltip_text(tip);
1996   tip = String::ucompose(
1997                          ngettext("You have %1 gold piece in your treasury!",
1998                                   "You have %1 gold pieces in your treasury!", s.gold), s.gold);
1999   gold_stats_image->set_tooltip_text(tip);
2000   gold_stats_label->set_tooltip_text(tip);
2001   tip = String::ucompose(
2002                          ngettext("You earn %1 gold piece in income!",
2003                                   "You earn %1 gold pieces in income!", s.income), s.income);
2004   income_stats_image->set_tooltip_text(tip);
2005   income_stats_label->set_tooltip_text(tip);
2006   tip = String::ucompose(
2007                          ngettext("You pay %1 gold piece in upkeep!",
2008                                   "You pay %1 gold pieces in upkeep!", s.upkeep), s.upkeep);
2009   upkeep_stats_image->set_tooltip_text(tip);
2010   upkeep_stats_label->set_tooltip_text(tip);
2011 }
2012
2013 void GameWindow::on_bigmap_changed(Glib::RefPtr<Gdk::Pixmap> map)
2014 {
2015   int width = 0;
2016   int height = 0;
2017   map->get_size(width, height);
2018   Glib::RefPtr<Gdk::Window> window = bigmap_drawingarea->get_window();
2019   if (window)
2020     {
2021       Gdk::Rectangle r = Gdk::Rectangle(0, 0, width, height);
2022       window->invalidate_rect(r, true);
2023     }
2024 }
2025 void GameWindow::on_smallmap_changed(Glib::RefPtr<Gdk::Pixmap> map, Gdk::Rectangle r)
2026 {
2027   int width = 0;
2028   int height = 0;
2029   map->get_size(width, height);
2030   map_container->property_width_request() = width;
2031   map_container->property_height_request() = height;
2032       
2033   Glib::RefPtr<Gdk::Window> window = map_drawingarea->get_window();
2034   if (window)
2035     window->invalidate_rect(r, true);
2036   //map_image->property_pixbuf() = map;
2037   //map.clear();
2038   //still resides at smallmap->get_surface()
2039 }
2040
2041 void GameWindow::on_smallmap_slid(Rectangle view)
2042 {
2043   on_smallmap_changed(game->get_smallmap().get_surface(),
2044                       Gdk::Rectangle(view.x, view.y, view.w, view.h));
2045   while (g_main_context_iteration(NULL, FALSE)); //doEvents
2046 }
2047
2048 void GameWindow::on_stack_info_changed(Stack *s)
2049 {
2050   clear_army_buttons();
2051
2052   currently_selected_stack = s;
2053
2054   if (!s)
2055     {
2056       if (Playerlist::getActiveplayer()->getType() == Player::HUMAN)
2057         show_stats();
2058       else
2059         show_progress();
2060     }
2061   else
2062     {
2063       if (s->getOwner()->getType() == Player::HUMAN)
2064         {
2065           StackTile *stile = GameMap::getStacks(s->getPos());
2066           stile->setDefending(s->getOwner(), false);
2067           stile->setParked(s->getOwner(), false);
2068
2069           show_stack(stile);
2070         }
2071       else
2072         show_progress();
2073     }
2074   return;
2075 }
2076
2077 void GameWindow::show_stats()
2078 {
2079   Armysetlist *al = Armysetlist::getInstance();
2080   int height = al->getTileSize(Playerlist::getActiveplayer()->getArmyset());
2081   height += turn_label->get_height();
2082   height += 50;
2083   stack_info_box->get_parent()->property_height_request() = height;
2084   stats_box->get_parent()->property_height_request() = height;
2085   stack_info_container->hide();
2086   progress_box->hide();
2087   stats_box->show();
2088 }
2089
2090 void GameWindow::show_progress()
2091 {
2092   turn_progressbar->property_fraction() = 0.0;
2093   if (Playerlist::getActiveplayer() == Playerlist::getInstance()->getNeutral())
2094     progress_status_label->set_text("");
2095   else
2096     progress_status_label->set_markup("<b>" + Playerlist::getActiveplayer()->getName() + "</b>");
2097   stats_box->hide();
2098   stack_info_container->hide();
2099   progress_box->show();
2100 }
2101
2102 void GameWindow::fill_in_group_info (StackTile *stile, Stack *s)
2103 {
2104   guint32 bonus = s->calculateMoveBonus();
2105   GraphicsCache *gc = GraphicsCache::getInstance();
2106   terrain_image->property_pixbuf() = gc->getMoveBonusPic(bonus, s->hasShip())->to_pixbuf();
2107   if (Configuration::s_decorated == true)
2108     group_moves_label->set_markup(String::ucompose("<b>%1</b>",
2109                                                    s->getMoves()));
2110   else
2111     group_moves_label->set_markup(String::ucompose("%1",
2112                                                    s->getMoves()));
2113   //printf ("toggling group/ungroup!\n");
2114   group_ungroup_toggle->set_sensitive(false);
2115   if (stile->getFriendlyStacks(s->getOwner()).size() != 1)
2116     group_ungroup_toggle->set_active(false);
2117   else
2118     group_ungroup_toggle->set_active(true);
2119   if (group_ungroup_toggle->get_active() == true)
2120     group_ungroup_toggle->set_label(_("UnGrp"));
2121   else
2122     group_ungroup_toggle->set_label(_("Grp"));
2123   group_ungroup_toggle->set_sensitive(true);
2124 }
2125
2126 void GameWindow::show_stack(StackTile *s)
2127 {
2128   Gtk::RadioButton *first_radio = NULL;
2129   GraphicsCache *gc = GraphicsCache::getInstance();
2130   //s->sortForViewing (true);
2131   stats_box->hide();
2132   progress_box->hide();
2133
2134   army_buttons.clear(); 
2135   stack_buttons.clear();
2136   int width = 0;
2137   int height = 0;
2138   std::list<Stack *> stks;
2139   stks = s->getFriendlyStacks(Playerlist::getActiveplayer());
2140   unsigned int count= 0;
2141   if (stack_info_button_table != NULL)
2142     delete stack_info_button_table;
2143   stack_info_button_table = new Gtk::Table(2, MAX_ARMIES_ON_A_SINGLE_TILE);
2144             
2145   for (std::list<Stack *>::iterator j = stks.begin(); j != stks.end(); j++)
2146     {
2147       bool first = true;
2148       for (Stack::iterator i = (*j)->begin(); i != (*j)->end(); ++i)
2149         {
2150           // construct a toggle button
2151           Army *army = *i;
2152           Gtk::VBox *toggle_box = manage(new Gtk::VBox);
2153
2154           // image
2155           Gtk::Image *army_image = new Gtk::Image();
2156           bool greyed_out = (*j)->getId() != currently_selected_stack->getId();
2157           Glib::RefPtr<Gdk::Pixbuf> army_icon = 
2158             gc->getArmyPic((*j)->getOwner()->getArmyset(), army->getTypeId(),
2159                            (*j)->getOwner(), army->getMedalBonuses(), 
2160                            greyed_out)->to_pixbuf();
2161           army_image->property_pixbuf() = army_icon;
2162           width = army_icon->get_width();
2163           height = army_icon->get_height();
2164           toggle_box->add(*manage(army_image));
2165           // number of moves
2166           Glib::ustring moves_str = String::ucompose("%1", army->getMoves());
2167           toggle_box->add(*manage(new Gtk::Label(moves_str,
2168                                                  Gtk::ALIGN_CENTER, Gtk::ALIGN_TOP)));
2169
2170           // the button itself
2171           Gtk::ToggleButton *toggle = new Gtk::ToggleButton;
2172           toggle->add(*toggle_box);
2173           toggle->set_active((*j)->getId() == currently_selected_stack->getId());
2174           toggle->signal_toggled().connect
2175             (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_army_toggled),
2176                         toggle, *j, army));
2177           toggle->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
2178           toggle->signal_button_press_event().connect
2179             (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_army_button_event),
2180                         toggle, army), false);
2181           toggle->signal_button_release_event().connect
2182             (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_army_button_event),
2183                         toggle, army), false);
2184           // add it
2185           if (first == true)
2186             {
2187               first = false;
2188               Gtk::RadioButton *radio;
2189               if (first_radio)
2190                 {
2191                   Gtk::RadioButtonGroup g = first_radio->get_group();
2192                   radio = new Gtk::RadioButton(g);
2193                 }
2194               else
2195               radio = new Gtk::RadioButton;
2196               radio->property_can_focus() = false;
2197               radio->set_active(currently_selected_stack->getId() == (*j)->getId());
2198               radio->signal_toggled().connect
2199                 (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_stack_toggled),
2200                             radio, *j));
2201               stack_info_button_table->attach(*toggle, count, count + 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
2202               stack_info_button_table->attach(*radio, count, count + 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
2203               stack_buttons.push_back(radio);
2204               if (first_radio == NULL)
2205                 first_radio = radio;
2206             }
2207           else
2208             {
2209               stack_info_button_table->attach(*toggle, count, count + 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
2210             }
2211           army_buttons.push_back(toggle);
2212
2213           count++;
2214         }
2215     }
2216   for (unsigned int i = count ; i < MAX_ARMIES_ON_A_SINGLE_TILE; i++)
2217     {
2218       // construct a toggle button
2219       Gtk::VBox *toggle_box = manage(new Gtk::VBox);
2220
2221       // image
2222       Gtk::Image *army_image = new Gtk::Image();
2223       Glib::RefPtr<Gdk::Pixbuf> empty_pic
2224         = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, width, height);
2225       empty_pic->fill(0x00000000);
2226       army_image->property_pixbuf() = empty_pic;
2227       toggle_box->add(*manage(army_image));
2228       // number of moves
2229       toggle_box->add(*manage
2230                       (new Gtk::Label(" ", Gtk::ALIGN_CENTER, Gtk::ALIGN_TOP)));
2231
2232       // the button itself
2233       Gtk::ToggleButton *toggle = new Gtk::ToggleButton;
2234       toggle->add(*toggle_box);
2235       toggle->set_sensitive(false);
2236       // clicking on this button does nothing.
2237       // add it
2238       //stack_info_box->pack_start(*toggle, Gtk::PACK_SHRINK);
2239       stack_info_button_table->attach(*toggle, i, i + 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
2240       army_buttons.push_back(toggle);
2241     }
2242   stack_info_box->pack_start(*manage(stack_info_button_table), Gtk::PACK_SHRINK);
2243
2244   fill_in_group_info(s, currently_selected_stack);
2245   //ensure_one_army_button_active(); 
2246   stack_info_container->show_all();
2247 }
2248
2249 void GameWindow::on_city_tip_changed(City *city, MapTipPosition mpos)
2250 {
2251   if (city == NULL)
2252     {
2253       delete city_info_tip;
2254       city_info_tip = NULL;
2255     }
2256   else
2257     {
2258       city_info_tip = new CityInfoTip(bigmap_drawingarea, mpos, city);
2259     }
2260 }
2261
2262 void GameWindow::on_stack_tip_changed(StackTile *stile, MapTipPosition mpos)
2263 {
2264   if (stile == NULL)
2265     {
2266       delete stack_info_tip;
2267       stack_info_tip = NULL;
2268     }
2269   else
2270     {
2271       stack_info_tip = new StackInfoTip(bigmap_drawingarea, mpos, stile);
2272     }
2273 }
2274
2275 void GameWindow::on_bigmap_tip_changed(Glib::ustring tip, MapTipPosition pos)
2276 {
2277   if (tip.empty())
2278     hide_map_tip();
2279   else
2280     show_map_tip(tip, pos);
2281 }
2282
2283 void GameWindow::show_map_tip(Glib::ustring msg, MapTipPosition pos)
2284 {
2285   // init the map tip
2286   if (map_tip != NULL)
2287     delete map_tip;
2288   map_tip = new Gtk::Window(Gtk::WINDOW_POPUP);
2289
2290   Gtk::Frame *f = manage(new Gtk::Frame);
2291   f->property_shadow_type() = Gtk::SHADOW_ETCHED_OUT;
2292
2293   Gtk::Label *l = manage(new Gtk::Label);
2294   l->set_padding(6, 6);
2295   l->set_text(msg);
2296   f->add(*l);
2297
2298   map_tip->add(*f);
2299   Decorated decorator;
2300   decorator.decorate(map_tip,File::getMiscFile("various/background.png"), 200);
2301   f->show_all();
2302
2303   // get screen position
2304   Vector<int> p;
2305   bigmap_drawingarea->get_window()->get_origin(p.x, p.y);
2306   p += pos.pos;
2307
2308   Vector<int> size(0, 0);
2309   map_tip->get_size(size.x, size.y);
2310
2311   switch (pos.justification)
2312     {
2313     case MapTipPosition::LEFT:
2314       map_tip->set_gravity(Gdk::GRAVITY_NORTH_WEST);
2315       break;
2316     case MapTipPosition::RIGHT:
2317       map_tip->set_gravity(Gdk::GRAVITY_NORTH_EAST);
2318       p.x -= size.x;
2319       break;
2320     case MapTipPosition::TOP:
2321       map_tip->set_gravity(Gdk::GRAVITY_NORTH_WEST);
2322       break;
2323     case MapTipPosition::BOTTOM:
2324       map_tip->set_gravity(Gdk::GRAVITY_SOUTH_WEST);
2325       p.y -= size.y;
2326       break;
2327     }
2328
2329   // and action
2330   map_tip->move(p.x, p.y);
2331   map_tip->show();
2332 }
2333
2334 void GameWindow::hide_map_tip()
2335 {
2336   if (map_tip != NULL)
2337     {
2338       delete map_tip;
2339       map_tip = NULL;
2340     }
2341 }
2342
2343 Reward* GameWindow::on_sage_visited (Ruin *ruin, Sage *sage, Stack *stack)
2344 {
2345   SageDialog d(sage, stack->getFirstHero()->getOwner(), 
2346                static_cast<Hero*>(stack->getFirstHero()), ruin);
2347   d.set_parent_window(*window);
2348   Reward *reward = d.run();
2349   d.hide();
2350   return reward;
2351 }
2352
2353 void GameWindow::on_ruin_rewarded (Reward_Ruin *reward)
2354 {
2355   RuinRewardedDialog d(reward);
2356   d.set_parent_window(*window);
2357   d.run();
2358   d.hide();
2359 }
2360
2361 void GameWindow::on_ruin_searched(Ruin *ruin, Stack *stack, Reward *reward)
2362 {
2363   Gtk::Dialog* dialog;
2364   if (ruin->hasSage())
2365     {
2366       if (reward->getType() == Reward::RUIN)
2367         return on_ruin_rewarded(static_cast<Reward_Ruin*>(reward));
2368     }
2369
2370   Glib::RefPtr<Gtk::Builder> xml
2371     = Gtk::Builder::create_from_file(get_glade_path() + "/ruin-searched-dialog.ui");
2372
2373
2374   xml->get_widget("dialog", dialog);
2375   Decorated decorator;
2376   decorator.decorate(dialog);
2377   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2378   dialog->set_transient_for(*window);
2379
2380   decorator.set_title(ruin->getName());
2381
2382   Gtk::Label *label;
2383   xml->get_widget("label", label);
2384
2385   Glib::ustring s = label->get_text();
2386   s += "\n\n";
2387   s += String::ucompose(_("%1 finds "), stack->getFirstHero()->getName());
2388   if (reward->getType() == Reward::GOLD)
2389     {
2390       Reward_Gold *gold = dynamic_cast<Reward_Gold*>(reward);
2391       s += String::ucompose(_("%1 gold pieces."), gold->getGold());
2392     }
2393   else if (reward->getType() == Reward::ALLIES)
2394     {
2395       Reward_Allies *allies = dynamic_cast<Reward_Allies*>(reward);
2396       s += String::ucompose(_("%1 allies!"), allies->getNoOfAllies());
2397     }
2398   else if (reward->getType() == Reward::ITEM)
2399     {
2400       Reward_Item *item = dynamic_cast<Reward_Item*>(reward);
2401       s += String::ucompose(_("the %1!"), item->getItem()->getName());
2402     }
2403   else if (reward->getType() == Reward::MAP)
2404     {
2405       Reward_Map *map = dynamic_cast<Reward_Map*>(reward);
2406       s += String::ucompose(_("a map!"), map->getName());
2407     }
2408
2409   label->set_text(s);
2410
2411   dialog->show_all();
2412   dialog->run();
2413   dialog->hide();
2414   delete dialog;
2415 }
2416
2417 void GameWindow::on_ruinfight_started(Stack *attackers, Stack *defenders)
2418 {
2419   //so and so encounters a wolf...
2420   Gtk::Dialog* dialog;
2421
2422   Glib::RefPtr<Gtk::Builder> xml
2423     = Gtk::Builder::create_from_file(get_glade_path() + "/ruinfight-started-dialog.ui");
2424
2425   xml->get_widget("dialog", dialog);
2426   Decorated decorator;
2427   decorator.decorate(dialog);
2428   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2429   dialog->set_transient_for(*window);
2430
2431   decorator.set_title(_("Searching"));
2432
2433   Gtk::Label *label;
2434   xml->get_widget("label", label);
2435   Glib::ustring s = label->get_text();
2436   s = "\n\n";
2437   s += attackers->getFirstHero()->getName() + " encounters some ";
2438   s += defenders->getStrongestArmy()->getName() + "...";
2439   label->set_text(s);
2440
2441   dialog->show_all();
2442   dialog->run();
2443   dialog->hide();
2444   delete dialog;
2445 }
2446 void GameWindow::on_ruinfight_finished(Fight::Result result)
2447 {
2448   Gtk::Dialog* dialog;
2449
2450   Glib::RefPtr<Gtk::Builder> xml
2451     = Gtk::Builder::create_from_file(get_glade_path() + "/ruinfight-finished-dialog.ui");
2452
2453   xml->get_widget("dialog", dialog);
2454   Decorated decorator;
2455   decorator.decorate(dialog);
2456   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2457   dialog->set_transient_for(*window);
2458
2459   if (result == Fight::ATTACKER_WON)
2460     decorator.set_title(_("Hero Victorious"));
2461   else
2462     decorator.set_title(_("Hero Defeated"));
2463
2464   Gtk::Label *label;
2465   xml->get_widget("label", label);
2466   Glib::ustring s = label->get_text();
2467   s = "\n\n";
2468   if (result == Fight::ATTACKER_WON)
2469     s += _("...and is victorious!");
2470   else
2471     s += _("...and is slain by it!");
2472   label->set_text(s);
2473
2474   Gtk::Image *image;
2475   xml->get_widget("image", image);
2476   if (result == Fight::ATTACKER_WON)
2477     image->property_file() = File::getMiscFile("various/ruin_2.png");
2478   else
2479     image->property_file() = File::getMiscFile("various/ruin_1.png");
2480
2481   dialog->show_all();
2482   dialog->run();
2483   dialog->hide();
2484   delete dialog;
2485 }
2486
2487 void GameWindow::on_fight_started(LocationBox box, Fight &fight)
2488 {
2489   FightWindow d(fight);
2490
2491   game->get_bigmap().setFighting(box);
2492   game->get_bigmap().draw(Playerlist::getViewingplayer());
2493   d.set_parent_window(*window);
2494   d.run(&d_quick_fights);
2495   d.hide();
2496   game->get_bigmap().setFighting(LocationBox(Vector<int>(-1,-1)));
2497   game->get_bigmap().draw(Playerlist::getViewingplayer());
2498   if (Playerlist::getActiveplayer()->getType() == Player::HUMAN)
2499     d_quick_fights = false;
2500 }
2501
2502 void GameWindow::on_hero_brings_allies (int numAllies)
2503 {
2504   Gtk::Dialog* dialog;
2505
2506   Glib::RefPtr<Gtk::Builder> xml
2507     = Gtk::Builder::create_from_file(get_glade_path() + "/hero-brings-allies-dialog.ui");
2508
2509   xml->get_widget("dialog", dialog);
2510   Decorated decorator;
2511   decorator.decorate(dialog);
2512   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2513   dialog->set_transient_for(*window);
2514
2515   decorator.set_title(_("Hero brings allies!"));
2516
2517   Gtk::Label *label;
2518   xml->get_widget("label", label);
2519   Glib::ustring s;
2520   s = String::ucompose(
2521                        ngettext("The hero brings %1 ally!",
2522                                 "The hero brings %1 allies!", numAllies), numAllies);
2523   label->set_text(s);
2524
2525   dialog->show_all();
2526   dialog->run();
2527   dialog->hide();
2528   delete dialog;
2529 }
2530
2531 bool GameWindow::on_hero_offers_service(Player *player, HeroProto *hero, City *city, int gold)
2532 {
2533   HeroOfferDialog d(player, hero, city, gold);
2534   d.set_parent_window(*window);
2535   bool retval = d.run();
2536   d.hide();
2537   return retval;
2538 }
2539
2540 bool GameWindow::on_enemy_offers_surrender(int numPlayers)
2541 {
2542   SurrenderDialog d(numPlayers);
2543   d.set_parent_window(*window);
2544   bool retval = d.run();
2545   d.hide();
2546   return retval;
2547 }
2548
2549 void GameWindow::on_surrender_answered (bool accepted)
2550 {
2551   if (accepted)
2552     on_message_requested
2553       (_("You graciously and benevolently accept their offer."));
2554   else
2555     {
2556       SurrenderRefusedDialog d;
2557       d.set_parent_window(*window);
2558       d.run();
2559       d.hide();
2560     }
2561 }
2562
2563 bool GameWindow::on_stack_considers_treachery (Player *me, Stack *stack, 
2564                                                Player *them, Vector<int> pos)
2565 {
2566   Gtk::Dialog* dialog;
2567
2568   Glib::RefPtr<Gtk::Builder> xml
2569     = Gtk::Builder::create_from_file(get_glade_path() + "/treachery-dialog.ui");
2570
2571   xml->get_widget("dialog", dialog);
2572   Decorated decorator;
2573   decorator.decorate(dialog);
2574   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2575   dialog->set_transient_for(*window);
2576   Gtk::Label *label;
2577   xml->get_widget("label", label);
2578   Glib::ustring s;
2579   s = String::ucompose(_("Are you sure you want to attack %1?"), 
2580                        them->getName());
2581   s += "\n";
2582   s += _("Other players may not like this!");
2583   label->set_text(s);
2584   dialog->show_all();
2585   int response = dialog->run();
2586   dialog->hide();
2587   delete dialog;
2588   if (response == Gtk::RESPONSE_DELETE_EVENT)
2589     return false;
2590   else if (response == Gtk::RESPONSE_ACCEPT)
2591     return true;
2592   else
2593     return false;
2594 }
2595
2596
2597 void GameWindow::on_temple_visited(Temple *temple)
2598 {
2599   RuinReportDialog d(temple->getPos());
2600   d.set_parent_window(*window);
2601   d.run();
2602   d.hide();
2603 }
2604
2605 bool GameWindow::on_temple_searched(Hero *hero, Temple *temple, int blessCount)
2606 {
2607   QuestsManager *qm = QuestsManager::getInstance();
2608   Gtk::Dialog* dialog;
2609   bool hasHero = hero != NULL;
2610   bool ask_quest = false;
2611
2612   Glib::RefPtr<Gtk::Builder> xml
2613     = Gtk::Builder::create_from_file(get_glade_path() + "/temple-visit-dialog.ui");
2614
2615   xml->get_widget("dialog", dialog);
2616   Decorated decorator;
2617   decorator.decorate(dialog);
2618   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2619   dialog->set_transient_for(*window);
2620
2621   decorator.set_title(temple->getName());
2622
2623   Gtk::Label *l;
2624   Gtk::Button *close_button;
2625   Gtk::Button *accept_button;
2626   xml->get_widget("label", l);
2627   xml->get_widget("close_button", close_button);
2628   xml->get_widget("accept_button", accept_button);
2629
2630   if (GameScenarioOptions::s_play_with_quests == 
2631       GameParameters::ONE_QUEST_PER_PLAYER)
2632     {
2633       if (qm->getPlayerQuests(Playerlist::getActiveplayer()).size() == 0 &&
2634           hasHero)
2635         ask_quest = true;
2636     }
2637   else if (GameScenarioOptions::s_play_with_quests == GameParameters::ONE_QUEST_PER_HERO)
2638     {
2639       if (hasHero && hero->hasQuest() == false)
2640         ask_quest = true;
2641     }
2642
2643   Glib::ustring s;
2644   if (blessCount > 0)
2645     s += String::ucompose(
2646                           ngettext("%1 army has been blessed!",
2647                                    "%1 armies have been blessed!", blessCount), blessCount);
2648   else
2649     s += _("We have already blessed thee!");
2650
2651   l->set_text(s);
2652   s = l->get_text() + "\n" + _("Seek more blessings in far temples!");
2653   l->set_text(s);
2654   if (ask_quest)
2655     {
2656       s = l->get_text() + "\n\n" + _("Do you seek a quest?");
2657       l->set_text(s);
2658     }
2659
2660   dialog->show_all();
2661
2662   if (ask_quest == false)
2663     {
2664       close_button->hide();
2665       s = _("_Close");
2666       accept_button->set_label(s);
2667     }
2668
2669   int response = dialog->run();
2670   dialog->hide();
2671   delete dialog;
2672
2673   if (ask_quest == false)
2674     response = Gtk::RESPONSE_ACCEPT;
2675
2676   if (response == Gtk::RESPONSE_ACCEPT)         // accepted a quest
2677     return true;
2678   else
2679     return false;
2680 }
2681
2682 void GameWindow::on_quest_assigned(Hero *hero, Quest *quest)
2683 {
2684   QuestAssignedDialog d(hero, quest);
2685   d.set_parent_window(*window);
2686   d.run();
2687   d.hide();
2688 }
2689
2690 static bool
2691 hero_has_quest_here (Stack *s, City *c, bool *pillage, bool *sack, bool *raze, bool *occupy)
2692 {
2693   Player *p = Playerlist::getActiveplayer();
2694   std::vector<Quest*> questlist;
2695   *pillage = false;
2696   *sack = false;
2697   *raze = false;
2698   *occupy = false;
2699
2700   QuestsManager *q_mgr = QuestsManager::getInstance();
2701   questlist = q_mgr->getPlayerQuests(p);
2702   /* loop over all quests */
2703   /* for each quest, check the quest type */
2704   for (std::vector<Quest*>::iterator i = questlist.begin();
2705        i != questlist.end(); ++i)
2706     {
2707       if ((*i) == NULL)
2708         continue;
2709       if ((*i)->isPendingDeletion() == true)
2710         continue;
2711       switch ((*i)->getType())
2712         {
2713         case Quest::CITYSACK:
2714         case Quest::CITYRAZE:
2715         case Quest::CITYOCCUPY:
2716           if ((*i)->getType() == Quest::CITYSACK)
2717             {
2718               if (dynamic_cast<QuestCitySack*>((*i))->getCity() != c)
2719                 continue;
2720             }
2721           else if ((*i)->getType() == Quest::CITYOCCUPY)
2722             {
2723               if (dynamic_cast<QuestCityOccupy*>((*i))->getCity() != c)
2724                 continue;
2725             }
2726           else if ((*i)->getType() == Quest::CITYRAZE)
2727             {
2728               if (dynamic_cast<QuestCityRaze*>((*i))->getCity() != c)
2729                 continue;
2730             }
2731           /* now check if the quest's hero is in our stack */
2732           for (Stack::iterator it = s->begin(); it != s->end(); ++it)
2733             {
2734               if ((*it)->isHero())
2735                 {
2736                   if ((*it)->getId() == (*i)->getHeroId())
2737                     {
2738                       /* hey we found one, set the corresponding boolean */
2739                       if ((*i)->getType() == Quest::CITYSACK)
2740                         *sack = true;
2741                       else if ((*i)->getType() == Quest::CITYRAZE)
2742                         *raze = true;
2743                       else if ((*i)->getType() == Quest::CITYOCCUPY)
2744                         *occupy = true;
2745                     }
2746                 }
2747             }
2748           break;
2749         case Quest::PILLAGEGOLD:
2750           *pillage = true;
2751           *sack = true;
2752           break;
2753         }
2754     }
2755   if ((*raze) || (*sack) || (*occupy))
2756     return true;
2757   else
2758     return false;
2759 }
2760
2761 CityDefeatedAction GameWindow::on_city_defeated(City *city, int gold)
2762 {
2763   CityDefeatedAction retval = CITY_DEFEATED_OCCUPY;
2764   Gtk::Button *raze_button;
2765   Gtk::Dialog* dialog;
2766   if (gold)
2767     on_city_looted (city, gold);
2768   Glib::RefPtr<Gtk::Builder> xml
2769     = Gtk::Builder::create_from_file(get_glade_path() + "/city-defeated-dialog.ui");
2770
2771   xml->get_widget("dialog", dialog);
2772   Decorated decorator;
2773   decorator.decorate(dialog);
2774   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2775   dialog->set_transient_for(*window);
2776
2777   Gtk::Image *image;
2778   xml->get_widget("city_image", image);
2779   image->property_file() = File::getMiscFile("various/city_occupied.png");
2780   image->show();
2781
2782   Gtk::Label *label;
2783   xml->get_widget("label", label);
2784   Gtk::Requisition req = image->size_request();
2785   label->set_size_request(req.width);
2786
2787   Glib::ustring name;
2788   Player *p = Playerlist::getActiveplayer();
2789   Army *h = p->getActivestack()->getFirstHero();
2790   if (h)
2791     name = h->getName();
2792   else
2793     name = p->getName(false);
2794
2795   Glib::ustring s;
2796   switch (rand() % 4)
2797     {
2798     case 0: s = _("%1, you have triumphed in the battle of %2."); break;
2799     case 1: s = _("%1, you have claimed victory in the battle of %2."); break;
2800     case 2: s = _("%1, you have shown no mercy in the battle of %2."); break;
2801     case 3: s = _("%1, you have slain the foe in the battle of %2."); break;
2802     }
2803
2804   s = String::ucompose(s, name, city->getName());
2805   s += "\n\n";
2806   s += label->get_text();
2807   label->set_text(s);
2808
2809   xml->get_widget("raze_button", raze_button);
2810
2811   raze_button->set_sensitive
2812     (GameScenarioOptions::s_razing_cities == GameParameters::ON_CAPTURE || 
2813      GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS);
2814
2815   if (h) /* if there was a hero in the stack */
2816     {
2817       bool pillage, sack, raze, occupy;
2818       if (hero_has_quest_here (p->getActivestack(), city, 
2819                                &pillage, &sack, &raze, &occupy))
2820         {
2821           Gtk::Button *button;
2822           if (pillage)
2823             {
2824               xml->get_widget("pillage_button", button);
2825                           button->set_focus_on_click(true);
2826 //              button->set_can_focus(true);
2827 //              button->set_can_default(true);
2828               button->grab_default();
2829             }
2830           if (sack)
2831             {
2832               xml->get_widget("sack_button", button);
2833                           button->set_focus_on_click(true);
2834 //              button->set_can_focus(true);
2835 //              button->set_can_default(true);
2836               button->grab_default();
2837             }
2838           if (raze)
2839             {
2840               xml->get_widget("raze_button", button);
2841                           button->set_focus_on_click(true);
2842 //              button->set_can_focus(true);
2843 //              button->set_can_default(true);
2844               button->grab_default();
2845             }
2846           if (occupy)
2847             {
2848               xml->get_widget("occupy_button", button);
2849                           button->set_focus_on_click(true);
2850 //              button->set_can_focus(true);
2851 //              button->set_can_default(true);
2852               button->grab_default();
2853             }
2854         }
2855     }
2856
2857   if (city->getNoOfProductionBases() <= 0) {
2858     Gtk::Button *b;
2859     xml->get_widget("pillage_button", b);
2860     b->hide();
2861   }
2862
2863   if (city->getNoOfProductionBases() <= 1) {
2864     Gtk::Button *b;
2865     xml->get_widget("sack_button", b);
2866     b->hide();
2867   }
2868
2869   dialog->show();
2870
2871   while (1)
2872     {
2873       int response = dialog->run();
2874       switch (response) 
2875         {
2876         case 1: retval = CITY_DEFEATED_OCCUPY; break;
2877         case 2: 
2878                 {
2879                   bool razed = CityWindow::on_raze_clicked(city, dialog);
2880                   if (razed == false)
2881                     continue;
2882                   retval = CITY_DEFEATED_RAZE;
2883                   break;
2884                 }
2885         case 3: retval = CITY_DEFEATED_PILLAGE; break;
2886         case 4: retval = CITY_DEFEATED_SACK; break;
2887         default: break;
2888         }
2889       if (retval)
2890         break;
2891     }
2892   dialog->hide();
2893   delete dialog;
2894   return retval;
2895 }
2896
2897 void GameWindow::on_city_looted (City *city, int gold)
2898 {
2899   Gtk::Dialog* dialog;
2900
2901   Glib::RefPtr<Gtk::Builder> xml
2902     = Gtk::Builder::create_from_file(get_glade_path() + "/city-looted-dialog.ui");
2903
2904   xml->get_widget("dialog", dialog);
2905   Decorated decorator;
2906   decorator.decorate(dialog);
2907   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2908   dialog->set_transient_for(*window);
2909
2910   decorator.set_title(String::ucompose(_("%1 Looted"), city->getName()));
2911
2912   Gtk::Label *label;
2913   xml->get_widget("label", label);
2914   Glib::ustring s = label->get_text();
2915   s += "\n\n";
2916   s += String::ucompose(
2917                         ngettext("Your armies loot %1 gold piece.",
2918                                  "Your armies loot %1 gold pieces.", gold), gold);
2919   label->set_text(s);
2920
2921   dialog->show_all();
2922   dialog->run();
2923   dialog->hide();
2924   delete dialog;
2925 }
2926 void GameWindow::on_city_pillaged(City *city, int gold, int pillaged_army_type)
2927 {
2928   GraphicsCache *gc = GraphicsCache::getInstance();
2929   Gtk::Dialog* dialog;
2930   Player *player = city->getOwner();
2931   unsigned int as = player->getArmyset();
2932
2933   Glib::RefPtr<Gtk::Builder> xml
2934     = Gtk::Builder::create_from_file(get_glade_path() + "/city-pillaged-dialog.ui");
2935
2936   Gtk::Image *pillaged_army_type_image;
2937   xml->get_widget("dialog", dialog);
2938   Decorated decorator;
2939   decorator.decorate(dialog);
2940   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2941   dialog->set_transient_for(*window);
2942
2943   decorator.set_title(String::ucompose(_("Pillaged %1"), city->getName()));
2944
2945   Gtk::Label *pillaged_army_type_cost_label;
2946   xml->get_widget("pillaged_army_type_cost_label", pillaged_army_type_cost_label);
2947   xml->get_widget("pillaged_army_type_image", pillaged_army_type_image);
2948   if (gold == 0)
2949     {
2950       Glib::RefPtr<Gdk::Pixbuf> s
2951         = GraphicsCache::getInstance()->getArmyPic(as, 0, player, NULL)->to_pixbuf();
2952       Glib::RefPtr<Gdk::Pixbuf> empty_pic
2953         = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, s->get_width(), s->get_height());
2954       empty_pic->fill(0x00000000);
2955       pillaged_army_type_image->set(empty_pic);
2956       pillaged_army_type_cost_label->set_text("");
2957     }
2958   else
2959     {
2960       Glib::RefPtr<Gdk::Pixbuf> pic;
2961       pic = gc->getArmyPic(as, pillaged_army_type, player, NULL)->to_pixbuf();
2962       pillaged_army_type_image->property_pixbuf() = pic;
2963       pillaged_army_type_cost_label->set_text(String::ucompose("%1 gp", gold));
2964     }
2965   Gtk::Label *label;
2966   xml->get_widget("label", label);
2967   Glib::ustring s = label->get_text();
2968   s += "\n\n";
2969   s += String::ucompose(
2970                         ngettext("The loot is worth %1 gold piece.",
2971                                  "The loot is worth %1 gold pieces.",
2972                                  gold), gold);
2973   label->set_text(s);
2974
2975   dialog->show_all();
2976   dialog->run();
2977   dialog->hide();
2978   delete dialog;
2979 }
2980
2981 void GameWindow::on_city_sacked(City *city, int gold, std::list<guint32> sacked_types)
2982 {
2983   GraphicsCache *gc = GraphicsCache::getInstance();
2984   Player *player = city->getOwner();
2985   unsigned int as = player->getArmyset();
2986   Gtk::Dialog* dialog;
2987
2988   Glib::RefPtr<Gtk::Builder> xml
2989     = Gtk::Builder::create_from_file(get_glade_path() + "/city-sacked-dialog.ui");
2990
2991   xml->get_widget("dialog", dialog);
2992   Decorated decorator;
2993   decorator.decorate(dialog);
2994   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2995   dialog->set_transient_for(*window);
2996
2997   decorator.set_title(String::ucompose(_("Sacked %1"), city->getName()));
2998
2999   Gtk::Label *label;
3000   xml->get_widget("label", label);
3001   Glib::ustring s = label->get_text();
3002   s = String::ucompose("The city of %1 is sacked\nfor %2 gold!\n\n",
3003                        city->getName(), gold);
3004   s += String::ucompose(
3005                         ngettext("Ability to produce %1 unit has been lost",
3006                                  "Ability to produce %1 units has been lost",
3007                                  sacked_types.size()), sacked_types.size());
3008   s += "\nand only 1 unit remains";
3009   label->set_text(s);
3010
3011   Gtk::Image *sacked_army_1_image;
3012   Gtk::Image *sacked_army_2_image;
3013   Gtk::Image *sacked_army_3_image;
3014   Gtk::Label *sacked_army_1_cost_label;
3015   Gtk::Label *sacked_army_2_cost_label;
3016   Gtk::Label *sacked_army_3_cost_label;
3017   xml->get_widget("sacked_army_1_image", sacked_army_1_image);
3018   xml->get_widget("sacked_army_2_image", sacked_army_2_image);
3019   xml->get_widget("sacked_army_3_image", sacked_army_3_image);
3020   xml->get_widget("sacked_army_1_cost_label", sacked_army_1_cost_label);
3021   xml->get_widget("sacked_army_2_cost_label", sacked_army_2_cost_label);
3022   xml->get_widget("sacked_army_3_cost_label", sacked_army_3_cost_label);
3023
3024   Glib::RefPtr<Gdk::Pixbuf> pic;
3025   Glib::RefPtr<Gdk::Pixbuf> surf
3026     = GraphicsCache::getInstance()->getArmyPic(as, 0, player, NULL)->to_pixbuf();
3027   Glib::RefPtr<Gdk::Pixbuf> empty_pic
3028     = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, surf->get_width(), surf->get_height());
3029   empty_pic->fill(0x00000000);
3030   int i = 0;
3031   Gtk::Label *sack_label = NULL;
3032   Gtk::Image *sack_image = NULL;
3033   for (std::list<guint32>::iterator it = sacked_types.begin(); it != sacked_types.end(); it++)
3034     {
3035       switch (i)
3036         {
3037         case 0:
3038           sack_label = sacked_army_1_cost_label;
3039           sack_image = sacked_army_1_image;
3040           break;
3041         case 1:
3042           sack_label = sacked_army_2_cost_label;
3043           sack_image = sacked_army_2_image;
3044           break;
3045         case 2:
3046           sack_label = sacked_army_3_cost_label;
3047           sack_image = sacked_army_3_image;
3048           break;
3049         }
3050       pic = gc->getArmyPic(as, *it, player, NULL)->to_pixbuf();
3051       sack_image->property_pixbuf() = pic;
3052       const ArmyProto *a = 
3053         Armysetlist::getInstance()->getArmy (player->getArmyset(), *it);
3054       s = String::ucompose("%1 gp", a->getNewProductionCost() / 2);
3055       sack_label->set_text(s);
3056       i++;
3057     }
3058   for (i = sacked_types.size(); i < 3; i++)
3059     {
3060       switch (i)
3061         {
3062         case 0:
3063           sack_label = sacked_army_1_cost_label;
3064           sack_image = sacked_army_1_image;
3065           break;
3066         case 1:
3067           sack_label = sacked_army_2_cost_label;
3068           sack_image = sacked_army_2_image;
3069           break;
3070         case 2:
3071           sack_label = sacked_army_3_cost_label;
3072           sack_image = sacked_army_3_image;
3073           break;
3074         }
3075       sack_image->set(empty_pic);
3076       sack_label->set_text("");
3077     }
3078   dialog->show_all();
3079   dialog->run();
3080   dialog->hide();
3081   delete dialog;
3082 }
3083
3084 void GameWindow::on_city_razed (City *city)
3085 {
3086   Gtk::Dialog* dialog;
3087
3088   Glib::RefPtr<Gtk::Builder> xml
3089     = Gtk::Builder::create_from_file(get_glade_path() + "/city-razed-dialog.ui");
3090
3091   xml->get_widget("dialog", dialog);
3092   Decorated decorator;
3093   decorator.decorate(dialog);
3094   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3095   dialog->set_transient_for(*window);
3096
3097   decorator.set_title(String::ucompose(_("Razed %1"), city->getName()));
3098
3099   Gtk::Label *label;
3100   xml->get_widget("label", label);
3101   Glib::ustring s;
3102   s = String::ucompose(_("The city of %1 is in ruins!"), city->getName());
3103   label->set_text(s);
3104
3105   dialog->show_all();
3106   dialog->run();
3107   dialog->hide();
3108   delete dialog;
3109 }
3110
3111 void GameWindow::on_city_visited(City *city)
3112 {
3113   CityWindow d(city, 
3114                GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS,
3115                GameScenarioOptions::s_see_opponents_production);
3116
3117   d.set_parent_window(*window);
3118   d.run();
3119   d.hide();
3120 }
3121
3122 void GameWindow::on_ruin_visited(Ruin *ruin)
3123 {
3124   RuinReportDialog d(ruin->getPos());
3125   d.set_parent_window(*window);
3126   d.run();
3127   d.hide();
3128 }
3129
3130 void GameWindow::show_shield_turn() //show turn indicator
3131 {
3132   Playerlist* pl = Playerlist::getInstance();
3133   GraphicsCache *gc = GraphicsCache::getInstance();
3134   unsigned int c = 0;
3135   for (Playerlist::iterator i = pl->begin(); i != pl->end(); ++i)
3136     {
3137       if (pl->getNeutral() == (*i))
3138         continue;
3139       if ((*i)->isDead())
3140         {
3141           shield_image[c]->clear();
3142           turn_hbox->remove(dynamic_cast<Gtk::Widget&>(*shield_image[c]));
3143           turn_hbox->resize_children();
3144           continue;
3145         }
3146       if (*i == pl->getActiveplayer())
3147         shield_image[c]->property_pixbuf()=gc->getShieldPic(1,(*i))->to_pixbuf();
3148       else
3149         shield_image[c]->property_pixbuf()=gc->getShieldPic(0,(*i))->to_pixbuf();
3150       shield_image[c]->property_tooltip_text() = (*i)->getName();
3151       c++;
3152     }
3153   for (unsigned int i = c; i < MAX_PLAYERS; i++)
3154     shield_image[i]->clear();
3155 }
3156
3157 void GameWindow::on_remote_next_player_turn()
3158 {
3159   on_stack_info_changed(NULL);
3160   while (g_main_context_iteration(NULL, FALSE)); //doEvents
3161
3162   d_quick_fights = false;
3163   show_shield_turn();
3164   turn_label->set_markup(String::ucompose("Turn %1", 
3165                                           GameScenarioOptions::s_round));
3166 }
3167
3168 void GameWindow::on_next_player_turn(Player *player, unsigned int turn_number)
3169 {
3170   Gtk::Dialog* dialog;
3171
3172   on_stack_info_changed(NULL);
3173   while (g_main_context_iteration(NULL, FALSE)); //doEvents
3174
3175   d_quick_fights = false;
3176   show_shield_turn();
3177   if (player->getType() != Player::HUMAN)
3178     return;
3179       
3180   if (Configuration::s_showNextPlayer == true)
3181     {
3182       Glib::RefPtr<Gtk::Builder> xml
3183         = Gtk::Builder::create_from_file(get_glade_path() + 
3184                                     "/next-player-turn-dialog.ui");
3185
3186       xml->get_widget("dialog", dialog);
3187       dialog->set_transient_for(*window);
3188
3189       Decorated decorator;
3190       decorator.decorate(dialog);
3191       decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3192       Gtk::Image *image;
3193       xml->get_widget("image", image);
3194       image->property_file() = File::getMiscFile("various/ship.png");
3195
3196       Gtk::Label *label;
3197       xml->get_widget("label", label);
3198       Glib::ustring s = String::ucompose(_("%1\nTurn %2"), player->getName(), 
3199                                          turn_number);
3200       label->set_text(s);
3201
3202       dialog->show_all();
3203       dialog->run();
3204       dialog->hide();
3205       delete dialog;
3206       show();
3207     }
3208
3209 }
3210
3211 void GameWindow::on_medal_awarded_to_army(Army *army, int medaltype)
3212 {
3213   GraphicsCache *gc = GraphicsCache::getInstance();
3214   Gtk::Dialog* dialog;
3215
3216   Glib::RefPtr<Gtk::Builder> xml
3217     = Gtk::Builder::create_from_file(get_glade_path() + "/medal-awarded-dialog.ui");
3218
3219   xml->get_widget("dialog", dialog);
3220   Decorated decorator;
3221   decorator.decorate(dialog);
3222   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3223   dialog->set_transient_for(*window);
3224
3225   Gtk::Image *image;
3226   xml->get_widget("image", image);
3227   Player *active = Playerlist::getInstance()->getActiveplayer();
3228   image->property_pixbuf() = 
3229     gc->getArmyPic(active->getArmyset(), army->getTypeId(), active, 
3230                    army->getMedalBonuses())->to_pixbuf();
3231   Gtk::Image *medal_image;
3232   xml->get_widget("medal_image", medal_image);
3233   medal_image->property_pixbuf() = 
3234     gc->getMedalPic(true, medaltype)->to_pixbuf();
3235
3236   Gtk::Label *label;
3237   xml->get_widget("label", label);
3238   Glib::ustring s;
3239   if (medaltype == 0)
3240     s += String::ucompose(_("Your unit of %1 is awarded the avenger's medal of valour!"), army->getName());
3241   else if (medaltype == 1)
3242     s += String::ucompose(_("Your unit of %1 is awarded the defender's medal of bravery!"), army->getName());
3243   else if (medaltype == 2)
3244     s += String::ucompose(_("Your unit of %1 is awarded the veteran's medal!"), army->getName());
3245   else
3246     s += String::ucompose(_("Your unit of %1 is awarded a medal!"), army->getName());
3247   label->set_text(s);
3248
3249   dialog->show_all();
3250   dialog->run();
3251   dialog->hide();
3252   delete dialog;
3253 }
3254
3255 Army::Stat GameWindow::on_hero_gains_level(Hero *hero)
3256 {
3257   ArmyGainsLevelDialog d(hero, GameScenario::s_hidden_map);
3258
3259   d.set_parent_window(*window);
3260   d.run();
3261   d.hide();
3262
3263   return d.get_selected_stat();
3264 }
3265
3266 void GameWindow::on_game_loaded(Player *player)
3267 {
3268   Gtk::Dialog* dialog;
3269
3270   Glib::RefPtr<Gtk::Builder> xml
3271     = Gtk::Builder::create_from_file(get_glade_path() + "/game-loaded-dialog.ui");
3272
3273   xml->get_widget("dialog", dialog);
3274   Decorated decorator;
3275   decorator.decorate(dialog);
3276   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3277   dialog->set_transient_for(*window);
3278
3279   Gtk::Label *label;
3280   xml->get_widget("label", label);
3281   Glib::ustring s;
3282   s += String::ucompose(_("%1, your turn continues."), player->getName());
3283   label->set_text(s);
3284
3285   dialog->show_all();
3286   dialog->run();
3287   dialog->hide();
3288   delete dialog;
3289 }
3290
3291 void GameWindow::on_quest_completed(Quest *quest, Reward *reward)
3292 {
3293   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3294     return;
3295   QuestCompletedDialog d(quest, reward);
3296   d.set_parent_window(*window);
3297   d.run();
3298   d.hide();
3299 }
3300
3301 void GameWindow::on_quest_expired(Quest *quest)
3302 {
3303   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3304     return;
3305   Gtk::Dialog* dialog;
3306
3307   Glib::RefPtr<Gtk::Builder> xml
3308     = Gtk::Builder::create_from_file(get_glade_path() + "/quest-expired-dialog.ui");
3309
3310   xml->get_widget("dialog", dialog);
3311   Decorated decorator;
3312   decorator.decorate(dialog);
3313   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3314   dialog->set_transient_for(*window);
3315
3316   Gtk::Label *label;
3317   xml->get_widget("label", label);
3318   Glib::ustring s;
3319   s += String::ucompose(_("%1 did not complete the quest."),
3320                         quest->getHeroName());
3321   s += "\n\n";
3322
3323   // add messages from the quest
3324   std::queue<std::string> msgs;
3325   quest->getExpiredMsg(msgs);
3326   while (!msgs.empty())
3327     {
3328       s += msgs.front();
3329       msgs.pop();
3330       if (!msgs.empty())
3331         s += "\n\n";
3332     }
3333
3334   label->set_text(s);
3335
3336   dialog->show_all();
3337   dialog->run();
3338   dialog->hide();
3339   delete dialog;
3340 }
3341
3342 void GameWindow::on_inspect_activated ()
3343 {
3344   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3345     return;
3346   if (Playerlist::getActiveplayer()->getHeroes().size() == 0)
3347     return;
3348   Hero *hero = NULL;
3349   Vector<int> pos = Vector<int>(-1,-1);
3350   if (currently_selected_stack != NULL)
3351     {
3352       hero = dynamic_cast<Hero*>(currently_selected_stack->getFirstHero());
3353       pos = currently_selected_stack->getPos();
3354     }
3355     
3356   HeroDialog d(hero, pos);
3357   d.set_parent_window(*window);
3358   d.run();
3359   d.hide();
3360 }
3361 void GameWindow::on_plant_standard_activated ()
3362 {
3363   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3364     return;
3365   Playerlist::getActiveplayer()->heroPlantStandard(NULL);
3366 }
3367     
3368 void GameWindow::on_stack_moves(Stack *stack, Vector<int> pos)
3369 {
3370   if (GameMap::getEnemyCity(pos))
3371     return;
3372   if (GameMap::getEnemyStack(pos))
3373     return;
3374   //assert (stack == Playerlist::getInstance()->getActiveplayer()->getActivestack());
3375   Player *active = Playerlist::getInstance()->getActiveplayer();
3376   Stack *old = active->getActivestack();
3377   active->setActivestack(stack);
3378   game->get_smallmap().center_view_on_tile (pos, true);
3379   // sleep for a specified amount of time
3380   int step = TIMER_BIGMAP_SELECTOR * 1000;
3381   for (int i = 0; i < Configuration::s_displaySpeedDelay; i += step)
3382     {
3383       game->get_bigmap().draw(Playerlist::getViewingplayer());
3384       while (g_main_context_iteration(NULL, FALSE)); //doEvents
3385       Glib::usleep(step);
3386     }
3387   active->setActivestack(old);
3388 }
3389
3390 void GameWindow::on_advice_asked(float percent)
3391 {
3392   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3393     return;
3394   //we asked for advice on a fight, and we're being told that we 
3395   //have a PERCENT chance of winning the fight
3396   Gtk::Dialog* dialog;
3397
3398   Glib::RefPtr<Gtk::Builder> xml
3399     = Gtk::Builder::create_from_file(get_glade_path() + "/military-advisor-dialog.ui");
3400
3401   xml->get_widget("dialog", dialog);
3402   Decorated decorator;
3403   decorator.decorate(dialog);
3404   decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3405   dialog->set_transient_for(*window);
3406
3407   decorator.set_title(_("Advisor!"));
3408
3409   Gtk::Label *label;
3410   xml->get_widget("label", label);
3411   Glib::ustring s;
3412
3413   int num = rand() % 5;
3414   if (num == 0)
3415     s += _("My Good Lord!");
3416   else if (num == 1)
3417     s += _("Great and Worthy Lord!");
3418   else if (num == 2)
3419     s += _("O Champion of Justice!");
3420   else if (num == 3)
3421     s += _("O Mighty Leader!");
3422   else if (num == 4)
3423     s += _("O Great Warlord!");
3424   s += "\n";
3425
3426   num = rand() % 7;
3427   num = rand() % 7;
3428   if (percent >= 90.0)
3429     {
3430       if (num == 0)
3431         s += _("This battle will surely be as simple as butchering sleeping cattle!");
3432       else if (num == 1)
3433         s += _("A battle here would be as simple as butchering sleeping cattle!");
3434       else if (num == 2)
3435         s += _("I believe this battle will surely be as simple as butchering sleeping cattle!");
3436       else if (num == 3)
3437         s += _("This battle would be as simple as butchering sleeping cattle!");
3438       else if (num == 4)
3439         s += _("A battle here would be as simple as butchering sleeping cattle!");
3440       else if (num == 5)
3441         s += _("I believe this battle will be as simple as butchering sleeping cattle!");
3442       else if (num == 6)
3443         s += _("This battle shall be as simple as butchering sleeping cattle!");
3444     }
3445   else if (percent >= 80.0)
3446     {
3447       if (num == 0)
3448         s += _("This battle will surely be an easy victory!  We cannot lose!");
3449       else if (num == 1)
3450         s += _("A battle here would be an easy victory!  We cannot lose!");
3451       else if (num == 2)
3452         s += _("I believe this battle will surely be an easy victory!  We cannot lose!");
3453       else if (num == 3)
3454         s += _("This battle would be an easy victory!  We cannot lose!");
3455       else if (num == 4)
3456         s += _("A battle here would be an easy victory!  We cannot lose!");
3457       else if (num == 5)
3458         s += _("I believe this battle will be an easy victory!  We cannot lose!");
3459       else if (num == 6)
3460         s += _("This battle shall be an easy victory!  We cannot lose!");
3461     }
3462   else if (percent >= 70.0)
3463     {
3464       if (num == 0)
3465         s += _("This battle will surely be a comfortable victory");
3466       else if (num == 1)
3467         s += _("A battle here would be a comfortable victory");
3468       else if (num == 2)
3469         s += _("I believe this battle will surely be a comfortable victory");
3470       else if (num == 3)
3471         s += _("This battle would be a comfortable victory");
3472       else if (num == 4)
3473         s += _("A battle here would be a comfortable victory");
3474       else if (num == 5)
3475         s += _("I believe this battle will be a comfortable victory");
3476       else if (num == 6)
3477         s += _("This battle shall be a comfortable victory");
3478     }
3479   else if (percent >= 60.0)
3480     {
3481       if (num == 0)
3482         s += _("This battle will surely be a hard fought victory! But we shall win!");
3483       else if (num == 1)
3484         s += _("A battle here would be a hard fought victory! But we shall win!");
3485       else if (num == 2)
3486         s += _("I believe this battle will surely be a hard fought victory! But we shall win!");
3487       else if (num == 3)
3488         s += _("This battle would be a hard fought victory! But we shall win!");
3489       else if (num == 4)
3490         s += _("A battle here would be a hard fought victory! But we shall win!");
3491       else if (num == 5)
3492         s += _("I believe this battle will be a hard fought victory! But we shall win!");
3493       else if (num == 6)
3494         s += _("This battle shall be a hard fought victory! But we shall win!");
3495     }
3496   else if (percent >= 50.0)
3497     {
3498       if (num == 0)
3499         s += _("This battle will surely be very evenly matched!");
3500       else if (num == 1)
3501         s += _("A battle here would be very evenly matched!");
3502       else if (num == 2)
3503         s += _("I believe this battle will surely be very evenly matched!");
3504       else if (num == 3)
3505         s += _("This battle would be very evenly matched!");
3506       else if (num == 4)
3507         s += _("A battle here would be very evenly matched!");
3508       else if (num == 5)
3509         s += _("I believe this battle will be very evenly matched!");
3510       else if (num == 6)
3511         s += _("This battle shall be very evenly matched!");
3512     }
3513   else if (percent >= 40.0)
3514     {
3515       if (num == 0)
3516         s += _("This battle will surely be difficult but not impossible to win!");
3517       else if (num == 1)
3518         s += _("A battle here would be difficult but not impossible to win!");
3519       else if (num == 2)
3520         s += _("I believe this battle will surely be difficult but not impossible to win!");
3521       else if (num == 3)
3522         s += _("This battle would be difficult but not impossible to win!");
3523       else if (num == 4)
3524         s += _("A battle here would be difficult but not impossible to win!");
3525       else if (num == 5)
3526         s += _("I believe this battle will be difficult but not impossible to win!");
3527       else if (num == 6)
3528         s += _("This battle shall be difficult but not impossible to win!");
3529     }
3530   else if (percent >= 30.0)
3531     {
3532       if (num == 0)
3533         s += _("This battle will surely be a brave choice! I leave it to thee!");
3534       else if (num == 1)
3535         s += _("A battle here would be a brave choice! I leave it to thee!");
3536       else if (num == 2)
3537         s += _("I believe this battle will surely be a brave choice! I leave it to thee!");
3538       else if (num == 3)
3539         s += _("This battle would be a brave choice! I leave it to thee!");
3540       else if (num == 4)
3541         s += _("A battle here would be a brave choice! I leave it to thee!");
3542       else if (num == 5)
3543         s += _("I believe this battle will be a brave choice! I leave it to thee!");
3544       else if (num == 6)
3545         s += _("This battle shall be a brave choice! I leave it to thee!");
3546     }
3547   else if (percent >= 20.0)
3548     {
3549       if (num == 0)
3550         s += _("This battle will surely be a foolish decision!");
3551       else if (num == 1)
3552         s += _("A battle here would be a foolish decision!");
3553       else if (num == 2)
3554         s += _("I believe this battle will surely be a foolish decision!");
3555       else if (num == 3)
3556         s += _("This battle would be a foolish decision!");
3557       else if (num == 4)
3558         s += _("A battle here would be a foolish decision!");
3559       else if (num == 5)
3560         s += _("I believe this battle will be a foolish decision!");
3561       else if (num == 6)
3562         s += _("This battle shall be a foolish decision!");
3563     }
3564   else if (percent >= 10.0)
3565     {
3566       if (num == 0)
3567         s += _("This battle will surely be sheerest folly!  Thou shouldst not attack!");
3568       else if (num == 1)
3569         s += _("A battle here would be sheerest folly!  Thou shouldst not attack!");
3570       else if (num == 2)
3571         s += _("I believe this battle will surely be sheerest folly!  Thou shouldst not attack!");
3572       else if (num == 3)
3573         s += _("This battle would be sheerest folly!  Thou shouldst not attack!");
3574       else if (num == 4)
3575         s += _("A battle here would be sheerest folly!  Thou shouldst not attack!");
3576       else if (num == 5)
3577         s += _("I believe this battle will be sheerest folly!  Thou shouldst not attack!");
3578       else if (num == 6)
3579         s += _("This battle shall be sheerest folly!  Thou shouldst not attack!");
3580     }
3581   else
3582     {
3583       if (num == 0)
3584         s += _("This battle will surely be complete and utter suicide!");
3585       else if (num == 1)
3586         s += _("A battle here would be complete and utter suicide!");
3587       else if (num == 2)
3588         s += _("I believe this battle will surely be complete and utter suicide!");
3589       else if (num == 3)
3590         s += _("This battle would be complete and utter suicide!");
3591       else if (num == 4)
3592         s += _("A battle here would be complete and utter suicide!");
3593       else if (num == 5)
3594         s += _("I believe this battle will be complete and utter suicide!");
3595       else if (num == 6)
3596         s += _("This battle shall be complete and utter suicide!");
3597     }
3598   label->set_text(s);
3599
3600   dialog->show_all();
3601   dialog->run();
3602   dialog->hide();
3603   delete dialog;
3604   return;
3605 }
3606
3607 void GameWindow::on_show_lobby_activated()
3608 {
3609   show_lobby.emit();
3610 }
3611
3612 //taken from go-file.c of gnucash 2.0.4
3613 static char *
3614 check_program (char const *prog)
3615 {
3616   if (NULL == prog)
3617     return NULL;
3618   if (g_path_is_absolute (prog)) {
3619     if (!g_file_test (prog, G_FILE_TEST_IS_EXECUTABLE))
3620       return NULL;
3621   } else if (!g_find_program_in_path (prog))
3622     return NULL;
3623   return g_strdup (prog);
3624 }
3625
3626 //taken from go-file.c of gnucash 2.0.4
3627 GError *
3628 go_url_show (gchar const *url)
3629 {
3630   GError *err = NULL;
3631   char *browser = NULL;
3632   char *clean_url = NULL;
3633
3634   /* 1) Check BROWSER env var */
3635   browser = check_program (getenv ("BROWSER"));
3636
3637   if (browser == NULL) {
3638     static char const * const browsers[] = {
3639       "sensible-browser",       /* debian */
3640       "htmlview", /* fedora */
3641       "firefox",
3642       "epiphany",
3643       "mozilla-firebird",
3644       "mozilla",
3645       "netscape",
3646       "konqueror",
3647       "xterm -e w3m",
3648       "xterm -e lynx",
3649       "xterm -e links"
3650     };
3651     unsigned i;
3652     for (i = 0 ; i < G_N_ELEMENTS (browsers) ; i++)
3653       if (NULL != (browser = check_program (browsers[i])))
3654         break;
3655   }
3656
3657   if (browser != NULL) {
3658     gint    argc;
3659     gchar **argv = NULL;
3660     char   *cmd_line = g_strconcat (browser, " %1", NULL);
3661
3662     if (g_shell_parse_argv (cmd_line, &argc, &argv, &err)) {
3663       /* check for '%1' in an argument and substitute the url
3664        *                         * otherwise append it */
3665       gint i;
3666       char *tmp;
3667
3668       for (i = 1 ; i < argc ; i++)
3669         if (NULL != (tmp = strstr (argv[i], "%1"))) {
3670           *tmp = '\0';
3671           tmp = g_strconcat (argv[i],
3672                              (clean_url != NULL) ? (char const *)clean_url : url,
3673                              tmp+2, NULL);
3674           g_free (argv[i]);
3675           argv[i] = tmp;
3676           break;
3677         }
3678
3679       /* there was actually a %1, drop the one we added */
3680       if (i != argc-1) {
3681         g_free (argv[argc-1]);
3682         argv[argc-1] = NULL;
3683       }
3684       g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
3685                      NULL, NULL, NULL, &err);
3686       g_strfreev (argv);
3687     }
3688     g_free (cmd_line);
3689   }
3690   g_free (browser);
3691   g_free (clean_url);
3692   return err;
3693 }
3694
3695 void GameWindow::on_online_help_activated()
3696 {
3697   go_url_show ("http://www.nongnu.org/lordsawar/manual/" PACKAGE_VERSION "/lordsawar.html");
3698   return;
3699 }
3700
3701 void GameWindow::on_player_replaced(Player *p)
3702 {
3703   game->addPlayer(p);
3704 }
3705
3706 void GameWindow::on_grid_toggled()
3707 {
3708   game->get_bigmap().toggle_grid();
3709 }
3710
3711 void GameWindow::give_some_cheese(Player *winner)
3712 {
3713   game->endOfGameRoaming(winner);
3714   end_turn_button->set_sensitive(false);
3715   end_turn_menuitem->set_sensitive(false);
3716   save_game_menuitem->set_sensitive(false);
3717   save_game_as_menuitem->set_sensitive(false);
3718   Playerlist::getActiveplayer()->clearFogMap();
3719   show_shield_turn();
3720   game->redraw();
3721   on_city_history_activated();
3722 }
3723
3724 void GameWindow::on_commentator_comments(std::string comment)
3725 {
3726   TimedMessageDialog dialog (*window, comment, 0);
3727   dialog.set_title(_("The Warlord Says..."));
3728     
3729   std::vector<PixMask* > buttons;
3730   buttons = disassemble_row(File::getMiscFile("various/buttons.png"), 11);
3731   PixMask::scale(buttons[0], 60, 60);
3732   dialog.set_image(buttons[0]->to_pixbuf());
3733   dialog.run();
3734   dialog.hide();
3735 }
3736       
3737 void GameWindow::on_abbreviated_fight_started(LocationBox box)
3738 {
3739   game->get_bigmap().setFighting(box);
3740   game->get_bigmap().draw(Playerlist::getViewingplayer());
3741   while (g_main_context_iteration(NULL, FALSE)); //doEvents
3742   Glib::usleep(TIMER_BIGMAP_SELECTOR * 1000);
3743   game->get_bigmap().setFighting(LocationBox(Vector<int>(-1,-1)));
3744   game->get_bigmap().draw(Playerlist::getViewingplayer());
3745 }