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',