diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 84e8c17d98..894e9b9eb7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -379,6 +379,8 @@ jobs: bundle_name: "groovy" - container_image: "debian:buster" bundle_name: "buster" + - container_image: "debian:bullseye" + bundle_name: "bullseye" runs-on: ubuntu-20.04 container: diff --git a/src/3rdparty/squirrel/squirrel/sqstate.cpp b/src/3rdparty/squirrel/squirrel/sqstate.cpp index eaad6a3f77..8233ad1789 100644 --- a/src/3rdparty/squirrel/squirrel/sqstate.cpp +++ b/src/3rdparty/squirrel/squirrel/sqstate.cpp @@ -252,7 +252,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM *vm) SQVM *vms = _thread(_root_vm); vms->Mark(&tchain); -#ifndef NDEBUG +#ifdef WITH_ASSERT SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed(); #endif _refs_table.Mark(&tchain); @@ -291,7 +291,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM *vm) t = t->_next; } _gc_chain = tchain; -#ifndef NDEBUG +#ifdef WITH_ASSERT SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed(); assert(z == x); #endif diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index 5419c94cf0..ad07ac512d 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -1460,7 +1460,7 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr } } res = t; - } + } break; default: Raise_Error("attempt to delete a slot from a %s",GetTypeName(self)); @@ -1471,7 +1471,7 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror,SQBool can_suspend) { -#ifndef NDEBUG +#ifdef WITH_ASSERT SQInteger prevstackbase = _stackbase; #endif switch(type(closure)) { @@ -1482,13 +1482,13 @@ bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObj bool ret = Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror); this->_can_suspend = backup_suspend; return ret; - } + } break; - case OT_NATIVECLOSURE:{ + case OT_NATIVECLOSURE: { bool suspend; return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend); - } + } break; case OT_CLASS: { SQObjectPtr constr; @@ -1499,12 +1499,12 @@ bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObj return Call(constr,nparams,stackbase,temp,raiseerror,false); } return true; - } + } break; default: return false; } -#ifndef NDEBUG +#ifdef WITH_ASSERT if(!_suspended) { assert(_stackbase == prevstackbase); } diff --git a/src/core/pool_type.hpp b/src/core/pool_type.hpp index e847dfbb72..33f952dde4 100644 --- a/src/core/pool_type.hpp +++ b/src/core/pool_type.hpp @@ -82,7 +82,7 @@ struct Pool : PoolBase { /* Ensure Tmax_size is within the bounds of Tindex. */ static_assert((uint64)(Tmax_size - 1) >> 8 * sizeof(Tindex) == 0); - static const size_t MAX_SIZE = Tmax_size; ///< Make template parameter accessible from outside + static constexpr size_t MAX_SIZE = Tmax_size; ///< Make template parameter accessible from outside const char * const name; ///< Name of this pool diff --git a/src/fileio.cpp b/src/fileio.cpp index 9a9e7e05dc..6b33f8aa24 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -1259,7 +1259,7 @@ void SanitizeFilename(char *filename) * @return Pointer to new memory containing the loaded data, or \c nullptr if loading failed. * @note If \a maxsize less than the length of the file, loading fails. */ -std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize) +std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize) { FILE *in = fopen(filename.c_str(), "rb"); if (in == nullptr) return nullptr; @@ -1271,10 +1271,7 @@ std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, s fseek(in, 0, SEEK_SET); if (len > maxsize) return nullptr; - /* std::unique_ptr assumes new/delete unless a custom deleter is supplied. - * As we don't want to have to carry that deleter all over the place, use - * new directly to allocate the memory instead of malloc. */ - std::unique_ptr mem(static_cast(::operator new(len + 1))); + std::unique_ptr mem = std::make_unique(len + 1); mem.get()[len] = 0; if (fread(mem.get(), len, 1, in) != 1) return nullptr; diff --git a/src/fileio_func.h b/src/fileio_func.h index f373188fa8..6dbaea8970 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -49,7 +49,7 @@ const char *FiosGetScreenshotDir(); void SanitizeFilename(char *filename); void AppendPathSeparator(std::string &buf); void DeterminePaths(const char *exe); -std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize); +std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize); bool FileExists(const std::string &filename); bool ExtractTar(const std::string &tar_filename, Subdirectory subdir); diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 11fc4f4a91..3b9df8b37f 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -2689,7 +2689,7 @@ STR_LAND_AREA_INFORMATION_OWNER :{BLACK}Propieta STR_LAND_AREA_INFORMATION_ROAD_OWNER :{BLACK}Propietari de la carretera: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_TRAM_OWNER :{BLACK}Propietari del rail del tramvia: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Propietari del rail: {LTBLUE}{STRING} -STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Autoritat Local: {LTBLUE}{STRING} +STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Autoritat local: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :Cap STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Coordenades: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING}) STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Construït: {LTBLUE}{DATE_LONG} diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 778b1b9eab..847986a93a 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -1087,11 +1087,11 @@ STR_NUM_CUSTOM :Personalizado STR_NUM_CUSTOM_NUMBER :Personalizado ({NUM}) STR_VARIETY_NONE :Ninguna -STR_VARIETY_VERY_LOW :Muy baja +STR_VARIETY_VERY_LOW :Muy Baja STR_VARIETY_LOW :Baja STR_VARIETY_MEDIUM :Media STR_VARIETY_HIGH :Alta -STR_VARIETY_VERY_HIGH :Muy alta +STR_VARIETY_VERY_HIGH :Muy Alta STR_AI_SPEED_VERY_SLOW :Muy lenta STR_AI_SPEED_SLOW :Lenta @@ -1099,7 +1099,7 @@ STR_AI_SPEED_MEDIUM :Media STR_AI_SPEED_FAST :Rápida STR_AI_SPEED_VERY_FAST :Muy rápida -STR_SEA_LEVEL_VERY_LOW :Muy bajo +STR_SEA_LEVEL_VERY_LOW :Muy Bajo STR_SEA_LEVEL_LOW :Bajo STR_SEA_LEVEL_MEDIUM :Medio STR_SEA_LEVEL_HIGH :Alto diff --git a/src/object.h b/src/object.h index e3f0c84ff5..c374ba9501 100644 --- a/src/object.h +++ b/src/object.h @@ -18,6 +18,6 @@ void UpdateCompanyHQ(TileIndex tile, uint score); void BuildObject(ObjectType type, TileIndex tile, CompanyID owner = OWNER_NONE, struct Town *town = nullptr, uint8 view = 0); -void ShowBuildObjectPicker(); +Window *ShowBuildObjectPicker(); #endif /* OBJECT_H */ diff --git a/src/object_gui.cpp b/src/object_gui.cpp index 7a6edb97d4..4ee3b7265f 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -9,9 +9,11 @@ #include "stdafx.h" #include "command_func.h" +#include "hotkeys.h" #include "newgrf.h" #include "newgrf_object.h" #include "newgrf_text.h" +#include "object.h" #include "querystring_gui.h" #include "sortlist_type.h" #include "stringfilter_type.h" @@ -33,6 +35,11 @@ static ObjectClassID _selected_object_class; ///< Currently selected available o static int _selected_object_index; ///< Index of the currently selected object if existing, else \c -1. static uint8 _selected_object_view; ///< the view of the selected object +/** Enum referring to the Hotkeys in the build object window */ +enum BuildObjectHotkeys { + BOHK_FOCUS_FILTER_BOX, ///< Focus the edit box for editing the filter string +}; + /** The window used for building objects. */ class BuildObjectWindow : public Window { typedef GUIList GUIObjectClassList; ///< Type definition for the list to hold available object classes. @@ -88,7 +95,7 @@ class BuildObjectWindow : public Window { } public: - BuildObjectWindow(WindowDesc *desc, WindowNumber number) : Window(desc), info_height(1), filter_editbox(EDITBOX_MAX_SIZE) + BuildObjectWindow(WindowDesc *desc, WindowNumber number) : Window(desc), info_height(1), filter_editbox(EDITBOX_MAX_SIZE * MAX_CHAR_LENGTH, EDITBOX_MAX_SIZE) { this->CreateNestedTree(); @@ -544,6 +551,21 @@ public: this->UpdateButtons(_selected_object_class, -1, _selected_object_view); } + EventState OnHotkey(int hotkey) override + { + switch (hotkey) { + case BOHK_FOCUS_FILTER_BOX: + this->SetFocusedWidget(WID_BO_FILTER); + SetFocusedWindow(this); // The user has asked to give focus to the text box, so make sure this window is focused. + break; + + default: + return ES_NOT_HANDLED; + } + + return ES_HANDLED; + } + void OnEditboxChanged(int wid) override { string_filter.SetFilterTerm(this->filter_editbox.text.buf); @@ -597,8 +619,29 @@ public: } this->SelectOtherObject(-1); } + + static HotkeyList hotkeys; }; +/** + * Handler for global hotkeys of the BuildObjectWindow. + * @param hotkey Hotkey + * @return ES_HANDLED if hotkey was accepted. + */ +static EventState BuildObjectGlobalHotkeys(int hotkey) +{ + if (_game_mode == GM_MENU) return ES_NOT_HANDLED; + Window *w = ShowBuildObjectPicker(); + if (w == nullptr) return ES_NOT_HANDLED; + return w->OnHotkey(hotkey); +} + +static Hotkey buildobject_hotkeys[] = { + Hotkey('F', "focus_filter_box", BOHK_FOCUS_FILTER_BOX), + HOTKEY_LIST_END +}; +HotkeyList BuildObjectWindow::hotkeys("buildobject", buildobject_hotkeys, BuildObjectGlobalHotkeys); + Listing BuildObjectWindow::last_sorting = { false, 0 }; Filtering BuildObjectWindow::last_filtering = { false, 0 }; @@ -661,16 +704,18 @@ static WindowDesc _build_object_desc( WDP_AUTO, "build_object", 0, 0, WC_BUILD_OBJECT, WC_BUILD_TOOLBAR, WDF_CONSTRUCTION, - _nested_build_object_widgets, lengthof(_nested_build_object_widgets) + _nested_build_object_widgets, lengthof(_nested_build_object_widgets), + &BuildObjectWindow::hotkeys ); /** Show our object picker. */ -void ShowBuildObjectPicker() +Window *ShowBuildObjectPicker() { /* Don't show the place object button when there are no objects to place. */ if (ObjectClass::GetUIClassCount() > 0) { - AllocateWindowDescFront(&_build_object_desc, 0); + return AllocateWindowDescFront(&_build_object_desc, 0); } + return nullptr; } /** Reset all data of the object GUI. */ diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 6e7c825a01..da9e726edc 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -72,7 +72,7 @@ static RailStationGUISettings _railstation; ///< Settings of the station builder static void HandleStationPlacement(TileIndex start, TileIndex end); static void ShowBuildTrainDepotPicker(Window *parent); static void ShowBuildWaypointPicker(Window *parent); -static void ShowStationBuilder(Window *parent); +static Window *ShowStationBuilder(Window *parent); static void ShowSignalBuilder(Window *parent); /** @@ -934,6 +934,11 @@ static void HandleStationPlacement(TileIndex start, TileIndex end) ShowSelectStationIfNeeded(cmdcont, ta); } +/** Enum referring to the Hotkeys in the build rail station window */ +enum BuildRalStationHotkeys { + BRASHK_FOCUS_FILTER_BOX, ///< Focus the edit box for editing the filter string +}; + struct BuildRailStationWindow : public PickerWindowBase { private: uint line_height; ///< Height of a single line in the newstation selection matrix (#WID_BRAS_NEWST_LIST widget). @@ -1005,7 +1010,7 @@ private: } public: - BuildRailStationWindow(WindowDesc *desc, Window *parent, bool newstation) : PickerWindowBase(desc, parent), filter_editbox(EDITBOX_MAX_SIZE) + BuildRailStationWindow(WindowDesc *desc, Window *parent, bool newstation) : PickerWindowBase(desc, parent), filter_editbox(EDITBOX_MAX_SIZE * MAX_CHAR_LENGTH, EDITBOX_MAX_SIZE) { this->coverage_height = 2 * FONT_HEIGHT_NORMAL + 3 * WD_PAR_VSEP_NORMAL; this->vscroll = nullptr; @@ -1159,6 +1164,21 @@ public: this->BuildStationClassesAvailable(); } + EventState OnHotkey(int hotkey) override + { + switch (hotkey) { + case BRASHK_FOCUS_FILTER_BOX: + this->SetFocusedWidget(WID_BRAS_FILTER_EDITBOX); + SetFocusedWindow(this); // The user has asked to give focus to the text box, so make sure this window is focused. + break; + + default: + return ES_NOT_HANDLED; + } + + return ES_HANDLED; + } + void OnEditboxChanged(int wid) override { string_filter.SetFilterTerm(this->filter_editbox.text.buf); @@ -1545,8 +1565,29 @@ public: { CheckRedrawStationCoverage(this); } + + static HotkeyList hotkeys; }; +/** + * Handler for global hotkeys of the BuildRailStationWindow. + * @param hotkey Hotkey + * @return ES_HANDLED if hotkey was accepted. + */ +static EventState BuildRailStationGlobalHotkeys(int hotkey) +{ + if (_game_mode == GM_MENU) return ES_NOT_HANDLED; + Window *w = ShowStationBuilder(FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL)); + if (w == nullptr) return ES_NOT_HANDLED; + return w->OnHotkey(hotkey); +} + +static Hotkey buildrailstation_hotkeys[] = { + Hotkey('F', "focus_filter_box", BRASHK_FOCUS_FILTER_BOX), + HOTKEY_LIST_END +}; +HotkeyList BuildRailStationWindow::hotkeys("buildrailstation", buildrailstation_hotkeys, BuildRailStationGlobalHotkeys); + Listing BuildRailStationWindow::last_sorting = { false, 0 }; Filtering BuildRailStationWindow::last_filtering = { false, 0 }; @@ -1679,14 +1720,15 @@ static WindowDesc _station_builder_desc( WDP_AUTO, "build_station_rail", 0, 0, WC_BUILD_STATION, WC_BUILD_TOOLBAR, WDF_CONSTRUCTION, - _nested_station_builder_widgets, lengthof(_nested_station_builder_widgets) + _nested_station_builder_widgets, lengthof(_nested_station_builder_widgets), + &BuildRailStationWindow::hotkeys ); /** Open station build window */ -static void ShowStationBuilder(Window *parent) +static Window *ShowStationBuilder(Window *parent) { bool newstations = StationClass::GetClassCount() > 2 || StationClass::Get(STAT_CLASS_DFLT)->GetSpecCount() != 1; - new BuildRailStationWindow(&_station_builder_desc, parent, newstations); + return new BuildRailStationWindow(&_station_builder_desc, parent, newstations); } struct BuildSignalWindow : public PickerWindowBase { diff --git a/src/spritecache.cpp b/src/spritecache.cpp index 0426e297b1..4cb99bab75 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -229,7 +229,7 @@ static void ResizeSpriteOut(SpriteLoader::Sprite *sprite, ZoomLevel zoom) SpriteLoader::CommonPixel *dst = sprite[zoom].data; const SpriteLoader::CommonPixel *src = sprite[zoom - 1].data; -#ifndef NDEBUG +#ifdef WITH_ASSERT const SpriteLoader::CommonPixel *src_end = src + sprite[zoom - 1].height * sprite[zoom - 1].width; #endif diff --git a/src/strings.cpp b/src/strings.cpp index 2c3933a120..e28943c57a 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -185,8 +185,16 @@ struct LanguagePack : public LanguagePackHeader { char data[]; // list of strings }; +struct LanguagePackDeleter { + void operator()(LanguagePack *langpack) + { + /* LanguagePack is in fact reinterpreted char[], we need to reinterpret it back to free it properly. */ + delete[] reinterpret_cast(langpack); + } +}; + struct LoadedLanguagePack { - std::unique_ptr langpack; + std::unique_ptr langpack; std::vector offsets; @@ -1713,7 +1721,7 @@ bool ReadLanguagePack(const LanguageMetadata *lang) { /* Current language pack */ size_t len = 0; - std::unique_ptr lang_pack(reinterpret_cast(ReadFileToMem(lang->file, len, 1U << 20).release())); + std::unique_ptr lang_pack(reinterpret_cast(ReadFileToMem(lang->file, len, 1U << 20).release())); if (!lang_pack) return false; /* End of read data (+ terminating zero added in ReadFileToMem()) */ diff --git a/src/tgp.cpp b/src/tgp.cpp index 39fda6e6b3..e23b2643df 100644 --- a/src/tgp.cpp +++ b/src/tgp.cpp @@ -658,7 +658,7 @@ static void HeightMapCurves(uint level) for (uint t = 0; t < lengthof(curve_maps); t++) { if (!HasBit(corner_bits, t)) continue; -#ifndef NDEBUG +#ifdef WITH_ASSERT bool found = false; #endif const control_point_t *cm = curve_maps[t].list; @@ -668,7 +668,7 @@ static void HeightMapCurves(uint level) if (*h >= p1.x && *h < p2.x) { ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x); -#ifndef NDEBUG +#ifdef WITH_ASSERT found = true; #endif break; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 023063c1f0..43f3523f8e 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -107,7 +107,7 @@ Town::~Town() DeleteWindowById(WC_TOWN_VIEW, this->index); /* Check no industry is related to us. */ -#ifndef NDEBUG +#ifdef WITH_ASSERT for (const Industry *i : Industry::Iterate()) assert(i->town != this); /* ... and no object is related to us. */ diff --git a/src/townname.cpp b/src/townname.cpp index 082c40f75e..519391f14e 100644 --- a/src/townname.cpp +++ b/src/townname.cpp @@ -600,7 +600,7 @@ static char *MakeCzechTownName(char *buf, const char *last, uint32 seed) return strecpy(buf, _name_czech_real[SeedModChance(4, lengthof(_name_czech_real), seed)], last); } -#ifndef NDEBUG +#ifdef WITH_ASSERT const char *orig = buf; #endif diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 8ffaea4082..a9af24c55a 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -953,7 +953,7 @@ void CallVehicleTicks() PerformanceAccumulator::Reset(PFE_GL_AIRCRAFT); for (Vehicle *v : Vehicle::Iterate()) { -#ifndef NDEBUG +#ifdef WITH_ASSERT size_t vehicle_index = v->index; #endif diff --git a/src/widget.cpp b/src/widget.cpp index b656098fab..45a7232577 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1390,7 +1390,7 @@ void NWidgetHorizontal::SetupSmallestSize(Window *w, bool init_array) this->smallest_y = std::max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom); } /* 1b. Make the container higher if needed to accommodate all children nicely. */ -#ifndef NDEBUG +#ifdef WITH_ASSERT uint max_smallest = this->smallest_y + 3 * max_vert_fill; // Upper limit to computing smallest height. #endif uint cur_height = this->smallest_y; @@ -1557,7 +1557,7 @@ void NWidgetVertical::SetupSmallestSize(Window *w, bool init_array) this->smallest_x = std::max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right); } /* 1b. Make the container wider if needed to accommodate all children nicely. */ -#ifndef NDEBUG +#ifdef WITH_ASSERT uint max_smallest = this->smallest_x + 3 * max_hor_fill; // Upper limit to computing smallest height. #endif uint cur_width = this->smallest_x;