From e8dbcf90430610e2f19aeb3b764d9e8809c8f3ea Mon Sep 17 00:00:00 2001 From: rubidium Date: Sun, 12 Feb 2012 10:32:41 +0000 Subject: [PATCH] (svn r23932) -Codechange: split the NewGRF text window into its own source files --- projects/openttd_vs100.vcxproj | 3 + projects/openttd_vs100.vcxproj.filters | 9 + projects/openttd_vs80.vcproj | 12 + projects/openttd_vs90.vcproj | 12 + source.list | 3 + src/newgrf_config.h | 13 +- src/newgrf_gui.cpp | 216 ++---------------- src/script/api/game/game_window.hpp.sq | 10 +- src/script/api/script_window.hpp | 18 +- .../api/template/template_window.hpp.sq | 4 +- src/textfile_gui.cpp | 194 ++++++++++++++++ src/textfile_gui.h | 46 ++++ src/textfile_type.h | 27 +++ src/widgets/misc_widget.h | 8 + src/widgets/newgrf_widget.h | 9 +- src/window.cpp | 2 +- src/window_type.h | 4 +- 17 files changed, 353 insertions(+), 237 deletions(-) create mode 100644 src/textfile_gui.cpp create mode 100644 src/textfile_gui.h create mode 100644 src/textfile_type.h diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 88aa596ec5..be3eb0a0d3 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -573,6 +573,8 @@ + + @@ -684,6 +686,7 @@ + diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index 9fcc8c6ee8..7fc87d093f 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -948,6 +948,12 @@ Header Files + + Header Files + + + Header Files + Header Files @@ -1281,6 +1287,9 @@ GUI Source Code + + GUI Source Code + GUI Source Code diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index f508c877e1..fb895a43f5 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -1566,6 +1566,14 @@ RelativePath=".\..\src\texteff.hpp" > + + + + @@ -2018,6 +2026,10 @@ RelativePath=".\..\src\terraform_gui.cpp" > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index d08098d971..37dc590031 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -1563,6 +1563,14 @@ RelativePath=".\..\src\texteff.hpp" > + + + + @@ -2015,6 +2023,10 @@ RelativePath=".\..\src\terraform_gui.cpp" > + + diff --git a/source.list b/source.list index 3ae8f2a3b0..774df5d8a8 100644 --- a/source.list +++ b/source.list @@ -306,6 +306,8 @@ tar_type.h terraform_gui.h textbuf_gui.h texteff.hpp +textfile_gui.h +textfile_type.h tgp.h tile_cmd.h tile_type.h @@ -436,6 +438,7 @@ station_gui.cpp statusbar_gui.cpp subsidy_gui.cpp terraform_gui.cpp +textfile_gui.cpp timetable_gui.cpp toolbar_gui.cpp town_gui.cpp diff --git a/src/newgrf_config.h b/src/newgrf_config.h index 038b18f866..c950e698a3 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -17,6 +17,7 @@ #include "core/smallmap_type.hpp" #include "misc/countedptr.hpp" #include "fileio_type.h" +#include "textfile_type.h" /** GRF config bit flags */ enum GCF_Flags { @@ -145,18 +146,6 @@ struct GRFTextWrapper : public SimpleCountedObject { ~GRFTextWrapper(); }; -/** Additional text files accompanying NewGRFs */ -enum TextfileType { - TFT_BEGIN, - - TFT_README = TFT_BEGIN, ///< NewGRF readme - TFT_CHANGELOG, ///< NewGRF changelog - TFT_LICENSE, ///< NewGRF license - - TFT_END, -}; -DECLARE_POSTFIX_INCREMENT(TextfileType) - /** Information about GRF, used in the game and (part of it) in savegames */ struct GRFConfig : ZeroedMemoryAllocator { GRFConfig(const char *filename = NULL); diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index f39b308170..42dc03b40f 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -25,10 +25,10 @@ #include "querystring_gui.h" #include "core/geometry_func.hpp" #include "newgrf_text.h" -#include "fileio_func.h" -#include "fontcache.h" +#include "textfile_gui.h" #include "widgets/newgrf_widget.h" +#include "widgets/misc_widget.h" #include "table/sprites.h" @@ -465,207 +465,27 @@ static void OpenGRFParameterWindow(GRFConfig *c, bool editable) } /** Window for displaying the textfile of a NewGRF. */ -struct NewGRFTextfileWindow : public Window, MissingGlyphSearcher { - const GRFConfig *grf_config; ///< View the textfile of this GRFConfig. - TextfileType file_type; ///< Type of textfile to view. - int line_height; ///< Height of a line in the display widget. - Scrollbar *vscroll; ///< Vertical scrollbar. - Scrollbar *hscroll; ///< Horizontal scrollbar. - char *text; ///< Lines of text from the NewGRF's textfile. - SmallVector lines; ///< #text, split into lines in a table with lines. - uint max_length; ///< The longest line in the textfile (in pixels). +struct NewGRFTextfileWindow : public TextfileWindow { + const GRFConfig *grf_config; ///< View the textfile of this GRFConfig. - static const int TOP_SPACING = WD_FRAMETEXT_TOP; ///< Additional spacing at the top of the #WID_NT_BACKGROUND widget. - static const int BOTTOM_SPACING = WD_FRAMETEXT_BOTTOM; ///< Additional spacing at the bottom of the #WID_NT_BACKGROUND widget. - - NewGRFTextfileWindow(const WindowDesc *desc, const GRFConfig *c, TextfileType file_type) : Window(), grf_config(c), file_type(file_type) + NewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) : TextfileWindow(file_type), grf_config(c) { - this->CreateNestedTree(desc); - this->GetWidget(WID_NT_CAPTION)->SetDataTip(STR_NEWGRF_README_CAPTION + file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); - this->vscroll = this->GetScrollbar(WID_NT_VSCROLLBAR); - this->hscroll = this->GetScrollbar(WID_NT_HSCROLLBAR); - this->FinishInitNested(desc); + this->GetWidget(WID_TF_CAPTION)->SetDataTip(STR_NEWGRF_README_CAPTION + file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); - this->LoadTextfile(); - } - - ~NewGRFTextfileWindow() - { - free(this->text); - } - - virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) - { - switch (widget) { - case WID_NT_BACKGROUND: - this->line_height = FONT_HEIGHT_MONO + 2; - resize->height = this->line_height; - - size->height = 4 * resize->height + TOP_SPACING + BOTTOM_SPACING; // At least 4 lines are visible. - size->width = max(200u, size->width); // At least 200 pixels wide. - break; - } - } - - virtual void SetStringParameters(int widget) const - { - if (widget == WID_NT_CAPTION) SetDParamStr(0, this->grf_config->GetName()); - } - - virtual void DrawWidget(const Rect &r, int widget) const - { - if (widget != WID_NT_BACKGROUND) return; - - int width = r.right - r.left + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT; - int height = r.bottom - r.top + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT; - - DrawPixelInfo new_dpi; - if (!FillDrawPixelInfo(&new_dpi, r.left + WD_BEVEL_LEFT, r.top, width, height)) return; - DrawPixelInfo *old_dpi = _cur_dpi; - _cur_dpi = &new_dpi; - - int left, right; - if (_current_text_dir == TD_RTL) { - left = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - this->hscroll->GetCount(); - right = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - 1 + this->hscroll->GetPosition(); - } else { - left = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT - this->hscroll->GetPosition(); - right = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT + this->hscroll->GetCount() - 1; - } - int top = TOP_SPACING; - for (uint i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->lines.Length(); i++) { - DrawString(left, right, top + i * this->line_height, this->lines[i + this->vscroll->GetPosition()], TC_WHITE, SA_LEFT, false, FS_MONO); - } - - _cur_dpi = old_dpi; - } - - virtual void OnResize() - { - this->vscroll->SetCapacityFromWidget(this, WID_NT_BACKGROUND, TOP_SPACING + BOTTOM_SPACING); - this->hscroll->SetCapacityFromWidget(this, WID_NT_BACKGROUND); - } - -private: - uint search_iterator; ///< Iterator for the font check search. - - /* virtual */ void Reset() - { - this->search_iterator = 0; - } - - FontSize DefaultSize() - { - return FS_MONO; - } - - const char *NextString() - { - if (this->search_iterator >= this->lines.Length()) return NULL; - - return this->lines[this->search_iterator++]; - } - - /* virtual */ bool Monospace() - { - return true; - } - - /* virtual */ void SetFontNames(FreeTypeSettings *settings, const char *font_name) - { -#ifdef WITH_FREETYPE - strecpy(settings->mono_font, font_name, lastof(settings->mono_font)); -#endif /* WITH_FREETYPE */ - } - - /** - * Load the NewGRF's textfile text from file, and setup #lines, #max_length, and both scrollbars. - */ - void LoadTextfile() - { - this->lines.Clear(); - - /* Does GRF have a file of the demanded type? */ const char *textfile = this->grf_config->GetTextfile(file_type); - if (textfile == NULL) return; + this->LoadTextfile(textfile, NEWGRF_DIR); + } - /* Get text from file */ - size_t filesize; - FILE *handle = FioFOpenFile(textfile, "rb", NEWGRF_DIR, &filesize); - if (handle == NULL) return; - - this->text = ReallocT(this->text, filesize + 1); - size_t read = fread(this->text, 1, filesize, handle); - fclose(handle); - - if (read != filesize) return; - - this->text[filesize] = '\0'; - - /* Replace tabs and line feeds with a space since str_validate removes those. */ - for (char *p = this->text; *p != '\0'; p++) { - if (*p == '\t' || *p == '\r') *p = ' '; - } - - /* Check for the byte-order-mark, and skip it if needed. */ - char *p = this->text + (strncmp("\xEF\xBB\xBF", this->text, 3) == 0 ? 3 : 0); - - /* Make sure the string is a valid UTF-8 sequence. */ - str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); - - /* Split the string on newlines. */ - *this->lines.Append() = p; - for (; *p != '\0'; p++) { - if (*p == '\n') { - *p = '\0'; - *this->lines.Append() = p + 1; - } - } - - CheckForMissingGlyphs(true, this); - - /* Initialize scrollbars */ - this->vscroll->SetCount(this->lines.Length()); - - this->max_length = 0; - for (uint i = 0; i < this->lines.Length(); i++) { - this->max_length = max(this->max_length, GetStringBoundingBox(this->lines[i], FS_MONO).width); - } - this->hscroll->SetCount(this->max_length + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT); - this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar + /* virtual */ void SetStringParameters(int widget) const + { + if (widget == WID_TF_CAPTION) SetDParamStr(0, this->grf_config->GetName()); } }; -static const NWidgetPart _nested_newgrf_textfile_widgets[] = { - NWidget(NWID_HORIZONTAL), - NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), - NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_NT_CAPTION), SetDataTip(STR_NULL, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - EndContainer(), - NWidget(NWID_HORIZONTAL), - NWidget(WWT_PANEL, COLOUR_MAUVE, WID_NT_BACKGROUND), SetMinimalSize(200, 125), SetResize(1, 12), SetScrollbar(WID_NT_VSCROLLBAR), - EndContainer(), - NWidget(NWID_VERTICAL), - NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_NT_VSCROLLBAR), - EndContainer(), - EndContainer(), - NWidget(NWID_HORIZONTAL), - NWidget(NWID_HSCROLLBAR, COLOUR_MAUVE, WID_NT_HSCROLLBAR), - NWidget(WWT_RESIZEBOX, COLOUR_MAUVE), - EndContainer(), -}; - -/** Window definition for the grf textfile window */ -static const WindowDesc _newgrf_textfile_desc( - WDP_CENTER, 630, 460, - WC_NEWGRF_TEXTFILE, WC_NONE, - WDF_UNCLICK_BUTTONS, - _nested_newgrf_textfile_widgets, lengthof(_nested_newgrf_textfile_widgets) -); - -void ShowNewGRFTextfileWindow(const GRFConfig *c, TextfileType file_type) +void ShowNewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) { - DeleteWindowByClass(WC_NEWGRF_TEXTFILE); - new NewGRFTextfileWindow(&_newgrf_textfile_desc, c, file_type); + DeleteWindowByClass(WC_TEXTFILE); + new NewGRFTextfileWindow(file_type, c); } static GRFPresetList _grf_preset_list; @@ -756,7 +576,7 @@ struct NewGRFWindow : public QueryStringBaseWindow, NewGRFScanCallback { ~NewGRFWindow() { DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_NEWGRF_TEXTFILE); + DeleteWindowByClass(WC_TEXTFILE); if (this->editable && !this->execute) { CopyGRFConfigList(this->orig_list, this->actives, true); @@ -962,7 +782,7 @@ struct NewGRFWindow : public QueryStringBaseWindow, NewGRFScanCallback { if (widget >= WID_NS_NEWGRF_TEXTFILE && widget < WID_NS_NEWGRF_TEXTFILE + TFT_END) { if (this->active_sel == NULL && this->avail_sel == NULL) return; - ShowNewGRFTextfileWindow(this->active_sel != NULL ? this->active_sel : this->avail_sel, (TextfileType)(widget - WID_NS_NEWGRF_TEXTFILE)); + ShowNewGRFTextfileWindow((TextfileType)(widget - WID_NS_NEWGRF_TEXTFILE), this->active_sel != NULL ? this->active_sel : this->avail_sel); return; } @@ -1185,8 +1005,8 @@ struct NewGRFWindow : public QueryStringBaseWindow, NewGRFScanCallback { this->avail_sel = NULL; this->avail_pos = -1; this->avails.ForceRebuild(); - this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window - this->DeleteChildWindows(WC_NEWGRF_TEXTFILE); // Remove the view textfile window + this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window + this->DeleteChildWindows(WC_TEXTFILE); // Remove the view textfile window } virtual void OnDropdownSelect(int widget, int index) diff --git a/src/script/api/game/game_window.hpp.sq b/src/script/api/game/game_window.hpp.sq index 084a724712..e1c118adf0 100644 --- a/src/script/api/game/game_window.hpp.sq +++ b/src/script/api/game/game_window.hpp.sq @@ -59,7 +59,7 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WC_SET_DATE, "WC_SET_DATE"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_AI_SETTINGS, "WC_AI_SETTINGS"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_GRF_PARAMETERS, "WC_GRF_PARAMETERS"); - SQGSWindow.DefSQConst(engine, ScriptWindow::WC_NEWGRF_TEXTFILE, "WC_NEWGRF_TEXTFILE"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WC_TEXTFILE, "WC_TEXTFILE"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_TOWN_AUTHORITY, "WC_TOWN_AUTHORITY"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_VEHICLE_DETAILS, "WC_VEHICLE_DETAILS"); SQGSWindow.DefSQConst(engine, ScriptWindow::WC_VEHICLE_REFIT, "WC_VEHICLE_REFIT"); @@ -750,10 +750,6 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NP_RESET, "WID_NP_RESET"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NP_SHOW_DESCRIPTION, "WID_NP_SHOW_DESCRIPTION"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NP_DESCRIPTION, "WID_NP_DESCRIPTION"); - SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NT_CAPTION, "WID_NT_CAPTION"); - SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NT_BACKGROUND, "WID_NT_BACKGROUND"); - SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NT_VSCROLLBAR, "WID_NT_VSCROLLBAR"); - SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NT_HSCROLLBAR, "WID_NT_HSCROLLBAR"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NS_PRESET_LIST, "WID_NS_PRESET_LIST"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NS_PRESET_SAVE, "WID_NS_PRESET_SAVE"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NS_PRESET_DELETE, "WID_NS_PRESET_DELETE"); @@ -782,6 +778,10 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NS_SHOW_APPLY, "WID_NS_SHOW_APPLY"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SP_PROGRESS_BAR, "WID_SP_PROGRESS_BAR"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SP_PROGRESS_TEXT, "WID_SP_PROGRESS_TEXT"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_CAPTION, "WID_TF_CAPTION"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_BACKGROUND, "WID_TF_BACKGROUND"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_VSCROLLBAR, "WID_TF_VSCROLLBAR"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TF_HSCROLLBAR, "WID_TF_HSCROLLBAR"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_N_PANEL, "WID_N_PANEL"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_N_TITLE, "WID_N_TITLE"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_N_HEADLINE, "WID_N_HEADLINE"); diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp index 558a8f620e..0cda667db4 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -250,7 +250,7 @@ public: * textfile; Window numbers: * - 0 = #NewGRFTextfileWidgets */ - WC_NEWGRF_TEXTFILE = ::WC_NEWGRF_TEXTFILE, + WC_TEXTFILE = ::WC_TEXTFILE, /** @@ -1671,14 +1671,6 @@ public: WID_NP_DESCRIPTION = ::WID_NP_DESCRIPTION, ///< Multi-line description of a parameter. }; - /** Widgets of the #NewGRFTextfileWindow class. */ - enum NewGRFTextfileWidgets { - WID_NT_CAPTION = ::WID_NT_CAPTION, ///< The caption of the window. - WID_NT_BACKGROUND = ::WID_NT_BACKGROUND, ///< Panel to draw the textfile on. - WID_NT_VSCROLLBAR = ::WID_NT_VSCROLLBAR, ///< Vertical scrollbar to scroll through the textfile up-and-down. - WID_NT_HSCROLLBAR = ::WID_NT_HSCROLLBAR, ///< Horizontal scrollbar to scroll through the textfile left-to-right. - }; - /** Widgets of the #NewGRFWindow class. */ enum NewGRFStateWidgets { WID_NS_PRESET_LIST = ::WID_NS_PRESET_LIST, ///< Active NewGRF preset. @@ -1715,6 +1707,14 @@ public: WID_SP_PROGRESS_TEXT = ::WID_SP_PROGRESS_TEXT, ///< Text explaining what is happening. }; + /** Widgets of the #TextfileWindow class. */ + enum TextfileWidgets { + WID_TF_CAPTION = ::WID_TF_CAPTION, ///< The caption of the window. + WID_TF_BACKGROUND = ::WID_TF_BACKGROUND, ///< Panel to draw the textfile on. + WID_TF_VSCROLLBAR = ::WID_TF_VSCROLLBAR, ///< Vertical scrollbar to scroll through the textfile up-and-down. + WID_TF_HSCROLLBAR = ::WID_TF_HSCROLLBAR, ///< Horizontal scrollbar to scroll through the textfile left-to-right. + }; + /** Widgets of the #NewsWindow class. */ enum NewsWidgets { WID_N_PANEL = ::WID_N_PANEL, ///< Panel of the window. diff --git a/src/script/api/template/template_window.hpp.sq b/src/script/api/template/template_window.hpp.sq index 3cb9c1afba..a4b9333416 100644 --- a/src/script/api/template/template_window.hpp.sq +++ b/src/script/api/template/template_window.hpp.sq @@ -155,12 +155,12 @@ namespace SQConvert { template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::SpriteAlignerWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::NewGRFParametersWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewGRFParametersWidgets)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::NewGRFParametersWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } - template <> inline ScriptWindow::NewGRFTextfileWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewGRFTextfileWidgets)tmp; } - template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::NewGRFTextfileWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::NewGRFStateWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewGRFStateWidgets)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::NewGRFStateWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::ScanProgressWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::ScanProgressWidgets)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::ScanProgressWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline ScriptWindow::TextfileWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::TextfileWidgets)tmp; } + template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::TextfileWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::NewsWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::NewsWidgets)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptWindow::NewsWidgets res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptWindow::MessageHistoryWidgets GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptWindow::MessageHistoryWidgets)tmp; } diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp new file mode 100644 index 0000000000..93138eac37 --- /dev/null +++ b/src/textfile_gui.cpp @@ -0,0 +1,194 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file textfile_gui.cpp Implementation of textfile window. */ + +#include "stdafx.h" +#include "fileio_func.h" +#include "fontcache.h" +#include "gfx_type.h" +#include "gfx_func.h" +#include "string_func.h" +#include "textfile_gui.h" + +#include "widgets/misc_widget.h" + +#include "table/strings.h" + + +/** Widgets for the textfile window. */ +static const NWidgetPart _nested_textfile_widgets[] = { + NWidget(NWID_HORIZONTAL), + NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), + NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_TF_CAPTION), SetDataTip(STR_NULL, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + EndContainer(), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_PANEL, COLOUR_MAUVE, WID_TF_BACKGROUND), SetMinimalSize(200, 125), SetResize(1, 12), SetScrollbar(WID_TF_VSCROLLBAR), + EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_TF_VSCROLLBAR), + EndContainer(), + EndContainer(), + NWidget(NWID_HORIZONTAL), + NWidget(NWID_HSCROLLBAR, COLOUR_MAUVE, WID_TF_HSCROLLBAR), + NWidget(WWT_RESIZEBOX, COLOUR_MAUVE), + EndContainer(), +}; + +/** Window definition for the textfile window */ +static const WindowDesc _textfile_desc( + WDP_CENTER, 630, 460, + WC_TEXTFILE, WC_NONE, + WDF_UNCLICK_BUTTONS, + _nested_textfile_widgets, lengthof(_nested_textfile_widgets) +); + +TextfileWindow::TextfileWindow(TextfileType file_type) : Window(), file_type(file_type) +{ + this->CreateNestedTree(&_textfile_desc); + this->vscroll = this->GetScrollbar(WID_TF_VSCROLLBAR); + this->hscroll = this->GetScrollbar(WID_TF_HSCROLLBAR); + this->FinishInitNested(&_textfile_desc); +} + +/* virtual */ TextfileWindow::~TextfileWindow() +{ + free(this->text); +} + +/* virtual */ void TextfileWindow::UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) +{ + switch (widget) { + case WID_TF_BACKGROUND: + this->line_height = FONT_HEIGHT_MONO + 2; + resize->height = this->line_height; + + size->height = 4 * resize->height + TOP_SPACING + BOTTOM_SPACING; // At least 4 lines are visible. + size->width = max(200u, size->width); // At least 200 pixels wide. + break; + } +} + +/* virtual */ void TextfileWindow::DrawWidget(const Rect &r, int widget) const +{ + if (widget != WID_TF_BACKGROUND) return; + + int width = r.right - r.left + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT; + int height = r.bottom - r.top + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT; + + DrawPixelInfo new_dpi; + if (!FillDrawPixelInfo(&new_dpi, r.left + WD_BEVEL_LEFT, r.top, width, height)) return; + DrawPixelInfo *old_dpi = _cur_dpi; + _cur_dpi = &new_dpi; + + int left, right; + if (_current_text_dir == TD_RTL) { + left = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - this->hscroll->GetCount(); + right = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - 1 + this->hscroll->GetPosition(); + } else { + left = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT - this->hscroll->GetPosition(); + right = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT + this->hscroll->GetCount() - 1; + } + int top = TOP_SPACING; + for (uint i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->lines.Length(); i++) { + DrawString(left, right, top + i * this->line_height, this->lines[i + this->vscroll->GetPosition()], TC_WHITE, SA_LEFT, false, FS_MONO); + } + + _cur_dpi = old_dpi; +} + +/* virtual */ void TextfileWindow::OnResize() +{ + this->vscroll->SetCapacityFromWidget(this, WID_TF_BACKGROUND, TOP_SPACING + BOTTOM_SPACING); + this->hscroll->SetCapacityFromWidget(this, WID_TF_BACKGROUND); +} + +/* virtual */ void TextfileWindow::Reset() +{ + this->search_iterator = 0; +} + +/* virtual */ FontSize TextfileWindow::DefaultSize() +{ + return FS_MONO; +} + +/* virtual */ const char *TextfileWindow::NextString() +{ + if (this->search_iterator >= this->lines.Length()) return NULL; + + return this->lines[this->search_iterator++]; +} + +/* virtual */ bool TextfileWindow::Monospace() +{ + return true; +} + +/* virtual */ void TextfileWindow::SetFontNames(FreeTypeSettings *settings, const char *font_name) +{ +#ifdef WITH_FREETYPE + strecpy(settings->mono_font, font_name, lastof(settings->mono_font)); +#endif /* WITH_FREETYPE */ +} + +/** + * Loads the textfile text from file, and setup #lines, #max_length, and both scrollbars. + */ +/* virtual */ void TextfileWindow::LoadTextfile(const char *textfile, Subdirectory dir) +{ + if (textfile == NULL) return; + + this->lines.Clear(); + + /* Get text from file */ + size_t filesize; + FILE *handle = FioFOpenFile(textfile, "rb", dir, &filesize); + if (handle == NULL) return; + + this->text = ReallocT(this->text, filesize + 1); + size_t read = fread(this->text, 1, filesize, handle); + fclose(handle); + + if (read != filesize) return; + + this->text[filesize] = '\0'; + + /* Replace tabs and line feeds with a space since str_validate removes those. */ + for (char *p = this->text; *p != '\0'; p++) { + if (*p == '\t' || *p == '\r') *p = ' '; + } + + /* Check for the byte-order-mark, and skip it if needed. */ + char *p = this->text + (strncmp("\xEF\xBB\xBF", this->text, 3) == 0 ? 3 : 0); + + /* Make sure the string is a valid UTF-8 sequence. */ + str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); + + /* Split the string on newlines. */ + *this->lines.Append() = p; + for (; *p != '\0'; p++) { + if (*p == '\n') { + *p = '\0'; + *this->lines.Append() = p + 1; + } + } + + CheckForMissingGlyphs(true, this); + + /* Initialize scrollbars */ + this->vscroll->SetCount(this->lines.Length()); + + this->max_length = 0; + for (uint i = 0; i < this->lines.Length(); i++) { + this->max_length = max(this->max_length, GetStringBoundingBox(this->lines[i], FS_MONO).width); + } + this->hscroll->SetCount(this->max_length + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT); + this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar +} diff --git a/src/textfile_gui.h b/src/textfile_gui.h new file mode 100644 index 0000000000..56760505ce --- /dev/null +++ b/src/textfile_gui.h @@ -0,0 +1,46 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file textfile_gui.h GUI functions related to textfiles. */ + +#ifndef TEXTFILE_GUI_H +#define TEXTFILE_GUI_H + +#include "strings_func.h" +#include "textfile_type.h" +#include "window_gui.h" + +/** Window for displaying a textfile */ +struct TextfileWindow : public Window, MissingGlyphSearcher { + TextfileType file_type; ///< Type of textfile to view. + int line_height; ///< Height of a line in the display widget. + Scrollbar *vscroll; ///< Vertical scrollbar. + Scrollbar *hscroll; ///< Horizontal scrollbar. + char *text; ///< Lines of text from the NewGRF's textfile. + SmallVector lines; ///< #text, split into lines in a table with lines. + uint max_length; ///< The longest line in the textfile (in pixels). + uint search_iterator; ///< Iterator for the font check search. + + static const int TOP_SPACING = WD_FRAMETEXT_TOP; ///< Additional spacing at the top of the #WID_TF_BACKGROUND widget. + static const int BOTTOM_SPACING = WD_FRAMETEXT_BOTTOM; ///< Additional spacing at the bottom of the #WID_TF_BACKGROUND widget. + + TextfileWindow(TextfileType file_type); + virtual ~TextfileWindow(); + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize); + virtual void DrawWidget(const Rect &r, int widget) const; + virtual void OnResize(); + virtual void Reset(); + virtual FontSize DefaultSize(); + virtual const char *NextString(); + virtual bool Monospace(); + virtual void SetFontNames(FreeTypeSettings *settings, const char *font_name); + virtual void LoadTextfile(const char *textfile, Subdirectory dir); +}; + +#endif /* TEXTFILE_GUI_H */ diff --git a/src/textfile_type.h b/src/textfile_type.h new file mode 100644 index 0000000000..374b4641a3 --- /dev/null +++ b/src/textfile_type.h @@ -0,0 +1,27 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file textfile_type.h Types related to textfiles. */ + +#ifndef TEXTFILE_TYPE_H +#define TEXTFILE_TYPE_H + +/** Additional text files accompanying Tar archives */ +enum TextfileType { + TFT_BEGIN, + + TFT_README = TFT_BEGIN, ///< NewGRF readme + TFT_CHANGELOG, ///< NewGRF changelog + TFT_LICENSE, ///< NewGRF license + + TFT_END, +}; +DECLARE_POSTFIX_INCREMENT(TextfileType) + +#endif /* TEXTFILE_TYPE_H */ diff --git a/src/widgets/misc_widget.h b/src/widgets/misc_widget.h index 04f81da71d..a54e830352 100644 --- a/src/widgets/misc_widget.h +++ b/src/widgets/misc_widget.h @@ -45,4 +45,12 @@ enum QueryWidgets { WID_Q_YES, ///< No button. }; +/** Widgets of the #TextfileWindow class. */ +enum TextfileWidgets { + WID_TF_CAPTION, ///< The caption of the window. + WID_TF_BACKGROUND, ///< Panel to draw the textfile on. + WID_TF_VSCROLLBAR, ///< Vertical scrollbar to scroll through the textfile up-and-down. + WID_TF_HSCROLLBAR, ///< Horizontal scrollbar to scroll through the textfile left-to-right. +}; + #endif /* WIDGETS_MISC_WIDGET_H */ diff --git a/src/widgets/newgrf_widget.h b/src/widgets/newgrf_widget.h index 32b5c5a304..878dcb891e 100644 --- a/src/widgets/newgrf_widget.h +++ b/src/widgets/newgrf_widget.h @@ -13,6 +13,7 @@ #define WIDGETS_NEWGRF_WIDGET_H #include "../newgrf_config.h" +#include "../textfile_type.h" /** Widgets of the #NewGRFParametersWindow class. */ enum NewGRFParametersWidgets { @@ -29,14 +30,6 @@ enum NewGRFParametersWidgets { WID_NP_DESCRIPTION, ///< Multi-line description of a parameter. }; -/** Widgets of the #NewGRFTextfileWindow class. */ -enum NewGRFTextfileWidgets { - WID_NT_CAPTION, ///< The caption of the window. - WID_NT_BACKGROUND, ///< Panel to draw the textfile on. - WID_NT_VSCROLLBAR, ///< Vertical scrollbar to scroll through the textfile up-and-down. - WID_NT_HSCROLLBAR, ///< Horizontal scrollbar to scroll through the textfile left-to-right. -}; - /** Widgets of the #NewGRFWindow class. */ enum NewGRFStateWidgets { WID_NS_PRESET_LIST, ///< Active NewGRF preset. diff --git a/src/window.cpp b/src/window.cpp index 9da7fe8128..a1a2899252 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -999,9 +999,9 @@ static uint GetWindowZPriority(const Window *w) case WC_CUSTOM_CURRENCY: case WC_NETWORK_WINDOW: case WC_GRF_PARAMETERS: - case WC_NEWGRF_TEXTFILE: case WC_AI_LIST: case WC_AI_SETTINGS: + case WC_TEXTFILE: ++z_priority; case WC_CONSOLE: diff --git a/src/window_type.h b/src/window_type.h index e5a9f85039..e6643a818f 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -179,9 +179,9 @@ enum WindowClass { /** * textfile; %Window numbers: - * - 0 = #NewGRFTextfileWidgets + * - 0 = #TextfileWidgets */ - WC_NEWGRF_TEXTFILE, + WC_TEXTFILE, /**