wesnoth-cvs-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Wesnoth-cvs-commits] wesnoth/src dialogs.cpp events.cpp events.hpp h...


From: Guillaume Melquiond
Subject: [Wesnoth-cvs-commits] wesnoth/src dialogs.cpp events.cpp events.hpp h...
Date: Sun, 31 Oct 2004 16:02:37 -0500

CVSROOT:        /cvsroot/wesnoth
Module name:    wesnoth
Branch:         
Changes by:     Guillaume Melquiond <address@hidden>    04/10/31 20:50:13

Modified files:
        src            : dialogs.cpp events.cpp events.hpp help.cpp 
                         intro.cpp mapgen_dialog.cpp multiplayer.cpp 
                         multiplayer_client.cpp multiplayer_connect.cpp 
                         multiplayer_lobby.cpp preferences.cpp 
                         sdl_utils.cpp sdl_utils.hpp show_dialog.cpp 
        src/editor     : editor_dialogs.cpp editor_palettes.cpp 
        src/widgets    : button.cpp button.hpp combo.cpp combo.hpp 
                         file_chooser.cpp menu.cpp menu.hpp 
                         scrollbar.cpp scrollbar.hpp slider.cpp 
                         slider.hpp textbox.cpp textbox.hpp widget.cpp 
                         widget.hpp 

Log message:
        The widgets rewrite; a whole lot of new bugs for those who were bored 
