GNOME Bugzilla – Bug 757881
gtk-3.18.3 breaks filediff
Last modified: 2015-11-13 23:35:36 UTC
Using gtk-3.18.3 breaks filediff, because GtkSource.Buffer.get_iter_at_line() now returns the tuple (bool, Gtk.TextIter) and not simply the iterator anymore.
It affects me also on Arch Linux: Traceback (most recent call last):
+ Trace 235714
ret = next(task)
for i in self._diff_files():
while next(step) is None:
while next(work) is None:
a, b = self.preprocess()
a, b = self.preprocess_remove_prefix_suffix(self.a, self.b)
self.common_prefix = find_common_prefix(a, b)
if a[0] == b[0]:
line_end = line_start.copy()
Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/meld/filediff.py", line 1775, in _sync_vscroll val, height = self.textview[i].get_line_yrange(it) TypeError: argument iter: Expected Gtk.TextIter, but got tuple
In case anyone comes across this issue and wants a temporary fix, here's a patch for MeldBuffer. Works with 3.15.0 too. I didn't look into the root cause of this so perhaps a gtk bug fix would be more appropriate. I don't know. But this will fix meld up to work if you happen to be using a distribution with gtk libs installed that expose this bug. --- meld-3.14.1-orig/meld/meldbuffer.py 2015-10-02 22:10:11.000000000 -0400 +++ meld-3.14.1/meld/meldbuffer.py 2015-11-11 20:37:09.412543281 -0500 @@ -76,6 +76,9 @@ self.data.filename = filename self.data.label = label + def get_iter_at_line(self, line): + return super(MeldBuffer, self).get_iter_at_line(line)[1] + def get_iter_at_line_or_eof(self, line): """Return a Gtk.TextIter at the given line, or the end of the buffer.
thank you very much for the patch - works for me.
(In reply to David I. Lehn from comment #2) > In case anyone comes across this issue and wants a temporary fix, here's a > patch for MeldBuffer. Works with 3.15.0 too. I didn't look into the root > cause of this so perhaps a gtk bug fix would be more appropriate. I don't > know. But this will fix meld up to work if you happen to be using a > distribution with gtk libs installed that expose this bug. > the root cause is this gtk patch where the get_iter_* now return gbooleans instead of void: commit cf51c4f6dbd91dae1878a0cb0d08b24c67e15232 Author: Sébastien Wilmet <swilmet@gnome.org> Date: Thu Oct 15 10:43:10 2015 +0200 textbuffer: nicer get_iter functions Avoid crashes when passing an invalid location to a gtk_text_buffer_get_iter_at_*() function. A boolean is returned to know if @iter has been set to the exact location. Unit tests are added. https://bugzilla.gnome.org/show_bug.cgi?id=735341 diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index 1bf1b68..7295021 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -2862,22 +2862,48 @@ gtk_text_buffer_remove_all_tags (GtkTextBuffer *buffer, * @line_number: line number counting from 0 * @char_offset: char offset from start of line * - * Obtains an iterator pointing to @char_offset within the given - * line. The @char_offset must exist, offsets off the end of the line - * are not allowed. Note characters, not bytes; - * UTF-8 may encode one character as multiple bytes. + * Obtains an iterator pointing to @char_offset within the given line. Note + * characters, not bytes; UTF-8 may encode one character as multiple bytes. + * + * Before the 3.20 version, it was not allowed to pass an invalid location. + * + * Since the 3.20 version, if @line_number is greater than the number of lines + * in the @buffer, the end iterator is returned. And if @char_offset is off the + * end of the line, the iterator at the end of the line is returned. + * + * Returns: whether the exact position has been found (since 3.20). **/ -void +gboolean gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer, GtkTextIter *iter, gint line_number, gint char_offset) { - g_return_if_fail (iter != NULL); - g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + GtkTextIter end_line_iter; + + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); + + if (line_number >= gtk_text_buffer_get_line_count (buffer)) + { + gtk_text_buffer_get_end_iter (buffer, iter); + return FALSE; + } + + _gtk_text_btree_get_iter_at_line_char (get_btree (buffer), iter, line_number, 0); - _gtk_text_btree_get_iter_at_line_char (get_btree (buffer), - iter, line_number, char_offset); + end_line_iter = *iter; + if (!gtk_text_iter_ends_line (&end_line_iter)) + gtk_text_iter_forward_to_line_end (&end_line_iter); + + if (char_offset > gtk_text_iter_get_line_offset (&end_line_iter)) + { + *iter = end_line_iter; + return FALSE; + } + + gtk_text_iter_set_line_offset (iter, char_offset); + return TRUE; } /** @@ -2888,21 +2914,48 @@ gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer, * @byte_index: byte index from start of line * * Obtains an iterator pointing to @byte_index within the given line. - * @byte_index must be the start of a UTF-8 character, and must not be - * beyond the end of the line. Note bytes, not + * @byte_index must be the start of a UTF-8 character. Note bytes, not * characters; UTF-8 may encode one character as multiple bytes. + * + * Before the 3.20 version, it was not allowed to pass an invalid location. + * + * Since the 3.20 version, if @line_number is greater than the number of lines + * in the @buffer, the end iterator is returned. And if @byte_index is off the + * end of the line, the iterator at the end of the line is returned. + * + * Returns: whether the exact position has been found (since 3.20). **/ -void +gboolean gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer, GtkTextIter *iter, gint line_number, gint byte_index) { - g_return_if_fail (iter != NULL); - g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + GtkTextIter end_line_iter; + + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); + + if (line_number >= gtk_text_buffer_get_line_count (buffer)) + { + gtk_text_buffer_get_end_iter (buffer, iter); + return FALSE; + } + + gtk_text_buffer_get_iter_at_line (buffer, iter, line_number); + + end_line_iter = *iter; + if (!gtk_text_iter_ends_line (&end_line_iter)) + gtk_text_iter_forward_to_line_end (&end_line_iter); - _gtk_text_btree_get_iter_at_line_byte (get_btree (buffer), - iter, line_number, byte_index); + if (byte_index > gtk_text_iter_get_line_index (&end_line_iter)) + { + *iter = end_line_iter; + return FALSE; + } + + gtk_text_iter_set_line_index (iter, byte_index); + return TRUE; } /** @@ -2913,16 +2966,18 @@ gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer, * * Initializes @iter to the start of the given line. If @line_number is greater * than the number of lines in the @buffer, the end iterator is returned. + * + * Returns: whether the exact position has been found (since 3.20). **/ -void +gboolean gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer, GtkTextIter *iter, gint line_number) { - g_return_if_fail (iter != NULL); - g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); - gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0); + return gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0); } /**
(In reply to arne from comment #4) > (In reply to David I. Lehn from comment #2) > > In case anyone comes across this issue and wants a temporary fix, here's a > > patch for MeldBuffer. Works with 3.15.0 too. I didn't look into the root > > cause of this so perhaps a gtk bug fix would be more appropriate. I don't > > know. But this will fix meld up to work if you happen to be using a > > distribution with gtk libs installed that expose this bug. > > > the root cause is this gtk patch where the get_iter_* now return gbooleans > instead of void: > > commit cf51c4f6dbd91dae1878a0cb0d08b24c67e15232 > Author: Sébastien Wilmet <swilmet@gnome.org> > Date: Thu Oct 15 10:43:10 2015 +0200 Thanks for chasing that down. This is a great situation where there's no C API break, but there *is* a Python-level API break in a micro release. The 'real' 'fix' will be approximately what was posted in comment 2, but with an isinstance check or something similarly terrible.
Gtk+ 3.18.4 reverted the API change; you can close this as a duplicate of bug #757963.
(In reply to Jan Alexander Steffens (heftig) from comment #6) > Gtk+ 3.18.4 reverted the API change; you can close this as a duplicate of > bug #757963. Thanks, that's very helpful. Since it was only in a single micro release, I'm not going to add a workaround here. *** This bug has been marked as a duplicate of bug 757963 ***