From 0a883afe19e6bd70cb79515dadb8c890cc3e68b1 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 9 Apr 2019 19:45:42 +0200 Subject: [PATCH 01/13] Update: Translations from eints luxembourgish: 20 changes by Phreeze --- src/lang/luxembourgish.txt | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index 610e939239..1190cd30f3 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -226,8 +226,8 @@ STR_UNITS_HEIGHT_METRIC :{COMMA}{NBSP}m STR_UNITS_HEIGHT_SI :{COMMA}{NBSP}m # Common window strings -STR_LIST_FILTER_TITLE :{BLACK}Filter String: -STR_LIST_FILTER_OSKTITLE :{BLACK}Filter String +STR_LIST_FILTER_TITLE :{BLACK}Filter-String: +STR_LIST_FILTER_OSKTITLE :{BLACK}Filter-String STR_LIST_FILTER_TOOLTIP :{BLACK}Filter d'Lëscht op e Wuert STR_TOOLTIP_GROUP_ORDER :{BLACK}Wiel Gruppéierreihefollëg @@ -675,6 +675,7 @@ STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Schalt d STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Weis d'Fënster fir Musik ze wielen # Playlist window +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Musik-Programm - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Lidder Index STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programm - '{STRING}' @@ -995,6 +996,7 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :Duebel STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Véierfach STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Schrëftgréisst +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Wiel d'Interface-Schrëftgréisst aus STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Normal STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Duebel Gréisst @@ -1356,6 +1358,7 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Mof STR_CONFIG_SETTING_SCROLLMODE :Usiicht-Scrollverhalen: {STRING} STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Verhalen beim Scrolle vun der Kaart STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :D'Usiicht mat der rietser Maustast bewegen, Maus-Positioun gespaart +STR_CONFIG_SETTING_SCROLLMODE_RMB :D'Kaart mat der rietser Maustast bewegen STR_CONFIG_SETTING_SCROLLMODE_LMB :Kaart mat der lénker Maustast bewegen STR_CONFIG_SETTING_SMOOTH_SCROLLING :Feine Scrolling: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Kontrolléiert wéi d'Haptusiicht op eng bestëmmten Positioun scrollt, wann een op déi kléng Kaart klickt oder en Befehl fir ob en spezifescht Objet ze scrollen gëtt. Wann ugeschalt, gëtt bis dohin gescrollt, wann ausgeschalt, spréngt d'Vue op den Zielobjet @@ -2707,7 +2710,10 @@ STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD # Framerate display window STR_FRAMERATE_CAPTION :{WHITE}Biller pro Sekonn +STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} ({DECIMAL}x) STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Unzuel Gameticks déi pro Sekonn simuléiert ginn. +STR_FRAMERATE_RATE_BLITTER :{BLACK}Grafikframerate: {STRING} +STR_FRAMERATE_SPEED_FACTOR :{BLACK}Aktuelle Spillgeschw.-Faktor: {DECIMAL}x STR_FRAMERATE_CURRENT :{WHITE}Aktuell STR_FRAMERATE_AVERAGE :{WHITE}Mëttel STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL} ms @@ -2721,10 +2727,11 @@ STR_FRAMERATE_GAMELOOP :{BLACK}Spill to STR_FRAMERATE_GL_TRAINS :{BLACK} Zuchticks: STR_FRAMERATE_GL_ROADVEHS :{BLACK} Stroossegefierer Ticken: STR_FRAMERATE_GL_LINKGRAPH :{BLACK} Linkgrafik-Verzögerung: -STR_FRAMERATE_DRAWING :{BLACK}Graphikrendering: +STR_FRAMERATE_DRAWING :{BLACK}Grafikrendering: STR_FRAMERATE_DRAWING_VIEWPORTS :{BLACK} Welt-Usiichten: STR_FRAMERATE_VIDEO :{BLACK}Video-output: STR_FRAMERATE_GAMESCRIPT :{BLACK} Gamescript: +STR_FRAMERATE_AI :{BLACK} KI {NUM} {STRING} ############ End of leave-in-this-order ############ Leave those lines in this order!! STR_FRAMETIME_CAPTION_GAMELOOP :Spill-Loop @@ -2732,7 +2739,11 @@ STR_FRAMETIME_CAPTION_GL_ECONOMY :Wuerenhandling STR_FRAMETIME_CAPTION_GL_TRAINS :Zuchticks STR_FRAMETIME_CAPTION_GL_ROADVEHS :Stroossegefierer Ticken STR_FRAMETIME_CAPTION_GL_SHIPS :Schëffticker +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Weltticks +STR_FRAMETIME_CAPTION_DRAWING :Grafikrendering +STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Weltusiicht-Rendering STR_FRAMETIME_CAPTION_SOUND :Soundmixing +STR_FRAMETIME_CAPTION_ALLSCRIPTS :GS/KI Scripttotaler STR_FRAMETIME_CAPTION_GAMESCRIPT :Spill-Script ############ End of leave-in-this-order @@ -2759,6 +2770,7 @@ STR_SAVELOAD_DETAIL_CAPTION :{BLACK}Detailer STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}Keng Informatioun do STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING} +STR_SAVELOAD_FILTER_TITLE :{BLACK}Filter-String: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Datei iwwerschreiwen STR_SAVELOAD_OSKTITLE :{BLACK}Gëff dem Spillstand en Numm @@ -3340,6 +3352,7 @@ STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Zentréi STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Produktiounslevel: {YELLOW}{COMMA}% STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}D'Industrie annoncéiert dass se zougemaach gëtt +STR_INDUSTRY_VIEW_PRODUCES_N_CARGO :{BLACK}Produzéiert: {YELLOW}{STRING}{STRING} STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :, {STRING}{STRING} STR_INDUSTRY_VIEW_REQUIRES :{BLACK}Brauch: @@ -3442,6 +3455,7 @@ STR_PURCHASE_INFO_COST :{BLACK}Käschte STR_PURCHASE_INFO_COST_REFIT :{BLACK}Käschten: {GOLD}{CURRENCY_LONG}{BLACK} (Embaukäschten: {GOLD}{CURRENCY_LONG}{BLACK}) STR_PURCHASE_INFO_WEIGHT_CWEIGHT :{BLACK}Gewiicht: {GOLD}{WEIGHT_SHORT} ({WEIGHT_SHORT}) STR_PURCHASE_INFO_COST_SPEED :{BLACK}Käschten: {GOLD}{CURRENCY_LONG}{BLACK} Geschw.: {GOLD}{VELOCITY} +STR_PURCHASE_INFO_COST_REFIT_SPEED :{BLACK}Käschten: {GOLD}{CURRENCY_LONG}{BLACK} (Embaukäschten: {GOLD}{CURRENCY_LONG}{BLACK}) Geschw.: {GOLD}{VELOCITY} STR_PURCHASE_INFO_AIRCRAFT_CAPACITY :{BLACK}Kapazitéit: {GOLD}{CARGO_LONG}, {CARGO_LONG} STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Ugedriwwen Waggonen: {GOLD}+{POWER}{BLACK} Gewiicht: {GOLD}+{WEIGHT_SHORT} STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Embaubar zu: {GOLD}{STRING} @@ -3462,6 +3476,8 @@ STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}Schëff STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}Fliger kafen STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Gefierer kafen an embauen +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Gefierer kafen an embauen +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Schëff kafen an embauen STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}Keeft den ungewielten Zuch. Shift+Klick weist ongeféier Käschten ouni Kaf STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Keeft dat ugewielte Stroossegefier. Shift+Klick weist ongeféier Käschten ouni Kaf @@ -4423,6 +4439,7 @@ STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Kann d'G STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}Kann d'Grupp net läschen... STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}Kann d'Grupp net ëmbenennen... STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}Kann iwwergeuerdent Grupp net setzen... +STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION :{WHITE}... Schläifen an der Gruppenhierarchie si net erlabt STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}Kann net all d'Gefierer aus der Grupp läschen... STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}Kann d'Gefier net bei d'Grupp bäisetzen... STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}Kann dei gedeelten Gefierer net bei d'Grupp bäisetzen... From d95c7083ea582ea723107aa42f27b8cf3e3365e1 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:20:19 +0200 Subject: [PATCH 02/13] Fix: Don't crash if reading a GS string file from disk produces an error. The raw_strings vector may not include NULLs as no consumer can deal with it. --- src/game/game_text.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index d57b2bc77f..5016f967d9 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -83,13 +83,12 @@ LanguageStrings::~LanguageStrings() LanguageStrings *ReadRawLanguageStrings(const char *file) { LanguageStrings *ret = NULL; - FILE *fh = NULL; try { size_t to_read; - fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read); - if (fh == NULL) { - return NULL; - } + FILE *fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read); + if (fh == NULL) return NULL; + + FileCloser fhClose(fh); const char *langname = strrchr(file, PATHSEPCHAR); if (langname == NULL) { @@ -99,10 +98,7 @@ LanguageStrings *ReadRawLanguageStrings(const char *file) } /* Check for invalid empty filename */ - if (*langname == '.' || *langname == 0) { - fclose(fh); - return NULL; - } + if (*langname == '.' || *langname == 0) return NULL; ret = new LanguageStrings(langname, strchr(langname, '.')); @@ -124,10 +120,8 @@ LanguageStrings *ReadRawLanguageStrings(const char *file) } } - fclose(fh); return ret; } catch (...) { - if (fh != NULL) fclose(fh); delete ret; return NULL; } @@ -246,7 +240,10 @@ public: { if (strcmp(filename, exclude) == 0) return true; - gs->raw_strings.push_back(ReadRawLanguageStrings(filename)); + auto ls = ReadRawLanguageStrings(filename); + if (ls == NULL) return false; + + gs->raw_strings.push_back(std::move(ls)); return true; } }; @@ -267,9 +264,12 @@ GameStrings *LoadTranslations() strecpy(e, "lang" PATHSEP "english.txt", lastof(filename)); if (!FioCheckFileExists(filename, GAME_DIR)) return NULL; + auto ls = ReadRawLanguageStrings(filename); + if (ls == NULL) return NULL; + GameStrings *gs = new GameStrings(); try { - gs->raw_strings.push_back(ReadRawLanguageStrings(filename)); + gs->raw_strings.push_back(std::move(ls)); /* Scan for other language files */ LanguageScanner scanner(gs, filename); From fbc4cef180a60d8875df6298364f0459beb3568a Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:30:34 +0200 Subject: [PATCH 03/13] Codechange: Use override specifier for text layout classes. --- src/gfx_layout.cpp | 58 ++++++++++++++--------------- src/os/macosx/string_osx.cpp | 28 +++++++------- src/os/macosx/string_osx.h | 8 ++-- src/os/windows/string_uniscribe.cpp | 30 +++++++-------- src/os/windows/string_uniscribe.h | 8 ++-- src/string.cpp | 10 ++--- 6 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index 124f1218a2..b46ac20d58 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -134,12 +134,12 @@ public: public: ICUVisualRun(const icu::ParagraphLayout::VisualRun *vr) : vr(vr) { } - const Font *GetFont() const { return (const Font*)vr->getFont(); } - int GetGlyphCount() const { return vr->getGlyphCount(); } - const GlyphID *GetGlyphs() const { return vr->getGlyphs(); } - const float *GetPositions() const { return vr->getPositions(); } - int GetLeading() const { return vr->getLeading(); } - const int *GetGlyphToCharMap() const { return vr->getGlyphToCharMap(); } + const Font *GetFont() const override { return (const Font*)vr->getFont(); } + int GetGlyphCount() const override { return vr->getGlyphCount(); } + const GlyphID *GetGlyphs() const override { return vr->getGlyphs(); } + const float *GetPositions() const override { return vr->getPositions(); } + int GetLeading() const override { return vr->getLeading(); } + const int *GetGlyphToCharMap() const override { return vr->getGlyphToCharMap(); } }; /** A single line worth of VisualRuns. */ @@ -153,14 +153,14 @@ public: this->push_back(new ICUVisualRun(l->getVisualRun(i))); } } - ~ICULine() { delete l; } + ~ICULine() override { delete l; } - int GetLeading() const { return l->getLeading(); } - int GetWidth() const { return l->getWidth(); } - int CountRuns() const { return l->countRuns(); } - const ParagraphLayouter::VisualRun *GetVisualRun(int run) const { return this->at(run); } + int GetLeading() const override { return l->getLeading(); } + int GetWidth() const override { return l->getWidth(); } + int CountRuns() const override { return l->countRuns(); } + const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override { return this->at(run); } - int GetInternalCharLength(WChar c) const + int GetInternalCharLength(WChar c) const override { /* ICU uses UTF-16 internally which means we need to account for surrogate pairs. */ return Utf8CharLen(c) < 4 ? 1 : 2; @@ -168,10 +168,10 @@ public: }; ICUParagraphLayout(icu::ParagraphLayout *p) : p(p) { } - ~ICUParagraphLayout() { delete p; } - void Reflow() { p->reflow(); } + ~ICUParagraphLayout() override { delete p; } + void Reflow() override { p->reflow(); } - ParagraphLayouter::Line *NextLine(int max_width) + ParagraphLayouter::Line *NextLine(int max_width) override { icu::ParagraphLayout::Line *l = p->nextLine(max_width); return l == NULL ? NULL : new ICULine(l); @@ -259,24 +259,24 @@ public: public: FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x); - ~FallbackVisualRun(); - const Font *GetFont() const; - int GetGlyphCount() const; - const GlyphID *GetGlyphs() const; - const float *GetPositions() const; - int GetLeading() const; - const int *GetGlyphToCharMap() const; + ~FallbackVisualRun() override; + const Font *GetFont() const override; + int GetGlyphCount() const override; + const GlyphID *GetGlyphs() const override; + const float *GetPositions() const override; + int GetLeading() const override; + const int *GetGlyphToCharMap() const override; }; /** A single line worth of VisualRuns. */ class FallbackLine : public AutoDeleteSmallVector, public ParagraphLayouter::Line { public: - int GetLeading() const; - int GetWidth() const; - int CountRuns() const; - const ParagraphLayouter::VisualRun *GetVisualRun(int run) const; + int GetLeading() const override; + int GetWidth() const override; + int CountRuns() const override; + const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override; - int GetInternalCharLength(WChar c) const { return 1; } + int GetInternalCharLength(WChar c) const override { return 1; } }; const WChar *buffer_begin; ///< Begin of the buffer. @@ -284,8 +284,8 @@ public: FontMap &runs; ///< The fonts we have to use for this paragraph. FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs); - void Reflow(); - const ParagraphLayouter::Line *NextLine(int max_width); + void Reflow() override; + const ParagraphLayouter::Line *NextLine(int max_width) override; }; /** diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index e14ca4183b..f26421e368 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -54,13 +54,13 @@ public: public: CoreTextVisualRun(CTRunRef run, Font *font, const CoreTextParagraphLayoutFactory::CharType *buff); - virtual const GlyphID *GetGlyphs() const { return &this->glyphs[0]; } - virtual const float *GetPositions() const { return &this->positions[0]; } - virtual const int *GetGlyphToCharMap() const { return &this->glyph_to_char[0]; } + const GlyphID *GetGlyphs() const override { return &this->glyphs[0]; } + const float *GetPositions() const override { return &this->positions[0]; } + const int *GetGlyphToCharMap() const override { return &this->glyph_to_char[0]; } - virtual const Font *GetFont() const { return this->font; } - virtual int GetLeading() const { return this->font->fc->GetHeight(); } - virtual int GetGlyphCount() const { return (int)this->glyphs.size(); } + const Font *GetFont() const override { return this->font; } + int GetLeading() const override { return this->font->fc->GetHeight(); } + int GetGlyphCount() const override { return (int)this->glyphs.size(); } int GetAdvance() const { return this->total_advance; } }; @@ -83,12 +83,12 @@ public: CFRelease(line); } - virtual int GetLeading() const; - virtual int GetWidth() const; - virtual int CountRuns() const { return this->size(); } - virtual const VisualRun *GetVisualRun(int run) const { return this->at(run); } + int GetLeading() const override; + int GetWidth() const override; + int CountRuns() const override { return this->size(); } + const VisualRun *GetVisualRun(int run) const override { return this->at(run); } - int GetInternalCharLength(WChar c) const + int GetInternalCharLength(WChar c) const override { /* CoreText uses UTF-16 internally which means we need to account for surrogate pairs. */ return c >= 0x010000U ? 2 : 1; @@ -100,17 +100,17 @@ public: this->Reflow(); } - virtual ~CoreTextParagraphLayout() + ~CoreTextParagraphLayout() override { CFRelease(this->typesetter); } - virtual void Reflow() + void Reflow() override { this->cur_offset = 0; } - virtual const Line *NextLine(int max_width); + const Line *NextLine(int max_width) override; }; diff --git a/src/os/macosx/string_osx.h b/src/os/macosx/string_osx.h index d632b0a440..8c9b7058ab 100644 --- a/src/os/macosx/string_osx.h +++ b/src/os/macosx/string_osx.h @@ -30,10 +30,10 @@ class OSXStringIterator : public StringIterator { size_t cur_pos; ///< Current iteration position. public: - virtual void SetString(const char *s); - virtual size_t SetCurPosition(size_t pos); - virtual size_t Next(IterType what); - virtual size_t Prev(IterType what); + void SetString(const char *s) override; + size_t SetCurPosition(size_t pos) override; + size_t Next(IterType what) override; + size_t Prev(IterType what) override; static StringIterator *Create(); }; diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index 1d17b02d7e..a5d03b9489 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -90,30 +90,30 @@ public: public: UniscribeVisualRun(const UniscribeRun &range, int x); - virtual ~UniscribeVisualRun() + ~UniscribeVisualRun() override { free(this->glyph_to_char); } - virtual const GlyphID *GetGlyphs() const { return &this->glyphs[0]; } - virtual const float *GetPositions() const { return &this->positions[0]; } - virtual const int *GetGlyphToCharMap() const; + const GlyphID *GetGlyphs() const override { return &this->glyphs[0]; } + const float *GetPositions() const override { return &this->positions[0]; } + const int *GetGlyphToCharMap() const override; - virtual const Font *GetFont() const { return this->font; } - virtual int GetLeading() const { return this->font->fc->GetHeight(); } - virtual int GetGlyphCount() const { return this->num_glyphs; } + const Font *GetFont() const override { return this->font; } + int GetLeading() const override { return this->font->fc->GetHeight(); } + int GetGlyphCount() const override { return this->num_glyphs; } int GetAdvance() const { return this->total_advance; } }; /** A single line worth of VisualRuns. */ class UniscribeLine : public AutoDeleteSmallVector, public ParagraphLayouter::Line { public: - virtual int GetLeading() const; - virtual int GetWidth() const; - virtual int CountRuns() const { return (uint)this->size(); } - virtual const VisualRun *GetVisualRun(int run) const { return this->at(run); } + int GetLeading() const override; + int GetWidth() const override; + int CountRuns() const override { return (uint)this->size(); } + const VisualRun *GetVisualRun(int run) const override { return this->at(run); } - int GetInternalCharLength(WChar c) const + int GetInternalCharLength(WChar c) const override { /* Uniscribe uses UTF-16 internally which means we need to account for surrogate pairs. */ return c >= 0x010000U ? 2 : 1; @@ -125,15 +125,15 @@ public: this->Reflow(); } - virtual ~UniscribeParagraphLayout() {} + ~UniscribeParagraphLayout() override {} - virtual void Reflow() + void Reflow() override { this->cur_range = this->ranges.begin(); this->cur_range_offset = 0; } - virtual const Line *NextLine(int max_width); + const Line *NextLine(int max_width) override; }; void UniscribeResetScriptCache(FontSize size) diff --git a/src/os/windows/string_uniscribe.h b/src/os/windows/string_uniscribe.h index 6af858a88f..49e1123a99 100644 --- a/src/os/windows/string_uniscribe.h +++ b/src/os/windows/string_uniscribe.h @@ -81,10 +81,10 @@ class UniscribeStringIterator : public StringIterator { size_t cur_pos; ///< Current iteration position. public: - virtual void SetString(const char *s); - virtual size_t SetCurPosition(size_t pos); - virtual size_t Next(IterType what); - virtual size_t Prev(IterType what); + void SetString(const char *s) override; + size_t SetCurPosition(size_t pos) override; + size_t Next(IterType what) override; + size_t Prev(IterType what) override; }; #endif /* defined(WITH_UNISCRIBE) */ diff --git a/src/string.cpp b/src/string.cpp index 7c16489bf5..208f5e8563 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -638,13 +638,13 @@ public: this->utf16_to_utf8.push_back(0); } - virtual ~IcuStringIterator() + ~IcuStringIterator() override { delete this->char_itr; delete this->word_itr; } - virtual void SetString(const char *s) + void SetString(const char *s) override { const char *string_base = s; @@ -681,7 +681,7 @@ public: this->word_itr->first(); } - virtual size_t SetCurPosition(size_t pos) + size_t SetCurPosition(size_t pos) override { /* Convert incoming position to an UTF-16 string index. */ uint utf16_pos = 0; @@ -699,7 +699,7 @@ public: return this->utf16_to_utf8[this->char_itr->current()]; } - virtual size_t Next(IterType what) + size_t Next(IterType what) override { int32_t pos; switch (what) { @@ -731,7 +731,7 @@ public: return pos == icu::BreakIterator::DONE ? END : this->utf16_to_utf8[pos]; } - virtual size_t Prev(IterType what) + size_t Prev(IterType what) override { int32_t pos; switch (what) { From 9325d63d8e55758a953f535c5f90534ab9bc01e3 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:30:44 +0200 Subject: [PATCH 04/13] Fix: Forgotten override keywords for DropDownListIconItem. --- src/widgets/dropdown_type.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/dropdown_type.h b/src/widgets/dropdown_type.h index d8e9b90288..bf8638a924 100644 --- a/src/widgets/dropdown_type.h +++ b/src/widgets/dropdown_type.h @@ -89,9 +89,9 @@ class DropDownListIconItem : public DropDownListParamStringItem { public: DropDownListIconItem(SpriteID sprite, PaletteID pal, StringID string, int result, bool masked); - /* virtual */ uint Height(uint width) const; - /* virtual */ uint Width() const; - /* virtual */ void Draw(int left, int right, int top, int bottom, bool sel, Colours bg_colour) const; + uint Height(uint width) const override; + uint Width() const override; + void Draw(int left, int right, int top, int bottom, bool sel, Colours bg_colour) const override; void SetDimension(Dimension d); }; From 329bb526134aca214a914f25006c805de78ec851 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:30:53 +0200 Subject: [PATCH 05/13] Codechange: Store text layout runs directly as values in a std::vector instead of heap allocated. This reduces memory allocations and heap fragmentation. --- src/gfx.cpp | 16 ++++---- src/gfx_layout.cpp | 59 ++++++++++++++++++----------- src/gfx_layout.h | 2 +- src/os/macosx/string_osx.cpp | 7 ++-- src/os/windows/string_uniscribe.cpp | 23 +++++++---- 5 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index f1b91c16eb..7c90285ba8 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -376,7 +376,7 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, * another size would be chosen it won't have truncated too little for * the truncation dots. */ - FontCache *fc = ((const Font*)line->GetVisualRun(0)->GetFont())->fc; + FontCache *fc = ((const Font*)line->GetVisualRun(0).GetFont())->fc; GlyphID dot_glyph = fc->MapCharToGlyph('.'); dot_width = fc->GetGlyphWidth(dot_glyph); dot_sprite = fc->GetGlyph(dot_glyph); @@ -422,8 +422,8 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, TextColour colour = TC_BLACK; bool draw_shadow = false; for (int run_index = 0; run_index < line->CountRuns(); run_index++) { - const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index); - const Font *f = (const Font*)run->GetFont(); + const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); + const Font *f = (const Font*)run.GetFont(); FontCache *fc = f->fc; colour = f->colour; @@ -435,15 +435,15 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, draw_shadow = fc->GetDrawGlyphShadow() && (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK; - for (int i = 0; i < run->GetGlyphCount(); i++) { - GlyphID glyph = run->GetGlyphs()[i]; + for (int i = 0; i < run.GetGlyphCount(); i++) { + GlyphID glyph = run.GetGlyphs()[i]; /* Not a valid glyph (empty) */ if (glyph == 0xFFFF) continue; - int begin_x = (int)run->GetPositions()[i * 2] + left - offset_x; - int end_x = (int)run->GetPositions()[i * 2 + 2] + left - offset_x - 1; - int top = (int)run->GetPositions()[i * 2 + 1] + y; + int begin_x = (int)run.GetPositions()[i * 2] + left - offset_x; + int end_x = (int)run.GetPositions()[i * 2 + 2] + left - offset_x - 1; + int top = (int)run.GetPositions()[i * 2 + 1] + y; /* Truncated away. */ if (truncation && (begin_x < min_x || end_x > max_x)) continue; diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index b46ac20d58..f0dee2f538 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -143,14 +143,14 @@ public: }; /** A single line worth of VisualRuns. */ - class ICULine : public AutoDeleteSmallVector, public ParagraphLayouter::Line { + class ICULine : public std::vector, public ParagraphLayouter::Line { icu::ParagraphLayout::Line *l; ///< The actual ICU line. public: ICULine(icu::ParagraphLayout::Line *l) : l(l) { for (int i = 0; i < l->countRuns(); i++) { - this->push_back(new ICUVisualRun(l->getVisualRun(i))); + this->emplace_back(l->getVisualRun(i)); } } ~ICULine() override { delete l; } @@ -158,7 +158,7 @@ public: int GetLeading() const override { return l->getLeading(); } int GetWidth() const override { return l->getWidth(); } int CountRuns() const override { return l->countRuns(); } - const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override { return this->at(run); } + const ParagraphLayouter::VisualRun &GetVisualRun(int run) const override { return this->at(run); } int GetInternalCharLength(WChar c) const override { @@ -259,6 +259,7 @@ public: public: FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x); + FallbackVisualRun(FallbackVisualRun &&other) noexcept; ~FallbackVisualRun() override; const Font *GetFont() const override; int GetGlyphCount() const override; @@ -269,12 +270,12 @@ public: }; /** A single line worth of VisualRuns. */ - class FallbackLine : public AutoDeleteSmallVector, public ParagraphLayouter::Line { + class FallbackLine : public std::vector, public ParagraphLayouter::Line { public: int GetLeading() const override; int GetWidth() const override; int CountRuns() const override; - const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override; + const ParagraphLayouter::VisualRun &GetVisualRun(int run) const override; int GetInternalCharLength(WChar c) const override { return 1; } }; @@ -350,6 +351,18 @@ FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const } } +/** Move constructor for visual runs.*/ +FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(FallbackVisualRun &&other) noexcept : font(other.font), glyph_count(other.glyph_count) +{ + this->positions = other.positions; + this->glyph_to_char = other.glyph_to_char; + this->glyphs = other.glyphs; + + other.positions = NULL; + other.glyph_to_char = NULL; + other.glyphs = NULL; +} + /** Free all data. */ FallbackParagraphLayout::FallbackVisualRun::~FallbackVisualRun() { @@ -419,8 +432,8 @@ int FallbackParagraphLayout::FallbackVisualRun::GetLeading() const int FallbackParagraphLayout::FallbackLine::GetLeading() const { int leading = 0; - for (const FallbackVisualRun * const &run : *this) { - leading = max(leading, run->GetLeading()); + for (const auto &run : *this) { + leading = max(leading, run.GetLeading()); } return leading; @@ -439,8 +452,8 @@ int FallbackParagraphLayout::FallbackLine::GetWidth() const * Since there is no left-to-right support, taking this value of * the last run gives us the end of the line and thus the width. */ - const ParagraphLayouter::VisualRun *run = this->GetVisualRun(this->CountRuns() - 1); - return (int)run->GetPositions()[run->GetGlyphCount() * 2]; + const auto &run = this->GetVisualRun(this->CountRuns() - 1); + return (int)run.GetPositions()[run.GetGlyphCount() * 2]; } /** @@ -456,7 +469,7 @@ int FallbackParagraphLayout::FallbackLine::CountRuns() const * Get a specific visual run. * @return The visual run. */ -const ParagraphLayouter::VisualRun *FallbackParagraphLayout::FallbackLine::GetVisualRun(int run) const +const ParagraphLayouter::VisualRun &FallbackParagraphLayout::FallbackLine::GetVisualRun(int run) const { return this->at(run); } @@ -498,7 +511,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) if (*this->buffer == '\0') { /* Only a newline. */ this->buffer = NULL; - l->push_back(new FallbackVisualRun(this->runs.front().second, this->buffer, 0, 0)); + l->emplace_back(this->runs.front().second, this->buffer, 0, 0); return l; } @@ -527,7 +540,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) if (this->buffer == next_run) { int w = l->GetWidth(); - l->push_back(new FallbackVisualRun(iter->second, begin, this->buffer - begin, w)); + l->emplace_back(iter->second, begin, this->buffer - begin, w); iter++; assert(iter != this->runs.End()); @@ -574,7 +587,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) if (l->size() == 0 || last_char - begin != 0) { int w = l->GetWidth(); - l->push_back(new FallbackVisualRun(iter->second, begin, last_char - begin, w)); + l->emplace_back(iter->second, begin, last_char - begin, w); } return l; } @@ -772,12 +785,12 @@ Point Layouter::GetCharPosition(const char *ch) const /* Scan all runs until we've found our code point index. */ for (int run_index = 0; run_index < line->CountRuns(); run_index++) { - const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index); + const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); - for (int i = 0; i < run->GetGlyphCount(); i++) { + for (int i = 0; i < run.GetGlyphCount(); i++) { /* Matching glyph? Return position. */ - if ((size_t)run->GetGlyphToCharMap()[i] == index) { - Point p = { (int)run->GetPositions()[i * 2], (int)run->GetPositions()[i * 2 + 1] }; + if ((size_t)run.GetGlyphToCharMap()[i] == index) { + Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] }; return p; } } @@ -798,18 +811,18 @@ const char *Layouter::GetCharAtPosition(int x) const const ParagraphLayouter::Line *line = this->front(); for (int run_index = 0; run_index < line->CountRuns(); run_index++) { - const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index); + const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); - for (int i = 0; i < run->GetGlyphCount(); i++) { + for (int i = 0; i < run.GetGlyphCount(); i++) { /* Not a valid glyph (empty). */ - if (run->GetGlyphs()[i] == 0xFFFF) continue; + if (run.GetGlyphs()[i] == 0xFFFF) continue; - int begin_x = (int)run->GetPositions()[i * 2]; - int end_x = (int)run->GetPositions()[i * 2 + 2]; + int begin_x = (int)run.GetPositions()[i * 2]; + int end_x = (int)run.GetPositions()[i * 2 + 2]; if (IsInsideMM(x, begin_x, end_x)) { /* Found our glyph, now convert to UTF-8 string index. */ - size_t index = run->GetGlyphToCharMap()[i]; + size_t index = run.GetGlyphToCharMap()[i]; size_t cur_idx = 0; for (const char *str = this->string; *str != '\0'; ) { diff --git a/src/gfx_layout.h b/src/gfx_layout.h index 93cc6fb2da..8a642c795b 100644 --- a/src/gfx_layout.h +++ b/src/gfx_layout.h @@ -137,7 +137,7 @@ public: virtual int GetLeading() const = 0; virtual int GetWidth() const = 0; virtual int CountRuns() const = 0; - virtual const VisualRun *GetVisualRun(int run) const = 0; + virtual const VisualRun &GetVisualRun(int run) const = 0; virtual int GetInternalCharLength(WChar c) const = 0; }; diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index f26421e368..55eac42f99 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -53,6 +53,7 @@ public: public: CoreTextVisualRun(CTRunRef run, Font *font, const CoreTextParagraphLayoutFactory::CharType *buff); + CoreTextVisualRun(CoreTextVisualRun &&other) = default; const GlyphID *GetGlyphs() const override { return &this->glyphs[0]; } const float *GetPositions() const override { return &this->positions[0]; } @@ -65,7 +66,7 @@ public: }; /** A single line worth of VisualRuns. */ - class CoreTextLine : public AutoDeleteSmallVector, public ParagraphLayouter::Line { + class CoreTextLine : public std::vector, public ParagraphLayouter::Line { public: CoreTextLine(CTLineRef line, const FontMap &fontMapping, const CoreTextParagraphLayoutFactory::CharType *buff) { @@ -78,7 +79,7 @@ public: auto map = fontMapping.begin(); while (map < fontMapping.end() - 1 && map->first <= chars.location) map++; - this->push_back(new CoreTextVisualRun(run, map->second, buff)); + this->emplace_back(run, map->second, buff); } CFRelease(line); } @@ -86,7 +87,7 @@ public: int GetLeading() const override; int GetWidth() const override; int CountRuns() const override { return this->size(); } - const VisualRun *GetVisualRun(int run) const override { return this->at(run); } + const VisualRun &GetVisualRun(int run) const override { return this->at(run); } int GetInternalCharLength(WChar c) const override { diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index a5d03b9489..f47d9236a7 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -90,6 +90,7 @@ public: public: UniscribeVisualRun(const UniscribeRun &range, int x); + UniscribeVisualRun(UniscribeVisualRun &&other) noexcept; ~UniscribeVisualRun() override { free(this->glyph_to_char); @@ -106,12 +107,12 @@ public: }; /** A single line worth of VisualRuns. */ - class UniscribeLine : public AutoDeleteSmallVector, public ParagraphLayouter::Line { + class UniscribeLine : public std::vector, public ParagraphLayouter::Line { public: int GetLeading() const override; int GetWidth() const override; int CountRuns() const override { return (uint)this->size(); } - const VisualRun *GetVisualRun(int run) const override { return this->at(run); } + const VisualRun &GetVisualRun(int run) const override { return this->at(run); } int GetInternalCharLength(WChar c) const override { @@ -424,7 +425,7 @@ static std::vector UniscribeItemizeString(UniscribeParagraphLayoutF if (!UniscribeShapeRun(this->text_buffer, run)) return NULL; } - line->push_back(new UniscribeVisualRun(run, cur_pos)); + line->emplace_back(run, cur_pos); cur_pos += run.total_advance; } @@ -448,8 +449,8 @@ static std::vector UniscribeItemizeString(UniscribeParagraphLayoutF int UniscribeParagraphLayout::UniscribeLine::GetLeading() const { int leading = 0; - for (const UniscribeVisualRun *run : *this) { - leading = max(leading, run->GetLeading()); + for (const auto &run : *this) { + leading = max(leading, run.GetLeading()); } return leading; @@ -462,8 +463,8 @@ int UniscribeParagraphLayout::UniscribeLine::GetLeading() const int UniscribeParagraphLayout::UniscribeLine::GetWidth() const { int length = 0; - for (const UniscribeVisualRun *run : *this) { - length += run->GetAdvance(); + for (const auto &run : *this) { + length += run.GetAdvance(); } return length; @@ -484,6 +485,14 @@ UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(const Uniscribe this->positions[this->num_glyphs * 2] = advance + x; } +UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(UniscribeVisualRun&& other) noexcept + : glyphs(std::move(other.glyphs)), positions(std::move(other.positions)), char_to_glyph(std::move(other.char_to_glyph)), + start_pos(other.start_pos), total_advance(other.total_advance), num_glyphs(other.num_glyphs), font(other.font) +{ + this->glyph_to_char = other.glyph_to_char; + other.glyph_to_char = NULL; +} + const int *UniscribeParagraphLayout::UniscribeVisualRun::GetGlyphToCharMap() const { if (this->glyph_to_char == NULL) { From baf9229931e4d5a3479892007e9bcc875bc9930b Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:31:10 +0200 Subject: [PATCH 06/13] Codechange: Replace AutoDeleteSmallVector with direct std::vector use in text layout code. --- src/gfx.cpp | 20 ++++++++--------- src/gfx_layout.cpp | 34 ++++++++++++++--------------- src/gfx_layout.h | 4 ++-- src/os/macosx/string_osx.cpp | 14 ++++++------ src/os/windows/string_uniscribe.cpp | 6 ++--- src/stdafx.h | 1 + 6 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 7c90285ba8..cb6aa45361 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -340,12 +340,12 @@ static void SetColourRemap(TextColour colour) * @return In case of left or center alignment the right most pixel we have drawn to. * In case of right alignment the left most pixel we have drawn to. */ -static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, int right, StringAlignment align, bool underline, bool truncation) +static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, int right, StringAlignment align, bool underline, bool truncation) { - if (line->CountRuns() == 0) return 0; + if (line.CountRuns() == 0) return 0; - int w = line->GetWidth(); - int h = line->GetLeading(); + int w = line.GetWidth(); + int h = line.GetLeading(); /* * The following is needed for truncation. @@ -376,7 +376,7 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, * another size would be chosen it won't have truncated too little for * the truncation dots. */ - FontCache *fc = ((const Font*)line->GetVisualRun(0).GetFont())->fc; + FontCache *fc = ((const Font*)line.GetVisualRun(0).GetFont())->fc; GlyphID dot_glyph = fc->MapCharToGlyph('.'); dot_width = fc->GetGlyphWidth(dot_glyph); dot_sprite = fc->GetGlyph(dot_glyph); @@ -421,8 +421,8 @@ static int DrawLayoutLine(const ParagraphLayouter::Line *line, int y, int left, TextColour colour = TC_BLACK; bool draw_shadow = false; - for (int run_index = 0; run_index < line->CountRuns(); run_index++) { - const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); + for (int run_index = 0; run_index < line.CountRuns(); run_index++) { + const ParagraphLayouter::VisualRun &run = line.GetVisualRun(run_index); const Font *f = (const Font*)run.GetFont(); FontCache *fc = f->fc; @@ -512,7 +512,7 @@ int DrawString(int left, int right, int top, const char *str, TextColour colour, Layouter layout(str, INT32_MAX, colour, fontsize); if (layout.size() == 0) return 0; - return DrawLayoutLine(layout.front(), top, left, right, align, underline, true); + return DrawLayoutLine(*layout.front(), top, left, right, align, underline, true); } /** @@ -648,14 +648,14 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, const char *st int last_line = top; int first_line = bottom; - for (const ParagraphLayouter::Line *line : layout) { + for (const auto &line : layout) { int line_height = line->GetLeading(); if (y >= top && y < bottom) { last_line = y + line_height; if (first_line > y) first_line = y; - DrawLayoutLine(line, y, left, right, align, underline, false); + DrawLayoutLine(*line, y, left, right, align, underline, false); } y += line_height; } diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index f0dee2f538..ff176e81f0 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -124,7 +124,7 @@ le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &poin /** * Wrapper for doing layouts with ICU. */ -class ICUParagraphLayout : public AutoDeleteSmallVector, public ParagraphLayouter { +class ICUParagraphLayout : public ParagraphLayouter { icu::ParagraphLayout *p; ///< The actual ICU paragraph layout. public: /** Visual run contains data about the bit of text with the same font. */ @@ -171,10 +171,10 @@ public: ~ICUParagraphLayout() override { delete p; } void Reflow() override { p->reflow(); } - ParagraphLayouter::Line *NextLine(int max_width) override + std::unique_ptr NextLine(int max_width) override { icu::ParagraphLayout::Line *l = p->nextLine(max_width); - return l == NULL ? NULL : new ICULine(l); + return std::unique_ptr(l == NULL ? NULL : new ICULine(l)); } }; @@ -286,7 +286,7 @@ public: FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs); void Reflow() override; - const ParagraphLayouter::Line *NextLine(int max_width) override; + std::unique_ptr NextLine(int max_width) override; }; /** @@ -498,7 +498,7 @@ void FallbackParagraphLayout::Reflow() * @param max_width The maximum width of the string. * @return A Line, or NULL when at the end of the paragraph. */ -const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) +std::unique_ptr FallbackParagraphLayout::NextLine(int max_width) { /* Simple idea: * - split a line at a newline character, or at a space where we can break a line. @@ -506,13 +506,13 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) */ if (this->buffer == NULL) return NULL; - FallbackLine *l = new FallbackLine(); + std::unique_ptr l(new FallbackLine()); if (*this->buffer == '\0') { /* Only a newline. */ this->buffer = NULL; l->emplace_back(this->runs.front().second, this->buffer, 0, 0); - return l; + return std::move(l); // Not supposed to be needed, but clang-3.8 barfs otherwise. } int offset = this->buffer - this->buffer_begin; @@ -562,7 +562,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) /* The character is wider than allowed width; don't know * what to do with this case... bail out! */ this->buffer = NULL; - return l; + return std::move(l); // Not supposed to be needed, but clang-3.8 barfs otherwise. } if (last_space == NULL) { @@ -589,7 +589,7 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) int w = l->GetWidth(); l->emplace_back(iter->second, begin, last_char - begin, w); } - return l; + return std::move(l); // Not supposed to be needed, but clang-3.8 barfs otherwise. } /** @@ -730,12 +730,12 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi } } - /* Copy all lines into a local cache so we can reuse them later on more easily. */ - const ParagraphLayouter::Line *l; - while ((l = line.layout->NextLine(maxw)) != NULL) { - this->push_back(l); + /* Move all lines into a local cache so we can reuse them later on more easily. */ + for (;;) { + auto l = line.layout->NextLine(maxw); + if (l == NULL) break; + this->push_back(std::move(l)); } - } while (c != '\0'); } @@ -746,7 +746,7 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi Dimension Layouter::GetBounds() { Dimension d = { 0, 0 }; - for (const ParagraphLayouter::Line *l : *this) { + for (const auto &l : *this) { d.width = max(d.width, l->GetWidth()); d.height += l->GetLeading(); } @@ -775,7 +775,7 @@ Point Layouter::GetCharPosition(const char *ch) const if (str == ch) { /* Valid character. */ - const ParagraphLayouter::Line *line = this->front(); + const auto &line = this->front(); /* Pointer to the end-of-string/line marker? Return total line width. */ if (*ch == '\0' || *ch == '\n') { @@ -808,7 +808,7 @@ Point Layouter::GetCharPosition(const char *ch) const */ const char *Layouter::GetCharAtPosition(int x) const { - const ParagraphLayouter::Line *line = this->front(); + const auto &line = this->front(); for (int run_index = 0; run_index < line->CountRuns(); run_index++) { const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); diff --git a/src/gfx_layout.h b/src/gfx_layout.h index 8a642c795b..1047366111 100644 --- a/src/gfx_layout.h +++ b/src/gfx_layout.h @@ -142,7 +142,7 @@ public: }; virtual void Reflow() = 0; - virtual const Line *NextLine(int max_width) = 0; + virtual std::unique_ptr NextLine(int max_width) = 0; }; /** @@ -150,7 +150,7 @@ public: * * It also accounts for the memory allocations and frees. */ -class Layouter : public AutoDeleteSmallVector { +class Layouter : public std::vector> { const char *string; ///< Pointer to the original string. /** Key into the linecache */ diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index 55eac42f99..580be35203 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -111,7 +111,7 @@ public: this->cur_offset = 0; } - const Line *NextLine(int max_width) override; + std::unique_ptr NextLine(int max_width) override; }; @@ -188,7 +188,7 @@ static CTRunDelegateCallbacks _sprite_font_callback = { return typesetter != NULL ? new CoreTextParagraphLayout(typesetter, buff, length, fontMapping) : NULL; } -/* virtual */ const CoreTextParagraphLayout::Line *CoreTextParagraphLayout::NextLine(int max_width) +/* virtual */ std::unique_ptr CoreTextParagraphLayout::NextLine(int max_width) { if (this->cur_offset >= this->length) return NULL; @@ -200,7 +200,7 @@ static CTRunDelegateCallbacks _sprite_font_callback = { CTLineRef line = CTTypesetterCreateLine(this->typesetter, CFRangeMake(this->cur_offset, len)); this->cur_offset += len; - return line != NULL ? new CoreTextLine(line, this->font_map, this->text_buffer) : NULL; + return std::unique_ptr(line != NULL ? new CoreTextLine(line, this->font_map, this->text_buffer) : NULL); } CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font *font, const CoreTextParagraphLayoutFactory::CharType *buff) : font(font) @@ -244,8 +244,8 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font int CoreTextParagraphLayout::CoreTextLine::GetLeading() const { int leading = 0; - for (const CoreTextVisualRun * const &run : *this) { - leading = max(leading, run->GetLeading()); + for (const auto &run : *this) { + leading = max(leading, run.GetLeading()); } return leading; @@ -260,8 +260,8 @@ int CoreTextParagraphLayout::CoreTextLine::GetWidth() const if (this->size() == 0) return 0; int total_width = 0; - for (const CoreTextVisualRun * const &run : *this) { - total_width += run->GetAdvance(); + for (const auto &run : *this) { + total_width += run.GetAdvance(); } return total_width; diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index f47d9236a7..5abe848bd2 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -134,7 +134,7 @@ public: this->cur_range_offset = 0; } - const Line *NextLine(int max_width) override; + std::unique_ptr NextLine(int max_width) override; }; void UniscribeResetScriptCache(FontSize size) @@ -318,7 +318,7 @@ static std::vector UniscribeItemizeString(UniscribeParagraphLayoutF return new UniscribeParagraphLayout(ranges, buff); } -/* virtual */ const ParagraphLayouter::Line *UniscribeParagraphLayout::NextLine(int max_width) +/* virtual */ std::unique_ptr UniscribeParagraphLayout::NextLine(int max_width) { std::vector::iterator start_run = this->cur_range; std::vector::iterator last_run = this->cur_range; @@ -404,7 +404,7 @@ static std::vector UniscribeItemizeString(UniscribeParagraphLayoutF if (FAILED(ScriptLayout((int)bidi_level.size(), &bidi_level[0], &vis_to_log[0], NULL))) return NULL; /* Create line. */ - UniscribeLine *line = new UniscribeLine(); + std::unique_ptr line(new UniscribeLine()); int cur_pos = 0; for (std::vector::iterator l = vis_to_log.begin(); l != vis_to_log.end(); l++) { diff --git a/src/stdafx.h b/src/stdafx.h index a9ed460c26..f85d68aa04 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -83,6 +83,7 @@ #include #include #include +#include #ifndef SIZE_MAX #define SIZE_MAX ((size_t)-1) From d3e113eb5f618ce0174fa0dfa2591cb96e999350 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:31:17 +0200 Subject: [PATCH 07/13] Codechange: Use std::vector instead of AutoDeleteSmallVector in GS text handling. --- src/game/game_text.cpp | 21 ++++++++++----------- src/game/game_text.hpp | 10 +++++----- src/saveload/game_sl.cpp | 6 +++--- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index 5016f967d9..26498338c1 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -23,6 +23,7 @@ #include "table/strings.h" #include +#include #include "../safeguards.h" @@ -80,9 +81,8 @@ LanguageStrings::~LanguageStrings() * @param file The file to read from. * @return The raw strings, or NULL upon error. */ -LanguageStrings *ReadRawLanguageStrings(const char *file) +std::unique_ptr ReadRawLanguageStrings(const char *file) { - LanguageStrings *ret = NULL; try { size_t to_read; FILE *fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read); @@ -100,7 +100,7 @@ LanguageStrings *ReadRawLanguageStrings(const char *file) /* Check for invalid empty filename */ if (*langname == '.' || *langname == 0) return NULL; - ret = new LanguageStrings(langname, strchr(langname, '.')); + std::unique_ptr ret(new LanguageStrings(langname, strchr(langname, '.'))); char buffer[2048]; while (to_read != 0 && fgets(buffer, sizeof(buffer), fh) != NULL) { @@ -122,7 +122,6 @@ LanguageStrings *ReadRawLanguageStrings(const char *file) return ret; } catch (...) { - delete ret; return NULL; } } @@ -140,8 +139,8 @@ struct StringListReader : StringReader { * @param master Are we reading the master file? * @param translation Are we reading a translation? */ - StringListReader(StringData &data, const LanguageStrings *strings, bool master, bool translation) : - StringReader(data, strings->language, master, translation), p(strings->lines.data()), end(p + strings->lines.size()) + StringListReader(StringData &data, const LanguageStrings &strings, bool master, bool translation) : + StringReader(data, strings.language, master, translation), p(strings.lines.data()), end(p + strings.lines.size()) { } @@ -309,7 +308,7 @@ GameStrings *LoadTranslations() void GameStrings::Compile() { StringData data(1); - StringListReader master_reader(data, this->raw_strings[0], true, false); + StringListReader master_reader(data, *this->raw_strings[0], true, false); master_reader.ParseFile(); if (_errors != 0) throw std::exception(); @@ -318,13 +317,13 @@ void GameStrings::Compile() StringNameWriter id_writer(&this->string_names); id_writer.WriteHeader(data); - for (LanguageStrings *p : this->raw_strings) { + for (const auto &p : this->raw_strings) { data.FreeTranslation(); - StringListReader translation_reader(data, p, false, strcmp(p->language, "english") != 0); + StringListReader translation_reader(data, *p, false, strcmp(p->language, "english") != 0); translation_reader.ParseFile(); if (_errors != 0) throw std::exception(); - this->compiled_strings.push_back(new LanguageStrings(p->language)); + this->compiled_strings.emplace_back(new LanguageStrings(p->language)); TranslationWriter writer(&this->compiled_strings.back()->lines); writer.WriteLang(data); } @@ -392,7 +391,7 @@ void ReconsiderGameScriptLanguage() assert(language != NULL); language++; - for (LanguageStrings *p : _current_data->compiled_strings) { + for (auto &p : _current_data->compiled_strings) { if (strcmp(p->language, language) == 0) { _current_data->cur_language = p; return; diff --git a/src/game/game_text.hpp b/src/game/game_text.hpp index 11c63b5abb..d199a52819 100644 --- a/src/game/game_text.hpp +++ b/src/game/game_text.hpp @@ -29,12 +29,12 @@ struct LanguageStrings { /** Container for all the game strings. */ struct GameStrings { - uint version; ///< The version of the language strings. - LanguageStrings *cur_language; ///< The current (compiled) language. + uint version; ///< The version of the language strings. + std::shared_ptr cur_language; ///< The current (compiled) language. - AutoDeleteSmallVector raw_strings; ///< The raw strings per language, first must be English/the master language!. - AutoDeleteSmallVector compiled_strings; ///< The compiled strings per language, first must be English/the master language!. - StringList string_names; ///< The names of the compiled strings. + std::vector> raw_strings; ///< The raw strings per language, first must be English/the master language!. + std::vector> compiled_strings; ///< The compiled strings per language, first must be English/the master language!. + StringList string_names; ///< The names of the compiled strings. void Compile(); }; diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index d2a968717a..626afb17e9 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -150,13 +150,13 @@ static void Load_GSTR() _game_saveload_string = NULL; SlObject(NULL, _game_language_header); - LanguageStrings *ls = new LanguageStrings(_game_saveload_string != NULL ? _game_saveload_string : ""); + std::unique_ptr ls(new LanguageStrings(_game_saveload_string != NULL ? _game_saveload_string : "")); for (uint i = 0; i < _game_saveload_strings; i++) { SlObject(NULL, _game_language_string); ls->lines.push_back(stredup(_game_saveload_string != NULL ? _game_saveload_string : "")); } - _current_data->raw_strings.push_back(ls); + _current_data->raw_strings.push_back(std::move(ls)); } /* If there were no strings in the savegame, set GameStrings to NULL */ @@ -176,7 +176,7 @@ static void Save_GSTR() for (uint i = 0; i < _current_data->raw_strings.size(); i++) { SlSetArrayIndex(i); - SlAutolength((AutolengthProc *)SaveReal_GSTR, _current_data->raw_strings[i]); + SlAutolength((AutolengthProc *)SaveReal_GSTR, _current_data->raw_strings[i].get()); } } From c7b9987d081ae4e0103309b18c93deecc395dec9 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:31:24 +0200 Subject: [PATCH 08/13] Codechange: Switch DropDownList to directly use std::vector, thus making AutoDeleteSmallVector obsolete. DropDownListItem are strongly managed using std::unique_ptr to ensure leak-free handling. Appropriate use of move-semantics make intent a lot clearer than parameter comments and allows the compiler to generate copy-free code for most situations. --- src/ai/ai_gui.cpp | 6 +-- src/airport_gui.cpp | 6 +-- src/autoreplace_gui.cpp | 8 +-- src/company_gui.cpp | 8 +-- src/core/smallvec_type.hpp | 30 ----------- src/date_gui.cpp | 10 ++-- src/genworld_gui.cpp | 6 +-- src/group_gui.cpp | 3 +- src/industry_gui.cpp | 24 ++++----- src/music_gui.cpp | 3 +- src/newgrf_gui.cpp | 14 ++--- src/order_gui.cpp | 6 +-- src/rail_gui.cpp | 9 ++-- src/rail_gui.h | 2 +- src/settings_gui.cpp | 105 ++++++++++++++++-------------------- src/settings_gui.h | 2 +- src/story_gui.cpp | 18 +++---- src/toolbar_gui.cpp | 94 ++++++++++++++++---------------- src/vehicle_gui.cpp | 17 +++--- src/vehicle_gui_base.h | 2 +- src/widgets/dropdown.cpp | 56 ++++++++----------- src/widgets/dropdown_type.h | 8 +-- 22 files changed, 184 insertions(+), 253 deletions(-) diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index 2730070c32..eaf2a9d83b 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -479,12 +479,12 @@ struct AISettingsWindow : public Window { this->clicked_dropdown = true; this->closing_dropdown = false; - DropDownList *list = new DropDownList(); + DropDownList list; for (int i = config_item.min_value; i <= config_item.max_value; i++) { - list->push_back(new DropDownListCharStringItem(config_item.labels->Find(i)->second, i, false)); + list.emplace_back(new DropDownListCharStringItem(config_item.labels->Find(i)->second, i, false)); } - ShowDropDownListAt(this, list, old_val, -1, wi_rect, COLOUR_ORANGE, true); + ShowDropDownListAt(this, std::move(list), old_val, -1, wi_rect, COLOUR_ORANGE, true); } } } else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) { diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 7e16717894..d170b0cbbb 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -214,12 +214,12 @@ class BuildAirportWindow : public PickerWindowBase { Scrollbar *vscroll; /** Build a dropdown list of available airport classes */ - static DropDownList *BuildAirportClassDropDown() + static DropDownList BuildAirportClassDropDown() { - DropDownList *list = new DropDownList(); + DropDownList list; for (uint i = 0; i < AirportClass::GetClassCount(); i++) { - list->push_back(new DropDownListStringItem(AirportClass::Get((AirportClassID)i)->name, i, false)); + list.emplace_back(new DropDownListStringItem(AirportClass::Get((AirportClassID)i)->name, i, false)); } return list; diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index 78c2fdc31c..40f8d8ef2b 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -467,10 +467,10 @@ public: break; case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: { - DropDownList *list = new DropDownList(); - list->push_back(new DropDownListStringItem(STR_REPLACE_ENGINES, 1, false)); - list->push_back(new DropDownListStringItem(STR_REPLACE_WAGONS, 0, false)); - ShowDropDownList(this, list, this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN); + DropDownList list; + list.emplace_back(new DropDownListStringItem(STR_REPLACE_ENGINES, 1, false)); + list.emplace_back(new DropDownListStringItem(STR_REPLACE_WAGONS, 0, false)); + ShowDropDownList(this, std::move(list), this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN); break; } diff --git a/src/company_gui.cpp b/src/company_gui.cpp index a3f8a24b6c..1c23a12513 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -602,18 +602,18 @@ private: } } - DropDownList *list = new DropDownList(); + DropDownList list; if (default_livery != NULL) { /* Add COLOUR_END to put the colour out of range, but also allow us to show what the default is */ default_col = (primary ? default_livery->colour1 : default_livery->colour2) + COLOUR_END; - list->push_back(new DropDownListColourItem(default_col, false)); + list.emplace_back(new DropDownListColourItem(default_col, false)); } for (uint i = 0; i < lengthof(_colour_dropdown); i++) { - list->push_back(new DropDownListColourItem(i, HasBit(used_colours, i))); + list.emplace_back(new DropDownListColourItem(i, HasBit(used_colours, i))); } byte sel = (default_livery == NULL || HasBit(livery->in_use, primary ? 0 : 1)) ? (primary ? livery->colour1 : livery->colour2) : default_col; - ShowDropDownList(this, list, sel, widget); + ShowDropDownList(this, std::move(list), sel, widget); } static int CDECL GroupNameSorter(const Group * const *a, const Group * const *b) diff --git a/src/core/smallvec_type.hpp b/src/core/smallvec_type.hpp index f43265ebe8..77b03ca6b7 100644 --- a/src/core/smallvec_type.hpp +++ b/src/core/smallvec_type.hpp @@ -99,36 +99,6 @@ public: } }; -/** - * Simple vector template class, with automatic delete. - * - * @note There are no asserts in the class so you have - * to care about that you grab an item which is - * inside the list. - * - * @param T The type of the items stored, must be a pointer - */ -template -class AutoDeleteSmallVector : public std::vector { -public: - ~AutoDeleteSmallVector() - { - this->Clear(); - } - - /** - * Remove all items from the list. - */ - inline void Clear() - { - for (T p : *this) { - delete p; - } - - std::vector::clear(); - } -}; - typedef AutoFreeSmallVector StringList; ///< Type for a list of strings. #endif /* SMALLVEC_TYPE_HPP */ diff --git a/src/date_gui.cpp b/src/date_gui.cpp index d55e7e2b34..900e42bd72 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -68,21 +68,21 @@ struct SetDateWindow : Window { void ShowDateDropDown(int widget) { int selected; - DropDownList *list = new DropDownList(); + DropDownList list; switch (widget) { default: NOT_REACHED(); case WID_SD_DAY: for (uint i = 0; i < 31; i++) { - list->push_back(new DropDownListStringItem(STR_DAY_NUMBER_1ST + i, i + 1, false)); + list.emplace_back(new DropDownListStringItem(STR_DAY_NUMBER_1ST + i, i + 1, false)); } selected = this->date.day; break; case WID_SD_MONTH: for (uint i = 0; i < 12; i++) { - list->push_back(new DropDownListStringItem(STR_MONTH_JAN + i, i, false)); + list.emplace_back(new DropDownListStringItem(STR_MONTH_JAN + i, i, false)); } selected = this->date.month; break; @@ -91,13 +91,13 @@ struct SetDateWindow : Window { for (Year i = this->min_year; i <= this->max_year; i++) { DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false); item->SetParam(0, i); - list->push_back(item); + list.emplace_back(item); } selected = this->date.year; break; } - ShowDropDownList(this, list, selected, widget); + ShowDropDownList(this, std::move(list), selected, widget); } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 697ce382d7..53cc2d39ea 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -282,14 +282,14 @@ static void LandscapeGenerationCallback(Window *w, bool confirmed) if (confirmed) StartGeneratingLandscape((GenerateLandscapeWindowMode)w->window_number); } -static DropDownList *BuildMapsizeDropDown() +static DropDownList BuildMapsizeDropDown() { - DropDownList *list = new DropDownList(); + DropDownList list; for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) { DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false); item->SetParam(0, 1LL << i); - list->push_back(item); + list.emplace_back(item); } return list; diff --git a/src/group_gui.cpp b/src/group_gui.cpp index ecc95064fa..22604fdf35 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -768,8 +768,7 @@ public: break; case WID_GL_MANAGE_VEHICLES_DROPDOWN: { - DropDownList *list = this->BuildActionDropdownList(true, Group::IsValidID(this->vli.index)); - ShowDropDownList(this, list, 0, WID_GL_MANAGE_VEHICLES_DROPDOWN); + ShowDropDownList(this, this->BuildActionDropdownList(true, Group::IsValidID(this->vli.index)), 0, WID_GL_MANAGE_VEHICLES_DROPDOWN); break; } diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index eff0a5f73d..2796cd979b 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2709,34 +2709,30 @@ struct IndustryCargoesWindow : public Window { break; case WID_IC_CARGO_DROPDOWN: { - DropDownList *lst = new DropDownList; + DropDownList lst; const CargoSpec *cs; FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) { - lst->push_back(new DropDownListStringItem(cs->name, cs->Index(), false)); + lst.emplace_back(new DropDownListStringItem(cs->name, cs->Index(), false)); } - if (lst->size() == 0) { - delete lst; - break; + if (!lst.empty()) { + int selected = (this->ind_cargo >= NUM_INDUSTRYTYPES) ? (int)(this->ind_cargo - NUM_INDUSTRYTYPES) : -1; + ShowDropDownList(this, std::move(lst), selected, WID_IC_CARGO_DROPDOWN, 0, true); } - int selected = (this->ind_cargo >= NUM_INDUSTRYTYPES) ? (int)(this->ind_cargo - NUM_INDUSTRYTYPES) : -1; - ShowDropDownList(this, lst, selected, WID_IC_CARGO_DROPDOWN, 0, true); break; } case WID_IC_IND_DROPDOWN: { - DropDownList *lst = new DropDownList; + DropDownList lst; for (uint i = 0; i < NUM_INDUSTRYTYPES; i++) { IndustryType ind = _sorted_industry_types[i]; const IndustrySpec *indsp = GetIndustrySpec(ind); if (!indsp->enabled) continue; - lst->push_back(new DropDownListStringItem(indsp->name, ind, false)); + lst.emplace_back(new DropDownListStringItem(indsp->name, ind, false)); } - if (lst->size() == 0) { - delete lst; - break; + if (!lst.empty()) { + int selected = (this->ind_cargo < NUM_INDUSTRYTYPES) ? (int)this->ind_cargo : -1; + ShowDropDownList(this, std::move(lst), selected, WID_IC_IND_DROPDOWN, 0, true); } - int selected = (this->ind_cargo < NUM_INDUSTRYTYPES) ? (int)this->ind_cargo : -1; - ShowDropDownList(this, lst, selected, WID_IC_IND_DROPDOWN, 0, true); break; } } diff --git a/src/music_gui.cpp b/src/music_gui.cpp index da63192e02..90fd476690 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -571,8 +571,7 @@ struct MusicTrackSelectionWindow : public Window { case WID_MTS_MUSICSET: { int selected = 0; - DropDownList *dropdown = BuildMusicSetDropDownList(&selected); - ShowDropDownList(this, dropdown, selected, widget, 0, true, false); + ShowDropDownList(this, BuildMusicSetDropDownList(&selected), selected, widget, 0, true, false); break; } diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index bd5d07a86a..520882667d 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -376,12 +376,12 @@ struct NewGRFParametersWindow : public Window { this->clicked_dropdown = true; this->closing_dropdown = false; - DropDownList *list = new DropDownList(); + DropDownList list; for (uint32 i = par_info->min_value; i <= par_info->max_value; i++) { - list->push_back(new DropDownListCharStringItem(GetGRFStringFromGRFText(par_info->value_names.Find(i)->second), i, false)); + list.emplace_back(new DropDownListCharStringItem(GetGRFStringFromGRFText(par_info->value_names.Find(i)->second), i, false)); } - ShowDropDownListAt(this, list, old_val, -1, wi_rect, COLOUR_ORANGE, true); + ShowDropDownListAt(this, std::move(list), old_val, -1, wi_rect, COLOUR_ORANGE, true); } } } else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) { @@ -924,19 +924,19 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { switch (widget) { case WID_NS_PRESET_LIST: { - DropDownList *list = new DropDownList(); + DropDownList list; /* Add 'None' option for clearing list */ - list->push_back(new DropDownListStringItem(STR_NONE, -1, false)); + list.emplace_back(new DropDownListStringItem(STR_NONE, -1, false)); for (uint i = 0; i < _grf_preset_list.size(); i++) { if (_grf_preset_list[i] != NULL) { - list->push_back(new DropDownListCharStringItem(_grf_preset_list[i], i, false)); + list.emplace_back(new DropDownListCharStringItem(_grf_preset_list[i], i, false)); } } this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window - ShowDropDownList(this, list, this->preset, WID_NS_PRESET_LIST); + ShowDropDownList(this, std::move(list), this->preset, WID_NS_PRESET_LIST); break; } diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 0b1ee2ae66..a48638a858 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -1295,11 +1295,11 @@ public: break; case WID_O_COND_VARIABLE: { - DropDownList *list = new DropDownList(); + DropDownList list; for (uint i = 0; i < lengthof(_order_conditional_variable); i++) { - list->push_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + _order_conditional_variable[i], _order_conditional_variable[i], false)); + list.emplace_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + _order_conditional_variable[i], _order_conditional_variable[i], false)); } - ShowDropDownList(this, list, this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable(), WID_O_COND_VARIABLE); + ShowDropDownList(this, std::move(list), this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable(), WID_O_COND_VARIABLE); break; } diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 176e8e6efb..e3d307dc94 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -1987,7 +1987,7 @@ void InitializeRailGUI() * @param all_option Whether to add an 'all types' item. * @return The populated and sorted #DropDownList. */ -DropDownList *GetRailTypeDropDownList(bool for_replacement, bool all_option) +DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option) { RailTypes used_railtypes; RailTypes avail_railtypes; @@ -2003,11 +2003,10 @@ DropDownList *GetRailTypeDropDownList(bool for_replacement, bool all_option) used_railtypes = GetRailTypes(true); } - DropDownList *list = new DropDownList(); + DropDownList list; if (all_option) { - DropDownListStringItem *item = new DropDownListStringItem(STR_REPLACE_ALL_RAILTYPE, INVALID_RAILTYPE, false); - list->push_back(item); + list.emplace_back(new DropDownListStringItem(STR_REPLACE_ALL_RAILTYPE, INVALID_RAILTYPE, false)); } Dimension d = { 0, 0 }; @@ -2038,7 +2037,7 @@ DropDownList *GetRailTypeDropDownList(bool for_replacement, bool all_option) } item->SetParam(0, rti->strings.menu_text); item->SetParam(1, rti->max_speed); - list->push_back(item); + list.emplace_back(item); } return list; } diff --git a/src/rail_gui.h b/src/rail_gui.h index e7a03b9120..0a5f240ab3 100644 --- a/src/rail_gui.h +++ b/src/rail_gui.h @@ -19,6 +19,6 @@ struct Window *ShowBuildRailToolbar(RailType railtype); void ReinitGuiAfterToggleElrail(bool disable); bool ResetSignalVariant(int32 = 0); void InitializeRailGUI(); -DropDownList *GetRailTypeDropDownList(bool for_replacement = false, bool all_option = false); +DropDownList GetRailTypeDropDownList(bool for_replacement = false, bool all_option = false); #endif /* RAIL_GUI_H */ diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index c15f075ecf..34514c86f0 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -122,20 +122,20 @@ static int GetCurRes() static void ShowCustCurrency(); template -static DropDownList *BuildSetDropDownList(int *selected_index, bool allow_selection) +static DropDownList BuildSetDropDownList(int *selected_index, bool allow_selection) { int n = T::GetNumSets(); *selected_index = T::GetIndexOfUsedSet(); - DropDownList *list = new DropDownList(); + DropDownList list; for (int i = 0; i < n; i++) { - list->push_back(new DropDownListCharStringItem(T::GetSet(i)->name, i, !allow_selection && (*selected_index != i))); + list.emplace_back(new DropDownListCharStringItem(T::GetSet(i)->name, i, !allow_selection && (*selected_index != i))); } return list; } -DropDownList *BuildMusicSetDropDownList(int *selected_index) +DropDownList BuildMusicSetDropDownList(int *selected_index) { return BuildSetDropDownList(selected_index, true); } @@ -200,12 +200,11 @@ struct GameOptionsWindow : Window { * @param selected_index Currently selected item * @return the built dropdown list, or NULL if the widget has no dropdown menu. */ - DropDownList *BuildDropDownList(int widget, int *selected_index) const + DropDownList BuildDropDownList(int widget, int *selected_index) const { - DropDownList *list = NULL; + DropDownList list; switch (widget) { case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown - list = new DropDownList(); *selected_index = this->opt->locale.currency; StringID *items = BuildCurrencyDropdown(); uint64 disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies(); @@ -213,18 +212,17 @@ struct GameOptionsWindow : Window { /* Add non-custom currencies; sorted naturally */ for (uint i = 0; i < CURRENCY_END; items++, i++) { if (i == CURRENCY_CUSTOM) continue; - list->push_back(new DropDownListStringItem(*items, i, HasBit(disabled, i))); + list.emplace_back(new DropDownListStringItem(*items, i, HasBit(disabled, i))); } - QSortT(list->data(), list->size(), DropDownListStringItem::NatSortFunc); + std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc); /* Append custom currency at the end */ - list->push_back(new DropDownListItem(-1, false)); // separator line - list->push_back(new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM))); + list.emplace_back(new DropDownListItem(-1, false)); // separator line + list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM))); break; } case WID_GO_ROADSIDE_DROPDOWN: { // Setup road-side dropdown - list = new DropDownList(); *selected_index = this->opt->vehicle.road_side; const StringID *items = _driveside_dropdown; uint disabled = 0; @@ -237,13 +235,12 @@ struct GameOptionsWindow : Window { } for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) { - list->push_back(new DropDownListStringItem(*items, i, HasBit(disabled, i))); + list.emplace_back(new DropDownListStringItem(*items, i, HasBit(disabled, i))); } break; } case WID_GO_TOWNNAME_DROPDOWN: { // Setup townname dropdown - list = new DropDownList(); *selected_index = this->opt->game_creation.town_name; int enabled_item = (_game_mode == GM_MENU || Town::GetNumItems() == 0) ? -1 : *selected_index; @@ -251,71 +248,66 @@ struct GameOptionsWindow : Window { /* Add and sort newgrf townnames generators */ for (int i = 0; i < _nb_grf_names; i++) { int result = _nb_orig_names + i; - list->push_back(new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0)); + list.emplace_back(new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0)); } - QSortT(list->data(), list->size(), DropDownListStringItem::NatSortFunc); + std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc); - size_t newgrf_size = list->size(); + size_t newgrf_size = list.size(); /* Insert newgrf_names at the top of the list */ if (newgrf_size > 0) { - list->push_back(new DropDownListItem(-1, false)); // separator line + list.emplace_back(new DropDownListItem(-1, false)); // separator line newgrf_size++; } /* Add and sort original townnames generators */ for (int i = 0; i < _nb_orig_names; i++) { - list->push_back(new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0)); + list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0)); } - QSortT(list->data() + newgrf_size, list->size() - newgrf_size, DropDownListStringItem::NatSortFunc); + std::sort(list.begin() + newgrf_size, list.end(), DropDownListStringItem::NatSortFunc); break; } case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown - list = new DropDownList(); *selected_index = _settings_client.gui.autosave; const StringID *items = _autosave_dropdown; for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) { - list->push_back(new DropDownListStringItem(*items, i, false)); + list.emplace_back(new DropDownListStringItem(*items, i, false)); } break; } case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown - list = new DropDownList(); for (uint i = 0; i < _languages.size(); i++) { if (&_languages[i] == _current_language) *selected_index = i; - list->push_back(new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false)); + list.emplace_back(new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false)); } - QSortT(list->data(), list->size(), DropDownListStringItem::NatSortFunc); + std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc); break; } case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown if (_num_resolutions == 0) break; - list = new DropDownList(); *selected_index = GetCurRes(); for (int i = 0; i < _num_resolutions; i++) { - list->push_back(new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false)); + list.emplace_back(new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false)); } break; case WID_GO_GUI_ZOOM_DROPDOWN: { - list = new DropDownList(); *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom; const StringID *items = _gui_zoom_dropdown; for (int i = 0; *items != INVALID_STRING_ID; items++, i++) { - list->push_back(new DropDownListStringItem(*items, i, _settings_client.gui.zoom_min > ZOOM_LVL_OUT_4X - i)); + list.emplace_back(new DropDownListStringItem(*items, i, _settings_client.gui.zoom_min > ZOOM_LVL_OUT_4X - i)); } break; } case WID_GO_FONT_ZOOM_DROPDOWN: { - list = new DropDownList(); *selected_index = ZOOM_LVL_OUT_4X - _font_zoom; const StringID *items = _font_zoom_dropdown; for (int i = 0; *items != INVALID_STRING_ID; items++, i++) { - list->push_back(new DropDownListStringItem(*items, i, false)); + list.emplace_back(new DropDownListStringItem(*items, i, false)); } break; } @@ -331,9 +323,6 @@ struct GameOptionsWindow : Window { case WID_GO_BASE_MUSIC_DROPDOWN: list = BuildMusicSetDropDownList(selected_index); break; - - default: - return NULL; } return list; @@ -429,17 +418,16 @@ struct GameOptionsWindow : Window { default: { int selected; - DropDownList *list = this->BuildDropDownList(widget, &selected); - if (list != NULL) { + DropDownList list = this->BuildDropDownList(widget, &selected); + if (!list.empty()) { /* Find the biggest item for the default size. */ - for (const DropDownListItem * const ddli : *list) { + for (const auto &ddli : list) { Dimension string_dim; int width = ddli->Width(); string_dim.width = width + padding.width; string_dim.height = ddli->Height(width) + padding.height; *size = maxdim(*size, string_dim); } - delete list; } } } @@ -477,9 +465,9 @@ struct GameOptionsWindow : Window { default: { int selected; - DropDownList *list = this->BuildDropDownList(widget, &selected); - if (list != NULL) { - ShowDropDownList(this, list, selected, widget); + DropDownList list = this->BuildDropDownList(widget, &selected); + if (!list.empty()) { + ShowDropDownList(this, std::move(list), selected, widget); } else { if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, WL_ERROR); } @@ -1952,28 +1940,25 @@ struct GameSettingsWindow : Window { } } - DropDownList *BuildDropDownList(int widget) const + DropDownList BuildDropDownList(int widget) const { - DropDownList *list = NULL; + DropDownList list; switch (widget) { case WID_GS_RESTRICT_DROPDOWN: - list = new DropDownList(); - for (int mode = 0; mode != RM_END; mode++) { /* If we are in adv. settings screen for the new game's settings, * we don't want to allow comparing with new game's settings. */ bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame; - list->push_back(new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled)); + list.emplace_back(new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled)); } break; case WID_GS_TYPE_DROPDOWN: - list = new DropDownList(); - list->push_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false)); - list->push_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME, false)); - list->push_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY, false)); - list->push_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false)); + list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false)); + list.emplace_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME, false)); + list.emplace_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY, false)); + list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false)); break; } return list; @@ -2045,17 +2030,17 @@ struct GameSettingsWindow : Window { break; case WID_GS_RESTRICT_DROPDOWN: { - DropDownList *list = this->BuildDropDownList(widget); - if (list != NULL) { - ShowDropDownList(this, list, this->filter.mode, widget); + DropDownList list = this->BuildDropDownList(widget); + if (!list.empty()) { + ShowDropDownList(this, std::move(list), this->filter.mode, widget); } break; } case WID_GS_TYPE_DROPDOWN: { - DropDownList *list = this->BuildDropDownList(widget); - if (list != NULL) { - ShowDropDownList(this, list, this->filter.type, widget); + DropDownList list = this->BuildDropDownList(widget); + if (!list.empty()) { + ShowDropDownList(this, std::move(list), this->filter.type, widget); } break; } @@ -2128,12 +2113,12 @@ struct GameSettingsWindow : Window { this->valuedropdown_entry = pe; this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED); - DropDownList *list = new DropDownList(); + DropDownList list; for (int i = sdb->min; i <= (int)sdb->max; i++) { - list->push_back(new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false)); + list.emplace_back(new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false)); } - ShowDropDownListAt(this, list, value, -1, wi_rect, COLOUR_ORANGE, true); + ShowDropDownListAt(this, std::move(list), value, -1, wi_rect, COLOUR_ORANGE, true); } } this->SetDirty(); diff --git a/src/settings_gui.h b/src/settings_gui.h index 23a343219f..a81fc0a2b3 100644 --- a/src/settings_gui.h +++ b/src/settings_gui.h @@ -24,7 +24,7 @@ void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clic void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable); void DrawBoolButton(int x, int y, bool state, bool clickable); -DropDownList *BuildMusicSetDropDownList(int *selected_index); +DropDownList BuildMusicSetDropDownList(int *selected_index); /* Actually implemented in music_gui.cpp */ void ChangeMusicSet(int index); diff --git a/src/story_gui.cpp b/src/story_gui.cpp index 5679bbdc6b..c90992c6b7 100644 --- a/src/story_gui.cpp +++ b/src/story_gui.cpp @@ -228,9 +228,9 @@ protected: /** * Builds the page selector drop down list. */ - DropDownList *BuildDropDownList() const + DropDownList BuildDropDownList() const { - DropDownList *list = new DropDownList(); + DropDownList list; uint16 page_num = 1; for (const StoryPage *p : this->story_pages) { bool current_page = p->index == this->selected_page_id; @@ -245,16 +245,10 @@ protected: item = str_item; } - list->push_back(item); + list.emplace_back(item); page_num++; } - /* Check if list is empty. */ - if (list->size() == 0) { - delete list; - list = NULL; - } - return list; } @@ -611,8 +605,8 @@ public: { switch (widget) { case WID_SB_SEL_PAGE: { - DropDownList *list = this->BuildDropDownList(); - if (list != NULL) { + DropDownList list = this->BuildDropDownList(); + if (!list.empty()) { /* Get the index of selected page. */ int selected = 0; for (uint16 i = 0; i < this->story_pages.size(); i++) { @@ -621,7 +615,7 @@ public: selected++; } - ShowDropDownList(this, list, selected, widget); + ShowDropDownList(this, std::move(list), selected, widget); } break; } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index eac99f2494..00d0bba0b0 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -181,9 +181,9 @@ public: * @param list List of items * @param def Default item */ -static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def) +static void PopupMainToolbMenu(Window *w, int widget, DropDownList &&list, int def) { - ShowDropDownList(w, list, def, widget, 0, true, true); + ShowDropDownList(w, std::move(list), def, widget, 0, true, true); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); } @@ -196,11 +196,11 @@ static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int de */ static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count) { - DropDownList *list = new DropDownList(); + DropDownList list; for (int i = 0; i < count; i++) { - list->push_back(new DropDownListStringItem(string + i, i, false)); + list.emplace_back(new DropDownListStringItem(string + i, i, false)); } - PopupMainToolbMenu(w, widget, list, 0); + PopupMainToolbMenu(w, widget, std::move(list), 0); } /** Enum for the Company Toolbar's network related buttons */ @@ -217,37 +217,37 @@ static const int CTMN_SPECTATOR = -4; ///< Show a company window as spectator */ static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0) { - DropDownList *list = new DropDownList(); + DropDownList list; switch (widget) { case WID_TN_COMPANIES: if (!_networking) break; /* Add the client list button for the companies menu */ - list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false)); + list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false)); if (_local_company == COMPANY_SPECTATOR) { - list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached())); + list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached())); } else { - list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached())); + list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached())); } break; case WID_TN_STORY: - list->push_back(new DropDownListStringItem(STR_STORY_BOOK_SPECTATOR, CTMN_SPECTATOR, false)); + list.emplace_back(new DropDownListStringItem(STR_STORY_BOOK_SPECTATOR, CTMN_SPECTATOR, false)); break; case WID_TN_GOAL: - list->push_back(new DropDownListStringItem(STR_GOALS_SPECTATOR, CTMN_SPECTATOR, false)); + list.emplace_back(new DropDownListStringItem(STR_GOALS_SPECTATOR, CTMN_SPECTATOR, false)); break; } for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { if (!Company::IsValidID(c)) continue; - list->push_back(new DropDownListCompanyItem(c, false, HasBit(grey, c))); + list.emplace_back(new DropDownListCompanyItem(c, false, HasBit(grey, c))); } - PopupMainToolbMenu(w, widget, list, _local_company == COMPANY_SPECTATOR ? (widget == WID_TN_COMPANIES ? CTMN_CLIENT_LIST : CTMN_SPECTATOR) : (int)_local_company); + PopupMainToolbMenu(w, widget, std::move(list), _local_company == COMPANY_SPECTATOR ? (widget == WID_TN_COMPANIES ? CTMN_CLIENT_LIST : CTMN_SPECTATOR) : (int)_local_company); } @@ -317,27 +317,27 @@ enum OptionMenuEntries { */ static CallBackFunction ToolbarOptionsClick(Window *w) { - DropDownList *list = new DropDownList(); - list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false)); - list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false)); + DropDownList list; + list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false)); + list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false)); /* Changes to the per-AI settings don't get send from the server to the clients. Clients get * the settings once they join but never update it. As such don't show the window at all * to network clients. */ - if (!_networking || _network_server) list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false)); - list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false)); - list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false)); - list->push_back(new DropDownListItem(-1, false)); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES))); - list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS))); + if (!_networking || _network_server) list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false)); + list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false)); + list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false)); + list.emplace_back(new DropDownListItem(-1, false)); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES))); + list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS))); - ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true); + ShowDropDownList(w, std::move(list), 0, WID_TN_SETTINGS, 140, true, true); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } @@ -463,24 +463,24 @@ enum MapMenuEntries { static CallBackFunction ToolbarMapClick(Window *w) { - DropDownList *list = new DropDownList(); - list->push_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false)); - list->push_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false)); - list->push_back(new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false)); - list->push_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false)); - PopupMainToolbMenu(w, WID_TN_SMALL_MAP, list, 0); + DropDownList list; + list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false)); + list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false)); + list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false)); + list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false)); + PopupMainToolbMenu(w, WID_TN_SMALL_MAP, std::move(list), 0); return CBF_NONE; } static CallBackFunction ToolbarScenMapTownDir(Window *w) { - DropDownList *list = new DropDownList(); - list->push_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false)); - list->push_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false)); - list->push_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false)); - list->push_back(new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false)); - list->push_back(new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false)); - PopupMainToolbMenu(w, WID_TE_SMALL_MAP, list, 0); + DropDownList list; + list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false)); + list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false)); + list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false)); + list.emplace_back(new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false)); + list.emplace_back(new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false)); + PopupMainToolbMenu(w, WID_TE_SMALL_MAP, std::move(list), 0); return CBF_NONE; } @@ -894,10 +894,10 @@ static CallBackFunction MenuClickBuildRail(int index) static CallBackFunction ToolbarBuildRoadClick(Window *w) { const Company *c = Company::Get(_local_company); - DropDownList *list = new DropDownList(); + DropDownList list; /* Road is always visible and available. */ - list->push_back(new DropDownListIconItem(SPR_IMG_ROAD_X_DIR, PAL_NONE, STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false)); + list.emplace_back(new DropDownListIconItem(SPR_IMG_ROAD_X_DIR, PAL_NONE, STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false)); /* Tram is only visible when there will be a tram, and available when that has been introduced. */ Engine *e; @@ -905,10 +905,10 @@ static CallBackFunction ToolbarBuildRoadClick(Window *w) if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue; if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue; - list->push_back(new DropDownListIconItem(SPR_IMG_TRAMWAY_X_DIR, PAL_NONE, STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM))); + list.emplace_back(new DropDownListIconItem(SPR_IMG_TRAMWAY_X_DIR, PAL_NONE, STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM))); break; } - ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true); + ShowDropDownList(w, std::move(list), _last_built_roadtype, WID_TN_ROADS, 140, true, true); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); return CBF_NONE; } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 647ab44f59..f940926502 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -164,17 +164,17 @@ Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bo * @param show_group If true include group-related stuff. * @return Itemlist for dropdown */ -DropDownList *BaseVehicleListWindow::BuildActionDropdownList(bool show_autoreplace, bool show_group) +DropDownList BaseVehicleListWindow::BuildActionDropdownList(bool show_autoreplace, bool show_group) { - DropDownList *list = new DropDownList(); + DropDownList list; - if (show_autoreplace) list->push_back(new DropDownListStringItem(STR_VEHICLE_LIST_REPLACE_VEHICLES, ADI_REPLACE, false)); - list->push_back(new DropDownListStringItem(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, false)); - list->push_back(new DropDownListStringItem(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, false)); + if (show_autoreplace) list.emplace_back(new DropDownListStringItem(STR_VEHICLE_LIST_REPLACE_VEHICLES, ADI_REPLACE, false)); + list.emplace_back(new DropDownListStringItem(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, false)); + list.emplace_back(new DropDownListStringItem(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, false)); if (show_group) { - list->push_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, false)); - list->push_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false)); + list.emplace_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, false)); + list.emplace_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false)); } return list; @@ -1636,8 +1636,7 @@ public: break; case WID_VL_MANAGE_VEHICLES_DROPDOWN: { - DropDownList *list = this->BuildActionDropdownList(VehicleListIdentifier::UnPack(this->window_number).type == VL_STANDARD, false); - ShowDropDownList(this, list, 0, WID_VL_MANAGE_VEHICLES_DROPDOWN); + ShowDropDownList(this, this->BuildActionDropdownList(VehicleListIdentifier::UnPack(this->window_number).type == VL_STANDARD, false), 0, WID_VL_MANAGE_VEHICLES_DROPDOWN); break; } diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h index 5755c7fa88..8e75278412 100644 --- a/src/vehicle_gui_base.h +++ b/src/vehicle_gui_base.h @@ -47,7 +47,7 @@ struct BaseVehicleListWindow : public Window { void SortVehicleList(); void BuildVehicleList(); Dimension GetActionDropdownSize(bool show_autoreplace, bool show_group); - DropDownList *BuildActionDropdownList(bool show_autoreplace, bool show_group); + DropDownList BuildActionDropdownList(bool show_autoreplace, bool show_group); }; uint GetVehicleListHeight(VehicleType type, uint divisor = 1); diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index d0ad6bc465..cb1382dd65 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -51,11 +51,11 @@ void DropDownListStringItem::Draw(int left, int right, int top, int bottom, bool * @return true if \a first precedes \a second. * @warning All items in the list need to be derivates of DropDownListStringItem. */ -/* static */ int DropDownListStringItem::NatSortFunc(const DropDownListItem * const *first, const DropDownListItem * const * second) +/* static */ int DropDownListStringItem::NatSortFunc(std::unique_ptr const &first, std::unique_ptr const &second) { char buffer1[512], buffer2[512]; - GetString(buffer1, static_cast(*first)->String(), lastof(buffer1)); - GetString(buffer2, static_cast(*second)->String(), lastof(buffer2)); + GetString(buffer1, static_cast(first.get())->String(), lastof(buffer1)); + GetString(buffer2, static_cast(second.get())->String(), lastof(buffer2)); return strnatcmp(buffer1, buffer2); } @@ -126,7 +126,7 @@ struct DropdownWindow : Window { WindowClass parent_wnd_class; ///< Parent window class. WindowNumber parent_wnd_num; ///< Parent window number. int parent_button; ///< Parent widget number where the window is dropped from. - const DropDownList *list; ///< List with dropdown menu items. + const DropDownList list; ///< List with dropdown menu items. int selected_index; ///< Index of the selected item in the list. byte click_delay; ///< Timer to delay selection. bool drag_mode; @@ -148,10 +148,10 @@ struct DropdownWindow : Window { * @param wi_colour Colour of the parent widget. * @param scroll Dropdown menu has a scrollbar. */ - DropdownWindow(Window *parent, const DropDownList *list, int selected, int button, bool instant_close, const Point &position, const Dimension &size, Colours wi_colour, bool scroll) - : Window(&_dropdown_desc) + DropdownWindow(Window *parent, DropDownList &&list, int selected, int button, bool instant_close, const Point &position, const Dimension &size, Colours wi_colour, bool scroll) + : Window(&_dropdown_desc), list(std::move(list)) { - assert(list->size() > 0); + assert(this->list.size() > 0); this->position = position; @@ -174,18 +174,17 @@ struct DropdownWindow : Window { /* Total length of list */ int list_height = 0; - for (const DropDownListItem *item : *list) { + for (const auto &item : this->list) { list_height += item->Height(items_width); } /* Capacity is the average number of items visible */ - this->vscroll->SetCapacity(size.height * (uint16)list->size() / list_height); - this->vscroll->SetCount((uint16)list->size()); + this->vscroll->SetCapacity(size.height * (uint16)this->list.size() / list_height); + this->vscroll->SetCount((uint16)this->list.size()); this->parent_wnd_class = parent->window_class; this->parent_wnd_num = parent->window_number; this->parent_button = button; - this->list = list; this->selected_index = selected; this->click_delay = 0; this->drag_mode = true; @@ -207,7 +206,6 @@ struct DropdownWindow : Window { pt.y -= w2->top; w2->OnDropdownClose(pt, this->parent_button, this->selected_index, this->instant_close); } - delete this->list; } virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) @@ -229,7 +227,7 @@ struct DropdownWindow : Window { int width = nwi->current_x - 4; int pos = this->vscroll->GetPosition(); - for (const DropDownListItem *item : *this->list) { + for (const auto &item : this->list) { /* Skip items that are scrolled up */ if (--pos >= 0) continue; @@ -255,7 +253,7 @@ struct DropdownWindow : Window { int y = r.top + 2; int pos = this->vscroll->GetPosition(); - for (const DropDownListItem *item : *this->list) { + for (const auto &item : this->list) { int item_height = item->Height(r.right - r.left + 1); /* Skip items that are scrolled up */ @@ -357,8 +355,7 @@ struct DropdownWindow : Window { /** * Show a drop down list. * @param w Parent window for the list. - * @param list Prepopulated DropDownList. Will be deleted when the list is - * closed. + * @param list Prepopulated DropDownList. * @param selected The initially selected list item. * @param button The widget which is passed to Window::OnDropdownSelect and OnDropdownClose. * Unless you override those functions, this should be then widget index of the dropdown button. @@ -368,7 +365,7 @@ struct DropdownWindow : Window { * @param instant_close Set to true if releasing mouse button should close the * list regardless of where the cursor is. */ -void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width, bool instant_close) +void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width, bool instant_close) { DeleteWindowById(WC_DROPDOWN_MENU, 0); @@ -384,7 +381,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b /* Total height of list */ uint height = 0; - for (const DropDownListItem *item : *list) { + for (const auto &item : list) { height += item->Height(width); if (auto_width) max_item_width = max(max_item_width, item->Width() + 5); } @@ -412,7 +409,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b /* If the dropdown doesn't fully fit, we need a dropdown. */ if (height > available_height) { scroll = true; - uint avg_height = height / (uint)list->size(); + uint avg_height = height / (uint)list.size(); /* Check at least there is space for one item. */ assert(available_height >= avg_height); @@ -435,7 +432,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b Point dw_pos = { w->left + (_current_text_dir == TD_RTL ? wi_rect.right + 1 - (int)width : wi_rect.left), top}; Dimension dw_size = {width, height}; - DropdownWindow *dropdown = new DropdownWindow(w, list, selected, button, instant_close, dw_pos, dw_size, wi_colour, scroll); + DropdownWindow *dropdown = new DropdownWindow(w, std::move(list), selected, button, instant_close, dw_pos, dw_size, wi_colour, scroll); /* The dropdown starts scrolling downwards when opening it towards * the top and holding down the mouse button. It can be fooled by @@ -446,8 +443,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b /** * Show a drop down list. * @param w Parent window for the list. - * @param list Prepopulated DropDownList. Will be deleted when the list is - * closed. + * @param list Prepopulated DropDownList. * @param selected The initially selected list item. * @param button The widget within the parent window that is used to determine * the list's location. @@ -456,7 +452,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b * @param instant_close Set to true if releasing mouse button should close the * list regardless of where the cursor is. */ -void ShowDropDownList(Window *w, const DropDownList *list, int selected, int button, uint width, bool auto_width, bool instant_close) +void ShowDropDownList(Window *w, DropDownList &&list, int selected, int button, uint width, bool auto_width, bool instant_close) { /* Our parent's button widget is used to determine where to place the drop * down list window. */ @@ -483,7 +479,7 @@ void ShowDropDownList(Window *w, const DropDownList *list, int selected, int but } } - ShowDropDownListAt(w, list, selected, button, wi_rect, wi_colour, auto_width, instant_close); + ShowDropDownListAt(w, std::move(list), selected, button, wi_rect, wi_colour, auto_width, instant_close); } /** @@ -499,21 +495,15 @@ void ShowDropDownList(Window *w, const DropDownList *list, int selected, int but */ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask, uint width) { - DropDownList *list = new DropDownList(); + DropDownList list; for (uint i = 0; strings[i] != INVALID_STRING_ID; i++) { if (!HasBit(hidden_mask, i)) { - list->push_back(new DropDownListStringItem(strings[i], i, HasBit(disabled_mask, i))); + list.emplace_back(new DropDownListStringItem(strings[i], i, HasBit(disabled_mask, i))); } } - /* No entries in the list? */ - if (list->size() == 0) { - delete list; - return; - } - - ShowDropDownList(w, list, selected, button, width); + if (!list.empty()) ShowDropDownList(w, std::move(list), selected, button, width); } /** diff --git a/src/widgets/dropdown_type.h b/src/widgets/dropdown_type.h index bf8638a924..26c699f164 100644 --- a/src/widgets/dropdown_type.h +++ b/src/widgets/dropdown_type.h @@ -49,7 +49,7 @@ public: void Draw(int left, int right, int top, int bottom, bool sel, Colours bg_colour) const override; virtual StringID String() const { return this->string; } - static int CDECL NatSortFunc(const DropDownListItem * const *first, const DropDownListItem * const *second); + static int NatSortFunc(std::unique_ptr const &first, std::unique_ptr const &second); }; /** @@ -98,10 +98,10 @@ public: /** * A drop down list is a collection of drop down list items. */ -typedef AutoDeleteSmallVector DropDownList; +typedef std::vector> DropDownList; -void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width = false, bool instant_close = false); +void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width = false, bool instant_close = false); -void ShowDropDownList(Window *w, const DropDownList *list, int selected, int button, uint width = 0, bool auto_width = false, bool instant_close = false); +void ShowDropDownList(Window *w, DropDownList &&list, int selected, int button, uint width = 0, bool auto_width = false, bool instant_close = false); #endif /* WIDGETS_DROPDOWN_TYPE_H */ From e804173595d49a537503ea08bec4663117bae047 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:31:33 +0200 Subject: [PATCH 09/13] Codechange: If something is a vector of strings, use a vector of strings instead of an AutoFreeSmallVector. --- src/console_cmds.cpp | 9 +++---- src/core/smallvec_type.hpp | 2 -- src/game/game_text.cpp | 35 +++++++++++------------- src/network/core/address.cpp | 11 ++++---- src/network/core/address.h | 2 +- src/network/core/tcp_listen.h | 6 ++--- src/network/network.cpp | 8 +++--- src/network/network_gui.cpp | 4 +-- src/network/network_server.cpp | 8 +++--- src/newgrf_gui.cpp | 49 +++++++++++++++------------------- src/openttd.cpp | 4 +-- src/saveload/game_sl.cpp | 8 +++--- src/settings.cpp | 39 +++++++++++++-------------- src/settings_func.h | 7 ++--- src/string_type.h | 6 +++++ 15 files changed, 94 insertions(+), 104 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 00b9536946..7a7d4827d8 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -553,7 +553,7 @@ DEF_CONSOLE_CMD(ConUnBan) /* Try by IP. */ uint index; for (index = 0; index < _network_ban_list.size(); index++) { - if (strcmp(_network_ban_list[index], argv[1]) == 0) break; + if (_network_ban_list[index] == argv[1]) break; } /* Try by index. */ @@ -563,9 +563,8 @@ DEF_CONSOLE_CMD(ConUnBan) if (index < _network_ban_list.size()) { char msg[64]; - seprintf(msg, lastof(msg), "Unbanned %s", _network_ban_list[index]); + seprintf(msg, lastof(msg), "Unbanned %s", _network_ban_list[index].c_str()); IConsolePrint(CC_DEFAULT, msg); - free(_network_ban_list[index]); _network_ban_list.erase(_network_ban_list.begin() + index); } else { IConsolePrint(CC_DEFAULT, "Invalid list index or IP not in ban-list."); @@ -585,8 +584,8 @@ DEF_CONSOLE_CMD(ConBanList) IConsolePrint(CC_DEFAULT, "Banlist: "); uint i = 1; - for (char *entry : _network_ban_list) { - IConsolePrintF(CC_DEFAULT, " %d) %s", i, entry); + for (const auto &entry : _network_ban_list) { + IConsolePrintF(CC_DEFAULT, " %d) %s", i, entry.c_str()); } return true; diff --git a/src/core/smallvec_type.hpp b/src/core/smallvec_type.hpp index 77b03ca6b7..6e726f556d 100644 --- a/src/core/smallvec_type.hpp +++ b/src/core/smallvec_type.hpp @@ -99,6 +99,4 @@ public: } }; -typedef AutoFreeSmallVector StringList; ///< Type for a list of strings. - #endif /* SMALLVEC_TYPE_HPP */ diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index 26498338c1..944bf82d19 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -111,7 +111,7 @@ std::unique_ptr ReadRawLanguageStrings(const char *file) while (i > 0 && (buffer[i - 1] == '\r' || buffer[i - 1] == '\n' || buffer[i - 1] == ' ')) i--; buffer[i] = '\0'; - ret->lines.push_back(stredup(buffer, buffer + to_read - 1)); + ret->lines.emplace_back(buffer, buffer + to_read - 1); if (len > to_read) { to_read = 0; @@ -129,8 +129,8 @@ std::unique_ptr ReadRawLanguageStrings(const char *file) /** A reader that simply reads using fopen. */ struct StringListReader : StringReader { - const char * const *p; ///< The current location of the iteration. - const char * const *end; ///< The end of the iteration. + StringList::const_iterator p; ///< The current location of the iteration. + StringList::const_iterator end; ///< The end of the iteration. /** * Create the reader. @@ -140,7 +140,7 @@ struct StringListReader : StringReader { * @param translation Are we reading a translation? */ StringListReader(StringData &data, const LanguageStrings &strings, bool master, bool translation) : - StringReader(data, strings.language, master, translation), p(strings.lines.data()), end(p + strings.lines.size()) + StringReader(data, strings.language, master, translation), p(strings.lines.begin()), end(strings.lines.end()) { } @@ -148,7 +148,7 @@ struct StringListReader : StringReader { { if (this->p == this->end) return NULL; - strecpy(buffer, *this->p, last); + strecpy(buffer, this->p->c_str(), last); this->p++; return buffer; @@ -157,13 +157,13 @@ struct StringListReader : StringReader { /** Class for writing an encoded language. */ struct TranslationWriter : LanguageWriter { - StringList *strings; ///< The encoded strings. + StringList &strings; ///< The encoded strings. /** * Writer for the encoded data. * @param strings The string table to add the strings to. */ - TranslationWriter(StringList *strings) : strings(strings) + TranslationWriter(StringList &strings) : strings(strings) { } @@ -184,28 +184,25 @@ struct TranslationWriter : LanguageWriter { void Write(const byte *buffer, size_t length) { - char *dest = MallocT(length + 1); - memcpy(dest, buffer, length); - dest[length] = '\0'; - this->strings->push_back(dest); + this->strings.emplace_back((const char *)buffer, length); } }; /** Class for writing the string IDs. */ struct StringNameWriter : HeaderWriter { - StringList *strings; ///< The string names. + StringList &strings; ///< The string names. /** * Writer for the string names. * @param strings The string table to add the strings to. */ - StringNameWriter(StringList *strings) : strings(strings) + StringNameWriter(StringList &strings) : strings(strings) { } void WriteStringID(const char *name, int stringid) { - if (stringid == (int)this->strings->size()) this->strings->push_back(stredup(name)); + if (stringid == (int)this->strings.size()) this->strings.emplace_back(name); } void Finalise(const StringData &data) @@ -314,7 +311,7 @@ void GameStrings::Compile() this->version = data.Version(); - StringNameWriter id_writer(&this->string_names); + StringNameWriter id_writer(this->string_names); id_writer.WriteHeader(data); for (const auto &p : this->raw_strings) { @@ -324,7 +321,7 @@ void GameStrings::Compile() if (_errors != 0) throw std::exception(); this->compiled_strings.emplace_back(new LanguageStrings(p->language)); - TranslationWriter writer(&this->compiled_strings.back()->lines); + TranslationWriter writer(this->compiled_strings.back()->lines); writer.WriteLang(data); } } @@ -340,7 +337,7 @@ GameStrings *_current_data = NULL; const char *GetGameStringPtr(uint id) { if (id >= _current_data->cur_language->lines.size()) return GetStringPtr(STR_UNDEFINED); - return _current_data->cur_language->lines[id]; + return _current_data->cur_language->lines[id].c_str(); } /** @@ -359,8 +356,8 @@ void RegisterGameTranslation(Squirrel *engine) if (SQ_FAILED(sq_get(vm, -2))) return; int idx = 0; - for (const char * const p : _current_data->string_names) { - sq_pushstring(vm, p, -1); + for (const auto &p : _current_data->string_names) { + sq_pushstring(vm, p.c_str(), -1); sq_pushinteger(vm, idx); sq_rawset(vm, -3); idx++; diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 9522297768..11b5d753f3 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -156,7 +156,7 @@ bool NetworkAddress::IsFamily(int family) * @note netmask without /n assumes all bits need to match. * @return true if this IP is within the netmask. */ -bool NetworkAddress::IsInNetmask(char *netmask) +bool NetworkAddress::IsInNetmask(const char *netmask) { /* Resolve it if we didn't do it already */ if (!this->IsResolved()) this->GetAddress(); @@ -166,17 +166,16 @@ bool NetworkAddress::IsInNetmask(char *netmask) NetworkAddress mask_address; /* Check for CIDR separator */ - char *chr_cidr = strchr(netmask, '/'); + const char *chr_cidr = strchr(netmask, '/'); if (chr_cidr != NULL) { int tmp_cidr = atoi(chr_cidr + 1); /* Invalid CIDR, treat as single host */ if (tmp_cidr > 0 || tmp_cidr < cidr) cidr = tmp_cidr; - /* Remove and then replace the / so that NetworkAddress works on the IP portion */ - *chr_cidr = '\0'; - mask_address = NetworkAddress(netmask, 0, this->address.ss_family); - *chr_cidr = '/'; + /* Remove the / so that NetworkAddress works on the IP portion */ + std::string ip_str(netmask, chr_cidr - netmask); + mask_address = NetworkAddress(ip_str.c_str(), 0, this->address.ss_family); } else { mask_address = NetworkAddress(netmask, 0, this->address.ss_family); } diff --git a/src/network/core/address.h b/src/network/core/address.h index 2f26a3d00f..bd1bab6769 100644 --- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -129,7 +129,7 @@ public: } bool IsFamily(int family); - bool IsInNetmask(char *netmask); + bool IsInNetmask(const char *netmask); /** * Compare the address of this class with the address of another. diff --git a/src/network/core/tcp_listen.h b/src/network/core/tcp_listen.h index 744f8841fd..5668e48b29 100644 --- a/src/network/core/tcp_listen.h +++ b/src/network/core/tcp_listen.h @@ -54,13 +54,13 @@ public: /* Check if the client is banned */ bool banned = false; - for (char *entry : _network_ban_list) { - banned = address.IsInNetmask(entry); + for (const auto &entry : _network_ban_list) { + banned = address.IsInNetmask(entry.c_str()); if (banned) { Packet p(Tban_packet); p.PrepareToSend(); - DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry); + DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str()); if (send(s, (const char*)p.buffer, p.size, 0) < 0) { DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR()); diff --git a/src/network/network.cpp b/src/network/network.cpp index be92623e41..ab3884c56e 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -632,8 +632,8 @@ void NetworkAddServer(const char *b) */ void GetBindAddresses(NetworkAddressList *addresses, uint16 port) { - for (char *iter : _network_bind_list) { - addresses->emplace_back(iter, port); + for (const auto &iter : _network_bind_list) { + addresses->emplace_back(iter.c_str(), port); } /* No address, so bind to everything. */ @@ -647,10 +647,10 @@ void GetBindAddresses(NetworkAddressList *addresses, uint16 port) * by the function that generates the config file. */ void NetworkRebuildHostList() { - _network_host_list.Clear(); + _network_host_list.clear(); for (NetworkGameList *item = _network_game_list; item != NULL; item = item->next) { - if (item->manually) _network_host_list.push_back(stredup(item->address.GetAddressAsString(false))); + if (item->manually) _network_host_list.emplace_back(item->address.GetAddressAsString(false)); } } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 0fd707676b..fc5822641d 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1045,8 +1045,8 @@ void ShowNetworkGameWindow() if (first) { first = false; /* Add all servers from the config file to our list. */ - for (char *iter : _network_host_list) { - NetworkAddServer(iter); + for (const auto &iter : _network_host_list) { + NetworkAddServer(iter.c_str()); } } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 97da64bd3b..8022f5ede5 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -2083,13 +2083,13 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban) /* Add address to ban-list */ if (ban) { bool contains = false; - for (char *iter : _network_ban_list) { - if (strcmp(iter, ip) == 0) { + for (const auto &iter : _network_ban_list) { + if (iter == ip) { contains = true; break; } } - if (!contains) _network_ban_list.push_back(stredup(ip)); + if (!contains) _network_ban_list.emplace_back(ip); } uint n = 0; @@ -2098,7 +2098,7 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban) NetworkClientSocket *cs; FOR_ALL_CLIENT_SOCKETS(cs) { if (cs->client_id == CLIENT_ID_SERVER) continue; - if (cs->client_address.IsInNetmask(const_cast(ip))) { + if (cs->client_address.IsInNetmask(ip)) { NetworkServerKickClient(cs->client_id); n++; } diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 520882667d..e2a76319cc 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -565,8 +565,6 @@ void ShowNewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) new NewGRFTextfileWindow(file_type, c); } -static GRFPresetList _grf_preset_list; ///< List of known NewGRF presets. @see GetGRFPresetList - typedef std::map GrfIdMap; ///< Map of grfid to the grf config. /** @@ -605,6 +603,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { StringFilter string_filter; ///< Filter for available grf. QueryString filter_editbox; ///< Filter editbox; + StringList grf_presets; ///< List of known NewGRF presets. + GRFConfig *actives; ///< Temporary active grf list to which changes are made. GRFConfig *active_sel; ///< Selected active grf item. @@ -632,7 +632,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->active_over = -1; CopyGRFConfigList(&this->actives, *orig_list, false); - GetGRFPresetList(&_grf_preset_list); + this->grf_presets = GetGRFPresetList(); this->CreateNestedTree(); this->vscroll = this->GetScrollbar(WID_NS_SCROLLBAR); @@ -673,7 +673,6 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { /* Remove the temporary copy of grf-list used in window */ ClearGRFConfigList(&this->actives); - _grf_preset_list.Clear(); } /** @@ -747,11 +746,9 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { case WID_NS_PRESET_LIST: { Dimension d = GetStringBoundingBox(STR_NUM_CUSTOM); - for (uint i = 0; i < _grf_preset_list.size(); i++) { - if (_grf_preset_list[i] != NULL) { - SetDParamStr(0, _grf_preset_list[i]); - d = maxdim(d, GetStringBoundingBox(STR_JUST_RAW_STRING)); - } + for (const auto &i : this->grf_presets) { + SetDParamStr(0, i.c_str()); + d = maxdim(d, GetStringBoundingBox(STR_JUST_RAW_STRING)); } d.width += padding.width; *size = maxdim(d, *size); @@ -783,7 +780,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { SetDParam(0, STR_NUM_CUSTOM); } else { SetDParam(0, STR_JUST_RAW_STRING); - SetDParamStr(1, _grf_preset_list[this->preset]); + SetDParamStr(1, this->grf_presets[this->preset].c_str()); } break; } @@ -929,10 +926,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { /* Add 'None' option for clearing list */ list.emplace_back(new DropDownListStringItem(STR_NONE, -1, false)); - for (uint i = 0; i < _grf_preset_list.size(); i++) { - if (_grf_preset_list[i] != NULL) { - list.emplace_back(new DropDownListCharStringItem(_grf_preset_list[i], i, false)); - } + for (uint i = 0; i < this->grf_presets.size(); i++) { + list.emplace_back(new DropDownListCharStringItem(this->grf_presets[i].c_str(), i, false)); } this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window @@ -949,14 +944,14 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { } case WID_NS_PRESET_SAVE: - ShowSavePresetWindow((this->preset == -1) ? NULL : _grf_preset_list[this->preset]); + ShowSavePresetWindow((this->preset == -1) ? NULL : this->grf_presets[this->preset].c_str()); break; case WID_NS_PRESET_DELETE: if (this->preset == -1) return; - DeleteGRFPresetFromConfig(_grf_preset_list[this->preset]); - GetGRFPresetList(&_grf_preset_list); + DeleteGRFPresetFromConfig(this->grf_presets[this->preset].c_str()); + this->grf_presets = GetGRFPresetList(); this->preset = -1; this->InvalidateData(); this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window @@ -1156,7 +1151,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->preset = index; if (index != -1) { - this->actives = LoadGRFPresetFromConfig(_grf_preset_list[index]); + this->actives = LoadGRFPresetFromConfig(this->grf_presets[index].c_str()); } this->avails.ForceRebuild(); @@ -1172,11 +1167,11 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { if (str == NULL) return; SaveGRFPresetToConfig(str, this->actives); - GetGRFPresetList(&_grf_preset_list); + this->grf_presets = GetGRFPresetList(); /* Switch to this preset */ - for (uint i = 0; i < _grf_preset_list.size(); i++) { - if (_grf_preset_list[i] != NULL && strcmp(_grf_preset_list[i], str) == 0) { + for (uint i = 0; i < this->grf_presets.size(); i++) { + if (this->grf_presets[i] == str) { this->preset = i; break; } @@ -2038,7 +2033,7 @@ static WindowDesc _save_preset_desc( /** Class for the save preset window. */ struct SavePresetWindow : public Window { QueryString presetname_editbox; ///< Edit box of the save preset. - GRFPresetList presets; ///< Available presets. + StringList presets; ///< Available presets. Scrollbar *vscroll; ///< Pointer to the scrollbar widget. int selected; ///< Selected entry in the preset list, or \c -1 if none selected. @@ -2048,11 +2043,11 @@ struct SavePresetWindow : public Window { */ SavePresetWindow(const char *initial_text) : Window(&_save_preset_desc), presetname_editbox(32) { - GetGRFPresetList(&this->presets); + this->presets = GetGRFPresetList(); this->selected = -1; if (initial_text != NULL) { for (uint i = 0; i < this->presets.size(); i++) { - if (!strcmp(initial_text, this->presets[i])) { + if (this->presets[i] == initial_text) { this->selected = i; break; } @@ -2083,7 +2078,7 @@ struct SavePresetWindow : public Window { resize->height = FONT_HEIGHT_NORMAL + 2U; size->height = 0; for (uint i = 0; i < this->presets.size(); i++) { - Dimension d = GetStringBoundingBox(this->presets[i]); + Dimension d = GetStringBoundingBox(this->presets[i].c_str()); size->width = max(size->width, d.width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT); resize->height = max(resize->height, d.height); } @@ -2108,7 +2103,7 @@ struct SavePresetWindow : public Window { for (uint i = min_index; i < max_index; i++) { if ((int)i == this->selected) GfxFillRect(r.left + 1, y, r.right - 1, y + step_height - 2, PC_DARK_BLUE); - const char *text = this->presets[i]; + const char *text = this->presets[i].c_str(); DrawString(r.left + WD_FRAMERECT_LEFT, r.right, y + offset_y, text, ((int)i == this->selected) ? TC_WHITE : TC_SILVER); y += step_height; } @@ -2124,7 +2119,7 @@ struct SavePresetWindow : public Window { uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SVP_PRESET_LIST); if (row < this->presets.size()) { this->selected = row; - this->presetname_editbox.text.Assign(this->presets[row]); + this->presetname_editbox.text.Assign(this->presets[row].c_str()); this->SetWidgetDirty(WID_SVP_PRESET_LIST); this->SetWidgetDirty(WID_SVP_EDITBOX); } diff --git a/src/openttd.cpp b/src/openttd.cpp index 9fd672916e..d4ce37b062 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -445,8 +445,8 @@ struct AfterNewGRFScan : NewGRFScanCallback { if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed; if (dedicated_host != NULL) { - _network_bind_list.Clear(); - _network_bind_list.push_back(stredup(dedicated_host)); + _network_bind_list.clear(); + _network_bind_list.emplace_back(dedicated_host); } if (dedicated_port != 0) _settings_client.network.server_port = dedicated_port; diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index 626afb17e9..52e8ac5215 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -129,14 +129,14 @@ static const SaveLoad _game_language_string[] = { SLE_END() }; -static void SaveReal_GSTR(LanguageStrings *ls) +static void SaveReal_GSTR(const LanguageStrings *ls) { _game_saveload_string = ls->language; _game_saveload_strings = (uint)ls->lines.size(); SlObject(NULL, _game_language_header); - for (uint i = 0; i < _game_saveload_strings; i++) { - _game_saveload_string = ls->lines[i]; + for (const auto &i : ls->lines) { + _game_saveload_string = i.c_str(); SlObject(NULL, _game_language_string); } } @@ -153,7 +153,7 @@ static void Load_GSTR() std::unique_ptr ls(new LanguageStrings(_game_saveload_string != NULL ? _game_saveload_string : "")); for (uint i = 0; i < _game_saveload_strings; i++) { SlObject(NULL, _game_language_string); - ls->lines.push_back(stredup(_game_saveload_string != NULL ? _game_saveload_string : "")); + ls->lines.emplace_back(_game_saveload_string != NULL ? _game_saveload_string : ""); } _current_data->raw_strings.push_back(std::move(ls)); diff --git a/src/settings.cpp b/src/settings.cpp index 546b137a14..749050132d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -84,7 +84,7 @@ static ErrorList _settings_error_list; ///< Errors while loading minimal setting typedef void SettingDescProc(IniFile *ini, const SettingDesc *desc, const char *grpname, void *object); -typedef void SettingDescProcList(IniFile *ini, const char *grpname, StringList *list); +typedef void SettingDescProcList(IniFile *ini, const char *grpname, StringList &list); static bool IsSignedVarMemType(VarType vt); @@ -718,16 +718,16 @@ static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grp * @param grpname character string identifying the section-header of the ini file that will be parsed * @param list new list with entries of the given section */ -static void IniLoadSettingList(IniFile *ini, const char *grpname, StringList *list) +static void IniLoadSettingList(IniFile *ini, const char *grpname, StringList &list) { IniGroup *group = ini->GetGroup(grpname); - if (group == NULL || list == NULL) return; + if (group == NULL) return; - list->Clear(); + list.clear(); for (const IniItem *item = group->item; item != NULL; item = item->next) { - if (item->name != NULL) list->push_back(stredup(item->name)); + if (item->name != NULL) list.emplace_back(item->name); } } @@ -740,15 +740,15 @@ static void IniLoadSettingList(IniFile *ini, const char *grpname, StringList *li * @param list pointer to an string(pointer) array that will be used as the * source to be saved into the relevant ini section */ -static void IniSaveSettingList(IniFile *ini, const char *grpname, StringList *list) +static void IniSaveSettingList(IniFile *ini, const char *grpname, StringList &list) { IniGroup *group = ini->GetGroup(grpname); - if (group == NULL || list == NULL) return; + if (group == NULL) return; group->Clear(); - for (char *iter : *list) { - group->GetItem(iter, true)->SetValue(""); + for (const auto &iter : list) { + group->GetItem(iter.c_str(), true)->SetValue(""); } } @@ -1699,9 +1699,9 @@ static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc, SettingDescP proc(ini, _currency_settings,"currency", &_custom_currency); proc(ini, _company_settings, "company", &_settings_client.company); - proc_list(ini, "server_bind_addresses", &_network_bind_list); - proc_list(ini, "servers", &_network_host_list); - proc_list(ini, "bans", &_network_ban_list); + proc_list(ini, "server_bind_addresses", _network_bind_list); + proc_list(ini, "servers", _network_host_list); + proc_list(ini, "bans", _network_ban_list); } } @@ -1767,21 +1767,20 @@ void SaveToConfig() /** * Get the list of known NewGrf presets. - * @param[in,out] list Pointer to list for storing the preset names. + * @returns List of preset names. */ -void GetGRFPresetList(GRFPresetList *list) +StringList GetGRFPresetList() { - list->Clear(); + StringList list; - IniFile *ini = IniLoadConfig(); - IniGroup *group; - for (group = ini->group; group != NULL; group = group->next) { + std::unique_ptr ini(IniLoadConfig()); + for (IniGroup *group = ini->group; group != NULL; group = group->next) { if (strncmp(group->name, "preset-", 7) == 0) { - list->push_back(stredup(group->name + 7)); + list.emplace_back(group->name + 7); } } - delete ini; + return list; } /** diff --git a/src/settings_func.h b/src/settings_func.h index a16c31c207..e75fd2b332 100644 --- a/src/settings_func.h +++ b/src/settings_func.h @@ -14,6 +14,7 @@ #include "core/smallvec_type.hpp" #include "company_type.h" +#include "string_type.h" struct IniFile; @@ -28,11 +29,7 @@ void SaveToConfig(); void IniLoadWindowSettings(IniFile *ini, const char *grpname, void *desc); void IniSaveWindowSettings(IniFile *ini, const char *grpname, void *desc); -/* Functions to load and save NewGRF settings to a separate - * configuration file, used for presets. */ -typedef AutoFreeSmallVector GRFPresetList; - -void GetGRFPresetList(GRFPresetList *list); +StringList GetGRFPresetList(); struct GRFConfig *LoadGRFPresetFromConfig(const char *config_name); void SaveGRFPresetToConfig(const char *config_name, struct GRFConfig *config); void DeleteGRFPresetFromConfig(const char *config_name); diff --git a/src/string_type.h b/src/string_type.h index 94d4304dfe..b4e8237c41 100644 --- a/src/string_type.h +++ b/src/string_type.h @@ -13,6 +13,8 @@ #define STRING_TYPE_H #include "core/enum_type.hpp" +#include +#include /** A non-breaking space. */ #define NBSP "\xC2\xA0" @@ -53,4 +55,8 @@ enum StringValidationSettings { }; DECLARE_ENUM_AS_BIT_SET(StringValidationSettings) + +/** Type for a list of strings. */ +typedef std::vector StringList; + #endif /* STRING_TYPE_H */ From 8b1880187a15173c11b9aeed69db3d8be2fd36b3 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 2 Apr 2019 21:31:41 +0200 Subject: [PATCH 10/13] Remove: AutoFreeSmallVector. The last use was for storing a list of memory blocks. As the way these lists are accessed is very specific, it is easier to just write an explicit destructor instead of trying to exactly match the behaviour. --- src/core/smallvec_type.hpp | 30 ------------------------------ src/network/network_client.cpp | 9 ++++++++- src/saveload/saveload.cpp | 13 ++++++++++--- 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/core/smallvec_type.hpp b/src/core/smallvec_type.hpp index 6e726f556d..11ceb3fa84 100644 --- a/src/core/smallvec_type.hpp +++ b/src/core/smallvec_type.hpp @@ -69,34 +69,4 @@ T* grow(std::vector& vec, std::size_t num) return vec.data() + pos; } -/** - * Simple vector template class, with automatic free. - * - * @note There are no asserts in the class so you have - * to care about that you grab an item which is - * inside the list. - * - * @param T The type of the items stored, must be a pointer - */ -template -class AutoFreeSmallVector : public std::vector { -public: - ~AutoFreeSmallVector() - { - this->Clear(); - } - - /** - * Remove all items from the list. - */ - inline void Clear() - { - for (T p : *this) { - free(p); - } - - std::vector::clear(); - } -}; - #endif /* SMALLVEC_TYPE_HPP */ diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 8c68b98f87..4dc5a80415 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -42,7 +42,7 @@ struct PacketReader : LoadFilter { static const size_t CHUNK = 32 * 1024; ///< 32 KiB chunks of memory. - AutoFreeSmallVector blocks; ///< Buffer with blocks of allocated memory. + std::vector blocks; ///< Buffer with blocks of allocated memory. byte *buf; ///< Buffer we're going to write to/read from. byte *bufe; ///< End of the buffer we write to/read from. byte **block; ///< The block we're reading from/writing to. @@ -54,6 +54,13 @@ struct PacketReader : LoadFilter { { } + ~PacketReader() override + { + for (auto p : this->blocks) { + free(p); + } + } + /** * Add a packet to this buffer. * @param p The packet to add. diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 721631fe68..f03e3d659f 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -126,15 +126,22 @@ struct ReadBuffer { /** Container for dumping the savegame (quickly) to memory. */ struct MemoryDumper { - AutoFreeSmallVector blocks; ///< Buffer with blocks of allocated memory. - byte *buf; ///< Buffer we're going to write to. - byte *bufe; ///< End of the buffer we write to. + std::vector blocks; ///< Buffer with blocks of allocated memory. + byte *buf; ///< Buffer we're going to write to. + byte *bufe; ///< End of the buffer we write to. /** Initialise our variables. */ MemoryDumper() : buf(NULL), bufe(NULL) { } + ~MemoryDumper() + { + for (auto p : this->blocks) { + free(p); + } + } + /** * Write a single byte into the dumper. * @param b The byte to write. From 01f957c51fcb294c4adb178fc6a1a123fe7c0d92 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 8 Apr 2019 07:57:42 +0100 Subject: [PATCH 11/13] Fix: Crash due to use of invalid iterator in ClientNetworkContentSocketHandler In particular this crash can be observed when using the bootstrap GUI to download the base graphics. In ClientNetworkContentSocketHandler::OnReceiveContentInfo ClientNetworkContentSocketHandler::callbacks is iterated, using an iterator cb->OnReceiveContentInfo() is called (cb is of type BootstrapAskForDownloadWindow) This calls new BootstrapContentDownloadStatusWindow() This inherits from BaseNetworkContentDownloadStatusWindow The constructor of which calls _network_content_client.AddCallback(this) This reallocates the std::vector which is being iterated in ClientNetworkContentSocketHandler::OnReceiveContentInfo This results in iter being invalid, and an assertion failure occurs shortly afterwards due to its use in the next iteration of cb->OnReceiveContentInfo() Adjust all locations where ClientNetworkContentSocketHandler::callbacks is iterated to avoid problematic behaviour --- src/network/network_content.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 19235c8c72..168ecd4297 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -1029,37 +1029,39 @@ void ClientNetworkContentSocketHandler::Clear() void ClientNetworkContentSocketHandler::OnConnect(bool success) { - for (auto iter = this->callbacks.begin(); iter != this->callbacks.end(); /* nothing */) { - ContentCallback *cb = *iter; + for (size_t i = 0; i < this->callbacks.size(); /* nothing */) { + ContentCallback *cb = this->callbacks[i]; + /* the callback may remove itself from this->callbacks */ cb->OnConnect(success); - if (iter != this->callbacks.end() && *iter == cb) iter++; + if (i != this->callbacks.size() && this->callbacks[i] == cb) i++; } } void ClientNetworkContentSocketHandler::OnDisconnect() { - for (auto iter = this->callbacks.begin(); iter != this->callbacks.end(); /* nothing */) { - ContentCallback *cb = *iter; + for (size_t i = 0; i < this->callbacks.size(); /* nothing */) { + ContentCallback *cb = this->callbacks[i]; cb->OnDisconnect(); - if (iter != this->callbacks.end() && *iter == cb) iter++; + if (i != this->callbacks.size() && this->callbacks[i] == cb) i++; } } void ClientNetworkContentSocketHandler::OnReceiveContentInfo(const ContentInfo *ci) { - for (auto iter = this->callbacks.begin(); iter != this->callbacks.end(); /* nothing */) { - ContentCallback *cb = *iter; + for (size_t i = 0; i < this->callbacks.size(); /* nothing */) { + ContentCallback *cb = this->callbacks[i]; + /* the callback may add items and/or remove itself from this->callbacks */ cb->OnReceiveContentInfo(ci); - if (iter != this->callbacks.end() && *iter == cb) iter++; + if (i != this->callbacks.size() && this->callbacks[i] == cb) i++; } } void ClientNetworkContentSocketHandler::OnDownloadProgress(const ContentInfo *ci, int bytes) { - for (auto iter = this->callbacks.begin(); iter != this->callbacks.end(); /* nothing */) { - ContentCallback *cb = *iter; + for (size_t i = 0; i < this->callbacks.size(); /* nothing */) { + ContentCallback *cb = this->callbacks[i]; cb->OnDownloadProgress(ci, bytes); - if (iter != this->callbacks.end() && *iter == cb) iter++; + if (i != this->callbacks.size() && this->callbacks[i] == cb) i++; } } @@ -1070,9 +1072,10 @@ void ClientNetworkContentSocketHandler::OnDownloadComplete(ContentID cid) ci->state = ContentInfo::ALREADY_HERE; } - for (auto iter = this->callbacks.begin(); iter != this->callbacks.end(); /* nothing */) { - ContentCallback *cb = *iter; + for (size_t i = 0; i < this->callbacks.size(); /* nothing */) { + ContentCallback *cb = this->callbacks[i]; + /* the callback may remove itself from this->callbacks */ cb->OnDownloadComplete(cid); - if (iter != this->callbacks.end() && *iter == cb) iter++; + if (i != this->callbacks.size() && this->callbacks[i] == cb) i++; } } From 87d588f22fc129b36fb42ec6fd7413b44cc8766c Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 10 Apr 2019 19:45:43 +0200 Subject: [PATCH 12/13] Update: Translations from eints luxembourgish: 17 changes by Phreeze spanish (mexican): 2 changes by njn --- src/lang/luxembourgish.txt | 24 +++++++++++++++++------- src/lang/spanish_MX.txt | 2 ++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index 1190cd30f3..30507953f4 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -1583,6 +1583,7 @@ STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :Verbueden STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :Erlaabt STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :Erlaabt, custom Stad-Layout STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Duerfwuerengeneratioun: {STRING} +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Wéivill Wuere produzéiert ginn, relativ zur Bevölkerung vum Duerf.{}Quadratesche Wuesstum: En duebel sou grousst Duerf, generéiert véier mol souvill Passagéier.{}Lineare Wuesstum: En duebel sou grousst Duerf, generéiert duebel souvill Passagéier. STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Linear STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :Bamplazéirung: {STRING} @@ -2713,13 +2714,16 @@ STR_FRAMERATE_CAPTION :{WHITE}Biller p STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} ({DECIMAL}x) STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Unzuel Gameticks déi pro Sekonn simuléiert ginn. STR_FRAMERATE_RATE_BLITTER :{BLACK}Grafikframerate: {STRING} +STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}Unzuel u Videobiller déi pro Sekonn gerendert ginn. STR_FRAMERATE_SPEED_FACTOR :{BLACK}Aktuelle Spillgeschw.-Faktor: {DECIMAL}x +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}Wéi séier d'Spill aktuell leeft, am Verglach mat der Geschw. vun der normaler Simulatioun. STR_FRAMERATE_CURRENT :{WHITE}Aktuell STR_FRAMERATE_AVERAGE :{WHITE}Mëttel STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL} ms STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL} ms STR_FRAMERATE_MS_BAD :{RED}{DECIMAL} ms STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL} Biller/s +STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL} Biller/s STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL} Biller/s STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} s ############ Leave those lines in this order!! @@ -2730,6 +2734,7 @@ STR_FRAMERATE_GL_LINKGRAPH :{BLACK} Linkgr STR_FRAMERATE_DRAWING :{BLACK}Grafikrendering: STR_FRAMERATE_DRAWING_VIEWPORTS :{BLACK} Welt-Usiichten: STR_FRAMERATE_VIDEO :{BLACK}Video-output: +STR_FRAMERATE_ALLSCRIPTS :{BLACK} GS/KI Total: STR_FRAMERATE_GAMESCRIPT :{BLACK} Gamescript: STR_FRAMERATE_AI :{BLACK} KI {NUM} {STRING} ############ End of leave-in-this-order @@ -2742,9 +2747,11 @@ STR_FRAMETIME_CAPTION_GL_SHIPS :Schëffticker STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Weltticks STR_FRAMETIME_CAPTION_DRAWING :Grafikrendering STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Weltusiicht-Rendering +STR_FRAMETIME_CAPTION_VIDEO :Video-output STR_FRAMETIME_CAPTION_SOUND :Soundmixing STR_FRAMETIME_CAPTION_ALLSCRIPTS :GS/KI Scripttotaler STR_FRAMETIME_CAPTION_GAMESCRIPT :Spill-Script +STR_FRAMETIME_CAPTION_AI :KI {NUM} {STRING} ############ End of leave-in-this-order @@ -2889,6 +2896,7 @@ STR_NEWGRF_SETTINGS_VERSION :{BLACK}Versioun STR_NEWGRF_SETTINGS_MIN_VERSION :{BLACK}Min. kompatibel Versioun: {SILVER}{NUM} STR_NEWGRF_SETTINGS_MD5SUM :{BLACK}MD5sum: {SILVER}{STRING} STR_NEWGRF_SETTINGS_PALETTE :{BLACK}Palette: {SILVER}{STRING} +STR_NEWGRF_SETTINGS_PALETTE_DEFAULT :Standard (S) STR_NEWGRF_SETTINGS_PALETTE_DEFAULT_32BPP :Standard (S) / 32 bpp STR_NEWGRF_SETTINGS_PALETTE_LEGACY :Legacy (W) STR_NEWGRF_SETTINGS_PARAMETER :{BLACK}Parameter: {SILVER}{STRING} @@ -3047,7 +3055,7 @@ STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Stad) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Awunner: {ORANGE}{COMMA}{BLACK} Haiser: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} leschte Mount: {ORANGE}{COMMA}{BLACK} Max: {ORANGE}{COMMA} -STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Gidder gebraucht fir Stadwuesstem: +STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Gidder gebraucht fir Stadwuesstum: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} gebraucht STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} gebraucht am Wanter STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED_GENERAL :{ORANGE}{STRING}{GREEN} geliwwert @@ -3475,15 +3483,17 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_BUTTON :{BLACK}Gefier k STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}Schëff kafen STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}Fliger kafen -STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Gefierer kafen an embauen -STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Gefierer kafen an embauen -STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Schëff kafen an embauen +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Gefierer kafen an ëmbauen +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Gefierer kafen an ëmbauen +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Schëff kafen an ëmbauen +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Fligeren kafen an ëmbauen STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}Keeft den ungewielten Zuch. Shift+Klick weist ongeféier Käschten ouni Kaf STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Keeft dat ugewielte Stroossegefier. Shift+Klick weist ongeféier Käschten ouni Kaf STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}Keeft dat ugewielte Schëff. Shift+Klick weist ongeféier Käschten ouni Kaf STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}Keeft den ungewielte Fliger. Shift+Klick weist ongeféier Käschten ouni Kaf +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Gewielte Fliger kafen an ëmbauen. Shift+Klick weist ongeféier Käschten ouni Kaf STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}Ëmbenennen STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}Ëmbenennen @@ -3841,7 +3851,7 @@ STR_ORDER_DROP_TRANSFER :Transferéieren STR_ORDER_DROP_NO_UNLOADING :Net entlueden STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Wiesselt d'Entluedverhale vun dem ungewielten Optrag -STR_ORDER_REFIT :{BLACK}Ëmbauen +STR_ORDER_REFIT :{BLACK}Embauen STR_ORDER_REFIT_TOOLTIP :{BLACK}Wielt an wéi een Luedungstyp sollt emgebaut ginn. Ctrl+Klick fir den Ëmbau ze läschen STR_ORDER_REFIT_AUTO :{BLACK}Embauen an der Statioun STR_ORDER_REFIT_AUTO_TOOLTIP :{BLACK}Wiel wellëch Wuerentypen sollen auto-ersat ginn an dësem Optrag. Ctrl+Klick fir all Auto-Erneierungen wechzehuelen. Auto-Erneiern geht just wann d'Gefier ët erlaabt @@ -3937,8 +3947,8 @@ STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :(Net entlueden STR_ORDER_NO_UNLOAD_NO_LOAD :(Keen Ent- an Belueden) STR_ORDER_AUTO_REFIT :(Embauen op {STRING}) -STR_ORDER_FULL_LOAD_REFIT :(Voll lueden mat Embauen op {STRING}) -STR_ORDER_FULL_LOAD_ANY_REFIT :(Voll lueden mat all Wueren mat Embauen op {STRING}) +STR_ORDER_FULL_LOAD_REFIT :(Voll lueden mat ëmbauen op {STRING}) +STR_ORDER_FULL_LOAD_ANY_REFIT :(Voll lueden mat all Wueren mat ëmbauen op {STRING}) STR_ORDER_UNLOAD_REFIT :(Entlueden an Wueren lueden mat Embauen op {STRING}) STR_ORDER_UNLOAD_FULL_LOAD_REFIT :(Entlueden an op voll Luedung waarden mat Embauen op {STRING}) STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT :(Entlueden an waard op iergendeng Volluedung mat Embauen op {STRING}) diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 04eb6c7fdb..ca0b6f0785 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -3436,6 +3436,7 @@ STR_GROUP_DEFAULT_ROAD_VEHICLES :Vehículos de c STR_GROUP_DEFAULT_SHIPS :Barcos sin agrupar STR_GROUP_DEFAULT_AIRCRAFTS :Aeronaves sin agrupar +STR_GROUP_COUNT_WITH_SUBGROUP :{TINY_FONT}{COMMA} (+{COMMA}) STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}Grupos: Clic en un grupo para ver los vehículos incluidos. Arrastrar y soltar para reorganizar los grupos. STR_GROUP_CREATE_TOOLTIP :{BLACK}Clic para crear un grupo @@ -4473,6 +4474,7 @@ STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}No se pu STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}No se puede eliminar grupo... STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}No se puede cambiar nombre del grupo... STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}No se puede establecer la jerarquía de grupos... +STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION :{WHITE}... los bucles en la jerarquía de grupos no están permitidos STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}No se pueden quitar todos los vehículos de este grupo... STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}No se puede añadir el vehículo a este grupo... STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}No se pueden añadir vehículos compartidos al grupo... From 3b4f224c0bc50e7248050d4bcbb6d83fd510c1cc Mon Sep 17 00:00:00 2001 From: glx22 Date: Wed, 10 Apr 2019 20:55:53 +0200 Subject: [PATCH 13/13] Fix #7494: std::sort() and qsort() use different comparators (#7495) --- src/widgets/dropdown.cpp | 4 ++-- src/widgets/dropdown_type.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index cb1382dd65..b123d7d946 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -51,12 +51,12 @@ void DropDownListStringItem::Draw(int left, int right, int top, int bottom, bool * @return true if \a first precedes \a second. * @warning All items in the list need to be derivates of DropDownListStringItem. */ -/* static */ int DropDownListStringItem::NatSortFunc(std::unique_ptr const &first, std::unique_ptr const &second) +/* static */ bool DropDownListStringItem::NatSortFunc(std::unique_ptr const &first, std::unique_ptr const &second) { char buffer1[512], buffer2[512]; GetString(buffer1, static_cast(first.get())->String(), lastof(buffer1)); GetString(buffer2, static_cast(second.get())->String(), lastof(buffer2)); - return strnatcmp(buffer1, buffer2); + return strnatcmp(buffer1, buffer2) < 0; } StringID DropDownListParamStringItem::String() const diff --git a/src/widgets/dropdown_type.h b/src/widgets/dropdown_type.h index 26c699f164..27c85cbe2a 100644 --- a/src/widgets/dropdown_type.h +++ b/src/widgets/dropdown_type.h @@ -49,7 +49,7 @@ public: void Draw(int left, int right, int top, int bottom, bool sel, Colours bg_colour) const override; virtual StringID String() const { return this->string; } - static int NatSortFunc(std::unique_ptr const &first, std::unique_ptr const &second); + static bool NatSortFunc(std::unique_ptr const &first, std::unique_ptr const &second); }; /**