mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
436c437189
add compiler directives
151 lines
5.5 KiB
C++
151 lines
5.5 KiB
C++
//+----------------------------------------------------------------------------+
|
|
//| Description: Magic Set Editor - Program to make card games |
|
|
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
//+----------------------------------------------------------------------------+
|
|
|
|
// ----------------------------------------------------------------------------- : Includes
|
|
|
|
#include <util/prec.hpp>
|
|
#include <script/functions/functions.hpp>
|
|
#include <script/functions/util.hpp>
|
|
#include <util/spell_checker.hpp>
|
|
#include <util/tagged_string.hpp>
|
|
#include <data/stylesheet.hpp>
|
|
|
|
// ----------------------------------------------------------------------------- : Functions
|
|
|
|
inline size_t spelled_correctly(const String& input, size_t start, size_t end, SpellChecker** checkers, const ScriptValueP& extra_test, Context& ctx) {
|
|
// untag
|
|
String word = untag(input.substr(start,end-start));
|
|
if (word.empty()) return true;
|
|
// run through spellchecker(s)
|
|
for (size_t i = 0 ; checkers[i] ; ++i) {
|
|
if (checkers[i]->spell(word)) {
|
|
return true;
|
|
}
|
|
}
|
|
// run through additional words regex
|
|
if (extra_test) {
|
|
// try on untagged
|
|
ctx.setVariable(SCRIPT_VAR_input, to_script(word));
|
|
if (extra_test->eval(ctx)->toBool()) {
|
|
return true;
|
|
}
|
|
// try on tagged
|
|
ctx.setVariable(SCRIPT_VAR_input, to_script(input.substr(start,end-start)));
|
|
if (extra_test->eval(ctx)->toBool()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void check_word(const String& tag, const String& input, size_t start, size_t end, String& out, bool check, SpellChecker** checkers, const ScriptValueP& extra_test, Context& ctx) {
|
|
if (start >= end) return;
|
|
bool good = !check || spelled_correctly(input, start, end, checkers, extra_test, ctx);
|
|
if (!good) { out += _("<"); out += tag; }
|
|
out.append(input, start, end-start);
|
|
if (!good) { out += _("</"); out += tag; }
|
|
}
|
|
|
|
bool isWordChar(wxUniChar c) {
|
|
return isAlpha(c) || c == '\'' || c == RIGHT_SINGLE_QUOTE;
|
|
}
|
|
|
|
SCRIPT_FUNCTION(check_spelling) {
|
|
SCRIPT_PARAM_C(StyleSheetP,stylesheet);
|
|
SCRIPT_PARAM_C(String,language);
|
|
SCRIPT_PARAM_C(String,input);
|
|
assert_tagged(input);
|
|
if (!settings.stylesheetSettingsFor(*stylesheet).card_spellcheck_enabled)
|
|
SCRIPT_RETURN(input);
|
|
SCRIPT_OPTIONAL_PARAM_(String, extra_dictionary);
|
|
SCRIPT_OPTIONAL_PARAM_(ScriptValueP, extra_match);
|
|
// remove old spelling error tags
|
|
input = remove_tag(input, _("<error-spelling"));
|
|
// no language -> spelling checking
|
|
if (language.empty()) {
|
|
SCRIPT_RETURN(input);
|
|
}
|
|
SpellChecker* checkers[3] = {nullptr};
|
|
checkers[0] = SpellChecker::get(language);
|
|
if (!extra_dictionary.empty()) {
|
|
checkers[1] = SpellChecker::get(extra_dictionary,language);
|
|
}
|
|
// what will the missspelling tag be?
|
|
String tag = _("error-spelling:");
|
|
tag += language;
|
|
if (!extra_dictionary.empty()) {
|
|
tag += _(":") + extra_dictionary;
|
|
}
|
|
tag += _(">");
|
|
// now walk over the words in the input, and mark misspellings
|
|
String result;
|
|
size_t word_start = String::npos; // start of the word to be checked, or npos if not inside a word
|
|
size_t pos = 0;
|
|
int unchecked_tag = 0;
|
|
bool check_this_word = true;
|
|
while (pos < input.size()) {
|
|
Char c = input.GetChar(pos);
|
|
if (c == _('<')) {
|
|
if (is_tag(input, pos, _("<nospellcheck"))) unchecked_tag++;
|
|
else if (is_tag(input, pos, _("</nospellcheck"))) unchecked_tag--;
|
|
else if (is_tag(input, pos, _("<sym"))) unchecked_tag++;
|
|
else if (is_tag(input, pos, _("</sym"))) unchecked_tag--;
|
|
else if (is_tag(input, pos, _("<atom"))) unchecked_tag++;
|
|
else if (is_tag(input, pos, _("</atom"))) unchecked_tag--;
|
|
// skip tag
|
|
auto after = skip_tag(input,pos);
|
|
if (word_start == pos) {
|
|
// prefer to place word start inside tags, i.e. as late as possible
|
|
word_start = pos = after;
|
|
result.append(input, pos, after-pos);
|
|
} else {
|
|
if (word_start == String::npos) {
|
|
result.append(input, pos, after - pos);
|
|
}
|
|
pos = after;
|
|
}
|
|
} else if (isWordChar(c)) {
|
|
// a word character
|
|
if (word_start == String::npos) word_start = pos;
|
|
if (unchecked_tag > 0) check_this_word = false;
|
|
++pos;
|
|
} else {
|
|
// a non-word character, punctuation or space
|
|
// check word, add to result
|
|
check_word(tag, input, word_start, pos, result, check_this_word, checkers, extra_match, ctx);
|
|
word_start = String::npos;
|
|
check_this_word = unchecked_tag <= 0;
|
|
result += c;
|
|
++pos;
|
|
}
|
|
}
|
|
// last word
|
|
check_word(tag, input, word_start, input.size(), result, check_this_word, checkers, extra_match, ctx);
|
|
// done
|
|
assert_tagged(result);
|
|
SCRIPT_RETURN(result);
|
|
}
|
|
|
|
SCRIPT_FUNCTION(check_spelling_word) {
|
|
SCRIPT_PARAM_C(String,language);
|
|
SCRIPT_PARAM_C(String,input);
|
|
if (language.empty()) {
|
|
// no language -> spelling checking
|
|
SCRIPT_RETURN(true);
|
|
} else {
|
|
auto checker = SpellChecker::get(language);
|
|
bool correct = !checker || checker->spell(input);
|
|
SCRIPT_RETURN(correct);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------- : Init
|
|
|
|
void init_script_spelling_functions(Context& ctx) {
|
|
ctx.setVariable(_("check_spelling"), script_check_spelling);
|
|
ctx.setVariable(_("check_spelling_word"), script_check_spelling_word);
|
|
}
|