summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/genworld_gui.cpp803
-rw-r--r--src/misc_gui.cpp684
-rw-r--r--src/network/network_gui.cpp1627
-rw-r--r--src/osk_gui.cpp285
-rw-r--r--src/querystring_gui.h38
-rw-r--r--src/signs_gui.cpp227
-rw-r--r--src/textbuf_gui.h17
7 files changed, 1876 insertions, 1805 deletions
diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp
index 13867c0e0..3c24f9491 100644
--- a/src/genworld_gui.cpp
+++ b/src/genworld_gui.cpp
@@ -29,6 +29,7 @@
#include "widgets/dropdown_func.h"
#include "core/random_func.hpp"
#include "landscape_type.h"
+#include "querystring_gui.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -43,14 +44,6 @@ enum glwp_modes {
GLWP_END
};
-struct generate_d {
- uint widget_id;
- uint x;
- uint y;
- char name[64];
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(generate_d));
-
extern void SwitchMode(int new_mode);
static inline void SetNewLandscapeType(byte landscape)
@@ -244,314 +237,324 @@ static DropDownList *BuildMapsizeDropDown()
return list;
}
-static void GenerateLandscapeWndProc(Window *w, WindowEvent *e)
-{
- static const StringID elevations[] = {STR_682A_VERY_FLAT, STR_682B_FLAT, STR_682C_HILLY, STR_682D_MOUNTAINOUS, INVALID_STRING_ID};
- static const StringID sea_lakes[] = {STR_VERY_LOW, STR_6820_LOW, STR_6821_MEDIUM, STR_6822_HIGH, INVALID_STRING_ID};
- static const StringID smoothness[] = {STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID};
- static const StringID tree_placer[] = {STR_CONFIG_PATCHES_TREE_PLACER_NONE, STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL, STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED, INVALID_STRING_ID};
- static const StringID rotation[] = {STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE, INVALID_STRING_ID};
- static const StringID landscape[] = {STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL, STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS, INVALID_STRING_ID};
- static const StringID num_towns[] = {STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
- static const StringID num_inds[] = {STR_NONE, STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
+static const StringID _elevations[] = {STR_682A_VERY_FLAT, STR_682B_FLAT, STR_682C_HILLY, STR_682D_MOUNTAINOUS, INVALID_STRING_ID};
+static const StringID _sea_lakes[] = {STR_VERY_LOW, STR_6820_LOW, STR_6821_MEDIUM, STR_6822_HIGH, INVALID_STRING_ID};
+static const StringID _smoothness[] = {STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_ROUGH, INVALID_STRING_ID};
+static const StringID _tree_placer[] = {STR_CONFIG_PATCHES_TREE_PLACER_NONE, STR_CONFIG_PATCHES_TREE_PLACER_ORIGINAL, STR_CONFIG_PATCHES_TREE_PLACER_IMPROVED, INVALID_STRING_ID};
+static const StringID _rotation[] = {STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION_CLOCKWISE, INVALID_STRING_ID};
+static const StringID _landscape[] = {STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL, STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS, INVALID_STRING_ID};
+static const StringID _num_towns[] = {STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
+static const StringID _num_inds[] = {STR_NONE, STR_NUM_VERY_LOW, STR_6816_LOW, STR_6817_NORMAL, STR_6818_HIGH, INVALID_STRING_ID};
- /* Data used for the generate seed edit box */
- static querystr_d _genseed_query;
- static char _genseed_buffer[11];
+struct GenerateLandscapeWindow : public QueryStringBaseWindow {
+ uint widget_id;
+ uint x;
+ uint y;
+ char name[64];
+ glwp_modes mode;
- glwp_modes mode = (glwp_modes)w->window_number;
+ GenerateLandscapeWindow(const WindowDesc *desc, void *data = NULL, WindowNumber number = 0) : QueryStringBaseWindow(desc, NULL, number)
+ {
+ this->LowerWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
- switch (e->event) {
- case WE_CREATE:
- w->LowerWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
+ snprintf(this->edit_str_buf, sizeof(this->edit_str_buf), "%u", _patches_newgame.generation_seed);
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
+ this->caption = STR_NULL;
+ this->afilter = CS_NUMERAL;
- snprintf(_genseed_buffer, sizeof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
- InitializeTextBuffer(&_genseed_query.text, _genseed_buffer, lengthof(_genseed_buffer), 120);
- _genseed_query.caption = STR_NULL;
- _genseed_query.afilter = CS_NUMERAL;
- break;
+ this->mode = (glwp_modes)this->window_number;
- case WE_PAINT:
- /* You can't select smoothness if not terragenesis */
- if (mode == GLWP_GENERATE) {
- w->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _patches_newgame.land_generator == 0);
- }
- /* Disable snowline if not hilly */
- w->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _opt_newgame.landscape != LT_ARCTIC);
- /* Disable town, industry and trees in SE */
- w->SetWidgetDisabledState(GLAND_TOWN_PULLDOWN, _game_mode == GM_EDITOR);
- w->SetWidgetDisabledState(GLAND_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
- w->SetWidgetDisabledState(GLAND_TREE_PULLDOWN, _game_mode == GM_EDITOR);
-
- w->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
- w->SetWidgetDisabledState(GLAND_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
- w->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_ARCTIC);
- w->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP, _patches_newgame.snow_line_height >= MAX_SNOWLINE_HEIGHT || _opt_newgame.landscape != LT_ARCTIC);
-
- w->SetWidgetLoweredState(GLAND_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
- w->SetWidgetLoweredState(GLAND_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
- w->SetWidgetLoweredState(GLAND_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
- w->SetWidgetLoweredState(GLAND_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
-
- if (_game_mode == GM_EDITOR) {
- w->widget[GLAND_TOWN_PULLDOWN].data = STR_6836_OFF;
- w->widget[GLAND_INDUSTRY_PULLDOWN].data = STR_6836_OFF;
- } else {
- w->widget[GLAND_TOWN_PULLDOWN].data = num_towns[_opt_newgame.diff.number_towns];
- w->widget[GLAND_INDUSTRY_PULLDOWN].data = num_inds[_opt_newgame.diff.number_industries];
- }
+ this->FindWindowPlacementAndResize(desc);
+ }
- if (mode == GLWP_GENERATE) {
- w->widget[GLAND_LANDSCAPE_PULLDOWN].data = landscape[_patches_newgame.land_generator];
- w->widget[GLAND_TREE_PULLDOWN].data = tree_placer[_patches_newgame.tree_placer];
- w->widget[GLAND_TERRAIN_PULLDOWN].data = elevations[_opt_newgame.diff.terrain_type];
- w->widget[GLAND_WATER_PULLDOWN].data = sea_lakes[_opt_newgame.diff.quantity_sea_lakes];
- w->widget[GLAND_SMOOTHNESS_PULLDOWN].data = smoothness[_patches_newgame.tgen_smoothness];
+ virtual void OnPaint()
+ {
+ /* You can't select smoothness if not terragenesis */
+ if (mode == GLWP_GENERATE) {
+ this->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _patches_newgame.land_generator == 0);
+ }
+ /* Disable snowline if not hilly */
+ this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _opt_newgame.landscape != LT_ARCTIC);
+ /* Disable town, industry and trees in SE */
+ this->SetWidgetDisabledState(GLAND_TOWN_PULLDOWN, _game_mode == GM_EDITOR);
+ this->SetWidgetDisabledState(GLAND_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
+ this->SetWidgetDisabledState(GLAND_TREE_PULLDOWN, _game_mode == GM_EDITOR);
+
+ this->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
+ this->SetWidgetDisabledState(GLAND_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
+ this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_ARCTIC);
+ this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP, _patches_newgame.snow_line_height >= MAX_SNOWLINE_HEIGHT || _opt_newgame.landscape != LT_ARCTIC);
+
+ this->SetWidgetLoweredState(GLAND_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
+ this->SetWidgetLoweredState(GLAND_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
+ this->SetWidgetLoweredState(GLAND_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
+ this->SetWidgetLoweredState(GLAND_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
+
+ if (_game_mode == GM_EDITOR) {
+ this->widget[GLAND_TOWN_PULLDOWN].data = STR_6836_OFF;
+ this->widget[GLAND_INDUSTRY_PULLDOWN].data = STR_6836_OFF;
+ } else {
+ this->widget[GLAND_TOWN_PULLDOWN].data = _num_towns[_opt_newgame.diff.number_towns];
+ this->widget[GLAND_INDUSTRY_PULLDOWN].data = _num_inds[_opt_newgame.diff.number_industries];
+ }
+
+ if (mode == GLWP_GENERATE) {
+ this->widget[GLAND_LANDSCAPE_PULLDOWN].data = _landscape[_patches_newgame.land_generator];
+ this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_patches_newgame.tree_placer];
+ this->widget[GLAND_TERRAIN_PULLDOWN].data = _elevations[_opt_newgame.diff.terrain_type];
+ this->widget[GLAND_WATER_PULLDOWN].data = _sea_lakes[_opt_newgame.diff.quantity_sea_lakes];
+ this->widget[GLAND_SMOOTHNESS_PULLDOWN].data = _smoothness[_patches_newgame.tgen_smoothness];
+ } else {
+ this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_patches_newgame.tree_placer];
+ this->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = _rotation[_patches_newgame.heightmap_rotation];
+ }
+
+ /* Set parameters for widget text that requires them. */
+ SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // GLAND_START_DATE_TEXT
+ SetDParam(1, 1 << _patches_newgame.map_x); // GLAND_MAPSIZE_X_PULLDOWN
+ SetDParam(2, 1 << _patches_newgame.map_y); // GLAND_MAPSIZE_Y_PULLDOWN
+ SetDParam(3, _patches_newgame.snow_line_height); // GLAND_SNOW_LEVEL_TEXT
+
+ DrawWindowWidgets(this);
+
+ this->DrawEditBox(GLAND_RANDOM_EDITBOX);
+
+ if (mode != GLWP_GENERATE) {
+ char buffer[512];
+
+ if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) {
+ SetDParam(0, this->y);
+ SetDParam(1, this->x);
} else {
- w->widget[GLAND_TREE_PULLDOWN].data = tree_placer[_patches_newgame.tree_placer];
- w->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = rotation[_patches_newgame.heightmap_rotation];
+ SetDParam(0, this->x);
+ SetDParam(1, this->y);
}
+ GetString(buffer, STR_HEIGHTMAP_SIZE, lastof(buffer));
+ DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, TC_BLACK);
- /* Set parameters for widget text that requires them. */
- SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // GLAND_START_DATE_TEXT
- SetDParam(1, 1 << _patches_newgame.map_x); // GLAND_MAPSIZE_X_PULLDOWN
- SetDParam(2, 1 << _patches_newgame.map_y); // GLAND_MAPSIZE_Y_PULLDOWN
- SetDParam(3, _patches_newgame.snow_line_height); // GLAND_SNOW_LEVEL_TEXT
-
- DrawWindowWidgets(w);
-
- DrawEditBox(w, &_genseed_query, GLAND_RANDOM_EDITBOX);
-
- if (mode != GLWP_GENERATE) {
- char buffer[512];
+ DrawString( 12, 91, STR_HEIGHTMAP_NAME, TC_BLACK);
+ SetDParamStr(0, this->name);
+ DrawStringTruncated(114, 91, STR_ORANGE, TC_BLACK, 326 - 114 - GetStringBoundingBox(buffer).width - 5);
+ }
+ }
- if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) {
- SetDParam(0, WP(w, generate_d).y);
- SetDParam(1, WP(w, generate_d).x);
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case 0: delete this; break;
+
+ case GLAND_TEMPERATE:
+ case GLAND_ARCTIC:
+ case GLAND_TROPICAL:
+ case GLAND_TOYLAND:
+ this->RaiseWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
+ SetNewLandscapeType(widget - GLAND_TEMPERATE);
+ break;
+
+ case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, GLAND_MAPSIZE_X_PULLDOWN);
+ break;
+
+ case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
+ break;
+
+ case GLAND_TOWN_PULLDOWN: // Number of towns
+ ShowDropDownMenu(this, _num_towns, _opt_newgame.diff.number_towns, GLAND_TOWN_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_INDUSTRY_PULLDOWN: // Number of industries
+ ShowDropDownMenu(this, _num_inds, _opt_newgame.diff.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_RANDOM_BUTTON: // Random seed
+ _patches_newgame.generation_seed = InteractiveRandom();
+ snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "%u", _patches_newgame.generation_seed);
+ UpdateTextBufferSize(&this->text);
+ this->SetDirty();
+ break;
+
+ case GLAND_RANDOM_EDITBOX: // edit box for random seed
+ ShowOnScreenKeyboard(this, GLAND_RANDOM_EDITBOX, 0, 0);
+ break;
+
+ case GLAND_GENERATE_BUTTON: // Generate
+ UpdatePatches();
+
+ if (_patches.town_layout == TL_NO_ROADS) {
+ ShowQuery(
+ STR_TOWN_LAYOUT_WARNING_CAPTION,
+ STR_TOWN_LAYOUT_WARNING_MESSAGE,
+ this,
+ LandscapeGenerationCallback);
+ } else if (mode == GLWP_HEIGHTMAP &&
+ (this->x * 2 < (1U << _patches_newgame.map_x) ||
+ this->x / 2 > (1U << _patches_newgame.map_x) ||
+ this->y * 2 < (1U << _patches_newgame.map_y) ||
+ this->y / 2 > (1U << _patches_newgame.map_y))) {
+ ShowQuery(
+ STR_HEIGHTMAP_SCALE_WARNING_CAPTION,
+ STR_HEIGHTMAP_SCALE_WARNING_MESSAGE,
+ this,
+ LandscapeGenerationCallback);
} else {
- SetDParam(0, WP(w, generate_d).x);
- SetDParam(1, WP(w, generate_d).y);
+ StartGeneratingLandscape(mode);
}
- GetString(buffer, STR_HEIGHTMAP_SIZE, lastof(buffer));
- DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, TC_BLACK);
-
- DrawString( 12, 91, STR_HEIGHTMAP_NAME, TC_BLACK);
- SetDParamStr(0, WP(w, generate_d).name);
- DrawStringTruncated(114, 91, STR_ORANGE, TC_BLACK, 326 - 114 - GetStringBoundingBox(buffer).width - 5);
- }
- break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 0: delete w; break;
-
- case GLAND_TEMPERATE:
- case GLAND_ARCTIC:
- case GLAND_TROPICAL:
- case GLAND_TOYLAND:
- w->RaiseWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
- SetNewLandscapeType(e->we.click.widget - GLAND_TEMPERATE);
- break;
-
- case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_x, GLAND_MAPSIZE_X_PULLDOWN);
- break;
-
- case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
- break;
-
- case GLAND_TOWN_PULLDOWN: // Number of towns
- ShowDropDownMenu(w, num_towns, _opt_newgame.diff.number_towns, GLAND_TOWN_PULLDOWN, 0, 0);
- break;
-
- case GLAND_INDUSTRY_PULLDOWN: // Number of industries
- ShowDropDownMenu(w, num_inds, _opt_newgame.diff.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0);
- break;
-
- case GLAND_RANDOM_BUTTON: // Random seed
- _patches_newgame.generation_seed = InteractiveRandom();
- snprintf(_genseed_buffer, lengthof(_genseed_buffer), "%u", _patches_newgame.generation_seed);
- UpdateTextBufferSize(&_genseed_query.text);
- w->SetDirty();
- break;
+ break;
- case GLAND_RANDOM_EDITBOX: // edit box for random seed
- ShowOnScreenKeyboard(w, & _genseed_query, GLAND_RANDOM_EDITBOX, 0, 0);
- break;
-
- case GLAND_GENERATE_BUTTON: // Generate
- UpdatePatches();
-
- if (_patches.town_layout == TL_NO_ROADS) {
- ShowQuery(
- STR_TOWN_LAYOUT_WARNING_CAPTION,
- STR_TOWN_LAYOUT_WARNING_MESSAGE,
- w,
- LandscapeGenerationCallback);
- } else if (mode == GLWP_HEIGHTMAP &&
- (WP(w, generate_d).x * 2 < (1U << _patches_newgame.map_x) ||
- WP(w, generate_d).x / 2 > (1U << _patches_newgame.map_x) ||
- WP(w, generate_d).y * 2 < (1U << _patches_newgame.map_y) ||
- WP(w, generate_d).y / 2 > (1U << _patches_newgame.map_y))) {
- ShowQuery(
- STR_HEIGHTMAP_SCALE_WARNING_CAPTION,
- STR_HEIGHTMAP_SCALE_WARNING_MESSAGE,
- w,
- LandscapeGenerationCallback);
- } else {
- StartGeneratingLandscape(mode);
- }
- break;
-
- case GLAND_START_DATE_DOWN:
- case GLAND_START_DATE_UP: // Year buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
-
- _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + e->we.click.widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
- }
- _left_button_clicked = false;
- break;
-
- case GLAND_START_DATE_TEXT: // Year text
- WP(w, generate_d).widget_id = GLAND_START_DATE_TEXT;
- SetDParam(0, _patches_newgame.starting_year);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, w, CS_NUMERAL);
- break;
+ case GLAND_START_DATE_DOWN:
+ case GLAND_START_DATE_UP: // Year buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
- case GLAND_SNOW_LEVEL_DOWN:
- case GLAND_SNOW_LEVEL_UP: // Snow line buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
-
- _patches_newgame.snow_line_height = Clamp(_patches_newgame.snow_line_height + e->we.click.widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
- }
- _left_button_clicked = false;
- break;
-
- case GLAND_SNOW_LEVEL_TEXT: // Snow line text
- WP(w, generate_d).widget_id = GLAND_SNOW_LEVEL_TEXT;
- SetDParam(0, _patches_newgame.snow_line_height);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, w, CS_NUMERAL);
- break;
-
- case GLAND_TREE_PULLDOWN: // Tree placer
- ShowDropDownMenu(w, tree_placer, _patches_newgame.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
- break;
-
- case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator OR Heightmap rotation
- /* case GLAND_HEIGHTMAP_ROTATION_TEXT: case GLAND_HEIGHTMAP_ROTATION_PULLDOWN:*/
- if (mode == GLWP_HEIGHTMAP) {
- ShowDropDownMenu(w, rotation, _patches_newgame.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
- } else {
- ShowDropDownMenu(w, landscape, _patches_newgame.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
- }
- break;
+ _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case GLAND_START_DATE_TEXT: // Year text
+ this->widget_id = GLAND_START_DATE_TEXT;
+ SetDParam(0, _patches_newgame.starting_year);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL);
+ break;
+
+ case GLAND_SNOW_LEVEL_DOWN:
+ case GLAND_SNOW_LEVEL_UP: // Snow line buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+
+ _patches_newgame.snow_line_height = Clamp(_patches_newgame.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case GLAND_SNOW_LEVEL_TEXT: // Snow line text
+ this->widget_id = GLAND_SNOW_LEVEL_TEXT;
+ SetDParam(0, _patches_newgame.snow_line_height);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, this, CS_NUMERAL);
+ break;
+
+ case GLAND_TREE_PULLDOWN: // Tree placer
+ ShowDropDownMenu(this, _tree_placer, _patches_newgame.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
+ break;
+
+ case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator OR Heightmap rotation
+ /* case GLAND_HEIGHTMAP_ROTATION_TEXT: case GLAND_HEIGHTMAP_ROTATION_PULLDOWN:*/
+ if (mode == GLWP_HEIGHTMAP) {
+ ShowDropDownMenu(this, _rotation, _patches_newgame.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
+ } else {
+ ShowDropDownMenu(this, _landscape, _patches_newgame.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
+ }
+ break;
- case GLAND_TERRAIN_PULLDOWN: // Terrain type
- ShowDropDownMenu(w, elevations, _opt_newgame.diff.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
- break;
+ case GLAND_TERRAIN_PULLDOWN: // Terrain type
+ ShowDropDownMenu(this, _elevations, _opt_newgame.diff.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
+ break;
- case GLAND_WATER_PULLDOWN: // Water quantity
- ShowDropDownMenu(w, sea_lakes, _opt_newgame.diff.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0);
- break;
+ case GLAND_WATER_PULLDOWN: // Water quantity
+ ShowDropDownMenu(this, _sea_lakes, _opt_newgame.diff.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0);
+ break;
- case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness
- ShowDropDownMenu(w, smoothness, _patches_newgame.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0);
- break;
- }
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, &_genseed_query, GLAND_RANDOM_EDITBOX);
- break;
+ case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness
+ ShowDropDownMenu(this, _smoothness, _patches_newgame.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0);
+ break;
+ }
+ }
- case WE_KEYPRESS:
- HandleEditBoxKey(w, &_genseed_query, GLAND_RANDOM_EDITBOX, e);
- /* the seed is unsigned, therefore atoi cannot be used.
- * As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value
- * (use random seed) it should not be possible to be
- * entered into the input field; the generate seed
- * button can be used instead. */
- _patches_newgame.generation_seed = minu(strtoul(_genseed_buffer, NULL, sizeof(_genseed_buffer) - 1), MAX_UVALUE(uint32) - 1);
- break;
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(GLAND_RANDOM_EDITBOX);
+ }
- case WE_DROPDOWN_SELECT:
- switch (e->we.dropdown.button) {
- case GLAND_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = e->we.dropdown.index; break;
- case GLAND_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = e->we.dropdown.index; break;
- case GLAND_TREE_PULLDOWN: _patches_newgame.tree_placer = e->we.dropdown.index; break;
- case GLAND_SMOOTHNESS_PULLDOWN: _patches_newgame.tgen_smoothness = e->we.dropdown.index; break;
-
- case GLAND_TOWN_PULLDOWN:
- _opt_newgame.diff.number_towns = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
- break;
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont;
+ this->HandleEditBoxKey(GLAND_RANDOM_EDITBOX, key, keycode, cont);
+ /* the seed is unsigned, therefore atoi cannot be used.
+ * As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value
+ * (use random seed) it should not be possible to be
+ * entered into the input field; the generate seed
+ * button can be used instead. */
+ _patches_newgame.generation_seed = minu(strtoul(this->edit_str_buf, NULL, sizeof(this->edit_str_buf) - 1), MAX_UVALUE(uint32) - 1);
+ return cont;
+ }
- case GLAND_INDUSTRY_PULLDOWN:
- _opt_newgame.diff.number_industries = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
- break;
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case GLAND_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = index; break;
+ case GLAND_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = index; break;
+ case GLAND_TREE_PULLDOWN: _patches_newgame.tree_placer = index; break;
+ case GLAND_SMOOTHNESS_PULLDOWN: _patches_newgame.tgen_smoothness = index; break;
+
+ case GLAND_TOWN_PULLDOWN:
+ _opt_newgame.diff.number_towns = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+
+ case GLAND_INDUSTRY_PULLDOWN:
+ _opt_newgame.diff.number_industries = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+
+ case GLAND_LANDSCAPE_PULLDOWN:
+ /* case GLAND_HEIGHTMAP_PULLDOWN: */
+ if (mode == GLWP_HEIGHTMAP) {
+ _patches_newgame.heightmap_rotation = index;
+ } else {
+ _patches_newgame.land_generator = index;
+ }
+ break;
+
+ case GLAND_TERRAIN_PULLDOWN:
+ _opt_newgame.diff.terrain_type = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+
+ case GLAND_WATER_PULLDOWN:
+ _opt_newgame.diff.quantity_sea_lakes = index;
+ if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+ DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ break;
+ }
+ this->SetDirty();
+ }
- case GLAND_LANDSCAPE_PULLDOWN:
- /* case GLAND_HEIGHTMAP_PULLDOWN: */
- if (mode == GLWP_HEIGHTMAP) {
- _patches_newgame.heightmap_rotation = e->we.dropdown.index;
- } else {
- _patches_newgame.land_generator = e->we.dropdown.index;
- }
- break;
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ int32 value = atoi(str);
- case GLAND_TERRAIN_PULLDOWN:
- _opt_newgame.diff.terrain_type = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ switch (this->widget_id) {
+ case GLAND_START_DATE_TEXT:
+ this->InvalidateWidget(GLAND_START_DATE_TEXT);
+ _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
break;
- case GLAND_WATER_PULLDOWN:
- _opt_newgame.diff.quantity_sea_lakes = e->we.dropdown.index;
- if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
- DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+ case GLAND_SNOW_LEVEL_TEXT:
+ this->InvalidateWidget(GLAND_SNOW_LEVEL_TEXT);
+ _patches_newgame.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
break;
}
- w->SetDirty();
- break;
-
- case WE_ON_EDIT_TEXT:
- if (!StrEmpty(e->we.edittext.str)) {
- int32 value = atoi(e->we.edittext.str);
-
- switch (WP(w, generate_d).widget_id) {
- case GLAND_START_DATE_TEXT:
- w->InvalidateWidget(GLAND_START_DATE_TEXT);
- _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
- break;
- case GLAND_SNOW_LEVEL_TEXT:
- w->InvalidateWidget(GLAND_SNOW_LEVEL_TEXT);
- _patches_newgame.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
- break;
- }
-
- w->SetDirty();
- }
- break;
+ this->SetDirty();
+ }
}
-}
+};
static const WindowDesc _generate_landscape_desc = {
WDP_CENTER, WDP_CENTER, 338, 268, 338, 268,
WC_GENERATE_LANDSCAPE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_generate_landscape_widgets,
- GenerateLandscapeWndProc,
+ NULL,
};
static const WindowDesc _heightmap_load_desc = {
@@ -559,7 +562,7 @@ static const WindowDesc _heightmap_load_desc = {
WC_GENERATE_LANDSCAPE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
_heightmap_load_widgets,
- GenerateLandscapeWndProc,
+ NULL,
};
static void _ShowGenerateLandscape(glwp_modes mode)
@@ -577,14 +580,12 @@ static void _ShowGenerateLandscape(glwp_modes mode)
if (!GetHeightmapDimensions(_file_to_saveload.name, &x, &y)) return;
}
- Window *w = AllocateWindowDescFront<Window>((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
-
- if (w == NULL) return;
+ GenerateLandscapeWindow *w = AllocateWindowDescFront<GenerateLandscapeWindow>((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
if (mode == GLWP_HEIGHTMAP) {
- WP(w, generate_d).x = x;
- WP(w, generate_d).y = y;
- strecpy(WP(w, generate_d).name, _file_to_saveload.title, lastof(WP(w, generate_d).name));
+ w->x = x;
+ w->y = y;
+ strecpy(w->name, _file_to_saveload.title, lastof(w->name));
}
InvalidateWindow(WC_GENERATE_LANDSCAPE, mode);
@@ -639,127 +640,131 @@ enum CreateScenarioWindowWidgets {
};
-static void CreateScenarioWndProc(Window *w, WindowEvent *e)
+struct CreateScenarioWindow : public Window
{
- switch (e->event) {
- case WE_CREATE:
- w->LowerWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
- break;
-
- case WE_PAINT:
- w->SetWidgetDisabledState(CSCEN_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
- w->SetWidgetDisabledState(CSCEN_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
- w->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _patches_newgame.se_flat_world_height <= 0);
- w->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP, _patches_newgame.se_flat_world_height >= MAX_TILE_HEIGHT);
-
- w->SetWidgetLoweredState(CSCEN_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
- w->SetWidgetLoweredState(CSCEN_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
- w->SetWidgetLoweredState(CSCEN_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
- w->SetWidgetLoweredState(CSCEN_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
-
- /* Set parameters for widget text that requires them */
- SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT
- SetDParam(1, 1 << _patches_newgame.map_x); // CSCEN_MAPSIZE_X_PULLDOWN
- SetDParam(2, 1 << _patches_newgame.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN
- SetDParam(3, _patches_newgame.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT
-
- DrawWindowWidgets(w);
-
- break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case CSCEN_TEMPERATE:
- case CSCEN_ARCTIC:
- case CSCEN_TROPICAL:
- case CSCEN_TOYLAND:
- w->RaiseWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
- SetNewLandscapeType(e->we.click.widget - CSCEN_TEMPERATE);
- break;
-
- case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
- break;
-
- case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y
- ShowDropDownList(w, BuildMapsizeDropDown(), _patches_newgame.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
- break;
-
- case CSCEN_EMPTY_WORLD: // Empty world / flat world
- StartGeneratingLandscape(GLWP_SCENARIO);
- break;
+ uint widget_id;
- case CSCEN_RANDOM_WORLD: // Generate
- ShowGenerateLandscape();
- break;
+ CreateScenarioWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, NULL, window_number)
+ {
+ this->LowerWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
+ }
- case CSCEN_START_DATE_DOWN:
- case CSCEN_START_DATE_UP: // Year buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
+ virtual void OnPaint()
+ {
+ this->SetWidgetDisabledState(CSCEN_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
+ this->SetWidgetDisabledState(CSCEN_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR);
+ this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _patches_newgame.se_flat_world_height <= 0);
+ this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP, _patches_newgame.se_flat_world_height >= MAX_TILE_HEIGHT);
+
+ this->SetWidgetLoweredState(CSCEN_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
+ this->SetWidgetLoweredState(CSCEN_ARCTIC, _opt_newgame.landscape == LT_ARCTIC);
+ this->SetWidgetLoweredState(CSCEN_TROPICAL, _opt_newgame.landscape == LT_TROPIC);
+ this->SetWidgetLoweredState(CSCEN_TOYLAND, _opt_newgame.landscape == LT_TOYLAND);
+
+ /* Set parameters for widget text that requires them */
+ SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT
+ SetDParam(1, 1 << _patches_newgame.map_x); // CSCEN_MAPSIZE_X_PULLDOWN
+ SetDParam(2, 1 << _patches_newgame.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN
+ SetDParam(3, _patches_newgame.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT
+
+ DrawWindowWidgets(this);
+ }
- _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + e->we.click.widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
- }
- _left_button_clicked = false;
- break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case CSCEN_TEMPERATE:
+ case CSCEN_ARCTIC:
+ case CSCEN_TROPICAL:
+ case CSCEN_TOYLAND:
+ this->RaiseWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
+ SetNewLandscapeType(widget - CSCEN_TEMPERATE);
+ break;
+
+ case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
+ break;
+
+ case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y
+ ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
+ break;
+
+ case CSCEN_EMPTY_WORLD: // Empty world / flat world
+ StartGeneratingLandscape(GLWP_SCENARIO);
+ break;
+
+ case CSCEN_RANDOM_WORLD: // Generate
+ ShowGenerateLandscape();
+ break;
+
+ case CSCEN_START_DATE_DOWN:
+ case CSCEN_START_DATE_UP: // Year buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+
+ _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case CSCEN_START_DATE_TEXT: // Year text
+ this->widget_id = CSCEN_START_DATE_TEXT;
+ SetDParam(0, _patches_newgame.starting_year);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL);
+ break;
+
+ case CSCEN_FLAT_LAND_HEIGHT_DOWN:
+ case CSCEN_FLAT_LAND_HEIGHT_UP: // Height level buttons
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+
+ _patches_newgame.se_flat_world_height = Clamp(_patches_newgame.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
+ }
+ _left_button_clicked = false;
+ break;
+
+ case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
+ this->widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
+ SetDParam(0, _patches_newgame.se_flat_world_height);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, this, CS_NUMERAL);
+ break;
+ }
+ }
- case CSCEN_START_DATE_TEXT: // Year text
- WP(w, generate_d).widget_id = CSCEN_START_DATE_TEXT;
- SetDParam(0, _patches_newgame.starting_year);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, w, CS_NUMERAL);
- break;
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case CSCEN_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = index; break;
+ case CSCEN_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = index; break;
+ }
+ this->SetDirty();
+ }
- case CSCEN_FLAT_LAND_HEIGHT_DOWN:
- case CSCEN_FLAT_LAND_HEIGHT_UP: // Height level buttons
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- w->SetDirty();
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ int32 value = atoi(str);
- _patches_newgame.se_flat_world_height = Clamp(_patches_newgame.se_flat_world_height + e->we.click.widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
- }
- _left_button_clicked = false;
+ switch (this->widget_id) {
+ case CSCEN_START_DATE_TEXT:
+ this->InvalidateWidget(CSCEN_START_DATE_TEXT);
+ _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
break;
- case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
- WP(w, generate_d).widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
- SetDParam(0, _patches_newgame.se_flat_world_height);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, w, CS_NUMERAL);
+ case CSCEN_FLAT_LAND_HEIGHT_TEXT:
+ this->InvalidateWidget(CSCEN_FLAT_LAND_HEIGHT_TEXT);
+ _patches_newgame.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
break;
}
- break;
-
- case WE_DROPDOWN_SELECT:
- switch (e->we.dropdown.button) {
- case CSCEN_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = e->we.dropdown.index; break;
- case CSCEN_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = e->we.dropdown.index; break;
- }
- w->SetDirty();
- break;
- case WE_ON_EDIT_TEXT:
- if (!StrEmpty(e->we.edittext.str)) {
- int32 value = atoi(e->we.edittext.str);
-
- switch (WP(w, generate_d).widget_id) {
- case CSCEN_START_DATE_TEXT:
- w->InvalidateWidget(CSCEN_START_DATE_TEXT);
- _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
- break;
-
- case CSCEN_FLAT_LAND_HEIGHT_TEXT:
- w->InvalidateWidget(CSCEN_FLAT_LAND_HEIGHT_TEXT);
- _patches_newgame.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
- break;
- }
-
- w->SetDirty();
- }
- break;
+ this->SetDirty();
+ }
}
-}
+};
static const Widget _create_scenario_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -796,13 +801,13 @@ static const WindowDesc _create_scenario_desc = {
WC_GENERATE_LANDSCAPE, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
_create_scenario_widgets,
- CreateScenarioWndProc,
+ NULL,
};
void ShowCreateScenario()
{
DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
- AllocateWindowDescFront<Window>(&_create_scenario_desc, GLWP_SCENARIO);
+ new CreateScenarioWindow(&_create_scenario_desc, GLWP_SCENARIO);
}
diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp
index 132863444..ffc9ab5d2 100644
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -44,6 +44,7 @@
#include "newgrf_cargo.h"
#include "rail_gui.h"
#include "tilehighlight_func.h"
+#include "querystring_gui.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -878,61 +879,61 @@ void UpdateTextBufferSize(Textbuf *tb)
tb->caretxoffs = tb->width;
}
-int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *e)
+bool HandleCaret(Textbuf *tb)
{
- e->we.keypress.cont = false;
+ /* caret changed? */
+ bool b = !!(_caret_timer & 0x20);
- switch (e->we.keypress.keycode) {
+ if (b != tb->caret) {
+ tb->caret = b;
+ return true;
+ }
+ return false;
+}
+
+int QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont)
+{
+ cont = false;
+
+ switch (keycode) {
case WKC_ESC: return 2;
case WKC_RETURN: case WKC_NUM_ENTER: return 1;
case (WKC_CTRL | 'V'):
- if (InsertTextBufferClipboard(&string->text)) w->InvalidateWidget(wid);
+ if (InsertTextBufferClipboard(&this->text)) w->InvalidateWidget(wid);
break;
case (WKC_CTRL | 'U'):
- DeleteTextBufferAll(&string->text);
+ DeleteTextBufferAll(&this->text);
w->InvalidateWidget(wid);
break;
case WKC_BACKSPACE: case WKC_DELETE:
- if (DeleteTextBufferChar(&string->text, e->we.keypress.keycode)) w->InvalidateWidget(wid);
+ if (DeleteTextBufferChar(&this->text, keycode)) w->InvalidateWidget(wid);
break;
case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
- if (MoveTextBufferPos(&string->text, e->we.keypress.keycode)) w->InvalidateWidget(wid);
+ if (MoveTextBufferPos(&this->text, keycode)) w->InvalidateWidget(wid);
break;
default:
- if (IsValidChar(e->we.keypress.key, string->afilter)) {
- if (InsertTextBufferChar(&string->text, e->we.keypress.key)) w->InvalidateWidget(wid);
+ if (IsValidChar(key, this->afilter)) {
+ if (InsertTextBufferChar(&this->text, key)) w->InvalidateWidget(wid);
} else { // key wasn't caught. Continue only if standard entry specified
- e->we.keypress.cont = (string->afilter == CS_ALPHANUMERAL);
+ cont = (this->afilter == CS_ALPHANUMERAL);
}
}
return 0;
}
-bool HandleCaret(Textbuf *tb)
-{
- /* caret changed? */
- bool b = !!(_caret_timer & 0x20);
-
- if (b != tb->caret) {
- tb->caret = b;
- return true;
- }
- return false;
-}
-
-void HandleEditBox(Window *w, querystr_d *string, int wid)
+void QueryString::HandleEditBox(Window *w, int wid)
{
- if (HandleCaret(&string->text)) w->InvalidateWidget(wid);
+ if (HandleCaret(&this->text)) w->InvalidateWidget(wid);
}
-void DrawEditBox(Window *w, querystr_d *string, int wid)
+void QueryString::DrawEditBox(Window *w, int wid)
{
const Widget *wi = &w->widget[wid];
@@ -957,7 +958,7 @@ void DrawEditBox(Window *w, querystr_d *string, int wid)
/* We will take the current widget length as maximum width, with a small
* space reserved at the end for the caret to show */
- const Textbuf *tb = &string->text;
+ const Textbuf *tb = &this->text;
delta = (wi->right - wi->left) - tb->width - 10;
if (delta > 0) delta = 0;
@@ -970,6 +971,21 @@ void DrawEditBox(Window *w, querystr_d *string, int wid)
_cur_dpi = old_dpi;
}
+int QueryStringBaseWindow::HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont)
+{
+ return this->QueryString::HandleEditBoxKey(this, wid, key, keycode, cont);
+}
+
+void QueryStringBaseWindow::HandleEditBox(int wid)
+{
+ this->QueryString::HandleEditBox(this, wid);
+}
+
+void QueryStringBaseWindow::DrawEditBox(int wid)
+{
+ this->QueryString::DrawEditBox(this, wid);
+}
+
enum QueryStringWidgets {
QUERY_STR_WIDGET_TEXT = 3,
QUERY_STR_WIDGET_CANCEL,
@@ -977,69 +993,79 @@ enum QueryStringWidgets {
};
-static void QueryStringWndProc(Window *w, WindowEvent *e)
+struct QueryStringWindow : public QueryStringBaseWindow
{
- querystr_d *qs = &WP(w, querystr_d);
+ Window *parent;
- switch (e->event) {
- case WE_CREATE:
- SetBit(_no_scroll, SCROLL_EDIT);
- break;
+ QueryStringWindow(const WindowDesc *desc, Window *parent) : QueryStringBaseWindow(desc), parent(parent)
+ {
+ SetBit(_no_scroll, SCROLL_EDIT);
- case WE_PAINT:
- SetDParam(0, qs->caption);
- DrawWindowWidgets(w);
+ this->FindWindowPlacementAndResize(desc);
+ }
- DrawEditBox(w, qs, QUERY_STR_WIDGET_TEXT);
- break;
+ virtual void OnPaint()
+ {
+ SetDParam(0, this->caption);
+ DrawWindowWidgets(this);
- case WE_CLICK:
- switch (e->we.click.widget) {
- case QUERY_STR_WIDGET_TEXT:
- ShowOnScreenKeyboard(w, &WP(w, querystr_d), QUERY_STR_WIDGET_TEXT, QUERY_STR_WIDGET_CANCEL, QUERY_STR_WIDGET_OK);
- break;
-
- case QUERY_STR_WIDGET_OK:
- press_ok:;
- if (qs->orig == NULL || strcmp(qs->text.buf, qs->orig) != 0) {
- Window *parent = w->parent;
- qs->handled = true;
-
- /* If the parent is NULL, the editbox is handled by general function
- * HandleOnEditText */
- if (parent != NULL) {
- parent->OnQueryTextFinished(qs->text.buf);
- } else {
- HandleOnEditText(qs->text.buf);
- }
- }
- /* Fallthrough */
- case QUERY_STR_WIDGET_CANCEL:
- delete w;
- break;
+ this->DrawEditBox(QUERY_STR_WIDGET_TEXT);
+ }
+
+ void OnOk()
+ {
+ if (this->orig == NULL || strcmp(this->text.buf, this->orig) != 0) {
+ /* If the parent is NULL, the editbox is handled by general function
+ * HandleOnEditText */
+ if (this->parent != NULL) {
+ this->parent->OnQueryTextFinished(this->text.buf);
+ } else {
+ HandleOnEditText(this->text.buf);
}
- break;
+ }
+ }
- case WE_MOUSELOOP:
- HandleEditBox(w, qs, QUERY_STR_WIDGET_TEXT);
- break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case QUERY_STR_WIDGET_TEXT:
+ ShowOnScreenKeyboard(this, QUERY_STR_WIDGET_TEXT, QUERY_STR_WIDGET_CANCEL, QUERY_STR_WIDGET_OK);
+ break;
- case WE_KEYPRESS:
- switch (HandleEditBoxKey(w, qs, QUERY_STR_WIDGET_TEXT, e)) {
- case 1: goto press_ok; // Enter pressed, confirms change
- case 2: delete w; break; // ESC pressed, closes window, abandons changes
- }
- break;
+ case QUERY_STR_WIDGET_OK:
+ this->OnOk();
+ /* Fallthrough */
+ case QUERY_STR_WIDGET_CANCEL:
+ delete this;
+ break;
+ }
+ }
- case WE_DESTROY: // Call cancellation of query, if we have not handled it before
- if (!qs->handled && w->parent != NULL) {
- qs->handled = true;
- w->parent->OnQueryTextFinished(NULL);
- }
- ClrBit(_no_scroll, SCROLL_EDIT);
- break;
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(QUERY_STR_WIDGET_TEXT);
}
-}
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont;
+ switch (this->HandleEditBoxKey(QUERY_STR_WIDGET_TEXT, key, keycode, cont)) {
+ case 1: this->OnOk(); // Enter pressed, confirms change
+ /* FALL THROUGH */
+ case 2: delete this; break; // ESC pressed, closes window, abandons changes
+ }
+ return cont;
+ }
+
+ ~QueryStringWindow()
+ {
+ if (!this->handled && this->parent != NULL) {
+ this->handled = true;
+ this->parent->OnQueryTextFinished(NULL);
+ }
+ ClrBit(_no_scroll, SCROLL_EDIT);
+ }
+};
static const Widget _query_string_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -1056,12 +1082,9 @@ static const WindowDesc _query_string_desc = {
WC_QUERY_STRING, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_query_string_widgets,
- QueryStringWndProc
+ NULL
};
-char _edit_str_buf[64];
-char _orig_str_buf[lengthof(_edit_str_buf)];
-
/** Show a query popup window with a textbox in it.
* @param str StringID for the text shown in the textbox
* @param caption StringID of text shown in caption of querywindow
@@ -1075,28 +1098,27 @@ void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth,
{
uint realmaxlen = maxlen & ~0x1000;
- assert(realmaxlen < lengthof(_edit_str_buf));
-
DeleteWindowById(WC_QUERY_STRING, 0);
DeleteWindowById(WC_SAVELOAD, 0);
- Window *w = new Window(&_query_string_desc);
- w->parent = parent;
+ QueryStringWindow *w = new QueryStringWindow(&_query_string_desc, parent);
+
+ assert(realmaxlen < lengthof(w->edit_str_buf));
- GetString(_edit_str_buf, str, lastof(_edit_str_buf));
- _edit_str_buf[realmaxlen - 1] = '\0';
+ GetString(w->edit_str_buf, str, lastof(w->edit_str_buf));
+ w->edit_str_buf[realmaxlen - 1] = '\0';
if (maxlen & 0x1000) {
- WP(w, querystr_d).orig = NULL;
+ w->orig = NULL;
} else {
- strecpy(_orig_str_buf, _edit_str_buf, lastof(_orig_str_buf));
- WP(w, querystr_d).orig = _orig_str_buf;
+ strecpy(w->orig_str_buf, w->edit_str_buf, lastof(w->orig_str_buf));
+ w->orig = w->orig_str_buf;
}
w->LowerWidget(QUERY_STR_WIDGET_TEXT);
- WP(w, querystr_d).caption = caption;
- WP(w, querystr_d).afilter = afilter;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, realmaxlen, maxwidth);
+ w->caption = caption;
+ w->afilter = afilter;
+ InitializeTextBuffer(&w->text, w->edit_str_buf, realmaxlen, maxwidth);
}
@@ -1306,230 +1328,276 @@ static void MakeSortedSaveGameList()
}
}
-static void GenerateFileName()
-{
- /* Check if we are not a spectator who wants to generate a name..
- Let's use the name of player #0 for now. */
- const Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST);
-
- SetDParam(0, p->index);
- SetDParam(1, _date);
- GetString(_edit_str_buf, STR_4004, lastof(_edit_str_buf));
- SanitizeFilename(_edit_str_buf);
-}
-
extern void StartupEngines();
-static void SaveLoadDlgWndProc(Window *w, WindowEvent *e)
-{
- static FiosItem o_dir;
+struct SaveLoadWindow : public QueryStringBaseWindow {
+ FiosItem o_dir;
- switch (e->event) {
- case WE_CREATE: // Set up OPENTTD button
- w->vscroll.cap = 10;
- w->resize.step_width = 2;
- w->resize.step_height = 10;
-
- o_dir.type = FIOS_TYPE_DIRECT;
- switch (_saveload_mode) {
- case SLD_SAVE_GAME:
- case SLD_LOAD_GAME:
- FioGetDirectory(o_dir.name, lengthof(o_dir.name), SAVE_DIR);
- break;
-
- case SLD_SAVE_SCENARIO:
- case SLD_LOAD_SCENARIO:
- FioGetDirectory(o_dir.name, lengthof(o_dir.name), SCENARIO_DIR);
- break;
-
- case SLD_LOAD_HEIGHTMAP:
- FioGetDirectory(o_dir.name, lengthof(o_dir.name), HEIGHTMAP_DIR);
- break;
-
- default:
- ttd_strlcpy(o_dir.name, _personal_dir, lengthof(o_dir.name));
- }
- break;
+ void GenerateFileName()
+ {
+ /* Check if we are not a spectator who wants to generate a name..
+ Let's use the name of player #0 for now. */
+ const Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST);
+
+ SetDParam(0, p->index);
+ SetDParam(1, _date);
+ GetString(this->edit_str_buf, STR_4004, lastof(this->edit_str_buf));
+ SanitizeFilename(this->edit_str_buf);
+ }
- case WE_PAINT: {
- int pos;
- int y;
+ SaveLoadWindow(const WindowDesc *desc, SaveLoadDialogMode mode) : QueryStringBaseWindow(desc)
+ {
+ static const StringID saveload_captions[] = {
+ STR_4001_LOAD_GAME,
+ STR_0298_LOAD_SCENARIO,
+ STR_4000_SAVE_GAME,
+ STR_0299_SAVE_SCENARIO,
+ STR_LOAD_HEIGHTMAP,
+ };
+
+ SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0);
+ SetBit(_no_scroll, SCROLL_SAVE);
+
+ /* Use an array to define what will be the current file type being handled
+ * by current file mode */
+ switch (mode) {
+ case SLD_SAVE_GAME: this->GenerateFileName(); break;
+ case SLD_SAVE_SCENARIO: strcpy(this->edit_str_buf, "UNNAMED"); break;
+ default: break;
+ }
- SetVScrollCount(w, _fios_num);
- DrawWindowWidgets(w);
- DrawFiosTexts(w->width);
+ assert((uint)mode < lengthof(saveload_captions));
- if (_savegame_sort_dirty) {
- _savegame_sort_dirty = false;
- MakeSortedSaveGameList();
- }
+ this->widget[1].data = saveload_captions[mode];
+ this->LowerWidget(7);
- GfxFillRect(w->widget[7].left + 1, w->widget[7].top + 1, w->widget[7].right, w->widget[7].bottom, 0xD7);
- DrawSortButtonState(w, _savegame_sort_order & SORT_BY_NAME ? 2 : 3, _savegame_sort_order & SORT_DESCENDING ? SBS_DOWN : SBS_UP);
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 240);
- y = w->widget[7].top + 1;
- for (pos = w->vscroll.pos; pos < _fios_num; pos++) {
- const FiosItem *item = _fios_list + pos;
+ /* pause is only used in single-player, non-editor mode, non-menu mode. It
+ * will be unpaused in the WE_DESTROY event handler. */
+ if (_game_mode != GM_MENU && !_networking && _game_mode != GM_EDITOR) {
+ if (_pause_game >= 0) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
+ }
- DoDrawStringTruncated(item->title, 4, y, _fios_colors[item->type], w->width - 18);
- y += 10;
- if (y >= w->vscroll.cap * 10 + w->widget[7].top + 1) break;
- }
+ BuildFileList();
- if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
- DrawEditBox(w, &WP(w, querystr_d), 10);
- }
- break;
+ ResetObjectToPlace();
+
+ o_dir.type = FIOS_TYPE_DIRECT;
+ switch (_saveload_mode) {
+ case SLD_SAVE_GAME:
+ case SLD_LOAD_GAME:
+ FioGetDirectory(o_dir.name, lengthof(o_dir.name), SAVE_DIR);
+ break;
+
+ case SLD_SAVE_SCENARIO:
+ case SLD_LOAD_SCENARIO:
+ FioGetDirectory(o_dir.name, lengthof(o_dir.name), SCENARIO_DIR);
+ break;
+
+ case SLD_LOAD_HEIGHTMAP:
+ FioGetDirectory(o_dir.name, lengthof(o_dir.name), HEIGHTMAP_DIR);
+ break;
+
+ default:
+ ttd_strlcpy(o_dir.name, _personal_dir, lengthof(o_dir.name));
}
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 2: // Sort save names by name
- _savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ?
- SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME;
- _savegame_sort_dirty = true;
- w->SetDirty();
- break;
-
- case 3: // Sort save names by date
- _savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ?
- SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE;
- _savegame_sort_dirty = true;
- w->SetDirty();
- break;
-
- case 6: // OpenTTD 'button', jumps to OpenTTD directory
- FiosBrowseTo(&o_dir);
- w->SetDirty();
- BuildFileList();
- break;
-
- case 7: { // Click the listbox
- int y = (e->we.click.pt.y - w->widget[e->we.click.widget].top - 1) / 10;
- char *name;
- const FiosItem *file;
-
- if (y < 0 || (y += w->vscroll.pos) >= w->vscroll.count) return;
-
- file = _fios_list + y;
-
- name = FiosBrowseTo(file);
- if (name != NULL) {
- if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
- _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD;
-
- SetFiosType(file->type);
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
-
- delete w;
- } else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
- SetFiosType(file->type);
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
-
- delete w;
- ShowHeightmapLoad();
- } else {
- /* SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox */
- ttd_strlcpy(WP(w, querystr_d).text.buf, file->title, WP(w, querystr_d).text.maxlength);
- UpdateTextBufferSize(&WP(w, querystr_d).text);
- w->InvalidateWidget(10);
- }
- } else {
- /* Changed directory, need repaint. */
- w->SetDirty();
- BuildFileList();
- }
- break;
- }
+ this->vscroll.cap = 10;
+ this->resize.step_width = 2;
+ this->resize.step_height = 10;
- case 10: // edit box
- ShowOnScreenKeyboard(w, &WP(w, querystr_d), e->we.click.widget, 0, 0);
- break;
+ this->FindWindowPlacementAndResize(desc);
+ }
- case 11: case 12: // Delete, Save game
- break;
- }
- break;
+ virtual ~SaveLoadWindow()
+ {
+ /* pause is only used in single-player, non-editor mode, non menu mode */
+ if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
+ if (_pause_game >= 0) DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
+ }
+ FiosFreeSavegameList();
+ ClrBit(_no_scroll, SCROLL_SAVE);
+ }
- case WE_MOUSELOOP:
- if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
- HandleEditBox(w, &WP(w, querystr_d), 10);
- }
- break;
+ virtual void OnPaint()
+ {
+ int pos;
+ int y;
- case WE_KEYPRESS:
- if (e->we.keypress.keycode == WKC_ESC) {
- delete w;
- return;
- }
+ SetVScrollCount(this, _fios_num);
+ DrawWindowWidgets(this);
+ DrawFiosTexts(this->width);
- if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) &&
- HandleEditBoxKey(w, &WP(w, querystr_d), 10, e) == 1) { // Press Enter
- w->HandleButtonClick(12);
- }
- break;
+ if (_savegame_sort_dirty) {
+ _savegame_sort_dirty = false;
+ MakeSortedSaveGameList();
+ }
+
+ GfxFillRect(this->widget[7].left + 1, this->widget[7].top + 1, this->widget[7].right, this->widget[7].bottom, 0xD7);
+ DrawSortButtonState(this, _savegame_sort_order & SORT_BY_NAME ? 2 : 3, _savegame_sort_order & SORT_DESCENDING ? SBS_DOWN : SBS_UP);
+
+ y = this->widget[7].top + 1;
+ for (pos = this->vscroll.pos; pos < _fios_num; pos++) {
+ const FiosItem *item = _fios_list + pos;
+
+ DoDrawStringTruncated(item->title, 4, y, _fios_colors[item->type], this->width - 18);
+ y += 10;
+ if (y >= this->vscroll.cap * 10 + this->widget[7].top + 1) break;
+ }
+
+ if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
+ this->DrawEditBox(10);
+ }
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case 2: // Sort save names by name
+ _savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ?
+ SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME;
+ _savegame_sort_dirty = true;
+ this->SetDirty();
+ break;
+
+ case 3: // Sort save names by date
+ _savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ?
+ SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE;
+ _savegame_sort_dirty = true;
+ this->SetDirty();
+ break;
+
+ case 6: // OpenTTD 'button', jumps to OpenTTD directory
+ FiosBrowseTo(&o_dir);
+ this->SetDirty();
+ BuildFileList();
+ break;
- case WE_TIMEOUT:
- /* This test protects against using widgets 11 and 12 which are only available
- * in those two saveload mode */
- if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO)) break;
+ case 7: { // Click the listbox
+ int y = (pt.y - this->widget[widget].top - 1) / 10;
+ char *name;
+ const FiosItem *file;
- if (w->IsWidgetLowered(11)) { // Delete button clicked
- if (!FiosDelete(WP(w, querystr_d).text.buf)) {
- ShowErrorMessage(INVALID_STRING_ID, STR_4008_UNABLE_TO_DELETE_FILE, 0, 0);
+ if (y < 0 || (y += this->vscroll.pos) >= this->vscroll.count) return;
+
+ file = _fios_list + y;
+
+ name = FiosBrowseTo(file);
+ if (name != NULL) {
+ if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
+ _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD;
+
+ SetFiosType(file->type);
+ ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+ ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
+
+ delete this;
+ } else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
+ SetFiosType(file->type);
+ ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+ ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title));
+
+ delete this;
+ ShowHeightmapLoad();
+ } else {
+ /* SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox */
+ ttd_strlcpy(this->text.buf, file->title, this->text.maxlength);
+ UpdateTextBufferSize(&this->text);
+ this->InvalidateWidget(10);
+ }
} else {
+ /* Changed directory, need repaint. */
+ this->SetDirty();
BuildFileList();
- /* Reset file name to current date on successful delete */
- if (_saveload_mode == SLD_SAVE_GAME) GenerateFileName();
}
+ break;
+ }
- UpdateTextBufferSize(&WP(w, querystr_d).text);
- w->SetDirty();
- } else if (w->IsWidgetLowered(12)) { // Save button clicked
- _switch_mode = SM_SAVE;
- FiosMakeSavegameName(_file_to_saveload.name, WP(w, querystr_d).text.buf, sizeof(_file_to_saveload.name));
+ case 10: // edit box
+ ShowOnScreenKeyboard(this, widget, 0, 0);
+ break;
- /* In the editor set up the vehicle engines correctly (date might have changed) */
- if (_game_mode == GM_EDITOR) StartupEngines();
- }
- break;
+ case 11: case 12: // Delete, Save game
+ break;
+ }
+ }
- case WE_DESTROY:
- /* pause is only used in single-player, non-editor mode, non menu mode */
- if (!_networking && _game_mode != GM_EDITOR && _game_mode != GM_MENU) {
- if (_pause_game >= 0) DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- }
- FiosFreeSavegameList();
- ClrBit(_no_scroll, SCROLL_SAVE);
- break;
+ virtual void OnMouseLoop()
+ {
+ if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
+ this->HandleEditBox(10);
+ }
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ if (keycode == WKC_ESC) {
+ delete this;
+ return false;
+ }
+
+ bool cont = true;
+ if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) &&
+ this->HandleEditBoxKey(10, key, keycode, cont) == 1) { // Press Enter
+ this->HandleButtonClick(12);
+ }
+
+ return cont;
+ }
+
+ virtual void OnTimeout()
+ {
+ /* This test protects against using widgets 11 and 12 which are only available
+ * in those two saveload mode */
+ if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO)) return;
- case WE_RESIZE: {
- /* Widget 2 and 3 have to go with halve speed, make it so obiwan */
- uint diff = e->we.sizing.diff.x / 2;
- w->widget[2].right += diff;
- w->widget[3].left += diff;
- w->widget[3].right += e->we.sizing.diff.x;
-
- /* Same for widget 11 and 12 in save-dialog */
- if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
- w->widget[11].right += diff;
- w->widget[12].left += diff;
- w->widget[12].right += e->we.sizing.diff.x;
+ if (this->IsWidgetLowered(11)) { // Delete button clicked
+ if (!FiosDelete(this->text.buf)) {
+ ShowErrorMessage(INVALID_STRING_ID, STR_4008_UNABLE_TO_DELETE_FILE, 0, 0);
+ } else {
+ BuildFileList();
+ /* Reset file name to current date on successful delete */
+ if (_saveload_mode == SLD_SAVE_GAME) GenerateFileName();
}
- w->vscroll.cap += e->we.sizing.diff.y / 10;
- } break;
+ UpdateTextBufferSize(&this->text);
+ this->SetDirty();
+ } else if (this->IsWidgetLowered(12)) { // Save button clicked
+ _switch_mode = SM_SAVE;
+ FiosMakeSavegameName(_file_to_saveload.name, this->text.buf, sizeof(_file_to_saveload.name));
+
+ /* In the editor set up the vehicle engines correctly (date might have changed) */
+ if (_game_mode == GM_EDITOR) StartupEngines();
+ }
}
-}
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ /* Widget 2 and 3 have to go with halve speed, make it so obiwan */
+ uint diff = delta.x / 2;
+ this->widget[2].right += diff;
+ this->widget[3].left += diff;
+ this->widget[3].right += delta.x;
+
+ /* Same for widget 11 and 12 in save-dialog */
+ if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
+ this->widget[11].right += diff;
+ this->widget[12].left += diff;
+ this->widget[12].right += delta.x;
+ }
+
+ this->vscroll.cap += delta.y / 10;
+ }
+};
static const WindowDesc _load_dialog_desc = {
WDP_CENTER, WDP_CENTER, 257, 154, 257, 294,
WC_SAVELOAD, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_load_dialog_widgets,
- SaveLoadDlgWndProc,
+ NULL,
};
static const WindowDesc _save_dialog_desc = {
@@ -1537,7 +1605,7 @@ static const WindowDesc _save_dialog_desc = {
WC_SAVELOAD, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_save_dialog_widgets,
- SaveLoadDlgWndProc,
+ NULL,
};
/** These values are used to convert the file/operations mode into a corresponding file type.
@@ -1553,50 +1621,22 @@ static const FileType _file_modetotype[] = {
void ShowSaveLoadDialog(SaveLoadDialogMode mode)
{
- static const StringID saveload_captions[] = {
- STR_4001_LOAD_GAME,
- STR_0298_LOAD_SCENARIO,
- STR_4000_SAVE_GAME,
- STR_0299_SAVE_SCENARIO,
- STR_LOAD_HEIGHTMAP,
- };
-
- const WindowDesc *sld = &_save_dialog_desc;
-
- SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0);
DeleteWindowById(WC_QUERY_STRING, 0);
DeleteWindowById(WC_SAVELOAD, 0);
- _saveload_mode = mode;
- SetBit(_no_scroll, SCROLL_SAVE);
-
- /* Use an array to define what will be the current file type being handled
- * by current file mode */
- _file_to_saveload.filetype = _file_modetotype[mode];
+ const WindowDesc *sld;
switch (mode) {
- case SLD_SAVE_GAME: GenerateFileName(); break;
- case SLD_SAVE_SCENARIO: strcpy(_edit_str_buf, "UNNAMED"); break;
- default: sld = &_load_dialog_desc; break;
- }
-
- assert((uint)mode < lengthof(saveload_captions));
-
- Window *w = new Window(sld);
- w->widget[1].data = saveload_captions[mode];
- w->LowerWidget(7);
-
- WP(w, querystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, lengthof(_edit_str_buf), 240);
-
- /* pause is only used in single-player, non-editor mode, non-menu mode. It
- * will be unpaused in the WE_DESTROY event handler. */
- if (_game_mode != GM_MENU && !_networking && _game_mode != GM_EDITOR) {
- if (_pause_game >= 0) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
+ case SLD_SAVE_GAME:
+ case SLD_SAVE_SCENARIO:
+ sld = &_save_dialog_desc; break;
+ default:
+ sld = &_load_dialog_desc; break;
}
- BuildFileList();
+ _saveload_mode = mode;
+ _file_to_saveload.filetype = _file_modetotype[mode];
- ResetObjectToPlace();
+ new SaveLoadWindow(sld, mode);
}
void RedrawAutosave()
diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp
index 9ef0a88a9..41d03e4a2 100644
--- a/src/network/network_gui.cpp
+++ b/src/network/network_gui.cpp
@@ -29,6 +29,7 @@
#include "../player_func.h"
#include "../settings_type.h"
#include "../widgets/dropdown_func.h"
+#include "../querystring_gui.h"
#include "table/strings.h"
#include "../table/sprites.h"
@@ -36,15 +37,11 @@
#define BGC 5
#define BTC 15
-struct chatquerystr_d : public querystr_d {
- DestType dtype;
- int dest;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(chatquerystr_d));
-
+/*
struct network_d {
byte field; // select text-field in start-server and game-listing
byte widget_id; ///< The widget that has the pop-up input menu
+ byte field; // select text-field in start-server and game-listing
NetworkGameList *server; // selected server in lobby and game-listing
FiosItem *map; // selected map in start-server
};
@@ -53,15 +50,14 @@ assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_d));
struct network_ql_d {
network_d n; // see above; general stuff
querystr_d q; // text-input in start-server and game-listing
- NetworkGameList **sort_list; // list of games (sorted)
list_d l; // accompanying list-administration
};
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_ql_d));
+*/
/* Global to remember sorting after window has been closed */
static Listing _ng_sorting;
-static char _edit_str_net_buf[150];
static bool _chat_tab_completion_active;
static void ShowNetworkStartServerWindow();
@@ -159,64 +155,6 @@ static int CDECL NGameAllowedSorter(const void *a, const void *b)
return _internal_sort_order ? -r : r;
}
-/** (Re)build the network game list as its amount has changed because
- * an item has been added or deleted for example
- * @param ngl list_d struct that contains all necessary information for sorting */
-static void BuildNetworkGameList(network_ql_d *nqld)
-{
- NetworkGameList *ngl_temp;
- uint n = 0;
-
- if (!(nqld->l.flags & VL_REBUILD)) return;
-
- /* Count the number of games in the list */
- for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
- if (n == 0) return;
-
- /* Create temporary array of games to use for listing */
- free(nqld->sort_list);
- nqld->sort_list = MallocT<NetworkGameList*>(n);
- nqld->l.list_length = n;
-
- for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
- nqld->sort_list[n++] = ngl_temp;
- }
-
- /* Force resort */
- nqld->l.flags &= ~VL_REBUILD;
- nqld->l.flags |= VL_RESORT;
-}
-
-static void SortNetworkGameList(network_ql_d *nqld)
-{
- static NGameNameSortFunction * const ngame_sorter[] = {
- &NGameNameSorter,
- &NGameClientSorter,
- &NGameAllowedSorter
- };
-
- NetworkGameList *item;
- uint i;
-
- if (!(nqld->l.flags & VL_RESORT)) return;
- if (nqld->l.list_length == 0) return;
-
- _internal_sort_order = !!(nqld->l.flags & VL_DESC);
- qsort(nqld->sort_list, nqld->l.list_length, sizeof(nqld->sort_list[0]), ngame_sorter[nqld->l.sort_type]);
-
- /* After sorting ngl->sort_list contains the sorted items. Put these back
- * into the original list. Basically nothing has changed, we are only
- * shuffling the ->next pointers */
- _network_game_list = nqld->sort_list[0];
- for (item = _network_game_list, i = 1; i != nqld->l.list_length; i++) {
- item->next = nqld->sort_list[i];
- item = item->next;
- }
- item->next = NULL;
-
- nqld->l.flags &= ~VL_RESORT;
-}
-
/** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
enum NetworkGameWindowWidgets {
NGWW_CLOSE, ///< Close 'X' button
@@ -248,366 +186,432 @@ enum NetworkGameWindowWidgets {
NGWW_CANCEL, ///< 'Cancel' button
};
-/**
- * Draw a single server line.
- * @param cur_item the server to draw.
- * @param y from where to draw?
- * @param highlight does the line need to be highlighted?
- */
-static void DrawServerLine(const Window *w, const NetworkGameList *cur_item, uint y, bool highlight)
-{
- /* show highlighted item with a different colour */
- if (highlight) GfxFillRect(w->widget[NGWW_NAME].left + 1, y - 2, w->widget[NGWW_INFO].right - 1, y + 9, 10);
+struct NetworkGameWindow : public QueryStringBaseWindow {
+ byte field; ///< selected text-field
+ NetworkGameList *server; ///< selected server
+ NetworkGameList **sort_list; ///< list of games (sorted)
+ list_d ld; ///< accompanying list-administration
- SetDParamStr(0, cur_item->info.server_name);
- DrawStringTruncated(w->widget[NGWW_NAME].left + 5, y, STR_02BD, TC_BLACK, w->widget[NGWW_NAME].right - w->widget[NGWW_NAME].left - 5);
+ NetworkGameWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+ {
+ ttd_strlcpy(this->edit_str_buf, _network_player_name, lengthof(this->edit_str_buf));
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
+
+ UpdateNetworkGameWindow(true);
- SetDParam(0, cur_item->info.clients_on);
- SetDParam(1, cur_item->info.clients_max);
- SetDParam(2, cur_item->info.companies_on);
- SetDParam(3, cur_item->info.companies_max);
- DrawStringCentered(w->widget[NGWW_CLIENTS].left + 39, y, STR_NETWORK_GENERAL_ONLINE, TC_GOLD);
+ this->vscroll.cap = 11;
+ this->resize.step_height = NET_PRC__SIZE_OF_ROW;
- /* only draw icons if the server is online */
- if (cur_item->online) {
- /* draw a lock if the server is password protected */
- if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, w->widget[NGWW_INFO].left + 5, y - 1);
+ this->field = NGWW_PLAYER;
+ this->server = NULL;
- /* draw red or green icon, depending on compatibility with server */
- DrawSprite(SPR_BLOT, (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), w->widget[NGWW_INFO].left + 15, y);
+ this->sort_list = NULL;
+ this->ld.flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
+ this->ld.sort_type = _ng_sorting.criteria;
- /* draw flag according to server language */
- DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, w->widget[NGWW_INFO].left + 25, y);
+ this->FindWindowPlacementAndResize(desc);
}
-}
-/**
- * Handler of actions done in the NetworkStartServer window
- *
- * @param w pointer to the Window structure
- * @param e pointer to window event
- * @note Uses network_ql_d (network_d, querystr_d and list_d) WP macro
- * @see struct _network_game_window_widgets
- * @see enum NetworkGameWindowWidgets
- */
+ ~NetworkGameWindow()
+ {
+ free(this->sort_list);
+ }
-static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
- list_d *ld = &WP(w, network_ql_d).l;
+ /**
+ * (Re)build the network game list as its amount has changed because
+ * an item has been added or deleted for example
+ */
+ void BuildNetworkGameList()
+ {
+ NetworkGameList *ngl_temp;
+ uint n = 0;
- switch (e->event) {
- case WE_CREATE: // Focus input box
- w->vscroll.cap = 11;
- w->resize.step_height = NET_PRC__SIZE_OF_ROW;
+ if (!(this->ld.flags & VL_REBUILD)) return;
- nd->field = NGWW_PLAYER;
- nd->server = NULL;
+ /* Count the number of games in the list */
+ for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
+ if (n == 0) return;
- WP(w, network_ql_d).sort_list = NULL;
- ld->flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
- ld->sort_type = _ng_sorting.criteria;
- break;
+ /* Create temporary array of games to use for listing */
+ this->sort_list = ReallocT(this->sort_list, n);
+ this->ld.list_length = n;
- case WE_PAINT: {
- const NetworkGameList *sel = nd->server;
- const SortButtonState arrow = (ld->flags & VL_DESC) ? SBS_DOWN : SBS_UP;
+ for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
+ this->sort_list[n++] = ngl_temp;
+ }
- if (ld->flags & VL_REBUILD) {
- BuildNetworkGameList(&WP(w, network_ql_d));
- SetVScrollCount(w, ld->list_length);
- }
- if (ld->flags & VL_RESORT) SortNetworkGameList(&WP(w, network_ql_d));
-
- /* 'Refresh' button invisible if no server selected */
- w->SetWidgetDisabledState(NGWW_REFRESH, sel == NULL);
- /* 'Join' button disabling conditions */
- w->SetWidgetDisabledState(NGWW_JOIN, sel == NULL || // no Selected Server
- !sel->online || // Server offline
- sel->info.clients_on >= sel->info.clients_max || // Server full
- !sel->info.compatible); // Revision mismatch
-
- /* 'NewGRF Settings' button invisible if no NewGRF is used */
- w->SetWidgetHiddenState(NGWW_NEWGRF, sel == NULL ||
- !sel->online ||
- sel->info.grfconfig == NULL);
-
- SetDParam(0, 0x00);
- SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
- DrawWindowWidgets(w);
+ /* Force resort */
+ this->ld.flags &= ~VL_REBUILD;
+ this->ld.flags |= VL_RESORT;
+ }
- /* Edit box to set player name */
- DrawEditBox(w, &WP(w, network_ql_d).q, NGWW_PLAYER);
+ void SortNetworkGameList()
+ {
+ static NGameNameSortFunction * const ngame_sorter[] = {
+ &NGameNameSorter,
+ &NGameClientSorter,
+ &NGameAllowedSorter
+ };
+
+ NetworkGameList *item;
+ uint i;
+
+ if (!(this->ld.flags & VL_RESORT)) return;
+ if (this->ld.list_length == 0) return;
+
+ _internal_sort_order = !!(this->ld.flags & VL_DESC);
+ qsort(this->sort_list, this->ld.list_length, sizeof(this->sort_list[0]), ngame_sorter[this->ld.sort_type]);
+
+ /* After sorting ngl->sort_list contains the sorted items. Put these back
+ * into the original list. Basically nothing has changed, we are only
+ * shuffling the ->next pointers */
+ _network_game_list = this->sort_list[0];
+ for (item = _network_game_list, i = 1; i != this->ld.list_length; i++) {
+ item->next = this->sort_list[i];
+ item = item->next;
+ }
+ item->next = NULL;
- DrawString(w->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
+ this->ld.flags &= ~VL_RESORT;
+ }
- /* Sort based on widgets: name, clients, compatibility */
- switch (ld->sort_type) {
- case NGWW_NAME - NGWW_NAME: DrawSortButtonState(w, NGWW_NAME, arrow); break;
- case NGWW_CLIENTS - NGWW_NAME: DrawSortButtonState(w, NGWW_CLIENTS, arrow); break;
- case NGWW_INFO - NGWW_NAME: DrawSortButtonState(w, NGWW_INFO, arrow); break;
- }
+ /**
+ * Draw a single server line.
+ * @param cur_item the server to draw.
+ * @param y from where to draw?
+ * @param highlight does the line need to be highlighted?
+ */
+ void DrawServerLine(const NetworkGameList *cur_item, uint y, bool highlight)
+ {
+ /* show highlighted item with a different colour */
+ if (highlight) GfxFillRect(this->widget[NGWW_NAME].left + 1, y - 2, this->widget[NGWW_INFO].right - 1, y + 9, 10);
- uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
- int32 n = 0;
- int32 pos = w->vscroll.pos;
- const NetworkGameList *cur_item = _network_game_list;
+ SetDParamStr(0, cur_item->info.server_name);
+ DrawStringTruncated(this->widget[NGWW_NAME].left + 5, y, STR_02BD, TC_BLACK, this->widget[NGWW_NAME].right - this->widget[NGWW_NAME].left - 5);
- while (pos > 0 && cur_item != NULL) {
- pos--;
- cur_item = cur_item->next;
- }
+ SetDParam(0, cur_item->info.clients_on);
+ SetDParam(1, cur_item->info.clients_max);
+ SetDParam(2, cur_item->info.companies_on);
+ SetDParam(3, cur_item->info.companies_max);
+ DrawStringCentered(this->widget[NGWW_CLIENTS].left + 39, y, STR_NETWORK_GENERAL_ONLINE, TC_GOLD);
- while (cur_item != NULL) {
- DrawServerLine(w, cur_item, y, cur_item == sel);
+ /* only draw icons if the server is online */
+ if (cur_item->online) {
+ /* draw a lock if the server is password protected */
+ if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, this->widget[NGWW_INFO].left + 5, y - 1);
- cur_item = cur_item->next;
- y += NET_PRC__SIZE_OF_ROW;
- if (++n == w->vscroll.cap) break; // max number of games in the window
- }
+ /* draw red or green icon, depending on compatibility with server */
+ DrawSprite(SPR_BLOT, (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), this->widget[NGWW_INFO].left + 15, y);
- const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
- /* Draw the last joined server, if any */
- if (last_joined != NULL) DrawServerLine(w, last_joined, y = w->widget[NGWW_LASTJOINED].top + 3, last_joined == sel);
-
- /* Draw the right menu */
- GfxFillRect(w->widget[NGWW_DETAILS].left + 1, 43, w->widget[NGWW_DETAILS].right - 1, 92, 157);
- if (sel == NULL) {
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 58, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
- } else if (!sel->online) {
- SetDParamStr(0, sel->info.server_name);
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 68, STR_ORANGE, TC_FROMSTRING); // game name
-
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 132, STR_NETWORK_SERVER_OFFLINE, TC_FROMSTRING); // server offline
- } else { // show game info
- uint16 y = 100;
- const uint16 x = w->widget[NGWW_DETAILS].left + 5;
-
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 48, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
-
-
- SetDParamStr(0, sel->info.server_name);
- DrawStringCenteredTruncated(w->widget[NGWW_DETAILS].left, w->widget[NGWW_DETAILS].right, 62, STR_ORANGE, TC_BLACK); // game name
-
- SetDParamStr(0, sel->info.map_name);
- DrawStringCenteredTruncated(w->widget[NGWW_DETAILS].left, w->widget[NGWW_DETAILS].right, 74, STR_02BD, TC_BLACK); // map name
-
- SetDParam(0, sel->info.clients_on);
- SetDParam(1, sel->info.clients_max);
- SetDParam(2, sel->info.companies_on);
- SetDParam(3, sel->info.companies_max);
- DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
- y += 10;
-
- SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
- DrawString(x, y, STR_NETWORK_LANGUAGE, TC_GOLD); // server language
- y += 10;
-
- SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
- DrawString(x, y, STR_NETWORK_TILESET, TC_GOLD); // tileset
- y += 10;
-
- SetDParam(0, sel->info.map_width);
- SetDParam(1, sel->info.map_height);
- DrawString(x, y, STR_NETWORK_MAP_SIZE, TC_GOLD); // map size
- y += 10;
-
- SetDParamStr(0, sel->info.server_revision);
- DrawString(x, y, STR_NETWORK_SERVER_VERSION, TC_GOLD); // server version
- y += 10;
-
- SetDParamStr(0, sel->info.hostname);
- SetDParam(1, sel->port);
- DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, TC_GOLD); // server address
- y += 10;
-
- SetDParam(0, sel->info.start_date);
- DrawString(x, y, STR_NETWORK_START_DATE, TC_GOLD); // start date
- y += 10;
-
- SetDParam(0, sel->info.game_date);
- DrawString(x, y, STR_NETWORK_CURRENT_DATE, TC_GOLD); // current date
- y += 10;
-
- y += 2;
-
- if (!sel->info.compatible) {
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, TC_FROMSTRING); // server mismatch
- } else if (sel->info.clients_on == sel->info.clients_max) {
- /* Show: server full, when clients_on == clients_max */
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_SERVER_FULL, TC_FROMSTRING); // server full
- } else if (sel->info.use_password) {
- DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_PASSWORD, TC_FROMSTRING); // password warning
- }
+ /* draw flag according to server language */
+ DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, this->widget[NGWW_INFO].left + 25, y);
+ }
+ }
- y += 10;
- }
- } break;
+ virtual void OnPaint()
+ {
+ const NetworkGameList *sel = this->server;
+ const SortButtonState arrow = (this->ld.flags & VL_DESC) ? SBS_DOWN : SBS_UP;
- case WE_CLICK:
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case NGWW_PLAYER:
- ShowOnScreenKeyboard(w, &WP(w, network_ql_d).q, NGWW_PLAYER, 0, 0);
- break;
+ if (this->ld.flags & VL_REBUILD) {
+ this->BuildNetworkGameList();
+ SetVScrollCount(this, this->ld.list_length);
+ }
+ if (this->ld.flags & VL_RESORT) this->SortNetworkGameList();
+
+ /* 'Refresh' button invisible if no server selected */
+ this->SetWidgetDisabledState(NGWW_REFRESH, sel == NULL);
+ /* 'Join' button disabling conditions */
+ this->SetWidgetDisabledState(NGWW_JOIN, sel == NULL || // no Selected Server
+ !sel->online || // Server offline
+ sel->info.clients_on >= sel->info.clients_max || // Server full
+ !sel->info.compatible); // Revision mismatch
+
+ /* 'NewGRF Settings' button invisible if no NewGRF is used */
+ this->SetWidgetHiddenState(NGWW_NEWGRF, sel == NULL ||
+ !sel->online ||
+ sel->info.grfconfig == NULL);
+
+ SetDParam(0, 0x00);
+ SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
+ DrawWindowWidgets(this);
- case NGWW_CANCEL: // Cancel button
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
- break;
+ /* Edit box to set player name */
+ this->DrawEditBox(NGWW_PLAYER);
- case NGWW_CONN_BTN: // 'Connection' droplist
- ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
- break;
+ DrawString(this->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
- case NGWW_NAME: // Sort by name
- case NGWW_CLIENTS: // Sort by connected clients
- case NGWW_INFO: // Connectivity (green dot)
- if (ld->sort_type == e->we.click.widget - NGWW_NAME) ld->flags ^= VL_DESC;
- ld->flags |= VL_RESORT;
- ld->sort_type = e->we.click.widget - NGWW_NAME;
+ /* Sort based on widgets: name, clients, compatibility */
+ switch (this->ld.sort_type) {
+ case NGWW_NAME - NGWW_NAME: DrawSortButtonState(this, NGWW_NAME, arrow); break;
+ case NGWW_CLIENTS - NGWW_NAME: DrawSortButtonState(this, NGWW_CLIENTS, arrow); break;
+ case NGWW_INFO - NGWW_NAME: DrawSortButtonState(this, NGWW_INFO, arrow); break;
+ }
- _ng_sorting.order = !!(ld->flags & VL_DESC);
- _ng_sorting.criteria = ld->sort_type;
- SetWindowDirty(w);
- break;
+ uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
+ int32 n = 0;
+ int32 pos = this->vscroll.pos;
+ const NetworkGameList *cur_item = _network_game_list;
- case NGWW_MATRIX: { // Matrix to show networkgames
- NetworkGameList *cur_item;
- uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
+ while (pos > 0 && cur_item != NULL) {
+ pos--;
+ cur_item = cur_item->next;
+ }
- if (id_v >= w->vscroll.cap) return; // click out of bounds
- id_v += w->vscroll.pos;
+ while (cur_item != NULL) {
+ this->DrawServerLine(cur_item, y, cur_item == sel);
- cur_item = _network_game_list;
- for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
+ cur_item = cur_item->next;
+ y += NET_PRC__SIZE_OF_ROW;
+ if (++n == this->vscroll.cap) break; // max number of games in the window
+ }
- nd->server = cur_item;
- SetWindowDirty(w);
- } break;
+ const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+ /* Draw the last joined server, if any */
+ if (last_joined != NULL) this->DrawServerLine(last_joined, y = this->widget[NGWW_LASTJOINED].top + 3, last_joined == sel);
- case NGWW_LASTJOINED: {
- NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
- if (last_joined != NULL) {
- nd->server = last_joined;
- SetWindowDirty(w);
- }
- } break;
+ /* Draw the right menu */
+ GfxFillRect(this->widget[NGWW_DETAILS].left + 1, 43, this->widget[NGWW_DETAILS].right - 1, 92, 157);
+ if (sel == NULL) {
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 58, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
+ } else if (!sel->online) {
+ SetDParamStr(0, sel->info.server_name);
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 68, STR_ORANGE, TC_FROMSTRING); // game name
- case NGWW_FIND: // Find server automatically
- switch (_network_lan_internet) {
- case 0: NetworkUDPSearchGame(); break;
- case 1: NetworkUDPQueryMasterServer(); break;
- }
- break;
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 132, STR_NETWORK_SERVER_OFFLINE, TC_FROMSTRING); // server offline
+ } else { // show game info
+ uint16 y = 100;
+ const uint16 x = this->widget[NGWW_DETAILS].left + 5;
- case NGWW_ADD: // Add a server
- ShowQueryString(
- BindCString(_network_default_ip),
- STR_NETWORK_ENTER_IP,
- 31 | 0x1000, // maximum number of characters OR
- 250, // characters up to this width pixels, whichever is satisfied first
- w, CS_ALPHANUMERAL);
- break;
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, 48, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
- case NGWW_START: // Start server
- ShowNetworkStartServerWindow();
- break;
- case NGWW_JOIN: // Join Game
- if (nd->server != NULL) {
- snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&nd->server->ip));
- _network_last_port = nd->server->port;
- ShowNetworkLobbyWindow(nd->server);
- }
- break;
+ SetDParamStr(0, sel->info.server_name);
+ DrawStringCenteredTruncated(this->widget[NGWW_DETAILS].left, this->widget[NGWW_DETAILS].right, 62, STR_ORANGE, TC_BLACK); // game name
- case NGWW_REFRESH: // Refresh
- if (nd->server != NULL) NetworkUDPQueryServer(nd->server->info.hostname, nd->server->port);
- break;
+ SetDParamStr(0, sel->info.map_name);
+ DrawStringCenteredTruncated(this->widget[NGWW_DETAILS].left, this->widget[NGWW_DETAILS].right, 74, STR_02BD, TC_BLACK); // map name
- case NGWW_NEWGRF: // NewGRF Settings
- if (nd->server != NULL) ShowNewGRFSettings(false, false, false, &nd->server->info.grfconfig);
- break;
- }
- break;
+ SetDParam(0, sel->info.clients_on);
+ SetDParam(1, sel->info.clients_max);
+ SetDParam(2, sel->info.companies_on);
+ SetDParam(3, sel->info.companies_max);
+ DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
+ y += 10;
- case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
- switch (e->we.dropdown.button) {
- case NGWW_CONN_BTN:
- _network_lan_internet = e->we.dropdown.index;
- break;
+ SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
+ DrawString(x, y, STR_NETWORK_LANGUAGE, TC_GOLD); // server language
+ y += 10;
+
+ SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
+ DrawString(x, y, STR_NETWORK_TILESET, TC_GOLD); // tileset
+ y += 10;
+
+ SetDParam(0, sel->info.map_width);
+ SetDParam(1, sel->info.map_height);
+ DrawString(x, y, STR_NETWORK_MAP_SIZE, TC_GOLD); // map size
+ y += 10;
+
+ SetDParamStr(0, sel->info.server_revision);
+ DrawString(x, y, STR_NETWORK_SERVER_VERSION, TC_GOLD); // server version
+ y += 10;
+
+ SetDParamStr(0, sel->info.hostname);
+ SetDParam(1, sel->port);
+ DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, TC_GOLD); // server address
+ y += 10;
- default:
- NOT_REACHED();
+ SetDParam(0, sel->info.start_date);
+ DrawString(x, y, STR_NETWORK_START_DATE, TC_GOLD); // start date
+ y += 10;
+
+ SetDParam(0, sel->info.game_date);
+ DrawString(x, y, STR_NETWORK_CURRENT_DATE, TC_GOLD); // current date
+ y += 10;
+
+ y += 2;
+
+ if (!sel->info.compatible) {
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, TC_FROMSTRING); // server mismatch
+ } else if (sel->info.clients_on == sel->info.clients_max) {
+ /* Show: server full, when clients_on == clients_max */
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_SERVER_FULL, TC_FROMSTRING); // server full
+ } else if (sel->info.use_password) {
+ DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_PASSWORD, TC_FROMSTRING); // password warning
}
- SetWindowDirty(w);
- break;
+ y += 10;
+ }
+ }
- case WE_MOUSELOOP:
- if (nd->field == NGWW_PLAYER) HandleEditBox(w, &WP(w, network_ql_d).q, NGWW_PLAYER);
- break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ this->field = widget;
+ switch (widget) {
+ case NGWW_PLAYER:
+ ShowOnScreenKeyboard(this, NGWW_PLAYER, 0, 0);
+ break;
- case WE_INVALIDATE_DATA:
- if (e->we.invalidate.data != 0) nd->server = NULL;
- ld->flags |= VL_REBUILD;
- SetWindowDirty(w);
- break;
+ case NGWW_CANCEL: // Cancel button
+ DeleteWindowById(WC_NETWORK_WINDOW, 0);
+ break;
- case WE_KEYPRESS:
- if (nd->field != NGWW_PLAYER) {
- if (nd->server != NULL) {
- if (e->we.keypress.keycode == WKC_DELETE) { // Press 'delete' to remove servers
- NetworkGameListRemoveItem(nd->server);
- NetworkRebuildHostList();
- nd->server = NULL;
- }
+ case NGWW_CONN_BTN: // 'Connection' droplist
+ ShowDropDownMenu(this, _lan_internet_types_dropdown, _network_lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
+ break;
+
+ case NGWW_NAME: // Sort by name
+ case NGWW_CLIENTS: // Sort by connected clients
+ case NGWW_INFO: // Connectivity (green dot)
+ if (this->ld.sort_type == widget - NGWW_NAME) this->ld.flags ^= VL_DESC;
+ this->ld.flags |= VL_RESORT;
+ this->ld.sort_type = widget - NGWW_NAME;
+
+ _ng_sorting.order = !!(this->ld.flags & VL_DESC);
+ _ng_sorting.criteria = this->ld.sort_type;
+ this->SetDirty();
+ break;
+
+ case NGWW_MATRIX: { // Matrix to show networkgames
+ NetworkGameList *cur_item;
+ uint32 id_v = (pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
+
+ if (id_v >= this->vscroll.cap) return; // click out of bounds
+ id_v += this->vscroll.pos;
+
+ cur_item = _network_game_list;
+ for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
+
+ this->server = cur_item;
+ this->SetDirty();
+ } break;
+
+ case NGWW_LASTJOINED: {
+ NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+ if (last_joined != NULL) {
+ this->server = last_joined;
+ this->SetDirty();
+ }
+ } break;
+
+ case NGWW_FIND: // Find server automatically
+ switch (_network_lan_internet) {
+ case 0: NetworkUDPSearchGame(); break;
+ case 1: NetworkUDPQueryMasterServer(); break;
}
break;
- }
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, NGWW_PLAYER, e) == 1) break; // enter pressed
+ case NGWW_ADD: // Add a server
+ ShowQueryString(
+ BindCString(_network_default_ip),
+ STR_NETWORK_ENTER_IP,
+ 31 | 0x1000, // maximum number of characters OR
+ 250, // characters up to this width pixels, whichever is satisfied first
+ this, CS_ALPHANUMERAL);
+ break;
- /* The name is only allowed when it starts with a letter! */
- if (_edit_str_net_buf[0] != '\0' && _edit_str_net_buf[0] != ' ') {
- ttd_strlcpy(_network_player_name, _edit_str_net_buf, lengthof(_network_player_name));
- } else {
- ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
- }
+ case NGWW_START: // Start server
+ ShowNetworkStartServerWindow();
+ break;
- break;
+ case NGWW_JOIN: // Join Game
+ if (this->server != NULL) {
+ snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&this->server->ip));
+ _network_last_port = this->server->port;
+ ShowNetworkLobbyWindow(this->server);
+ }
+ break;
- case WE_ON_EDIT_TEXT:
- if (!StrEmpty(e->we.edittext.str)) {
- NetworkAddServer(e->we.edittext.str);
- NetworkRebuildHostList();
- }
- break;
+ case NGWW_REFRESH: // Refresh
+ if (this->server != NULL) NetworkUDPQueryServer(this->server->info.hostname, this->server->port);
+ break;
- case WE_RESIZE: {
- w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
+ case NGWW_NEWGRF: // NewGRF Settings
+ if (this->server != NULL) ShowNewGRFSettings(false, false, false, &this->server->info.grfconfig);
+ break;
+ }
+ }
- w->widget[NGWW_MATRIX].data = (w->vscroll.cap << 8) + 1;
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case NGWW_CONN_BTN:
+ _network_lan_internet = index;
+ break;
- SetVScrollCount(w, ld->list_length);
+ default:
+ NOT_REACHED();
+ }
+
+ this->SetDirty();
+ }
+
+ virtual void OnMouseLoop()
+ {
+ if (this->field == NGWW_PLAYER) this->HandleEditBox(NGWW_PLAYER);
+ }
- int widget_width = w->widget[NGWW_FIND].right - w->widget[NGWW_FIND].left;
- int space = (w->width - 4 * widget_width - 25) / 3;
+ virtual void OnInvalidateData(int data)
+ {
+ if (data != 0) this->server = NULL;
+ this->ld.flags |= VL_REBUILD;
+ this->SetDirty();
+ }
- int offset = 10;
- for (uint i = 0; i < 4; i++) {
- w->widget[NGWW_FIND + i].left = offset;
- offset += widget_width;
- w->widget[NGWW_FIND + i].right = offset;
- offset += space;
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ if (this->field != NGWW_PLAYER) {
+ if (this->server != NULL) {
+ if (keycode == WKC_DELETE) { // Press 'delete' to remove servers
+ NetworkGameListRemoveItem(this->server);
+ NetworkRebuildHostList();
+ this->server = NULL;
+ }
}
- } break;
+ return cont;
+ }
- case WE_DESTROY: // Nicely clean up the sort-list
- free(WP(w, network_ql_d).sort_list);
- break;
+ if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, cont) == 1) return cont; // enter pressed
+
+ /* The name is only allowed when it starts with a letter! */
+ if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
+ ttd_strlcpy(_network_player_name, this->edit_str_buf, lengthof(_network_player_name));
+ } else {
+ ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
+ }
+ return cont;
}
-}
+
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (!StrEmpty(str)) {
+ NetworkAddServer(str);
+ NetworkRebuildHostList();
+ }
+ }
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->vscroll.cap += delta.y / (int)this->resize.step_height;
+
+ this->widget[NGWW_MATRIX].data = (this->vscroll.cap << 8) + 1;
+
+ SetVScrollCount(this, this->ld.list_length);
+
+ int widget_width = this->widget[NGWW_FIND].right - this->widget[NGWW_FIND].left;
+ int space = (this->width - 4 * widget_width - 25) / 3;
+
+ int offset = 10;
+ for (uint i = 0; i < 4; i++) {
+ this->widget[NGWW_FIND + i].left = offset;
+ offset += widget_width;
+ this->widget[NGWW_FIND + i].right = offset;
+ offset += space;
+ }
+ }
+};
static const Widget _network_game_window_widgets[] = {
/* TOP */
@@ -654,7 +658,7 @@ static const WindowDesc _network_game_window_desc = {
WC_NETWORK_WINDOW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_network_game_window_widgets,
- NetworkGameWindowWndProc,
+ NULL,
};
void ShowNetworkGameWindow()
@@ -676,16 +680,7 @@ void ShowNetworkGameWindow()
_ng_sorting.order = 0; // sort ascending by default
}
- Window *w = new Window(&_network_game_window_desc);
- if (w != NULL) {
- querystr_d *querystr = &WP(w, network_ql_d).q;
-
- ttd_strlcpy(_edit_str_net_buf, _network_player_name, lengthof(_edit_str_net_buf));
- querystr->afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&querystr->text, _edit_str_net_buf, lengthof(_edit_str_net_buf), 120);
-
- UpdateNetworkGameWindow(true);
- }
+ new NetworkGameWindow(&_network_game_window_desc);
}
enum {
@@ -715,225 +710,237 @@ enum NetworkStartServerWidgets {
NSSW_CANCEL = 27, ///< 'Cancel' button
};
-/**
- * Handler of actions done in the NetworkStartServer window
- *
- * @param w pointer to the Window structure
- * @param e pointer to window event
- * @note Uses network_ql_d (network_d, querystr_d and list_d) WP macro
- * @see struct _network_start_server_window_widgets
- * @see enum NetworkStartServerWidgets
- */
-static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
+struct NetworkStartServerWindow : public QueryStringBaseWindow {
+ byte field; ///< Selected text-field
+ FiosItem *map; ///< Selected map
+ byte widget_id; ///< The widget that has the pop-up input menu
- switch (e->event) {
- case WE_CREATE: // focus input box
- nd->field = NSSW_GAMENAME;
- _network_game_info.use_password = (_network_server_password[0] != '\0');
- break;
+ NetworkStartServerWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+ {
+ ttd_strlcpy(this->edit_str_buf, _network_server_name, lengthof(this->edit_str_buf));
- case WE_PAINT: {
- int y = NSSWND_START, pos;
- const FiosItem *item;
-
- /* draw basic widgets */
- SetDParam(1, _connection_types_dropdown[_network_advertise]);
- SetDParam(2, _network_game_info.clients_max);
- SetDParam(3, _network_game_info.companies_max);
- SetDParam(4, _network_game_info.spectators_max);
- SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
- DrawWindowWidgets(w);
+ _saveload_mode = SLD_NEW_GAME;
+ BuildFileList();
+ this->vscroll.cap = 12;
+ this->vscroll.count = _fios_num + 1;
- /* editbox to set game name */
- DrawEditBox(w, &WP(w, network_ql_d).q, NSSW_GAMENAME);
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 160);
- /* if password is set, draw red '*' next to 'Set password' button */
- if (_network_game_info.use_password) DoDrawString("*", 408, 23, TC_RED);
+ this->field = NSSW_GAMENAME;
+ _network_game_info.use_password = !StrEmpty(_network_server_password);
- /* draw list of maps */
- GfxFillRect(11, 63, 258, 215, 0xD7); // black background of maps list
+ this->FindWindowPlacementAndResize(desc);
+ }
- pos = w->vscroll.pos;
- while (pos < _fios_num + 1) {
- item = _fios_list + pos - 1;
- if (item == nd->map || (pos == 0 && nd->map == NULL))
- GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
+ virtual void OnPaint()
+ {
+ int y = NSSWND_START, pos;
+ const FiosItem *item;
+
+ /* draw basic widgets */
+ SetDParam(1, _connection_types_dropdown[_network_advertise]);
+ SetDParam(2, _network_game_info.clients_max);
+ SetDParam(3, _network_game_info.companies_max);
+ SetDParam(4, _network_game_info.spectators_max);
+ SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
+ DrawWindowWidgets(this);
- if (pos == 0) {
- DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, TC_DARK_GREEN);
- } else {
- DoDrawString(item->title, 14, y, _fios_colors[item->type] );
- }
- pos++;
- y += NSSWND_ROWSIZE;
+ /* editbox to set game name */
+ this->DrawEditBox(NSSW_GAMENAME);
+
+ /* if password is set, draw red '*' next to 'Set password' button */
+ if (_network_game_info.use_password) DoDrawString("*", 408, 23, TC_RED);
+
+ /* draw list of maps */
+ GfxFillRect(11, 63, 258, 215, 0xD7); // black background of maps list
- if (y >= w->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
+ pos = this->vscroll.pos;
+ while (pos < _fios_num + 1) {
+ item = _fios_list + pos - 1;
+ if (item == this->map || (pos == 0 && this->map == NULL))
+ GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
+
+ if (pos == 0) {
+ DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, TC_DARK_GREEN);
+ } else {
+ DoDrawString(item->title, 14, y, _fios_colors[item->type] );
}
- } break;
+ pos++;
+ y += NSSWND_ROWSIZE;
- case WE_CLICK:
- if (e->we.click.widget != NSSW_CONNTYPE_BTN && e->we.click.widget != NSSW_LANGUAGE_BTN) HideDropDownMenu(w);
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case NSSW_CLOSE: // Close 'X'
- case NSSW_CANCEL: // Cancel button
- ShowNetworkGameWindow();
- break;
+ if (y >= this->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
+ }
+ }
- case NSSW_GAMENAME:
- ShowOnScreenKeyboard(w, &WP(w, network_ql_d).q, NSSW_GAMENAME, 0, 0);
- break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ if (widget != NSSW_CONNTYPE_BTN && widget != NSSW_LANGUAGE_BTN) HideDropDownMenu(this);
+ this->field = widget;
+ switch (widget) {
+ case NSSW_CLOSE: // Close 'X'
+ case NSSW_CANCEL: // Cancel button
+ ShowNetworkGameWindow();
+ break;
- case NSSW_SETPWD: // Set password button
- nd->widget_id = NSSW_SETPWD;
- ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
- break;
+ case NSSW_GAMENAME:
+ ShowOnScreenKeyboard(this, NSSW_GAMENAME, 0, 0);
+ break;
- case NSSW_SELMAP: { // Select map
- int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
+ case NSSW_SETPWD: // Set password button
+ this->widget_id = NSSW_SETPWD;
+ ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, this, CS_ALPHANUMERAL);
+ break;
- y += w->vscroll.pos;
- if (y >= w->vscroll.count) return;
+ case NSSW_SELMAP: { // Select map
+ int y = (pt.y - NSSWND_START) / NSSWND_ROWSIZE;
- nd->map = (y == 0) ? NULL : _fios_list + y - 1;
- SetWindowDirty(w);
- } break;
+ y += this->vscroll.pos;
+ if (y >= this->vscroll.count) return;
- case NSSW_CONNTYPE_BTN: // Connection type
- ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, NSSW_CONNTYPE_BTN, 0, 0); // do it for widget NSSW_CONNTYPE_BTN
- break;
+ this->map = (y == 0) ? NULL : _fios_list + y - 1;
+ this->SetDirty();
+ } break;
+
+ case NSSW_CONNTYPE_BTN: // Connection type
+ ShowDropDownMenu(this, _connection_types_dropdown, _network_advertise, NSSW_CONNTYPE_BTN, 0, 0); // do it for widget NSSW_CONNTYPE_BTN
+ break;
- case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU: // Click on up/down button for number of clients
- case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU: // Click on up/down button for number of companies
- case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU: // Click on up/down button for number of spectators
- /* Don't allow too fast scrolling */
- if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
- w->HandleButtonClick(e->we.click.widget);
- SetWindowDirty(w);
- switch (e->we.click.widget) {
- default: NOT_REACHED();
- case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU:
- _network_game_info.clients_max = Clamp(_network_game_info.clients_max + e->we.click.widget - NSSW_CLIENTS_TXT, 2, MAX_CLIENTS);
- break;
- case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU:
- _network_game_info.companies_max = Clamp(_network_game_info.companies_max + e->we.click.widget - NSSW_COMPANIES_TXT, 1, MAX_PLAYERS);
- break;
- case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU:
- _network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + e->we.click.widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
- break;
- }
+ case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU: // Click on up/down button for number of clients
+ case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU: // Click on up/down button for number of companies
+ case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU: // Click on up/down button for number of spectators
+ /* Don't allow too fast scrolling */
+ if ((this->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
+ this->HandleButtonClick(widget);
+ this->SetDirty();
+ switch (widget) {
+ default: NOT_REACHED();
+ case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU:
+ _network_game_info.clients_max = Clamp(_network_game_info.clients_max + widget - NSSW_CLIENTS_TXT, 2, MAX_CLIENTS);
+ break;
+ case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU:
+ _network_game_info.companies_max = Clamp(_network_game_info.companies_max + widget - NSSW_COMPANIES_TXT, 1, MAX_PLAYERS);
+ break;
+ case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU:
+ _network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
+ break;
}
- _left_button_clicked = false;
- break;
+ }
+ _left_button_clicked = false;
+ break;
- case NSSW_CLIENTS_TXT: // Click on number of players
- nd->widget_id = NSSW_CLIENTS_TXT;
- SetDParam(0, _network_game_info.clients_max);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, w, CS_NUMERAL);
- break;
+ case NSSW_CLIENTS_TXT: // Click on number of players
+ this->widget_id = NSSW_CLIENTS_TXT;
+ SetDParam(0, _network_game_info.clients_max);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, this, CS_NUMERAL);
+ break;
- case NSSW_COMPANIES_TXT: // Click on number of companies
- nd->widget_id = NSSW_COMPANIES_TXT;
- SetDParam(0, _network_game_info.companies_max);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES, 3, 50, w, CS_NUMERAL);
- break;
+ case NSSW_COMPANIES_TXT: // Click on number of companies
+ this->widget_id = NSSW_COMPANIES_TXT;
+ SetDParam(0, _network_game_info.companies_max);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES, 3, 50, this, CS_NUMERAL);
+ break;
- case NSSW_SPECTATORS_TXT: // Click on number of spectators
- nd->widget_id = NSSW_SPECTATORS_TXT;
- SetDParam(0, _network_game_info.spectators_max);
- ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, w, CS_NUMERAL);
- break;
+ case NSSW_SPECTATORS_TXT: // Click on number of spectators
+ this->widget_id = NSSW_SPECTATORS_TXT;
+ SetDParam(0, _network_game_info.spectators_max);
+ ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, this, CS_NUMERAL);
+ break;
- case NSSW_LANGUAGE_BTN: { // Language
- uint sel = 0;
- for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
- if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
- sel = i;
- break;
- }
+ case NSSW_LANGUAGE_BTN: { // Language
+ uint sel = 0;
+ for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
+ if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
+ sel = i;
+ break;
}
- ShowDropDownMenu(w, _language_dropdown, sel, NSSW_LANGUAGE_BTN, 0, 0);
- } break;
-
- case NSSW_START: // Start game
- _is_network_server = true;
-
- if (nd->map == NULL) { // start random new game
- ShowGenerateLandscape();
- } else { // load a scenario
- char *name = FiosBrowseTo(nd->map);
- if (name != NULL) {
- SetFiosType(nd->map->type);
- _file_to_saveload.filetype = FT_SCENARIO;
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, nd->map->title, sizeof(_file_to_saveload.title));
-
- delete w;
- SwitchMode(SM_START_SCENARIO);
- }
+ }
+ ShowDropDownMenu(this, _language_dropdown, sel, NSSW_LANGUAGE_BTN, 0, 0);
+ } break;
+
+ case NSSW_START: // Start game
+ _is_network_server = true;
+
+ if (this->map == NULL) { // start random new game
+ ShowGenerateLandscape();
+ } else { // load a scenario
+ char *name = FiosBrowseTo(this->map);
+ if (name != NULL) {
+ SetFiosType(this->map->type);
+ _file_to_saveload.filetype = FT_SCENARIO;
+ ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+ ttd_strlcpy(_file_to_saveload.title, this->map->title, sizeof(_file_to_saveload.title));
+
+ delete this;
+ SwitchMode(SM_START_SCENARIO);
}
- break;
+ }
+ break;
- case NSSW_LOAD: // Load game
- _is_network_server = true;
- /* XXX - WC_NETWORK_WINDOW (this window) should stay, but if it stays, it gets
- * copied all the elements of 'load game' and upon closing that, it segfaults */
- delete w;
- ShowSaveLoadDialog(SLD_LOAD_GAME);
- break;
- }
- break;
+ case NSSW_LOAD: // Load game
+ _is_network_server = true;
+ /* XXX - WC_NETWORK_WINDOW (this window) should stay, but if it stays, it gets
+ * copied all the elements of 'load game' and upon closing that, it segfaults */
+ delete this;
+ ShowSaveLoadDialog(SLD_LOAD_GAME);
+ break;
+ }
+ }
- case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
- switch (e->we.dropdown.button) {
- case NSSW_CONNTYPE_BTN:
- _network_advertise = (e->we.dropdown.index != 0);
- break;
- case NSSW_LANGUAGE_BTN:
- _network_game_info.server_lang = _language_dropdown[e->we.dropdown.index] - STR_NETWORK_LANG_ANY;
- break;
- default:
- NOT_REACHED();
- }
+ virtual void OnDropdownSelect(int widget, int index)
+ {
+ switch (widget) {
+ case NSSW_CONNTYPE_BTN:
+ _network_advertise = (index != 0);
+ break;
+ case NSSW_LANGUAGE_BTN:
+ _network_game_info.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
+ break;
+ default:
+ NOT_REACHED();
+ }
- SetWindowDirty(w);
- break;
+ this->SetDirty();
+ }
- case WE_MOUSELOOP:
- if (nd->field == NSSW_GAMENAME) HandleEditBox(w, &WP(w, network_ql_d).q, NSSW_GAMENAME);
- break;
+ virtual void OnMouseLoop()
+ {
+ if (this->field == NSSW_GAMENAME) this->HandleEditBox(NSSW_GAMENAME);
+ }
- case WE_KEYPRESS:
- if (nd->field == NSSW_GAMENAME) {
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, NSSW_GAMENAME, e) == 1) break; // enter pressed
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ if (this->field == NSSW_GAMENAME) {
+ if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, cont) == 1) return cont; // enter pressed
- ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
- }
- break;
+ ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name));
+ }
- case WE_ON_EDIT_TEXT:
- if (e->we.edittext.str == NULL) break;
+ return cont;
+ }
- if (nd->widget_id == NSSW_SETPWD) {
- ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
- _network_game_info.use_password = !StrEmpty(_network_server_password);
- } else {
- int32 value = atoi(e->we.edittext.str);
- w->InvalidateWidget(nd->widget_id);
- switch (nd->widget_id) {
- default: NOT_REACHED();
- case NSSW_CLIENTS_TXT: _network_game_info.clients_max = Clamp(value, 2, MAX_CLIENTS); break;
- case NSSW_COMPANIES_TXT: _network_game_info.companies_max = Clamp(value, 1, MAX_PLAYERS); break;
- case NSSW_SPECTATORS_TXT: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
- }
+ virtual void OnQueryTextFinished(char *str)
+ {
+ if (str == NULL) return;
+
+ if (this->widget_id == NSSW_SETPWD) {
+ ttd_strlcpy(_network_server_password, str, lengthof(_network_server_password));
+ _network_game_info.use_password = !StrEmpty(_network_server_password);
+ } else {
+ int32 value = atoi(str);
+ this->InvalidateWidget(this->widget_id);
+ switch (this->widget_id) {
+ default: NOT_REACHED();
+ case NSSW_CLIENTS_TXT: _network_game_info.clients_max = Clamp(value, 2, MAX_CLIENTS); break;
+ case NSSW_COMPANIES_TXT: _network_game_info.companies_max = Clamp(value, 1, MAX_PLAYERS); break;
+ case NSSW_SPECTATORS_TXT: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
}
+ }
- SetWindowDirty(w);
- break;
+ this->SetDirty();
}
-}
+};
static const Widget _network_start_server_window_widgets[] = {
/* Window decoration and background panel */
@@ -986,23 +993,14 @@ static const WindowDesc _network_start_server_window_desc = {
WC_NETWORK_WINDOW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_network_start_server_window_widgets,
- NetworkStartServerWindowWndProc,
+ NULL,
};
static void ShowNetworkStartServerWindow()
{
DeleteWindowById(WC_NETWORK_WINDOW, 0);
- Window *w = new Window(&_network_start_server_window_desc);
- ttd_strlcpy(_edit_str_net_buf, _network_server_name, lengthof(_edit_str_net_buf));
-
- _saveload_mode = SLD_NEW_GAME;
- BuildFileList();
- w->vscroll.cap = 12;
- w->vscroll.count = _fios_num + 1;
-
- WP(w, network_ql_d).q.afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, network_ql_d).q.text, _edit_str_net_buf, lengthof(_edit_str_net_buf), 160);
+ new NetworkStartServerWindow(&_network_start_server_window_desc);
}
static PlayerID NetworkLobbyFindCompanyIndex(byte pos)
@@ -1036,7 +1034,6 @@ struct NetworkLobbyWindow : public Window {
NetworkLobbyWindow(const WindowDesc *desc, NetworkGameList *ngl) :
Window(desc), company(INVALID_PLAYER), server(ngl)
{
- strcpy(_edit_str_net_buf, "");
this->vscroll.cap = 10;
this->FindWindowPlacementAndResize(desc);
@@ -1370,10 +1367,10 @@ static bool CheckClientListHeight(Window *w)
/* If height is changed */
if (w->height != CLNWND_OFFSET + num + 1) {
// XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
- SetWindowDirty(w);
+ w->SetDirty();
w->widget[3].bottom = w->widget[3].top + num + 2;
w->height = CLNWND_OFFSET + num + 1;
- SetWindowDirty(w);
+ w->SetDirty();
return false;
}
return true;
@@ -1508,7 +1505,7 @@ static void ClientListPopupWndProc(Window *w, WindowEvent *e)
if (index == -1 || index == WP(w, menu_d).sel_index) return;
WP(w, menu_d).sel_index = index;
- SetWindowDirty(w);
+ w->SetDirty();
} else {
if (index >= 0 && _cursor.pos.y >= w->top) {
HandleClientListPopupClick(index, WP(w, menu_d).main_button);
@@ -1573,7 +1570,7 @@ static void ClientListWndProc(Window *w, WindowEvent *e)
if (e->we.mouseover.pt.y == -1) {
_selected_clientlist_y = 0;
_selected_clientlist_item = 255;
- SetWindowDirty(w);
+ w->SetDirty();
break;
}
/* It did not change.. no update! */
@@ -1588,7 +1585,7 @@ static void ClientListWndProc(Window *w, WindowEvent *e)
}
/* Repaint */
- SetWindowDirty(w);
+ w->SetDirty();
break;
case WE_DESTROY: case WE_CREATE:
@@ -1706,202 +1703,217 @@ static void SendChat(const char *buf, DestType type, int dest)
}
}
-/**
- * Find the next item of the list of things that can be auto-completed.
- * @param item The current indexed item to return. This function can, and most
- * likely will, alter item, to skip empty items in the arrays.
- * @return Returns the char that matched to the index.
- */
-static const char *ChatTabCompletionNextItem(uint *item)
-{
- static char chat_tab_temp_buffer[64];
- /* First, try clients */
- if (*item < MAX_CLIENT_INFO) {
- /* Skip inactive clients */
- while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
- if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
+struct NetworkChatWindow : public QueryStringBaseWindow {
+ DestType dtype;
+ int dest;
+
+ NetworkChatWindow (const WindowDesc *desc, DestType type, int dest) : QueryStringBaseWindow(desc)
+ {
+ this->LowerWidget(2);
+ this->dtype = type;
+ this->dest = dest;
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 0);
+
+ InvalidateWindowData(WC_NEWS_WINDOW, 0, this->height);
+ SetBit(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
+
+ _chat_tab_completion_active = false;
+
+ this->FindWindowPlacementAndResize(desc);
}
- /* Then, try townnames */
- /* Not that the following assumes all town indices are adjacent, ie no
- * towns have been deleted. */
- if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
- const Town *t;
-
- FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
- /* Get the town-name via the string-system */
- SetDParam(0, t->index);
- GetString(chat_tab_temp_buffer, STR_TOWN, lastof(chat_tab_temp_buffer));
- return &chat_tab_temp_buffer[0];
+ ~NetworkChatWindow ()
+ {
+ InvalidateWindowData(WC_NEWS_WINDOW, 0, 0);
+ ClrBit(_no_scroll, SCROLL_CHAT);
+ }
+
+ /**
+ * Find the next item of the list of things that can be auto-completed.
+ * @param item The current indexed item to return. This function can, and most
+ * likely will, alter item, to skip empty items in the arrays.
+ * @return Returns the char that matched to the index.
+ */
+ const char *ChatTabCompletionNextItem(uint *item)
+ {
+ static char chat_tab_temp_buffer[64];
+
+ /* First, try clients */
+ if (*item < MAX_CLIENT_INFO) {
+ /* Skip inactive clients */
+ while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
+ if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
}
+
+ /* Then, try townnames */
+ /* Not that the following assumes all town indices are adjacent, ie no
+ * towns have been deleted. */
+ if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
+ const Town *t;
+
+ FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
+ /* Get the town-name via the string-system */
+ SetDParam(0, t->index);
+ GetString(chat_tab_temp_buffer, STR_TOWN, lastof(chat_tab_temp_buffer));
+ return &chat_tab_temp_buffer[0];
+ }
+ }
+
+ return NULL;
}
- return NULL;
-}
+ /**
+ * Find what text to complete. It scans for a space from the left and marks
+ * the word right from that as to complete. It also writes a \0 at the
+ * position of the space (if any). If nothing found, buf is returned.
+ */
+ static char *ChatTabCompletionFindText(char *buf)
+ {
+ char *p = strrchr(buf, ' ');
+ if (p == NULL) return buf;
-/**
- * Find what text to complete. It scans for a space from the left and marks
- * the word right from that as to complete. It also writes a \0 at the
- * position of the space (if any). If nothing found, buf is returned.
- */
-static char *ChatTabCompletionFindText(char *buf)
-{
- char *p = strrchr(buf, ' ');
- if (p == NULL) return buf;
+ *p = '\0';
+ return p + 1;
+ }
- *p = '\0';
- return p + 1;
-}
+ /**
+ * See if we can auto-complete the current text of the user.
+ */
+ void ChatTabCompletion()
+ {
+ static char _chat_tab_completion_buf[lengthof(this->edit_str_buf)];
+ Textbuf *tb = &this->text;
+ size_t len, tb_len;
+ uint item;
+ char *tb_buf, *pre_buf;
+ const char *cur_name;
+ bool second_scan = false;
+
+ item = 0;
+
+ /* Copy the buffer so we can modify it without damaging the real data */
+ pre_buf = (_chat_tab_completion_active) ? strdup(_chat_tab_completion_buf) : strdup(tb->buf);
+
+ tb_buf = ChatTabCompletionFindText(pre_buf);
+ tb_len = strlen(tb_buf);
+
+ while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
+ item++;
+
+ if (_chat_tab_completion_active) {
+ /* We are pressing TAB again on the same name, is there an other name
+ * that starts with this? */
+ if (!second_scan) {
+ size_t offset;
+ size_t length;
+
+ /* If we are completing at the begin of the line, skip the ': ' we added */
+ if (tb_buf == pre_buf) {
+ offset = 0;
+ length = tb->length - 2;
+ } else {
+ /* Else, find the place we are completing at */
+ offset = strlen(pre_buf) + 1;
+ length = tb->length - offset;
+ }
-/**
- * See if we can auto-complete the current text of the user.
- */
-static void ChatTabCompletion(Window *w)
-{
- static char _chat_tab_completion_buf[lengthof(_edit_str_net_buf)];
- Textbuf *tb = &WP(w, chatquerystr_d).text;
- size_t len, tb_len;
- uint item;
- char *tb_buf, *pre_buf;
- const char *cur_name;
- bool second_scan = false;
-
- item = 0;
-
- /* Copy the buffer so we can modify it without damaging the real data */
- pre_buf = (_chat_tab_completion_active) ? strdup(_chat_tab_completion_buf) : strdup(tb->buf);
-
- tb_buf = ChatTabCompletionFindText(pre_buf);
- tb_len = strlen(tb_buf);
-
- while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
- item++;
-
- if (_chat_tab_completion_active) {
- /* We are pressing TAB again on the same name, is there an other name
- * that starts with this? */
- if (!second_scan) {
- size_t offset;
- size_t length;
-
- /* If we are completing at the begin of the line, skip the ': ' we added */
- if (tb_buf == pre_buf) {
- offset = 0;
- length = tb->length - 2;
- } else {
- /* Else, find the place we are completing at */
- offset = strlen(pre_buf) + 1;
- length = tb->length - offset;
- }
+ /* Compare if we have a match */
+ if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
- /* Compare if we have a match */
- if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
+ continue;
+ }
- continue;
+ /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
}
- /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
- }
+ len = strlen(cur_name);
+ if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
+ /* Save the data it was before completion */
+ if (!second_scan) snprintf(_chat_tab_completion_buf, lengthof(_chat_tab_completion_buf), "%s", tb->buf);
+ _chat_tab_completion_active = true;
- len = strlen(cur_name);
- if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
- /* Save the data it was before completion */
- if (!second_scan) snprintf(_chat_tab_completion_buf, lengthof(_chat_tab_completion_buf), "%s", tb->buf);
- _chat_tab_completion_active = true;
+ /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
+ if (pre_buf == tb_buf) {
+ snprintf(tb->buf, lengthof(this->edit_str_buf), "%s: ", cur_name);
+ } else {
+ snprintf(tb->buf, lengthof(this->edit_str_buf), "%s %s", pre_buf, cur_name);
+ }
- /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
- if (pre_buf == tb_buf) {
- snprintf(tb->buf, lengthof(_edit_str_net_buf), "%s: ", cur_name);
- } else {
- snprintf(tb->buf, lengthof(_edit_str_net_buf), "%s %s", pre_buf, cur_name);
+ /* Update the textbuffer */
+ UpdateTextBufferSize(&this->text);
+
+ this->SetDirty();
+ free(pre_buf);
+ return;
}
+ }
+
+ if (second_scan) {
+ /* We walked all posibilities, and the user presses tab again.. revert to original text */
+ strcpy(tb->buf, _chat_tab_completion_buf);
+ _chat_tab_completion_active = false;
/* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, chatquerystr_d).text);
+ UpdateTextBufferSize(&this->text);
- SetWindowDirty(w);
- free(pre_buf);
- return;
+ this->SetDirty();
}
+ free(pre_buf);
}
- if (second_scan) {
- /* We walked all posibilities, and the user presses tab again.. revert to original text */
- strcpy(tb->buf, _chat_tab_completion_buf);
- _chat_tab_completion_active = false;
+ virtual void OnPaint()
+ {
+ static const StringID chat_captions[] = {
+ STR_NETWORK_CHAT_ALL_CAPTION,
+ STR_NETWORK_CHAT_COMPANY_CAPTION,
+ STR_NETWORK_CHAT_CLIENT_CAPTION
+ };
- /* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, chatquerystr_d).text);
+ DrawWindowWidgets(this);
- SetWindowDirty(w);
+ assert((uint)this->dtype < lengthof(chat_captions));
+ DrawStringRightAligned(this->widget[2].left - 2, this->widget[2].top + 1, chat_captions[this->dtype], TC_BLACK);
+ this->DrawEditBox(2);
}
- free(pre_buf);
-}
-/*
- * uses chatquerystr_d WP macro
- * uses chatquerystr_d->dtype to store type of chat message (Private/Team/All)
- */
-static void ChatWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_CREATE:
- InvalidateWindowData(WC_NEWS_WINDOW, 0, w->height);
- SetBit(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
- break;
-
- case WE_PAINT: {
- static const StringID chat_captions[] = {
- STR_NETWORK_CHAT_ALL_CAPTION,
- STR_NETWORK_CHAT_COMPANY_CAPTION,
- STR_NETWORK_CHAT_CLIENT_CAPTION
- };
-
- DrawWindowWidgets(w);
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case 2:
+ ShowOnScreenKeyboard(this, 2, 0, 3);
+ break;
- assert((uint)WP(w, chatquerystr_d).dtype < lengthof(chat_captions));
- DrawStringRightAligned(w->widget[2].left - 2, w->widget[2].top + 1, chat_captions[WP(w, chatquerystr_d).dtype], TC_BLACK);
- DrawEditBox(w, &WP(w, chatquerystr_d), 2);
- } break;
+ case 3: /* Send */
+ SendChat(this->text.buf, this->dtype, this->dest);
+ /* FALLTHROUGH */
+ case 0: /* Cancel */ delete this; break;
+ }
+ }
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 2:
- ShowOnScreenKeyboard(w, &WP(w, chatquerystr_d), 2, 0, 3);
- break;
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(2);
+ }
- case 3: /* Send */
- SendChat(WP(w, chatquerystr_d).text.buf, WP(w, chatquerystr_d).dtype, WP(w, chatquerystr_d).dest);
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ if (keycode == WKC_TAB) {
+ ChatTabCompletion();
+ } else {
+ _chat_tab_completion_active = false;
+ switch (this->HandleEditBoxKey(2, key, keycode, cont)) {
+ case 1: /* Return */
+ SendChat(this->text.buf, this->dtype, this->dest);
/* FALLTHROUGH */
- case 0: /* Cancel */ delete w; break;
+ case 2: /* Escape */ delete this; break;
}
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, &WP(w, chatquerystr_d), 2);
- break;
-
- case WE_KEYPRESS:
- if (e->we.keypress.keycode == WKC_TAB) {
- ChatTabCompletion(w);
- } else {
- _chat_tab_completion_active = false;
- switch (HandleEditBoxKey(w, &WP(w, chatquerystr_d), 2, e)) {
- case 1: /* Return */
- SendChat(WP(w, chatquerystr_d).text.buf, WP(w, chatquerystr_d).dtype, WP(w, chatquerystr_d).dest);
- /* FALLTHROUGH */
- case 2: /* Escape */ delete w; break;
- }
- }
- break;
-
- case WE_DESTROY:
- InvalidateWindowData(WC_NEWS_WINDOW, 0, 0);
- ClrBit(_no_scroll, SCROLL_CHAT);
- break;
+ }
+ return cont;
}
-}
+};
static const Widget _chat_window_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -1916,23 +1928,13 @@ static const WindowDesc _chat_window_desc = {
WC_SEND_NETWORK_MSG, WC_NONE,
WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
_chat_window_widgets,
- ChatWindowWndProc
+ NULL
};
void ShowNetworkChatQueryWindow(DestType type, int dest)
{
DeleteWindowById(WC_SEND_NETWORK_MSG, 0);
-
- _edit_str_net_buf[0] = '\0';
- _chat_tab_completion_active = false;
-
- Window *w = new Window(&_chat_window_desc);
-
- w->LowerWidget(2);
- WP(w, chatquerystr_d).dtype = type;
- WP(w, chatquerystr_d).dest = dest;
- WP(w, chatquerystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, chatquerystr_d).text, _edit_str_net_buf, lengthof(_edit_str_net_buf), 0);
+ new NetworkChatWindow (&_chat_window_desc, type, dest);
}
/** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
@@ -1947,61 +1949,75 @@ enum NetworkCompanyPasswordWindowWidgets {
NCPWW_OK, ///< Safe the password etc.
};
-static void NetworkCompanyPasswordWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT:
- DrawWindowWidgets(w);
- DrawEditBox(w, &WP(w, chatquerystr_d), 4);
- break;
+struct NetworkCompanyPasswordWindow : public QueryStringBaseWindow {
+ NetworkCompanyPasswordWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+ {
+ this->afilter = CS_ALPHANUMERAL;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_network_default_company_pass), lengthof(this->edit_str_buf)), 0);
- case WE_CLICK:
- switch (e->we.click.widget) {
- case NCPWW_OK: {
- if (w->IsWidgetLowered(NCPWW_SAVE_AS_DEFAULT_PASSWORD)) {
- snprintf(_network_default_company_pass, lengthof(_network_default_company_pass), "%s", _edit_str_net_buf);
- }
+ this->FindWindowPlacementAndResize(desc);
+ }
- /* empty password is a '*' because of console argument */
- if (StrEmpty(_edit_str_net_buf)) snprintf(_edit_str_net_buf, lengthof(_edit_str_net_buf), "*");
- char *password = _edit_str_net_buf;
- NetworkChangeCompanyPassword(1, &password);
- }
+ void OnOk()
+ {
+ if (this->IsWidgetLowered(NCPWW_SAVE_AS_DEFAULT_PASSWORD)) {
+ snprintf(_network_default_company_pass, lengthof(_network_default_company_pass), "%s", this->edit_str_buf);
+ }
- /* FALL THROUGH */
- case NCPWW_CANCEL:
- delete w;
- break;
+ /* empty password is a '*' because of console argument */
+ if (StrEmpty(this->edit_str_buf)) snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "*");
+ char *password = this->edit_str_buf;
+ NetworkChangeCompanyPassword(1, &password);
+ }
- case NCPWW_SAVE_AS_DEFAULT_PASSWORD:
- w->ToggleWidgetLoweredState(NCPWW_SAVE_AS_DEFAULT_PASSWORD);
- SetWindowDirty(w);
- break;
- case NCPWW_PASSWORD:
- ShowOnScreenKeyboard(w, &WP(w, chatquerystr_d), NCPWW_PASSWORD, 2, 1);
- break;
- }
- break;
+ virtual void OnPaint()
+ {
+ DrawWindowWidgets(this);
+ this->DrawEditBox(4);
+ }
- case WE_MOUSELOOP:
- HandleEditBox(w, &WP(w, chatquerystr_d), 4);
- break;
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case NCPWW_OK:
+ this->OnOk();
- case WE_KEYPRESS:
- switch (HandleEditBoxKey(w, &WP(w, chatquerystr_d), 4, e)) {
- case 1: // Return
- e->event = WE_CLICK;
- e->we.click.widget = NCPWW_OK;
- NetworkCompanyPasswordWindowWndProc(w, e);
- break;
+ /* FALL THROUGH */
+ case NCPWW_CANCEL:
+ delete this;
+ break;
- case 2: // Escape
- delete w;
- break;
- }
- break;
+ case NCPWW_SAVE_AS_DEFAULT_PASSWORD:
+ this->ToggleWidgetLoweredState(NCPWW_SAVE_AS_DEFAULT_PASSWORD);
+ this->SetDirty();
+ break;
+
+ case NCPWW_PASSWORD:
+ ShowOnScreenKeyboard(this, NCPWW_PASSWORD, 2, 1);
+ break;
+ }
}
-}
+
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(4);
+ }
+
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont;
+ switch (this->HandleEditBoxKey(4, key, keycode, cont)) {
+ case 1: // Return
+ this->OnOk();
+ /* FALL THROUGH */
+
+ case 2: // Escape
+ delete this;
+ break;
+ }
+ return cont;
+ }
+};
static const Widget _ncp_window_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -2020,17 +2036,14 @@ static const WindowDesc _ncp_window_desc = {
WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
_ncp_window_widgets,
- NetworkCompanyPasswordWindowWndProc
+ NULL
};
void ShowNetworkCompanyPasswordWindow()
{
DeleteWindowById(WC_COMPANY_PASSWORD_WINDOW, 0);
- _edit_str_net_buf[0] = '\0';
- Window *w = new Window(&_ncp_window_desc);
- WP(w, chatquerystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, chatquerystr_d).text, _edit_str_net_buf, min(lengthof(_network_default_company_pass), lengthof(_edit_str_net_buf)), 0);
+ new NetworkCompanyPasswordWindow(&_ncp_window_desc);
}
#endif /* ENABLE_NETWORK */
diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp
index 432c207bf..b3955a822 100644
--- a/src/osk_gui.cpp
+++ b/src/osk_gui.cpp
@@ -12,20 +12,11 @@
#include "debug.h"
#include "window_func.h"
#include "gfx_func.h"
+#include "querystring_gui.h"
#include "table/sprites.h"
#include "table/strings.h"
-struct osk_d {
- querystr_d *qs; // text-input
- int text_btn; // widget number of parent's text field
- int ok_btn; // widget number of parent's ok button (=0 when ok shouldn't be passed on)
- int cancel_btn; // widget number of parent's cancel button (=0 when cancel shouldn't be passed on; text will be reverted to original)
- Textbuf *text; // pointer to parent's textbuffer (to update caret position)
- char *orig; // the original text, in case we cancel
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(osk_d));
-
enum OskWidgets {
OSK_WIDGET_TEXT = 3,
OSK_WIDGET_CANCEL = 5,
@@ -50,142 +41,162 @@ enum {
};
static byte _keystate = KEYS_NONE;
-/*
- * Only show valid characters; do not show characters that would
- * only insert a space when we have a spacebar to do that or
- * characters that are not allowed to be entered.
- */
-static void ChangeOskDiabledState(Window *w, const querystr_d *qs, bool shift)
-{
- for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
- w->SetWidgetDisabledState(OSK_WIDGET_LETTERS + i,
- !IsValidChar(_keyboard[shift][i], qs->afilter) || _keyboard[shift][i] == ' ');
+struct OskWindow : public Window {
+ QueryString *qs; ///< text-input
+ int text_btn; ///< widget number of parent's text field
+ int ok_btn; ///< widget number of parent's ok button (=0 when ok shouldn't be passed on)
+ int cancel_btn; ///< widget number of parent's cancel button (=0 when cancel shouldn't be passed on; text will be reverted to original)
+ Textbuf *text; ///< pointer to parent's textbuffer (to update caret position)
+ char orig_str_buf[64]; ///< Original string.
+
+ OskWindow(const WindowDesc *desc, QueryStringBaseWindow *parent, int button, int cancel, int ok) : Window(desc)
+ {
+ this->parent = parent;
+ assert(parent != NULL);
+
+ if (parent->widget[button].data != 0) parent->caption = parent->widget[button].data;
+
+ this->qs = parent;
+ this->text_btn = button;
+ this->cancel_btn = cancel;
+ this->ok_btn = ok;
+ this->text = &parent->text;
+
+ /* make a copy in case we need to reset later */
+ strcpy(this->orig_str_buf, this->qs->text.buf);
+
+ SetBit(_no_scroll, SCROLL_EDIT);
+ /* Not needed by default. */
+ this->DisableWidget(OSK_WIDGET_SPECIAL);
+
+ this->FindWindowPlacementAndResize(desc);
}
- w->SetWidgetDisabledState(OSK_WIDGET_SPACE, !IsValidChar(' ', qs->afilter));
-}
-/* on screen keyboard */
-static void OskWndProc(Window *w, WindowEvent *e)
-{
- querystr_d *qs = WP(w, osk_d).qs;
+ /**
+ * Only show valid characters; do not show characters that would
+ * only insert a space when we have a spacebar to do that or
+ * characters that are not allowed to be entered.
+ */
+ void ChangeOskDiabledState(bool shift)
+ {
+ for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
+ this->SetWidgetDisabledState(OSK_WIDGET_LETTERS + i,
+ !IsValidChar(_keyboard[shift][i], this->qs->afilter) || _keyboard[shift][i] == ' ');
+ }
+ this->SetWidgetDisabledState(OSK_WIDGET_SPACE, !IsValidChar(' ', this->qs->afilter));
+ }
+
+ virtual void OnPaint()
+ {
+ bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
+
+ this->LowerWidget(OSK_WIDGET_TEXT);
+ this->SetWidgetLoweredState(OSK_WIDGET_SHIFT, HasBit(_keystate, KEYS_SHIFT));
+ this->SetWidgetLoweredState(OSK_WIDGET_CAPS, HasBit(_keystate, KEYS_CAPS));
- switch (e->event) {
- case WE_CREATE:
- SetBit(_no_scroll, SCROLL_EDIT);
- /* Not needed by default. */
- w->DisableWidget(OSK_WIDGET_SPECIAL);
- break;
+ this->ChangeOskDiabledState(shift);
- case WE_PAINT: {
+ SetDParam(0, this->qs->caption);
+ DrawWindowWidgets(this);
+
+ for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
+ DrawCharCentered(_keyboard[shift][i],
+ this->widget[OSK_WIDGET_LETTERS + i].left + 8,
+ this->widget[OSK_WIDGET_LETTERS + i].top + 3,
+ TC_BLACK);
+ }
+
+ this->qs->DrawEditBox(this, OSK_WIDGET_TEXT);
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ /* clicked a letter */
+ if (widget >= OSK_WIDGET_LETTERS) {
bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
- w->LowerWidget(OSK_WIDGET_TEXT);
- w->SetWidgetLoweredState(OSK_WIDGET_SHIFT, HasBit(_keystate, KEYS_SHIFT));
- w->SetWidgetLoweredState(OSK_WIDGET_CAPS, HasBit(_keystate, KEYS_CAPS));
+ WChar c = _keyboard[shift][widget - OSK_WIDGET_LETTERS];
- ChangeOskDiabledState(w, qs, shift);
+ if (!IsValidChar(c, this->qs->afilter)) return;
- SetDParam(0, qs->caption);
- DrawWindowWidgets(w);
+ if (InsertTextBufferChar(&this->qs->text, c)) this->InvalidateWidget(OSK_WIDGET_TEXT);
- for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
- DrawCharCentered(_keyboard[shift][i],
- w->widget[OSK_WIDGET_LETTERS + i].left + 8,
- w->widget[OSK_WIDGET_LETTERS + i].top + 3,
- TC_BLACK);
+ if (HasBit(_keystate, KEYS_SHIFT)) {
+ ToggleBit(_keystate, KEYS_SHIFT);
+ this->widget[OSK_WIDGET_SHIFT].color = HasBit(_keystate, KEYS_SHIFT) ? 15 : 14;
+ this->SetDirty();
}
-
- DrawEditBox(w, qs, OSK_WIDGET_TEXT);
- break;
+ return;
}
- case WE_CLICK:
- /* clicked a letter */
- if (e->we.click.widget >= OSK_WIDGET_LETTERS) {
- bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
+ switch (widget) {
+ case OSK_WIDGET_BACKSPACE:
+ if (DeleteTextBufferChar(&this->qs->text, WKC_BACKSPACE)) this->InvalidateWidget(OSK_WIDGET_TEXT);
+ break;
- WChar c = _keyboard[shift][e->we.click.widget - OSK_WIDGET_LETTERS];
+ case OSK_WIDGET_SPECIAL:
+ /*
+ * Anything device specific can go here.
+ * The button itself is hidden by default, and when you need it you
+ * can not hide it in the create event.
+ */
+ break;
- if (!IsValidChar(c, qs->afilter)) break;
+ case OSK_WIDGET_CAPS:
+ ToggleBit(_keystate, KEYS_CAPS);
+ this->SetDirty();
+ break;
- if (InsertTextBufferChar(&qs->text, c)) w->InvalidateWidget(OSK_WIDGET_TEXT);
+ case OSK_WIDGET_SHIFT:
+ ToggleBit(_keystate, KEYS_SHIFT);
+ this->SetDirty();
+ break;
- if (HasBit(_keystate, KEYS_SHIFT)) {
- ToggleBit(_keystate, KEYS_SHIFT);
- w->widget[OSK_WIDGET_SHIFT].color = HasBit(_keystate, KEYS_SHIFT) ? 15 : 14;
- w->SetDirty();
- }
+ case OSK_WIDGET_SPACE:
+ if (InsertTextBufferChar(&this->qs->text, ' ')) this->InvalidateWidget(OSK_WIDGET_TEXT);
break;
- }
- switch (e->we.click.widget) {
- case OSK_WIDGET_BACKSPACE:
- if (DeleteTextBufferChar(&qs->text, WKC_BACKSPACE)) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
-
- case OSK_WIDGET_SPECIAL:
- /*
- * Anything device specific can go here.
- * The button itself is hidden by default, and when you need it you
- * can not hide it in the create event.
- */
- break;
-
- case OSK_WIDGET_CAPS:
- ToggleBit(_keystate, KEYS_CAPS);
- w->SetDirty();
- break;
-
- case OSK_WIDGET_SHIFT:
- ToggleBit(_keystate, KEYS_SHIFT);
- w->SetDirty();
- break;
-
- case OSK_WIDGET_SPACE:
- if (InsertTextBufferChar(&qs->text, ' ')) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
-
- case OSK_WIDGET_LEFT:
- if (MoveTextBufferPos(&qs->text, WKC_LEFT)) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
-
- case OSK_WIDGET_RIGHT:
- if (MoveTextBufferPos(&qs->text, WKC_RIGHT)) w->InvalidateWidget(OSK_WIDGET_TEXT);
- break;
-
- case OSK_WIDGET_OK:
- if (qs->orig == NULL || strcmp(qs->text.buf, qs->orig) != 0) {
- /* pass information by simulating a button press on parent window */
- if (WP(w, osk_d).ok_btn != 0) {
- w->parent->OnClick(e->we.click.pt, WP(w, osk_d).ok_btn);
- }
- }
- delete w;
- break;
-
- case OSK_WIDGET_CANCEL:
- if (WP(w, osk_d).cancel_btn != 0) { // pass a cancel event to the parent window
- w->parent->OnClick(e->we.click.pt, WP(w, osk_d).cancel_btn);
- /* Window gets deleted when the parent window removes itself. */
- } else { // or reset to original string
- strcpy(qs->text.buf, WP(w, osk_d).orig);
- UpdateTextBufferSize(&qs->text);
- MoveTextBufferPos(&qs->text, WKC_END);
- delete w;
+ case OSK_WIDGET_LEFT:
+ if (MoveTextBufferPos(&this->qs->text, WKC_LEFT)) this->InvalidateWidget(OSK_WIDGET_TEXT);
+ break;
+
+ case OSK_WIDGET_RIGHT:
+ if (MoveTextBufferPos(&this->qs->text, WKC_RIGHT)) this->InvalidateWidget(OSK_WIDGET_TEXT);
+ break;
+
+ case OSK_WIDGET_OK:
+ if (this->qs->orig == NULL || strcmp(this->qs->text.buf, this->qs->orig) != 0) {
+ /* pass information by simulating a button press on parent window */
+ if (this->ok_btn != 0) {
+ this->parent->OnClick(pt, this->ok_btn);
}
- break;
- }
- /* make sure that the parent window's textbox also gets updated */
- if (w->parent != NULL) w->parent->InvalidateWidget(WP(w, osk_d).text_btn);
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, qs, OSK_WIDGET_TEXT);
- /* make the caret of the parent window also blink */
- w->parent->InvalidateWidget(WP(w, osk_d).text_btn);
- break;
+ }
+ delete this;
+ break;
+
+ case OSK_WIDGET_CANCEL:
+ if (this->cancel_btn != 0) { // pass a cancel event to the parent window
+ this->parent->OnClick(pt, this->cancel_btn);
+ /* Window gets deleted when the parent window removes itself. */
+ } else { // or reset to original string
+ strcpy(qs->text.buf, this->orig_str_buf);
+ UpdateTextBufferSize(&qs->text);
+ MoveTextBufferPos(&qs->text, WKC_END);
+ delete this;
+ }
+ break;
+ }
+ /* make sure that the parent window's textbox also gets updated */
+ if (this->parent != NULL) this->parent->InvalidateWidget(this->text_btn);
}
-}
+
+ virtual void OnMouseLoop()
+ {
+ this->qs->HandleEditBox(this, OSK_WIDGET_TEXT);
+ /* make the caret of the parent window also blink */
+ this->parent->InvalidateWidget(this->text_btn);
+ }
+};
static const Widget _osk_widgets[] = {
{ WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
@@ -270,7 +281,7 @@ WindowDesc _osk_desc = {
WC_OSK, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_osk_widgets,
- OskWndProc
+ NULL
};
/**
@@ -338,26 +349,10 @@ void GetKeyboardLayout()
* @param ok widget number of parent's ok button (0 if ok events should not
* be passed)
*/
-void ShowOnScreenKeyboard(Window *parent, querystr_d *q, int button, int cancel, int ok)
+void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button, int cancel, int ok)
{
DeleteWindowById(WC_OSK, 0);
- Window *w = new Window(&_osk_desc);
-
- w->parent = parent;
- assert(parent != NULL);
-
- if (parent->widget[button].data != 0) q->caption = parent->widget[button].data;
-
- WP(w, osk_d).qs = q;
- WP(w, osk_d).text_btn = button;
- WP(w, osk_d).cancel_btn = cancel;
- WP(w, osk_d).ok_btn = ok;
- WP(w, osk_d).text = &q->text;
-
GetKeyboardLayout();
-
- /* make a copy in case we need to reset later */
- strcpy(_orig_str_buf, WP(w, osk_d).qs->text.buf);
- WP(w, osk_d).orig = _orig_str_buf;
+ new OskWindow(&_osk_desc, parent, button, cancel, ok);
}
diff --git a/src/querystring_gui.h b/src/querystring_gui.h
new file mode 100644
index 000000000..7b001dadd
--- /dev/null
+++ b/src/querystring_gui.h
@@ -0,0 +1,38 @@
+/* $Id$ */
+
+/** @file querystring_gui.h Base for the GUIs that have an edit box in them. */
+
+#ifndef QUERYSTRING_GUI_H
+#define QUERYSTRING_GUI_H
+
+#include "textbuf_gui.h"
+#include "window_gui.h"
+
+struct QueryString {
+ StringID caption;
+ Textbuf text;
+ const char *orig;
+ CharSetFilter afilter;
+ bool handled;
+
+ void DrawEditBox(Window *w, int wid);
+ void HandleEditBox(Window *w, int wid);
+ int HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont);
+};
+
+struct QueryStringBaseWindow : public Window, public QueryString {
+ char edit_str_buf[64];
+ char orig_str_buf[64];
+
+ QueryStringBaseWindow(const WindowDesc *desc, void *data = NULL, WindowNumber window_number = 0) : Window(desc, data, window_number)
+ {
+ }
+
+ void DrawEditBox(int wid);
+ void HandleEditBox(int wid);
+ int HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont);
+};
+
+void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button, int cancel, int ok);
+
+#endif /* QUERYSTRING_GUI_H */
diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp
index 643caf8b3..3c282b6a5 100644
--- a/src/signs_gui.cpp
+++ b/src/signs_gui.cpp
@@ -19,6 +19,7 @@
#include "map_func.h"
#include "gfx_func.h"
#include "viewport_func.h"
+#include "querystring_gui.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -143,11 +144,11 @@ void ShowSignList()
}
}
-/** Edit sign window stuff */
-struct editsign_d : querystr_d {
- SignID cur_sign;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(editsign_d));
+static void RenameSign(SignID index, const char *text)
+{
+ _cmd_text = text;
+ DoCommandP(0, index, 0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME));
+}
enum QueryEditSignWidgets {
QUERY_EDIT_SIGN_WIDGET_TEXT = 3,
@@ -158,120 +159,122 @@ enum QueryEditSignWidgets {
QUERY_EDIT_SIGN_WIDGET_NEXT,
};
-static void UpdateSignEditWindow(Window *w, const Sign *si)
-{
- /* Display an empty string when the sign hasnt been edited yet */
- if (si->name != NULL) {
- SetDParam(0, si->index);
- GetString(_edit_str_buf, STR_SIGN_NAME, lastof(_edit_str_buf));
- } else {
- GetString(_edit_str_buf, STR_EMPTY, lastof(_edit_str_buf));
- }
- _edit_str_buf[lengthof(_edit_str_buf) - 1] = '\0';
-
- WP(w, editsign_d).cur_sign = si->index;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, 31, 255); // Allow 31 characters (including \0)
+struct SignWindow : QueryStringBaseWindow {
+ SignID cur_sign;
- w->InvalidateWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
-}
+ SignWindow(const WindowDesc *desc, const Sign *si) : QueryStringBaseWindow(desc)
+ {
+ SetBit(_no_scroll, SCROLL_EDIT);
+ this->caption = STR_280B_EDIT_SIGN_TEXT;
+ this->afilter = CS_ALPHANUMERAL;
+ this->LowerWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
-static void RenameSign(SignID index, const char *text)
-{
- _cmd_text = text;
- DoCommandP(0, index, 0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME));
-}
+ UpdateSignEditWindow(si);
+ }
-static void QuerySignEditWndProc(Window *w, WindowEvent *e)
-{
- editsign_d *qs = &WP(w, editsign_d);
- Sign *si;
- uint sign_index = 0;
+ ~SignWindow()
+ {
+ ClrBit(_no_scroll, SCROLL_EDIT);
+ }
- switch (e->event) {
- case WE_CREATE:
- SetBit(_no_scroll, SCROLL_EDIT);
- break;
+ void UpdateSignEditWindow(const Sign *si)
+ {
+ /* Display an empty string when the sign hasnt been edited yet */
+ if (si->name != NULL) {
+ SetDParam(0, si->index);
+ GetString(this->edit_str_buf, STR_SIGN_NAME, lastof(this->edit_str_buf));
+ } else {
+ GetString(this->edit_str_buf, STR_EMPTY, lastof(this->edit_str_buf));
+ }
+ this->edit_str_buf[lengthof(this->edit_str_buf) - 1] = '\0';
+
+ this->cur_sign = si->index;
+ InitializeTextBuffer(&this->text, this->edit_str_buf, 31, 255); // Allow 31 characters (including \0)
+
+ this->InvalidateWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
+ }
- case WE_PAINT:
- SetDParam(0, qs->caption);
- DrawWindowWidgets(w);
- DrawEditBox(w, qs, QUERY_EDIT_SIGN_WIDGET_TEXT);
- break;
+ virtual void OnPaint()
+ {
+ SetDParam(0, this->caption);
+ DrawWindowWidgets(this);
+ this->DrawEditBox(QUERY_EDIT_SIGN_WIDGET_TEXT);
+ }
- case WE_CLICK:
- switch (e->we.click.widget) {
- case QUERY_EDIT_SIGN_WIDGET_PREVIOUS:
- if (_sign_sort_dirty) GlobalSortSignList();
- sign_index = _sign_sort[_num_sign_sort - 1]->index;
- for (uint i = 1; i < _num_sign_sort; i++) {
- if (qs->cur_sign == _sign_sort[i]->index) {
- sign_index = _sign_sort[i - 1]->index;
- break;
- }
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case QUERY_EDIT_SIGN_WIDGET_PREVIOUS: {
+ if (_sign_sort_dirty) GlobalSortSignList();
+ SignID sign_index = _sign_sort[_num_sign_sort - 1]->index;
+ for (uint i = 1; i < _num_sign_sort; i++) {
+ if (this->cur_sign == _sign_sort[i]->index) {
+ sign_index = _sign_sort[i - 1]->index;
+ break;
}
- si = GetSign(sign_index);
-
- /* Scroll to sign and reopen window */
- ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
- UpdateSignEditWindow(w, si);
- break;
-
- case QUERY_EDIT_SIGN_WIDGET_NEXT:
- if (_sign_sort_dirty) GlobalSortSignList();
- sign_index = _sign_sort[0]->index;
- for (uint i = 0; i < _num_sign_sort - 1; i++) {
- if (qs->cur_sign == _sign_sort[i]->index) {
- sign_index = _sign_sort[i + 1]->index;
- break;
- }
- }
- si = GetSign(sign_index);
-
- /* Scroll to sign and reopen window */
- ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
- UpdateSignEditWindow(w, si);
- break;
-
- case QUERY_EDIT_SIGN_WIDGET_TEXT:
- ShowOnScreenKeyboard(w, qs, e->we.click.widget, QUERY_EDIT_SIGN_WIDGET_CANCEL, QUERY_EDIT_SIGN_WIDGET_OK);
- break;
+ }
+ const Sign *si = GetSign(sign_index);
- case QUERY_EDIT_SIGN_WIDGET_DELETE:
- /* Only need to set the buffer to null, the rest is handled as the OK button */
- DeleteTextBufferAll(&qs->text);
- /* FALL THROUGH */
-
- case QUERY_EDIT_SIGN_WIDGET_OK:
- RenameSign(qs->cur_sign, qs->text.buf);
- /* FALL THROUGH */
-
- case QUERY_EDIT_SIGN_WIDGET_CANCEL:
- delete w;
- break;
- }
- break;
-
- case WE_KEYPRESS:
- switch (HandleEditBoxKey(w, qs, QUERY_EDIT_SIGN_WIDGET_TEXT, e)) {
- case 1: // Enter pressed, confirms change
- RenameSign(qs->cur_sign, qs->text.buf);
- /* FALL THROUGH */
+ /* Scroll to sign and reopen window */
+ ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
+ UpdateSignEditWindow(si);
+ } break;
+
+ case QUERY_EDIT_SIGN_WIDGET_NEXT: {
+ if (_sign_sort_dirty) GlobalSortSignList();
+ SignID sign_index = _sign_sort[0]->index;
+ for (uint i = 0; i < _num_sign_sort - 1; i++) {
+ if (this->cur_sign == _sign_sort[i]->index) {
+ sign_index = _sign_sort[i + 1]->index;
+ break;
+ }
+ }
+ const Sign *si = GetSign(sign_index);
- case 2: // ESC pressed, closes window, abandons changes
- delete w;
- break;
- }
- break;
+ /* Scroll to sign and reopen window */
+ ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
+ UpdateSignEditWindow(si);
+ } break;
+
+ case QUERY_EDIT_SIGN_WIDGET_TEXT:
+ ShowOnScreenKeyboard(this, widget, QUERY_EDIT_SIGN_WIDGET_CANCEL, QUERY_EDIT_SIGN_WIDGET_OK);
+ break;
+
+ case QUERY_EDIT_SIGN_WIDGET_DELETE:
+ /* Only need to set the buffer to null, the rest is handled as the OK button */
+ DeleteTextBufferAll(&this->text);
+ /* FALL THROUGH */
+
+ case QUERY_EDIT_SIGN_WIDGET_OK:
+ RenameSign(this->cur_sign, this->text.buf);
+ /* FALL THROUGH */
+
+ case QUERY_EDIT_SIGN_WIDGET_CANCEL:
+ delete this;
+ break;
+ }
+ }
- case WE_MOUSELOOP:
- HandleEditBox(w, qs, QUERY_EDIT_SIGN_WIDGET_TEXT);
- break;
+ virtual bool OnKeyPress(uint16 key, uint16 keycode)
+ {
+ bool cont = true;
+ switch (this->HandleEditBoxKey(QUERY_EDIT_SIGN_WIDGET_TEXT, key, keycode, cont)) {
+ case 1: // Enter pressed, confirms change
+ RenameSign(this->cur_sign, this->text.buf);
+ /* FALL THROUGH */
+
+ case 2: // ESC pressed, closes window, abandons changes
+ delete this;
+ break;
+ }
+ return cont;
+ }
- case WE_DESTROY:
- ClrBit(_no_scroll, SCROLL_EDIT);
- break;
+ virtual void OnMouseLoop()
+ {
+ this->HandleEditBox(QUERY_EDIT_SIGN_WIDGET_TEXT);
}
-}
+};
static const Widget _query_sign_edit_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
@@ -292,7 +295,7 @@ static const WindowDesc _query_sign_edit_desc = {
WC_QUERY_STRING, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_query_sign_edit_widgets,
- QuerySignEditWndProc
+ NULL
};
void ShowRenameSignWindow(const Sign *si)
@@ -301,11 +304,5 @@ void ShowRenameSignWindow(const Sign *si)
DeleteWindowById(WC_QUERY_STRING, 0);
DeleteWindowById(WC_SAVELOAD, 0);
- Window *w = new Window(&_query_sign_edit_desc);
-
- WP(w, editsign_d).caption = STR_280B_EDIT_SIGN_TEXT;
- WP(w, editsign_d).afilter = CS_ALPHANUMERAL;
- w->LowerWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
-
- UpdateSignEditWindow(w, si);
+ new SignWindow(&_query_sign_edit_desc, si);
}
diff --git a/src/textbuf_gui.h b/src/textbuf_gui.h
index 4a7f70c85..13778cea8 100644
--- a/src/textbuf_gui.h
+++ b/src/textbuf_gui.h
@@ -18,21 +18,6 @@ struct Textbuf {
uint16 caretxoffs; ///< the current position of the caret in pixels
};
-struct querystr_d {
- StringID caption;
- Textbuf text;
- const char *orig;
- CharSetFilter afilter;
- bool handled;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(querystr_d));
-
-extern char _edit_str_buf[64];
-extern char _orig_str_buf[lengthof(_edit_str_buf)];
-
-void DrawEditBox(Window *w, querystr_d *string, int wid);
-void HandleEditBox(Window *w, querystr_d *string, int wid);
-int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *we);
bool HandleCaret(Textbuf *tb);
void DeleteTextBufferAll(Textbuf *tb);
@@ -56,6 +41,4 @@ static const uint OSK_KEYBOARD_ENTRIES = 50;
*/
extern char _keyboard_opt[2][OSK_KEYBOARD_ENTRIES * 4 + 1];
-void ShowOnScreenKeyboard(Window *parent, querystr_d *q, int button, int cancel, int ok);
-
#endif /* TEXTBUF_GUI_H */