font: Cleanup link formatting logic

Let's internally handle this mess in terms of tokens instead of
delimiter positions.

This alters the code so we don't add and substract ones (1) all over the
place. It also simplifies the final std::string_view::substr() call so
we don't need to count the remainder's length at all.

And more importantly, this makes the case where no delimiters had been
previously found trivial instead of causing it to break and result in no
text being output at all. We also don't start with a size_t value of -1
(actually a very large unsigned value).

Closes #5625.
This commit is contained in:
Iris Morelle 2021-04-09 20:58:36 -04:00
parent a2c795bfd7
commit f23ef62282
2 changed files with 22 additions and 17 deletions

View file

@ -20,6 +20,7 @@
* Minor adjustments to the sidebar's minimap area in the default game theme to reclaim empty and uneven space back. Note that this WILL break custom WML themes that use the same sidebar graphics as the default theme.
* Minor adjustment to the placement of numerals on the debug clock.
* Players now receive an error message when attempting to save games using illegal file names (issue #5679).
* Fixed text labels containing only a single link becoming empty (issue #5625).
### WML Engine
### Miscellaneous and Bug Fixes
* Fixed units with max movement set to zero being given one max movement point by `[unstore_unit]` or when loading a saved game

View file

@ -816,27 +816,31 @@ std::string pango_text::format_links(std::string_view text) const
static const std::string delim = " \n\r\t";
std::ostringstream result;
std::size_t last_delim = -1;
for(std::size_t index = 0; index < text.size(); ++index) {
if(delim.find(text[index]) != std::string::npos) {
// Token starts from after the last delimiter up to (but not including) this delimiter
auto token = text.substr(last_delim + 1, index - last_delim - 1);
if(looks_like_url(token)) {
result << format_as_link(std::string(token), link_color_) << text[index];
} else {
result << token << text[index];
}
last_delim = index;
std::size_t tok_start = 0;
for(std::size_t pos = 0; pos < text.length(); ++pos) {
if(delim.find(text[pos]) == std::string::npos) {
continue;
}
if(const auto tok_length = pos - tok_start) {
// Token starts from after the last delimiter up to (but not including) this delimiter
auto token = text.substr(tok_start, tok_length);
if(looks_like_url(token)) {
result << format_as_link(std::string{token}, link_color_);
} else {
result << token;
}
}
result << text[pos];
tok_start = pos + 1;
}
if(last_delim < text.size() - 1) {
auto token = text.substr(last_delim + 1, text.size() - last_delim - 1);
// Deal with the remainder token
if(tok_start < text.length()) {
auto token = text.substr(tok_start);
if(looks_like_url(token)) {
result << format_as_link(std::string(token), link_color_);
result << format_as_link(std::string{token}, link_color_);
} else {
result << token;
}