17 #define GETTEXT_DOMAIN "wesnoth-lib"
31 #define ERR_NG LOG_STREAM(err, log_engine)
32 #define WRN_NG LOG_STREAM(warn, log_engine)
34 static bool two_dots(
char a,
char b) {
return a ==
'.' &&
b ==
'.'; }
51 const auto itor =
map_.find(key);
52 if (itor !=
map_.end())
59 for(
const auto&
p :
map_) {
60 temp_->insert(
p.first,
p.second);
65 const std::map<std::string,T>&
map_;
66 mutable std::shared_ptr<config>
temp_;
72 std::string res = str;
75 int rfind_dollars_sign_from = res.size();
76 while(rfind_dollars_sign_from >= 0) {
79 const std::string::size_type var_begin_loc = res.rfind(
'$', rfind_dollars_sign_from);
82 if(var_begin_loc == std::string::npos) {
88 rfind_dollars_sign_from =
static_cast<int>(var_begin_loc) - 1;
97 if(var_name_begin == res.end()) {
100 }
else if(*var_name_begin ==
'(') {
102 int paren_nesting_level = 0;
103 bool in_string =
false,
108 if(!in_string && !in_comment) {
109 ++paren_nesting_level;
113 if(!in_string && !in_comment) {
114 --paren_nesting_level;
119 in_comment = !in_comment;
124 in_string = !in_string;
129 }
while(++var_end != res.end() && paren_nesting_level > 0);
131 WRN_NG <<
"Formula substitution ignored (and removed) because WFL engine is not present in the server.";
132 res.replace(var_begin, var_end,
"");
135 if(paren_nesting_level > 0) {
136 ERR_NG <<
"Formula in WML string cannot be evaluated due to "
137 <<
"a missing closing parenthesis:\n\t--> \""
138 << std::string(var_begin, var_end) <<
"\"";
139 res.replace(var_begin, var_end,
"");
147 for(
int bracket_nesting_level = 0; var_end != res.end(); ++var_end) {
148 const char c = *var_end;
150 ++bracket_nesting_level;
153 if(--bracket_nesting_level < 0) {
158 else if (!(((
c) & ~0x7f) == 0) || (!isalnum(
c) &&
c !=
'.' &&
c !=
'_')) {
165 var_end = std::adjacent_find(var_name_begin, var_end,
two_dots);
167 const std::string::iterator default_start = var_end < res.end() && *var_end ==
'?' ? var_end + 1 : res.end();
174 if(*(var_end-1) ==
'.'
181 && *(var_end-2) !=
']') {
185 const std::string var_name(var_name_begin, var_end);
186 if(default_start == res.end()) {
187 if(var_end != res.end() && *var_end ==
'|') {
197 if (var_name.empty()) {
200 res.replace(var_begin, var_end,
"$");
204 res.replace(var_begin, var_end,
205 set.get_variable_const(var_name));
209 var_end = default_start;
210 while(var_end != res.end() && *var_end !=
'|') {
215 if(var_end == res.end()) {
216 res.replace(var_begin, default_start - 1, val);
218 else if(!val.
empty()) {
219 res.replace(var_begin, var_end + 1, val);
222 res.replace(var_begin, var_end + 1, std::string(default_start, default_end));
251 if(!tstr.
str().empty()) {
253 if(tstr.
str() != interp) {
261 switch(elems.size()) {
262 case 0:
return empty;
263 case 1:
return elems[0];
265 case 2:
return VGETTEXT(
"conjunct pair^$first and $second", {{
"first", elems[0]}, {
"second", elems[1]}});
268 std::string prefix =
VGETTEXT(
"conjunct start^$first, $second", {{
"first", elems[0]}, {
"second", elems[1]}});
270 for(std::size_t
i = 2;
i < elems.size() - 1;
i++) {
272 prefix =
VGETTEXT(
"conjunct mid^$prefix, $next", {{
"prefix", prefix}, {
"next", elems[
i]}});
275 return VGETTEXT(
"conjunct end^$prefix, and $last", {{
"prefix", prefix}, {
"last", elems.back()}});
279 switch(elems.size()) {
280 case 0:
return empty;
281 case 1:
return elems[0];
283 case 2:
return VGETTEXT(
"disjunct pair^$first or $second", {{
"first", elems[0]}, {
"second", elems[1]}});
286 std::string prefix =
VGETTEXT(
"disjunct start^$first, $second", {{
"first", elems[0]}, {
"second", elems[1]}});
288 for(std::size_t
i = 2;
i < elems.size() - 1;
i++) {
290 prefix =
VGETTEXT(
"disjunct mid^$prefix, $next", {{
"prefix", prefix}, {
"next", elems[
i]}});
293 return VGETTEXT(
"disjunct end^$prefix, or $last", {{
"prefix", prefix}, {
"last", elems.back()}});
299 return _(
"timespan^expired");
302 typedef std::tuple<std::time_t, const char*, const char*> time_factor;
304 static const std::vector<time_factor> TIME_FACTORS{
313 time_factor{ 31104000,
N_n(
"timespan^$num year",
"timespan^$num years") },
314 time_factor{ 2592000,
N_n(
"timespan^$num month",
"timespan^$num months") },
315 time_factor{ 604800,
N_n(
"timespan^$num week",
"timespan^$num weeks") },
316 time_factor{ 86400,
N_n(
"timespan^$num day",
"timespan^$num days") },
317 time_factor{ 3600,
N_n(
"timespan^$num hour",
"timespan^$num hours") },
318 time_factor{ 60,
N_n(
"timespan^$num minute",
"timespan^$num minutes") },
319 time_factor{ 1,
N_n(
"timespan^$num second",
"timespan^$num seconds") },
322 std::vector<t_string> display_text;
325 for(
const auto& factor : TIME_FACTORS) {
326 const auto [ secs, fmt_singular, fmt_plural ] = factor;
327 const int amount = time / secs;
330 time -= secs * amount;
331 i18n[
"num"] = std::to_string(amount);
332 display_text.emplace_back(
VNGETTEXT(fmt_singular, fmt_plural, amount, i18n));
354 const char* singular,
367 auto s1_first = str_1.begin();
368 auto s2_first = str_2.begin();
370 while(s1_first != str_1.end() && s2_first != str_2.end() && *s1_first == *s2_first) {
376 auto s1_size =
static_cast<std::size_t
>(str_1.end() - s1_first);
377 auto s2_size =
static_cast<std::size_t
>(str_2.end() - s2_first);
379 while(s1_size != 0 && s2_size != 0 && s1_first[s1_size - 1] == s2_first[s2_size - 1]) {
393 s1_size = std::min(s1_size, std::size_t{15});
394 s2_size = std::min(s2_size, std::size_t{15});
396 if(s1_size < s2_size) {
407 std::array<std::size_t, 16> row{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
409 for(std::size_t
i = 0;
i != s1_size; ++
i) {
413 for(std::size_t j = 0; j != s2_size; ++j) {
414 const auto up = row[j + 1];
415 const bool transposed =
i > 0 && j > 0 && s1_first[
i] == s2_first[j - 1] && s1_first[
i - 1] == s2_first[j];
417 if(s1_first[
i] != s2_first[j] && !transposed) {
418 row[j + 1] = std::min({up, row[j], upper_left}) + 1;
420 row[j + 1] = upper_left;
Variant for storing WML attributes.
bool empty() const
Tests for an attribute that either was never set or was set to "".
A config object defines a single node in a WML file, with access to child nodes.
const std::string & str() const
const std::map< std::string, T > & map_
virtual config::attribute_value get_variable_const(const std::string &key) const
string_map_variable_set(const std::map< std::string, T > &map)
std::shared_ptr< config > temp_
virtual variable_access_const get_variable_access_read(const std::string &varname) const
Information on a WML variable.
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
Definitions for the interface to Wesnoth Markup Language (WML).
#define N_n(String1, String2)
static std::string _(const char *str)
Standard logging facilities (interface).
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
std::string dsgettext(const char *domainname, const char *msgid)
std::string dsngettext(const char *domainname, const char *singular, const char *plural, int n)
std::string(* evaluate_formula)(const std::string &formula)
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
std::string format_timespan(std::time_t time, bool detailed)
Formats a timespan into human-readable text for player authentication functions.
t_string interpolate_variables_into_tstring(const t_string &tstr, const variable_set &variables)
Function that does the same as the above, for t_stringS.
std::string format_disjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a disjunctive list.
std::string format_conjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a conjunctive list.
std::map< std::string, t_string > string_map
std::string::const_iterator iterator
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
variable_info< const variable_info_implementation::vi_policy_const > variable_access_const
Read-only access.