mirror of https://github.com/OpenTTD/OpenTTD.git
Codechange: replace C-style strings with C++-style strings in textfile (#10772)
This commit is contained in:
parent
90529ea48b
commit
febe394806
|
@ -221,9 +221,14 @@ static void StrMakeValidInPlace(T &dst, const char *str, const char *last, Strin
|
|||
str += len;
|
||||
continue;
|
||||
}
|
||||
/* Replace the undesirable character with a question mark */
|
||||
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 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 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);
|
||||
|
||||
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 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 {
|
||||
SVS_NONE = 0, ///< Allow nothing and replace nothing.
|
||||
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.
|
||||
/**
|
||||
* 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)
|
||||
|
||||
|
|
|
@ -2103,9 +2103,13 @@ bool MissingGlyphSearcher::FindMissingGlyphs()
|
|||
}
|
||||
|
||||
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();
|
||||
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) {
|
||||
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]) {
|
||||
|
@ -2144,9 +2148,9 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
|
|||
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];
|
||||
|
||||
|
|
|
@ -261,9 +261,9 @@ public:
|
|||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
@ -70,11 +70,6 @@ TextfileWindow::TextfileWindow(TextfileType file_type) : Window(&_textfile_desc)
|
|||
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.
|
||||
* @return the height in pixels
|
||||
|
@ -199,9 +194,9 @@ void TextfileWindow::SetupScrollbars(bool force_reflow)
|
|||
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;
|
||||
}
|
||||
|
@ -344,48 +339,48 @@ static void Xunzip(byte **bufp, size_t *sizep)
|
|||
FILE *handle = FioFOpenFile(textfile, "rb", dir, &filesize);
|
||||
if (handle == nullptr) return;
|
||||
|
||||
this->text = ReallocT(this->text, filesize);
|
||||
size_t read = fread(this->text, 1, filesize, handle);
|
||||
char *buf = MallocT<char>(filesize);
|
||||
size_t read = fread(buf, 1, filesize, handle);
|
||||
fclose(handle);
|
||||
|
||||
if (read != filesize) return;
|
||||
if (read != filesize) {
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(WITH_ZLIB)
|
||||
/* In-place gunzip */
|
||||
if (StrEndsWith(textfile, ".gz")) Gunzip((byte**)&this->text, &filesize);
|
||||
if (StrEndsWith(textfile, ".gz")) Gunzip((byte**)&buf, &filesize);
|
||||
#endif
|
||||
|
||||
#if defined(WITH_LIBLZMA)
|
||||
/* In-place xunzip */
|
||||
if (StrEndsWith(textfile, ".xz")) Xunzip((byte**)&this->text, &filesize);
|
||||
if (StrEndsWith(textfile, ".xz")) Xunzip((byte**)&buf, &filesize);
|
||||
#endif
|
||||
|
||||
if (!this->text) return;
|
||||
if (buf == nullptr) return;
|
||||
|
||||
/* Add space for trailing \0 */
|
||||
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 = ' ';
|
||||
}
|
||||
std::string_view sv_buf(buf, filesize);
|
||||
|
||||
/* 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. */
|
||||
StrMakeValidInPlace(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
|
||||
/* Replace any invalid characters with a question-mark. This copies the buf in the process. */
|
||||
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. */
|
||||
std::string_view p(this->text);
|
||||
int row = 0;
|
||||
this->lines.emplace_back(row, p);
|
||||
for (; *p != '\0'; p++) {
|
||||
if (*p == '\n') {
|
||||
*p = '\0';
|
||||
this->lines.emplace_back(++row, p + 1);
|
||||
}
|
||||
auto next = p.find_first_of('\n');
|
||||
while (next != std::string_view::npos) {
|
||||
this->lines.emplace_back(row, p.substr(0, next));
|
||||
p.remove_prefix(next + 1);
|
||||
|
||||
row++;
|
||||
next = p.find_first_of('\n');
|
||||
}
|
||||
this->lines.emplace_back(row, p);
|
||||
|
||||
/* Calculate maximum text line length. */
|
||||
uint max_length = 0;
|
||||
|
|
|
@ -19,25 +19,14 @@ std::optional<std::string> GetTextfile(TextfileType type, Subdirectory dir, cons
|
|||
|
||||
/** Window for displaying a textfile */
|
||||
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.
|
||||
Scrollbar *vscroll; ///< Vertical 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 max_length; ///< Maximum length of unwrapped text line.
|
||||
|
||||
TextfileWindow(TextfileType file_type);
|
||||
~TextfileWindow();
|
||||
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override;
|
||||
void OnClick(Point pt, int widget, int click_count) override;
|
||||
|
@ -47,13 +36,24 @@ struct TextfileWindow : public Window, MissingGlyphSearcher {
|
|||
|
||||
void Reset() override;
|
||||
FontSize DefaultSize() override;
|
||||
const char *NextString() override;
|
||||
std::optional<std::string_view> NextString() override;
|
||||
bool Monospace() override;
|
||||
void SetFontNames(FontCacheSettings *settings, const char *font_name, const void *os_data) override;
|
||||
|
||||
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir);
|
||||
|
||||
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 GetContentHeight();
|
||||
void SetupScrollbars(bool force_reflow);
|
||||
|
|
Loading…
Reference in New Issue