diff --git a/src/lay/layGenericSyntaxHighlighter.cc b/src/lay/layGenericSyntaxHighlighter.cc index bcd94c494..9b5bfb370 100644 --- a/src/lay/layGenericSyntaxHighlighter.cc +++ b/src/lay/layGenericSyntaxHighlighter.cc @@ -1612,6 +1612,7 @@ GenericSyntaxHighlighter::highlightBlock(const QString &text) SyntaxHighlighterElement el; el.start_offset = last_index; el.length = index - last_index; + el.basic_attribute_id = mp_attributes->basic_id (def_attribute_id); user_data->elements ().push_back (el); } @@ -1627,6 +1628,7 @@ GenericSyntaxHighlighter::highlightBlock(const QString &text) SyntaxHighlighterElement el; el.start_offset = index; el.length = end_index - index; + el.basic_attribute_id = mp_attributes->basic_id (attribute_id); user_data->elements ().push_back (el); } diff --git a/src/lay/layGenericSyntaxHighlighter.h b/src/lay/layGenericSyntaxHighlighter.h index f8d9a9c67..c06f1ff9b 100644 --- a/src/lay/layGenericSyntaxHighlighter.h +++ b/src/lay/layGenericSyntaxHighlighter.h @@ -46,12 +46,13 @@ public: * @brief Default constructor */ SyntaxHighlighterElement () - : start_offset (0), length (0) + : start_offset (0), length (0), basic_attribute_id (0) { // .. nothing yet .. } size_t start_offset, length; + int basic_attribute_id; }; /** diff --git a/src/lay/layMacroEditorPage.cc b/src/lay/layMacroEditorPage.cc index 47a2236f0..528601b5e 100644 --- a/src/lay/layMacroEditorPage.cc +++ b/src/lay/layMacroEditorPage.cc @@ -586,6 +586,11 @@ void MacroEditorPage::breakpoints_changed () } } +static bool valid_element (const SyntaxHighlighterElement &e) +{ + return e.basic_attribute_id != lay::dsComment && e.basic_attribute_id != lay::dsString; +} + void MacroEditorPage::cursor_position_changed () { QTextCursor cursor = mp_text->textCursor (); @@ -602,6 +607,12 @@ void MacroEditorPage::cursor_position_changed () SyntaxHighlighterUserData *user_data = dynamic_cast (b.userData()); if (user_data) { + // Look for matching brackets and highlight the other one + // NOTE: the whole scheme is somewhat more complex than it could be. It's + // based on the syntax highlighter elements and we confine ourselves to + // elements not being comment or string. So we need to iterate over elements + // and over characters inside these elements. + size_t pos = size_t (cursor.positionInBlock ()); std::vector::const_iterator e; @@ -619,12 +630,12 @@ void MacroEditorPage::cursor_position_changed () static const QString close_cbracket (QString::fromUtf8 ("}")); bool forward = false, backward = false; - if (e != user_data->elements ().end ()) { - QString t = b.text ().mid (e->start_offset, e->length).trimmed (); + if (e != user_data->elements ().end () && valid_element (*e)) { + QString t = b.text ().mid (pos, 1); forward = (t == open_rbracket || t == open_sqbracket || t == open_cbracket); } - if (e != user_data->elements ().begin () && e[-1].start_offset + e[-1].length == pos) { - QString t = b.text ().mid (e[-1].start_offset, e[-1].length).trimmed (); + if (e != user_data->elements ().begin () && e[-1].start_offset + e[-1].length >= pos && valid_element (*e)) { + QString t = b.text ().mid (pos - 1, 1); backward = (t == close_rbracket || t == close_sqbracket || t == close_cbracket); } @@ -637,34 +648,68 @@ void MacroEditorPage::cursor_position_changed () if (forward || backward) { std::vector bs; - std::vector::const_iterator e0 = e; - bool found = false; - while (e != user_data->elements ().end ()) { + int found = -1; + while (true) { QString t = b.text ().mid (e->start_offset, e->length).trimmed (); - if (forward && t == open_rbracket) { - bs.push_back (close_rbracket); - } else if (forward && t == open_cbracket) { - bs.push_back (close_cbracket); - } else if (forward && t == open_sqbracket) { - bs.push_back (close_sqbracket); - } else if (backward && t == close_rbracket) { - bs.push_back (open_rbracket); - } else if (backward && t == close_cbracket) { - bs.push_back (open_cbracket); - } else if (backward && t == close_sqbracket) { - bs.push_back (open_sqbracket); - } else if (t == bs.back ()) { - bs.pop_back (); - if (bs.empty ()) { - found = true; - break; + + if (valid_element (*e)) { + + if (forward) { + + for (int p = 0; p != t.size () && found < 0; ++p) { + if (p + e->start_offset >= pos) { + QString c = t.mid (p, 1); + if (c == open_rbracket) { + bs.push_back (close_rbracket); + } else if (c == open_cbracket) { + bs.push_back (close_cbracket); + } else if (c == open_sqbracket) { + bs.push_back (close_sqbracket); + } else if (c == bs.back ()) { + bs.pop_back (); + if (bs.empty ()) { + found = p + e->start_offset; + } + } + } + } + + } else if (backward) { + + for (int p = t.size (); p > 0 && found < 0; ) { + --p; + if (p + e->start_offset < pos) { + QString c = t.mid (p, 1); + if (c == close_rbracket) { + bs.push_back (open_rbracket); + } else if (c == close_cbracket) { + bs.push_back (open_cbracket); + } else if (c == close_sqbracket) { + bs.push_back (open_sqbracket); + } else if (c == bs.back ()) { + bs.pop_back (); + if (bs.empty ()) { + found = p + e->start_offset; + } + } + } + } + } + + } + + if (found >= 0) { + break; } if (forward) { ++e; + if (e == user_data->elements ().end ()) { + break; + } } else { if (e == user_data->elements ().begin ()) { break; @@ -674,7 +719,7 @@ void MacroEditorPage::cursor_position_changed () } - if (found) { + if (found >= 0) { QList extra_selections = mp_text->extraSelections (); for (QList::iterator i = extra_selections.begin (); i != extra_selections.end (); ) { @@ -689,13 +734,13 @@ void MacroEditorPage::cursor_position_changed () es.format = fmt; es.cursor = QTextCursor (b); - es.cursor.setPosition (b.position () + e0->start_offset); - es.cursor.movePosition (QTextCursor::NextCharacter, QTextCursor::KeepAnchor, e0->length); + es.cursor.setPosition (b.position () + found); + es.cursor.movePosition (QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 1); extra_selections.push_back (es); es.cursor = QTextCursor (b); - es.cursor.setPosition (b.position () + e->start_offset); - es.cursor.movePosition (QTextCursor::NextCharacter, QTextCursor::KeepAnchor, e->length); + es.cursor.setPosition (b.position () + found); + es.cursor.movePosition (QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 1); extra_selections.push_back (es); mp_text->setExtraSelections (extra_selections);