diff --git a/src/data/action/value.cpp b/src/data/action/value.cpp index 5101587f..ed1e9d57 100644 --- a/src/data/action/value.cpp +++ b/src/data/action/value.cpp @@ -140,8 +140,7 @@ TextValueAction* toggle_format_action(const TextValueP& value, const String& tag String new_value; const String& str = value->value(); // Are we inside the tag we are toggling? - size_t tagpos = in_tag(str, _("<") + tag, start_i, end_i); - if (tagpos == String::npos) { + if (!is_in_tag(str, _("<") + tag, start_i, end_i)) { // we are not inside this tag, add it new_value = str.substr(0, start_i); new_value += _("<") + tag + _(">"); diff --git a/src/gui/value/text.cpp b/src/gui/value/text.cpp index 4319dff4..122e70b3 100644 --- a/src/gui/value/text.cpp +++ b/src/gui/value/text.cpp @@ -809,7 +809,7 @@ bool TextValueEditor::canFormat(int type) const { return !style().always_symbol && style().allow_formating && style().symbol_font.valid(); case ID_FORMAT_REMINDER: return !style().always_symbol && style().allow_formating && - in_tag(value().value(), _(" tags should prevent spellcheck return true; diff --git a/src/util/tagged_string.cpp b/src/util/tagged_string.cpp index 44f4779d..e7411914 100644 --- a/src/util/tagged_string.cpp +++ b/src/util/tagged_string.cpp @@ -148,12 +148,32 @@ size_t last_start_tag_before(const String& str, const String& tag, size_t start) } size_t in_tag(const String& str, const String& tag, size_t start, size_t end) { - if (start > end) swap(start, end); - size_t pos = last_start_tag_before(str, tag, start); - if (pos == String::npos) return String::npos; // no tag found before start - size_t posE = match_close_tag(str, pos); - if (posE < end) return String::npos; // the tag ends before end - return pos; + size_t last_start = String::npos; + size_t size = str.size(); + int taglevel = 0; + end = min(end,size); + for (size_t pos = 0 ; pos < end ; ) { + Char c = str.GetChar(pos); + if (c == _('<')) { + if (is_substr(str, pos + 1, tag.c_str()+1)) { + if (pos < start) last_start = pos; + ++taglevel; + } else if (pos + 2 < size && str.GetChar(pos+1) == _('/') && is_substr(str, pos + 2, tag.c_str()+1)) { + --taglevel; // close tag + } + pos = skip_tag(str,pos); + } else { + pos++; + } + if (pos >= start && taglevel < 1) { + // not inside tag anymore + return String::npos; + } + } + return taglevel < 1 ? String::npos : last_start; +} +bool is_in_tag(const String& str, const String& tag, size_t start, size_t end) { + return in_tag(str,tag,start,end) != String::npos; } diff --git a/src/util/tagged_string.hpp b/src/util/tagged_string.hpp index acfbdafe..1e1216b8 100644 --- a/src/util/tagged_string.hpp +++ b/src/util/tagged_string.hpp @@ -73,8 +73,13 @@ size_t last_start_tag_before(const String& str, const String& tag, size_t start) /// Is the given range entirely contained in a given tagged block? /** If so: return the start position of that tag, otherwise returns String::npos * A tagged block is everything between ... + * Note: this function looks for a positive number of tags, so in for example + * x + * the x is in_tag */ size_t in_tag(const String& str, const String& tag, size_t start, size_t end); +/// Boolean returning version of the above +bool is_in_tag(const String& str, const String& tag, size_t start, size_t end); /// Return the tag at the given position (without the <>) String tag_at(const String& str, size_t pos);