Problem
In Part 1, you have highlighted enclosing curly brackets in a GtkTextView.
However, pressing the button when the cursor is at "else" should not highlight anything. We'll fix this in this article as shown below:
Solution
- On the left, we need to make sure that there's no "}" after the "{" by using the method.
- Similarly, on the right, we need to make sure that there's no "{" before the "}".
- GtkTextiter::compare() is the method that allows us to compare the position of two iters.
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 60 61 62 63 64 65 66 68 69 70 71 72 73 76 78 79 80 81 82 83 84 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 108 110 111 112 113 114 115 116 121 122 123 124 125 126 127 128 129 131 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 150 151 152 153 154 155 156 157 158 159 | <?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("Find matching curly bracket - Part 2\n". "Place the cursor on 'else' and press the button.\n". "Nothing will be highlighted."); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 60); $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('if ($i==1) { test(); } else { test2(); }'); $view = new GtkTextView(); $view->set_buffer($buffer); $view->modify_font(new PangoFontDescription("Arial 10")); $view->set_wrap_mode(Gtk::WRAP_WORD); $hbox = new GtkHBox(); $hbox->pack_start($button = new GtkButton('Find enclosing bracket'), 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_bracket($iter, $buffer) { global $tag; $iter2 = $iter->copy(); $match_start = $iter->copy(); $match_end = $iter->copy(); // check left { first $found = $iter->backward_search('{', 0, $match_start, $match_end, null); if (!$found) return null; // check if there's a } on the left $match_start2 = $iter->copy(); $match_end2 = $iter->copy(); $found2 = $iter2->backward_search('}', 0, $match_start2, // note 1 $match_end2, null); if ($found2 && $match_start->compare($match_start2)!=1) // note 2 return null; $buffer->apply_tag($tag['highlight'], $match_start, $match_end); return array($match_start, $match_end); } function find_right_bracket($iter, $buffer) { global $tag; $iter2 = $iter->copy(); $match_start = $iter->copy(); $match_end = $iter->copy(); // check right } first $found = $iter->forward_search('}', 0, $match_start, $match_end, null); if (!$found) return null; // check if there's a { on the right $match_start2 = $iter->copy(); $match_end2 = $iter->copy(); $found2 = $iter2->forward_search('{', 0, $match_start2, // note 3 $match_end2, null); if ($found2 && $match_start->compare($match_start2)!=-1) // note 4 return null; $buffer->apply_tag($tag['highlight'], $match_start, $match_end); return array($match_start, $match_end); } function on_button($button, $buffer) { global $view, $tag; $cursor_pos = $buffer->get_mark('insert'); $iter = $buffer->get_iter_at_mark($cursor_pos); $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_bracket($iter, $buffer); if ($left_start_iter==null) return; list($right_start_iter, $right_end_iter) = find_right_bracket($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(); } ?> |
Output
As shown above.Explanation
- Check if there's a "}" on the left.
- If the } comes after the {, we do not highlight the curly bracket.
- Check if there's a "{" on the right.
- If the { comes after the }, we do not highlight the curly bracket.
Note
There is one more thing we need to improve:
- When the user moves the cursor (by mouse or keyboard), the highlight should disappear.
We will fix this in the next article.
Related Links
- How to highlight matching brackets in GtkTextView - Part 1?
- How to highlight matching brackets in GtkTextView - Part 3?
- How to highlight matching html tags in GtkTextView?
- 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...