Commit eed5eab8 authored by twanvl's avatar twanvl

implemented html export (only for writing the main file, not the write_file functions);

fixed parser bug: (...\n...) was not parsed as a statement separator if the second ... starts with a string or number
parent 8731c101
...@@ -12,7 +12,10 @@ ...@@ -12,7 +12,10 @@
// ----------------------------------------------------------------------------- : Export template, basics // ----------------------------------------------------------------------------- : Export template, basics
ExportTemplate::ExportTemplate() {} ExportTemplate::ExportTemplate()
: create_directory(false)
, file_type(_("HTML files (*.html)|*.html"))
{}
String ExportTemplate::typeNameStatic() { return _("export-template"); } String ExportTemplate::typeNameStatic() { return _("export-template"); }
String ExportTemplate::typeName() const { return _("export-template"); } String ExportTemplate::typeName() const { return _("export-template"); }
...@@ -28,4 +31,6 @@ IMPLEMENT_REFLECTION(ExportTemplate) { ...@@ -28,4 +31,6 @@ IMPLEMENT_REFLECTION(ExportTemplate) {
REFLECT(script); REFLECT(script);
} }
// ----------------------------------------------------------------------------- : // ----------------------------------------------------------------------------- : ExportInfo
IMPLEMENT_DYNAMIC_ARG(ExportInfo*, export_info, nullptr);
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
DECLARE_POINTER_TYPE(Game); DECLARE_POINTER_TYPE(Game);
DECLARE_POINTER_TYPE(Field); DECLARE_POINTER_TYPE(Field);
DECLARE_POINTER_TYPE(Style); DECLARE_POINTER_TYPE(Style);
DECLARE_POINTER_TYPE(ExportTemplate);
// ----------------------------------------------------------------------------- : ExportTemplate // ----------------------------------------------------------------------------- : ExportTemplate
...@@ -26,7 +27,7 @@ class ExportTemplate : public Packaged { ...@@ -26,7 +27,7 @@ class ExportTemplate : public Packaged {
GameP game; ///< Game this template is for GameP game; ///< Game this template is for
String file_type; ///< Type of the created file, in "name|*.ext" format String file_type; ///< Type of the created file, in "name|*.ext" format
bool create_directory; ///< The export creates an entire directory bool create_directory; ///< The export creates a directory for additional data files
vector<FieldP> option_fields; ///< Options for exporting vector<FieldP> option_fields; ///< Options for exporting
IndexMap<FieldP,StyleP> option_style; ///< Style of the options IndexMap<FieldP,StyleP> option_style; ///< Style of the options
OptionalScript script; ///< Export script, for multi file templates and initialization OptionalScript script; ///< Export script, for multi file templates and initialization
...@@ -37,11 +38,17 @@ class ExportTemplate : public Packaged { ...@@ -37,11 +38,17 @@ class ExportTemplate : public Packaged {
DECLARE_REFLECTION(); DECLARE_REFLECTION();
}; };
// ----------------------------------------------------------------------------- : ExportPackage // ----------------------------------------------------------------------------- : ExportInfo
/// A package that is being written to when exporting /// Information that can be used by export functions
class ExportingPackage : public Package { struct ExportInfo {
ExportTemplateP export_template; ///< The export template used
String directory_relative; ///< The directory for storing extra files (or "" if !export->create_directory)
/// This is just the directory name
String directory_absolute; ///< The absolute path of the directory
}; };
DECLARE_DYNAMIC_ARG(ExportInfo*, export_info);
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -38,10 +38,10 @@ class PackageList : public GalleryList { ...@@ -38,10 +38,10 @@ class PackageList : public GalleryList {
/** @pre hasSelection() /** @pre hasSelection()
* Throws if the selection is not of type T */ * Throws if the selection is not of type T */
template <typename T> template <typename T>
intrusive_ptr<T> getSelection() const { intrusive_ptr<T> getSelection(bool load_fully = true) const {
intrusive_ptr<T> ret = dynamic_pointer_cast<T>(packages.at(selection).package); intrusive_ptr<T> ret = dynamic_pointer_cast<T>(packages.at(selection).package);
if (!ret) throw InternalError(_("PackageList: Selected package has the wrong type")); if (!ret) throw InternalError(_("PackageList: Selected package has the wrong type"));
ret->loadFully(); if (load_fully) ret->loadFully();
return ret; return ret;
} }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <data/export_template.hpp> #include <data/export_template.hpp>
#include <util/window_id.hpp> #include <util/window_id.hpp>
#include <util/error.hpp> #include <util/error.hpp>
#include <wx/filename.h>
#include <wx/wfstream.h>
DECLARE_POINTER_TYPE(ExportTemplate); DECLARE_POINTER_TYPE(ExportTemplate);
...@@ -45,17 +47,35 @@ HtmlExportWindow::HtmlExportWindow(Window* parent, const SetP& set) ...@@ -45,17 +47,35 @@ HtmlExportWindow::HtmlExportWindow(Window* parent, const SetP& set)
} }
void HtmlExportWindow::onOk(wxCommandEvent&) { void HtmlExportWindow::onOk(wxCommandEvent&) {
handle_error(Error(_("HTML export is not implemented yet, sorry"))); ExportTemplateP exp = list->getSelection<ExportTemplate>();
/*;//%% // get filename
String name = fileSelector(_("Exort to html"),_(""),_(""),_(""), { String name = wxFileSelector(_TITLE_("save html"),_(""),_(""),_(""),exp->file_type, wxSAVE | wxOVERWRITE_PROMPT);
_("HTML files (*.html)|*.html"), if (name.empty()) return;
wxSAVE | wxOVERWRITE_PROMPT); // export info for script
ExportInfo info;
info.export_template = exp;
WITH_DYNAMIC_ARG(export_info, &info);
// create directory?
if (exp->create_directory) {
wxFileName fn(name);
info.directory_relative = fn.GetName() + _("-files");
fn.SetFullName(info.directory_relative);
info.directory_absolute = fn.GetFullPath();
wxMkDir(info.directory_absolute);
} }
if (!name.empty()) { // run export script
HtmlExportWindow wnd(&this, set, name); Context& ctx = set->getContext();
wnd.showModal(); LocalScope scope(ctx);
ctx.setVariable(_("options"), to_script(&settings.exportOptionsFor(*exp)));
ctx.setVariable(_("directory"), to_script(info.directory_relative));
ScriptValueP result = exp->script.invoke(ctx);
// Save to file
wxFileOutputStream file(name);
{ // TODO: write as image?
// write as string
wxTextOutputStream stream(file);
stream.WriteString(*result);
} }
*/
// Done // Done
EndModal(wxID_OK); EndModal(wxID_OK);
} }
......
...@@ -59,7 +59,7 @@ NewSetWindow::NewSetWindow(Window* parent) ...@@ -59,7 +59,7 @@ NewSetWindow::NewSetWindow(Window* parent)
void NewSetWindow::onGameSelect(wxCommandEvent&) { void NewSetWindow::onGameSelect(wxCommandEvent&) {
wxBusyCursor wait; wxBusyCursor wait;
GameP game = game_list->getSelection<Game>(); GameP game = game_list->getSelection<Game>(false);
handle_pending_errors(); handle_pending_errors();
settings.default_game = game->name(); settings.default_game = game->name();
stylesheet_list->showData<StyleSheet>(game->name() + _("-*")); stylesheet_list->showData<StyleSheet>(game->name() + _("-*"));
...@@ -76,8 +76,8 @@ void NewSetWindow::onGameSelect(wxCommandEvent&) { ...@@ -76,8 +76,8 @@ void NewSetWindow::onGameSelect(wxCommandEvent&) {
void NewSetWindow::onStyleSheetSelect(wxCommandEvent&) { void NewSetWindow::onStyleSheetSelect(wxCommandEvent&) {
// store this as default selection // store this as default selection
GameP game = game_list ->getSelection<Game>(); GameP game = game_list ->getSelection<Game>(false);
StyleSheetP stylesheet = stylesheet_list->getSelection<StyleSheet>(); StyleSheetP stylesheet = stylesheet_list->getSelection<StyleSheet>(false);
handle_pending_errors(); handle_pending_errors();
settings.gameSettingsFor(*game).default_stylesheet = stylesheet->name(); settings.gameSettingsFor(*game).default_stylesheet = stylesheet->name();
UpdateWindowUI(wxUPDATE_UI_RECURSE); UpdateWindowUI(wxUPDATE_UI_RECURSE);
......
...@@ -508,7 +508,9 @@ void SetWindow::onFileReload(wxCommandEvent&) { ...@@ -508,7 +508,9 @@ void SetWindow::onFileReload(wxCommandEvent&) {
String filename = set->absoluteFilename(); String filename = set->absoluteFilename();
if (filename.empty()) return; if (filename.empty()) return;
wxBusyCursor busy; wxBusyCursor busy;
settings.write(); // save settings
packages.destroy(); // unload all packages packages.destroy(); // unload all packages
settings.read(); // reload settings
setSet(import_set(filename)); setSet(import_set(filename));
} }
......
...@@ -91,8 +91,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) { ...@@ -91,8 +91,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
// Loop over a container, push next value or jump // Loop over a container, push next value or jump
case I_LOOP: { case I_LOOP: {
ScriptValueP& it = stack[stack.size() - 2]; // second element of stack ScriptValueP& it = stack[stack.size() - 2]; // second element of stack
assert(dynamic_pointer_cast<ScriptIterator>(it)); // top of stack must be an iterator ScriptValueP val = it->next();
ScriptValueP val = static_pointer_cast<ScriptIterator>(it)->next();
if (val) { if (val) {
stack.push_back(val); stack.push_back(val);
} else { } else {
......
...@@ -57,6 +57,12 @@ class Context { ...@@ -57,6 +57,12 @@ class Context {
/// Get the value of a variable, returns ScriptValue() if it is not set /// Get the value of a variable, returns ScriptValue() if it is not set
ScriptValueP getVariableOpt(const String& name); ScriptValueP getVariableOpt(const String& name);
/// Open a new scope
/** returns the number of shadowed binding before that scope */
size_t openScope();
/// Close a scope, must be passed a value from openScope
void closeScope(size_t scope);
public:// public for FOR_EACH public:// public for FOR_EACH
/// Record of a variable /// Record of a variable
struct Variable { struct Variable {
...@@ -85,11 +91,6 @@ class Context { ...@@ -85,11 +91,6 @@ class Context {
/// Set a variable to a new value (in the current scope) /// Set a variable to a new value (in the current scope)
void setVariable(int name, const ScriptValueP& value); void setVariable(int name, const ScriptValueP& value);
/// Open a new scope
/** returns the number of shadowed binding before that scope */
size_t openScope();
/// Close a scope, must be passed a value from openScope
void closeScope(size_t scope);
/// Return the bindings in the current scope /// Return the bindings in the current scope
void getBindings(size_t scope, vector<Binding>&); void getBindings(size_t scope, vector<Binding>&);
/// Remove all bindings made in the current scope /// Remove all bindings made in the current scope
...@@ -98,5 +99,15 @@ class Context { ...@@ -98,5 +99,15 @@ class Context {
void makeObject(size_t n); void makeObject(size_t n);
}; };
/// A class that creates a local scope
class LocalScope {
public:
inline LocalScope(Context& ctx) : ctx(ctx), scope(ctx.openScope()) {}
inline ~LocalScope() { ctx.closeScope(scope); }
private:
Context& ctx;
size_t scope;
};
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -220,8 +220,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script) ...@@ -220,8 +220,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script)
// Loop over a container, push next value or jump (almost as normal) // Loop over a container, push next value or jump (almost as normal)
case I_LOOP: { case I_LOOP: {
ScriptValueP& it = stack[stack.size() - 2]; // second element of stack ScriptValueP& it = stack[stack.size() - 2]; // second element of stack
assert(dynamic_pointer_cast<ScriptIterator>(it)); // top of stack must be an iterator ScriptValueP val = it->next();
ScriptValueP val = static_pointer_cast<ScriptIterator>(it)->next();
if (val) { if (val) {
it = dependency_dummy; // invalidate iterator, so we loop only once it = dependency_dummy; // invalidate iterator, so we loop only once
stack.push_back(val); stack.push_back(val);
......
...@@ -206,7 +206,7 @@ ScriptValueP sort_script(Context& ctx, const ScriptValueP& list, ScriptValue& or ...@@ -206,7 +206,7 @@ ScriptValueP sort_script(Context& ctx, const ScriptValueP& list, ScriptValue& or
sort(s.begin(), s.end()); sort(s.begin(), s.end());
SCRIPT_RETURN(s); SCRIPT_RETURN(s);
} else { } else {
// are we sorting a set // are we sorting a set?
ScriptObject<Set*>* set = dynamic_cast<ScriptObject<Set*>*>(list.get()); ScriptObject<Set*>* set = dynamic_cast<ScriptObject<Set*>*>(list.get());
// sort a collection // sort a collection
vector<pair<String,ScriptValueP> > values; vector<pair<String,ScriptValueP> > values;
...@@ -254,6 +254,22 @@ SCRIPT_FUNCTION(number_of_items) { ...@@ -254,6 +254,22 @@ SCRIPT_FUNCTION(number_of_items) {
SCRIPT_RETURN(ctx.getVariable(_("in"))->itemCount()); SCRIPT_RETURN(ctx.getVariable(_("in"))->itemCount());
} }
// filtering items from a list
SCRIPT_FUNCTION(filter_list) {
SCRIPT_PARAM(ScriptValueP, input);
SCRIPT_PARAM(ScriptValueP, filter);
// filter a collection
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection());
ScriptValueP it = input->makeIterator(input);
while (ScriptValueP v = it->next()) {
ctx.setVariable(_("input"), v);
if (*filter->eval(ctx)) {
ret->value.push_back(v);
}
}
// TODO : somehow preserve keys
return ret;
}
// ----------------------------------------------------------------------------- : Keywords // ----------------------------------------------------------------------------- : Keywords
...@@ -560,8 +576,11 @@ class ScriptRule_sort_order: public ScriptValue { ...@@ -560,8 +576,11 @@ class ScriptRule_sort_order: public ScriptValue {
virtual ScriptType type() const { return SCRIPT_FUNCTION; } virtual ScriptType type() const { return SCRIPT_FUNCTION; }
virtual String typeName() const { return _("sort_rule"); } virtual String typeName() const { return _("sort_rule"); }
virtual ScriptValueP eval(Context& ctx) const { virtual ScriptValueP eval(Context& ctx) const {
SCRIPT_PARAM(String, input); SCRIPT_PARAM(ScriptValueP, input);
SCRIPT_RETURN(spec_sort(order, input)); if (input->type() == SCRIPT_COLLECTION) {
handle_warning(_("Sorting a collection as a string, this is probably not intended, if it is use 'collection+\"\"' to force conversion"), false);
}
SCRIPT_RETURN(spec_sort(order, input->toString()));
} }
private: private:
String order; String order;
...@@ -585,9 +604,13 @@ class ScriptRule_sort: public ScriptValue { ...@@ -585,9 +604,13 @@ class ScriptRule_sort: public ScriptValue {
virtual ScriptType type() const { return SCRIPT_FUNCTION; } virtual ScriptType type() const { return SCRIPT_FUNCTION; }
virtual String typeName() const { return _("sort_rule"); } virtual String typeName() const { return _("sort_rule"); }
virtual ScriptValueP eval(Context& ctx) const { virtual ScriptValueP eval(Context& ctx) const {
SCRIPT_PARAM(String, input); SCRIPT_PARAM(ScriptValueP, input);
sort(input.begin(), input.end()); if (input->type() == SCRIPT_COLLECTION) {
SCRIPT_RETURN(input); handle_warning(_("Sorting a collection as a string, this is probably not intended, if it is use 'collection+\"\"' to force conversion"), false);
}
String input_str = input->toString();
sort(input_str.begin(), input_str.end());
SCRIPT_RETURN(input_str);
} }
private: private:
ScriptValueP order_by; ScriptValueP order_by;
...@@ -597,7 +620,7 @@ SCRIPT_FUNCTION(sort_rule) { ...@@ -597,7 +620,7 @@ SCRIPT_FUNCTION(sort_rule) {
SCRIPT_OPTIONAL_PARAM(String, order) { SCRIPT_OPTIONAL_PARAM(String, order) {
return new_intrusive1<ScriptRule_sort_order >(order); return new_intrusive1<ScriptRule_sort_order >(order);
} }
SCRIPT_OPTIONAL_PARAM(ScriptValueP, order_by) { SCRIPT_OPTIONAL_PARAM_N(ScriptValueP, _("order by"), order_by) {
return new_intrusive1<ScriptRule_sort_order_by>(order_by); return new_intrusive1<ScriptRule_sort_order_by>(order_by);
} else { } else {
return new_intrusive <ScriptRule_sort >(); return new_intrusive <ScriptRule_sort >();
...@@ -607,7 +630,7 @@ SCRIPT_FUNCTION(sort) { ...@@ -607,7 +630,7 @@ SCRIPT_FUNCTION(sort) {
SCRIPT_OPTIONAL_PARAM(String, order) { SCRIPT_OPTIONAL_PARAM(String, order) {
return ScriptRule_sort_order (order ).eval(ctx); return ScriptRule_sort_order (order ).eval(ctx);
} }
SCRIPT_OPTIONAL_PARAM(ScriptValueP, order_by) { SCRIPT_OPTIONAL_PARAM_N(ScriptValueP, _("order by"), order_by) {
return ScriptRule_sort_order_by(order_by).eval(ctx); return ScriptRule_sort_order_by(order_by).eval(ctx);
} else { } else {
return ScriptRule_sort ( ).eval(ctx); return ScriptRule_sort ( ).eval(ctx);
...@@ -637,6 +660,7 @@ void init_script_basic_functions(Context& ctx) { ...@@ -637,6 +660,7 @@ void init_script_basic_functions(Context& ctx) {
// collection // collection
ctx.setVariable(_("position"), script_position_of); ctx.setVariable(_("position"), script_position_of);
ctx.setVariable(_("number of items"), script_number_of_items); ctx.setVariable(_("number of items"), script_number_of_items);
ctx.setVariable(_("filter list"), script_filter_list);
// keyword // keyword
ctx.setVariable(_("expand keywords"), script_expand_keywords); ctx.setVariable(_("expand keywords"), script_expand_keywords);
ctx.setVariable(_("expand keywords rule"), script_expand_keywords_rule); ctx.setVariable(_("expand keywords rule"), script_expand_keywords_rule);
...@@ -645,6 +669,7 @@ void init_script_basic_functions(Context& ctx) { ...@@ -645,6 +669,7 @@ void init_script_basic_functions(Context& ctx) {
ctx.setVariable(_("filter"), script_filter); ctx.setVariable(_("filter"), script_filter);
ctx.setVariable(_("match"), script_match); ctx.setVariable(_("match"), script_match);
ctx.setVariable(_("sort"), script_sort); ctx.setVariable(_("sort"), script_sort);
ctx.setVariable(_("sort list"), script_sort);
ctx.setVariable(_("replace rule"), script_replace_rule); ctx.setVariable(_("replace rule"), script_replace_rule);
ctx.setVariable(_("filter rule"), script_filter_rule); ctx.setVariable(_("filter rule"), script_filter_rule);
ctx.setVariable(_("match rule"), script_match_rule); ctx.setVariable(_("match rule"), script_match_rule);
......
...@@ -56,7 +56,9 @@ class TagStack { ...@@ -56,7 +56,9 @@ class TagStack {
} }
// Close all tags, should be called at end of input // Close all tags, should be called at end of input
void close_all(String& ret) { void close_all(String& ret) {
pending_tags.clear(); // cancel out tags with pending tags
write_pending_tags(ret);
// close all open tags
while (!tags.empty()) { while (!tags.empty()) {
tags.back()->write(ret, true); tags.back()->write(ret, true);
tags.pop_back(); tags.pop_back();
...@@ -77,7 +79,7 @@ class TagStack { ...@@ -77,7 +79,7 @@ class TagStack {
void add(String& ret, const NegTag& tag) { void add(String& ret, const NegTag& tag) {
// Cancel out with pending tag? // Cancel out with pending tag?
for (size_t i = pending_tags.size() - 1 ; i >= 0 ; --i) { for (int i = (int)pending_tags.size() - 1 ; i >= 0 ; --i) {
if (pending_tags[i].tag == tag.tag) { if (pending_tags[i].tag == tag.tag) {
if (pending_tags[i].neg != tag.neg) { if (pending_tags[i].neg != tag.neg) {
pending_tags.erase(pending_tags.begin() + i); pending_tags.erase(pending_tags.begin() + i);
...@@ -89,18 +91,18 @@ class TagStack { ...@@ -89,18 +91,18 @@ class TagStack {
} }
// Cancel out with existing tag? // Cancel out with existing tag?
if (tag.neg) { if (tag.neg) {
for (size_t i = tags.size() - 1 ; i >= 0 ; --i) { for (int i = (int)tags.size() - 1 ; i >= 0 ; --i) {
if (tags[i] == tag.tag) { if (tags[i] == tag.tag) {
// cancel out with existing tag i, e.g. <b>: // cancel out with existing tag i, e.g. <b>:
// situation was <a><b><c>text // situation was <a><b><c>text
// situation will become <a><b><c>text</c></b><c> // situation will become <a><b><c>text</c></b><c>
vector<NegTag> reopen; vector<NegTag> reopen;
for (size_t j = tags.size() - 1 ; j > i ; --j) { for (int j = (int)tags.size() - 1 ; j > i ; --j) {
pending_tags.push_back(NegTag(tags[j], true)); // close tag, top down pending_tags.push_back(NegTag(tags[j], true)); // close tag, top down
tags.pop_back(); tags.pop_back();
} }
pending_tags.push_back(tag); // now close tag i pending_tags.push_back(tag); // now close tag i
for (size_t j = i + 1 ; j < tags.size() ; ++j) { for (int j = i + 1 ; j < (int)tags.size() ; ++j) {
pending_tags.push_back(NegTag(tags[j], false)); // reopen later, bottom up pending_tags.push_back(NegTag(tags[j], false)); // reopen later, bottom up
tags.pop_back(); tags.pop_back();
} }
...@@ -119,7 +121,7 @@ String symbols_to_html(const String& str, const SymbolFontP& symbol_font) { ...@@ -119,7 +121,7 @@ String symbols_to_html(const String& str, const SymbolFontP& symbol_font) {
} }
String to_html(const String& str_in, const SymbolFontP& symbol_font) { String to_html(const String& str_in, const SymbolFontP& symbol_font) {
String str = remove_tag_contents(str,_("<sep-soft")); String str = remove_tag_contents(str_in,_("<sep-soft"));
String ret; String ret;
Tag bold (_("<b>"), _("</b>")), Tag bold (_("<b>"), _("</b>")),
italic(_("<i>"), _("</i>")), italic(_("<i>"), _("</i>")),
...@@ -163,6 +165,8 @@ String to_html(const String& str_in, const SymbolFontP& symbol_font) { ...@@ -163,6 +165,8 @@ String to_html(const String& str_in, const SymbolFontP& symbol_font) {
ret += _("&amp;"); ret += _("&amp;");
} else if (c >= 0x80) { // escape non ascii } else if (c >= 0x80) { // escape non ascii
ret += String(_("&#")) << (int)c << _(';'); ret += String(_("&#")) << (int)c << _(';');
} else if (c == _('\n')) {
ret += _("<br>\n");
} else { } else {
ret += c; ret += c;
} }
......
...@@ -524,7 +524,8 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc ...@@ -524,7 +524,8 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
// without left recursion: expr = expr (oper expr)* // without left recursion: expr = expr (oper expr)*
while (true) { while (true) {
const Token& token = input.read(); const Token& token = input.read();
if (token != TOK_OPER && token != TOK_NAME && token!=TOK_LPAREN) { if (token != TOK_OPER && token != TOK_NAME && token!=TOK_LPAREN &&
!((token == TOK_STRING || token == TOK_INT || token == TOK_DOUBLE) && minPrec <= PREC_NEWLINE && token.newline)) {
// not an operator-like token // not an operator-like token
input.putBack(); input.putBack();
break; break;
......
...@@ -172,7 +172,7 @@ class ScriptString : public ScriptValue { ...@@ -172,7 +172,7 @@ class ScriptString : public ScriptValue {
public: public:
ScriptString(const String& v) : value(v) {} ScriptString(const String& v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_STRING; } virtual ScriptType type() const { return SCRIPT_STRING; }
virtual String typeName() const { return _TYPE_("string"); } virtual String typeName() const { return _TYPE_("string") + _(" (\"") + (value.size() < 30 ? value : value.substr(0,30) + _("...")) + _("\")"); }
virtual operator String() const { return value; } virtual operator String() const { return value; }
virtual operator double() const { virtual operator double() const {
double d; double d;
...@@ -209,7 +209,7 @@ class ScriptString : public ScriptValue { ...@@ -209,7 +209,7 @@ class ScriptString : public ScriptValue {
if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) { if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) {
return to_script(String(1,value[index])); return to_script(String(1,value[index]));
} else { } else {
throw ScriptError(_ERROR_2_("has no member value", value, name)); return delayError(_ERROR_2_("has no member value", value, name));
} }
} }
private: private:
......
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