with the old ones. It comes with a patch (see task #3503) in case somebody 
needs to revert it.

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/dialogs.cpp.diff?tr1=1.62&tr2=1.63&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/events.cpp.diff?tr1=1.24&tr2=1.25&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/events.hpp.diff?tr1=1.13&tr2=1.14&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/help.cpp.diff?tr1=1.47&tr2=1.48&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/intro.cpp.diff?tr1=1.60&tr2=1.61&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/mapgen_dialog.cpp.diff?tr1=1.27&tr2=1.28&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer.cpp.diff?tr1=1.125&tr2=1.126&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer_client.cpp.diff?tr1=1.72&tr2=1.73&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer_connect.cpp.diff?tr1=1.83&tr2=1.84&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer_lobby.cpp.diff?tr1=1.46&tr2=1.47&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/preferences.cpp.diff?tr1=1.118&tr2=1.119&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/sdl_utils.cpp.diff?tr1=1.61&tr2=1.62&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/sdl_utils.hpp.diff?tr1=1.47&tr2=1.48&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/show_dialog.cpp.diff?tr1=1.99&tr2=1.100&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/editor/editor_dialogs.cpp.diff?tr1=1.19&tr2=1.20&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/editor/editor_palettes.cpp.diff?tr1=1.19&tr2=1.20&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/button.cpp.diff?tr1=1.44&tr2=1.45&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/button.hpp.diff?tr1=1.26&tr2=1.27&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/combo.cpp.diff?tr1=1.22&tr2=1.23&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/combo.hpp.diff?tr1=1.17&tr2=1.18&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/file_chooser.cpp.diff?tr1=1.7&tr2=1.8&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/menu.cpp.diff?tr1=1.65&tr2=1.66&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/menu.hpp.diff?tr1=1.24&tr2=1.25&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/scrollbar.cpp.diff?tr1=1.16&tr2=1.17&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/scrollbar.hpp.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/slider.cpp.diff?tr1=1.30&tr2=1.31&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/slider.hpp.diff?tr1=1.18&tr2=1.19&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/textbox.cpp.diff?tr1=1.58&tr2=1.59&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/textbox.hpp.diff?tr1=1.31&tr2=1.32&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/widget.cpp.diff?tr1=1.20&tr2=1.21&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/widgets/widget.hpp.diff?tr1=1.17&tr2=1.18&r1=text&r2=text

Patches:
Index: wesnoth/src/dialogs.cpp
diff -u wesnoth/src/dialogs.cpp:1.62 wesnoth/src/dialogs.cpp:1.63
--- wesnoth/src/dialogs.cpp:1.62        Wed Oct 27 19:28:07 2004
+++ wesnoth/src/dialogs.cpp     Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: dialogs.cpp,v 1.62 2004/10/27 19:28:07 gruikya Exp $ */
+/* $Id: dialogs.cpp,v 1.63 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -238,7 +238,6 @@
        }
 }
 
-static const SDL_Rect save_preview_pane_area = {-200,-400,200,400};
 static const int save_preview_border = 10;
 
 class save_preview_pane : public gui::preview_pane
@@ -248,9 +247,13 @@
                          const std::vector<save_info>& info, const 
std::vector<config*>& summaries)
                : gui::preview_pane(disp), game_config_(&game_config), 
map_(map), data_(&data), info_(&info), summaries_(&summaries), index_(0)
        {
-               set_location(save_preview_pane_area);
+               set_width(200);
+               set_height(400);
        }
 
+       virtual void set_location(SDL_Rect const &rect);
+       using widget::set_location;
+
        void draw();
        void set_selection(int index) {
                index_ = index;
@@ -269,6 +272,12 @@
        std::map<std::string,surface> map_cache_;
 };
 
+void save_preview_pane::set_location(SDL_Rect const &rect)
+{
+       widget::set_location(rect);
+       register_rectangle(rect);
+}
+
 void save_preview_pane::draw()
 {
        if(!dirty()) {
Index: wesnoth/src/editor/editor_dialogs.cpp
diff -u wesnoth/src/editor/editor_dialogs.cpp:1.19 
wesnoth/src/editor/editor_dialogs.cpp:1.20
--- wesnoth/src/editor/editor_dialogs.cpp:1.19  Fri Sep  3 08:27:13 2004
+++ wesnoth/src/editor/editor_dialogs.cpp       Sun Oct 31 20:50:13 2004
@@ -108,13 +108,15 @@
        SDL_Rect slider_rect = { 
slider_left,width_rect.y,slider_right-slider_left,width_rect.h};
 
        slider_rect.y = width_rect.y;
-       gui::slider width_slider(disp,slider_rect);
+       gui::slider width_slider(disp);
+       width_slider.set_location(slider_rect);
        width_slider.set_min(map_min_width);
        width_slider.set_max(map_max_width);
        width_slider.set_value(map_width);
 
        slider_rect.y = height_rect.y;
-       gui::slider height_slider(disp,slider_rect);
+       gui::slider height_slider(disp);
+       height_slider.set_location(slider_rect);
        height_slider.set_min(map_min_height);
        height_slider.set_max(map_max_height);
        height_slider.set_value(map_height);
@@ -269,7 +271,8 @@
        SDL_Rect slider_rect = { slider_left, scroll_pos, slider_right - 
slider_left, 10  };
 
        slider_rect.y = scroll_pos;
-       gui::slider scroll_slider(disp,slider_rect);
+       gui::slider scroll_slider(disp);
+       scroll_slider.set_location(slider_rect);
        scroll_slider.set_min(1);
        scroll_slider.set_max(100);
        scroll_slider.set_value(preferences::scroll_speed());
@@ -415,13 +418,15 @@
        SDL_Rect slider_rect = { 
slider_left,width_rect.y,slider_right-slider_left,width_rect.h};
 
        slider_rect.y = width_rect.y;
-       gui::slider width_slider(disp,slider_rect);
+       gui::slider width_slider(disp);
+       width_slider.set_location(slider_rect);
        width_slider.set_min(map_min_width);
        width_slider.set_max(map_max_width);
        width_slider.set_value(map_width);
 
        slider_rect.y = height_rect.y;
-       gui::slider height_slider(disp,slider_rect);
+       gui::slider height_slider(disp);
+       height_slider.set_location(slider_rect);
        height_slider.set_min(map_min_height);
        height_slider.set_max(map_max_height);
        height_slider.set_value(map_height);
Index: wesnoth/src/editor/editor_palettes.cpp
diff -u wesnoth/src/editor/editor_palettes.cpp:1.19 
wesnoth/src/editor/editor_palettes.cpp:1.20
--- wesnoth/src/editor/editor_palettes.cpp:1.19 Wed Oct 20 19:11:30 2004
+++ wesnoth/src/editor/editor_palettes.cpp      Sun Oct 31 20:50:13 2004
@@ -54,14 +54,16 @@
        scroll_top();
        const size_t button_height = 24;
        const size_t button_palette_padding = 8;
-       set_location(size_specs_.palette_x, size_specs_.palette_y);
-       set_width(size_specs_.palette_w);
-       set_height(size_specs_.palette_h);
+       SDL_Rect rect = { size_specs_.palette_x, size_specs_.palette_y, 
size_specs_.palette_w, size_specs_.palette_h };
+       set_location(rect);
        top_button_y_ = size_specs_.palette_y;
        button_x_ = size_specs_.palette_x + size_specs_.palette_w/2 - 
button_height/2;
        terrain_start_ = top_button_y_ + button_height + button_palette_padding;
        const size_t space_for_terrains = size_specs_.palette_h -
                (button_height + button_palette_padding) * 2;
+       rect.y = terrain_start_;
+       rect.h = space_for_terrains;
+       register_rectangle(rect);
        const unsigned terrains_fitting =
                (unsigned)(space_for_terrains / size_specs_.terrain_space) * 2;
        const unsigned total_terrains = num_terrains();
@@ -72,7 +74,6 @@
        bot_button_.set_location(button_x_, bot_button_y_);
        top_button_.set_dirty();
        bot_button_.set_dirty();
-       bg_backup();
        set_dirty();
 }
 
@@ -295,6 +296,7 @@
        update_rect(loc);
        set_dirty(false);
 }
+
 int terrain_palette::tile_selected(const int x, const int y) const {
        for(unsigned int i = 0; i != nterrains_; i++) {
                const int px = size_specs_.palette_x +
Index: wesnoth/src/events.cpp
diff -u wesnoth/src/events.cpp:1.24 wesnoth/src/events.cpp:1.25
--- wesnoth/src/events.cpp:1.24 Fri Oct 29 19:53:22 2004
+++ wesnoth/src/events.cpp      Sun Oct 31 20:50:13 2004
@@ -332,7 +332,7 @@
                //events may cause more event handlers to be added and/or 
removed,
                //so we must use indexes instead of iterators here.
                for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < 
event_handlers.size(); ++i1) {
-                       event_handlers[i1]->process();
+                       event_handlers[i1]->process_event();
                }
        }
 }
Index: wesnoth/src/events.hpp
diff -u wesnoth/src/events.hpp:1.13 wesnoth/src/events.hpp:1.14
--- wesnoth/src/events.hpp:1.13 Thu Jun 10 23:43:24 2004
+++ wesnoth/src/events.hpp      Sun Oct 31 20:50:13 2004
@@ -27,7 +27,7 @@
 {
 public:
        virtual void handle_event(const SDL_Event& event) = 0;
-       virtual void process() {}
+       virtual void process_event() {}
        virtual void draw() {}
 
        virtual void volatile_draw() {}
Index: wesnoth/src/help.cpp
diff -u wesnoth/src/help.cpp:1.47 wesnoth/src/help.cpp:1.48
--- wesnoth/src/help.cpp:1.47   Sun Oct 31 08:19:40 2004
+++ wesnoth/src/help.cpp        Sun Oct 31 20:50:13 2004
@@ -153,17 +153,7 @@
 class help_menu : public gui::menu {
 public:
        help_menu(display& disp, const section &toplevel, int max_height=-1);
-       void bg_backup();
-       void bg_restore();
-       int process(int x, int y, bool button,bool up_arrow,bool down_arrow,
-                   bool page_up, bool page_down, int select_item=-1);
-
-       /// Overloaded from menu so that the background can be saved.
-       void set_loc(int x, int y);
-       /// Overloaded from menu so that the background can be saved.
-       void set_width(int w);
-       /// Overloaded from menu so that the background can be saved.
-       void set_max_height(const int new_height);
+       int process();
 
        /// Make the topic the currently selected one, and expand all
        /// sections that need to be expanded to show it.
@@ -173,8 +163,6 @@
        /// NULL. If one topic is returned, it will not be returned again,
        /// if it is not re-chosen.
        const topic *chosen_topic();
-protected:
-       void handle_event(const SDL_Event &event);
 
 private:
        /// Information about an item that is visible in the menu.
@@ -220,16 +208,13 @@
        /// section was expanded, otherwise untouched.
        bool select_topic_internal(const topic &t, const section &sec);
 
-       display &disp_;
        std::vector<visible_item> visible_items_;
        const section &toplevel_;
        std::set<const section*> expanded_; 
        surface_restorer restorer_;
        SDL_Rect rect_;
        topic const *chosen_topic_;
-       int internal_width_;
        visible_item selected_item_;
-       bool selected_;
 };
 
 /// Thrown when the help system fails to parse something.
@@ -255,15 +240,9 @@
 
        void scroll(int pos);
 
-       void set_dirty(bool dirty);
+       virtual void set_location(const SDL_Rect& rect);
+       using gui::widget::set_location;
 
-       /// Scroll the contents up an amount. If how_much is below zero the
-       /// amount will depend on the height.
-       void scroll_up(const int how_much=-1);
-
-       /// Scroll the contents down an amount. If how_much is below zero
-       /// the amount will depend on the height.
-       void scroll_down(const int how_much=-1);
 private:
        enum ALIGNMENT {LEFT, MIDDLE, RIGHT, HERE};
        /// Convert a string to an alignment. Throw parse_error if
@@ -326,16 +305,7 @@
        void handle_jump_cfg(const config &cfg);
        void handle_format_cfg(const config &cfg);
 
-       void handle_event(const SDL_Event &event);
        void draw();
-       void process();
-
-       /// Update the scrollbar to take account for the current items.
-       void update_scrollbar();
-
-       /// Get the current amount of scrolling that should be
-       /// added/substracted from the locations to get the desired effect.
-       unsigned get_scroll_offset() const;
 
        /// Add an item with text. If ref_dst is something else than the
        /// empty string, the text item will be underlined to show that it
@@ -381,7 +351,6 @@
 
        std::list<item> items_;
        std::list<item *> last_row_;
-       display &disp_;
        const section &toplevel_;
        topic const *shown_topic_;
        const int title_spacing_;
@@ -390,8 +359,6 @@
        const unsigned min_row_height_;
        unsigned curr_row_height_;
        gui::scrollbar scrollbar_;
-       bool use_scrollbar_;
-       gui::button uparrow_, downarrow_;
        /// The height of all items in total.
        int contents_height_;
 };
@@ -403,25 +370,24 @@
 
        // Overloaded from widget so that the layout may be adjusted to fit
        // the new dimensions.
-       void set_location(const SDL_Rect& rect);
-       void set_location(int x, int y);
-       void set_width(int w);
-       void set_height(int h);
+       virtual void set_location(const SDL_Rect& rect);
+       using gui::widget::set_location;
 
-       void set_dirty(bool dirty);
        void adjust_layout();
 
-       void process();
        /// Display the topic with the specified identifier. Open the menu
        /// on the right location and display the topic in the text area.
        void show_topic(const std::string &topic_id);
 
+protected:
+       virtual void process_event();
+       virtual void handle_event(const SDL_Event &event);
+
 private:
        /// Update the current cursor, set it to the reference cursor if
        /// mousex, mousey is over a cross-reference, otherwise, set it to
        /// the normal cursor.
        void update_cursor();
-       void handle_event(const SDL_Event &event);
        void show_topic(const topic &t, bool save_in_history=true);
        /// Move in the topic history. Pop an element from from and insert
        /// it in to. Pop at the fronts if the maximum number of elements is
@@ -1486,27 +1452,15 @@
        sections.clear();
 }
 
-help_menu::help_menu(display& disp, const section &toplevel, int max_height)
-       : menu(disp, empty_string_vector, false, max_height), disp_(disp),
-         toplevel_(toplevel), chosen_topic_(NULL), internal_width_(0), 
selected_item_(&toplevel, ""),
-         selected_(false) {
-       bg_backup();
+help_menu::help_menu(display &disp, section const &toplevel, int max_height)
+       : menu(disp, empty_string_vector, false, max_height),
+         toplevel_(toplevel), chosen_topic_(NULL), selected_item_(&toplevel, 
"") {
        update_visible_items(toplevel_);
        display_visible_items();
-       if (!visible_items_.empty()) {
+       if (!visible_items_.empty())
                selected_item_ = visible_items_.front();
-       }
-}
-
-void help_menu::bg_backup() {
-       restorer_ = surface_restorer(&disp_.video(), get_rect());
-}
-
-void help_menu::bg_restore() {
-       restorer_.restore();
 }
 
-
 bool help_menu::expanded(const section &sec) {
        return expanded_.find(&sec) != expanded_.end();
 }
@@ -1567,52 +1521,6 @@
        return to_show.str();
 }
 
-void help_menu::handle_event(const SDL_Event &event) {
-       int mousex, mousey;
-       SDL_GetMouseState(&mousex,&mousey);
-       // Only handle events if we have focus, that is, the mouse is within
-       // the menu.
-       if (point_in_rect(mousex, mousey, get_rect())) {
-               if (event.type == SDL_MOUSEBUTTONDOWN) {
-                       SDL_MouseButtonEvent mouse_event = event.button;
-                       if (mouse_event.button == SDL_BUTTON_LEFT) {
-                               if (mousex < get_rect().x + item_area_width()) {
-                                       // See to that only clicks on items are 
noticed, not
-                                       // scrollbar clicks.
-                                       selected_ = true;
-                               }
-                       }
-               }
-               else if (event.type == SDL_KEYDOWN) {
-                       if (event.key.keysym.sym == SDLK_RETURN) {
-                               // Select items on return press too.
-                               selected_ = true;
-                       }
-               }
-               menu::handle_event(event);
-       }
-}
-
-void help_menu::set_loc(int x, int y) {
-       menu::set_loc(x, y);
-       bg_backup();
-       display_visible_items();
-}
-
-void help_menu::set_width(int w) {
-       menu::set_width(w);
-       set_max_width(w);
-       bg_backup();
-       internal_width_ = w;
-       display_visible_items();
-}
-
-void help_menu::set_max_height(const int new_height) {
-       menu::set_max_height(new_height);
-       bg_backup();
-       display_visible_items();
-}
-
 bool help_menu::select_topic_internal(const topic &t, const section &sec) {
        topic_list::const_iterator tit =
                std::find(sec.topics.begin(), sec.topics.end(), t);
@@ -1648,25 +1556,20 @@
        }
 }
        
-int help_menu::process(int x, int y, bool button,bool up_arrow,bool down_arrow,
-                                          bool page_up, bool page_down, int 
select_item) {
-       int res = menu::process(x, y, button, up_arrow, down_arrow, page_up, 
page_down, select_item);
-       if (!visible_items_.empty() && selection() >= 0
-               && (unsigned)selection() < visible_items_.size()) {
-               selected_item_ = visible_items_[selection()];
-               if (selected_) {
-                       selected_ = false;
-                       if (selected_item_.sec != NULL) {
-                               // Open or close a section if it is clicked.
-                               expanded(*selected_item_.sec) ? 
contract(*selected_item_.sec)
-                                       : expand(*selected_item_.sec);
-                               update_visible_items(toplevel_);
-                               display_visible_items();
-                       }
-                       else if (selected_item_.t != NULL) {
-                               /// Choose a topic if it is clicked.
-                               chosen_topic_ = selected_item_.t;
-                       }
+int help_menu::process() {
+       int res = menu::process();
+       if (double_clicked())
+               res = selection();
+       if (!visible_items_.empty() && (unsigned)res < visible_items_.size()) {
+               selected_item_ = visible_items_[res];
+               if (selected_item_.sec != NULL) {
+                       // Open or close a section if it is clicked.
+                       expanded(*selected_item_.sec) ? 
contract(*selected_item_.sec) : expand(*selected_item_.sec);
+                       update_visible_items(toplevel_);
+                       display_visible_items();
+               } else if (selected_item_.t != NULL) {
+                       /// Choose a topic if it is clicked.
+                       chosen_topic_ = selected_item_.t;
                }
        }
        return res;
@@ -1679,18 +1582,15 @@
 }
        
 void help_menu::display_visible_items() {
-       bg_restore();
        std::vector<std::string> menu_items;
-       std::vector<visible_item>::const_iterator items_it;
-       for (items_it = visible_items_.begin(); items_it != 
visible_items_.end(); items_it++) {
-               std::string to_show = (*items_it).visible_string;
-               if (selected_item_ == *items_it) {
+       for(std::vector<visible_item>::const_iterator items_it = 
visible_items_.begin(),
+                end = visible_items_.end(); items_it != end; ++items_it) {
+               std::string to_show = items_it->visible_string;
+               if (selected_item_ == *items_it)
                        to_show = std::string("*") + to_show;
-               }
                menu_items.push_back(to_show);
        }
        set_items(menu_items, false, true);
-       menu::set_width(internal_width_);
 }
 
 help_menu::visible_item::visible_item(const section *_sec, const std::string 
&vis_string) :
@@ -1712,22 +1612,26 @@
 }
 
 help_text_area::help_text_area(display &disp, const section &toplevel)
-       : gui::widget(disp), disp_(disp), toplevel_(toplevel), 
shown_topic_(NULL),
+       : gui::widget(disp), toplevel_(toplevel), shown_topic_(NULL),
          title_spacing_(16), curr_loc_(0, 0),
          min_row_height_(font::get_max_height(normal_font_size)), 
curr_row_height_(min_row_height_),
-         scrollbar_(disp, this), use_scrollbar_(false),
-         uparrow_(disp,"",gui::button::TYPE_PRESS,"uparrow-button"),
-         downarrow_(disp,"",gui::button::TYPE_PRESS,"downarrow-button"),
-         contents_height_(0)
+         scrollbar_(disp, *this, this), contents_height_(0)
 {}
 
+void help_text_area::set_location(SDL_Rect const &rect) {
+       widget::set_location(rect);
+       SDL_Rect r = rect;
+       int w = scrollbar_.width();
+       r.w -= w;
+       register_rectangle(r);
+       r.x += r.w;
+       r.w = w;
+       scrollbar_.set_location(r);
+}
+
 void help_text_area::show_topic(const topic &t) {
        bg_restore();
        shown_topic_ = &t;
-       scrollbar_.set_grip_position(0);
-       // A new topic will be shown, we do not know yet if a new scrollbar
-       // is needed.
-       use_scrollbar_ = false;
        set_items(t.text, t.title);
        set_dirty(true);
 }
@@ -1771,19 +1675,10 @@
                contents_height_ = title_spacing_;
                down_one_line();
        }
-       bool retry = false;
        // Parse and add the text.
        std::vector<std::string>::const_iterator it;
        for (it = parsed_items.begin(); it != parsed_items.end(); it++) {
                if (*it != "" && (*it)[0] == '[') {
-                       if (contents_height_ > (int)height() && 
!use_scrollbar_) {
-                               // The items did not fit, we need a
-                               // scrollbar. Everything has to be redone since 
the
-                               // width is less now and items added before may 
not fit.
-                               retry = true;
-                               use_scrollbar_ = true;
-                               break;
-                       }
                        // Should be parsed as WML.
                        try {
                                config cfg(*it);
@@ -1827,15 +1722,10 @@
                }
        }
        down_one_line(); // End the last line.
-       if (contents_height_ > (int)height() && !use_scrollbar_) {
-               // Last line caused us to have to use a scrollbar.
-               use_scrollbar_ = true;
-               retry = true;
-       }
-       if (retry) {
-               set_items(parsed_items, title);
-       }
-       update_scrollbar();
+       int h = height();
+       scrollbar_.set_full_size(contents_height_);
+       scrollbar_.set_shown_size(h);
+       scrollbar_.hide(h >= contents_height_);
 }
 
 void help_text_area::handle_ref_cfg(const config &cfg) {
@@ -1944,8 +1834,7 @@
        if (cfg["font_size"] != "") {
                try {
                        font_size = lexical_cast<int, 
std::string>(cfg["font_size"]);
-               }
-               catch (bad_lexical_cast) {
+               } catch (bad_lexical_cast) {
                        throw parse_error("Invalid font_size in format 
markup.");
                }
        }
@@ -1953,60 +1842,16 @@
        add_text_item(text, "", font_size, bold, italic, color);
 }
 
-void help_text_area::update_scrollbar() {
-       if (!use_scrollbar_) {
-               scrollbar_.enable(false);
-               downarrow_.hide(true);
-               uparrow_.hide(true);
-               return;
-       }
-       uparrow_.set_location(location().x + width() - uparrow_.width(), 
location().y);
-       downarrow_.set_location(location().x + width() - downarrow_.width(),
-                                                       location().y + 
location().h - downarrow_.height());
-       const int scrollbar_height = height() - uparrow_.height() - 
downarrow_.height();
-       scrollbar_.enable(true);
-       scrollbar_.set_location(location().x + width() - scrollbar_.get_width(),
-                                                       location().y + 
uparrow_.height());
-       scrollbar_.set_height(scrollbar_height);
-       scrollbar_.set_width(scrollbar_.get_max_width()); // Needed to update 
the screen.
-       float pos_percent = (float)scrollbar_height / (float)contents_height_;
-       int grip_height = (int)(pos_percent * scrollbar_height);
-       const int min_height = scrollbar_.get_minimum_grip_height();
-       if (grip_height < min_height) {
-               grip_height = min_height;
-       }
-       if (grip_height > (int)height()) {
-               std::cerr << "Strange. For some reason I want my scrollbar"
-                                 << " to be larger than me!\n\n";
-               grip_height = height();
-       }
-       scrollbar_.set_grip_height(grip_height);
-       scrollbar_.set_grip_position(0);
-}
-
-void help_text_area::set_dirty(bool dirty) {
-       widget::set_dirty(dirty);
-       if (dirty) {
-               scrollbar_.set_dirty(true);
-               uparrow_.set_dirty(true);
-               downarrow_.set_dirty(true);
-       }
-}
-
 int help_text_area::text_width() const {
-       if (use_scrollbar_) {
-               return width() - scrollbar_.get_max_width();
-       }
-       return width();
+       return width() - scrollbar_.width();
 }
 
 void help_text_area::add_text_item(const std::string text, const std::string 
ref_dst,
                                                                   int 
_font_size, bool bold, bool italic,
                                                                   SDL_Color 
text_color) {
        const int font_size = _font_size < 0 ? normal_font_size : _font_size;
-       if (text == "") {
+       if (text.empty())
                return;
-       }
        const int remaining_width = get_remaining_width();
        size_t first_word_start = text.find_first_not_of(" ");
        if (first_word_start == std::string::npos) {
@@ -2218,115 +2063,36 @@
        return total_w - curr_loc_.first;
 }
 
-unsigned help_text_area::get_scroll_offset() const {
-       const int scrollbar_pos = scrollbar_.get_grip_position();
-       float pos_percent = scrollbar_.height() / (float)contents_height_;
-       unsigned to_sub = 0;
-       if (pos_percent > 0) {
-               to_sub = (unsigned)(scrollbar_pos / pos_percent);
-       }
-       return to_sub;
-}
-
 void help_text_area::draw() {
-       if (dirty()) {
-               bg_restore();
-               SDL_Rect clip_rect = { location().x, location().y, 
text_width(), height() };
-               const int scrollbar_pos = scrollbar_.get_grip_position();
-               uparrow_.hide(scrollbar_pos == 0 || !scrollbar_.enabled());
-               downarrow_.hide(scrollbar_pos + scrollbar_.get_grip_height() == 
(int)scrollbar_.height()
-                                               || !scrollbar_.enabled());
-               surface const screen = disp_.video().getSurface();
-               clip_rect_setter clip_rect_set(screen, clip_rect);
-               std::list<item>::const_iterator it;
-               for (it = items_.begin(); it != items_.end(); it++) {
-                       SDL_Rect dst = (*it).rect;
-                       dst.y -= get_scroll_offset();
-                       if (dst.y < (int)height() && dst.y + (*it).rect.h > 0) {
-                               dst.x += location().x;
-                               dst.y += location().y;
-                               if ((*it).box) {
-                                       for (int i = 0; i < box_width; i++) {
-                                               gui::draw_rectangle(dst.x, 
dst.y, (*it).rect.w - i * 2, (*it).rect.h - i * 2,
-                                                                               
        0, screen);
-                                               dst.x++;
-                                               dst.y++;
-                                       }
-                               }
-                               SDL_BlitSurface((*it).surf, NULL, screen, &dst);
-                       }
-               }
-               update_rect(location());
-               scrollbar_.set_dirty(true);
-               set_dirty(false);
-       }
-}
-
-void help_text_area::process() {
-       if (uparrow_.pressed()) {
-               scroll_up();
-       }
-       if (downarrow_.pressed()) {
-               scroll_down();
-       }
-}
-
-void help_text_area::scroll_up(int how_much) {
-       if (use_scrollbar_) {
-               // Only allow scrolling when we have a scrollbar.
-               const int amount = how_much < 0 ? height() / 50 : how_much;
-               scrollbar_.set_grip_position(scrollbar_.get_grip_position() - 
amount);
-               set_dirty(true);
-       }
-}
-
-void help_text_area::scroll_down(int how_much) {
-       if (use_scrollbar_) {
-               // Only allow scrolling when we have a scrollbar.
-               const int amount = how_much < 0 ? height() / 50 : how_much;
-               scrollbar_.set_grip_position(scrollbar_.get_grip_position() + 
amount);
-               set_dirty(true);
-       }
-}
-
-void help_text_area::handle_event(const SDL_Event &event) {
-       if(event.type == SDL_MOUSEMOTION) {
-               // If the mouse has moved, check if this widget still has focus 
or not.
-               int mousex, mousey;
-               SDL_GetMouseState(&mousex,&mousey);
-               if (point_in_rect(mousex, mousey, location())) {
-                       if (!focus()) {
-                               set_focus(true);
-                               // wiget::set_focus will set everything dirty, 
so we
-                               // need to redraw the contents.
-                               set_dirty(true);
-                       }
-               }
-               else {
-                       if (focus()) {
-                               set_focus(false);
-                               // wiget::set_focus will set everything dirty, 
so we
-                               // need to redraw the contents.
-                               set_dirty(true);
-                       }
-               }
+       if (!dirty())
                return;
-       }
-       if (focus()) {
-               if (event.type == SDL_MOUSEBUTTONDOWN) {
-                       // Scroll up/down when the mouse wheel is used.
-                       SDL_MouseButtonEvent mouse_event = event.button;
-                       if (mouse_event.button == SDL_BUTTON_WHEELUP) {
-                               scroll_up();
-                       }
-                       if (mouse_event.button == SDL_BUTTON_WHEELDOWN) {
-                               scroll_down();
+       SDL_Rect const &loc = location();
+       SDL_Rect clip_rect = { loc.x, loc.y, text_width(), loc.h };
+       bg_restore(clip_rect);
+       surface const screen = disp().video().getSurface();
+       clip_rect_setter clip_rect_set(screen, clip_rect);
+       for(std::list<item>::const_iterator it = items_.begin(), end = 
items_.end(); it != end; ++it) {
+               SDL_Rect dst = it->rect;
+               dst.y -= scrollbar_.get_position();
+               if (dst.y < (int)loc.h && dst.y + it->rect.h > 0) {
+                       dst.x += loc.x;
+                       dst.y += loc.y;
+                       if (it->box) {
+                               for (int i = 0; i < box_width; i++) {
+                                       gui::draw_rectangle(dst.x, dst.y, 
it->rect.w - i * 2, it->rect.h - i * 2,
+                                                           0, screen);
+                                       dst.x++;
+                                       dst.y++;
+                               }
                        }
+                       SDL_BlitSurface(it->surf, NULL, screen, &dst);
                }
        }
+       update_rect(clip_rect);
+       set_dirty(false);
 }
 
-void help_text_area::scroll(int pos) {
+void help_text_area::scroll(int) {
        // Nothing will be done on the actual scroll event. The scroll
        // position is checked when drawing instead and things drawn
        // accordingly.
@@ -2341,7 +2107,7 @@
        const int local_x = x - location().x;
        const int local_y = y - location().y;
        if (local_y < (int)height() && local_y > 0) {
-               const int cmp_y = local_y + get_scroll_offset();
+               const int cmp_y = local_y + scrollbar_.get_position();
                const std::list<item>::const_iterator it =
                        std::find_if(items_.begin(), items_.end(), 
item_at(local_x, cmp_y));
                if (it != items_.end()) {
@@ -2393,7 +2159,7 @@
        const int forward_button_y = back_button_y;
 
        menu_.set_width(menu_w);
-       menu_.set_loc(menu_x, menu_y);
+       menu_.set_location(menu_x, menu_y);
        menu_.set_max_height(menu_h);
        menu_.set_max_width(menu_w);
 
@@ -2407,53 +2173,19 @@
        set_dirty(true);
 }
 
-void help_browser::set_dirty(bool dirty) {
-       widget::set_dirty(dirty);
-       if (dirty) {
-               update_cursor();
-               forward_button_.set_dirty();
-               back_button_.set_dirty();
-               menu_.set_dirty();
-               text_area_.set_dirty(true);
-       }
-}
-
 void help_browser::set_location(const SDL_Rect& rect) {
        widget::set_location(rect);
        adjust_layout();
 }
 
-void help_browser::set_location(int x, int y) {
-       widget::set_location(x, y);
-       adjust_layout();
-}
-
-void help_browser::set_width(int w) {
-       widget::set_width(w);
-       adjust_layout();
-}
-
-void help_browser::set_height(int h) {
-       widget::set_height(h);
-       adjust_layout();
-}
-
-void help_browser::process() {
+void help_browser::process_event() {
        CKey key;
        int mousex, mousey;
-       const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
+       SDL_GetMouseState(&mousex,&mousey);
 
-       const bool new_left_button = mouse_flags&SDL_BUTTON_LMASK;
-       
-       const bool new_up_arrow = key[SDLK_UP];
-       const bool new_down_arrow = key[SDLK_DOWN];
-       
-       const bool new_page_up = key[SDLK_PAGEUP];
-       const bool new_page_down = key[SDLK_PAGEDOWN];
        /// Fake focus functionality for the menu, only process it if it has 
focus.
-       if (point_in_rect(mousex, mousey, menu_.get_rect())) {
-               menu_.process(mousex, mousey, new_left_button, new_up_arrow,
-                                         new_down_arrow, new_page_up, 
new_page_down, -1);
+       if (point_in_rect(mousex, mousey, menu_.location())) {
+               menu_.process();
                const topic *chosen_topic = menu_.chosen_topic();
                if (chosen_topic != NULL && chosen_topic != shown_topic_) {
                        /// A new topic has been chosen in the menu, display it.
Index: wesnoth/src/intro.cpp
diff -u wesnoth/src/intro.cpp:1.60 wesnoth/src/intro.cpp:1.61
--- wesnoth/src/intro.cpp:1.60  Sat Sep 25 19:46:33 2004
+++ wesnoth/src/intro.cpp       Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: intro.cpp,v 1.60 2004/09/25 19:46:33 ydirson Exp $ */
+/* $Id: intro.cpp,v 1.61 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -125,8 +125,6 @@
                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();
 
        //draw title if needed
        if(show_title) {
@@ -267,10 +265,6 @@
 
                }
 
-               int mousex, mousey;
-               const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
-               const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
-
                const bool keydown = key[SDLK_SPACE] || key[SDLK_RETURN];
 
                if(keydown && !last_key || next_button.pressed()) {
@@ -283,7 +277,7 @@
 
                last_key = keydown;
 
-               if(key[SDLK_ESCAPE] || 
skip_button.process(mousex,mousey,left_button))
+               if(key[SDLK_ESCAPE] || skip_button.pressed())
                        return false;
 
                events::pump();
Index: wesnoth/src/mapgen_dialog.cpp
diff -u wesnoth/src/mapgen_dialog.cpp:1.27 wesnoth/src/mapgen_dialog.cpp:1.28
--- wesnoth/src/mapgen_dialog.cpp:1.27  Sat Oct  9 22:45:08 2004
+++ wesnoth/src/mapgen_dialog.cpp       Sun Oct 31 20:50:13 2004
@@ -122,7 +122,8 @@
        const int slider_left = text_right + 10;
        const int slider_right = xpos + width - horz_margin - right_space;
        SDL_Rect slider_rect = { 
slider_left,players_rect.y,slider_right-slider_left,players_rect.h};
-       gui::slider players_slider(disp,slider_rect);
+       gui::slider players_slider(disp);
+       players_slider.set_location(slider_rect);
        players_slider.set_min(2);
        players_slider.set_max(max_players);
        players_slider.set_value(nplayers_);
@@ -133,13 +134,15 @@
        const int extra_size_per_player = 2;
        
        slider_rect.y = width_rect.y;
-       gui::slider width_slider(disp,slider_rect);
+       gui::slider width_slider(disp);
+       width_slider.set_location(slider_rect);
        
width_slider.set_min(min_width+(players_slider.value()-2)*extra_size_per_player);
        width_slider.set_max(max_width);
        width_slider.set_value(width_);
 
        slider_rect.y = height_rect.y;
-       gui::slider height_slider(disp,slider_rect);
+       gui::slider height_slider(disp);
+       height_slider.set_location(slider_rect);
        
height_slider.set_min(min_width+(players_slider.value()-2)*extra_size_per_player);
        height_slider.set_max(max_height);
        height_slider.set_value(height_);
@@ -148,7 +151,8 @@
        const int max_iterations = 3000;
 
        slider_rect.y = iterations_rect.y;
-       gui::slider iterations_slider(disp,slider_rect);
+       gui::slider iterations_slider(disp);
+       iterations_slider.set_location(slider_rect);
        iterations_slider.set_min(min_iterations);
        iterations_slider.set_max(max_iterations);
        iterations_slider.set_value(iterations_);
@@ -157,7 +161,8 @@
        const int max_hillsize = 50;
 
        slider_rect.y = hillsize_rect.y;
-       gui::slider hillsize_slider(disp,slider_rect);
+       gui::slider hillsize_slider(disp);
+       hillsize_slider.set_location(slider_rect);
        hillsize_slider.set_min(min_hillsize);
        hillsize_slider.set_max(max_hillsize);
        hillsize_slider.set_value(hill_size_);
@@ -166,7 +171,8 @@
        const int max_villages = 50;
 
        slider_rect.y = villages_rect.y;
-       gui::slider villages_slider(disp,slider_rect);
+       gui::slider villages_slider(disp);
+       villages_slider.set_location(slider_rect);
        villages_slider.set_min(min_villages);
        villages_slider.set_max(max_villages);
        villages_slider.set_value(nvillages_);
@@ -174,7 +180,8 @@
        const int min_landform = 0;
        const int max_landform = int(max_island);
        slider_rect.y = landform_rect.y;
-       gui::slider landform_slider(disp,slider_rect);
+       gui::slider landform_slider(disp);
+       landform_slider.set_location(slider_rect);
        landform_slider.set_min(min_landform);
        landform_slider.set_max(max_landform);
        landform_slider.set_value(island_size_);
@@ -187,11 +194,6 @@
        link_castles.set_location(link_rect);
 
        for(bool draw = true;; draw = false) {
-               int mousex, mousey;
-               const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
-
-               const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
-
                nplayers_ = players_slider.value();
                width_ = width_slider.value();
                height_ = height_slider.value();
@@ -202,9 +204,8 @@
 
                dialog_restorer.restore();
                close_button.set_dirty(true);
-               if(close_button.process(mousex,mousey,left_button)) {
+               if (close_button.pressed())
                        break;
-               }
 
                players_slider.set_dirty();
                width_slider.set_dirty();
Index: wesnoth/src/multiplayer.cpp
diff -u wesnoth/src/multiplayer.cpp:1.125 wesnoth/src/multiplayer.cpp:1.126
--- wesnoth/src/multiplayer.cpp:1.125   Wed Oct 27 19:36:00 2004
+++ wesnoth/src/multiplayer.cpp Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: multiplayer.cpp,v 1.125 2004/10/27 19:36:00 gruikya Exp $ */
+/* $Id: multiplayer.cpp,v 1.126 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -84,21 +84,19 @@
        maps_menu_.assign(new gui::menu(disp_,map_options_));
        maps_menu_->set_numeric_keypress_selection(false);
 
-       SDL_Rect rect = {0,0,0,0};
-
-       turns_slider_.assign(new gui::slider(disp_,rect));
+       turns_slider_.assign(new gui::slider(disp_));
        turns_slider_->set_min(20);
        turns_slider_->set_max(100);
        turns_slider_->set_value(50);
        turns_slider_->set_help_string(_("The maximum turns the game will go 
for"));
 
-       village_gold_slider_.assign(new gui::slider(disp_,rect));
+       village_gold_slider_.assign(new gui::slider(disp_));
        village_gold_slider_->set_min(1);
        village_gold_slider_->set_max(5);
        village_gold_slider_->set_value(1);
        village_gold_slider_->set_help_string(_("The amount of income each 
village yields per turn"));
 
-       xp_modifier_slider_.assign(new gui::slider(disp_,rect));
+       xp_modifier_slider_.assign(new gui::slider(disp_));
        xp_modifier_slider_->set_min(25);
        xp_modifier_slider_->set_max(200);
        xp_modifier_slider_->set_value(100);
@@ -191,7 +189,7 @@
        maps_menu_->set_max_width(area.x + area.w - (xpos + minimap_width) - 
250);
        maps_menu_->set_max_height(area.y + area.h - (ypos + map_label_height));
        maps_menu_->set_items(map_options_);
-       maps_menu_->set_loc(xpos + minimap_width + border_size,ypos + 
map_label_height + border_size);
+       maps_menu_->set_location(xpos + minimap_width + border_size,ypos + 
map_label_height + border_size);
        maps_menu_->set_dirty();
 
        SDL_Rect rect;
@@ -252,7 +250,6 @@
 
        //Ally shared view settings
        vision_combo_->set_location(rect.x,rect.y);
-       vision_combo_->set_dirty();
 
        rect.y += vision_combo_->height() + border_size;
 
@@ -272,14 +269,10 @@
        
 
        regenerate_map_->set_location(rect.x,rect.y);
-       regenerate_map_->bg_backup();
-       regenerate_map_->set_dirty();
 
        rect.y += regenerate_map_->location().h + border_size;
 
        generator_settings_->set_location(rect.x,rect.y);
-       generator_settings_->bg_backup();
-       generator_settings_->set_dirty();
 
        //player amount number background
        SDL_Rect player_num_rect = {xpos+minimap_width/2 - 
30,ypos+minimap_width,100,25};
@@ -290,7 +283,6 @@
                                   era_rect.x,era_rect.y);
        
        era_combo_->set_location(era_rect.x+era_rect.w+border_size,era_rect.y);
-       era_combo_->set_dirty();
 
        SDL_Rect minimap_rect = {xpos,ypos,minimap_width,minimap_width};
        minimap_restorer_ = surface_restorer(&disp_.video(),minimap_rect);
@@ -302,19 +294,8 @@
 {
        CKey key;
 
-       int mousex, mousey;
-       const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
-       const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
-
        name_entry_->process();
-       turns_slider_->process();
-       village_gold_slider_->process();
-       xp_modifier_slider_->process();
-       era_combo_->process(mousex,mousey,left_button);
-       vision_combo_->process(mousex,mousey,left_button);
-       maps_menu_->process(mousex,mousey,left_button,
-                           key[SDLK_UP],key[SDLK_DOWN],
-                           key[SDLK_PAGEUP],key[SDLK_PAGEDOWN]);
+       maps_menu_->process();
 
        if(cancel_game_->pressed() || key[SDLK_ESCAPE]) 
                return lobby::QUIT;
@@ -327,13 +308,6 @@
                }
        }
 
-       fog_game_->pressed();
-       fog_game_->draw();
-       shroud_game_->pressed();
-       shroud_game_->draw();
-       observers_game_->pressed();
-       observers_game_->draw();
-
        events::raise_process_event();
        events::raise_draw_event();
 
Index: wesnoth/src/multiplayer_client.cpp
diff -u wesnoth/src/multiplayer_client.cpp:1.72 
wesnoth/src/multiplayer_client.cpp:1.73
--- wesnoth/src/multiplayer_client.cpp:1.72     Sun Oct 17 20:54:18 2004
+++ wesnoth/src/multiplayer_client.cpp  Sun Oct 31 20:50:13 2004
@@ -130,7 +130,7 @@
                
SDL_FillRect(disp_.video().getSurface(),&rect,SDL_MapRGB(disp_.video().getSurface()->format,0,0,0));
 
                menu_.assign(new gui::menu(disp_,details,false,area_.h/2));
-               menu_->set_loc(area_.x,area_.y);
+               menu_->set_location(area_.x,area_.y);
                menu_->set_width(area_.w);
        }
        
@@ -148,7 +148,7 @@
                cancel_button_.assign(new gui::button(disp_,_("Cancel")));
                cancel_button_->set_location(area.x+area.w - 
cancel_button_->width() - gui::ButtonHPadding,
                                                 area.y+area.h - 
cancel_button_->height() - gui::ButtonVPadding);
-               cancel_button_->draw();
+               events::raise_draw_event();
        }
 
        void clear_widgets() {
@@ -157,14 +157,11 @@
        }
 
        lobby::RESULT process() {
-               int mousex, mousey;
-               const bool button = 
SDL_GetMouseState(&mousex,&mousey)&SDL_BUTTON_LMASK;
-               if(cancel_button_->process(mousex,mousey,button)) {
+               if (cancel_button_->pressed())
                        return lobby::QUIT;
-               }
 
                if(menu_ != NULL) {
-                       
menu_->process(mousex,mousey,button,false,false,false,false);
+                       menu_->process();
                }
 
                config reply;
@@ -712,11 +709,7 @@
 
 void leader_preview_pane::process()
 {
-       int mousex, mousey;
-       const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
-       const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
-
-       if(leader_combo_.process(mousex, mousey, left_button)) {
+       if (leader_combo_.changed()) {
                set_dirty();
        }
 }
@@ -806,7 +799,6 @@
        selection_ = selection;
        leaders_.update_leader_list(selection_);
        set_dirty();
-       leader_combo_.set_dirty();
 }
 
 std::string leader_preview_pane::get_selected_leader()
Index: wesnoth/src/multiplayer_connect.cpp
diff -u wesnoth/src/multiplayer_connect.cpp:1.83 
wesnoth/src/multiplayer_connect.cpp:1.84
--- wesnoth/src/multiplayer_connect.cpp:1.83    Sun Oct 17 19:35:16 2004
+++ wesnoth/src/multiplayer_connect.cpp Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: multiplayer_connect.cpp,v 1.83 2004/10/17 19:35:16 silene Exp $ */
+/* $Id: multiplayer_connect.cpp,v 1.84 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -442,7 +442,8 @@
                r.y = top+55+(60*side_num);
                r.w = launch_.width()-5;
                r.h = launch_.height();
-               sliders_gold_.push_back(gui::slider(*disp_, r));
+               sliders_gold_.push_back(gui::slider(*disp_));
+               sliders_gold_.back().set_location(r);
                sliders_gold_.back().set_min(20);
                sliders_gold_.back().set_max(1000);
                sliders_gold_.back().set_increment(25);
@@ -582,10 +583,6 @@
 
        const config::child_itors sides = level_->child_range("side");
 
-       int mousex, mousey;
-       const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
-       const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
-
        bool start_game = false;
 
        bool level_changed = false;
@@ -597,23 +594,21 @@
                //Don't let user change this if a player is sitting
                combos_type_[n].enable(combos_type_[n].selected() < 4);
 
-               int old_select = combos_type_[n].selected();
-               if(combos_type_[n].process(mousex, mousey, left_button)) {
-                       if(combos_type_[n].selected() == 0) {
-                               side["controller"] = "network";
-                               side["description"] = "";
-                       } else if(combos_type_[n].selected() == 1){
+               if (combos_type_[n].changed()) {
+                       switch (combos_type_[n].selected()) {
+                       case 1:
                                side["controller"] = "human";
                                side["description"] = "";
-                       } else if(combos_type_[n].selected() == 2){
+                               break;
+                       case 2:
                                side["controller"] = "ai";
                                side["description"] = _("Computer Player");
-                       } else if(combos_type_[n].selected() == 3) {
+                               break;
+                       case 3:
                                side["controller"] = "null";
                                side["description"] = "";
-                       } else if(combos_type_[n].selected() == 4){
-                               combos_type_[n].set_selected(old_select);
-                       } else if(combos_type_[n].selected() == 5){
+                               break;
+                       case 5:
                                side["controller"] = "human";
                                side["description"] = preferences::login();
                                for(size_t m = 0; m != combos_type_.size(); 
++m) {
@@ -626,7 +621,11 @@
                                                }
                                        }
                                }
-                       }else{
+                               break;
+                       case 4:
+                               combos_type_[n].set_selected(0);
+                       case 0:
+                       default:
                                side["controller"] = "network";
                                side["description"] = "";
                        }
@@ -634,13 +633,12 @@
                        level_changed = true;
                }
 
-               if(combos_color_[n].process(mousex, mousey, left_button)) {
+               if (combos_color_[n].changed()) {
                        side["colour"] = 
lexical_cast_default<std::string>(combos_color_[n].selected()+1);
                }
 
                        
-               old_select = combos_race_[n].selected();
-               if(combos_race_[n].process(mousex, mousey, left_button)) {
+               if (combos_race_[n].changed()) {
                        const string_map& values =  
possible_sides[combos_race_[n].selected()]->values;
                        side["random_faction"] = "";
                        for(string_map::const_iterator i = values.begin(); i != 
values.end(); ++i) {
@@ -650,13 +648,11 @@
                        level_changed = true;
 
                        assert(!save_);
-                       if (combos_race_[n].selected() != old_select) {
                                
player_leaders_[n].update_leader_list(combos_race_[n].selected());
-                       }
                }
 
                //Player leader
-               if(combos_leader_[n].process(mousex, mousey, left_button)) {
+               if (combos_leader_[n].changed()) {
                        assert(!save_);
                        std::stringstream str;
                        str << (combos_team_[n].selected()+1);
@@ -665,18 +661,17 @@
                }
 
                //Player team
-               if(combos_team_[n].process(mousex, mousey, left_button)) {
+               if (combos_team_[n].changed()) {
                        std::stringstream str;
                        str << (combos_team_[n].selected()+1);
                        side["team_name"] = str.str();
                        level_changed = true;
                }
 
-               if(combos_color_[n].process(mousex, mousey, left_button)) {
+               if (combos_color_[n].changed()) {
                        level_changed = true;
                }
 
-               sliders_gold_[n].process();
                if(!save_){
                        const int cur_playergold = sliders_gold_[n].value();
                        std::stringstream playergold;
@@ -699,7 +694,7 @@
                }
        }
 
-       if(cancel_.process(mousex,mousey,left_button)) {
+       if (cancel_.pressed()) {
                if(network::nconnections() > 0) {
                        config cfg;
                        cfg.add_child("leave_game");
@@ -709,7 +704,7 @@
                return lobby::QUIT;
        }
 
-       if(ai_.process(mousex,mousey,left_button)) {
+       if (ai_.pressed()) {
                for(size_t m = 0; m != combos_team_.size(); ++m) {
                        config& si = **(sides.first+m);
                        si["controller"] = "ai";
@@ -721,7 +716,7 @@
 
        launch_.enable(is_full());
 
-       if(launch_.process(mousex,mousey,left_button)) {
+       if (launch_.pressed()) {
                const config::child_list& real_sides = 
era_cfg->get_children("multiplayer_side");
 
                for(config::child_iterator side = sides.first; side != 
sides.second; ++side) {
Index: wesnoth/src/multiplayer_lobby.cpp
diff -u wesnoth/src/multiplayer_lobby.cpp:1.46 
wesnoth/src/multiplayer_lobby.cpp:1.47
--- wesnoth/src/multiplayer_lobby.cpp:1.46      Sun Oct 31 15:21:03 2004
+++ wesnoth/src/multiplayer_lobby.cpp   Sun Oct 31 20:50:13 2004
@@ -214,9 +214,8 @@
                gui::menu users_menu(disp,users);
 
                // Set GUI locations
-               users_menu.set_loc(xscale(disp,856),yscale(disp,42));
                users_menu.set_width(xscale(disp,156));
-               users_menu.set_max_width(xscale(disp,156));
+               users_menu.set_location(xscale(disp,856),yscale(disp,42));
 
                
update_rect(xscale(disp,856),yscale(disp,42),xscale(disp,156),yscale(disp,708));
 
@@ -225,8 +224,8 @@
                                dlg->set_area(dlg_rect);
                        }
                } else {
-                       games_menu.set_loc(xscale(disp,12),yscale(disp,42));
                        games_menu.set_width(xscale(disp,832));
+                       
games_menu.set_location(xscale(disp,12),yscale(disp,42));
                }
 
                
update_rect(xscale(disp,12),yscale(disp,42),xscale(disp,832),yscale(disp,518));
@@ -276,9 +275,7 @@
                                        return res;
                                }
                        } else {
-                               games_menu.process(mousex,mousey,left_button,
-                                                  key[SDLK_UP],key[SDLK_DOWN],
-                                                  
key[SDLK_PAGEUP],key[SDLK_PAGEDOWN]);
+                               games_menu.process();
 
                                if(games_menu.selection() >= 0 && 
games_menu.selection() < int(game_vacant_slots.size())) {
                                        
join_game.hide(!game_vacant_slots[games_menu.selection()]);
@@ -286,9 +283,7 @@
                                }
                        }
 
-                       users_menu.process(mousex,mousey,left_button,
-                                          key[SDLK_UP],key[SDLK_DOWN],
-                                          key[SDLK_PAGEUP],key[SDLK_PAGEDOWN]);
+                       users_menu.process();
                         
                        const bool double_click = games_menu.double_clicked();
                        const bool observe = observe_game.pressed() || 
!games_available && double_click;
@@ -338,7 +333,7 @@
                                message_entry.clear();
                        }
 
-                       if(last_escape == false && key[SDLK_ESCAPE] || dlg == 
NULL && quit_game.process(mousex,mousey,left_button)){
+                       if(last_escape == false && key[SDLK_ESCAPE] || dlg == 
NULL && quit_game.pressed()){
                                return QUIT;
                        }
 
Index: wesnoth/src/preferences.cpp
diff -u wesnoth/src/preferences.cpp:1.118 wesnoth/src/preferences.cpp:1.119
--- wesnoth/src/preferences.cpp:1.118   Sun Oct 31 18:48:07 2004
+++ wesnoth/src/preferences.cpp Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: preferences.cpp,v 1.118 2004/10/31 18:48:07 gruikya Exp $ */
+/* $Id: preferences.cpp,v 1.119 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -615,9 +615,6 @@
 
 namespace {
 
-const SDL_Rect empty_rect = {0,0,0,0};
-const SDL_Rect preferences_dialog_area = {-400,-400,400,400};
-
 class preferences_dialog : public gui::preview_pane
 {
 public:
@@ -636,9 +633,10 @@
 private:
 
        void draw();
-       void process();
+       void process_event();
        bool left_side() const { return false; }
        void set_selection(int index);
+       void set_location(SDL_Rect const &rect);
 
        gui::slider music_slider_, sound_slider_, scroll_slider_, gamma_slider_;
        gui::button fullscreen_button_, turbo_button_, show_ai_moves_button_,
@@ -652,9 +650,10 @@
        TAB tab_;
 };
 
-preferences_dialog::preferences_dialog(display& disp) : 
gui::preview_pane(disp),
-music_slider_(disp,empty_rect), sound_slider_(disp,empty_rect),
-scroll_slider_(disp,empty_rect), gamma_slider_(disp,empty_rect),
+preferences_dialog::preferences_dialog(display& disp)
+       : gui::preview_pane(disp),
+         music_slider_(disp), sound_slider_(disp),
+         scroll_slider_(disp), gamma_slider_(disp),
 fullscreen_button_(disp,_("Full Screen"),gui::button::TYPE_CHECK),
 turbo_button_(disp,_("Accelerated Speed"),gui::button::TYPE_CHECK),
 show_ai_moves_button_(disp,_("Skip AI Moves"),gui::button::TYPE_CHECK),
@@ -672,7 +671,8 @@
 scroll_label_(_("Scroll Speed:")), gamma_label_(_("Gamma:")),
 slider_label_width_(0), tab_(GENERAL_TAB)
 {
-       set_location(preferences_dialog_area);
+       set_width(400);
+       set_height(400);
 
        slider_label_width_ = 
maximum<size_t>(font::text_area(music_label_,font::SIZE_NORMAL).w,
                              
maximum<size_t>(font::text_area(sound_label_,font::SIZE_NORMAL).w,
@@ -736,62 +736,84 @@
        hotkeys_button_.set_help_string(_("View and configure keyboard 
shortcuts"));
 }
 
-void preferences_dialog::process()
+void preferences_dialog::set_location(SDL_Rect const &rect)
 {
-       if(turbo_button_.pressed()) {
-               set_turbo(turbo_button_.checked());
-       }
+       widget::set_location(rect);
+       register_rectangle(rect);
+       const int border = 10;
 
-       if(show_ai_moves_button_.pressed()) {
-               set_show_ai_moves(!show_ai_moves_button_.checked());
-       }
+       // General tab
+       int ypos = rect.y;
+       SDL_Rect scroll_rect = { rect.x + slider_label_width_, ypos,
+                                rect.w - slider_label_width_ - border, 0 };
+       scroll_slider_.set_location(scroll_rect);
+       ypos += 50; turbo_button_.set_location(rect.x, ypos);
+       ypos += 50; show_ai_moves_button_.set_location(rect.x, ypos);
+       ypos += 50; turn_dialog_button_.set_location(rect.x, ypos);
+       ypos += 50; turn_bell_button_.set_location(rect.x, ypos);
+       ypos += 50; show_team_colours_button_.set_location(rect.x, ypos);
+       ypos += 50; show_grid_button_.set_location(rect.x, ypos);
+       ypos += 50; hotkeys_button_.set_location(rect.x, ypos);
+
+       // Display tab
+       ypos = rect.y;
+       gamma_button_.set_location(rect.x, ypos);
+       ypos += 50;
+       SDL_Rect gamma_rect = { rect.x + slider_label_width_, ypos,
+                               rect.w - slider_label_width_ - border, 0 };
+       gamma_slider_.set_location(gamma_rect);
+       ypos += 50; show_floating_labels_button_.set_location(rect.x, ypos);
+       ypos += 50; show_colour_cursors_button_.set_location(rect.x, ypos);
+       ypos += 50; show_haloing_button_.set_location(rect.x, ypos);
+       ypos += 50; fullscreen_button_.set_location(rect.x, ypos);
+       ypos += 50; video_mode_button_.set_location(rect.x, ypos);
+
+       // Sound tab
+       ypos = rect.y;
+       SDL_Rect music_rect = { rect.x + slider_label_width_, ypos,
+                               rect.w - slider_label_width_ - border, 0 };
+       music_slider_.set_location(music_rect);
+       ypos += 50;
+       SDL_Rect sound_rect = { rect.x + slider_label_width_, ypos,
+                               rect.w - slider_label_width_ - border, 0 };
+       sound_slider_.set_location(sound_rect);
 
-       if(show_grid_button_.pressed()) {
-               set_grid(show_grid_button_.checked());
-       }
+       set_selection(tab_);
+}
 
-       if(show_floating_labels_button_.pressed()) {
+void preferences_dialog::process_event()
+{
+       if (turbo_button_.pressed())
+               set_turbo(turbo_button_.checked());
+       if (show_ai_moves_button_.pressed())
+               set_show_ai_moves(!show_ai_moves_button_.checked());
+       if (show_grid_button_.pressed())
+               set_grid(show_grid_button_.checked());
+       if (show_floating_labels_button_.pressed())
                
set_show_floating_labels(show_floating_labels_button_.checked());
-       }
-
-       if(video_mode_button_.pressed()) {
+       if (video_mode_button_.pressed())
                throw 
video_mode_change_exception(video_mode_change_exception::CHANGE_RESOLUTION);
-       }
-
-       if(fullscreen_button_.pressed()) {
-               throw video_mode_change_exception(fullscreen_button_.checked() 
? video_mode_change_exception::MAKE_FULLSCREEN
-                                                                              
: video_mode_change_exception::MAKE_WINDOWED);
-       }
-
-       if(turn_bell_button_.pressed()) {
+       if (fullscreen_button_.pressed())
+               throw video_mode_change_exception(fullscreen_button_.checked()
+                                                 ? 
video_mode_change_exception::MAKE_FULLSCREEN
+                                                 : 
video_mode_change_exception::MAKE_WINDOWED);
+       if (turn_bell_button_.pressed())
                set_turn_bell(turn_bell_button_.checked());
-       }
-
-       if(turn_dialog_button_.pressed()) {
+       if (turn_dialog_button_.pressed())
                set_turn_dialog(turn_dialog_button_.checked());
-       }
-
-       if(show_team_colours_button_.pressed()) {
+       if (show_team_colours_button_.pressed())
                set_show_side_colours(show_team_colours_button_.checked());
-       }
-
-       if(hotkeys_button_.pressed()) {
+       if (hotkeys_button_.pressed())
                show_hotkeys_dialog(disp());
-       }
-
-       if(show_colour_cursors_button_.pressed()) {
+       if (show_colour_cursors_button_.pressed())
                set_colour_cursors(show_colour_cursors_button_.checked());
-       }
-
-       if(show_haloing_button_.pressed()) {
+       if (show_haloing_button_.pressed())
                set_show_haloes(show_haloing_button_.checked());
-       }
-
-       if(gamma_button_.pressed()) {
+       if (gamma_button_.pressed()) {
                set_adjust_gamma(gamma_button_.checked());
-               set_selection(int(tab_));
+               gamma_slider_.hide(!adjust_gamma());
+               // we need a textlabel widget so that we can deal with the 
"gamma" text
        }
-
        set_sound_volume(sound_slider_.value());
        set_music_volume(music_slider_.value());
        set_scroll_speed(scroll_slider_.value());
@@ -800,96 +822,17 @@
 
 void preferences_dialog::draw()
 {
-       if(!dirty()) {
+       if (!dirty())
                return;
-       }
-
-       bg_restore();
-
-       music_slider_.set_dirty();
-       sound_slider_.set_dirty();
-       scroll_slider_.set_dirty();
-       gamma_slider_.set_dirty();
-       fullscreen_button_.set_dirty();
-       turbo_button_.set_dirty();
-       show_ai_moves_button_.set_dirty();
-       show_grid_button_.set_dirty();
-       show_floating_labels_button_.set_dirty();
-       turn_dialog_button_.set_dirty();
-       turn_bell_button_.set_dirty();
-       show_team_colours_button_.set_dirty();
-       show_colour_cursors_button_.set_dirty();
-       show_haloing_button_.set_dirty();
-       video_mode_button_.set_dirty();
-       hotkeys_button_.set_dirty();
-       gamma_button_.set_dirty();
-
-       const int border = 10;
-
-       int ypos = location().y;
-       if(tab_ == GENERAL_TAB) {
-               
font::draw_text(&disp(),location(),font::SIZE_NORMAL,font::NORMAL_COLOUR,scroll_label_,location().x,ypos);
-               const SDL_Rect scroll_rect = {location().x + 
slider_label_width_,ypos,location().w - slider_label_width_ - 
border,scroll_slider_.location().h};
-               scroll_slider_.set_location(scroll_rect);
-
-               ypos += 50;
-               turbo_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               show_ai_moves_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               turn_dialog_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               turn_bell_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               show_team_colours_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               show_grid_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               hotkeys_button_.set_location(location().x,ypos);
-
-       } else if(tab_ == DISPLAY_TAB) {
-               gamma_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-
-               if(adjust_gamma()) {
-                       
font::draw_text(&disp(),location(),font::SIZE_NORMAL,font::NORMAL_COLOUR,gamma_label_,location().x,ypos);
-               }
-
-               const SDL_Rect gamma_rect = {location().x + 
slider_label_width_,ypos,location().w - slider_label_width_ - 
border,gamma_slider_.location().h};
-               gamma_slider_.set_location(gamma_rect);
-
-               ypos += 50;
-               show_floating_labels_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               show_colour_cursors_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               show_haloing_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               fullscreen_button_.set_location(location().x,ypos);
-
-               ypos += 50;
-               video_mode_button_.set_location(location().x,ypos);
 
+       SDL_Rect const &loc = location();
+       if (tab_ == GENERAL_TAB) {
+               font::draw_text(&disp(), loc, font::SIZE_NORMAL, 
font::NORMAL_COLOUR, scroll_label_, loc.x, loc.y);
+       } else if (tab_ == DISPLAY_TAB && adjust_gamma()) {
+               font::draw_text(&disp(), loc, font::SIZE_NORMAL, 
font::NORMAL_COLOUR, gamma_label_, loc.x, loc.y + 50);
        } else if(tab_ == SOUND_TAB) {
-               
font::draw_text(&disp(),location(),font::SIZE_NORMAL,font::NORMAL_COLOUR,music_label_,location().x,ypos);
-               const SDL_Rect music_rect = {location().x + 
slider_label_width_,ypos,location().w - slider_label_width_ - 
border,music_slider_.location().h};
-               music_slider_.set_location(music_rect);
-
-               ypos += 50;
-
-               
font::draw_text(&disp(),location(),font::SIZE_NORMAL,font::NORMAL_COLOUR,sound_label_,location().x,ypos);
-               const SDL_Rect sound_rect = {location().x + 
slider_label_width_,ypos,location().w - slider_label_width_ - 
border,sound_slider_.location().h};
-               sound_slider_.set_location(sound_rect);
+               font::draw_text(&disp(), loc, font::SIZE_NORMAL, 
font::NORMAL_COLOUR, music_label_, loc.x, loc.y);
+               font::draw_text(&disp(), loc, font::SIZE_NORMAL, 
font::NORMAL_COLOUR, sound_label_, loc.x, loc.y + 50);
        }
 
        set_dirty(false);
@@ -899,11 +842,9 @@
 {
        tab_ = TAB(index);
        set_dirty();
+       bg_restore();
 
        scroll_slider_.hide(tab_ != GENERAL_TAB);
-       gamma_slider_.hide(tab_ != DISPLAY_TAB || !adjust_gamma());
-       music_slider_.hide(tab_ != SOUND_TAB);
-       sound_slider_.hide(tab_ != SOUND_TAB);
        turbo_button_.hide(tab_ != GENERAL_TAB);
        show_ai_moves_button_.hide(tab_ != GENERAL_TAB);
        turn_dialog_button_.hide(tab_ != GENERAL_TAB);
@@ -912,13 +853,17 @@
        show_team_colours_button_.hide(tab_ != GENERAL_TAB);
        show_grid_button_.hide(tab_ != GENERAL_TAB);
 
+       gamma_slider_.hide(tab_ != DISPLAY_TAB || !adjust_gamma());
        gamma_button_.hide(tab_ != DISPLAY_TAB);
        show_floating_labels_button_.hide(tab_ != DISPLAY_TAB);
        show_colour_cursors_button_.hide(tab_ != DISPLAY_TAB);
        show_haloing_button_.hide(tab_ != DISPLAY_TAB);
        fullscreen_button_.hide(tab_ != DISPLAY_TAB);
        video_mode_button_.hide(tab_ != DISPLAY_TAB);
-}                                          
+
+       music_slider_.hide(tab_ != SOUND_TAB);
+       sound_slider_.hide(tab_ != SOUND_TAB);
+}
 
 }
 
@@ -1063,9 +1008,9 @@
                menu_items.push_back (str.str ());
        }
 
-       gui::menu menu_ (disp, menu_items, false, height);
+       gui::menu menu_(disp, menu_items, false, height);
        menu_.set_width(400);   
-       menu_.set_loc (xpos + 20, ypos);
+       menu_.set_location(xpos + 20, ypos);
        
        gui::button change_button (disp, _("Change Hotkey"));
        change_button.set_location(xpos + width - change_button.width () 
-30,ypos + 80);
@@ -1073,28 +1018,12 @@
        gui::button save_button (disp, _("Save Hotkeys"));
        save_button.set_location(xpos + width - save_button.width () - 30,ypos 
+ 130);
 
-       bool redraw_all = true;
-
        for(;;) {
 
-               int mousex, mousey;
-               const int mouse_flags = SDL_GetMouseState (&mousex, &mousey);
-               const bool left_button = mouse_flags & SDL_BUTTON_LMASK;
-
-               if(redraw_all) {
-                       menu_.redraw();
-                       close_button.draw ();
-                       change_button.draw();
-                       save_button.draw();
-                                               
-                       redraw_all = false;
-               };
-
-               if(close_button.process (mousex, mousey, left_button)) {
+               if (close_button.pressed())
                        break;
-               }
 
-               if(change_button.process (mousex, mousey, left_button)) {
+               if (change_button.pressed ()) {
                        // Lets change this hotkey......
                        SDL_Rect dlgr = {centerx-text_size.w/2-30,
                                                                
centery-text_size.h/2 - 16,
@@ -1140,21 +1069,16 @@
 
                                menu_.change_item(menu_.selection(), 2, 
newhk.get_name());
                        };
-                       redraw_all = true;
                }
-               if (save_button.process(mousex, mousey, left_button))
-               {
+               if (save_button.pressed()) {
                        if (save_config == NULL) {
                                hotkey::save_hotkeys(prefs);
-                       }
-                       else {
+                       } else {
                                hotkey::save_hotkeys(*save_config);
                        }
-                       redraw_all = true;
                }
 
-               menu_.process(mousex, mousey, left_button, false,
-                              false, false, false);
+               menu_.process();
 
                events::pump();
                events::raise_process_event();
Index: wesnoth/src/sdl_utils.cpp
diff -u wesnoth/src/sdl_utils.cpp:1.61 wesnoth/src/sdl_utils.cpp:1.62
--- wesnoth/src/sdl_utils.cpp:1.61      Sat Oct 30 13:18:04 2004
+++ wesnoth/src/sdl_utils.cpp   Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: sdl_utils.cpp,v 1.61 2004/10/30 13:18:04 gruikya Exp $ */
+/* $Id: sdl_utils.cpp,v 1.62 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -34,6 +34,16 @@
               point_in_rect(rect1.x,rect1.y+rect1.h,rect2) || 
point_in_rect(rect1.x+rect1.w,rect1.y+rect1.h,rect2);
 }
 
+SDL_Rect intersect_rects(SDL_Rect const &rect1, SDL_Rect const &rect2)
+{
+       SDL_Rect res;
+       res.x = maximum(rect1.x, rect2.x);
+       res.y = maximum(rect1.y, rect2.y);
+       res.w = maximum<int>(minimum<int>(rect1.x + rect1.w, rect2.x + rect2.w) 
- res.x, 0);
+       res.h = maximum<int>(minimum<int>(rect1.y + rect1.h, rect2.y + rect2.h) 
- res.y, 0);
+       return res;
+}
+
 bool operator<(const surface& a, const surface& b)
 {
        return a.get() < b.get();
@@ -846,12 +856,27 @@
        restore();
 }
 
-void surface_restorer::restore()
+void surface_restorer::restore(SDL_Rect const &dst) const
 {
-       if(surface_ != NULL) {
-               SDL_BlitSurface(surface_,NULL,target_->getSurface(),&rect_);
-               update_rect(rect_);
-       }
+       if (surface_.null())
+               return;
+       SDL_Rect dst2 = intersect_rects(dst, rect_);
+       if (dst2.w == 0 || dst2.h == 0)
+               return;
+       SDL_Rect src = dst2;
+       src.x -= rect_.x;
+       src.y -= rect_.y;
+       SDL_BlitSurface(surface_, &src, target_->getSurface(), &dst2);
+       update_rect(dst2);
+}
+
+void surface_restorer::restore() const
+{
+       if (surface_.null())
+               return;
+       SDL_Rect dst = rect_;
+       SDL_BlitSurface(surface_, NULL, target_->getSurface(), &dst);
+       update_rect(rect_);
 }
 
 void surface_restorer::update()
Index: wesnoth/src/sdl_utils.hpp
diff -u wesnoth/src/sdl_utils.hpp:1.47 wesnoth/src/sdl_utils.hpp:1.48
--- wesnoth/src/sdl_utils.hpp:1.47      Sat Oct 30 13:18:04 2004
+++ wesnoth/src/sdl_utils.hpp   Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: sdl_utils.hpp,v 1.47 2004/10/30 13:18:04 gruikya Exp $ */
+/* $Id: sdl_utils.hpp,v 1.48 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -33,8 +33,8 @@
 #endif
 
 bool point_in_rect(int x, int y, const SDL_Rect& rect);
-
 bool rects_overlap(const SDL_Rect& rect1, const SDL_Rect& rect2);
+SDL_Rect intersect_rects(SDL_Rect const &rect1, SDL_Rect const &rect2);
 
 struct surface
 {
@@ -184,7 +184,8 @@
        surface_restorer(class CVideo* target, const SDL_Rect& rect);
        ~surface_restorer();
 
-       void restore();
+       void restore() const;
+       void restore(SDL_Rect const &dst) const;
        void update();
        void cancel();
 
Index: wesnoth/src/show_dialog.cpp
diff -u wesnoth/src/show_dialog.cpp:1.99 wesnoth/src/show_dialog.cpp:1.100
--- wesnoth/src/show_dialog.cpp:1.99    Wed Oct 27 19:28:07 2004
+++ wesnoth/src/show_dialog.cpp Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: show_dialog.cpp,v 1.99 2004/10/27 19:28:07 gruikya Exp $ */
+/* $Id: show_dialog.cpp,v 1.100 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -682,7 +682,7 @@
        const int menu_xpos = xloc+image_width+left_padding+image_h_padding;
        const int menu_ypos = 
yloc+top_padding+text_and_image_height+menu_hpadding+ (use_textbox ? 
text_widget.location().h + top_padding : 0);
        if(menu_.height() > 0) {
-               menu_.set_loc(menu_xpos,menu_ypos);
+               menu_.set_location(menu_xpos,menu_ypos);
        }
 
        if(image != NULL) {
@@ -751,12 +751,6 @@
                const bool new_page_up = key[SDLK_PAGEUP];
                const bool new_page_down = key[SDLK_PAGEDOWN];
 
-               int select_item = -1;
-               for(int item = 0; item != 10; ++item) {
-                       if(key['1' + item])
-                               select_item = item;
-               }
-
                if((!key_down && key[SDLK_RETURN] || menu_.double_clicked()) &&
                   (type == YES_NO || type == OK_CANCEL || type == OK_ONLY || 
type == CLOSE_ONLY)) {
 
@@ -806,12 +800,7 @@
                first_time = false;
 
                if(menu_.height() > 0) {
-                       const int res = 
menu_.process(mousex,mousey,new_left_button,
-                                                     !up_arrow && new_up_arrow,
-                                                     !down_arrow && 
new_down_arrow,
-                                                     !page_up && new_page_up,
-                                                     !page_down && 
new_page_down,
-                                                     select_item);
+                       const int res = menu_.process();
                        if(res != -1)
                        {
                                return res;     
@@ -863,8 +852,7 @@
                }
 
                for(unsigned int n = 0; n != check_buttons.size(); ++n) {
-                       const bool pressed = 
check_buttons[n].process(mousex,mousey,left_button);
-                       check_buttons[n].draw();
+                       const bool pressed = check_buttons[n].pressed();
 
                        if(options != NULL && n < options->size()) {
                                (*options)[n].checked = 
check_buttons[n].checked();
Index: wesnoth/src/widgets/button.cpp
diff -u wesnoth/src/widgets/button.cpp:1.44 wesnoth/src/widgets/button.cpp:1.45
--- wesnoth/src/widgets/button.cpp:1.44 Sat Oct 30 11:24:27 2004
+++ wesnoth/src/widgets/button.cpp      Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: button.cpp,v 1.44 2004/10/30 11:24:27 gruikya Exp $ */
+/* $Id: button.cpp,v 1.45 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -28,10 +28,10 @@
 const int vertical_padding = font::SIZE_SMALL / 2;
 
 button::button(display& disp, const std::string& label, button::TYPE type,
-               std::string button_image_name, SPACE_CONSUMPTION spacing) :
-                          widget(disp), label_(label), display_(&disp),
-                         image_(NULL), pressedImage_(NULL), 
activeImage_(NULL), pressedActiveImage_(NULL),
-                          button_(true), state_(NORMAL), type_(type), 
enabled_(true), pressed_(false)
+               std::string button_image_name, SPACE_CONSUMPTION spacing)
+       : widget(disp), label_(label),
+         image_(NULL), pressedImage_(NULL), activeImage_(NULL), 
pressedActiveImage_(NULL),
+         button_(true), state_(NORMAL), type_(type), enabled_(true), 
pressed_(false)
 {
        set_label(label);
 
@@ -101,10 +101,21 @@
        }
 }
 
+void button::set_location(SDL_Rect const &rect)
+{
+       widget::set_location(rect);
+       register_rectangle(rect);
+}
+
 void button::set_check(bool check)
 {
-       if(type_ == TYPE_CHECK)
-               state_ = check ? PRESSED : NORMAL;
+       if (type_ != TYPE_CHECK)
+               return;
+       STATE new_state = check ? PRESSED : NORMAL;
+       if (state_ != new_state) {
+               state_ = new_state;
+               set_dirty();
+       }
 }
 
 bool button::checked() const
@@ -114,9 +125,9 @@
 
 void button::enable(bool new_val)
 {
-       if(enabled_ != new_val) {
+       if (enabled_ != new_val) {
                enabled_ = new_val;
-               set_dirty(true);
+               set_dirty();
        }
 }
 
@@ -127,52 +138,50 @@
 
 void button::draw()
 {
-       if(location().x == 0 && location().y == 0 || hidden() || !dirty()) {
+       if (hidden() || !dirty())
                return;
-       }
 
-       if(type_ == TYPE_CHECK) {
+       if (type_ == TYPE_CHECK)
                bg_restore();
-       }
 
        surface image = image_;
        const int image_w = image_->w;
        
        int offset = 0;
        switch(state_) {
-               case ACTIVE: image = activeImage_;
-                            break;
-               case PRESSED: image = pressedImage_;
-                                 if(type_ == TYPE_PRESS) { offset = 1; }
-                                 break;
-               case PRESSED_ACTIVE: image = pressedActiveImage_;
-                                    break;
-               case NORMAL:
-               default: break;
+       case ACTIVE:
+               image = activeImage_;
+               break;
+       case PRESSED:
+               image = pressedImage_;
+               if (type_ == TYPE_PRESS)
+                       offset = 1;
+               break;
+       case PRESSED_ACTIVE:
+               image = pressedActiveImage_;
+               break;
+       default:
+               break;
        }
 
-       const SDL_Rect clipArea = display_->screen_area();
-       const int texty = location().y + location().h/2 - textRect_.h/2 + 
offset;
+       SDL_Rect const &clipArea = disp().screen_area();
+       SDL_Rect const &loc = location();
+       const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset;
        int textx;
 
-       if(type_ == TYPE_PRESS) {
-               textx = location().x + image->w/2 - textRect_.w/2 + offset;
-       } else {
-               textx = location().x + image_w + checkbox_horizontal_padding/2;
-       }
-
-       surface greyed_image(NULL);
-       if(!enabled_) {
-               greyed_image.assign(greyscale_image(image));
-               image = greyed_image;
-       }
+       if (type_ != TYPE_CHECK)
+               textx = loc.x + image->w / 2 - textRect_.w / 2 + offset;
+       else
+               textx = loc.x + image_w + checkbox_horizontal_padding / 2;
+  
+       if (!enabled_)
+               image = greyscale_image(image);
 
-       display_->blit_surface(location().x,location().y,image);
+       disp().blit_surface(loc.x, loc.y, image);
        const std::string etext = font::make_text_ellipsis(label_, font_size, 
width());
-       font::draw_text(display_,clipArea,font_size,
-                                       font::BUTTON_COLOUR,etext,textx,texty);
+       font::draw_text(&disp(), clipArea, font_size, font::BUTTON_COLOUR, 
etext, textx, texty);
 
-       update_rect(location());
+       update_rect(loc);
 
        set_dirty(false);
 }
@@ -199,7 +208,7 @@
                }
        }
 
-       textRect_ = display_->screen_area();
+       textRect_ = disp().screen_area();
        const std::string etext = font::make_text_ellipsis(label_, font_size, 
width());
        textRect_ = font::draw_text(NULL,textRect_,font_size,
                                    font::BUTTON_COLOUR,etext,0,0);
@@ -207,53 +216,53 @@
        set_dirty(true);
 }
 
-void button::mouse_motion(const SDL_MouseMotionEvent& event)
+void button::mouse_motion(SDL_MouseMotionEvent const &event)
 {
-       const bool is_hit = hit(event.x,event.y);
-
-       if(state_ == NORMAL && is_hit) {
-               state_ = ACTIVE;
-       } else if(state_ == PRESSED && is_hit && type_ == TYPE_CHECK) {
-               state_ = PRESSED_ACTIVE;
-       } else if(state_ == ACTIVE && !is_hit) {
-               state_ = NORMAL;
-       } else if(state_ == PRESSED_ACTIVE && !is_hit) {
-               state_ = PRESSED;
-       } else if(state_ == PRESSED && !is_hit && type_ == TYPE_PRESS) {
-               state_ = NORMAL;
+       if (hit(event.x, event.y)) {
+               // the cursor is over the widget
+               if (state_ == NORMAL)
+                       state_ = ACTIVE;
+               else if (state_ == PRESSED && type_ == TYPE_CHECK)
+                       state_ = PRESSED_ACTIVE;
+       } else {
+               // the cursor is not over the widget
+               if (state_ == PRESSED_ACTIVE)
+                       state_ = PRESSED;
+               else
+                       state_ = NORMAL;
        }
 }
 
-void button::mouse_down(const SDL_MouseButtonEvent& event)
+void button::mouse_down(SDL_MouseButtonEvent const &event)
 {
-       const bool is_hit = hit(event.x,event.y);
-       if(is_hit && type_ == TYPE_PRESS) {
+       if (hit(event.x, event.y) && event.button == SDL_BUTTON_LEFT && type_ 
!= TYPE_CHECK)
                state_ = PRESSED;
-       }
 }
 
-void button::mouse_up(const SDL_MouseButtonEvent& event)
+void button::mouse_up(SDL_MouseButtonEvent const &event)
 {
-       const bool is_hit = hit(event.x,event.y);
-       if(is_hit && type_ == TYPE_CHECK) {
-               if(state_ == ACTIVE) {
-                       state_ = PRESSED_ACTIVE;
-               } else {
-                       state_ = ACTIVE;
-               }
-
+       if (!(hit(event.x, event.y) && event.button == SDL_BUTTON_LEFT))
+               return;
+       // the user has stopped pressing the mouse left button while on the 
widget
+       switch (type_) {
+       case TYPE_CHECK:
+               state_ = state_ == ACTIVE ? PRESSED_ACTIVE : ACTIVE;
                pressed_ = true;
-       } else if(is_hit && type_ == TYPE_PRESS && state_ == PRESSED) {
+               break;
+       case TYPE_PRESS:
                state_ = ACTIVE;
                pressed_ = true;
+               break;
+       case TYPE_TURBO:
+               state_ = ACTIVE;
+               break;
        }
 }
 
 void button::handle_event(const SDL_Event& event)
 {
-       if(hidden() || !enabled_) {
+       if (hidden() || !enabled_)
                return;
-       }
 
        STATE start_state = state_;
 
@@ -267,23 +276,22 @@
        case SDL_MOUSEMOTION:
                mouse_motion(event.motion);
                break;
+       default:
+               return;
        }
 
-       if(start_state != state_) {
+       if (start_state != state_)
                set_dirty(true);
-       }
-}
-
-bool button::process(int mousex, int mousey, bool button)
-{
-       return pressed();
 }
 
 bool button::pressed()
 {
-       const bool res = pressed_;
-       pressed_ = false;
-       return res;
+       if (type_ != TYPE_TURBO) {
+               const bool res = pressed_;
+               pressed_ = false;
+               return res;
+       } else
+               return state_ == PRESSED || state_ == PRESSED_ACTIVE;
 }
 
 }
Index: wesnoth/src/widgets/button.hpp
diff -u wesnoth/src/widgets/button.hpp:1.26 wesnoth/src/widgets/button.hpp:1.27
--- wesnoth/src/widgets/button.hpp:1.26 Sun Jul 18 19:02:25 2004
+++ wesnoth/src/widgets/button.hpp      Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: button.hpp,v 1.26 2004/07/18 19:02:25 gruikya Exp $ */
+/* $Id: button.hpp,v 1.27 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -32,7 +32,7 @@
 public:
        struct error {};
 
-       enum TYPE { TYPE_PRESS, TYPE_CHECK };
+       enum TYPE { TYPE_PRESS, TYPE_CHECK, TYPE_TURBO };
 
        enum SPACE_CONSUMPTION { DEFAULT_SPACE, MINIMUM_SPACE };
 
@@ -40,15 +40,14 @@
               std::string button_image="", SPACE_CONSUMPTION 
spacing=DEFAULT_SPACE);
 
        virtual ~button() {}
+       virtual void set_location(SDL_Rect const &rect);
+       using widget::set_location;
 
        void set_check(bool check);
        bool checked() const;
 
-       void draw();
-
        void set_label(const std::string& val);
 
-       bool process(int mousex, int mousey, bool button);
        bool pressed();
 
        void enable(bool new_val);
@@ -59,11 +58,11 @@
        virtual void mouse_motion(const SDL_MouseMotionEvent& event);
        virtual void mouse_down(const SDL_MouseButtonEvent& event);
        virtual void mouse_up(const SDL_MouseButtonEvent& event);
+       virtual void draw();
 
 private:
 
        std::string label_;
-       display* display_;
        surface image_, pressedImage_, activeImage_, pressedActiveImage_;
        SDL_Rect textRect_;
 
Index: wesnoth/src/widgets/combo.cpp
diff -u wesnoth/src/widgets/combo.cpp:1.22 wesnoth/src/widgets/combo.cpp:1.23
--- wesnoth/src/widgets/combo.cpp:1.22  Wed Oct 27 20:42:37 2004
+++ wesnoth/src/widgets/combo.cpp       Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: combo.cpp,v 1.22 2004/10/27 20:42:37 gruikya Exp $ */
+/* $Id: combo.cpp,v 1.23 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -22,75 +22,49 @@
 const int horizontal_padding = 10;
 const int vertical_padding = 10;
 
-combo::combo(display& disp, const std::vector<std::string>& items) :
-               items_(items), selected_(0), display_(&disp),
-               button_(gui::button(disp, items.empty() ? "" : items[0]))
+combo::combo(display& disp, const std::vector<std::string>& items)
+       : button(disp, items.empty() ? "" : items[0]),
+         items_(items), selected_(0), oldSelected_(0)
 {
 }
 
-int combo::height() const
-{
-       return button_.height();
-}
-
-int combo::width() const
-{
-       return button_.width();
-}
-
-void combo::set_width(int new_width)
-{
-       button_.set_width(new_width);
-}
-
 int combo::selected() const
 {
        return selected_;
 }
 
-void combo::set_items(const std::vector<std::string>& items)
+bool combo::changed()
 {
-       items_ = items;
+       if (oldSelected_ != selected_) {
+               oldSelected_ = selected_;
+               return true;
+       } else
+               return false;
 }
 
-void combo::set_location(int x, int y)
+void combo::set_items(const std::vector<std::string>& items)
 {
-       button_.set_location(x,y);
+       items_ = items;
 }
 
 void combo::set_selected(int val)
 {
        const size_t index = size_t(val);
-       if(index < items_.size()) {
-               button_.set_label(items_[index]);
-               selected_ = val;
-               button_.draw();
-       }
+       if (val == selected_ || index >= items_.size())
+               return;
+       set_label(items_[index]);
+       oldSelected_ = selected_;
+       selected_ = val;
 }
 
-void combo::draw()
-{
-       button_.draw();
+void combo::process_event()
+{
+       if (!pressed())
+               return;
+       SDL_Rect const &loc = location();
+       set_selected(gui::show_dialog(disp(), NULL, "", "",
+                       gui::MESSAGE, &items_, NULL, "", NULL, -1, NULL, NULL,
+                       loc.x, loc.y + loc.h));
 }
 
-bool combo::process(int x, int y, bool button)
-{
-       if(button_.process(x,y,button)) {
-               const SDL_Rect rect = button_.location();
-               set_selected(gui::show_dialog(*display_,NULL,"","",
-                                       
gui::MESSAGE,&items_,NULL,"",NULL,-1,NULL,NULL,
-                                       rect.x,rect.y+rect.h));
-               
-               button_.draw();
-
-               return true;
-       }
-
-       return false;
-}
-
-void combo::enable(bool new_val) { button_.enable(new_val); }
-
-bool combo::enabled() const { return button_.enabled(); }
-
 }
Index: wesnoth/src/widgets/combo.hpp
diff -u wesnoth/src/widgets/combo.hpp:1.17 wesnoth/src/widgets/combo.hpp:1.18
--- wesnoth/src/widgets/combo.hpp:1.17  Sun Aug 29 23:28:26 2004
+++ wesnoth/src/widgets/combo.hpp       Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: combo.hpp,v 1.17 2004/08/29 23:28:26 Sirp Exp $ */
+/* $Id: combo.hpp,v 1.18 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -20,35 +20,22 @@
 
 namespace gui {
 
-class combo
+class combo : public button
 {
 public:
        combo(display& disp, const std::vector<std::string>& items);
-       void draw();
 
-       void set_location(int valx, int valy);
-       void set_width(int new_width);
        void set_selected(int val);
        void set_items(const std::vector<std::string>& items);
-
-       int width() const;
-       int height() const;
        int selected() const;
+       bool changed();
 
-       bool process(int mousex, int mousey, bool button);
-
-       void enable(bool new_val);
-       bool enabled() const;
-
-       void set_dirty() { button_.set_dirty(); }
+protected:
+       virtual void process_event();
 
 private:
        std::vector<std::string> items_;
-       int selected_;
-       display *display_;
-       gui::button button_;
-
-
+       int selected_, oldSelected_;
 }; //end class combo
 
 }
Index: wesnoth/src/widgets/file_chooser.cpp
diff -u wesnoth/src/widgets/file_chooser.cpp:1.7 
wesnoth/src/widgets/file_chooser.cpp:1.8
--- wesnoth/src/widgets/file_chooser.cpp:1.7    Mon Sep 27 00:24:42 2004
+++ wesnoth/src/widgets/file_chooser.cpp        Sun Oct 31 20:50:13 2004
@@ -62,7 +62,7 @@
        file_list_.set_width(width());
        filename_textbox_.set_width(width());
 
-       file_list_.set_loc(location().x, file_list_y);
+       file_list_.set_location(location().x, file_list_y);
        filename_textbox_.set_location(location().x, filename_textbox_y);
 
        file_list_.set_max_height(file_list_height);
@@ -131,7 +131,6 @@
 void file_chooser::process() {
        CKey key;
        int mousex, mousey;
-       const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
        // The menu does not implement focus functionality, so we fake
        // it. We give the file list focus whenever the filename textbox
        // does not have focus. Inflexible but easy solution.
@@ -147,15 +146,7 @@
                filename_textbox_.set_focus(false);
        }
        if (!filename_textbox_.focus()) {
-               const bool new_left_button = mouse_flags&SDL_BUTTON_LMASK;
-               
-               const bool new_up_arrow = key[SDLK_UP];
-               const bool new_down_arrow = key[SDLK_DOWN];
-               
-               const bool new_page_up = key[SDLK_PAGEUP];
-               const bool new_page_down = key[SDLK_PAGEDOWN];
-               file_list_.process(mousex, mousey, new_left_button, 
new_up_arrow,
-                                                  new_down_arrow, new_page_up, 
new_page_down, -1);
+               file_list_.process();
                const int new_selection = file_list_.selection();
                const bool double_click = file_list_.double_clicked();
                if (double_click && new_selection >= 0) {
Index: wesnoth/src/widgets/menu.cpp
diff -u wesnoth/src/widgets/menu.cpp:1.65 wesnoth/src/widgets/menu.cpp:1.66
--- wesnoth/src/widgets/menu.cpp:1.65   Sat Oct 30 17:20:01 2004
+++ wesnoth/src/widgets/menu.cpp        Sun Oct 31 20:50:13 2004
@@ -22,15 +22,13 @@
 
 menu::menu(display& disp, const std::vector<std::string>& items,
            bool click_selects, int max_height, int max_width)
-        : max_height_(max_height), max_width_(max_width), max_items_(-1), 
item_height_(-1),
-         display_(&disp), x_(0), y_(0), cur_help_(-1,-1), help_string_(-1), 
buffer_(NULL),
+        : widget(disp),
+          max_height_(max_height), max_width_(max_width), max_items_(-1), 
item_height_(-1),
+         cur_help_(-1,-1), help_string_(-1),
          selected_(0), click_selects_(click_selects),
-         previous_button_(true), drawn_(false), show_result_(false),
-         height_(-1), width_(-1), first_item_on_screen_(0),
-         uparrow_(disp,"",gui::button::TYPE_PRESS,"uparrow-button"),
-         downarrow_(disp,"",gui::button::TYPE_PRESS,"downarrow-button"),
+         previous_button_(true), show_result_(false),
          double_clicked_(false),
-         scrollbar_(disp,this),
+         scrollbar_(disp, *this, this),
          num_selects_(true),
          ignore_next_doubleclick_(false),
          last_was_doubleclick_(false)
@@ -58,6 +56,7 @@
        }
 
        create_help_strings();
+       update_size();
 }
 
 void menu::create_help_strings()
@@ -83,118 +82,44 @@
 
 void menu::update_scrollbar_grip_height()
 {
-       int h = scrollbar_.height();
-       size_t nb_items = items_.size(), max_items = max_items_onscreen();
-       int new_height = nb_items > max_items  ? h * max_items / nb_items : h;
-       int min_height = scrollbar_.get_minimum_grip_height();
-
-       if (new_height < min_height) 
-               new_height = min_height;
-       scrollbar_.set_grip_height(new_height);
+       scrollbar_.set_full_size(items_.size());
+       scrollbar_.set_shown_size(max_items_onscreen());
 }
 
-int menu::update_scrollbar_position()
-{
-       size_t nb_items = items_.size(), max_items = max_items_onscreen();
-       int new_scrollpos;
-       if (nb_items > max_items) {
-               int max_scroll_position = scrollbar_.height() - 
scrollbar_.get_grip_height();
-               size_t last_top_idx = nb_items - max_items;
-               new_scrollpos = (first_item_on_screen_ * max_scroll_position + 
last_top_idx - 1) / last_top_idx;
-       } else
-               new_scrollpos = 0;
-       scrollbar_.set_grip_position(new_scrollpos);
-       return new_scrollpos;
-}
+void menu::update_size() {
+       SDL_Rect rect = location();
+       for(size_t i = scrollbar_.get_position(),
+           i_end = minimum(items_.size(), i + max_items_onscreen());
+           i != i_end; ++i)
+               rect.h += get_item_rect(i).h;
+       if (max_height_ > 0 && rect.h > max_height_)
+               rect.h = max_height_;
+
+       std::vector<int> const &widths = column_widths();
+       rect.w = std::accumulate(widths.begin(), widths.end(), 0);
+       if (show_scrollbar())
+               rect.w += scrollbar_.width();
+       if (max_width_ > 0 && rect.w > max_width_)
+               rect.w = max_width_;
 
-int menu::height() const
-{
-       if(height_ == -1) {
-               height_ = 0;
-               for(size_t i = first_item_on_screen_; i != items_.size()
-                               && i != first_item_on_screen_ + 
max_items_onscreen(); ++i) {
-                       height_ += get_item_rect(i).h;
-               }
-       }
-       return height_;
-}
-
-int menu::width() const
-{
-       if(width_ == -1) {
-               const std::vector<int>& widths = column_widths();
-               width_ = std::accumulate(widths.begin(),widths.end(),0);
-               if(show_scrollbar()) {
-                       width_ += scrollbar_.get_max_width();
-               }
-       }
-
-       if(max_width_ > 0 && width_ > max_width_) {
-               width_ = max_width_;
-       }
-
-       return width_;
-}
-
-int menu::item_area_width() const {
-       return width() - scrollbar_.get_width();
+       set_location(rect);
 }
 
 int menu::selection() const { return selected_; }
 
-void menu::set_loc(int x, int y)
+void menu::set_location(SDL_Rect const &rect)
 {
-       x_ = x;
-       y_ = y;
-
-       const int w = width();
-
-       SDL_Rect portion = {x_,y_,w,height()};
-       surface const screen = display_->video().getSurface();
-       buffer_.assign(get_surface_portion(screen, portion));
-
-       if(show_scrollbar()) {
-               const int menu_width = w - scrollbar_.get_max_width();
-
-               scrollbar_.enable(true);
-               int scr_width = scrollbar_.get_width();
-               
-               SDL_Rect scroll_rect = {x_ + menu_width, y_+uparrow_.height(),
-                                                               scr_width, 
-                                                               
height()-downarrow_.height()-uparrow_.height()};
+       widget::set_location(rect);
+       itemRects_.clear();
+       bool scr = show_scrollbar();
+       if (scr) {
+               int scr_width = scrollbar_.width();
+               SDL_Rect scroll_rect = { rect.x + rect.w - scr_width, rect.y, 
scr_width, rect.h };
                scrollbar_.set_location(scroll_rect);
                update_scrollbar_grip_height();
-
-               uparrow_.set_location(x_ + menu_width,y_);
-               downarrow_.set_location(x_+ menu_width,scrollbar_.location().y 
+ scrollbar_.location().h);
-
-       }
-}
-
-void menu::set_width(int w)
-{
-       width_ = w;
-       set_loc(x_, y_);
-       itemRects_.clear();
-}
-
-SDL_Rect menu::get_rect() const
-{
-       SDL_Rect r = {x_, y_, max_width_ < 0 ? width_ : max_width_,
-                                 max_height_ < 0 ? height_ : max_height_};
-       return r;
-}
-
-void menu::redraw()
-{
-       if(x_ == 0 && y_ == 0) {
-               return;
        }
-
-       draw();
-       uparrow_.draw();
-       downarrow_.draw();
-       scrollbar_.redraw();
+       scrollbar_.hide(!scr);
+       register_rectangle(get_list_rect());
 }
 
 void menu::change_item(int pos1, int pos2,std::string str)
@@ -216,33 +141,28 @@
 
        update_scrollbar_grip_height();
        adjust_viewport_to_selection();
-       update_scrollbar_position();
        itemRects_.clear();
-       drawn_ = false;
+       set_dirty();
 }
 
-void menu::set_items(const std::vector<std::string>& items, bool strip_spaces,
-                                        bool keep_viewport) {
+void menu::set_items(const std::vector<std::string>& items, bool strip_spaces, 
bool keep_viewport)
+{
        items_.clear();
        itemRects_.clear();
        column_widths_.clear();
        undrawn_items_.clear();
-       height_ = -1; // Force recalculation of the height.
-       width_ = -1; // Force recalculation of the width.
        max_items_ = -1; // Force recalculation of the max items.
        item_height_ = -1; // Force recalculation of the item height.
-       // Scrollbar and buttons will be reenabled if they are needed.
-       scrollbar_.enable(false);
-       uparrow_.hide(true);
-       downarrow_.hide(true);
+       // Scrollbar will be reenabled if it is needed.
+       scrollbar_.hide(true);
        selected_ = 0;
        fill_items(items, strip_spaces);
        if (!keep_viewport)
-               first_item_on_screen_ = 0;
-       set_loc(x_, y_); // Force some more updating.
+               scrollbar_.set_position(0);
+       set_location(location()); // Force some more updating.
+       update_scrollbar_grip_height();
        adjust_viewport_to_selection();
-       update_scrollbar_position();
-       drawn_ = false;
+       set_dirty();
 }
 
 void menu::set_max_height(const int new_max_height) {
@@ -259,7 +179,7 @@
                return size_t(max_items_);
        }
 
-       const size_t max_height = max_height_ == -1 ? (display_->y()*66)/100 : 
max_height_;
+       const size_t max_height = max_height_ == -1 ? (disp().y()*66)/100 : 
max_height_;
        std::vector<int> heights;
        size_t n;
        for(n = 0; n != items_.size(); ++n) {
@@ -282,20 +202,7 @@
 {
        if(click_selects_)
                return;
-
-       size_t nb_items = items_.size(), max_items = max_items_onscreen();
-       size_t new_first_item = first_item_on_screen_;
-
-       if (selected_ < first_item_on_screen_)
-               new_first_item = selected_;
-       else if (selected_ >= first_item_on_screen_ + max_items)
-               new_first_item = selected_ - (max_items - 1);
-       if (nb_items <= max_items)
-               new_first_item = 0;
-       else if (new_first_item > nb_items - max_items)
-               new_first_item = nb_items - max_items;
-
-       move_viewport(new_first_item);
+       scrollbar_.adjust_position(selected_);
 }
 
 void menu::move_selection_up(size_t dep)
@@ -320,31 +227,6 @@
        adjust_viewport_to_selection();
 }
 
-void menu::move_viewport_up(size_t dep)
-{
-       move_viewport(first_item_on_screen_ > dep ? first_item_on_screen_ - dep 
: 0);
-}
-
-void menu::move_viewport_down(size_t dep)
-{
-       size_t nb_items = items_.size(), max_items = max_items_onscreen();
-       if (nb_items <= max_items)
-               return;
-       size_t last_top_idx = nb_items - max_items;
-       move_viewport(first_item_on_screen_ + dep >= last_top_idx ? 
last_top_idx : first_item_on_screen_ + dep);
-}
-
-void menu::move_viewport(size_t new_first_item)
-{
-       if (new_first_item == first_item_on_screen_)
-               return;
-
-       first_item_on_screen_ = new_first_item;
-       update_scrollbar_position();
-       itemRects_.clear();
-       drawn_ = false;
-}
-
 void menu::key_press(SDLKey key)
 {
        if (!click_selects_) {
@@ -361,6 +243,9 @@
                case SDLK_PAGEDOWN:
                        move_selection_down(max_items_onscreen());
                        break;
+               case SDLK_RETURN:
+                       double_clicked_ = true;
+                       break;
                default:
                        break;
                }
@@ -376,7 +261,7 @@
                key_press(event.key.keysym.sym);
        } else if(event.type == SDL_MOUSEBUTTONDOWN &&
                  event.button.button == SDL_BUTTON_LEFT ||
-                         event.type == DOUBLE_CLICK_EVENT) {
+                 event.type == DOUBLE_CLICK_EVENT) {
                int x = 0;
                int y = 0;
                if(event.type == SDL_MOUSEBUTTONDOWN) {
@@ -398,13 +283,11 @@
                        if(event.type == DOUBLE_CLICK_EVENT) {
                                if (ignore_next_doubleclick_) {
                                        ignore_next_doubleclick_ = false;
-                               }
-                               else {
+                               } else {
                                        double_clicked_ = true;
                                        last_was_doubleclick_ = true;
                                }
-                       }
-                       else if (last_was_doubleclick_) {
+                       } else if (last_was_doubleclick_) {
                                // If we have a double click as the next event, 
it means
                                // this double click was generated from a click 
that
                                // already has helped in generating a double 
click.
@@ -421,49 +304,12 @@
                const int item = hit(event.motion.x,event.motion.y);
                if (item != -1)
                        move_selection(item);
-       } else if(event.type == SDL_MOUSEBUTTONDOWN 
-                       && event.button.button == SDL_BUTTON_WHEELDOWN) {
-               move_viewport_down(1);
-       } else if(event.type == SDL_MOUSEBUTTONDOWN
-                       && event.button.button == SDL_BUTTON_WHEELUP) {
-               move_viewport_up(1);
        }
 }
 
-int menu::process(int x, int y, bool button, bool, bool, bool, bool, int)
-{
-       int max_scroll_position = scrollbar_.height() - 
scrollbar_.get_grip_height();
-       size_t nb_items = items_.size(), max_items = max_items_onscreen();
-       if (nb_items > max_items) {
-               if (uparrow_.process(x, y, button))
-                       move_viewport_up(1);
-               if (downarrow_.process(x, y, button))
-                       move_viewport_down(1);
-
-               scrollbar_.process();
-               int scroll_position = scrollbar_.get_grip_position();
-               size_t last_top_idx = nb_items - max_items;
-               size_t new_first_item = (scroll_position * last_top_idx) / 
max_scroll_position;
-               move_viewport(new_first_item >= last_top_idx ? last_top_idx : 
new_first_item);
-               int groove = scrollbar_.groove_clicked();
-               if (groove == -1)
-                       move_viewport_up(max_items);
-               else if (groove == 1)
-                       move_viewport_down(max_items);
-       }
-
-       // update enabled/disabled status for up/down buttons and the scrollbar
-       bool enable_scrollbar = nb_items > max_items;
-       scrollbar_.enable(enable_scrollbar);
-       uparrow_.hide(!enable_scrollbar);
-       downarrow_.hide(!enable_scrollbar);
-       if (enable_scrollbar) {
-               uparrow_.enable(first_item_on_screen_ != 0);
-               downarrow_.enable(first_item_on_screen_ < nb_items - max_items);
-       }
-
-       if (!drawn_)
-               draw();
+int menu::process()
+{
+       scrollbar_.hide(!show_scrollbar());
 
        if(show_result_) {
                show_result_ = false;
@@ -492,6 +338,8 @@
 
 void menu::scroll(int)
 {
+       itemRects_.clear();
+       set_dirty();
 }
 
 namespace {
@@ -548,17 +396,9 @@
 void menu::clear_item(int item)
 {
        SDL_Rect rect = get_item_rect(item);
-       if(rect.w == 0) {
+       if (rect.w == 0)
                return;
-       }
-
-       if(buffer_.get() != NULL) {
-               const int ypos = (item-first_item_on_screen_)*rect.h;
-               SDL_Rect srcrect = {0,ypos,rect.w,rect.h};
-               SDL_Rect dstrect = rect;
-               SDL_BlitSurface(buffer_,&srcrect,
-                               display_->video().getSurface(),&dstrect);
-       }
+       bg_restore(rect);
 }
 
 void menu::draw_item(int item)
@@ -569,13 +409,14 @@
        }
 
        clear_item(item);
-       
gui::draw_solid_tinted_rectangle(x_,rect.y,width()-scrollbar_.get_width(),rect.h,
+       gui::draw_solid_tinted_rectangle(rect.x, rect.y, rect.w, rect.h,
                                         item == selected_ ? 150:0,0,0,
                                         item == selected_ ? 0.6 : 0.2,
-                                        display_->video().getSurface());
+                                        disp().video().getSurface());
 
-       SDL_Rect area = display_->screen_area();
+       SDL_Rect const &area = disp().screen_area();
        //SDL_Rect area = { 0, 0, rect.w, rect.h };
+       SDL_Rect const &loc = location();
 
        const std::vector<int>& widths = column_widths();
 
@@ -590,22 +431,20 @@
                        if(str.empty() == false && str[0] == ImagePrefix) {
                                const std::string 
image_name(str.begin()+1,str.end());
                                surface const img = 
image::get_image(image_name,image::UNSCALED);
-                               const int max_width = max_width_ < 0 ? 
display_->x() :
-                                       minimum<int>(max_width_, display_->x() 
- xpos);
+                               const int max_width = max_width_ < 0 ? area.w :
+                                       minimum<int>(max_width_, area.w - xpos);
                                if(img != NULL && (xpos - rect.x) + img->w < 
max_width
-                                  && rect.y+img->h < display_->y()) {
+                                  && rect.y + img->h < area.h) {
                                        const size_t y = rect.y + (rect.h - 
img->h)/2;
-                                       display_->blit_surface(xpos,y,img);
+                                       disp().blit_surface(xpos,y,img);
                                        xpos += img->w + 5;
                                }
                        } else {
                                const std::string to_show = max_width_ > -1 ? 
-                                       font::make_text_ellipsis(str, 
menu_font_size,
-                                                                        
max_width_ - (xpos - rect.x)
-                                                                        - 
scrollbar_.get_width()) : str;
+                                       font::make_text_ellipsis(str, 
menu_font_size, loc.w - (xpos - rect.x)) : str;
                                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,to_show,xpos,y);
+                               
font::draw_text(&disp(),area,menu_font_size,font::NORMAL_COLOUR,to_show,xpos,y);
                                xpos += text_size.w + 5;
                        }
                }
@@ -615,11 +454,10 @@
 
 void menu::draw()
 {
-       if(x_ == 0 && y_ == 0 || drawn_ && undrawn_items_.empty()) {
+       if (hidden() || !dirty() && undrawn_items_.empty())
                return;
-       }
 
-       if(drawn_) {
+       if (!dirty()) {
                for(std::set<size_t>::const_iterator i = 
undrawn_items_.begin(); i != undrawn_items_.end(); ++i) {
                        if(*i < items_.size()) {
                                draw_item(*i);
@@ -632,21 +470,28 @@
        }
 
        undrawn_items_.clear();
-       drawn_ = true;
+       set_dirty(false);
 
        for(size_t i = 0; i != items_.size(); ++i)
                draw_item(i);
 
-       update_rect(x_,y_,width(),height());
+       update_rect(get_list_rect());
+}
+
+SDL_Rect menu::get_list_rect() const
+{
+       SDL_Rect loc = location();
+       if (!scrollbar_.hidden()) loc.w -= scrollbar_.width();
+       return loc;
 }
 
 int menu::hit(int x, int y) const
 {
-       if(x > x_  && x < x_ + width() - scrollbar_.get_width() && 
-          y > y_ && y < y_ + height()) {
+       SDL_Rect const &loc = get_list_rect();
+       if (x >= loc.x  && x < loc.x + loc.w && y >= loc.y && y < loc.y + 
loc.h) {
                for(size_t i = 0; i != items_.size(); ++i) {
                        const SDL_Rect& rect = get_item_rect(i);
-                       if(y > rect.y && y < rect.y + rect.h)
+                       if (y >= rect.y && y < rect.y + rect.h)
                                return i;
                }
        }
@@ -656,30 +501,27 @@
 
 std::pair<int,int> menu::hit_cell(int x, int y) const
 {
-       if(x > x_  && x < x_ + width() - scrollbar_.get_width() && 
-          y > y_ && y < y_ + height()) {
-               for(size_t i = 0; i != items_.size(); ++i) {
-                       const SDL_Rect& rect = get_item_rect(i);
-                       if(y > rect.y && y < rect.y + rect.h) {
-                               const std::vector<int>& widths = 
column_widths();
-                               for(std::vector<int>::const_iterator w = 
widths.begin(); w != widths.end(); ++w) {
-                                       x -= *w;
-                                       if(x <= x_) {
-                                               return 
std::pair<int,int>(int(i),int(w-widths.begin()));
-                                       }
-                               }
-                       }
-               }
+       int i = hit(x, y);
+       if (i < 0)
+               return std::pair<int,int>(-1, -1);
+
+       std::vector<int> const &widths = column_widths();
+       x -= location().x;
+       for(int j = 0, j_end = widths.size(); j != j_end; ++j) {
+               x -= widths[j];
+               if (x < 0)
+                       return std::pair<int,int>(i, j);
        }
 
-       return std::pair<int,int>(-1,-1);
+       return std::pair<int,int>(-1, -1);
 }
 
 SDL_Rect menu::get_item_rect(int item) const
 {
        const SDL_Rect empty_rect = {0,0,0,0};
-       if(item < first_item_on_screen_ ||
-          size_t(item) >= first_item_on_screen_ + max_items_onscreen()) {
+       int first_item_on_screen = scrollbar_.get_position();
+       if (item < first_item_on_screen ||
+           size_t(item) >= first_item_on_screen + max_items_onscreen()) {
                return empty_rect;
        }
 
@@ -687,17 +529,17 @@
        if(i != itemRects_.end())
                return i->second;
 
-       int y = y_;
-       if(item != first_item_on_screen_) {
+       SDL_Rect const &loc = get_list_rect();
+
+       int y = loc.y;
+       if (item != first_item_on_screen) {
                const SDL_Rect& prev = get_item_rect(item-1);
                y = prev.y + prev.h;
        }
 
-       const SDL_Rect screen_area = display_->screen_area();
+       SDL_Rect res = { loc.x, y, loc.w, get_item_height(item) };
 
-       SDL_Rect res = {x_, y,
-                           width() - scrollbar_.get_width(),
-                                       get_item_height(item)};
+       SDL_Rect const &screen_area = disp().screen_area();
 
        if(res.x > screen_area.w) {
                return empty_rect;
@@ -713,7 +555,7 @@
 
        //only insert into the cache if the menu's co-ordinates have
        //been initialized
-       if(x_ > 0 && y_ > 0)
+       if (loc.x > 0 && loc.y > 0)
                itemRects_.insert(std::pair<int,SDL_Rect>(item,res));
 
        return res;
@@ -749,11 +591,11 @@
        if(loc == cur_help_) {
                return;
        } else if(loc.first == -1) {
-               display_->clear_help_string(help_string_);
+               disp().clear_help_string(help_string_);
                help_string_ = -1;
        } else {
                if(help_string_ != -1) {
-                       display_->clear_help_string(help_string_);
+                       disp().clear_help_string(help_string_);
                        help_string_ = -1;
                }
 
@@ -763,7 +605,7 @@
                                const std::string& help = row[loc.second];
                                if(help.empty() == false) {
                                        //std::cerr << "setting help string 
from menu to '" << help << "'\n";
-                                       help_string_ = 
display_->set_help_string(help);
+                                       help_string_ = 
disp().set_help_string(help);
                                }
                        }
                }
Index: wesnoth/src/widgets/menu.hpp
diff -u wesnoth/src/widgets/menu.hpp:1.24 wesnoth/src/widgets/menu.hpp:1.25
--- wesnoth/src/widgets/menu.hpp:1.24   Sat Oct 30 17:20:01 2004
+++ wesnoth/src/widgets/menu.hpp        Sun Oct 31 20:50:13 2004
@@ -15,27 +15,14 @@
 
 namespace gui {
 
-class menu : public events::handler, public scrollable
+class menu : public widget, public scrollable
 {
 public:
        menu(display& disp, const std::vector<std::string>& items,
             bool click_selects=false, int max_height=-1, int max_width=-1);
 
-       int height() const;
-       int width() const;
-       /// Return the width of the area where the items are. That is, the
-       /// width excluding the scrollbar.
-       int item_area_width() const;
        int selection() const;
 
-       void set_loc(int x, int y);
-       void set_width(int w);
-       // Get the rect bounding the menu. If the max_height/max_width is
-       // set, use those, otherwise use the current values.
-       SDL_Rect get_rect() const;
-
-       void redraw(); //forced redraw
-       
        // allows user to change_item while running (dangerous)
        void change_item(int pos1,int pos2,std::string str);
 
@@ -49,15 +36,14 @@
                                   bool keep_viewport=false);
 
        /// Set a new max height for this menu. Note that this does not take
-       /// effect immideately, only after certain operations that clear
+       /// effect immediately, only after certain operations that clear
        /// everything, such as set_items().
        void set_max_height(const int new_max_height);
        void set_max_width(const int new_max_width);
 
        size_t nitems() const { return items_.size(); }
        
-       int process(int x, int y, bool button,bool up_arrow,bool down_arrow,
-                   bool page_up, bool page_down, int select_item=-1);
+       int process();
 
        bool double_clicked();
 
@@ -65,11 +51,11 @@
 
        void scroll(int pos);
 
-       void set_dirty() { drawn_ = false; }
        enum { HELP_STRING_SEPARATOR = '|', DEFAULT_ITEM = '*' };
-       enum { IMG_TEXT_SEPARATOR = 1 }; // Re-evaluate if this should be
-                                                                        // 
something else to be settable
-                                                                        // 
from WML.
+       enum { IMG_TEXT_SEPARATOR = 1 }; // Re-evaluate if this should be 
something else to be settable from WML.
+
+       virtual void set_location(const SDL_Rect& rect);
+       using widget::set_location;
 
 protected:
        void handle_event(const SDL_Event& event);
@@ -83,11 +69,8 @@
        void adjust_viewport_to_selection();
        void key_press(SDLKey key);
 
-
        bool show_scrollbar() const;
 
-       display* display_;
-       int x_, y_;
        std::vector<std::vector<std::string> > items_, help_;
 
        void create_help_strings();
@@ -98,21 +81,13 @@
 
        mutable std::vector<int> column_widths_;
 
-       surface buffer_;
        size_t selected_;
        bool click_selects_;
        bool previous_button_;
-       bool drawn_;
        std::set<size_t> undrawn_items_;
 
        bool show_result_;
 
-       mutable int height_;
-       mutable int width_;
-
-       mutable size_t first_item_on_screen_;
-       gui::button uparrow_, downarrow_;
-
        bool double_clicked_;
 
        const std::vector<int>& column_widths() const;
@@ -125,6 +100,7 @@
 
        mutable std::map<int,SDL_Rect> itemRects_;
 
+       SDL_Rect get_list_rect() const;
        SDL_Rect get_item_rect(int item) const;
        size_t get_item_height_internal(int item) const;
        size_t get_item_height(int item) const;
@@ -133,15 +109,8 @@
        int items_end() const;
        int items_height() const;
 
-       /// Set the vertical size of the scroll bar grip. The size should
-       /// vary inversely with the ratio of the number of items to the 
-       /// size of the viewing rect
        void update_scrollbar_grip_height();
-       /// Update the current position of the scrollbar to reflect possible
-       /// changes in the menu. Return the new position of the scrollbar.
-       int update_scrollbar_position();
        gui::scrollbar scrollbar_;
-       int scrollbar_width_;
 
        ///variable which determines whether a numeric keypress should
        ///select an item on the dialog
@@ -156,12 +125,10 @@
        /// remain at the item edges.
        void fill_items(const std::vector<std::string>& items, bool 
strip_spaces);
 
+       void update_size();
        void move_selection_up(size_t dep);
        void move_selection_down(size_t dep);
        void move_selection(size_t pos);
-       void move_viewport_up(size_t dep);
-       void move_viewport_down(size_t dep);
-       void move_viewport(size_t pos);
 };
 
 }
Index: wesnoth/src/widgets/scrollbar.cpp
diff -u wesnoth/src/widgets/scrollbar.cpp:1.16 
wesnoth/src/widgets/scrollbar.cpp:1.17
--- wesnoth/src/widgets/scrollbar.cpp:1.16      Tue Sep 28 00:36:24 2004
+++ wesnoth/src/widgets/scrollbar.cpp   Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: scrollbar.cpp,v 1.16 2004/09/28 00:36:24 Sirp Exp $*/
+/* $Id: scrollbar.cpp,v 1.17 2004/10/31 20:50:13 silene Exp $*/
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -36,97 +36,141 @@
 
 namespace gui {
 
-scrollbar::scrollbar(display& d, scrollable* callback)
-       : widget(d), mid_scaled_(NULL), groove_scaled_(NULL),
-         callback_(callback), minimum_grip_height_(0), width_(0),
-         highlight_(false), clicked_(false), dragging_(false),
-         grip_position_(0), grip_height_(0), enabled_(false),
-         groove_click_code_(0)
+scrollbar::scrollbar(display& d, widget const &pane, scrollable* callback)
+       : widget(d), pane_(pane), mid_scaled_(NULL), groove_scaled_(NULL), 
callback_(callback),
+         uparrow_(d, "", button::TYPE_TURBO, "uparrow-button"),
+         downarrow_(d, "", button::TYPE_TURBO, "downarrow-button"),
+         state_(NORMAL), grip_position_(0), old_position_(0), grip_height_(0), 
full_height_(0)
 {
-       static const surface img(image::get_image(scrollbar_mid, 
-                                                                               
image::UNSCALED));
+       static const surface img(image::get_image(scrollbar_mid, 
image::UNSCALED));
        
        if (img != NULL) {
-               width_ = img->w;
+               set_width(img->w);
                // this is a bit rough maybe
                minimum_grip_height_ = 2 * img->h;
-               grip_height_ = minimum_grip_height_;
        }
 }
 
-void scrollbar::enable(bool en)
+void scrollbar::set_location(SDL_Rect const &rect)
 {
-       enabled_ = en;
+       widget::set_location(rect);
+       int uh = uparrow_.height(), dh = downarrow_.height();
+       uparrow_.set_location(rect.x, rect.y);
+       downarrow_.set_location(rect.x, rect.y + rect.h - dh);
+       SDL_Rect r = rect;
+       r.y += uh;
+       r.h -= uh + dh;
+       register_rectangle(r);
 }
 
-bool scrollbar::enabled() const 
+void scrollbar::hide(bool value)
 {
-       return enabled_;
+       widget::hide(value);
+       uparrow_.hide(value);
+       downarrow_.hide(value);
 }
-               
-int scrollbar::get_width() const
+
+unsigned scrollbar::get_position() const
 {
-       if (enabled()) 
-               return get_max_width();
-       else 
-               return 0;
+       return grip_position_;
 }
 
-int scrollbar::get_max_width() const 
+void scrollbar::set_position(unsigned pos)
 {
-       return width_;
+       if (pos > full_height_ - grip_height_)
+               pos = full_height_ - grip_height_;
+       if (pos == grip_position_)
+               return;
+       grip_position_ = pos;
+       uparrow_.enable(grip_position_ != 0);
+       downarrow_.enable(grip_position_ < full_height_ - grip_height_);
+       set_dirty();
 }
 
-int scrollbar::get_grip_height() const 
+void scrollbar::adjust_position(unsigned pos)
 {
-       return grip_height_;
+       if (pos < grip_position_)
+               set_position(pos);
+       else if (pos >= grip_position_ + grip_height_)
+               set_position(pos - (grip_height_ - 1));
 }
 
-bool scrollbar::set_grip_height(int h) 
+void scrollbar::move_position(int dep)
 {
-       if (h < minimum_grip_height_ || h > location().h) {
-               return false;
-       }
-
-       if(h != grip_height_) {
-               grip_height_ = h;
-               set_dirty(true);
-       }
-
-       return true;
+       int pos = grip_position_ + dep;
+       if (pos > 0)
+               set_position(pos);
+       else
+               set_position(0);
 }
 
-int scrollbar::get_minimum_grip_height() const 
+void scrollbar::set_shown_size(unsigned h)
 {
-       return minimum_grip_height_;
+       if (h > full_height_)
+               h = full_height_;
+       if (h == grip_height_)
+               return;
+       grip_height_ = h;
+       set_position(grip_position_);
+       set_dirty(true);
 }
-       
 
-SDL_Rect scrollbar::scroll_grip_area() const
+void scrollbar::set_full_size(unsigned h)
 {
-       SDL_Rect res = {location().x, location().y+grip_position_, 
-                                       width_, grip_height_};
-       return res;
-
+       if (h == full_height_)
+               return;
+       full_height_ = h;
+       set_shown_size(grip_height_);
+       set_position(grip_position_);
+       set_dirty(true);
 }
 
-void scrollbar::redraw()
+void scrollbar::process_event()
 {
-       draw();
+       if (uparrow_.pressed())
+               move_position(-1);
+       if (downarrow_.pressed())
+               move_position(1);
+
+       if (grip_position_ == old_position_)
+               return;
+       old_position_ = grip_position_;
+       if (callback_)
+               callback_->scroll(grip_position_);
+}
+
+SDL_Rect scrollbar::groove_area() const
+{
+       SDL_Rect loc = location();
+       int uh = uparrow_.height();
+       loc.y += uh;
+       loc.h -= uh + downarrow_.height();
+       return loc;
+}
+
+SDL_Rect scrollbar::grip_area() const
+{
+       SDL_Rect const &loc = groove_area();
+       if (full_height_ == grip_height_)
+               return loc;
+       int h = (int)loc.h * grip_height_ / full_height_;
+       if (h < minimum_grip_height_)
+               h = minimum_grip_height_;
+       int y = loc.y + ((int)loc.h - h) * grip_position_ / (full_height_ - 
grip_height_);
+       SDL_Rect res = { loc.x, y, loc.w, h };
+       return res;
 }
 
 void scrollbar::draw()
 {
-       if(!enabled() || !dirty())
+       if (hidden() || !dirty())
                return;
 
-       set_dirty(false);
-       
-       const surface mid_img(image::get_image(highlight_ ? 
+       const surface mid_img(image::get_image(state_ != NORMAL ? 
                                        scrollbar_mid_hl : scrollbar_mid, 
image::UNSCALED));
-       const surface bottom_img(image::get_image(highlight_ ? 
+       const surface bottom_img(image::get_image(state_ != NORMAL ? 
                                        scrollbar_bottom_hl : scrollbar_bottom, 
image::UNSCALED));
-       const surface top_img(image::get_image(highlight_ ?
+       const surface top_img(image::get_image(state_ != NORMAL ?
                                        scrollbar_top_hl : scrollbar_top, 
image::UNSCALED));
 
        const surface top_grv(image::get_image(groove_top,image::UNSCALED));
@@ -134,15 +178,16 @@
        const surface 
bottom_grv(image::get_image(groove_bottom,image::UNSCALED));
 
        if (mid_img == NULL || bottom_img == NULL || top_img == NULL
-        || top_grv == NULL || bottom_grv == NULL || mid_grv == NULL){
+        || top_grv == NULL || bottom_grv == NULL || mid_grv == NULL) {
                std::cerr << "Failure to load scrollbar image.\n";
                return;
        }
 
-       int mid_height = grip_height_ - top_img->h - bottom_img->h;
+       SDL_Rect grip = grip_area();
+       int mid_height = grip.h - top_img->h - bottom_img->h;
        if (mid_height <= 0) {
                // for now, minimum size of the middle piece is 1. This should
-               // never really be encountered, and if it is, it's an symptom
+               // never really be encountered, and if it is, it's a symptom
                // of a larger problem, I think.
                mid_height = 1;
        }
@@ -151,12 +196,13 @@
                
mid_scaled_.assign(scale_surface_blended(mid_img,mid_img->w,mid_height));
        }
 
-       int groove_height = location().h - top_grv->h - bottom_grv->h;
+       SDL_Rect groove = groove_area();
+       int groove_height = groove.h - top_grv->h - bottom_grv->h;
        if (groove_height <= 0) {
                groove_height = 1;
        }
 
-       if(groove_scaled_.null() || groove_scaled_->h != groove_height) {
+       if (groove_scaled_.null() || groove_scaled_->h != groove_height) {
                
groove_scaled_.assign(scale_surface_blended(mid_grv,mid_grv->w,groove_height));
        }
 
@@ -165,7 +211,7 @@
                return;
        }
 
-       if (grip_height_ > location().h) {
+       if (grip.h > groove.h) {
                std::cerr << "abort draw scrollbar: grip too large\n";
                return;
        }
@@ -174,118 +220,80 @@
 
        bg_restore();
 
-       int xpos = location().x;
-
        // draw scrollbar "groove"
-       disp().blit_surface(xpos, location().y, top_grv);
-       disp().blit_surface(xpos, location().y + top_grv->h, groove_scaled_);
-       disp().blit_surface(xpos, location().y + top_grv->h + groove_height,
-                                               bottom_grv);
+       disp().blit_surface(groove.x, groove.y, top_grv);
+       disp().blit_surface(groove.x, groove.y + top_grv->h, groove_scaled_);
+       disp().blit_surface(groove.x, groove.y + top_grv->h + groove_height, 
bottom_grv);
 
        // draw scrollbar "grip"
-       SDL_Rect scrollbar = scroll_grip_area();
-       xpos = scrollbar.x;
-       disp().blit_surface(xpos, scrollbar.y, top_img); 
-       disp().blit_surface(xpos, scrollbar.y + top_img->h, mid_scaled_);
-       disp().blit_surface(xpos, scrollbar.y + top_img->h + mid_height,
-                                               bottom_img);
+       disp().blit_surface(grip.x, grip.y, top_img);
+       disp().blit_surface(grip.x, grip.y + top_img->h, mid_scaled_);
+       disp().blit_surface(grip.x, grip.y + top_img->h + mid_height, 
bottom_img);
 
-       update_rect(location());
+       set_dirty(false);
+       update_rect(groove);
 }      
 
-bool scrollbar::set_grip_position(int pos) 
-{
-       if (pos < 0)
-               pos = 0;
-       if (pos >= location().h - grip_height_) 
-               pos = location().h - grip_height_;
-
-       if(pos != grip_position_) {
-               grip_position_ = pos;
-               set_dirty();
-       }
-
-       return true;
-}
-
-int scrollbar::get_grip_position() const
-{
-       return grip_position_;
-}
-
-int scrollbar::groove_clicked()
-{
-       int res = groove_click_code_;
-       groove_click_code_ = 0;
-       return res;
-}
-
-void scrollbar::process()
+void scrollbar::handle_event(const SDL_Event& event)
 {
-       if (!enabled()) 
-               return; 
-
-       int mousex, mousey;
-       const int mouse_flags = SDL_GetMouseState(&mousex, &mousey);
-       const bool button = mouse_flags & SDL_BUTTON_LMASK;
-       static int mousey_on_grip = 0;
-
-       const SDL_Rect& hit_area = scroll_grip_area();
-       const bool barx= mousex > hit_area.x && mousex <= hit_area.x+hit_area.w;
-       const bool gripy = mousey > hit_area.y && mousey <= 
hit_area.y+hit_area.h;
-       const bool bary = mousey > location().y && 
-                                         mousey <= location().y+location().h;
-
-       const bool on = barx && gripy;
-
-       bool start_dragging = (button && !clicked_ && on);
-
-       if(start_dragging) {
-               dragging_ = true;
-               mousey_on_grip = mousey - grip_position_;
-       }
-
-       if(!button) {
-               dragging_ = false;
-       }
-       
-       if(highlight_ != on) {
-               highlight_ = on;
-               mid_scaled_.assign(NULL);
-               set_dirty(true);
-       }
-
-       if(dragging_) {
-               // mouse over grip & button down
-               int new_position = grip_position_;
-               highlight_ = true;
-               new_position = mousey - mousey_on_grip;
-               
-               if(new_position < 0)
-                       new_position = 0;
-               if(new_position > location().h - grip_height_)
-                       new_position = location().h - grip_height_;
-
-               if(new_position != grip_position_) {
-                       grip_position_ = new_position;
-                       set_dirty(true);
+       if (hidden())
+               return;
 
-                       callback_->scroll(grip_position_);
+       STATE new_state = state_;
+       SDL_Rect const &grip = grip_area();
+       SDL_Rect const &groove = groove_area();
+
+       switch (event.type) {
+       case SDL_MOUSEBUTTONUP:
+       {
+               SDL_MouseButtonEvent const &e = event.button;
+               bool on_grip = point_in_rect(e.x, e.y, grip);
+               new_state = on_grip ? ACTIVE : NORMAL;
+               break;
+       }
+       case SDL_MOUSEBUTTONDOWN:
+       {
+               SDL_MouseButtonEvent const &e = event.button;
+               bool on_grip = point_in_rect(e.x, e.y, grip);
+               bool on_groove = point_in_rect(e.x, e.y, groove);
+               bool on_scrollable = point_in_rect(e.x, e.y, pane_.location()) 
|| on_groove;
+               if (on_scrollable && e.button == SDL_BUTTON_WHEELDOWN) {
+                       move_position(1);
+               } else if (on_scrollable && e.button == SDL_BUTTON_WHEELUP) {
+                       move_position(-1);
+               } else if (on_grip && e.button == SDL_BUTTON_LEFT) {
+                       mousey_on_grip_ = e.y - grip.y;
+                       new_state = DRAGGED;
+               } else if (on_groove && e.button == SDL_BUTTON_LEFT && groove.h 
!= grip.h) {
+                       if (e.y < grip.y)
+                               move_position(-grip_height_);
+                       else
+                               move_position(grip_height_);
                }
+               break;
        }
-       else if (button && barx && bary && (!clicked_)) {
-               if (mousey > hit_area.y + hit_area.h) {
-                       // mouse on groove below grip & button down
-                       groove_click_code_ = 1;
-               }
-               else {
-                       // mouse on groove above grip & button down
-                       groove_click_code_ = -1;
+       case SDL_MOUSEMOTION:
+       {
+               SDL_MouseMotionEvent const &e = event.motion;
+               if (state_ == NORMAL || state_ == ACTIVE) {
+                       bool on_grip = point_in_rect(e.x, e.y, grip);
+                       new_state = on_grip ? ACTIVE : NORMAL;
+               } else if (state_ == DRAGGED && groove.h != grip.h) {
+                       int y_dep = e.y - grip.y - mousey_on_grip_;
+                       int dep = y_dep * (full_height_ - grip_height_) / 
(int)(groove.h - grip.h);
+                       move_position(dep);
                }
+               break;
+       }
+       default:
+               break;
        }
 
-       clicked_ = button;
-       draw();
+       if ((new_state == NORMAL) ^ (state_ == NORMAL)) {
+               set_dirty();
+               mid_scaled_.assign(NULL);
+       }
+       state_ = new_state;
 }
-       
+
 }
Index: wesnoth/src/widgets/scrollbar.hpp
diff -u wesnoth/src/widgets/scrollbar.hpp:1.6 
wesnoth/src/widgets/scrollbar.hpp:1.7
--- wesnoth/src/widgets/scrollbar.hpp:1.6       Tue Aug 24 01:12:03 2004
+++ wesnoth/src/widgets/scrollbar.hpp   Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: scrollbar.hpp,v 1.6 2004/08/24 01:12:03 Sirp Exp $ */
+/* $Id: scrollbar.hpp,v 1.7 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -16,8 +16,8 @@
 
 #include "SDL.h"
 #include "../sdl_utils.hpp"
+#include "button.hpp"
 #include "widget.hpp"
-#include <vector>
 
 namespace gui {
 
@@ -27,109 +27,61 @@
        virtual void scroll(int pos) = 0;
 };
 
-/// class scrollbar implements a rather stupid scrollbar widget. It requires
-/// some hand-holding from the widget using it. Many of these functions will
-/// likely be removed (possibly replaced) at a later date, as the "widget"
-/// class hierarchy is expanded
 class scrollbar : public widget
 {
 public:
-       /// Create a scrollbar
-       /// \param d The display object
-       ///
-       scrollbar(display& d, scrollable* callback);
-
-       /// \return the current width of the scrollbar (if it is disabled,
-       ///                     that value is zero
-       ///
-       int get_width() const;
-
-       /// \return the maximum width of the scrollbar, determined by the
-       ///                     image files used and a constant "padding" value
-       ///
-       int get_max_width() const;
-       
-
-       /// Process any scrollbar usage
-       ///
-       void process();
-
-       /// Turn scrollbar on or off
-       ///
-       /// \param en true to enable, false otherwise
-       ///
-       void enable(bool en);
-       
-       /// \return true if scrollbar enabled, false otherwise
-       bool enabled() const;
-
-       void redraw();
-
-       /// This function is used to determine where the scrollbar is. This 
-       /// should be used when trying to find out if the user has moved
-       /// the scrollbar.
-       ///
-       /// \return The distance in pixels from the highest
-       ///  (vertically) position. For example, will return 0 if the scrollbar
-       ///  is at the top.
-       int get_grip_position() const;
-
-       /// Used to manually update the scrollbar; for example, if the user has
-       /// changed the scroll position some other way (via button or 
mousewheel)
-       ///
-       /// \param the distance from the top of the scrollbar
-       ///
-       /// \return true if the function succeeds, false otherwise.
-       bool set_grip_position(int pos); 
-
-       /// \return the smallest the scrollbar "grip" can be
-       int get_minimum_grip_height() const;
-
-       /// \return the current height of the grip.
-       int get_grip_height() const;
-
-       /// Set the size of the grip
-       ///
-       /// \param pos the size for the grip
-       ///
-       /// \return true if successful, false otherwise.
-       bool set_grip_height(int pos);
-
-       /// This function determines whether the user clicked on the scrollbar
-       /// groove, and whether it was above or below the grip. The query
-       /// resets the state.
-       /// 
-       /// \return -1 if click was above, 1 if click was below, 0 otherwise
-       int groove_clicked();
+       /// Create a scrollbar.
+       /// \param d the display object
+       /// \param pane the widget where wheel events take place
+       /// \param callback a callback interface for warning that the grip has 
been moved
+       scrollbar(display &d, widget const &pane, scrollable *callback);
+
+       virtual void set_location(SDL_Rect const &rect);
+       using widget::set_location;
+       virtual void hide(bool value = true);
+
+       /// This function is used to determine where the scrollbar is.
+       /// \return the position. For example, will return 0 if the scrollbar
+       ///  is at the top, and (full_size - shown_size) if it is at the bottom.
+       unsigned get_position() const;
+
+       /// Used to manually update the scrollbar.
+       void set_position(unsigned pos);
+
+       /// Ensure the viewport contains the position.
+       void adjust_position(unsigned pos);
+
+       ///Move the scrollbar.
+       void move_position(int dep);
+
+       /// Set the relative size of the grip.
+       void set_shown_size(unsigned h);
+
+       /// Set the relative size of the scrollbar.
+       void set_full_size(unsigned h);
+
+protected:
+       virtual void handle_event(const SDL_Event& event);
+       virtual void process_event();
+       virtual void draw();
 
 private:
-       SDL_Rect scroll_grip_area() const;
-       void draw();
-
+       SDL_Rect grip_area() const;
+       SDL_Rect groove_area() const;
+       widget const &pane_;
        surface mid_scaled_, groove_scaled_;
 
        scrollable* callback_;
+       button uparrow_, downarrow_;
 
-       int minimum_grip_height_;
-       int width_;
-       bool highlight_;
-       bool clicked_;
-
-       bool dragging_;
-
-       // location of scrollbar grip (number of pixels below top of scrollbar)
-       int grip_position_;
+       enum STATE { UNINIT, NORMAL, ACTIVE, DRAGGED };
+       STATE state_;
 
-       // vertical extent of grip
-       int grip_height_;
-
-       int enabled_;
-
-       // -1 if user just clicked above the groove, 1 if they just clicked 
below
-       // 0 otherwise
-       int groove_click_code_;
+       int minimum_grip_height_, mousey_on_grip_;
+       // Relative data
+       int grip_position_, old_position_, grip_height_, full_height_;
 };
-       
+
 }
 
 #endif
Index: wesnoth/src/widgets/slider.cpp
diff -u wesnoth/src/widgets/slider.cpp:1.30 wesnoth/src/widgets/slider.cpp:1.31
--- wesnoth/src/widgets/slider.cpp:1.30 Sun Sep 19 07:24:59 2004
+++ wesnoth/src/widgets/slider.cpp      Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: slider.cpp,v 1.30 2004/09/19 07:24:59 silene Exp $ */
+/* $Id: slider.cpp,v 1.31 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -26,11 +26,19 @@
 
 namespace gui {
 
-slider::slider(display& d, const SDL_Rect& rect)
-       : widget(d, rect), min_(-100000), max_(100000), value_(0), 
-         increment_(1), highlight_(false), clicked_(true), dragging_(false)
+slider::slider(display& d)
+       : widget(d), image_(image::get_image(slider_image, image::UNSCALED)),
+         highlightedImage_(image::get_image(selected_image, image::UNSCALED)),
+         min_(-100000), max_(100000), value_(0), 
+         increment_(1), state_(NORMAL)
 {
-       set_dirty(true);
+}
+
+void slider::set_location(SDL_Rect const &rect)
+{
+       SDL_Rect dst = { rect.x, rect.y, rect.w, image_->h };
+       widget::set_location(dst);
+       register_rectangle(dst);
 }
 
 void slider::set_min(int value)
@@ -51,20 +59,20 @@
 
 void slider::set_value(int value)
 {
-       if (value == value_)
-               return;
-
-       value_ = value;
-       if (value_ > max_)
-               value_ = max_;
-       if (value_ < min_)
-               value_ = min_;
+       if (value > max_)
+               value = max_;
+       if (value < min_)
+               value = min_;
 
        if (increment_ > 1) {
                int hi = increment_ / 2;
-               value_ = ((value_ + hi) / increment_) * increment_;
+               value = ((value + hi) / increment_) * increment_;
        }
 
+       if (value == value_)
+               return;
+
+       value_ = value;
        set_dirty(true);
 }
 
@@ -91,108 +99,97 @@
 SDL_Rect slider::slider_area() const
 {
        static const SDL_Rect default_value = {0,0,0,0};
-       const surface img(image::get_image(slider_image,image::UNSCALED));
-       if(img == NULL)
+       SDL_Rect const &loc = location();
+       if (image_.null() || image_->w >= loc.w)
                return default_value;
 
-       if(img->w >= location().w)
-               return default_value;
-
-       double tmp = (value_ - min_ + 0.0) / (max_ - min_ + 0.0);
-       int tmp2 = (int)(tmp * (location().w - img->w));
-       const int xpos = location().x + tmp2;
-       SDL_Rect res = {xpos,location().y,img->w,img->h};
+       int xpos = loc.x + (value_ - min_) * (int)(loc.w - image_->w) / (max_ - 
min_);
+       SDL_Rect res = { xpos, loc.y, image_->w, image_->h };
        return res;
 }
 
 void slider::draw()
 {
-       if(!dirty() || hidden()) {
+       if (!dirty() || hidden())
                return;
-       }
 
-       const surface image(image::get_image(highlight_ ? selected_image : 
slider_image,image::UNSCALED));
-       if(image == NULL || dirty() == false)
+       const surface image(state_ != NORMAL ? highlightedImage_ : image_);
+       if (image == NULL)
                return;
 
-       if(image->w >= location().w)
+       SDL_Rect const &loc = location();
+       if (image->w >= loc.w)
                return;
 
        surface const screen = disp().video().getSurface();
 
        bg_restore();
 
-       SDL_Rect line_rect = {location().x, location().y + location().h/2,
-                             location().w, 1};
-       SDL_FillRect(screen,&line_rect,SDL_MapRGB(screen->format,255,255,255));
+       SDL_Rect line_rect = { loc.x + image->w / 2, loc.y + loc.h / 2, loc.w - 
image->w, 1 };
+       SDL_FillRect(screen, &line_rect, SDL_MapRGB(screen->format, 255, 255, 
255));
 
-       SDL_Rect slider = slider_area();
-       disp().blit_surface(slider.x,slider.y,image);
+       SDL_Rect const &slider = slider_area();
+       disp().blit_surface(slider.x, slider.y, image);
 
        set_dirty(false);
-       update_rect(location());
+       update_rect(loc);
 }
 
-void slider::process()
+void slider::set_slider_position(int x)
 {
-       if(hidden()) {
-               return;
-       }
+       SDL_Rect const &loc = location();
+       int tmp = x - loc.x - image_->w / 2;
+       if (tmp < 0)
+               tmp = 0;
+       if (tmp > loc.w - image_->w)
+               tmp = loc.w - image_->w;
 
-       int mousex, mousey;
-       const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
-       const bool button = mouse_flags&SDL_BUTTON_LMASK;
-
-       const surface img(image::get_image(slider_image,image::UNSCALED));
-       if(img == NULL)
-               return;
-
-       SDL_Rect rect = {location().x, location().y, location().w, img->h};
-       set_location(rect);
-
-       const SDL_Rect& hit_area = slider_area();
-       const bool on = mousex > hit_area.x && mousex <= hit_area.x+hit_area.w 
&&
-                       mousey > hit_area.y && mousey <= hit_area.y+hit_area.h;
-
-       if(on != highlight_) {
-               highlight_ = on;
-               set_dirty(true);
-       }
+       set_value(tmp * (max_ - min_) / (int)(loc.w - image_->w) + min_);
+}
 
-       const bool new_click = button && !clicked_;
-       if(new_click && on) {
-               dragging_ = true;
+void slider::mouse_motion(const SDL_MouseMotionEvent& event)
+{
+       if (state_ == NORMAL || state_ == ACTIVE) {
+               bool on = point_in_rect(event.x, event.y, slider_area());
+               state_ = on ? ACTIVE : NORMAL;
+       } else if (state_ == CLICKED || state_ == DRAGGED) {
+               state_ = DRAGGED;
+               set_slider_position(event.x);
        }
+}
 
-       if(!button) {
-               dragging_ = false;
-       }
+void slider::mouse_down(const SDL_MouseButtonEvent& event)
+{
+       if (event.button != SDL_BUTTON_LEFT || !point_in_rect(event.x, event.y, 
location()))
+               return;
 
-       clicked_ = button;
+       state_ = CLICKED;
+       set_slider_position(event.x);
+}
 
-       int new_value = value_;
+void slider::handle_event(const SDL_Event& event)
+{
+       if (hidden())
+               return;
 
-       if(dragging_ || new_click && point_in_rect(mousex,mousey,rect)) {
-               int tmp = mousex - location().x;
-               if (tmp < 0)
-                       tmp = 0;
-               if (tmp > location().w - img->w)
-                       tmp = location().w - img->w;
+       STATE start_state = state_;
 
-               double tmp2 = (tmp + 0.0) / (location().w - img->w + 0.0);
-               new_value = (int)(tmp2 * (max_ - min_ + 0.0)) + min_;
+       switch(event.type) {
+       case SDL_MOUSEBUTTONUP:
+               state_ = NORMAL;
+               break;
+       case SDL_MOUSEBUTTONDOWN:
+               mouse_down(event.button);
+               break;
+       case SDL_MOUSEMOTION:
+               mouse_motion(event.motion);
+               break;
+       default:
+               return;
        }
 
-       set_value(new_value);
-
-#if 0
-       if(new_value != value_) {
-               value_ = new_value;
+       if (start_state != state_)
                set_dirty(true);
-       }
-#endif
-
-       draw();
 }
 
 }
Index: wesnoth/src/widgets/slider.hpp
diff -u wesnoth/src/widgets/slider.hpp:1.18 wesnoth/src/widgets/slider.hpp:1.19
--- wesnoth/src/widgets/slider.hpp:1.18 Sat Sep 18 22:51:17 2004
+++ wesnoth/src/widgets/slider.hpp      Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: slider.hpp,v 1.18 2004/09/18 22:51:17 gruikya Exp $ */
+/* $Id: slider.hpp,v 1.19 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -26,7 +26,7 @@
 class slider : public widget
 {
 public:
-       slider(display& d, const SDL_Rect& rect);
+       slider(display& d);
 
        void set_min(int value);
        void set_max(int value);
@@ -37,20 +37,26 @@
        int max_value() const;
        int min_value() const;
 
-       void process();
+       virtual void set_location(SDL_Rect const &rect);
+
+protected:
+       virtual void handle_event(const SDL_Event& event);
+       virtual void draw();
 
 private:
+       void mouse_motion(const SDL_MouseMotionEvent& event);
+       void mouse_down(const SDL_MouseButtonEvent& event);
+       void set_slider_position(int x);
        SDL_Rect slider_area() const;
-       void draw();
+       surface image_, highlightedImage_;
 
        int min_;
        int max_;
        int value_;
        int increment_;
 
-       bool highlight_;
-       bool clicked_;
-       bool dragging_;
+       enum STATE { UNINIT, NORMAL, ACTIVE, CLICKED, DRAGGED };
+       STATE state_;
 };
 
 }
Index: wesnoth/src/widgets/textbox.cpp
diff -u wesnoth/src/widgets/textbox.cpp:1.58 
wesnoth/src/widgets/textbox.cpp:1.59
--- wesnoth/src/widgets/textbox.cpp:1.58        Wed Oct 27 19:28:07 2004
+++ wesnoth/src/widgets/textbox.cpp     Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: textbox.cpp,v 1.58 2004/10/27 19:28:07 gruikya Exp $ */
+/* $Id: textbox.cpp,v 1.59 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -33,9 +33,7 @@
             cursor_(text_.size()), selstart_(-1), selend_(-1),
             grabmouse_(false), text_pos_(0), editable_(editable),
             show_cursor_(true), show_cursor_at_(0), text_image_(NULL),
-            scrollbar_(d,this),
-            uparrow_(d,"",gui::button::TYPE_PRESS,"uparrow-button"),
-             downarrow_(d,"",gui::button::TYPE_PRESS,"downarrow-button"),
+            scrollbar_(d, *this, this),
             scroll_bottom_(false), wrap_(false), line_height_(0), yscroll_(0)
 {
        static const SDL_Rect area = d.screen_area();
@@ -114,20 +112,15 @@
 
 void textbox::draw()
 {
-       if(location().x == 0 || !dirty()) {
-               uparrow_.draw();
-               downarrow_.draw();
+       if (location().x == 0 || !dirty())
                return;
-       }
 
        bg_restore();
 
        const bool has_scrollbar = show_scrollbar();
        SDL_Rect loc = location();
-       if(has_scrollbar && loc.w > scrollbar_.get_max_width()) {
-               scrollbar_.set_dirty();
-               loc.w -= scrollbar_.get_max_width();
-       }
+       if (has_scrollbar)
+               loc.w -= scrollbar_.width();
 
        gui::draw_solid_tinted_rectangle(loc.x,loc.y,loc.w,loc.h,0,0,0,
                                  focus() ? 0.2 : 0.4, 
disp().video().getSurface());
@@ -143,50 +136,6 @@
                dest.x = loc.x;
                dest.y = loc.y;
 
-               scrollbar_.enable(has_scrollbar);
-
-               if(has_scrollbar && text_image_->h > 0 && loc.h > 
uparrow_.height() + downarrow_.height()) {
-                       SDL_Rect scroll_loc = {loc.x + loc.w,loc.y + 
uparrow_.height(),
-                                              scrollbar_.get_max_width(),loc.h 
- uparrow_.height() - downarrow_.height()};
-                       scrollbar_.set_location(scroll_loc);
-
-                       uparrow_.set_location(loc.x + loc.w,loc.y);
-                       downarrow_.set_location(loc.x + loc.w,loc.y + loc.h - 
downarrow_.height());
-
-                       const size_t max_height = scrollbar_.location().h;
-                       const size_t proportion = (loc.h*100)/text_image_->h;
-                       const size_t grip_height = 
maximum<size_t>((max_height*proportion)/100,scrollbar_.get_minimum_grip_height());
-                       scrollbar_.set_grip_height(grip_height);
-
-                       const size_t max_y = text_image_->h - loc.h;
-
-                       const size_t max_grip_y = scrollbar_.location().h - 
grip_height;
-
-                       if(scroll_bottom_) {
-                               scrollbar_.set_grip_position(max_grip_y);
-                       }
-
-                       if(max_grip_y > 0) {
-                               const size_t grip_y = 
scrollbar_.get_grip_position();
-
-                               uparrow_.hide(grip_y == 0);
-                               downarrow_.hide(grip_y == max_grip_y);
-
-                               src.y = (max_y*(grip_y*100)/max_grip_y)/100;
-                               lg::info(lg::display) << "set src.y to " << 
src.y << "/" << max_grip_y << "\n";
-                       }
-
-                       uparrow_.set_dirty(true);
-                       downarrow_.set_dirty(true);
-                       uparrow_.draw();
-                       downarrow_.draw();
-
-                       scrollbar_.redraw();
-               } else {
-                       uparrow_.hide();
-                       downarrow_.hide();
-               }
-
                scroll_bottom_ = false;
 
                // Fills the selected area
@@ -229,18 +178,6 @@
 
 void textbox::process()
 {
-       if(show_scrollbar()) {
-               if(uparrow_.pressed()) {
-                       
scrollbar_.set_grip_position(scrollbar_.get_grip_position() - 
scrollbar_.get_grip_height()/5);
-                       set_dirty(true);
-               }
-
-               if(downarrow_.pressed()) {
-                       
scrollbar_.set_grip_position(scrollbar_.get_grip_position() + 
scrollbar_.get_grip_height()/5);
-                       set_dirty(true);
-               }
-       }
-
        if(editable_) {
                if(focus()) {
                        const int ticks = SDL_GetTicks();
@@ -324,7 +261,7 @@
 
                int w = font::line_width(visible_string, font_size);
 
-               if(wrap_ && w >= location().w - scrollbar_.get_max_width()) {
+               if(wrap_ && w >= location().w - scrollbar_.width()) {
                        if(backup_itor != text.end()) {
                                int backup = itor - backup_itor;
                                itor = backup_itor + 1;
@@ -353,6 +290,7 @@
        return res;
 }
 
+
 void textbox::update_text_cache(bool changed)
 {
        if(changed) {
@@ -407,7 +345,7 @@
 
        if( (grabmouse_ && (event.type == SDL_MOUSEMOTION)) ||  (
                    event.type == SDL_MOUSEBUTTONDOWN  && (mousebuttons & 
SDL_BUTTON(1))  && ! 
-                       (mousex < location().x || mousex > location().x + 
location().w - (show_scrollbar() ? scrollbar_.get_max_width() : 0) ||
+                       (mousex < location().x || mousex > location().x + 
location().w - (show_scrollbar() ? scrollbar_.width() : 0) ||
                    mousey < location().y || mousey > location().y + 
location().h))) {
 
                const int x = mousex - location().x + text_pos_;
Index: wesnoth/src/widgets/textbox.hpp
diff -u wesnoth/src/widgets/textbox.hpp:1.31 
wesnoth/src/widgets/textbox.hpp:1.32
--- wesnoth/src/widgets/textbox.hpp:1.31        Tue Oct 12 03:35:57 2004
+++ wesnoth/src/widgets/textbox.hpp     Sun Oct 31 20:50:13 2004
@@ -1,4 +1,4 @@
-/* $Id: textbox.hpp,v 1.31 2004/10/12 03:35:57 Sirp Exp $ */
+/* $Id: textbox.hpp,v 1.32 2004/10/31 20:50:13 silene Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -74,9 +74,8 @@
        int show_cursor_at_;
        surface text_image_;
 
-       //variables used for multi-line textboxes which support scrolling
+       //variable used for multi-line textboxes which support scrolling
        scrollbar scrollbar_;
-       button uparrow_, downarrow_;
 
        bool scroll_bottom_;
 
Index: wesnoth/src/widgets/widget.cpp
diff -u wesnoth/src/widgets/widget.cpp:1.20 wesnoth/src/widgets/widget.cpp:1.21
--- wesnoth/src/widgets/widget.cpp:1.20 Fri Sep 10 17:23:09 2004
+++ wesnoth/src/widgets/widget.cpp      Sun Oct 31 20:50:13 2004
@@ -2,80 +2,71 @@
 #include "../display.hpp"
 
 namespace {
-       const SDL_Rect EmptyRect = {0,0,0,0};
+       const SDL_Rect EmptyRect = {-1234,-1234,0,0};
 }
 
 namespace gui {
 
-widget::widget(const widget &o) :
-       events::handler(), disp_(o.disp_), rect_(o.rect_), focus_(o.focus_), 
dirty_(o.dirty_),
-       needs_restore_(o.needs_restore_), hidden_(false), 
volatile_(o.volatile_),
-       help_text_(o.help_text_), help_string_(o.help_string_)
+widget::widget(const widget &o)
+       : events::handler(), disp_(o.disp_), restorer_(o.restorer_), 
rect_(o.rect_),
+         focus_(o.focus_), needs_restore_(o.needs_restore_),
+         state_(o.state_), volatile_(o.volatile_),
+         help_text_(o.help_text_), help_string_(o.help_string_)
 {
-       bg_backup();
 }
 
-widget::widget(display& disp) :
-       disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), 
needs_restore_(false), hidden_(false), volatile_(false), help_string_(0)
+widget::widget(display& disp)
+       : disp_(&disp), rect_(EmptyRect), focus_(true), needs_restore_(false),
+         state_(UNINIT), volatile_(false), help_string_(0)
 {
 }
 
-widget::widget(display& disp, const SDL_Rect& rect) :
-       disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), 
needs_restore_(false), hidden_(false), volatile_(false), help_string_(0)
+widget::~widget()
 {
-       set_location(rect);
-       bg_backup();
+       bg_cancel();
 }
 
-void widget::set_location(const SDL_Rect& rect)
+void widget::bg_cancel()
 {
-       if(rect_.x == rect.x && rect_.y == rect.y && rect_.w == rect.w && 
rect_.h == rect.h) {
-               return;
-       }
+       for(std::vector< surface_restorer >::iterator i = restorer_.begin(),
+           i_end = restorer_.end(); i != i_end; ++i)
+               i->cancel();
+       restorer_.clear();
+}
 
+void widget::set_location(SDL_Rect const &rect)
+{
+       if (rect_.x == rect.x && rect_.y == rect.y && rect_.w == rect.w && 
rect_.h == rect.h)
+               return;
+       if (state_ == UNINIT && rect.x != -1234 && rect.y != -1234)
+               state_ = DRAWN;
        bg_restore();
        rect_ = rect;
        set_dirty(true);
-       bg_backup();
+       bg_cancel();
 }
 
-void widget::set_location(int x, int y)
+void widget::register_rectangle(SDL_Rect const &rect)
 {
-       if(x == rect_.x && y == rect_.y) {
-               return;
-       }
+       restorer_.push_back(surface_restorer(&disp().video(), rect));
+}
 
-       bg_restore();
-       SDL_Rect rect = {x,y,location().w,location().h};
-       rect_ = rect;
-       set_dirty(true);
-       bg_backup();
+void widget::set_location(int x, int y)
+{
+       SDL_Rect rect = { x, y, location().w, location().h };
+       set_location(rect);
 }
 
 void widget::set_width(int w)
 {
-       if(w == rect_.w) {
-               return;
-       }
-
-       bg_restore();
-       SDL_Rect rect = {location().x,location().y,w,location().h};
-       rect_ = rect;
-       set_dirty(true);
-       bg_backup();
+       SDL_Rect rect = { location().x, location().y, w, location().h };
+       set_location(rect);
 }
 
 void widget::set_height(int h)
 {
-       if(h == rect_.h) {
-               return;
-       }
-
-       bg_restore();
-       SDL_Rect rect = {location().x,location().y,location().w,h};
-       rect_ = rect;
-       set_dirty(true);
-       bg_backup();
+       SDL_Rect rect = { location().x, location().y, location().w, h };
+       set_location(rect);
 }
 
 size_t widget::width() const
@@ -95,10 +86,8 @@
 
 void widget::set_focus(bool focus)
 {
-       if(focus) {
+       if (focus)
                events::focus_handler(this);
-       }
-
        focus_ = focus;
        set_dirty(true);
 }
@@ -110,87 +99,85 @@
 
 void widget::hide(bool value)
 {
-       if(value != hidden_) {
-               if(value) {
-                       restorer_.restore();
-               } else {
-                       set_dirty(true);
-               }
-
-               hidden_ = value;
+       if (value) {
+               if (state_ == DIRTY || state_ == DRAWN)
+                       bg_restore();
+               state_ = HIDDEN;
+       } else if (state_ == HIDDEN) {
+               state_ = DRAWN;
+               bg_update();
+               set_dirty(true);
        }
 }
 
 bool widget::hidden() const
 {
-       return hidden_;
+       return state_ == HIDDEN || state_ == UNINIT;
 }
 
 void widget::set_dirty(bool dirty)
 {
-       if(dirty == true && volatile_) {
+       if (dirty && (volatile_ || state_ != DRAWN) || !dirty && state_ != 
DIRTY)
                return;
-       }
 
-       dirty_ = dirty;
-       if(dirty_ == false) {
+       state_ = dirty ? DIRTY : DRAWN;
+       if (!dirty)
                needs_restore_ = true;
-       }
 }
 
 bool widget::dirty() const
 {
-       return dirty_;
+       return state_ == DIRTY;
 }
 
-void widget::bg_backup()
+void widget::bg_update()
 {
-       restorer_ = surface_restorer(&disp().video(), rect_);
+       for(std::vector< surface_restorer >::iterator i = restorer_.begin(),
+           i_end = restorer_.end(); i != i_end; ++i)
+               i->update();
 }
 
 void widget::bg_restore() const
 {
-       if(needs_restore_) {
-               restorer_.restore();
+       if (needs_restore_) {
+               for(std::vector< surface_restorer >::const_iterator i = 
restorer_.begin(),
+                   i_end = restorer_.end(); i != i_end; ++i)
+                       i->restore();
                needs_restore_ = false;
        } else {
                //this function should be able to be relied upon to update the 
rectangle,
                //so do that even if we don't restore
-               update_rect(location());
+               update_rect(rect_);
        }
 }
 
-void widget::handle_event(const SDL_Event& event)
+void widget::bg_restore(SDL_Rect const &rect) const
 {
-       if(!focus_)
-               return;
+       for(std::vector< surface_restorer >::const_iterator i = 
restorer_.begin(),
+           i_end = restorer_.end(); i != i_end; ++i)
+               i->restore(rect);
 }
 
 void widget::set_volatile(bool val)
 {
        volatile_ = val;
-       if(volatile_) {
-               dirty_ = false;
-       }
+       if (volatile_ && state_ == DIRTY)
+               state_ = DRAWN;
 }
 
 void widget::volatile_draw()
 {
-       if(!volatile_) {
+       if (!volatile_ || state_ != DRAWN)
                return;
-       }
-
-       dirty_ = true;
-       bg_backup();
+       state_ = DIRTY;
+       bg_update();
        draw();
 }
 
 void widget::volatile_undraw()
 {
-       if(!volatile_) {
+       if (!volatile_)
                return;
-       }
-
        bg_restore();
 }
 
@@ -201,7 +188,7 @@
 
 void widget::process_help_string(int mousex, int mousey)
 {
-       if(!hidden() && point_in_rect(mousex,mousey,location())) {
+       if (!hidden() && point_in_rect(mousex, mousey, rect_)) {
                if(help_string_ == 0 && help_text_ != "") {
                        //std::cerr << "setting help string to '" << help_text_ 
<< "'\n";
                        help_string_ = disp().set_help_string(help_text_);
Index: wesnoth/src/widgets/widget.hpp
diff -u wesnoth/src/widgets/widget.hpp:1.17 wesnoth/src/widgets/widget.hpp:1.18
--- wesnoth/src/widgets/widget.hpp:1.17 Sun Aug 29 16:09:57 2004
+++ wesnoth/src/widgets/widget.hpp      Sun Oct 31 20:50:13 2004
@@ -2,11 +2,12 @@
 #define WIDGET_HPP_INCLUDED
 
 #include "../events.hpp"
-
 #include "../sdl_utils.hpp"
 
 #include "SDL.h"
 
+#include <vector>
+
 class display;
 
 namespace gui {
@@ -14,8 +15,8 @@
 class widget : public events::handler
 {
 public:
-       const SDL_Rect& location() const;
-       void set_location(const SDL_Rect& rect);
+       SDL_Rect const &location() const;
+       virtual void set_location(SDL_Rect const &rect);
        void set_location(int x, int y);
        void set_width(int w);
        void set_height(int h);
@@ -26,11 +27,9 @@
        virtual bool focus() const;
        void set_focus(bool focus);
 
-       void hide(bool value=true);
+       virtual void hide(bool value = true);
        bool hidden() const;
 
-       void bg_backup();
-
        //Function to set the widget to draw in 'volatile' mode.
        //When in 'volatile' mode, instead of using the normal
        //save-background-redraw-when-dirty procedure, redrawing is done
@@ -49,29 +48,34 @@
        virtual void process_help_string(int mousex, int mousey);
 
 protected:
-       widget(const widget &o);
+       widget(widget const &o);
        widget(display& disp);
-       widget(display& disp, const SDL_Rect& rect);
-       virtual ~widget() { restorer_.cancel(); }
+       virtual ~widget();
 
+       // During each relocation, this function should be called to register
+       // the rectangles the widget needs to refresh automatically
+       void register_rectangle(SDL_Rect const &rect);
        void bg_restore() const;
+       void bg_restore(SDL_Rect const &rect) const;
 
        display& disp() const { return *disp_; }
 
-       virtual void handle_event(const SDL_Event& event);
+       virtual void handle_event(SDL_Event const &event) {}
 
 private:
        void volatile_draw();
        void volatile_undraw();
 
-       mutable display* disp_;
-       mutable surface_restorer restorer_;
+       void bg_update();
+       void bg_cancel();
+
+       display* disp_;
+       std::vector< surface_restorer > restorer_;
        SDL_Rect rect_;
        bool focus_;            // Should user input be ignored?
-       bool dirty_;            // Does the widget need drawn?
-       mutable bool needs_restore_; //have we drawn ourselves, so that if 
moved, we need to restore the background?
+       mutable bool needs_restore_; // Have we drawn ourselves, so that if 
moved, we need to restore the background?
 
-       bool hidden_;
+       enum { UNINIT, HIDDEN, DIRTY, DRAWN } state_;
 
        bool volatile_;
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]