diff --git a/src/data/field.cpp b/src/data/field.cpp index 1156579c..b0d8828f 100644 --- a/src/data/field.cpp +++ b/src/data/field.cpp @@ -50,7 +50,7 @@ IMPLEMENT_REFLECTION(Field) { REFLECT(type); } REFLECT(name); - REFLECT_IF_READING name = cannocial_name_form(name); + REFLECT_IF_READING name = canonical_name_form(name); REFLECT(description); REFLECT_N("icon", icon_filename); REFLECT(editable); diff --git a/src/gui/value/choice.cpp b/src/gui/value/choice.cpp index a8fdffe5..2f651147 100644 --- a/src/gui/value/choice.cpp +++ b/src/gui/value/choice.cpp @@ -46,7 +46,7 @@ ChoiceThumbnailRequest::ChoiceThumbnailRequest(ValueViewer* viewer, int id, bool Image ChoiceThumbnailRequest::generate() { ChoiceStyle& s = style(); - String name = cannocial_name_form(s.field().choices->choiceName(id)); + String name = canonical_name_form(s.field().choices->choiceName(id)); ScriptableImage& img = s.choice_images[name]; return img.isReady() ? img.generate(GeneratedImage::Options(16,16, &viewer().getStylePackage(), &viewer().getLocalPackage(), ASPECT_BORDER, true)) @@ -181,7 +181,7 @@ void DropDownChoiceListBase::generateThumbnailImages() { if (style().choice_images.empty() && style().image.isScripted()) { for (int i = 0 ; i < end ; ++i) { try { - String name = cannocial_name_form(field().choices->choiceName(i)); + String name = canonical_name_form(field().choices->choiceName(i)); ctx.setVariable(_("input"), to_script(name)); GeneratedImageP img = image_from_script(style().image.getValidScriptP()->eval(ctx)); style().choice_images.insert(make_pair(name, ScriptableImage(img))); @@ -197,7 +197,7 @@ void DropDownChoiceListBase::generateThumbnailImages() { if (i >= image_count || status != THUMB_OK) { // update image ChoiceStyle& s = style(); - String name = cannocial_name_form(s.field().choices->choiceName(i)); + String name = canonical_name_form(s.field().choices->choiceName(i)); ScriptableImage& img = s.choice_images[name]; if (!img.update(ctx) && status == THUMB_CHANGED) { status = THUMB_OK; // no need to rebuild diff --git a/src/render/value/multiple_choice.cpp b/src/render/value/multiple_choice.cpp index ecb94173..59e627e5 100644 --- a/src/render/value/multiple_choice.cpp +++ b/src/render/value/multiple_choice.cpp @@ -58,7 +58,7 @@ void MultipleChoiceValueViewer::drawChoice(RotatedDC& dc, RealPoint& pos, const size = add_horizontal(size, RealSize(14,16)); } if (style().render_style & RENDER_IMAGE) { - map::iterator it = style().choice_images.find(cannocial_name_form(choice)); + map::iterator it = style().choice_images.find(canonical_name_form(choice)); if (it != style().choice_images.end() && it->second.isReady()) { // TODO: caching GeneratedImage::Options options(0,0, &getStylePackage(), &getLocalPackage()); diff --git a/src/script/functions/export.cpp b/src/script/functions/export.cpp index 6983cbba..b62609b6 100644 --- a/src/script/functions/export.cpp +++ b/src/script/functions/export.cpp @@ -59,12 +59,12 @@ String get_export_full_path(String& rel_name) { // ----------------------------------------------------------------------------- : 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 "" +// 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 "" const Char* close_tag; ///< The tags to insert in HTML "" int opened; ///< How often is the tag opened in the input? /// Write an open or close tag to a string if needed @@ -80,198 +80,198 @@ struct 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) { - // cancel out tags with pending tags - write_pending_tags(ret); - // close all open tags - 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 tags; ///< Tags opened in the html output - vector 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 (int i = (int)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 (int i = (int)tags.size() - 1 ; i >= 0 ; --i) { - if (tags[i] == tag.tag) { - // cancel out with existing tag i, e.g. : - // situation was text - // situation will become text - vector reopen; - for (int j = (int)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 (int j = i + 1 ; j < (int)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); - } -}; - -// html-escape a string -String html_escape(const String& str) { - String ret; - FOR_EACH_CONST(c, str) { - if (c == _('\1') || c == _('<')) { // escape < - ret += _("<"); - } else if (c == _('>')) { // escape > - ret += _(">"); - } else if (c == _('&')) { // escape & - ret += _("&"); - } else if (c == _('\'')) { // escape ' - ret += _("'"); - } else if (c == _('\"')) { // escape " - ret += _("""); - } else if (c >= 0x80) { // escape non ascii - ret += String(_("&#")) << (int)c << _(';'); - } else { - ret += c; - } - } - return ret; + +// 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) { + // cancel out tags with pending tags + write_pending_tags(ret); + // close all open tags + 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 tags; ///< Tags opened in the html output + vector 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 (int i = (int)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 (int i = (int)tags.size() - 1 ; i >= 0 ; --i) { + if (tags[i] == tag.tag) { + // cancel out with existing tag i, e.g. : + // situation was text + // situation will become text + vector reopen; + for (int j = (int)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 (int j = i + 1 ; j < (int)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); + } +}; + +// html-escape a string +String html_escape(const String& str) { + String ret; + FOR_EACH_CONST(c, str) { + if (c == _('\1') || c == _('<')) { // escape < + ret += _("<"); + } else if (c == _('>')) { // escape > + ret += _(">"); + } else if (c == _('&')) { // escape & + ret += _("&"); + } else if (c == _('\'')) { // escape ' + ret += _("'"); + } else if (c == _('\"')) { // escape " + ret += _("""); + } else if (c >= 0x80) { // escape non ascii + ret += String(_("&#")) << (int)c << _(';'); + } else { + ret += c; + } + } + return ret; } - -// write symbols to html -String symbols_to_html(const String& str, SymbolFont& symbol_font, double size) { - guard_export_info(_("symbols_to_html")); - ExportInfo& ei = *export_info(); - vector symbols; - symbol_font.split(str, symbols); - String html; - FOR_EACH(sym, symbols) { - String filename = symbol_font.name() + _("-") + clean_filename(sym.text) + _(".png"); - map::iterator it = ei.exported_images.find(filename); - if (it == ei.exported_images.end()) { - // save symbol image - Image img = symbol_font.getImage(size, sym); + +// write symbols to html +String symbols_to_html(const String& str, SymbolFont& symbol_font, double size) { + guard_export_info(_("symbols_to_html")); + ExportInfo& ei = *export_info(); + vector symbols; + symbol_font.split(str, symbols); + String html; + FOR_EACH(sym, symbols) { + String filename = symbol_font.name() + _("-") + clean_filename(sym.text) + _(".png"); + map::iterator it = ei.exported_images.find(filename); + if (it == ei.exported_images.end()) { + // save symbol image + Image img = symbol_font.getImage(size, sym); wxFileName fn; fn.SetPath(ei.directory_absolute); - fn.SetFullName(filename); - img.SaveFile(fn.GetFullPath()); - it = ei.exported_images.insert(make_pair(filename, wxSize(img.GetWidth(), img.GetHeight()))).first; - } - html += _("") + html_escape(sym.text)
-		     +  _(""); - } - return html; -} - -String to_html(const String& str_in, const SymbolFontP& symbol_font, double symbol_size) { - String str = remove_tag_contents(str_in,_(""), _("")), - italic(_(""), _("")), - symbol(_(""), _("")); - 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.open (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, symbol_size); - 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 { - c = untag_char(c); - if (c == _('<')) { // escape < - ret += _("<"); - } else if (c == _('&')) { // escape & - ret += _("&"); - } else if (c >= 0x80) { // escape non ascii - ret += String(_("&#")) << (int)c << _(';'); - } else if (c == _('\n')) { - ret += _("
\n"); - } else { - ret += c; - } - } - } - } - // end of input - if (!symbols.empty()) { - tags.write_pending_tags(ret); - ret += symbols_to_html(symbols, *symbol_font, symbol_size); - symbols.clear(); - } - tags.close_all(ret); - return ret; + fn.SetFullName(filename); + img.SaveFile(fn.GetFullPath()); + it = ei.exported_images.insert(make_pair(filename, wxSize(img.GetWidth(), img.GetHeight()))).first; + } + html += _("") + html_escape(sym.text)
+		     +  _(""); + } + return html; +} + +String to_html(const String& str_in, const SymbolFontP& symbol_font, double symbol_size) { + String str = remove_tag_contents(str_in,_(""), _("
")), + italic(_(""), _("")), + symbol(_(""), _("")); + 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.open (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, symbol_size); + 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 { + c = untag_char(c); + if (c == _('<')) { // escape < + ret += _("<"); + } else if (c == _('&')) { // escape & + ret += _("&"); + } else if (c >= 0x80) { // escape non ascii + ret += String(_("&#")) << (int)c << _(';'); + } else if (c == _('\n')) { + ret += _("
\n"); + } else { + ret += c; + } + } + } + } + // end of input + if (!symbols.empty()) { + tags.write_pending_tags(ret); + ret += symbols_to_html(symbols, *symbol_font, symbol_size); + symbols.clear(); + } + tags.close_all(ret); + return ret; } // convert a tagged string to html @@ -300,57 +300,57 @@ SCRIPT_FUNCTION(symbols_to_html) { } // ----------------------------------------------------------------------------- : BB Code - -String to_bbcode(const String& str_in) { - String str = remove_tag_contents(str_in,_(" 0 && symbol_font) { -// symbols += c; // write as symbols instead -// } else { - ret += untag_char(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; + +String to_bbcode(const String& str_in) { + String str = remove_tag_contents(str_in,_(" 0 && symbol_font) { +// symbols += c; // write as symbols instead +// } else { + ret += untag_char(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 BBCode @@ -443,6 +443,12 @@ SCRIPT_FUNCTION(write_set_file) { } +SCRIPT_FUNCTION(sanitize) { + SCRIPT_PARAM_C(String, input); + //TODO + SCRIPT_RETURN(input); +} + // ----------------------------------------------------------------------------- : Init void init_script_export_functions(Context& ctx) { @@ -453,4 +459,5 @@ void init_script_export_functions(Context& ctx) { ctx.setVariable(_("write text file"), script_write_text_file); ctx.setVariable(_("write image file"), script_write_image_file); ctx.setVariable(_("write set file"), script_write_set_file); + ctx.setVariable(_("sanitize"), script_sanitize); } diff --git a/src/script/parser.cpp b/src/script/parser.cpp index f699ae90..c6bc660e 100644 --- a/src/script/parser.cpp +++ b/src/script/parser.cpp @@ -210,7 +210,7 @@ void TokenIterator::readToken() { // name, or a number after a . token, as in array.0 size_t start = pos - 1; while (pos < input.size() && isAlnum_(input.GetChar(pos))) ++pos; - addToken(TOK_NAME, cannocial_name_form(input.substr(start, pos-start)), start); // convert name to cannocial form + addToken(TOK_NAME, canonical_name_form(input.substr(start, pos-start)), start); // convert name to cannocial form } else if (isDigit(c)) { // number size_t start = pos - 1; diff --git a/src/script/script.cpp b/src/script/script.cpp index d4529b05..e78ad8a9 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -27,7 +27,7 @@ Variable string_to_variable(const String& s) { if (it == variables.end()) { #ifdef _DEBUG variable_names.push_back(s); - assert(s == cannocial_name_form(s)); // only use cannocial names + assert(s == canonical_name_form(s)); // only use cannocial names #endif Variable v = (Variable)variables.size(); variables.insert(make_pair(s,v)); diff --git a/src/util/io/reader.cpp b/src/util/io/reader.cpp index 23743d80..87c6c3bc 100644 --- a/src/util/io/reader.cpp +++ b/src/util/io/reader.cpp @@ -257,7 +257,7 @@ void Reader::readLine(bool in_string) { indent += 1; } } - key = cannocial_name_form(trim(key)); + key = canonical_name_form(trim(key)); value = pos == String::npos ? _("") : trim_left(line.substr(pos+1)); if (key.empty() && pos!=String::npos) key = _(" "); // we don't want an empty key if there was a colon } diff --git a/src/util/io/writer.cpp b/src/util/io/writer.cpp index 848b5130..2c7db5e7 100644 --- a/src/util/io/writer.cpp +++ b/src/util/io/writer.cpp @@ -51,7 +51,7 @@ void Writer::writePending() { } indentation += 1; writeIndentation(); - writeUTF8(stream, cannocial_name_form(pending_opened[i])); + writeUTF8(stream, canonical_name_form(pending_opened[i])); } pending_opened.clear(); } diff --git a/src/util/string.cpp b/src/util/string.cpp index 16d11277..b6f1e647 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -178,7 +178,7 @@ String capitalize_sentence(const String& s) { return ret; } -String cannocial_name_form(const String& str) { +String canonical_name_form(const String& str) { String ret; ret.reserve(str.size()); bool leading = true; diff --git a/src/util/string.hpp b/src/util/string.hpp index 1615bfd4..bd80f554 100644 --- a/src/util/string.hpp +++ b/src/util/string.hpp @@ -152,12 +152,12 @@ String capitalize(const String&); /** for use in dialogs */ String capitalize_sentence(const String&); -/// Convert a field name to cannocial form +/// Convert a field name to canonical form /** - lower case and ' ' instead of '_'. * - non alphanumeric characters are droped * - "camalCase" is converted to words "camel case" (TODO) */ -String cannocial_name_form(const String&); +String canonical_name_form(const String&); /// Returns the singular form of a string /** Used for reflection, for example "vector apples" is written with keys