Commit db9d93eb authored by twanvl's avatar twanvl

Addded script functions for exporting, ExportTemplate package type

parent fc395f0f
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2006 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// ----------------------------------------------------------------------------- : Includes
#include <data/export_template.hpp>
// ----------------------------------------------------------------------------- : Export template, basics
String ExportTemplate::typeNameStatic() { return _("export-template"); }
String ExportTemplate::typeName() const { return _("export-template"); }
IMPLEMENT_REFLECTION(ExportTemplate) {
REFLECT_BASE(Packaged);
REFLECT(file_type);
REFLECT(create_directory);
}
// ----------------------------------------------------------------------------- :
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2006 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#ifndef HEADER_DATA_EXPORT_TEMPLATE
#define HEADER_DATA_EXPORT_TEMPLATE
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <util/io/package.hpp>
#include <script/scriptable.hpp>
// ----------------------------------------------------------------------------- : ExportTemplate
/// A template for exporting sets to HTML or text format
class ExportTemplate : public Packaged {
public:
OptionalScript script; ///< Export script
String file_type; ///< Type of the created file, in "name|*.ext" format
bool create_directory; ///< The export creates an entire directory
static String typeNameStatic();
virtual String typeName() const;
private:
DECLARE_REFLECTION();
};
// ----------------------------------------------------------------------------- : EOF
#endif
...@@ -44,8 +44,8 @@ IMPLEMENT_REFLECTION(Game) { ...@@ -44,8 +44,8 @@ IMPLEMENT_REFLECTION(Game) {
REFLECT(statistics_dimensions); REFLECT(statistics_dimensions);
REFLECT(statistics_categories); REFLECT(statistics_categories);
REFLECT(has_keywords); REFLECT(has_keywords);
REFLECT(keyword_parameter_types);
REFLECT(keyword_modes); REFLECT(keyword_modes);
REFLECT(keyword_parameter_types);
REFLECT(keywords); REFLECT(keywords);
// REFLECT(word_lists); // REFLECT(word_lists);
} }
......
...@@ -23,7 +23,7 @@ struct CharInfo; ...@@ -23,7 +23,7 @@ struct CharInfo;
// ----------------------------------------------------------------------------- : SymbolFont // ----------------------------------------------------------------------------- : SymbolFont
// A font that is drawn using images /// A font that is drawn using images
class SymbolFont : public Packaged { class SymbolFont : public Packaged {
public: public:
SymbolFont(); SymbolFont();
......
...@@ -1574,6 +1574,12 @@ ...@@ -1574,6 +1574,12 @@
<Filter <Filter
Name="aux" Name="aux"
Filter=""> Filter="">
<File
RelativePath=".\data\export_template.cpp">
</File>
<File
RelativePath=".\data\export_template.hpp">
</File>
<File <File
RelativePath=".\data\font.cpp"> RelativePath=".\data\font.cpp">
<FileConfiguration <FileConfiguration
......
...@@ -209,7 +209,7 @@ void Context::closeScope(size_t scope) { ...@@ -209,7 +209,7 @@ void Context::closeScope(size_t scope) {
void instrUnary (UnaryInstructionType i, ScriptValueP& a) { void instrUnary (UnaryInstructionType i, ScriptValueP& a) {
switch (i) { switch (i) {
case I_ITERATOR_C: case I_ITERATOR_C:
a = a->makeIterator(); a = a->makeIterator(a);
break; break;
case I_NEGATE: case I_NEGATE:
a = to_script(-(int)*a); a = to_script(-(int)*a);
......
...@@ -48,8 +48,8 @@ class DependencyUnion : public ScriptValue { ...@@ -48,8 +48,8 @@ class DependencyUnion : public ScriptValue {
virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const { virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const {
return unified( a->dependencies(ctx,dep), b->dependencies(ctx,dep)); return unified( a->dependencies(ctx,dep), b->dependencies(ctx,dep));
} }
virtual ScriptValueP makeIterator() const { virtual ScriptValueP makeIterator(ScriptValueP thisP) const {
return unified(a->makeIterator(), b->makeIterator()); return unified(a->makeIterator(thisP), b->makeIterator(thisP));
} }
virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const { virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const {
return unified(a->dependencyMember(name,dep), b->dependencyMember(name,dep)); return unified(a->dependencyMember(name,dep), b->dependencyMember(name,dep));
...@@ -279,7 +279,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script) ...@@ -279,7 +279,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script)
ScriptValueP& a = stack.back(); ScriptValueP& a = stack.back();
switch (i.instr1) { switch (i.instr1) {
case I_ITERATOR_C: case I_ITERATOR_C:
a = a->makeIterator(); // as normal a = a->makeIterator(a); // as normal
break; break;
default: default:
a = dependency_dummy; a = dependency_dummy;
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <data/set.hpp> #include <data/set.hpp>
#include <data/game.hpp> #include <data/game.hpp>
DECLARE_TYPEOF_COLLECTION(pair<String COMMA ScriptValueP>);
// ----------------------------------------------------------------------------- : String stuff // ----------------------------------------------------------------------------- : String stuff
// convert a string to upper case // convert a string to upper case
...@@ -147,7 +149,7 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr ...@@ -147,7 +149,7 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr
} }
} else { } else {
// unordered position // unordered position
ScriptValueP it = in->makeIterator(); ScriptValueP it = in->makeIterator(in);
int i = 0; int i = 0;
while (ScriptValueP v = it->next()) { while (ScriptValueP v = it->next()) {
if (equal(*of, *v)) return i; if (equal(*of, *v)) return i;
...@@ -157,6 +159,34 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr ...@@ -157,6 +159,34 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr
return -1; // TODO? return -1; // TODO?
} }
// sort a script list
ScriptValueP sort_script(Context& ctx, const ScriptValueP& list, ScriptValue& order_by) {
ScriptType list_t = list->type();
if (list_t == SCRIPT_STRING) {
// sort a string
String s = list->toString();
sort(s.begin(), s.end());
SCRIPT_RETURN(s);
} else {
// are we sorting a set
ScriptObject<Set*>* set = dynamic_cast<ScriptObject<Set*>*>(list.get());
// sort a collection
vector<pair<String,ScriptValueP> > values;
ScriptValueP it = list->makeIterator(list);
while (ScriptValueP v = it->next()) {
ctx.setVariable(set ? _("card") : _("input"), v);
values.push_back(make_pair(order_by.eval(ctx)->toString(), v));
}
sort(values.begin(), values.end());
// return collection
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection());
FOR_EACH(v, values) {
ret->value.push_back(v.second);
}
return ret;
}
}
// finding positions, also of substrings // finding positions, also of substrings
SCRIPT_FUNCTION_WITH_DEP(position_of) { SCRIPT_FUNCTION_WITH_DEP(position_of) {
ScriptValueP of = ctx.getVariable(_("of")); ScriptValueP of = ctx.getVariable(_("of"));
...@@ -436,12 +466,66 @@ String spec_sort(const String& spec, const String& input) { ...@@ -436,12 +466,66 @@ String spec_sort(const String& spec, const String& input) {
} }
// Create a rule for spec_sorting strings // Sort using spec_sort
SCRIPT_RULE_1(sort, String, order) { class ScriptRule_sort_order: public ScriptValue {
SCRIPT_PARAM(String, input); public:
SCRIPT_RETURN(spec_sort(order, input)); inline ScriptRule_sort_order(const String& order) : order(order) {}
} virtual ScriptType type() const { return SCRIPT_FUNCTION; }
virtual String typeName() const { return _("sort_rule"); }
virtual ScriptValueP eval(Context& ctx) const {
SCRIPT_PARAM(String, input);
SCRIPT_RETURN(spec_sort(order, input));
}
private:
String order;
};
// Sort using sort_script
class ScriptRule_sort_order_by: public ScriptValue {
public:
inline ScriptRule_sort_order_by(const ScriptValueP& order_by) : order_by(order_by) {}
virtual ScriptType type() const { return SCRIPT_FUNCTION; }
virtual String typeName() const { return _("sort_rule"); }
virtual ScriptValueP eval(Context& ctx) const {
SCRIPT_PARAM(ScriptValueP, input);
return sort_script(ctx, input, *order_by);
}
private:
ScriptValueP order_by;
};
// Sort a string alphabetically
class ScriptRule_sort: public ScriptValue {
public:
virtual ScriptType type() const { return SCRIPT_FUNCTION; }
virtual String typeName() const { return _("sort_rule"); }
virtual ScriptValueP eval(Context& ctx) const {
SCRIPT_PARAM(String, input);
sort(input.begin(), input.end());
SCRIPT_RETURN(input);
}
private:
ScriptValueP order_by;
};
SCRIPT_FUNCTION(sort_rule) {
SCRIPT_OPTIONAL_PARAM(String, order) {
return new_intrusive1<ScriptRule_sort_order >(order);
}
SCRIPT_OPTIONAL_PARAM(ScriptValueP, order_by) {
return new_intrusive1<ScriptRule_sort_order_by>(order_by);
} else {
return new_intrusive <ScriptRule_sort >();
}
}
SCRIPT_FUNCTION(sort) {
SCRIPT_OPTIONAL_PARAM(String, order) {
return ScriptRule_sort_order (order ).eval(ctx);
}
SCRIPT_OPTIONAL_PARAM(ScriptValueP, order_by) {
return ScriptRule_sort_order_by(order_by).eval(ctx);
} else {
return ScriptRule_sort ( ).eval(ctx);
}
}
// ----------------------------------------------------------------------------- : Init // ----------------------------------------------------------------------------- : Init
......
...@@ -7,10 +7,116 @@ ...@@ -7,10 +7,116 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <script/functions/functions.hpp> #include <script/functions/functions.hpp>
#include <script/functions/util.hpp>
#include <util/tagged_string.hpp>
// ----------------------------------------------------------------------------- : Numbers // ----------------------------------------------------------------------------- : Numbers
/// Write a number using words, for example 23 -> "twenty-three"
String english_number(int i) {
switch (i) {
case 0: return _("zero");
case 1: return _("one");
case 2: return _("two");
case 3: return _("three");
case 4: return _("four");
case 5: return _("five");
case 6: return _("six");
case 7: return _("seven");
case 8: return _("eight");
case 9: return _("nine");
case 10: return _("ten");
case 11: return _("eleven");
case 12: return _("twelve");
case 13: return _("thirteen");
case 15: return _("fifteen");
case 18: return _("eighteen");
case 20: return _("twenty");
case 30: return _("thirty");
case 50: return _("fifty");
case 80: return _("eighty");
default: {
if (i < 0 || i >= 100) {
// number too large, keep as digits
return (String() << i);
} else if (i < 20) {
return english_number(i%10) + english_number(10);
} else if (i % 10 == 0) {
return english_number(i/10) + _("ty");
} else {
// <a>ty-<b>
return english_number(i/10*10) + _("-") + english_number(i%10);
}
}
}
}
SCRIPT_FUNCTION(english_number) {
SCRIPT_PARAM(int, input);
SCRIPT_RETURN(english_number(input));
}
SCRIPT_FUNCTION(english_number_a) {
SCRIPT_PARAM(int, input);
if (input == 1) {
SCRIPT_RETURN(_("a"));
} else {
SCRIPT_RETURN(english_number(input));
}
}
// ----------------------------------------------------------------------------- : A/an
// ----------------------------------------------------------------------------- : Singular/plural
// ----------------------------------------------------------------------------- : Hints
// insert a hint, <hint-1> for singular, <hint-2> otherwise
SCRIPT_FUNCTION(plural_hint) {
SCRIPT_PARAM(int, input);
SCRIPT_RETURN(input == 1 ? _("<hint-1>") : _("<hint-2>"));
}
/// Process english hints in the input string
/** Hints have the following meaning:
* - "<hint-1>xxx(yyy)zzz" ---> "xxxzzz" (singular)
* - "<hint-2>xxx(yyy)zzz" ---> "xxxyyyzzz" (plural)
* - "[^., ]a <hint-v>[aeiou]" ---> "\1 an \2" (articla 'an', case insensitive)
* - "<hint-?>" ---> "" (remove <hint>s afterwards)
*
* Note: there is no close tags for hints
*/
String process_english_hints(const String& str) {
String ret; ret.reserve(str.size());
int singplur = 0; // 1 for singular, 2 for plural
for (size_t i = 0 ; i < str.size() ; ) {
Char c = str.GetChar(i);
if (i + 6 < str.size() && is_substr(str, i, _("<hint-"))) {
Char h = str.GetChar(i + 6); // hint code
if (h == _('1')) {
singplur = 1;
} else if (h == _('2')) {
singplur = 2;
} else if (h == _('v')) {
// TODO
}
i = skip_tag(str, i);
} else if (c == _('(') && singplur) {
// singular -> drop (...), plural -> keep it
// TODO
} else {
ret += c;
++i;
}
}
return ret; // TODO
}
// ----------------------------------------------------------------------------- : Init // ----------------------------------------------------------------------------- : Init
void init_script_english_functions(Context& ctx) { void init_script_english_functions(Context& ctx) {
ctx.setVariable(_("english number"), script_english_number);
ctx.setVariable(_("english number a"), script_english_number_a);
} }
...@@ -7,10 +7,226 @@ ...@@ -7,10 +7,226 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <script/functions/functions.hpp> #include <script/functions/functions.hpp>
#include <script/functions/util.hpp>
#include <data/symbol_font.hpp>
#include <util/tagged_string.hpp>
#include <util/error.hpp>
// ----------------------------------------------------------------------------- : // ----------------------------------------------------------------------------- : HTML
// An HTML tag
struct Tag {
Tag(const Char* open_tag, const Char* close_tag)
: open_tag(open_tag), close_tag(close_tag), opened(0)
{}
const Char* open_tag; ///< The tags to insert in HTML "<tag>"
const Char* close_tag; ///< The tags to insert in HTML "</tag>"
int opened; ///< How often is the tag opened in the input?
/// Write an open or close tag to a string if needed
void write(String& ret, bool close) {
if (close) {
if (--opened == 0) {
ret += close_tag;
}
} else {
if (++opened == 1) {
ret += open_tag;
}
}
}
};
// A tag, or a close tag
struct NegTag {
Tag* tag;
bool neg; // a close tag instead of an open tag
NegTag(Tag* tag, bool neg) : tag(tag), neg(neg) {}
};
DECLARE_TYPEOF_COLLECTION(NegTag);
/// A stack of opened HTML tags
class TagStack {
public:
void open(String& ret, Tag& tag) {
add(ret, NegTag(&tag, false));
}
void close(String& ret, Tag& tag) {
add(ret, NegTag(&tag, true));
}
// Close all tags, should be called at end of input
void close_all(String& ret) {
pending_tags.clear();
while (!tags.empty()) {
tags.back()->write(ret, true);
tags.pop_back();
}
}
// Write all pending tags, should be called before non-tag output
void write_pending_tags(String& ret) {
FOR_EACH(t, pending_tags) {
t.tag->write(ret, t.neg);
if (!t.neg) tags.push_back(t.tag);
}
pending_tags.clear();
}
private:
vector<Tag*> tags; ///< Tags opened in the html output
vector<NegTag> pending_tags; ///< Tags opened in the tagged string, but not (yet) in the output
void add(String& ret, const NegTag& tag) {
// Cancel out with pending tag?
for (size_t i = pending_tags.size() - 1 ; i >= 0 ; --i) {
if (pending_tags[i].tag == tag.tag) {
if (pending_tags[i].neg != tag.neg) {
pending_tags.erase(pending_tags.begin() + i);
return;
} else {
break; // look no further
}
}
}
// Cancel out with existing tag?
if (tag.neg) {
for (size_t i = tags.size() - 1 ; i >= 0 ; --i) {
if (tags[i] == tag.tag) {
// cancel out with existing tag i, e.g. <b>:
// situation was <a><b><c>text
// situation will become <a><b><c>text</c></b><c>
vector<NegTag> reopen;
for (size_t j = tags.size() - 1 ; j > i ; --j) {
pending_tags.push_back(NegTag(tags[j], true)); // close tag, top down
tags.pop_back();
}
pending_tags.push_back(tag); // now close tag i
for (size_t j = i + 1 ; j < tags.size() ; ++j) {
pending_tags.push_back(NegTag(tags[j], false)); // reopen later, bottom up
tags.pop_back();
}
tags.resize(i);
return;
}
}
}
// Just insert normally
pending_tags.push_back(tag);
}
};
String symbols_to_html(const String& str, const SymbolFontP& symbol_font) {
return str; // TODO
}
String to_html(const String& str_in, const SymbolFontP& symbol_font) {
String str = remove_tag_contents(str,_("<sep-soft"));
String ret;
Tag bold (_("<b>"), _("</b>")),
italic(_("<i>"), _("</i>")),
symbol(_("<span class=\"symbol\">"), _("</span>"));
TagStack tags;
String symbols;
for (size_t i = 0 ; i < str.size() ; ) {
Char c = str.GetChar(i);
if (c == _('<')) {
++i;
if (is_substr(str, i, _("b"))) {
tags.open (ret, bold);
} else if (is_substr(str, i, _("/b"))) {
tags.close(ret, bold);
} else if (is_substr(str, i, _("i"))) {
tags.open (ret, italic);
} else if (is_substr(str, i, _("/i"))) {
tags.close(ret, italic);
} else if (is_substr(str, i, _("sym"))) {
tags.close(ret, symbol);
} else if (is_substr(str, i, _("/sym"))) {
if (!symbols.empty()) {
// write symbols in a special way
tags.write_pending_tags(ret);
ret += symbols_to_html(symbols, symbol_font);
symbols.clear();
}
tags.close(ret, symbol);
}
i = skip_tag(str, i-1);
} else {
// normal character
tags.write_pending_tags(ret);
++i;
if (symbol.opened > 0 && symbol_font) {
symbols += c; // write as symbols instead
} else {
if (c == _('\1')) { // escape <
ret += _("&lt;");
} else if (c == _('&')) { // escape &
ret += _("&amp;");
} else if (c >= 0x80) { // escape non ascii
ret += String(_("&#")) << (int)c << _(';');
} else {
ret += c;
}
}
}
}
// end of input
if (!symbols.empty()) {
tags.write_pending_tags(ret);
ret += symbols_to_html(symbols, symbol_font);
symbols.clear();
}
tags.close_all(ret);
return ret;
}
// convert a tagged string to html
SCRIPT_FUNCTION(to_html) {
SCRIPT_PARAM(String, input);
SymbolFontP symbol_font; // TODO
SCRIPT_RETURN(to_html(input, symbol_font));
}
// ----------------------------------------------------------------------------- : Text
// convert a tagged string to plain text
SCRIPT_FUNCTION(to_text) {
SCRIPT_PARAM(String, input);
SCRIPT_RETURN(untag_hide_sep(input));
}
// ----------------------------------------------------------------------------- : Files
// copy from source package -> destination package, return new filename (relative)
SCRIPT_FUNCTION(copy_file) {
throw InternalError(_("TODO: copy_file")); // TODO
}
// write a file to the destination package.
// if 'filename' is not set, writes to the 'main' output file.
SCRIPT_FUNCTION(write_file) {
throw InternalError(_("TODO: write_file")); // TODO
}
// write an ImageValue to a new file, return the filename
// if the image was not written, return nil
// TODO: write a ScriptImage?
SCRIPT_FUNCTION(image_to_file) {
throw InternalError(_("TODO: image_to_file")); // TODO
}
// render a card, and write the image to a file
SCRIPT_FUNCTION(render_to_file) {
throw InternalError(_("TODO: render_to_file")); // TODO
}
// ----------------------------------------------------------------------------- : Init // ----------------------------------------------------------------------------- : Init
void init_script_export_functions(Context& ctx) { void init_script_export_functions(Context& ctx) {
ctx.setVariable(_("to html"), script_to_html);
ctx.setVariable(_("to text"), script_to_text);
ctx.setVariable(_("copy file"), script_copy_file);
ctx.setVariable(_("write file"), script_write_file);
ctx.setVariable(_("image to file"), script_image_to_file);
ctx.setVariable(_("write image"), script_image_to_file);
ctx.setVariable(_("render to file"), script_render_to_file);
} }
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <util/error.hpp> #include <util/error.hpp>
#include <script/to_value.hpp> #include <script/to_value.hpp>
#include <script/context.hpp>
// ----------------------------------------------------------------------------- : Functions // ----------------------------------------------------------------------------- : Functions
......
...@@ -62,7 +62,7 @@ class ScriptCollection : public ScriptValue { ...@@ -62,7 +62,7 @@ class ScriptCollection : public ScriptValue {
return ScriptValue::getMember(name); return ScriptValue::getMember(name);
} }
} }
virtual ScriptValueP makeIterator() const { virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const {
return new_intrusive1<ScriptCollectionIterator<Collection> >(value); return new_intrusive1<ScriptCollectionIterator<Collection> >(value);
} }
virtual int itemCount() const { return (int)value->size(); } virtual int itemCount() const { return (int)value->size(); }
...@@ -113,6 +113,23 @@ class ScriptMap : public ScriptValue { ...@@ -113,6 +113,23 @@ class ScriptMap : public ScriptValue {
const Collection* value; const Collection* value;
}; };
// ----------------------------------------------------------------------------- : Collections : from script
/// Script value containing a custom collection, returned from script functions
class ScriptCustomCollection : public ScriptValue {
public:
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
virtual String typeName() const { return _TYPE_("collection"); }
virtual ScriptValueP getMember(const String& name) const;
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
virtual int itemCount() const { return (int)value.size(); }
/// Collections can be compared by comparing pointers
virtual const void* comparePointer() const { return &value; }
/// The collection
vector<ScriptValueP> value;
};
// ----------------------------------------------------------------------------- : Objects // ----------------------------------------------------------------------------- : Objects
/// Number of items in some collection like object, can be overloaded /// Number of items in some collection like object, can be overloaded
...@@ -159,9 +176,9 @@ class ScriptObject : public ScriptValue { ...@@ -159,9 +176,9 @@ class ScriptObject : public ScriptValue {
mark_dependency_member(value, name, dep); mark_dependency_member(value, name, dep);
return getMember(name); return getMember(name);
} }
virtual ScriptValueP makeIterator() const { virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const {
ScriptValueP it = make_iterator(*value); ScriptValueP it = make_iterator(*value);
return it ? it : ScriptValue::makeIterator(); return it ? it : ScriptValue::makeIterator(thisP);
} }
virtual int itemCount() const { virtual int itemCount() const {
int i = item_count(*value); int i = item_count(*value);
......
...@@ -14,16 +14,16 @@ ...@@ -14,16 +14,16 @@
// ----------------------------------------------------------------------------- : ScriptValue // ----------------------------------------------------------------------------- : ScriptValue
// Base cases // Base cases
ScriptValue::operator String() const { return _("[[") + typeName() + _("]]"); } ScriptValue::operator String() const { return _("[[") + typeName() + _("]]"); }
ScriptValue::operator int() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("integer" ))); } ScriptValue::operator int() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("integer" ))); }
ScriptValue::operator double() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("real" ))); } ScriptValue::operator double() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("real" ))); }
ScriptValue::operator Color() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("color" ))); } ScriptValue::operator Color() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("color" ))); }
ScriptValueP ScriptValue::eval(Context&) const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); } ScriptValueP ScriptValue::eval(Context&) const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); }
ScriptValueP ScriptValue::getMember(const String& name) const { throw ScriptError(_ERROR_2_("has no member", typeName(), name)); } ScriptValueP ScriptValue::getMember(const String& name) const { throw ScriptError(_ERROR_2_("has no member", typeName(), name)); }
ScriptValueP ScriptValue::next() { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); } ScriptValueP ScriptValue::next() { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); }
ScriptValueP ScriptValue::makeIterator() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); } ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
int ScriptValue::itemCount() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); } int ScriptValue::itemCount() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
const void* ScriptValue::comparePointer() const { return nullptr; } const void* ScriptValue::comparePointer() const { return nullptr; }
ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&) const { return dependency_dummy; } ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&) const { return dependency_dummy; }
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; } ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
...@@ -236,5 +236,35 @@ class ScriptNil : public ScriptValue { ...@@ -236,5 +236,35 @@ class ScriptNil : public ScriptValue {
/// The preallocated nil value /// The preallocated nil value
ScriptValueP script_nil(new ScriptNil); ScriptValueP script_nil(new ScriptNil);
// ----------------------------------------------------------------------------- : Custom collection
// Iterator over a custom collection
class ScriptCustomCollectionIterator : public ScriptIterator {
public:
ScriptCustomCollectionIterator(const vector<ScriptValueP>* col, ScriptValueP colP)
: pos(0), col(col), colP(colP) {}
virtual ScriptValueP next() {
if (pos < col->size()) {
return to_script(col->at(pos++));
} else {
return ScriptValueP();
}
}
private:
size_t pos;
ScriptValueP colP; // for ownership of the collection
const vector<ScriptValueP>* col;
};
ScriptValueP ScriptCustomCollection::getMember(const String& name) const {
long index;
if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) {
return to_script(value.at(index));
} else {
return ScriptValue::getMember(name);
}
}
ScriptValueP ScriptCustomCollection::makeIterator(const ScriptValueP& thisP) const {
return new_intrusive2<ScriptCustomCollectionIterator>(&value, thisP);
}
// ----------------------------------------------------------------------------- : EOF
...@@ -74,7 +74,8 @@ class ScriptValue : public IntrusivePtrBase { ...@@ -74,7 +74,8 @@ class ScriptValue : public IntrusivePtrBase {
virtual ScriptValueP dependencies(Context&, const Dependency&) const; virtual ScriptValueP dependencies(Context&, const Dependency&) const;
/// Return an iterator for the current collection, an iterator is a value that has next() /// Return an iterator for the current collection, an iterator is a value that has next()
virtual ScriptValueP makeIterator() const; /** thisP can be used to prevent destruction of the collection */
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
/// Return the next item for this iterator, or ScriptValueP() if there is no such item /// Return the next item for this iterator, or ScriptValueP() if there is no such item
virtual ScriptValueP next(); virtual ScriptValueP next();
/// Return the number of items in this value (assuming it is a collection) /// Return the number of items in this value (assuming it is a collection)
......
...@@ -54,9 +54,6 @@ String Package::name() const { ...@@ -54,9 +54,6 @@ String Package::name() const {
else if ( ext == String::npos) return filename.substr(slash+1); else if ( ext == String::npos) return filename.substr(slash+1);
else return filename.substr(slash+1, ext-slash-1); else return filename.substr(slash+1, ext-slash-1);
} }
String Package::fullName() const {
return name();
}
const String& Package::absoluteFilename() const { const String& Package::absoluteFilename() const {
return filename; return filename;
} }
......
...@@ -59,8 +59,6 @@ class Package { ...@@ -59,8 +59,6 @@ class Package {
bool needSaveAs() const; bool needSaveAs() const;
/// Determines the short name of this package: the filename without path or extension /// Determines the short name of this package: the filename without path or extension
String name() const; String name() const;
/// Return the (user friendly) full name of this package, by default equal to name()
virtual String fullName() const;
/// Return the absolute filename of this file /// Return the absolute filename of this file
const String& absoluteFilename() const; const String& absoluteFilename() const;
/// The time this package was last modified /// The time this package was last modified
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <data/stylesheet.hpp> #include <data/stylesheet.hpp>
#include <data/symbol_font.hpp> #include <data/symbol_font.hpp>
#include <data/locale.hpp> #include <data/locale.hpp>
#include <data/export_template.hpp>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
// ----------------------------------------------------------------------------- : IncludePackage // ----------------------------------------------------------------------------- : IncludePackage
...@@ -69,11 +70,12 @@ PackagedP PackageManager::openAny(const String& name) { ...@@ -69,11 +70,12 @@ PackagedP PackageManager::openAny(const String& name) {
return p; return p;
} else { } else {
// load with the right type, based on extension // load with the right type, based on extension
if (fn.GetExt() == _("mse-game")) p = new_shared<Game>(); if (fn.GetExt() == _("mse-game")) p = new_shared<Game>();
else if (fn.GetExt() == _("mse-style")) p = new_shared<StyleSheet>(); else if (fn.GetExt() == _("mse-style")) p = new_shared<StyleSheet>();
else if (fn.GetExt() == _("mse-locale")) p = new_shared<Locale>(); else if (fn.GetExt() == _("mse-locale")) p = new_shared<Locale>();
else if (fn.GetExt() == _("mse-include")) p = new_shared<IncludePackage>(); else if (fn.GetExt() == _("mse-include")) p = new_shared<IncludePackage>();
else if (fn.GetExt() == _("mse-symbol-font")) p = new_shared<SymbolFont>(); else if (fn.GetExt() == _("mse-symbol-font")) p = new_shared<SymbolFont>();
else if (fn.GetExt() == _("mse-export-template")) p = new_shared<ExportTemplate>();
else { else {
throw PackageError(_("Unrecognized package type: '") + fn.GetExt() + _("'\nwhile trying to open: ") + name); throw PackageError(_("Unrecognized package type: '") + fn.GetExt() + _("'\nwhile trying to open: ") + name);
} }
......
...@@ -291,8 +291,9 @@ String remove_tag(const String& str, const String& tag) { ...@@ -291,8 +291,9 @@ String remove_tag(const String& str, const String& tag) {
} }
String remove_tag_exact(const String& str, const String& tag) { String remove_tag_exact(const String& str, const String& tag) {
String ret; ret.reserve(str.size());
size_t start = 0, pos = str.find(tag); size_t start = 0, pos = str.find(tag);
if (pos == String::npos) return str; // no need to copy
String ret; ret.reserve(str.size());
while (pos != String::npos) { while (pos != String::npos) {
ret += str.substr(start, pos - start); // before ret += str.substr(start, pos - start); // before
// next // next
...@@ -305,8 +306,9 @@ String remove_tag_exact(const String& str, const String& tag) { ...@@ -305,8 +306,9 @@ String remove_tag_exact(const String& str, const String& tag) {
} }
String remove_tag_contents(const String& str, const String& tag) { String remove_tag_contents(const String& str, const String& tag) {
String ret; ret.reserve(str.size());
size_t start = 0, pos = str.find(tag); size_t start = 0, pos = str.find(tag);
if (pos == String::npos) return str; // no need to copy
String ret; ret.reserve(str.size());
while (pos != String::npos) { while (pos != String::npos) {
size_t end = match_close_tag(str, pos); size_t end = match_close_tag(str, pos);
if (end == String::npos) return ret; // missing close tag if (end == String::npos) return ret; // missing close tag
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment