fixed segfault that could happen when changing video modes (CVS internal)

This commit is contained in:
Dave White 2004-05-06 23:44:01 +00:00
parent 06f0389ff4
commit 38992ed5bd
18 changed files with 197 additions and 60 deletions

View file

@ -328,7 +328,7 @@ height=600
[/unit_xp]
[unit_weapons]
font_size=12
rect=900,452,1020,680
rect=900,452,1020,620
xanchor=right
yanchor=fixed
[/unit_weapons]

View file

@ -1307,8 +1307,7 @@ std::string config::interpolate_variables_into_string(const std::string& str, co
void config::clear()
{
for(std::map<std::string,std::vector<config*> >::iterator i =
children.begin(); i != children.end(); ++i) {
for(std::map<std::string,std::vector<config*> >::iterator i = children.begin(); i != children.end(); ++i) {
std::vector<config*>& v = i->second;
for(std::vector<config*>::iterator j = v.begin(); j != v.end(); ++j)
delete *j;

View file

@ -73,8 +73,6 @@ display::display(unit_map& units, CVideo& video, const gamemap& map,
energy_bar_rect_.x = -1;
create_buttons();
std::fill(reportRects_,reportRects_+reports::NUM_REPORTS,empty_rect);
image::set_zoom(zoom_);
@ -446,7 +444,10 @@ void display::redraw_everything()
tooltips::clear_tooltips();
theme_.set_resolution(screen_area());
create_buttons();
if(buttons_.empty() == false) {
create_buttons();
}
panelsDrawn_ = false;
@ -458,7 +459,7 @@ void display::redraw_everything()
namespace {
void draw_panel(display& disp, const theme::panel& panel)
void draw_panel(display& disp, const theme::panel& panel, std::vector<gui::button>& buttons)
{
log_scope("draw panel");
scoped_sdl_surface surf(image::get_image(panel.image(),image::UNSCALED));
@ -473,6 +474,12 @@ void draw_panel(display& disp, const theme::panel& panel)
disp.blit_surface(loc.x,loc.y,surf);
update_rect(loc);
for(std::vector<gui::button>::iterator b = buttons.begin(); b != buttons.end(); ++b) {
if(rects_overlap(b->location(),loc)) {
b->set_dirty(true);
}
}
}
void draw_label(display& disp, SDL_Surface* target, const theme::label& label)
@ -506,12 +513,14 @@ void draw_label(display& disp, SDL_Surface* target, const theme::label& label)
void display::draw(bool update,bool force)
{
std::cerr << "starting draw...\n";
if(!panelsDrawn_) {
std::cerr << "drawing panels...\n";
SDL_Surface* const screen = screen_.getSurface();
const std::vector<theme::panel>& panels = theme_.panels();
for(std::vector<theme::panel>::const_iterator p = panels.begin(); p != panels.end(); ++p) {
draw_panel(*this,*p);
draw_panel(*this,*p,buttons_);
}
const std::vector<theme::label>& labels = theme_.labels();
@ -519,14 +528,12 @@ void display::draw(bool update,bool force)
draw_label(*this,screen,*i);
}
for(std::vector<gui::button>::iterator b = buttons_.begin(); b != buttons_.end(); ++b) {
b->draw();
}
//invalidate the reports so they are redrawn
std::fill(reports_,reports_+sizeof(reports_)/sizeof(*reports_),reports::report());
invalidateGameStatus_ = true;
panelsDrawn_ = true;
std::cerr << "done panels...\n";
}
if(invalidateAll_ && !map_.empty()) {
@ -576,6 +583,8 @@ void display::draw(bool update,bool force)
drawSkips_++;
}
std::cerr << "done draw...\n";
}
void display::update_display()
@ -668,6 +677,8 @@ void display::draw_report(reports::TYPE report_num)
if(!team_valid())
return;
std::cerr << "drawing report " << (int)report_num << "\n";
const theme::status_item* const item = theme_.get_status_item(reports::report_name(report_num));
if(item != NULL) {
@ -682,6 +693,7 @@ void display::draw_report(reports::TYPE report_num)
//report and its location is unchanged since last time. Do nothing.
if(rect == new_rect && reports_[report_num] == report) {
std::cerr << "report needs no redrawing\n";
return;
}
@ -772,6 +784,8 @@ void display::draw_report(reports::TYPE report_num)
} else {
reportSurfaces_[report_num].assign(NULL);
}
std::cerr << "done drawing report\n";
}
void display::draw_unit_details(int x, int y, const gamemap::location& loc,
@ -821,7 +835,7 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
std::stringstream details;
details << font::LARGE_TEXT << u.description() << "\n"
<< font::LARGE_TEXT << u.type().language_name()
<< "\n-(" << string_table["level"] << " "
<< "\n" << font::SMALL_TEXT << "(" << string_table["level"] << " "
<< u.type().level() << ")\n"
<< status << "\n"
<< translate_string(unit_type::alignment_description(u.type().alignment()))
@ -2059,15 +2073,29 @@ const theme::menu* display::menu_pressed(int mousex, int mousey, bool button_pre
void display::create_buttons()
{
std::cerr << "clearing buttons...\n";
buttons_.clear();
std::cerr << "creating buttons...\n";
const std::vector<theme::menu>& buttons = theme_.menus();
for(std::vector<theme::menu>::const_iterator i = buttons.begin(); i != buttons.end(); ++i) {
std::cerr << "a\n";
gui::button b(*this,i->title(),gui::button::TYPE_PRESS,i->image());
std::cerr << "b\n";
const SDL_Rect& loc = i->location(screen_area());
std::cerr << "c\n";
b.set_location(loc.x,loc.y);
// if(rects_overlap(b.location(),map_area())) {
// b.set_volatile(true);
// }
std::cerr << "d\n";
buttons_.push_back(b);
std::cerr << "e\n";
}
std::cerr << "done creating buttons...\n";
}
void display::add_observer(const std::string& name)

View file

@ -319,6 +319,8 @@ public:
void remove_highlighted_loc(const gamemap::location &hex);
void create_buttons();
private:
display(const display&);
void operator=(const display&);
@ -420,7 +422,6 @@ private:
theme theme_;
terrain_builder builder_;
void create_buttons();
std::vector<gui::button> buttons_;
bool firstTurn_;

View file

@ -8,7 +8,7 @@
#include <algorithm>
#include <cassert>
#include <stack>
#include <deque>
#include <utility>
#include <vector>
@ -35,7 +35,7 @@ struct context
{
context() : focused_handler(-1) {}
void add_handler(handler* ptr);
void remove_handler(handler* ptr);
bool remove_handler(handler* ptr);
int cycle_focus();
void set_focus(const handler* ptr);
@ -53,6 +53,7 @@ void context::add_handler(handler* ptr)
void context::delete_handler_index(size_t handler)
{
std::cerr << "delete handler index " << handler << "\n";
if(focused_handler == int(handler)) {
focused_handler = -1;
} else if(focused_handler > int(handler)) {
@ -61,15 +62,20 @@ void context::delete_handler_index(size_t handler)
handlers.erase(handlers.begin()+handler);
cycle_focus();
std::cerr << "done delete handler index " << handler << "\n";
}
void context::remove_handler(handler* ptr)
bool context::remove_handler(handler* ptr)
{
if(handlers.empty()) {
return;
return false;
}
std::cerr << "remove handler...\n";
static int depth = 0;
++depth;
//the handler is most likely on the back of the events array,
//so look there first, otherwise do a complete search.
if(handlers.back() == ptr) {
@ -78,8 +84,22 @@ void context::remove_handler(handler* ptr)
const std::vector<handler*>::iterator i = std::find(handlers.begin(),handlers.end(),ptr);
if(i != handlers.end()) {
delete_handler_index(i - handlers.begin());
} else {
return false;
}
}
--depth;
if(depth == 0) {
cycle_focus();
} else {
focused_handler = -1;
}
std::cerr << "done remove handler...\n";
return true;
}
int context::cycle_focus()
@ -111,33 +131,37 @@ void context::set_focus(const handler* ptr)
//a new event context is created when e.g. a modal dialog is opened, and then
//closed when that dialog is closed. Each context contains a list of the handlers
//in that context. The current context is the one on the top of the stack
std::stack<context> event_contexts;
std::deque<context> event_contexts;
} //end anon namespace
event_context::event_context()
{
event_contexts.push(context());
event_contexts.push_back(context());
}
event_context::~event_context()
{
assert(event_contexts.empty() == false);
event_contexts.pop();
event_contexts.pop_back();
}
handler::handler() : unicode_(SDL_EnableUNICODE(1))
{
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
event_contexts.top().add_handler(this);
event_contexts.back().add_handler(this);
}
handler::~handler()
{
assert(event_contexts.empty() == false);
event_contexts.top().remove_handler(this);
for(std::deque<context>::reverse_iterator i = event_contexts.rbegin(); i != event_contexts.rend(); ++i) {
if(i->remove_handler(this)) {
break;
}
}
SDL_EnableUNICODE(unicode_);
}
@ -145,14 +169,14 @@ handler::~handler()
void focus_handler(const handler* ptr)
{
if(event_contexts.empty() == false) {
event_contexts.top().set_focus(ptr);
event_contexts.back().set_focus(ptr);
}
}
void cycle_focus()
{
if(event_contexts.empty() == false) {
event_contexts.top().cycle_focus();
event_contexts.back().cycle_focus();
}
}
@ -166,7 +190,7 @@ bool has_focus(const handler* ptr)
return true;
}
const int index = event_contexts.top().focused_handler;
const int index = event_contexts.back().focused_handler;
//if no-one has focus at the moment, this handler obviously wants
//focus, so give it to it.
@ -174,7 +198,7 @@ bool has_focus(const handler* ptr)
focus_handler(ptr);
return true;
} else {
return event_contexts.top().handlers[index] == ptr;
return event_contexts.back().handlers[index] == ptr;
}
}
@ -261,7 +285,7 @@ void pump()
if(event_contexts.empty() == false) {
const std::vector<handler*>& event_handlers = event_contexts.top().handlers;
const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here.
@ -282,7 +306,7 @@ void raise_process_event()
{
if(event_contexts.empty() == false) {
const std::vector<handler*>& event_handlers = event_contexts.top().handlers;
const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here.
@ -296,7 +320,7 @@ void raise_draw_event()
{
if(event_contexts.empty() == false) {
const std::vector<handler*>& event_handlers = event_contexts.top().handlers;
const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here.
@ -310,7 +334,7 @@ void raise_volatile_draw_event()
{
if(event_contexts.empty() == false) {
const std::vector<handler*>& event_handlers = event_contexts.top().handlers;
const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here.
@ -324,7 +348,7 @@ void raise_volatile_undraw_event()
{
if(event_contexts.empty() == false) {
const std::vector<handler*>& event_handlers = event_contexts.top().handlers;
const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here.

View file

@ -190,6 +190,31 @@ const SDL_Color& get_side_colour(int side)
}
namespace {
SDL_Rect text_size(TTF_Font* font, const std::string& str, const SDL_Color& colour, int style)
{
const font_style_setter style_setter(font,style);
SDL_Rect res = {0,0,0,0};
int w = 0, h = 0;
switch(charset())
{
case CHARSET_UTF8:
TTF_SizeUTF8(font,str.c_str(),&w,&h);
break;
case CHARSET_LATIN1:
TTF_SizeText(font,str.c_str(),&w,&h);
break;
default:
std::cerr << "Unrecognized charset\n";
}
res.w = size_t(w);
res.h = size_t(h);
return res;
}
SDL_Surface* render_text_internal(TTF_Font* font,const std::string& str,
const SDL_Color& colour, int style)
{
@ -324,15 +349,17 @@ SDL_Rect draw_text_line(SDL_Surface *gui_surface, const SDL_Rect& area, int size
TTF_Font* const font = get_font(size);
if(font == NULL) {
std::cerr << "Could not get font\n";
SDL_Rect res;
res.x = 0; res.y = 0; res.w = 0; res.h = 0;
SDL_Rect res = {0,0,0,0};
return res;
}
scoped_sdl_surface surface(render_text(font,text.c_str(),colour,style));
if(gui_surface == NULL) {
return text_size(font,text,colour,style);
}
scoped_sdl_surface surface(render_text(font,text,colour,style));
if(surface == NULL) {
SDL_Rect res;
res.x = 0; res.y = 0; res.w = 0; res.h = 0;
SDL_Rect res = {0,0,0,0};
return res;
}
@ -398,10 +425,10 @@ SDL_Rect draw_text_line(display* gui, const SDL_Rect& area, int size,
return draw_text_line(surface, area, size, colour, text, x, y, bg, use_tooltips, style);
}
SDL_Rect text_area(const std::string& text, int size)
SDL_Rect text_area(const std::string& text, int size, int style)
{
const SDL_Rect area = {0,0,10000,10000};
return draw_text(NULL,area,size,font::NORMAL_COLOUR,text,0,0);
return draw_text(NULL,area,size,font::NORMAL_COLOUR,text,0,0,NULL,false,USE_MARKUP,style);
}
SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,

View file

@ -41,6 +41,7 @@ void show_intro(display& screen, const config& data,
{
std::cerr << "showing intro sequence...\n";
const events::resize_lock stop_resizing;
const events::event_context context;
const std::string& music = data["music"];
if(music != "") {
@ -89,9 +90,6 @@ bool show_intro_part(display& screen, const config& part,
gui::button next_button(screen,string_table["next_button"] + ">>>");
gui::button skip_button(screen,string_table["skip_button"]);
next_button.set_location(screen.x()-200,screen.y()-150);
skip_button.set_location(screen.x()-200,screen.y()-100);
gui::draw_solid_tinted_rectangle(0,0,screen.x()-1,screen.y()-1,
0,0,0,1.0,screen.video().getSurface());
const std::string& image_name = part["image"];
@ -122,8 +120,12 @@ bool show_intro_part(display& screen, const config& part,
next_button.set_location(dstrect.x+dstrect.w-40,dstrect.y+dstrect.h+20);
skip_button.set_location(dstrect.x+dstrect.w-40,dstrect.y+dstrect.h+70);
} else {
next_button.set_location(screen.x()-200,screen.y()-150);
skip_button.set_location(screen.x()-200,screen.y()-100);
}
next_button.draw();
skip_button.draw();
update_whole_screen();
@ -223,6 +225,8 @@ bool show_intro_part(display& screen, const config& part,
return false;
events::pump();
events::raise_process_event();
events::raise_draw_event();
screen.video().flip();
if(!skip || j == story.end())

View file

@ -709,6 +709,18 @@ bool mp_connect::get_network_data(config& cfg)
void mp_connect::start_game()
{
combos_type_.clear();
combos_race_.clear();
combos_team_.clear();
combos_color_.clear();
sliders_gold_.clear();
ai_.hide();
launch_.hide();
cancel_.hide();
gold_bg_.clear();
//Tell everyone to start
config cfg;
cfg.add_child("start_game");

View file

@ -162,6 +162,10 @@ RESULT enter(display& disp, config& game_data, const config& terrain_data, dialo
new_game.hide();
quit_game.hide();
}
if(!games_available) {
join_game.hide();
}
std::vector<std::string> users;
for(config::const_child_itors i = game_data.child_range("user"); i.first != i.second; ++i.first) {

View file

@ -322,6 +322,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
turn_info::floating_textbox textbox_info;
try {
gui.create_buttons();
gui.adjust_colours(0,0,0);
game_events::fire("prestart");
@ -331,7 +332,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
}
gui.scroll_to_tile(map.starting_position(1).x,map.starting_position(1).y,display::WARP);
bool replaying = (recorder.at_end() == false);
//if a team is specified whose turn it is, it means we're loading a game
@ -354,12 +355,14 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
std::cerr << "first_time..." << (recorder.skipping() ? "skipping" : "no skip") << "\n";
update_locker lock_display(gui,recorder.skipping());
events::raise_draw_event();
game_events::fire("start");
gui.draw();
}
gui.new_turn();
gui.invalidate_game_status();
events::raise_draw_event();
std::cerr << "turn: " << turn++ << "\n";

View file

@ -144,6 +144,8 @@ turn_info::turn_info(game_data& gameinfo, game_state& state_of_game,
void turn_info::turn_slice()
{
events::pump();
events::raise_process_event();
events::raise_draw_event();
int mousex, mousey;
const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);

View file

@ -668,9 +668,9 @@ void show_preferences_dialog(display& disp)
set_colour_cursors(colour_cursors_button.checked());
}
music_slider.process();
sound_slider.process();
scroll_slider.process();
events::pump();
events::raise_process_event();
events::raise_draw_event();
set_sound_volume(sound_slider.value());
set_music_volume(music_slider.value());
@ -679,7 +679,6 @@ void show_preferences_dialog(display& disp)
disp.update_display();
SDL_Delay(20);
events::pump();
}
}
@ -869,15 +868,18 @@ void show_hotkeys_dialog (display & disp)
hotkey::save_hotkeys(prefs);
redraw_all = true;
}
disp.update_display ();
menu_.process (mousex, mousey, left_button, false,
false, false, false);
SDL_Delay (10);
events::pump ();
}
events::pump();
events::raise_process_event();
events::raise_draw_event();
disp.update_display();
SDL_Delay(10);
}
}
bool green_confirm()

View file

@ -27,6 +27,12 @@ bool point_in_rect(int x, int y, const SDL_Rect& rect)
return x >= rect.x && y >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h;
}
bool rects_overlap(const SDL_Rect& rect1, const SDL_Rect& rect2)
{
return point_in_rect(rect1.x,rect1.y,rect2) || point_in_rect(rect1.x+rect1.w,rect1.y,rect2) ||
point_in_rect(rect1.x,rect1.y+rect1.h,rect2) || point_in_rect(rect1.x+rect1.w,rect1.y+rect1.h,rect2);
}
namespace {
SDL_PixelFormat& get_neutral_pixel_format()
{

View file

@ -35,6 +35,8 @@
bool point_in_rect(int x, int y, const SDL_Rect& rect);
bool rects_overlap(const SDL_Rect& rect1, const SDL_Rect& rect2);
struct free_sdl_surface {
void operator()(SDL_Surface* surface) const { SDL_FreeSurface(surface); }
};

View file

@ -284,6 +284,8 @@ bool theme::set_resolution(const SDL_Rect& screen)
context_ = new_menu;
else
menus_.push_back(new_menu);
std::cerr << "done adding menu...\n";
}
return result;

View file

@ -194,11 +194,13 @@ void menu::calculate_position()
if(selected_ < first_item_on_screen_) {
first_item_on_screen_ = selected_;
itemRects_.clear();
drawn_ = false;
}
if(selected_ >= first_item_on_screen_ + int(max_items_onscreen())) {
first_item_on_screen_ = selected_ - (max_items_onscreen() - 1);
itemRects_.clear();
drawn_ = false;
}
}
@ -209,7 +211,8 @@ void menu::key_press(SDLKey key)
if(!click_selects_ && selected_ > 0) {
--selected_;
calculate_position();
drawn_ = false;
undrawn_items_.insert(selected_);
undrawn_items_.insert(selected_+1);
}
break;
@ -219,7 +222,8 @@ void menu::key_press(SDLKey key)
if(!click_selects_ && selected_ < int(items_.size())-1) {
++selected_;
calculate_position();
drawn_ = false;
undrawn_items_.insert(selected_);
undrawn_items_.insert(selected_-1);
}
break;
@ -258,9 +262,11 @@ void menu::key_press(SDLKey key)
if(key >= SDLK_1 && key <= SDLK_9 && num_selects_) {
const int pos = key - SDLK_1;
if(size_t(pos) < items_.size()) {
undrawn_items_.insert(selected_);
selected_ = pos;
calculate_position();
drawn_ = false;
undrawn_items_.insert(selected_);
}
}
}
@ -284,8 +290,9 @@ void menu::handle_event(const SDL_Event& event)
const int item = hit(x,y);
if(item != -1) {
undrawn_items_.insert(selected_);
selected_ = item;
drawn_ = false;
undrawn_items_.insert(selected_);
if(click_selects_) {
show_result_ = true;
@ -512,7 +519,7 @@ void menu::draw_item(int item)
}
} else {
const SDL_Rect& text_size = font::draw_text(NULL,area,menu_font_size,font::NORMAL_COLOUR,str,xpos,rect.y);
const SDL_Rect& text_size = font::text_area(str,menu_font_size);
const size_t y = rect.y + (rect.h - text_size.h)/2;
font::draw_text(display_,area,menu_font_size,font::NORMAL_COLOUR,str,xpos,y);
}
@ -522,10 +529,23 @@ void menu::draw_item(int item)
void menu::draw()
{
if(x_ == 0 && y_ == 0 || drawn_) {
if(x_ == 0 && y_ == 0 || drawn_ && undrawn_items_.empty()) {
return;
}
if(drawn_) {
for(std::set<size_t>::const_iterator i = undrawn_items_.begin(); i != undrawn_items_.end(); ++i) {
if(*i < items_.size()) {
draw_item(*i);
update_rect(get_item_rect(*i));
}
}
undrawn_items_.clear();
return;
}
undrawn_items_.clear();
drawn_ = true;
// update enabled/disabled status for up/down buttons

View file

@ -70,6 +70,7 @@ private:
bool click_selects_;
bool previous_button_;
bool drawn_;
std::set<size_t> undrawn_items_;
bool show_result_;

View file

@ -8,7 +8,7 @@ namespace {
namespace gui {
widget::widget(const widget &o) :
disp_(o.disp_), rect_(o.rect_), focus_(o.focus_), dirty_(o.dirty_), hidden_(false), volatile_(false)
disp_(o.disp_), rect_(o.rect_), focus_(o.focus_), dirty_(o.dirty_), hidden_(false), volatile_(o.volatile_)
{
bg_backup();
}