17 #define GETTEXT_DOMAIN "wesnoth-lib" 27 #define ERR_NG LOG_STREAM(err, log_engine) 28 #define WRN_NG LOG_STREAM(warn, log_engine) 30 static bool two_dots(
char a,
char b) {
return a ==
'.' && b ==
'.'; }
47 const auto itor = map_.find(key);
48 if (itor != map_.end())
55 for(
const auto&
p : map_) {
56 temp_->insert(
p.first,
p.second);
61 const std::map<std::string,T>&
map_;
62 mutable std::shared_ptr<config>
temp_;
68 std::string res = str;
71 int rfind_dollars_sign_from = res.size();
72 while(rfind_dollars_sign_from >= 0) {
75 const std::string::size_type var_begin_loc = res.rfind(
'$', rfind_dollars_sign_from);
78 if(var_begin_loc == std::string::npos) {
84 rfind_dollars_sign_from =
static_cast<int>(var_begin_loc) - 1;
93 if(var_name_begin == res.end()) {
96 }
else if(*var_name_begin ==
'(') {
98 int paren_nesting_level = 0;
99 bool in_string =
false,
104 if(!in_string && !in_comment) {
105 ++paren_nesting_level;
109 if(!in_string && !in_comment) {
110 --paren_nesting_level;
115 in_comment = !in_comment;
120 in_string = !in_string;
125 }
while(++var_end != res.end() && paren_nesting_level > 0);
127 WRN_NG <<
"Formula substitution ignored (and removed) because WFL engine is not present in the server.";
128 res.replace(var_begin, var_end,
"");
131 if(paren_nesting_level > 0) {
132 ERR_NG <<
"Formula in WML string cannot be evaluated due to " 133 <<
"a missing closing parenthesis:\n\t--> \"" 134 << std::string(var_begin, var_end) <<
"\"";
135 res.replace(var_begin, var_end,
"");
143 for(
int bracket_nesting_level = 0; var_end != res.end(); ++var_end) {
144 const char c = *var_end;
146 ++bracket_nesting_level;
149 if(--bracket_nesting_level < 0) {
154 else if (!(((c) & ~0x7f) == 0) || (!isalnum(c) && c !=
'.' && c !=
'_')) {
161 var_end = std::adjacent_find(var_name_begin, var_end,
two_dots);
163 const std::string::iterator default_start = var_end < res.end() && *var_end ==
'?' ? var_end + 1 : res.end();
170 if(*(var_end-1) ==
'.' 177 && *(var_end-2) !=
']') {
181 const std::string var_name(var_name_begin, var_end);
182 if(default_start == res.end()) {
183 if(var_end != res.end() && *var_end ==
'|') {
193 if (var_name.empty()) {
196 res.replace(var_begin, var_end,
"$");
200 res.replace(var_begin, var_end,
201 set.get_variable_const(var_name));
205 var_end = default_start;
206 while(var_end != res.end() && *var_end !=
'|') {
211 if(var_end == res.end()) {
212 res.replace(var_begin, default_start - 1, val);
214 else if(!val.
empty()) {
215 res.replace(var_begin, var_end + 1, val);
218 res.replace(var_begin, var_end + 1, std::string(default_start, default_end));
247 if(!tstr.
str().empty()) {
249 if(tstr.
str() != interp) {
257 switch(elems.size()) {
258 case 0:
return empty;
259 case 1:
return elems[0];
261 case 2:
return VGETTEXT(
"conjunct pair^$first and $second", {{
"first", elems[0]}, {
"second", elems[1]}});
264 std::string prefix =
VGETTEXT(
"conjunct start^$first, $second", {{
"first", elems[0]}, {
"second", elems[1]}});
266 for(std::size_t
i = 2;
i < elems.size() - 1;
i++) {
268 prefix =
VGETTEXT(
"conjunct mid^$prefix, $next", {{
"prefix", prefix}, {
"next", elems[
i]}});
271 return VGETTEXT(
"conjunct end^$prefix, and $last", {{
"prefix", prefix}, {
"last", elems.back()}});
275 switch(elems.size()) {
276 case 0:
return empty;
277 case 1:
return elems[0];
279 case 2:
return VGETTEXT(
"disjunct pair^$first or $second", {{
"first", elems[0]}, {
"second", elems[1]}});
282 std::string prefix =
VGETTEXT(
"disjunct start^$first, $second", {{
"first", elems[0]}, {
"second", elems[1]}});
284 for(std::size_t
i = 2;
i < elems.size() - 1;
i++) {
286 prefix =
VGETTEXT(
"disjunct mid^$prefix, $next", {{
"prefix", prefix}, {
"next", elems[
i]}});
289 return VGETTEXT(
"disjunct end^$prefix, or $last", {{
"prefix", prefix}, {
"last", elems.back()}});
295 return _(
"timespan^expired");
298 typedef std::tuple<std::time_t, const char*, const char*> time_factor;
309 time_factor{ 31104000,
N_n(
"timespan^$num year",
"timespan^$num years") },
310 time_factor{ 2592000,
N_n(
"timespan^$num month",
"timespan^$num months") },
311 time_factor{ 604800,
N_n(
"timespan^$num week",
"timespan^$num weeks") },
312 time_factor{ 86400,
N_n(
"timespan^$num day",
"timespan^$num days") },
313 time_factor{ 3600,
N_n(
"timespan^$num hour",
"timespan^$num hours") },
314 time_factor{ 60,
N_n(
"timespan^$num minute",
"timespan^$num minutes") },
315 time_factor{ 1,
N_n(
"timespan^$num second",
"timespan^$num seconds") },
318 std::vector<t_string> display_text;
322 const auto [ secs, fmt_singular, fmt_plural ] = factor;
323 const int amount = time / secs;
326 time -= secs * amount;
327 i18n[
"num"] = std::to_string(amount);
328 display_text.emplace_back(
VNGETTEXT(fmt_singular, fmt_plural, amount, i18n));
350 const char* singular,
362 int edit_distance = 0;
363 if(str_1.length() == 0) {
364 return str_2.length();
366 else if(str_2.length() == 0) {
367 return str_1.length();
371 int len_max = std::max(str_1.length(), str_2.length());
372 for(
int i = 0;
i < len_max;
i++) {
373 if(str_1[
i] != str_2[j]) {
375 if(str_1[
i+1] == str_2[j] && str_1[
i] == str_2[j+1]) {
380 else if(str_1[
i+1] == str_2[j]) {
384 else if(str_1[
i] == str_2[j+1]) {
389 if(edit_distance * 100 / std::min(str_1.length(), str_2.length()) > 33) {
396 return edit_distance;
bool empty() const
Tests for an attribute that either was never set or was set to "".
std::string format_conjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a conjunctive list.
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
std::map< std::string, t_string > string_map
Variant for storing WML attributes.
std::string dsngettext(const char *domainname, const char *singular, const char *plural, int n)
std::shared_ptr< config > temp_
std::string format_disjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a disjunctive list.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
static std::string _(const char *str)
Definitions for the interface to Wesnoth Markup Language (WML).
const std::map< std::string, T > & map_
std::string dsgettext(const char *domainname, const char *msgid)
variable_info< const variable_info_implementation::vi_policy_const > variable_access_const
Read-only access.
virtual config::attribute_value get_variable_const(const std::string &key) const
virtual variable_access_const get_variable_access_read(const std::string &varname) const
#define N_n(String1, String2)
string_map_variable_set(const std::map< std::string, T > &map)
std::string format_timespan(std::time_t time, bool detailed)
Formats a timespan into human-readable text for player authentication functions.
std::string(* evaluate_formula)(const std::string &formula)
Information on a WML variable.
Standard logging facilities (interface).
A config object defines a single node in a WML file, with access to child nodes.
const std::string & str() const
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::const_iterator iterator