Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

New plugin: Pair Tag Highlighter #99

Merged
merged 1 commit into from

3 participants

@vmkononenko

The plugin finds and highlights matching opening/closing
HTML tag by clicking or moving cursor inside a tag.

pairtaghighlighter/src/pair_tag_highlighter.c
@@ -0,0 +1,347 @@
+/*
+ * Pair Tag Highlighter
+ *
+ * highlights matching opening/closing HTML tags
+ *
+ * Author: Volodymyr Kononenko aka kvm
+ * Email: vm@kononenko.ws
+ *
+ */
+
+#include <geanyplugin.h>
+#include "Scintilla.h" // for the SCNotification struct
@b4n Owner
b4n added a note

We prefer C89 comments (/* ... */) rather than C++ comments (// ...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@b4n
Owner
b4n commented

And you need to update root Makefile.am too (sorry if I forgot to mention it before)

diff --git a/Makefile.am b/Makefile.am
index 3c1d40b..f81fe5d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -94,6 +94,10 @@ if ENABLE_MULTITERM
 SUBDIRS += multiterm
 endif

+if ENABLE_PAIRTAGHIGHLIGHTER
+SUBDIRS += pairtaghighlighter
+endif
+
 if ENABLE_POHELPER
 SUBDIRS += pohelper
 endif
@b4n b4n commented on the diff
pairtaghighlighter/src/pair_tag_highlighter.c
((18 lines not shown))
+#define MAX_TAG_NAME 64
+
+/* These items are set by Geany before plugin_init() is called. */
+GeanyPlugin *geany_plugin;
+GeanyData *geany_data;
+GeanyFunctions *geany_functions;
+
+static ScintillaObject *sci;
+
+/* Is needed for clearing highlighting after moving cursor out
+ * from the tag */
+static gint highlightedBrackets[] = {0, 0, 0, 0};
+
+PLUGIN_VERSION_CHECK(211)
+
+PLUGIN_SET_TRANSLATABLE_INFO(LOCALEDIR, GETTEXT_PACKAGE, _("Pair Tag Highlighter"),
@b4n Owner
b4n added a note

pair_tag_highlighter.c:33:1: error: `GETTEXT_PACKAGE' undeclared (first use in this function)
You need to #include "config.h"

And try build your plugin with the build system, please ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((20 lines not shown))
+/* These items are set by Geany before plugin_init() is called. */
+GeanyPlugin *geany_plugin;
+GeanyData *geany_data;
+GeanyFunctions *geany_functions;
+
+static ScintillaObject *sci;
+
+/* Is needed for clearing highlighting after moving cursor out
+ * from the tag */
+static gint highlightedBrackets[] = {0, 0, 0, 0};
+
+PLUGIN_VERSION_CHECK(211)
+
+PLUGIN_SET_TRANSLATABLE_INFO(LOCALEDIR, GETTEXT_PACKAGE, _("Pair Tag Highlighter"),
+ _("Finds and highlights matching opening/closing HTML tag"),
+ "1.0", "Volodymyr Kononenko <vm@kononenko.ws>");
@b4n Owner
b4n added a note

pair_tag_highlighter.c:35:76: warning: ISO C does not allow extra `;' outside of a function [-pedantic]
No need for a semicolon here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((100 lines not shown))
+ scintilla_send_message(sci, SCI_INDICATORCLEARRANGE, rangeStart, rangeEnd+1);
+}
+
+
+static gboolean is_tag_self_closing(gint closingBracket)
+{
+ gboolean isTagSelfClosing = FALSE;
+ gchar charBeforeBracket = sci_get_char_at(sci, closingBracket-1);
+
+ if('/' == charBeforeBracket)
+ isTagSelfClosing = TRUE;
+ return isTagSelfClosing;
+}
+
+
+static gboolean is_tag_opening(openingBracket)
@b4n Owner
b4n added a note

pair_tag_highlighter.c:115:17: warning: function declaration isn't a prototype [-Wstrict-prototypes]
The type of the openingBracket argument is missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((141 lines not shown))
+ sci_get_text_range(sci, nameStart, nameEnd-1, tagName);
+}
+
+
+static void findMatchingOpeningTag(gchar *tagName, gint openingBracket)
+{
+ gint pos;
+ gint openingTagsCount = 0;
+ gint closingTagsCount = 1;
+
+ for(pos=openingBracket; pos>0; pos--)
+ {
+ /* are we inside tag? */
+ gint lineNumber = sci_get_line_from_position(sci, pos);
+ gint lineStart = sci_get_position_from_line(sci, lineNumber);
+ gint matchingOpeningBracket = findBracket(pos, lineStart, '<', NULL, FALSE);
@b4n Owner
b4n added a note

pair_tag_highlighter.c:156:9: warning: passing argument 4 of `findBracket' makes integer from pointer without a cast [enabled by default]
pair_tag_highlighter.c:44:13: note: expected `gchar' but argument is of type `void *'
NULL isn't a valid value for a gchar: gchar is a byte, isn't not gchar* (pointer to byte(s)). You probably want 0 (or '\0')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((142 lines not shown))
+}
+
+
+static void findMatchingOpeningTag(gchar *tagName, gint openingBracket)
+{
+ gint pos;
+ gint openingTagsCount = 0;
+ gint closingTagsCount = 1;
+
+ for(pos=openingBracket; pos>0; pos--)
+ {
+ /* are we inside tag? */
+ gint lineNumber = sci_get_line_from_position(sci, pos);
+ gint lineStart = sci_get_position_from_line(sci, lineNumber);
+ gint matchingOpeningBracket = findBracket(pos, lineStart, '<', NULL, FALSE);
+ gint matchingClosingBracket = findBracket(pos, lineStart, '>', NULL, FALSE);
@b4n Owner
b4n added a note

Same here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@b4n b4n commented on the diff
pairtaghighlighter/src/pair_tag_highlighter.c
((152 lines not shown))
+ {
+ /* are we inside tag? */
+ gint lineNumber = sci_get_line_from_position(sci, pos);
+ gint lineStart = sci_get_position_from_line(sci, lineNumber);
+ gint matchingOpeningBracket = findBracket(pos, lineStart, '<', NULL, FALSE);
+ gint matchingClosingBracket = findBracket(pos, lineStart, '>', NULL, FALSE);
+
+ if(-1 != matchingOpeningBracket && -1 != matchingClosingBracket
+ && (matchingClosingBracket > matchingOpeningBracket))
+ {
+ /* we are inside of some tag. Let us check what tag*/
+ gchar matchingTagName[MAX_TAG_NAME];
+ gboolean isMatchingTagOpening = is_tag_opening(matchingOpeningBracket);
+ get_tag_name(matchingOpeningBracket, matchingClosingBracket,
+ matchingTagName, isMatchingTagOpening);
+ if(strcmp(tagName, matchingTagName) == 0)
@b4n Owner
b4n added a note

pair_tag_highlighter.c:167:13: error: implicit declaration of function `strcmp' [-Werror=implicit-function-declaration]
Please don't forget to #include <string.h>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((194 lines not shown))
+
+
+static void findMatchingClosingTag(gchar *tagName, gint closingBracket)
+{
+ gint pos;
+ gint linesInDocument = sci_get_line_count(sci);
+ gint endOfDocument = sci_get_position_from_line(sci, linesInDocument);
+ gint openingTagsCount = 1;
+ gint closingTagsCount = 0;
+
+ for(pos=closingBracket; pos<endOfDocument; pos++)
+ {
+ /* are we inside tag? */
+ gint lineNumber = sci_get_line_from_position(sci, pos);
+ gint lineEnd = sci_get_line_end_position(sci, lineNumber);
+ gint matchingOpeningBracket = findBracket(pos, endOfDocument, '<', NULL, TRUE);
@b4n Owner
b4n added a note

Same as above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((195 lines not shown))
+
+static void findMatchingClosingTag(gchar *tagName, gint closingBracket)
+{
+ gint pos;
+ gint linesInDocument = sci_get_line_count(sci);
+ gint endOfDocument = sci_get_position_from_line(sci, linesInDocument);
+ gint openingTagsCount = 1;
+ gint closingTagsCount = 0;
+
+ for(pos=closingBracket; pos<endOfDocument; pos++)
+ {
+ /* are we inside tag? */
+ gint lineNumber = sci_get_line_from_position(sci, pos);
+ gint lineEnd = sci_get_line_end_position(sci, lineNumber);
+ gint matchingOpeningBracket = findBracket(pos, endOfDocument, '<', NULL, TRUE);
+ gint matchingClosingBracket = findBracket(pos, endOfDocument, '>', NULL, TRUE);
@b4n Owner
b4n added a note

And here too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((234 lines not shown))
+ pos = lineEnd;
+ continue;
+ }
+ if(openingTagsCount == closingTagsCount)
+ {
+ /* matching tag is found */
+ highlight_tag(matchingOpeningBracket, matchingClosingBracket);
+ highlightedBrackets[2] = matchingOpeningBracket;
+ highlightedBrackets[3] = matchingClosingBracket;
+ break;
+ }
+ }
+}
+
+
+static void findMatchingTag(openingBracket, closingBracket)
@b4n Owner
b4n added a note
pair_tag_highlighter.c:249:13: warning: function declaration isn't a prototype [-Wstrict-prototypes]
pair_tag_highlighter.c: In function `findMatchingTag':
pair_tag_highlighter.c:249:13: warning: type of `openingBracket' defaults to `int' [-Wmissing-parameter-type]
pair_tag_highlighter.c:249:13: warning: type of `closingBracket' defaults to `int' [-Wmissing-parameter-type]

Argument types missing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pairtaghighlighter/src/pair_tag_highlighter.c
((260 lines not shown))
+
+
+static void run_tag_highlighter(void)
+{
+ gint position = sci_get_current_position(sci);
+ gint lineNumber = sci_get_current_line(sci);
+ gint lineStart = sci_get_position_from_line(sci, lineNumber);
+ gint lineEnd = sci_get_line_end_position(sci, lineNumber);
+ gint openingBracket = findBracket(position, lineStart, '<', '>', FALSE);
+ gint closingBracket = findBracket(position, lineEnd, '>', '<', TRUE);
+
+ if(-1 == openingBracket || -1 == closingBracket)
+ {
+ clear_previous_highlighting(highlightedBrackets[0], highlightedBrackets[1]);
+ clear_previous_highlighting(highlightedBrackets[2], highlightedBrackets[3]);
+ int i;
@b4n Owner
b4n added a note

pair_tag_highlighter.c:275:9: warning: ISO C90 forbids mixed declarations and code [-pedantic]
We try to follow C89/C90 whenever possible, so you might want to move this to the start of the block (e.g. between lines 272 and 273)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@vmkononenko vmkononenko New plugin: Pair Tag Highlighter
The plugin finds and highlights matching opening/closing
HTML tag by clicking or moving cursor inside a tag.
f81769e
@frlan frlan merged commit d1d8425 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 5, 2013
  1. @vmkononenko

    New plugin: Pair Tag Highlighter

    vmkononenko authored Volodymyr Kononenko committed
    The plugin finds and highlights matching opening/closing
    HTML tag by clicking or moving cursor inside a tag.
This page is out of date. Refresh to see the latest.
View
4 Makefile.am
@@ -94,6 +94,10 @@ if ENABLE_MULTITERM
SUBDIRS += multiterm
endif
+if ENABLE_PAIRTAGHIGHLIGHTER
+SUBDIRS += pairtaghighlighter
+endif
+
if ENABLE_POHELPER
SUBDIRS += pohelper
endif
View
9 build/pairtaghighlighter.m4
@@ -0,0 +1,9 @@
+AC_DEFUN([GP_CHECK_PAIRTAGHIGHLIGHTER],
+[
+ GP_ARG_DISABLE([PairTagHighlighter], [auto])
+ GP_COMMIT_PLUGIN_STATUS([PairTagHighlighter])
+ AC_CONFIG_FILES([
+ pairtaghighlighter/Makefile
+ pairtaghighlighter/src/Makefile
+ ])
+])
View
1  configure.ac
@@ -48,6 +48,7 @@ GP_CHECK_GENIUSPASTE
GP_CHECK_GPROJECT
GP_CHECK_MARKDOWN
GP_CHECK_MULTITERM
+GP_CHECK_PAIRTAGHIGHLIGHTER
GP_CHECK_POHELPER
GP_CHECK_PRETTYPRINTER
GP_CHECK_SCOPE
View
1  pairtaghighlighter/AUTHORS
@@ -0,0 +1 @@
+Volodymyr Kononenko <vm@kononenko.ws>
View
25 pairtaghighlighter/COPYING
@@ -0,0 +1,25 @@
+Copyright (c) 2013, Volodymyr Kononenko
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
3  pairtaghighlighter/ChangeLog
@@ -0,0 +1,3 @@
+Changes in v1.0 Apr 5, 2013
+
+ * The first public version.
View
4 pairtaghighlighter/Makefile.am
@@ -0,0 +1,4 @@
+include $(top_srcdir)/build/vars.auxfiles.mk
+
+SUBDIRS = src
+plugin = pairtaghighlighter
View
0  pairtaghighlighter/NEWS
No changes.
View
28 pairtaghighlighter/README
@@ -0,0 +1,28 @@
+Pair Tag Highlighter
+====================
+
+About
+-----
+
+Finds and highlights matching opening/closing HTML tag by clicking or
+moving cursor inside a tag.
+
+Usage
+-----
+
+Just enable plugin through Geany's plugin manager.
+
+Licence
+-------
+
+This plugin is distributed under the terms of the BSD 2-Clause License.
+You should have received a copy of the the BSD 2-Clause License in the
+file COPYING included with the source code of this plugin. If not, find
+it at <http://opensource.org/licenses/BSD-2-Clause>.
+
+Contact developer
+-----------------
+
+You may contact developer (Volodymyr Kononenko) via e-mail:
+<vm(at)kononenko(dot)ws>. The complete up to date list of contacts
+can be found at <http://kononenko.ws/en/contacts>.
View
9 pairtaghighlighter/src/Makefile.am
@@ -0,0 +1,9 @@
+include $(top_srcdir)/build/vars.build.mk
+
+geanyplugins_LTLIBRARIES = pairtaghighlighter.la
+
+pairtaghighlighter_la_SOURCES = pair_tag_highlighter.c
+
+pairtaghighlighter_la_LIBADD = $(COMMONLIBS)
+
+include $(top_srcdir)/build/cppcheck.mk
View
349 pairtaghighlighter/src/pair_tag_highlighter.c
@@ -0,0 +1,349 @@
+/*
+ * Pair Tag Highlighter
+ *
+ * highlights matching opening/closing HTML tags
+ *
+ * Author: Volodymyr Kononenko aka kvm
+ * Email: vm@kononenko.ws
+ *
+ */
+
+#include "config.h"
+#include <geanyplugin.h>
+#include <string.h>
+#include "Scintilla.h" /* for the SCNotification struct */
+#include "SciLexer.h"
+
+/* If to set indicator >8, highlighting will be of grey color.
+ * Light grey line highlighter covers higher values of indicator. */
+#define INDICATOR_TAGMATCH 0
+#define MAX_TAG_NAME 64
+
+/* These items are set by Geany before plugin_init() is called. */
+GeanyPlugin *geany_plugin;
+GeanyData *geany_data;
+GeanyFunctions *geany_functions;
+
+static ScintillaObject *sci;
+
+/* Is needed for clearing highlighting after moving cursor out
+ * from the tag */
+static gint highlightedBrackets[] = {0, 0, 0, 0};
+
+PLUGIN_VERSION_CHECK(211)
+
+PLUGIN_SET_TRANSLATABLE_INFO(LOCALEDIR, GETTEXT_PACKAGE, _("Pair Tag Highlighter"),
@b4n Owner
b4n added a note

pair_tag_highlighter.c:33:1: error: `GETTEXT_PACKAGE' undeclared (first use in this function)
You need to #include "config.h"

And try build your plugin with the build system, please ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ _("Finds and highlights matching opening/closing HTML tag"),
+ "1.0", "Volodymyr Kononenko <vm@kononenko.ws>")
+
+
+/* Searches tag brackets.
+ * direction variable shows sets search direction:
+ * TRUE - to the right
+ * FALSE - to the left
+ * from the current cursor position to the start of the line.
+ */
+static gint findBracket(gint position, gint endOfSearchPos,
+ gchar searchedBracket, gchar breakBracket, gboolean direction)
+{
+ gint foundBracket = -1;
+ gint pos;
+
+ if(TRUE == direction)
+ {
+ /* search to the right */
+ for(pos=position; pos<=endOfSearchPos; pos++)
+ {
+ gchar charAtCurPosition = sci_get_char_at(sci, pos);
+ if(charAtCurPosition == searchedBracket)
+ {
+ foundBracket = pos;
+ break;
+ }
+ if(charAtCurPosition == breakBracket)
+ break;
+ }
+ }
+ else
+ {
+ /* search to the left */
+ for(pos=position-1; pos>=endOfSearchPos; pos--)
+ {
+ gchar charAtCurPosition = sci_get_char_at(sci, pos);
+ if(charAtCurPosition == searchedBracket)
+ {
+ foundBracket = pos;
+ break;
+ }
+ if(charAtCurPosition == breakBracket)
+ break;
+ }
+ }
+
+ return foundBracket;
+}
+
+
+static void highlight_tag(gint openingBracket, gint closingBracket)
+{
+ scintilla_send_message(sci, SCI_SETINDICATORCURRENT, INDICATOR_TAGMATCH, 0);
+ scintilla_send_message(sci, SCI_INDICSETSTYLE,
+ INDICATOR_TAGMATCH, INDIC_ROUNDBOX);
+ scintilla_send_message(sci, SCI_INDICSETFORE, 0, 0x00d000); // green
+ scintilla_send_message(sci, SCI_INDICSETALPHA, INDICATOR_TAGMATCH, 60);
+ scintilla_send_message(sci, SCI_INDICATORFILLRANGE,
+ openingBracket, closingBracket-openingBracket+1);
+}
+
+
+static void clear_previous_highlighting(gint rangeStart, gint rangeEnd)
+{
+ scintilla_send_message(sci, SCI_SETINDICATORCURRENT, INDICATOR_TAGMATCH, 0);
+ scintilla_send_message(sci, SCI_INDICATORCLEARRANGE, rangeStart, rangeEnd+1);
+}
+
+
+static gboolean is_tag_self_closing(gint closingBracket)
+{
+ gboolean isTagSelfClosing = FALSE;
+ gchar charBeforeBracket = sci_get_char_at(sci, closingBracket-1);
+
+ if('/' == charBeforeBracket)
+ isTagSelfClosing = TRUE;
+ return isTagSelfClosing;
+}
+
+
+static gboolean is_tag_opening(gint openingBracket)
+{
+ gboolean isTagOpening = TRUE;
+ gchar charAfterBracket = sci_get_char_at(sci, openingBracket+1);
+
+ if('/' == charAfterBracket)
+ isTagOpening = FALSE;
+ return isTagOpening;
+}
+
+
+static void get_tag_name(gint openingBracket, gint closingBracket,
+ gchar tagName[], gboolean isTagOpening)
+{
+ gint nameStart = openingBracket + (TRUE == isTagOpening ? 1 : 2);
+ gint nameEnd = nameStart;
+ gchar charAtCurPosition = sci_get_char_at(sci, nameStart);
+
+ while(' ' != charAtCurPosition && '>' != charAtCurPosition &&
+ '\t' != charAtCurPosition && '\r' != charAtCurPosition && '\n' != charAtCurPosition)
+ {
+ charAtCurPosition = sci_get_char_at(sci, nameEnd);
+ nameEnd++;
+ if(nameEnd-nameStart > MAX_TAG_NAME)
+ break;
+ }
+ sci_get_text_range(sci, nameStart, nameEnd-1, tagName);
+}
+
+
+static void findMatchingOpeningTag(gchar *tagName, gint openingBracket)
+{
+ gint pos;
+ gint openingTagsCount = 0;
+ gint closingTagsCount = 1;
+
+ for(pos=openingBracket; pos>0; pos--)
+ {
+ /* are we inside tag? */
+ gint lineNumber = sci_get_line_from_position(sci, pos);
+ gint lineStart = sci_get_position_from_line(sci, lineNumber);
+ gint matchingOpeningBracket = findBracket(pos, lineStart, '<', '\0', FALSE);
+ gint matchingClosingBracket = findBracket(pos, lineStart, '>', '\0', FALSE);
+
+ if(-1 != matchingOpeningBracket && -1 != matchingClosingBracket
+ && (matchingClosingBracket > matchingOpeningBracket))
+ {
+ /* we are inside of some tag. Let us check what tag*/
+ gchar matchingTagName[MAX_TAG_NAME];
+ gboolean isMatchingTagOpening = is_tag_opening(matchingOpeningBracket);
+ get_tag_name(matchingOpeningBracket, matchingClosingBracket,
+ matchingTagName, isMatchingTagOpening);
+ if(strcmp(tagName, matchingTagName) == 0)
@b4n Owner
b4n added a note

pair_tag_highlighter.c:167:13: error: implicit declaration of function `strcmp' [-Werror=implicit-function-declaration]
Please don't forget to #include <string.h>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ {
+ if(TRUE == isMatchingTagOpening)
+ openingTagsCount++;
+ else
+ closingTagsCount++;
+ }
+ pos = matchingOpeningBracket+1;
+ }
+ /* Speed up search: if findBracket returns -1, that means start of line
+ * is reached. There is no need to go through the same positions again.
+ * Jump to the start of line */
+ else if(-1 == matchingOpeningBracket || -1 == matchingClosingBracket)
+ {
+ pos = lineStart;
+ continue;
+ }
+ if(openingTagsCount == closingTagsCount)
+ {
+ /* matching tag is found */
+ highlight_tag(matchingOpeningBracket, matchingClosingBracket);
+ highlightedBrackets[2] = matchingOpeningBracket;
+ highlightedBrackets[3] = matchingClosingBracket;
+ break;
+ }
+ }
+}
+
+
+static void findMatchingClosingTag(gchar *tagName, gint closingBracket)
+{
+ gint pos;
+ gint linesInDocument = sci_get_line_count(sci);
+ gint endOfDocument = sci_get_position_from_line(sci, linesInDocument);
+ gint openingTagsCount = 1;
+ gint closingTagsCount = 0;
+
+ for(pos=closingBracket; pos<endOfDocument; pos++)
+ {
+ /* are we inside tag? */
+ gint lineNumber = sci_get_line_from_position(sci, pos);
+ gint lineEnd = sci_get_line_end_position(sci, lineNumber);
+ gint matchingOpeningBracket = findBracket(pos, endOfDocument, '<', '\0', TRUE);
+ gint matchingClosingBracket = findBracket(pos, endOfDocument, '>', '\0', TRUE);
+
+ if(-1 != matchingOpeningBracket && -1 != matchingClosingBracket
+ && (matchingClosingBracket > matchingOpeningBracket))
+ {
+ /* we are inside of some tag. Let us check what tag*/
+ gchar matchingTagName[64];
+ gboolean isMatchingTagOpening = is_tag_opening(matchingOpeningBracket);
+ get_tag_name(matchingOpeningBracket, matchingClosingBracket,
+ matchingTagName, isMatchingTagOpening);
+ if(strcmp(tagName, matchingTagName) == 0)
+ {
+ if(TRUE == isMatchingTagOpening)
+ openingTagsCount++;
+ else
+ closingTagsCount++;
+ }
+ pos = matchingClosingBracket;
+ }
+ /* Speed up search: if findBracket returns -1, that means end of line
+ * is reached. There is no need to go through the same positions again.
+ * Jump to the end of line */
+ else if(-1 == matchingOpeningBracket || -1 == matchingClosingBracket)
+ {
+ pos = lineEnd;
+ continue;
+ }
+ if(openingTagsCount == closingTagsCount)
+ {
+ /* matching tag is found */
+ highlight_tag(matchingOpeningBracket, matchingClosingBracket);
+ highlightedBrackets[2] = matchingOpeningBracket;
+ highlightedBrackets[3] = matchingClosingBracket;
+ break;
+ }
+ }
+}
+
+
+static void findMatchingTag(gint openingBracket, gint closingBracket)
+{
+ gchar tagName[MAX_TAG_NAME];
+ gboolean isTagOpening = is_tag_opening(openingBracket);
+ get_tag_name(openingBracket, closingBracket, tagName, isTagOpening);
+
+ if(TRUE == isTagOpening)
+ findMatchingClosingTag(tagName, closingBracket);
+ else
+ findMatchingOpeningTag(tagName, openingBracket);
+}
+
+
+static void run_tag_highlighter(void)
+{
+ gint position = sci_get_current_position(sci);
+ gint lineNumber = sci_get_current_line(sci);
+ gint lineStart = sci_get_position_from_line(sci, lineNumber);
+ gint lineEnd = sci_get_line_end_position(sci, lineNumber);
+ gint openingBracket = findBracket(position, lineStart, '<', '>', FALSE);
+ gint closingBracket = findBracket(position, lineEnd, '>', '<', TRUE);
+ int i;
+
+ if(-1 == openingBracket || -1 == closingBracket)
+ {
+ clear_previous_highlighting(highlightedBrackets[0], highlightedBrackets[1]);
+ clear_previous_highlighting(highlightedBrackets[2], highlightedBrackets[3]);
+ for(i=0; i<3; i++)
+ highlightedBrackets[i] = 0;
+ return;
+ }
+
+ /* If the cursor jumps from one tag into another, clear
+ * previous highlighted tags*/
+ if(openingBracket != highlightedBrackets[0] ||
+ closingBracket != highlightedBrackets[1])
+ {
+ clear_previous_highlighting(highlightedBrackets[0], highlightedBrackets[1]);
+ clear_previous_highlighting(highlightedBrackets[2], highlightedBrackets[3]);
+ }
+
+ highlightedBrackets[0] = openingBracket;
+ highlightedBrackets[1] = closingBracket;
+
+ /* Highlight current tag. Matching tag will be highlighted from
+ * findMatchingTag() functiong */
+ highlight_tag(openingBracket, closingBracket);
+
+ /* Find matching tag only if a tag is not self-closing */
+ if(FALSE == is_tag_self_closing(closingBracket))
+ findMatchingTag(openingBracket, closingBracket);
+}
+
+
+/* Notification handler for editor-notify */
+static gboolean on_editor_notify(GObject *obj, GeanyEditor *editor,
+ SCNotification *nt, gpointer user_data)
+{
+ gint lexer;
+
+ /* setting global sci variable to be available in other functions */
+ sci = editor->sci;
+
+ lexer = sci_get_lexer(sci);
+ if(lexer != SCLEX_HTML)
+ {
+ return FALSE;
+ }
+
+ /* nmhdr is a structure containing information about the event */
+ switch (nt->nmhdr.code)
+ {
+ case SCN_UPDATEUI:
+ run_tag_highlighter();
+ break;
+ }
+
+ /* returning FALSE to allow Geany processing the event */
+ return FALSE;
+}
+
+
+PluginCallback plugin_callbacks[] =
+{
+ { "editor-notify", (GCallback) &on_editor_notify, FALSE, NULL },
+ { NULL, NULL, FALSE, NULL }
+};
+
+
+void plugin_init(GeanyData *data)
+{
+}
+
+
+void plugin_cleanup(void)
+{
+ clear_previous_highlighting(highlightedBrackets[0], highlightedBrackets[1]);
+ clear_previous_highlighting(highlightedBrackets[2], highlightedBrackets[3]);
+}
Something went wrong with that request. Please try again.