From 2c6c6645f75e73bea63b518d9057b5d0e8b3b725 Mon Sep 17 00:00:00 2001 From: twanvl Date: Thu, 7 Aug 2008 01:01:51 +0000 Subject: [PATCH] Lower case keywords are now recognized, but only if all parameters are given. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1078 0fc631ac-6414-0410-93d0-97cfa31319b6 --- data/magic.mse-game/script | 11 ++-- data/magic.mse-game/set_fields | 1 + src/data/keyword.cpp | 106 ++++++++++++++++++++++++--------- src/data/keyword.hpp | 4 +- src/script/functions/basic.cpp | 18 ++++-- 5 files changed, 100 insertions(+), 40 deletions(-) diff --git a/data/magic.mse-game/script b/data/magic.mse-game/script index 4b972239..0faaa3fe 100644 --- a/data/magic.mse-game/script +++ b/data/magic.mse-game/script @@ -311,9 +311,7 @@ mana_context := | , # keyword argument that is declared as cost "; # truncates the name of legends -legend_filter := replace@(match:", [A-Z,a-z,Æ,0-9,' ]*", replace: "" )+ - replace@(match:" of [A-Z,a-z,Æ,0-9,' ]*", replace: "" )+ - replace@(match:" the [A-Z,a-z,Æ,0-9,' ]*", replace: "" ) +legend_filter := replace@(match:"(, | of | the ).*", replace: "" ) # the rule text filter # - adds mana symbols # - makes text in parentheses italic @@ -323,7 +321,12 @@ text_filter := remove_tag@(tag: "") + # step 2 : reminder text for keywords expand_keywords@( - default_expand: { chosen(choice:mode, set.automatic_reminder_text) }, + condition: { + correct_case or (mode != "pseudo" and not used_placeholders) + } + default_expand: { + chosen(choice:if correct_case then mode else "lower case", set.automatic_reminder_text) + }, combine: { if mode == "pseudo" then "{keyword}" else "{keyword} ({process_english_hints(reminder)})" } diff --git a/data/magic.mse-game/set_fields b/data/magic.mse-game/set_fields index 7adb4c5d..f022a223 100644 --- a/data/magic.mse-game/set_fields +++ b/data/magic.mse-game/set_fields @@ -50,6 +50,7 @@ set field: choice: pseudo choice: action choice: custom + choice: lower case initial: old, core, expert, pseudo, action, custom # Convert from older mse versions script: diff --git a/src/data/keyword.cpp b/src/data/keyword.cpp index db472608..1d69c51e 100644 --- a/src/data/keyword.cpp +++ b/src/data/keyword.cpp @@ -21,6 +21,8 @@ DECLARE_POINTER_TYPE(KeywordParamValue); class Value; DECLARE_DYNAMIC_ARG(Value*, value_being_updated); +#define USE_CASE_INSENSITIVE_KEYWORDS 1 + // ----------------------------------------------------------------------------- : Reflection KeywordParam::KeywordParam() @@ -215,7 +217,12 @@ void Keyword::prepare(const vector& param_types, bool force) { } regex += _("(") + regex_escape(text) + _(")"); regex = _("\\y") + regex + _("(?=$|[^a-zA-Z0-9\\(])"); // only match whole words - if (match_re.Compile(regex, wxRE_ADVANCED)) { + #if USE_CASE_INSENSITIVE_KEYWORDS + int flags = wxRE_ADVANCED | wxRE_ICASE; // case insensitive matching + #else + int flags = wxRE_ADVANCED + #endif + if (match_re.Compile(regex, flags)) { // not valid if it matches "", that would make MSE hang valid = !match_re.Matches(_("")); } else { @@ -262,6 +269,9 @@ KeywordTrie::~KeywordTrie() { } KeywordTrie* KeywordTrie::insert(Char c) { + #if USE_CASE_INSENSITIVE_KEYWORDS + c = toLower(c); // case insensitive matching + #endif KeywordTrie*& child = children[c]; if (!child) child = new KeywordTrie; return child; @@ -391,9 +401,9 @@ void dump(int i, KeywordTrie* t) { #endif String KeywordDatabase::expand(const String& text, + const ScriptValueP& match_condition, const ScriptValueP& expand_default, const ScriptValueP& combine_script, - bool case_sensitive, Context& ctx) const { assert(combine_script); @@ -451,6 +461,9 @@ String KeywordDatabase::expand(const String& text, } continue; } else { + #if USE_CASE_INSENSITIVE_KEYWORDS + c = toLower(c); // case insensitive matching + #endif ++i; } // find 'next' trie node set matching c @@ -478,12 +491,10 @@ String KeywordDatabase::expand(const String& text, if (used.insert(kw).second) { // we have found a possible match, for a keyword which we have not seen before if (tryExpand(*kw, i, tagged, untagged, result, expand_type, - expand_default, combine_script, case_sensitive, ctx, + match_condition, expand_default, combine_script, ctx, stat, stat_key)) { // it matches - used.clear(); - expand_type = _('a'); goto matched_keyword; } } @@ -506,9 +517,9 @@ bool KeywordDatabase::tryExpand(const Keyword& kw, String& untagged, String& result, char expand_type, + const ScriptValueP& match_condition, const ScriptValueP& expand_default, const ScriptValueP& combine_script, - bool case_sensitive, Context& ctx, KeywordUsageStatistics* stat, Value* stat_key) const @@ -523,9 +534,6 @@ bool KeywordDatabase::tryExpand(const Keyword& kw, end = untagged_to_index(tagged, start_u + len_u, true); if (start == end) return false; // don't match empty keywords - // copy text before keyword - result += remove_tag(tagged.substr(0, start), _(" text // j = 0 mod 2 -> parameter #((j-1)/2) == (j/2-1) - size_t start_u, len_u; - kw.match_re.GetMatch(&start_u, &len_u, j); - // note: start_u can be (uint)-1 when len_u == 0 - size_t part_end = len_u > 0 ? untagged_to_index(tagged, start_u + len_u, true) : start; - String part = tagged.substr(start, part_end - start); + size_t part_start_u, part_len_u; + kw.match_re.GetMatch(&part_start_u, &part_len_u, j); + // note: start_u can be (uint)-1 when part_len_u == 0 + size_t part_end = part_len_u > 0 ? untagged_to_index(tagged, part_start_u + part_len_u, true) : part_start; + String part = tagged.substr(part_start, part_end - part_start); // strip left over value = _("") + (kwp.placeholder.empty() ? kwp.name : kwp.placeholder) + _(""); script_part->value = part + script_param->value; // keep tags } else { @@ -613,11 +632,39 @@ bool KeywordDatabase::tryExpand(const Keyword& kw, } part = separator_before + script_part->toString() + separator_after; ctx.setVariable(String(_("param")) << (int)(j/2), script_param); + + } else if (correct_case) { + // Plain text, check if the case matches + for (size_t i = part_start_u ; i < part_start_u + part_len_u ; ++i, ++pos_in_match_string) { + if (pos_in_match_string > kw.match.size()) { + // outside match string, shouldn't happen, strings should be the same length + correct_case = false; + break; + } + Char actual_char = untagged.GetChar(i); + Char match_char = kw.match.GetChar(pos_in_match_string); + if (actual_char != match_char) { + correct_case = false; + break; + } + } + // we should have arrived at a param tag, skip it + if (pos_in_match_string < kw.match.size() && is_substr(kw.match, pos_in_match_string, _("eval(ctx) == false) { + return false; + } // Show reminder text? bool expand = expand_type == _('1'); @@ -627,6 +674,9 @@ bool KeywordDatabase::tryExpand(const Keyword& kw, expand_type = expand ? _('A') : _('a'); } + // Copy text before keyword + result += remove_tag(tagged.substr(0, start), _("keyword_db; if (db.empty()) { db.prepare_parameters(set->game->keyword_parameter_types, set->keywords); @@ -553,15 +555,19 @@ SCRIPT_RULE_2_N_DEP(expand_keywords, ScriptValueP, _("default expand"), default_ SCRIPT_OPTIONAL_PARAM_C_(CardP, card); WITH_DYNAMIC_ARG(keyword_usage_statistics, card ? &card->keyword_usage : nullptr); try { - SCRIPT_RETURN(db.expand(input, default_expand, combine, true, ctx)); + SCRIPT_RETURN(db.expand(input, match_condition, default_expand, combine, ctx)); } catch (const Error& e) { throw ScriptError(_ERROR_2_("in function", e.what(), _("expand_keywords"))); } } -SCRIPT_RULE_2_DEPENDENCIES(expand_keywords) { - default_expand->dependencies(ctx, dep); - combine ->dependencies(ctx, dep); +SCRIPT_FUNCTION_DEPENDENCIES(expand_keywords) { SCRIPT_PARAM_C(Set*, set); + SCRIPT_PARAM_N(ScriptValueP, _("condition"), match_condition); + SCRIPT_PARAM_N(ScriptValueP, _("default expand"), default_expand); + SCRIPT_PARAM_N(ScriptValueP, _("combine"), combine); + match_condition->dependencies(ctx,dep); + default_expand ->dependencies(ctx,dep); + combine ->dependencies(ctx,dep); set->game->dependent_scripts_keywords.add(dep); // this depends on the set's keywords return ctx.getVariable(SCRIPT_VAR_input); }