Problem
You want to highlight enclosing html tags in a GtkTextView as shown below:
Solution
- We use the technique as described in How to highlight matching brackets in GtkTextView - Part 3?
- To search for left tag, do a search for "<" followed by ">".
- Similarly, to search for right tag, do a search for "<" followed by ">".
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 16 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 59 60 61 62 63 64 66 67 68 69 70 71 74 76 77 78 79 80 81 82 83 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 106 108 109 110 111 112 113 114 115 120 121 122 123 124 125 126 127 129 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 149 150 151 152 153 154 155 156 157 158 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | <?php $window = new GtkWindow(); $window->set_size_request(400, 240); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // display title $title = new GtkLabel("Highlight matching HTML tags"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 20); $title->set_justify(Gtk::JUSTIFY_CENTER); $alignment = new GtkAlignment(0.5, 0.5, 0, 0); $alignment->add($title); $vbox->pack_start($alignment); $left_start_iter = $left_end_iter = null; $right_start_iter = $right_end_iter = null; // Create a new buffer and a new view to show the buffer. $buffer = new GtkTextBuffer(); $buffer->set_text('<p>This is a test</p> <ul> <li>item 1</li> <li>item 2</li> <li>item 3</li> </ul>'); $view = new GtkTextView(); $view->set_buffer($buffer); $view->modify_font(new PangoFontDescription("Arial 10")); $view->set_wrap_mode(Gtk::WRAP_WORD); $view->connect('button-press-event', 'on_button_press_in_textview'); $view->connect('key-press-event', 'on_key_press_in_textview'); $hbox = new GtkHBox(); $hbox->pack_start($button = new GtkButton('Find enclosing tags'), 0); $vbox->pack_start($hbox, 0); $button->connect('clicked', 'on_button', $buffer); $scrolled_win = new GtkScrolledWindow(); $scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); $vbox->pack_start($scrolled_win); $scrolled_win->add($view); $tag_table = $buffer->get_tag_table(); $tag['highlight'] = new GtkTextTag(); $tag['highlight']->set_property('background', "#ffff00"); $tag_table->add($tag['highlight']); $window->show_all(); Gtk::main(); function find_left_tag($iter, $buffer) { global $tag; $match_start = $iter->copy(); $match_end = $iter->copy(); // check left { first $found = $iter->backward_search('<', 0, $match_start, // note 1 $match_end, null); if (!$found) return null; // check if there's a } on the left $iter2 = $match_end->copy(); $match_start2 = $iter2->copy(); $match_end2 = $iter2->copy(); $found2 = $iter2->forward_search('>', 0, $match_start2, // note 2 $match_end2, null); if ($found2 && $match_start->compare($match_start2)!=-1) return null; $buffer->apply_tag($tag['highlight'], $match_start, $match_end2); // note 3 return array($match_start, $match_end2); } function find_right_tag($current_iter, $buffer) { global $tag; $iter = $current_iter->copy(); $match_start = $iter->copy(); $match_end = $iter->copy(); // check right } first $found = $iter->forward_search('<', 0, $match_start, // note 4 $match_end, null); if (!$found) return null; // check if there's a { on the left $iter2 = $match_end->copy(); $match_start2 = $iter2->copy(); $match_end2 = $iter2->copy(); $found2 = $iter2->forward_search('>', 0, $match_start2, // note 5 $match_end2, null); if ($found2 && $match_start->compare($match_start2)!=-1) return null; $buffer->apply_tag($tag['highlight'], $match_start, $match_end2); // note 6 return array($match_start, $match_end2); } function on_button($button, $buffer) { global $view, $tag; $cursor_pos = $buffer->get_mark('insert'); $iter = $buffer->get_iter_at_mark($cursor_pos); if ($iter==null) return; $last_pos = $buffer->create_mark('last_pos', $iter, false); global $left_start_iter, $left_end_iter; global $right_start_iter, $right_end_iter; list($left_start_iter, $left_end_iter) = find_left_tag($iter, $buffer); if ($left_start_iter==null) return; list($right_start_iter, $right_end_iter) = find_right_tag($iter, $buffer); if ($right_start_iter==null) return; $view->scroll_mark_onscreen($last_pos); $view->grab_focus(); } function on_button_press_in_textview($widget, $event) { remove_highlight(); } function on_key_press_in_textview($widget, $event) { remove_highlight(); } function remove_highlight() { global $buffer, $tag; global $left_start_iter, $left_end_iter; global $right_start_iter, $right_end_iter; if ($left_start_iter==null || $left_end_iter==null) return; // note 3 if ($right_start_iter==null || $right_end_iter==null) return; // note 3 $buffer->remove_tag($tag['highlight'], $left_start_iter, $left_end_iter); // note 4 $buffer->remove_tag($tag['highlight'], $right_start_iter, $right_end_iter); // note 4 } ?> |
Output
As shown above.Explanation
- Search for start of left tag.
- Search for end of left tag.
- Highlight the left tag.
- Search for start of right tag.
- Search for end of right tag.
- Highlight the right tag.
Note
To make the code easier to understand, I did not put in any error checking here. In your actual implementation, you should check that the start and end tags are matching, otherwise the following might occur:
Related Links
- How to highlight matching brackets in GtkTextView - Part 1?
- How to highlight matching brackets in GtkTextView - Part 2?
- How to highlight matching brackets in GtkTextView - Part 3?
- How to apply styles to GtkTextView using GtkTextTag - Part 1?
- How to search for text in GtkTextView - Part 1?
- How to search for text in GtkTextView - Part 2?
- How to search for text in GtkTextView - Part 3?
Read more...