diff --git a/data/magic.mse-game/game b/data/magic.mse-game/game index 0cfc08f7..95e1c04d 100644 --- a/data/magic.mse-game/game +++ b/data/magic.mse-game/game @@ -598,6 +598,12 @@ default set style: automatic reminder text: render style: checklist direction: vertical + sort special rarity: + render style: both + choice images: + with the rest: /magic.mse-game/icons/number_cards_mixed.png + after other cards: /magic.mse-game/icons/number_cards_after.png + separate numbering: /magic.mse-game/icons/number_cards_separate.png use gradient multicolor: render style: both choice images: diff --git a/data/magic.mse-game/icons/number_cards_after.png b/data/magic.mse-game/icons/number_cards_after.png new file mode 100644 index 00000000..180bc46e Binary files /dev/null and b/data/magic.mse-game/icons/number_cards_after.png differ diff --git a/data/magic.mse-game/icons/number_cards_mixed.png b/data/magic.mse-game/icons/number_cards_mixed.png new file mode 100644 index 00000000..6983cea8 Binary files /dev/null and b/data/magic.mse-game/icons/number_cards_mixed.png differ diff --git a/data/magic.mse-game/icons/number_cards_separate.png b/data/magic.mse-game/icons/number_cards_separate.png new file mode 100644 index 00000000..591285a6 Binary files /dev/null and b/data/magic.mse-game/icons/number_cards_separate.png differ diff --git a/doc/function/index.txt b/doc/function/index.txt index c4eef234..bf19258f 100644 --- a/doc/function/index.txt +++ b/doc/function/index.txt @@ -20,6 +20,7 @@ These functions are built into the program, other [[type:function]]s can be defi | [[fun:contains]] Does a string contain another one? | [[fun:match|match / match_rule]] Does a string match a regular expression? +| [[fun:regex_escape]] Escape a string for use in a regular expression. ! [[type:tagged_string|Tags]] <<< | [[fun:tag_contents|tag_contents / tag_contents_rule]] diff --git a/doc/type/style.txt b/doc/type/style.txt index 47ddff7f..ffdbc127 100644 --- a/doc/type/style.txt +++ b/doc/type/style.txt @@ -87,13 +87,16 @@ The rest of the properties depend on the type of [[type:field]] this style is fo | ^^^ @render style@ [[type:choice render style]] @"text"@ How should the field be rendered? | ^^^ @mask@ [[type:scriptable]] [[type:filename]] ''none'' A mask to apply to the image, black areas in the mask become transparent, similair to [[fun:set_mask]]. | ^^^ @combine@ [[type:combine]] @"normal"@ How to combine the image with the background? Can be overriden using the [[fun:set_combine]] function. -| ^^^ @alignment@ [[type:alignment]] Alignment of text and images in the box. +| ^^^ @alignment@ [[type:alignment]] @"stretch"@ Alignment of text and images in the box. | ^^^ @angle@ [[type:int]] @0@ Rotation of the text and images inside the box, in degrees. | ^^^ @font@ [[type:font]] Font to use for rendering text (depending on @render style@) | ^^^ @image@ [[type:image|scriptable image]] Image to show (depending on @render style@).
The script will be called with @input@ set to the value to determine an image for. | ^^^ @choice images@ [[type:map]] of [[type:image]]s An alternative way to specify what image to show.
For each [[type:choice]] a separate image is specified. +| ^^^ @content width@ [[type:double]] ''automatic'' When read from a script, gives the width of the current choice image in this box.
+ This is only useful when the alignment is changed, otherwise it is always equal the box size itself. +| ^^^ @content height@ [[type:double]] ''automatic'' When read from a script, gives the height of the current choice image in this box. | @"multiple choice"@ @direction@ [[type:direction]] @"left to right"@ Direction the items are layed out in, only when @render style@ is @list@. | ^^^ @spacing@ [[type:double]] @0@ Spacing between the items. diff --git a/src/data/keyword.cpp b/src/data/keyword.cpp index ca25a9e2..a86a28f6 100644 --- a/src/data/keyword.cpp +++ b/src/data/keyword.cpp @@ -157,55 +157,6 @@ size_t Keyword::findMode(const vector& modes) const { // ----------------------------------------------------------------------------- : Regex stuff -/// Make sure the given regex does no capturing -/** Basicly replaces "(" with "(?:" */ -String make_non_capturing(const String& re) { - String ret; - bool escape = false, bracket = false, capture = false; - FOR_EACH_CONST(c, re) { - if (capture && c != _('?')) { - // change this capture into a non-capturing "(" by appending "?:" - ret += _("?:"); - capture = false; - } - if (escape) { // second char of escape sequence - escape = false; - } else if (c == _('\\')) { // start of escape sequence - escape = true; - } else if (c == _('[')) { // start of [...] - bracket = true; - } else if (c == _(']')) { // end of [...] - bracket = false; - } else if (bracket && c == _('(')) { - // wx has a bug, it counts the '(' in "[(]" as a matching group - // escape it so wx doesn't see it - ret += _('\\'); - } else if (c == _('(')) { // start of capture? - capture = true; - } - ret += c; - } - return ret; -} - -/// Escape a single character for use in regular expressions -String regex_escape(Char c) { - if (c == _('(') || c == _(')') || c == _('[') || c == _(']') || c == _('{') || - c == _('.') || c == _('^') || c == _('$') || c == _('#') || c == _('\\') || - c == _('|') || c == _('+') || c == _('*') || c == _('?')) { - // c needs to be escaped - return _("\\") + String(1,c); - } else { - return String(1,c); - } -} -/// Escape a string for use in regular expressions -String regex_escape(const String& s) { - String ret; - FOR_EACH_CONST(c,s) ret += regex_escape(c); - return ret; -} - void Keyword::prepare(const vector& param_types, bool force) { if (!force && match_re.IsValid()) return; parameters.clear(); diff --git a/src/script/functions/basic.cpp b/src/script/functions/basic.cpp index eb6079d2..926e65c6 100644 --- a/src/script/functions/basic.cpp +++ b/src/script/functions/basic.cpp @@ -114,6 +114,11 @@ SCRIPT_FUNCTION(curly_quotes) { SCRIPT_RETURN(input); } +// regex escape a string +SCRIPT_FUNCTION(regex_escape) { + SCRIPT_PARAM(String, input); + SCRIPT_RETURN(regex_escape(input)); +} // ----------------------------------------------------------------------------- : Tagged string @@ -593,6 +598,7 @@ void init_script_basic_functions(Context& ctx) { ctx.setVariable(_("format"), script_format); ctx.setVariable(_("format rule"), script_format_rule); ctx.setVariable(_("curly quotes"), script_curly_quotes); + ctx.setVariable(_("regex_escape"), script_regex_escape); // tagged string ctx.setVariable(_("tag contents"), script_tag_contents); ctx.setVariable(_("remove tag"), script_tag_remove); @@ -608,7 +614,7 @@ void init_script_basic_functions(Context& ctx) { ctx.setVariable(_("expand keywords"), script_expand_keywords); ctx.setVariable(_("expand keywords rule"), script_expand_keywords_rule); ctx.setVariable(_("keyword usage"), script_keyword_usage); - // advanced string rules + // advanced string rules/functions ctx.setVariable(_("replace"), script_replace); ctx.setVariable(_("filter text"), script_filter_text); ctx.setVariable(_("match"), script_match); diff --git a/src/util/string.cpp b/src/util/string.cpp index 5ae4036a..38def722 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -384,4 +384,53 @@ String clean_filename(const String& name) { clean = _("no-name") + clean; } return clean; -} \ No newline at end of file +} + +// ----------------------------------------------------------------------------- : Regular expressions + +/// Escape a single character for use in regular expressions +String regex_escape(Char c) { + if (c == _('(') || c == _(')') || c == _('[') || c == _(']') || c == _('{') || + c == _('.') || c == _('^') || c == _('$') || c == _('#') || c == _('\\') || + c == _('|') || c == _('+') || c == _('*') || c == _('?')) { + // c needs to be escaped + return _("\\") + String(1,c); + } else { + return String(1,c); + } +} +/// Escape a string for use in regular expressions +String regex_escape(const String& s) { + String ret; + FOR_EACH_CONST(c,s) ret += regex_escape(c); + return ret; +} + +String make_non_capturing(const String& re) { + String ret; + bool escape = false, bracket = false, capture = false; + FOR_EACH_CONST(c, re) { + if (capture && c != _('?')) { + // change this capture into a non-capturing "(" by appending "?:" + ret += _("?:"); + capture = false; + } + if (escape) { // second char of escape sequence + escape = false; + } else if (c == _('\\')) { // start of escape sequence + escape = true; + } else if (c == _('[')) { // start of [...] + bracket = true; + } else if (c == _(']')) { // end of [...] + bracket = false; + } else if (bracket && c == _('(')) { + // wx has a bug, it counts the '(' in "[(]" as a matching group + // escape it so wx doesn't see it + ret += _('\\'); + } else if (c == _('(')) { // start of capture? + capture = true; + } + ret += c; + } + return ret; +} diff --git a/src/util/string.hpp b/src/util/string.hpp index 5b1c1f11..d6af3599 100644 --- a/src/util/string.hpp +++ b/src/util/string.hpp @@ -179,5 +179,16 @@ bool cannocial_name_compare(const String& a, const Char* b); /// Make sure a string is safe to use as a filename String clean_filename(const String& name); +// ----------------------------------------------------------------------------- : Regular expressions + +/// Escape a single character for use in regular expressions +String regex_escape(Char c); +/// Escape a string for use in regular expressions +String regex_escape(const String& s); + +/// Make sure the given regex does no capturing +/** Basicly replaces "(" with "(?:" */ +String make_non_capturing(const String& re); + // ----------------------------------------------------------------------------- : EOF #endif diff --git a/tools/website/drupal/mse-drupal-modules/highlight.inc b/tools/website/drupal/mse-drupal-modules/highlight.inc index 364c3130..dac6ea82 100644 --- a/tools/website/drupal/mse-drupal-modules/highlight.inc +++ b/tools/website/drupal/mse-drupal-modules/highlight.inc @@ -17,6 +17,7 @@ $built_in_functions = array( 'sort_text' =>'', 'sort_rule' => 'sort_text', 'contains' =>'', 'match' =>'', 'match_rule' => 'match', + 'regex_escape' =>'', // tags 'tag_contents' =>'', 'tag_contents_rule'=>'tag_contents', 'remove_tag' =>'', 'tag_remove_rule' =>'remove_tag',