mirror of https://github.com/OpenTTD/OpenTTD
Codechange: replace C-style strings with C++-style strings in textfile (#10772)
parent
90529ea48b
commit
febe394806
|
@ -221,9 +221,14 @@ static void StrMakeValidInPlace(T &dst, const char *str, const char *last, Strin
|
||||||
str += len;
|
str += len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Replace the undesirable character with a question mark */
|
|
||||||
str += len;
|
str += len;
|
||||||
if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) *dst++ = '?';
|
if ((settings & SVS_REPLACE_TAB_CR_NL_WITH_SPACE) != 0 && (c == '\r' || c == '\n' || c == '\t')) {
|
||||||
|
/* Replace the tab, carriage return or newline with a space. */
|
||||||
|
*dst++ = ' ';
|
||||||
|
} else if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) {
|
||||||
|
/* Replace the undesirable character with a question mark */
|
||||||
|
*dst++ = '?';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +268,7 @@ void StrMakeValidInPlace(char *str, StringValidationSettings settings)
|
||||||
* @param str The string to validate.
|
* @param str The string to validate.
|
||||||
* @param settings The settings for the string validation.
|
* @param settings The settings for the string validation.
|
||||||
*/
|
*/
|
||||||
std::string StrMakeValid(const std::string &str, StringValidationSettings settings)
|
std::string StrMakeValid(std::string_view str, StringValidationSettings settings)
|
||||||
{
|
{
|
||||||
auto buf = str.data();
|
auto buf = str.data();
|
||||||
auto last = buf + str.size();
|
auto last = buf + str.size();
|
||||||
|
|
|
@ -40,7 +40,7 @@ int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FO
|
||||||
std::string FormatArrayAsHex(span<const byte> data);
|
std::string FormatArrayAsHex(span<const byte> data);
|
||||||
|
|
||||||
void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2);
|
void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2);
|
||||||
[[nodiscard]] std::string StrMakeValid(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
|
[[nodiscard]] std::string StrMakeValid(std::string_view str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
|
||||||
void StrMakeValidInPlace(char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
|
void StrMakeValidInPlace(char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
|
||||||
|
|
||||||
void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2);
|
void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2);
|
||||||
|
|
|
@ -47,8 +47,14 @@ static const WChar CHAR_TD_PDF = 0x202C; ///< Restore the text-direction state t
|
||||||
enum StringValidationSettings {
|
enum StringValidationSettings {
|
||||||
SVS_NONE = 0, ///< Allow nothing and replace nothing.
|
SVS_NONE = 0, ///< Allow nothing and replace nothing.
|
||||||
SVS_REPLACE_WITH_QUESTION_MARK = 1 << 0, ///< Replace the unknown/bad bits with question marks.
|
SVS_REPLACE_WITH_QUESTION_MARK = 1 << 0, ///< Replace the unknown/bad bits with question marks.
|
||||||
SVS_ALLOW_NEWLINE = 1 << 1, ///< Allow newlines.
|
SVS_ALLOW_NEWLINE = 1 << 1, ///< Allow newlines; replaces '\r\n' with '\n' during processing.
|
||||||
SVS_ALLOW_CONTROL_CODE = 1 << 2, ///< Allow the special control codes.
|
SVS_ALLOW_CONTROL_CODE = 1 << 2, ///< Allow the special control codes.
|
||||||
|
/**
|
||||||
|
* Replace tabs ('\t'), carriage returns ('\r') and newlines ('\n') with spaces.
|
||||||
|
* When #SVS_ALLOW_NEWLINE is set, a '\n' or '\r\n' combination are not replaced with a space. A lone '\r' is replaced with a space.
|
||||||
|
* When #SVS_REPLACE_WITH_QUESTION_MARK is set, this replacement runs first.
|
||||||
|
*/
|
||||||
|
SVS_REPLACE_TAB_CR_NL_WITH_SPACE = 1 << 3,
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(StringValidationSettings)
|
DECLARE_ENUM_AS_BIT_SET(StringValidationSettings)
|
||||||
|
|
||||||
|
|
|
@ -2103,9 +2103,13 @@ bool MissingGlyphSearcher::FindMissingGlyphs()
|
||||||
}
|
}
|
||||||
|
|
||||||
this->Reset();
|
this->Reset();
|
||||||
for (const char *text = this->NextString(); text != nullptr; text = this->NextString()) {
|
for (auto text = this->NextString(); text.has_value(); text = this->NextString()) {
|
||||||
|
auto src = text->cbegin();
|
||||||
|
|
||||||
FontSize size = this->DefaultSize();
|
FontSize size = this->DefaultSize();
|
||||||
for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) {
|
while (src != text->cend()) {
|
||||||
|
WChar c = Utf8Consume(src);
|
||||||
|
|
||||||
if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
|
if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
|
||||||
size = (FontSize)(c - SCC_FIRST_FONT);
|
size = (FontSize)(c - SCC_FIRST_FONT);
|
||||||
} else if (!IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END) && IsPrintable(c) && !IsTextDirectionChar(c) && c != '?' && GetGlyph(size, c) == question_mark[size]) {
|
} else if (!IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END) && IsPrintable(c) && !IsTextDirectionChar(c) && c != '?' && GetGlyph(size, c) == question_mark[size]) {
|
||||||
|
@ -2144,9 +2148,9 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
|
||||||
return FS_NORMAL;
|
return FS_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *NextString() override
|
std::optional<std::string_view> NextString() override
|
||||||
{
|
{
|
||||||
if (this->i >= TEXT_TAB_END) return nullptr;
|
if (this->i >= TEXT_TAB_END) return std::nullopt;
|
||||||
|
|
||||||
const char *ret = _langpack.offsets[_langpack.langtab_start[this->i] + this->j];
|
const char *ret = _langpack.offsets[_langpack.langtab_start[this->i] + this->j];
|
||||||
|
|
||||||
|
|
|
@ -261,9 +261,9 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next string to search through.
|
* Get the next string to search through.
|
||||||
* @return The next string or nullptr if there is none.
|
* @return The next string or nullopt if there is none.
|
||||||
*/
|
*/
|
||||||
virtual const char *NextString() = 0;
|
virtual std::optional<std::string_view> NextString() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default (font) size of the string.
|
* Get the default (font) size of the string.
|
||||||
|
|
|
@ -70,11 +70,6 @@ TextfileWindow::TextfileWindow(TextfileType file_type) : Window(&_textfile_desc)
|
||||||
this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar
|
this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ TextfileWindow::~TextfileWindow()
|
|
||||||
{
|
|
||||||
free(this->text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total height of the content displayed in this window, if wrapping is disabled.
|
* Get the total height of the content displayed in this window, if wrapping is disabled.
|
||||||
* @return the height in pixels
|
* @return the height in pixels
|
||||||
|
@ -199,9 +194,9 @@ void TextfileWindow::SetupScrollbars(bool force_reflow)
|
||||||
return FS_MONO;
|
return FS_MONO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ const char *TextfileWindow::NextString()
|
/* virtual */ std::optional<std::string_view> TextfileWindow::NextString()
|
||||||
{
|
{
|
||||||
if (this->search_iterator >= this->lines.size()) return nullptr;
|
if (this->search_iterator >= this->lines.size()) return std::nullopt;
|
||||||
|
|
||||||
return this->lines[this->search_iterator++].text;
|
return this->lines[this->search_iterator++].text;
|
||||||
}
|
}
|
||||||
|
@ -344,48 +339,48 @@ static void Xunzip(byte **bufp, size_t *sizep)
|
||||||
FILE *handle = FioFOpenFile(textfile, "rb", dir, &filesize);
|
FILE *handle = FioFOpenFile(textfile, "rb", dir, &filesize);
|
||||||
if (handle == nullptr) return;
|
if (handle == nullptr) return;
|
||||||
|
|
||||||
this->text = ReallocT(this->text, filesize);
|
char *buf = MallocT<char>(filesize);
|
||||||
size_t read = fread(this->text, 1, filesize, handle);
|
size_t read = fread(buf, 1, filesize, handle);
|
||||||
fclose(handle);
|
fclose(handle);
|
||||||
|
|
||||||
if (read != filesize) return;
|
if (read != filesize) {
|
||||||
|
free(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(WITH_ZLIB)
|
#if defined(WITH_ZLIB)
|
||||||
/* In-place gunzip */
|
/* In-place gunzip */
|
||||||
if (StrEndsWith(textfile, ".gz")) Gunzip((byte**)&this->text, &filesize);
|
if (StrEndsWith(textfile, ".gz")) Gunzip((byte**)&buf, &filesize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WITH_LIBLZMA)
|
#if defined(WITH_LIBLZMA)
|
||||||
/* In-place xunzip */
|
/* In-place xunzip */
|
||||||
if (StrEndsWith(textfile, ".xz")) Xunzip((byte**)&this->text, &filesize);
|
if (StrEndsWith(textfile, ".xz")) Xunzip((byte**)&buf, &filesize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!this->text) return;
|
if (buf == nullptr) return;
|
||||||
|
|
||||||
/* Add space for trailing \0 */
|
std::string_view sv_buf(buf, filesize);
|
||||||
this->text = ReallocT(this->text, filesize + 1);
|
|
||||||
this->text[filesize] = '\0';
|
|
||||||
|
|
||||||
/* Replace tabs and line feeds with a space since StrMakeValidInPlace 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. */
|
/* Check for the byte-order-mark, and skip it if needed. */
|
||||||
char *p = this->text + (strncmp(u8"\ufeff", this->text, 3) == 0 ? 3 : 0);
|
if (StrStartsWith(sv_buf, u8"\ufeff")) sv_buf.remove_prefix(3);
|
||||||
|
|
||||||
/* Make sure the string is a valid UTF-8 sequence. */
|
/* Replace any invalid characters with a question-mark. This copies the buf in the process. */
|
||||||
StrMakeValidInPlace(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
|
this->text = StrMakeValid(sv_buf, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE | SVS_REPLACE_TAB_CR_NL_WITH_SPACE);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
/* Split the string on newlines. */
|
/* Split the string on newlines. */
|
||||||
|
std::string_view p(this->text);
|
||||||
int row = 0;
|
int row = 0;
|
||||||
this->lines.emplace_back(row, p);
|
auto next = p.find_first_of('\n');
|
||||||
for (; *p != '\0'; p++) {
|
while (next != std::string_view::npos) {
|
||||||
if (*p == '\n') {
|
this->lines.emplace_back(row, p.substr(0, next));
|
||||||
*p = '\0';
|
p.remove_prefix(next + 1);
|
||||||
this->lines.emplace_back(++row, p + 1);
|
|
||||||
}
|
row++;
|
||||||
|
next = p.find_first_of('\n');
|
||||||
}
|
}
|
||||||
|
this->lines.emplace_back(row, p);
|
||||||
|
|
||||||
/* Calculate maximum text line length. */
|
/* Calculate maximum text line length. */
|
||||||
uint max_length = 0;
|
uint max_length = 0;
|
||||||
|
|
|
@ -19,25 +19,14 @@ std::optional<std::string> GetTextfile(TextfileType type, Subdirectory dir, cons
|
||||||
|
|
||||||
/** Window for displaying a textfile */
|
/** Window for displaying a textfile */
|
||||||
struct TextfileWindow : public Window, MissingGlyphSearcher {
|
struct TextfileWindow : public Window, MissingGlyphSearcher {
|
||||||
struct Line {
|
|
||||||
int top; ///< Top scroll position.
|
|
||||||
int bottom; ///< Bottom scroll position.
|
|
||||||
const char *text; ///< Pointer to text buffer.
|
|
||||||
|
|
||||||
Line(int top, const char *text) : top(top), bottom(top + 1), text(text) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
TextfileType file_type; ///< Type of textfile to view.
|
TextfileType file_type; ///< Type of textfile to view.
|
||||||
Scrollbar *vscroll; ///< Vertical scrollbar.
|
Scrollbar *vscroll; ///< Vertical scrollbar.
|
||||||
Scrollbar *hscroll; ///< Horizontal scrollbar.
|
Scrollbar *hscroll; ///< Horizontal scrollbar.
|
||||||
char *text; ///< Lines of text from the NewGRF's textfile.
|
|
||||||
std::vector<Line> lines; ///< #text, split into lines in a table with lines.
|
|
||||||
uint search_iterator; ///< Iterator for the font check search.
|
uint search_iterator; ///< Iterator for the font check search.
|
||||||
|
|
||||||
uint max_length; ///< Maximum length of unwrapped text line.
|
uint max_length; ///< Maximum length of unwrapped text line.
|
||||||
|
|
||||||
TextfileWindow(TextfileType file_type);
|
TextfileWindow(TextfileType file_type);
|
||||||
~TextfileWindow();
|
|
||||||
|
|
||||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override;
|
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override;
|
||||||
void OnClick(Point pt, int widget, int click_count) override;
|
void OnClick(Point pt, int widget, int click_count) override;
|
||||||
|
@ -47,13 +36,24 @@ struct TextfileWindow : public Window, MissingGlyphSearcher {
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
FontSize DefaultSize() override;
|
FontSize DefaultSize() override;
|
||||||
const char *NextString() override;
|
std::optional<std::string_view> NextString() override;
|
||||||
bool Monospace() override;
|
bool Monospace() override;
|
||||||
void SetFontNames(FontCacheSettings *settings, const char *font_name, const void *os_data) override;
|
void SetFontNames(FontCacheSettings *settings, const char *font_name, const void *os_data) override;
|
||||||
|
|
||||||
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir);
|
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Line {
|
||||||
|
int top; ///< Top scroll position.
|
||||||
|
int bottom; ///< Bottom scroll position.
|
||||||
|
std::string_view text; ///< Pointer to text buffer.
|
||||||
|
|
||||||
|
Line(int top, std::string_view text) : top(top), bottom(top + 1), text(text) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string text; ///< Lines of text from the NewGRF's textfile.
|
||||||
|
std::vector<Line> lines; ///< #text, split into lines in a table with lines.
|
||||||
|
|
||||||
uint ReflowContent();
|
uint ReflowContent();
|
||||||
uint GetContentHeight();
|
uint GetContentHeight();
|
||||||
void SetupScrollbars(bool force_reflow);
|
void SetupScrollbars(bool force_reflow);
|
||||||
|
|
Loading…
Reference in New Issue