mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Choice rendering now uses "style.image()" instead of "style.choice_images[value]";
Added script functions for working with multiple choice values; Added in_context support for filter_rule; Optimized toUpper/toLower because they are slow on windows (they use thread local storage and mutexes) git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@427 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -26,11 +26,14 @@ String ValueAction::getName(bool to_undo) const {
|
||||
|
||||
/// Swap the value in a Value object with a new one
|
||||
inline void swap_value(ChoiceValue& a, ChoiceValue ::ValueType& b) { swap(a.value, b); }
|
||||
inline void swap_value(MultipleChoiceValue& a, MultipleChoiceValue::ValueType& b) { swap(a.value, b); }
|
||||
inline void swap_value(ColorValue& a, ColorValue ::ValueType& b) { swap(a.value, b); }
|
||||
inline void swap_value(ImageValue& a, ImageValue ::ValueType& b) { swap(a.filename, b); a.last_update.update(); }
|
||||
inline void swap_value(SymbolValue& a, SymbolValue ::ValueType& b) { swap(a.filename, b); a.last_update.update(); }
|
||||
inline void swap_value(TextValue& a, TextValue ::ValueType& b) { swap(a.value, b); a.last_update.update(); }
|
||||
inline void swap_value(MultipleChoiceValue& a, MultipleChoiceValue::ValueType& b) {
|
||||
swap(a.value, b.value);
|
||||
swap(a.last_change, b.last_change);
|
||||
}
|
||||
|
||||
/// A ValueAction that swaps between old and new values
|
||||
template <typename T, bool ALLOW_MERGE>
|
||||
@@ -62,10 +65,13 @@ class SimpleValueAction : public ValueAction {
|
||||
};
|
||||
|
||||
ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<ChoiceValue, true> (value, new_value); }
|
||||
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<MultipleChoiceValue, false>(value, new_value); }
|
||||
ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value) { return new SimpleValueAction<ColorValue, true> (value, new_value); }
|
||||
ValueAction* value_action(const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction<ImageValue, false>(value, new_value); }
|
||||
ValueAction* value_action(const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction<SymbolValue, false>(value, new_value); }
|
||||
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change) {
|
||||
MultipleChoiceValue::ValueType v = { new_value, last_change };
|
||||
return new SimpleValueAction<MultipleChoiceValue, false>(value, v);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : Text
|
||||
|
||||
@@ -45,7 +45,7 @@ class ValueAction : public Action {
|
||||
|
||||
/// Action that updates a Value to a new value
|
||||
ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value);
|
||||
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value);
|
||||
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change);
|
||||
ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value);
|
||||
ValueAction* value_action(const ImageValueP& value, const FileName& new_value);
|
||||
ValueAction* value_action(const SymbolValueP& value, const FileName& new_value);
|
||||
|
||||
@@ -179,6 +179,35 @@ ChoiceStyle::~ChoiceStyle() {
|
||||
delete thumbnails;
|
||||
}
|
||||
|
||||
void ChoiceStyle::initImage() {
|
||||
if (image.isSet() || choice_images.empty()) return;
|
||||
// for, for example:
|
||||
// choice images:
|
||||
// a: {uvw}
|
||||
// b: {xyz}
|
||||
// generate the script:
|
||||
// [a: {uvw}, b: {xyz}][input]() or else nil
|
||||
// or in bytecode
|
||||
// PUSH_CONST [a: {uvw}, b: {xyz}]
|
||||
// GET_VAR input
|
||||
// MEMBER
|
||||
// CALL 0
|
||||
// PUSH_CONST nil
|
||||
// OR_ELSE
|
||||
// RET
|
||||
intrusive_ptr<ScriptCustomCollection> lookup(new ScriptCustomCollection());
|
||||
FOR_EACH(ci, choice_images) {
|
||||
lookup->key_value[ci.first] = ci.second.getScriptP();
|
||||
}
|
||||
Script& script = image.getScript();
|
||||
script.addInstruction(I_PUSH_CONST, lookup);
|
||||
script.addInstruction(I_GET_VAR, string_to_variable(_("input")));
|
||||
script.addInstruction(I_BINARY, I_MEMBER);
|
||||
script.addInstruction(I_CALL, 0);
|
||||
script.addInstruction(I_PUSH_CONST, script_nil);
|
||||
script.addInstruction(I_BINARY, I_OR_ELSE);
|
||||
script.addInstruction(I_RET);
|
||||
}
|
||||
|
||||
bool ChoiceStyle::update(Context& ctx) {
|
||||
// Don't update the choice images, leave that to invalidate()
|
||||
@@ -256,6 +285,7 @@ IMPLEMENT_REFLECTION(ChoiceStyle) {
|
||||
REFLECT(alignment);
|
||||
REFLECT(angle);
|
||||
REFLECT(font);
|
||||
REFLECT(image);
|
||||
REFLECT(choice_images);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ class ChoiceStyle : public Style {
|
||||
ChoicePopupStyle popup_style; ///< Style of popups/menus
|
||||
ChoiceRenderStyle render_style; ///< Style of rendering
|
||||
Font font; ///< Font for drawing text (when RENDER_TEXT)
|
||||
ScriptableImage image; ///< Image to draw (when RENDER_IMAGE)
|
||||
map<String,ScriptableImage> choice_images; ///< Images for the various choices (when RENDER_IMAGE)
|
||||
bool choice_images_initialized;
|
||||
Scriptable<String> mask_filename; ///< Filename of an additional mask over the images
|
||||
@@ -150,6 +151,8 @@ class ChoiceStyle : public Style {
|
||||
|
||||
/// Load the mask image, if it's not already done
|
||||
void loadMask(Package& pkg);
|
||||
/// Initialize image from choice_images
|
||||
void initImage();
|
||||
|
||||
virtual bool update(Context&);
|
||||
virtual void initDependencies(Context&, const Dependency&) const;
|
||||
|
||||
@@ -48,6 +48,14 @@ IMPLEMENT_REFLECTION_NAMELESS(MultipleChoiceValue) {
|
||||
REFLECT_BASE(ChoiceValue);
|
||||
}
|
||||
|
||||
bool MultipleChoiceValue::update(Context& ctx) {
|
||||
String old_value = value();
|
||||
ctx.setVariable(_("last change"), to_script(last_change));
|
||||
ChoiceValue::update(ctx);
|
||||
normalForm();
|
||||
return value() != old_value;
|
||||
}
|
||||
|
||||
void MultipleChoiceValue::get(vector<String>& out) const {
|
||||
// split the value
|
||||
out.clear();
|
||||
@@ -66,3 +74,38 @@ void MultipleChoiceValue::get(vector<String>& out) const {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MultipleChoiceValue::normalForm() {
|
||||
String& val = value.mutateDontChangeDefault();
|
||||
// which choices are active?
|
||||
vector<bool> seen(field().choices->lastId());
|
||||
for (size_t pos = 0 ; pos < val.size() ; ) {
|
||||
if (val.GetChar(pos) == _(' ')) {
|
||||
++pos; // ingore whitespace
|
||||
} else {
|
||||
// does this choice match the one asked about?
|
||||
size_t end = val.find_first_of(_(','), pos);
|
||||
if (end == String::npos) end = val.size();
|
||||
// find this choice
|
||||
for (size_t i = 0 ; i < seen.size() ; ++i) {
|
||||
if (is_substr(val, pos, field().choices->choiceName((int)i))) {
|
||||
seen[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos = end + 1;
|
||||
}
|
||||
}
|
||||
// now put them back in the right order
|
||||
val.clear();
|
||||
for (size_t i = 0 ; i < seen.size() ; ++i) {
|
||||
if (seen[i]) {
|
||||
if (!val.empty()) val += _(", ");
|
||||
val += field().choices->choiceName((int)i);
|
||||
}
|
||||
}
|
||||
// empty choice name
|
||||
if (val.empty()) {
|
||||
val = field().empty_choice;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,13 +57,24 @@ class MultipleChoiceValue : public ChoiceValue {
|
||||
inline MultipleChoiceValue(const MultipleChoiceFieldP& field) : ChoiceValue(field, true) {}
|
||||
DECLARE_HAS_FIELD(MultipleChoice);
|
||||
|
||||
String last_choice; ///< Which of the choices was selected/deselected last?
|
||||
String last_change; ///< Which of the choices was selected/deselected last?
|
||||
|
||||
// for SimpleValueAction
|
||||
struct ValueType {
|
||||
ChoiceValue::ValueType value;
|
||||
String last_change;
|
||||
};
|
||||
|
||||
/// Splits the value, stores the selected choices in the out parameter
|
||||
void get(vector<String>& out) const;
|
||||
|
||||
virtual bool update(Context&);
|
||||
|
||||
private:
|
||||
DECLARE_REFLECTION();
|
||||
|
||||
/// Put the value in normal form (all choices ordered, empty_name
|
||||
void normalForm();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Utilities
|
||||
|
||||
@@ -35,8 +35,7 @@ DropDownMultipleChoiceList::DropDownMultipleChoiceList
|
||||
void DropDownMultipleChoiceList::select(size_t item) {
|
||||
MultipleChoiceValueEditor& mcve = dynamic_cast<MultipleChoiceValueEditor&>(cve);
|
||||
if (isFieldDefault(item)) {
|
||||
// make default
|
||||
mcve.getSet().actions.add(value_action(mcve.valueP(), Defaultable<String>()));
|
||||
mcve.toggleDefault();
|
||||
} else {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
mcve.toggle(choice->first_id);
|
||||
@@ -143,6 +142,7 @@ void MultipleChoiceValueEditor::onValueChange() {
|
||||
|
||||
void MultipleChoiceValueEditor::toggle(int id) {
|
||||
String new_value;
|
||||
String toggled_choice;
|
||||
// old selection
|
||||
vector<String> selected;
|
||||
value().get(selected);
|
||||
@@ -157,7 +157,12 @@ void MultipleChoiceValueEditor::toggle(int id) {
|
||||
if (!new_value.empty()) new_value += _(", ");
|
||||
new_value += choice;
|
||||
}
|
||||
if (i == id) toggled_choice = choice;
|
||||
}
|
||||
// store value
|
||||
getSet().actions.add(value_action(valueP(), new_value));
|
||||
getSet().actions.add(value_action(valueP(), new_value, toggled_choice));
|
||||
}
|
||||
|
||||
void MultipleChoiceValueEditor::toggleDefault() {
|
||||
getSet().actions.add(value_action(valueP(), Defaultable<String>(value().value(), !value().value.isDefault()), _("")));
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ class MultipleChoiceValueEditor : public MultipleChoiceValueViewer, public Value
|
||||
DropDownList& initDropDown();
|
||||
/// Toggle a choice or on or off
|
||||
void toggle(int id);
|
||||
/// Toggle defaultness or on or off
|
||||
void toggleDefault();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -19,9 +19,15 @@ void ChoiceValueViewer::draw(RotatedDC& dc) {
|
||||
double margin = 0;
|
||||
if (style().render_style & RENDER_IMAGE) {
|
||||
// draw image
|
||||
map<String,ScriptableImage>::iterator it = style().choice_images.find(cannocial_name_form(value().value()));
|
||||
if (it != style().choice_images.end() && it->second.isReady()) {
|
||||
ScriptableImage& img = it->second;
|
||||
// map<String,ScriptableImage>::iterator it = style().choice_images.find(cannocial_name_form(value().value()));
|
||||
// if (it != style().choice_images.end() && it->second.isReady()) {
|
||||
// ScriptableImage& img = it->second;
|
||||
style().initImage();
|
||||
ScriptableImage& img = style().image;
|
||||
Context& ctx = viewer.getContext();
|
||||
ctx.setVariable(_("input"), to_script(value().value()));
|
||||
img.update(ctx);
|
||||
if (img.isReady()) {
|
||||
GeneratedImage::Options img_options(0,0, viewer.stylesheet.get(), &getSet());
|
||||
if (nativeLook()) {
|
||||
img_options.width = img_options.height = 16;
|
||||
|
||||
@@ -43,9 +43,12 @@ void MultipleChoiceValueViewer::draw(RotatedDC& dc) {
|
||||
double margin = 0;
|
||||
if (style().render_style & RENDER_IMAGE) {
|
||||
// draw image
|
||||
map<String,ScriptableImage>::iterator it = style().choice_images.find(cannocial_name_form(value().value()));
|
||||
if (it != style().choice_images.end() && it->second.isReady()) {
|
||||
ScriptableImage& img = it->second;
|
||||
style().initImage();
|
||||
ScriptableImage& img = style().image;
|
||||
Context& ctx = viewer.getContext();
|
||||
ctx.setVariable(_("input"), to_script(value().value()));
|
||||
img.update(ctx);
|
||||
if (img.isReady()) {
|
||||
GeneratedImage::Options img_options(0,0, viewer.stylesheet.get(), &getSet());
|
||||
if (nativeLook()) {
|
||||
img_options.width = img_options.height = 16;
|
||||
|
||||
@@ -35,6 +35,13 @@ SCRIPT_FUNCTION(to_title) {
|
||||
SCRIPT_RETURN(capitalize(input));
|
||||
}
|
||||
|
||||
// reverse a string
|
||||
SCRIPT_FUNCTION(reverse) {
|
||||
SCRIPT_PARAM(String, input);
|
||||
reverse(input.begin(), input.end());
|
||||
SCRIPT_RETURN(input);
|
||||
}
|
||||
|
||||
// extract a substring
|
||||
SCRIPT_FUNCTION(substring) {
|
||||
SCRIPT_PARAM(String, input);
|
||||
@@ -360,13 +367,19 @@ class ScriptFilterRule : public ScriptValue {
|
||||
size_t start, len;
|
||||
bool ok = regex.GetMatch(&start, &len, 0);
|
||||
assert(ok);
|
||||
ret += input.substr(start, len); // the match
|
||||
input = input.substr(start + len); // everything after the match
|
||||
String inside = input.substr(start, len); // the match
|
||||
String next_input = input.substr(start + len); // everything after the match
|
||||
if (!context.IsValid() || context.Matches(input.substr(0,start) + _("<match>") + next_input)) {
|
||||
// no context or context match
|
||||
ret += inside;
|
||||
}
|
||||
input = next_input;
|
||||
}
|
||||
SCRIPT_RETURN(ret);
|
||||
}
|
||||
|
||||
wxRegEx regex; ///< Regex to match
|
||||
wxRegEx regex; ///< Regex to match
|
||||
wxRegEx context; ///< Match only in a given context, optional
|
||||
};
|
||||
|
||||
// Create a regular expression rule for filtering strings
|
||||
@@ -377,6 +390,12 @@ ScriptValueP filter_rule(Context& ctx) {
|
||||
if (!ret->regex.Compile(match, wxRE_ADVANCED)) {
|
||||
throw ScriptError(_("Error while compiling regular expression: '")+match+_("'"));
|
||||
}
|
||||
// in_context
|
||||
SCRIPT_OPTIONAL_PARAM_N(String, _("in context"), in_context) {
|
||||
if (!ret->context.Compile(in_context, wxRE_ADVANCED)) {
|
||||
throw ScriptError(_("Error while compiling regular expression: '")+in_context+_("'"));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -592,6 +611,7 @@ void init_script_basic_functions(Context& ctx) {
|
||||
ctx.setVariable(_("to upper"), script_to_upper);
|
||||
ctx.setVariable(_("to lower"), script_to_lower);
|
||||
ctx.setVariable(_("to title"), script_to_title);
|
||||
ctx.setVariable(_("reverse"), script_reverse);
|
||||
ctx.setVariable(_("substring"), script_substring);
|
||||
ctx.setVariable(_("contains"), script_contains);
|
||||
ctx.setVariable(_("format"), script_format);
|
||||
|
||||
+132
-19
@@ -157,10 +157,8 @@ SCRIPT_FUNCTION(primary_choice) {
|
||||
|
||||
// ----------------------------------------------------------------------------- : Multiple choice values
|
||||
|
||||
// is the given choice active?
|
||||
SCRIPT_FUNCTION(chosen) {
|
||||
SCRIPT_PARAM(String,choice);
|
||||
SCRIPT_PARAM(String,input);
|
||||
/// Is the given choice active?
|
||||
bool chosen(const String& choice, const String& input) {
|
||||
for (size_t pos = 0 ; pos < input.size() ; ) {
|
||||
if (input.GetChar(pos) == _(' ')) {
|
||||
++pos; // ingore whitespace
|
||||
@@ -169,32 +167,147 @@ SCRIPT_FUNCTION(chosen) {
|
||||
size_t end = input.find_first_of(_(','), pos);
|
||||
if (end == String::npos) end = input.size();
|
||||
if (end - pos == choice.size() && is_substr(input, pos, choice)) {
|
||||
SCRIPT_RETURN(true);
|
||||
return true;
|
||||
}
|
||||
pos = end + 1;
|
||||
}
|
||||
}
|
||||
SCRIPT_RETURN(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// is the given choice active?
|
||||
SCRIPT_FUNCTION(chosen) {
|
||||
SCRIPT_PARAM(String,choice);
|
||||
SCRIPT_PARAM(String,input);
|
||||
SCRIPT_RETURN(chosen(choice, input));
|
||||
}
|
||||
|
||||
/// Filter the choices
|
||||
/** Keep at most max elements of choices,
|
||||
* and at least min. Use prefered as choice to add/keep in case of conflicts.
|
||||
*/
|
||||
String filter_choices(const String& input, const vector<String>& choices, int min, int max, String prefered) {
|
||||
if (choices.empty()) return input; // do nothing, shouldn't happen, but better make sure
|
||||
String ret;
|
||||
int count = 0;
|
||||
vector<bool> seen(choices.size()); // which choices have we seen?
|
||||
for (size_t pos = 0 ; pos < input.size() ; ) {
|
||||
if (input.GetChar(pos) == _(' ')) {
|
||||
++pos; // ingore whitespace
|
||||
} else {
|
||||
// does this choice match the one asked about?
|
||||
size_t end = input.find_first_of(_(','), pos);
|
||||
if (end == String::npos) end = input.size();
|
||||
// is this choice in choices
|
||||
bool in_choices = false;
|
||||
for (size_t i = 0 ; i < choices.size() ; ++i) {
|
||||
if (!seen[i] && is_substr(input, pos, choices[i])) {
|
||||
seen[i] = true; ++count;
|
||||
in_choices = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// is this choice unaffected?
|
||||
if (!in_choices) {
|
||||
if (!ret.empty()) ret += _(", ");
|
||||
ret += input.substr(pos, end - pos);
|
||||
}
|
||||
pos = end + 1;
|
||||
}
|
||||
}
|
||||
// keep more choices
|
||||
if (count < min) {
|
||||
// add prefered choice
|
||||
for (size_t i = 0 ; i < choices.size() ; ++i) {
|
||||
if (choices[i] == prefered) {
|
||||
if (!seen[i]) {
|
||||
seen[i] = true; ++count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add more choices
|
||||
for (size_t i = 0 ; i < choices.size() ; ++i) {
|
||||
if (count >= min) break;
|
||||
if (!seen[i]) {
|
||||
seen[i] = true; ++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
// keep less choices
|
||||
if (count > max) {
|
||||
for (size_t i = choices.size() - 1 ; i >= 0 ; --i) {
|
||||
if (count <= max) break;
|
||||
if (seen[i]) {
|
||||
if (max > 0 && choices[i] == prefered) continue; // we would rather not remove prefered choice
|
||||
seen[i] = false; --count;
|
||||
}
|
||||
}
|
||||
}
|
||||
// add the 'seen' choices to ret
|
||||
for (size_t i = 0 ; i < choices.size() ; ++i) {
|
||||
if (seen[i]) {
|
||||
if (!ret.empty()) ret += _(", ");
|
||||
ret += choices[i];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// read 'choice#' arguments
|
||||
void read_choices_param(Context& ctx, vector<String>& choices) {
|
||||
for (int i = 0 ; ; ++i) {
|
||||
String name = _("choice"); if (i > 0) name = name << i;
|
||||
SCRIPT_OPTIONAL_PARAM_N(String, name, choice) {
|
||||
choices.push_back(choice);
|
||||
} else if (i > 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
// add the given choice if it is not already active
|
||||
SCRIPT_FUNCTION(require_choice) {
|
||||
SCRIPT_PARAM(ValueP,input);
|
||||
MultipleChoiceValueP value = dynamic_pointer_cast<MultipleChoiceValue>(input);
|
||||
if (!value) {
|
||||
throw ScriptError(_("Argument 'input' to 'require_choice' should be a multiple choice value"));
|
||||
}
|
||||
SCRIPT_PARAM(String,choice);
|
||||
// TODO
|
||||
SCRIPT_RETURN(input);
|
||||
SCRIPT_PARAM(String,input);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(String,_("last change"),last_change);
|
||||
vector<String> choices;
|
||||
read_choices_param(ctx, choices);
|
||||
SCRIPT_RETURN(filter_choices(input, choices, 1, (int)choices.size(), last_change));
|
||||
}
|
||||
|
||||
// make sure at most one of the choices is active
|
||||
SCRIPT_FUNCTION(exclusive_choice) {
|
||||
SCRIPT_PARAM(String,input);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(String,_("last change"),last_change);
|
||||
vector<String> choices;
|
||||
read_choices_param(ctx, choices);
|
||||
SCRIPT_RETURN(filter_choices(input, choices, 0, 1, last_change));
|
||||
}
|
||||
|
||||
// make sure exactly one of the choices is active
|
||||
SCRIPT_FUNCTION(require_exclusive_choice) {
|
||||
SCRIPT_PARAM(String,input);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(String,_("last change"),last_change);
|
||||
vector<String> choices;
|
||||
read_choices_param(ctx, choices);
|
||||
SCRIPT_RETURN(filter_choices(input, choices, 1, 1, last_change));
|
||||
}
|
||||
|
||||
// make sure none of the choices are active
|
||||
SCRIPT_FUNCTION(remove_choice) {
|
||||
SCRIPT_PARAM(String,input);
|
||||
vector<String> choices;
|
||||
read_choices_param(ctx, choices);
|
||||
SCRIPT_RETURN(filter_choices(input, choices, 0, 0, _("")));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Init
|
||||
|
||||
void init_script_editor_functions(Context& ctx) {
|
||||
ctx.setVariable(_("forward editor"), script_combined_editor); // combatability
|
||||
ctx.setVariable(_("combined editor"), script_combined_editor);
|
||||
ctx.setVariable(_("primary choice"), script_primary_choice);
|
||||
ctx.setVariable(_("chosen"), script_chosen);
|
||||
ctx.setVariable(_("require choice"), script_require_choice);
|
||||
ctx.setVariable(_("forward editor"), script_combined_editor); // compatability
|
||||
ctx.setVariable(_("combined editor"), script_combined_editor);
|
||||
ctx.setVariable(_("primary choice"), script_primary_choice);
|
||||
ctx.setVariable(_("chosen"), script_chosen);
|
||||
ctx.setVariable(_("require choice"), script_require_choice);
|
||||
ctx.setVariable(_("exclusive choice"), script_exclusive_choice);
|
||||
ctx.setVariable(_("require exclusive choice"), script_require_exclusive_choice);
|
||||
ctx.setVariable(_("remove choice"), script_remove_choice);
|
||||
}
|
||||
|
||||
@@ -61,15 +61,15 @@ ScriptValueP Script::dependencies(Context& ctx, const Dependency& dep) const {
|
||||
}
|
||||
|
||||
void Script::addInstruction(InstructionType t) {
|
||||
//if (t == I_MEMBER_V && !instructions.empty() && instructions.back().instr == I_PUSH_CONST) {
|
||||
// // optimize: push x ; member_v --> member x
|
||||
// instructions.back().instr = I_MEMBER;
|
||||
//} else {
|
||||
Instruction i = {t, {0}};
|
||||
instructions.push_back(i);
|
||||
//}
|
||||
}
|
||||
void Script::addInstruction(InstructionType t, unsigned int d) {
|
||||
if (t == I_BINARY && d == I_MEMBER && !instructions.empty() && instructions.back().instr == I_PUSH_CONST) {
|
||||
// optimize: push x ; member --> member_c x
|
||||
instructions.back().instr = I_MEMBER_C;
|
||||
return;
|
||||
}
|
||||
Instruction i = {t, {d}};
|
||||
instructions.push_back(i);
|
||||
}
|
||||
|
||||
@@ -46,13 +46,13 @@ class Defaultable {
|
||||
is_default = false;
|
||||
return value;
|
||||
}
|
||||
/// Get access to the value, for changing it, don't change the defaultness
|
||||
inline T& mutateDontChangeDefault() { return value; }
|
||||
|
||||
/// Is this value in the default state?
|
||||
inline bool isDefault() const { return is_default; }
|
||||
/// Set the defaultness to true
|
||||
inline void makeDefault() { is_default = true; }
|
||||
/// Set the defaultness to false
|
||||
inline void unsetDefault() { is_default = false; }
|
||||
/// Set the defaultness to d
|
||||
inline void makeDefault(bool d = true) { is_default = d; }
|
||||
|
||||
/// Compare the values, ignore defaultness
|
||||
/** used by scriptable to check for changes */
|
||||
|
||||
+27
-3
@@ -41,6 +41,30 @@ void writeUTF8(wxTextOutputStream& stream, const String& str) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Char functions
|
||||
|
||||
#ifdef CHAR_FUNCTIONS_ARE_SLOW
|
||||
|
||||
Char toLower(Char c) {
|
||||
if (c <= 128) {
|
||||
if (c >= _('A') && c <= _('Z')) return c + (_('a') - _('A'));
|
||||
else return c;
|
||||
} else {
|
||||
return IF_UNICODE( towlower(c) , tolower(c) );
|
||||
}
|
||||
}
|
||||
|
||||
Char toUpper(Char c) {
|
||||
if (c <= 128) {
|
||||
if (c >= _('a') && c <= _('z')) return c + (_('A') - _('a'));
|
||||
else return c;
|
||||
} else {
|
||||
return IF_UNICODE( towupper(c) , toupper(c) );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------- : String utilities
|
||||
|
||||
String trim(const String& s){
|
||||
@@ -180,7 +204,6 @@ bool smart_less(const String& as, const String& bs) {
|
||||
bool eq = true; // so far is everything equal?
|
||||
FOR_EACH_2_CONST(a, as, b, bs) {
|
||||
bool na = isDigit(a), nb = isDigit(b);
|
||||
Char la = toLower(a), lb = toLower(b);
|
||||
if (na && nb) {
|
||||
// compare numbers
|
||||
in_num = true;
|
||||
@@ -198,8 +221,9 @@ bool smart_less(const String& as, const String& bs) {
|
||||
return lt;
|
||||
} else {
|
||||
// compare characters
|
||||
if (la < lb) return true;
|
||||
if (la > lb) return false;
|
||||
Char la = toLower(a), lb = toLower(b);
|
||||
if (la < lb) return true;
|
||||
if (la > lb) return false;
|
||||
}
|
||||
in_num = na && nb;
|
||||
}
|
||||
|
||||
+12
-2
@@ -88,8 +88,18 @@ inline bool isUpper(Char c) { return IF_UNICODE( iswupper(c) , isupper(c) ); }
|
||||
inline bool isLower(Char c) { return IF_UNICODE( iswlower(c) , islower(c) ); }
|
||||
inline bool isPunct(Char c) { return IF_UNICODE( iswpunct(c) , ispunct(c) ); }
|
||||
// Character conversions
|
||||
inline Char toUpper(Char c) { return IF_UNICODE( towupper(c) , toupper(c) ); }
|
||||
inline Char toLower(Char c) { return IF_UNICODE( towlower(c) , tolower(c) ); }
|
||||
#ifdef _MSC_VER
|
||||
#define CHAR_FUNCTIONS_ARE_SLOW
|
||||
#endif
|
||||
#ifdef CHAR_FUNCTIONS_ARE_SLOW
|
||||
// These functions are slow as hell on msvc.
|
||||
// If also in other compilers, they can also use these routines.
|
||||
Char toLower(Char c);
|
||||
Char toUpper(Char c);
|
||||
#else
|
||||
inline Char toLower(Char c) { return IF_UNICODE( towlower(c) , tolower(c) ); }
|
||||
inline Char toUpper(Char c) { return IF_UNICODE( towupper(c) , toupper(c) ); }
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------- : String utilities
|
||||
|
||||
|
||||
Reference in New Issue
Block a user