From 7cbdbc2b39059bfcfae8d28ba93b680d8df4d295 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 6 Jul 2000 23:33:15 +0000 Subject: [PATCH] tons of fixes --- gtk/gtkdialog.c | 4 +- gtk/gtktextbtree.c | 28 ++- gtk/gtktextbtree.h | 1 + gtk/gtktextbuffer.c | 139 ++++++++---- gtk/gtktextbuffer.h | 5 +- gtk/gtktextdisplay.c | 6 +- gtk/gtktextiter.c | 472 ++++++++++++++++++++++++++++++++++------- gtk/gtktextiter.h | 27 ++- gtk/gtktextlayout.c | 150 +++++++------ gtk/gtktexttag.c | 8 + gtk/gtktexttag.h | 1 + gtk/gtktextview.c | 62 ++++-- gtk/gtkwindow.c | 4 +- gtk/testtext.c | 130 +++++++++++- gtk/testtextbuffer.c | 18 +- tests/testtext.c | 130 +++++++++++- tests/testtextbuffer.c | 18 +- 17 files changed, 965 insertions(+), 238 deletions(-) diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c index 7cfa13409b..f73cab5a4b 100644 --- a/gtk/gtkdialog.c +++ b/gtk/gtkdialog.c @@ -252,7 +252,7 @@ connect_action_widget (GtkDialog *dialog, GtkWidget *child) if (GTK_WIDGET_GET_CLASS (child)->activate_signal != 0) { const gchar* name = - gtk_signal_name (GTK_WIDGET_GET_CLASS (child)->activate_signal != 0); + gtk_signal_name (GTK_WIDGET_GET_CLASS (child)->activate_signal); gtk_signal_connect_while_alive (GTK_OBJECT (child), name, @@ -279,7 +279,7 @@ gtk_dialog_add_action_widget (GtkDialog *dialog, ad->response_id = response_id; connect_action_widget (dialog, widget); - + gtk_box_pack_end (GTK_BOX (dialog->action_area), widget, FALSE, TRUE, 5); diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index 51075a0353..b06f93fc73 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -2085,18 +2085,17 @@ gtk_text_btree_get_text (const GtkTextIter *start_orig, iter = start; seg = gtk_text_iter_get_indexable_segment(&iter); while (seg != end_seg) - { + { copy_segment(retval, include_hidden, include_nonchars, &iter, &end); - if (!gtk_text_iter_forward_indexable_segment(&iter)) - g_assert_not_reached(); /* must be able to go forward to - end_seg, if end_seg still exists - and was in front. */ - + gtk_text_iter_forward_indexable_segment(&iter); + seg = gtk_text_iter_get_indexable_segment(&iter); } + copy_segment(retval, include_hidden, include_nonchars, &iter, &end); + str = retval->str; g_string_free(retval, FALSE); return str; @@ -2937,6 +2936,23 @@ gtk_text_line_byte_has_tag (GtkTextLine *line, return find_toggle_outside_current_line(line, tree, tag); } +gboolean +gtk_text_line_is_last (GtkTextLine *line) +{ + GtkTextBTreeNode *node; + + if (line->next != NULL) + return FALSE; + else + { + node = line->parent; + while (node != NULL && node->next == NULL) + node = node->parent; + + return node == NULL; + } +} + GtkTextLine* gtk_text_line_next (GtkTextLine *line) { diff --git a/gtk/gtktextbtree.h b/gtk/gtktextbtree.h index 0c594c3c85..2b932ea27f 100644 --- a/gtk/gtktextbtree.h +++ b/gtk/gtktextbtree.h @@ -201,6 +201,7 @@ gboolean gtk_text_line_byte_has_tag (GtkTextLine GtkTextBTree *tree, gint byte_in_line, GtkTextTag *tag); +gboolean gtk_text_line_is_last (GtkTextLine *line); GtkTextLine * gtk_text_line_next (GtkTextLine *line); GtkTextLine * gtk_text_line_previous (GtkTextLine *line); void gtk_text_line_add_data (GtkTextLine *line, diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index 141dabff13..732f650edc 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -59,6 +59,7 @@ static void gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffe const GtkTextIter *start_char, const GtkTextIter *end_char); +static GtkTextBTree* get_btree (GtkTextBuffer *buffer); void gtk_marshal_NONE__INT_POINTER_INT (GtkObject *object, GtkSignalFunc func, @@ -265,23 +266,16 @@ GtkTextBuffer* gtk_text_buffer_new (GtkTextTagTable *table) { GtkTextBuffer *text_buffer; - - /* This is broken, need construct_only argument for the tag table - so language bindings can set it. - */ text_buffer = GTK_TEXT_BUFFER (gtk_type_new (gtk_text_buffer_get_type ())); if (table) - text_buffer->tag_table = table; - else - text_buffer->tag_table = gtk_text_tag_table_new(); - - gtk_object_ref (GTK_OBJECT(text_buffer->tag_table)); - gtk_object_sink (GTK_OBJECT(text_buffer->tag_table)); - - text_buffer->tree = gtk_text_btree_new(text_buffer->tag_table, - text_buffer); + { + text_buffer->tag_table = table; + + gtk_object_ref (GTK_OBJECT(text_buffer->tag_table)); + gtk_object_sink (GTK_OBJECT(text_buffer->tag_table)); + } return text_buffer; } @@ -296,11 +290,17 @@ gtk_text_buffer_destroy (GtkObject *object) gtk_widget_destroy(buffer->selection_widget); buffer->selection_widget = NULL; - gtk_object_unref(GTK_OBJECT(buffer->tag_table)); - buffer->tag_table = NULL; - - gtk_text_btree_unref(buffer->tree); - buffer->tree = NULL; + if (buffer->tag_table) + { + gtk_object_unref(GTK_OBJECT(buffer->tag_table)); + buffer->tag_table = NULL; + } + + if (buffer->btree) + { + gtk_text_btree_unref(buffer->btree); + buffer->btree = NULL; + } (* parent_class->destroy) (object); } @@ -315,6 +315,44 @@ gtk_text_buffer_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static GtkTextTagTable* +get_table (GtkTextBuffer *buffer) +{ + if (buffer->tag_table == NULL) + { + buffer->tag_table = gtk_text_tag_table_new (); + + gtk_object_ref (GTK_OBJECT(buffer->tag_table)); + gtk_object_sink (GTK_OBJECT(buffer->tag_table)); + } + + return buffer->tag_table; +} + +static GtkTextBTree* +get_btree (GtkTextBuffer *buffer) +{ + if (buffer->btree == NULL) + buffer->btree = gtk_text_btree_new(gtk_text_buffer_get_tag_table (buffer), + buffer); + + return buffer->btree; +} + +GtkTextBTree* +_gtk_text_buffer_get_btree (GtkTextBuffer *buffer) +{ + return get_btree (buffer); +} + +GtkTextTagTable* +gtk_text_buffer_get_tag_table (GtkTextBuffer *buffer) +{ + g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), NULL); + + return get_table (buffer); +} + /* * Insertion */ @@ -505,12 +543,14 @@ gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer, current_state = gtk_text_iter_editable (&iter, default_editable); - while (gtk_text_iter_forward_find_tag_toggle (&iter, NULL)) + while (TRUE) { gboolean new_state; gboolean done = FALSE; GtkTextIter end; + gtk_text_iter_forward_find_tag_toggle (&iter, NULL); + gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark); if (gtk_text_iter_compare (&iter, &end) >= 0) @@ -529,11 +569,11 @@ gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer, { /* We're ending an editable region. Delete said region. */ GtkTextIter start; - + gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark); - + gtk_text_buffer_delete (buffer, &start, &iter); - + deleted_stuff = TRUE; } @@ -574,6 +614,7 @@ gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer, break; } + gtk_text_buffer_delete_mark (buffer, start_mark); gtk_text_buffer_delete_mark (buffer, end_mark); @@ -689,20 +730,20 @@ gtk_text_buffer_set_mark(GtkTextBuffer *buffer, GtkTextIter location; GtkTextMark *mark; - mark = gtk_text_btree_set_mark(buffer->tree, + mark = gtk_text_btree_set_mark(get_btree (buffer), existing_mark, mark_name, left_gravity, iter, should_exist); - if (gtk_text_btree_mark_is_insert(buffer->tree, mark) || - gtk_text_btree_mark_is_selection_bound(buffer->tree, mark)) + if (gtk_text_btree_mark_is_insert(get_btree (buffer), mark) || + gtk_text_btree_mark_is_selection_bound(get_btree (buffer), mark)) { gtk_text_buffer_update_primary_selection(buffer); } - gtk_text_btree_get_iter_at_mark(buffer->tree, + gtk_text_btree_get_iter_at_mark(get_btree (buffer), &location, mark); @@ -744,7 +785,7 @@ gtk_text_buffer_get_iter_at_mark(GtkTextBuffer *buffer, g_return_if_fail (!gtk_text_mark_deleted (mark)); g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); - gtk_text_btree_get_iter_at_mark(buffer->tree, + gtk_text_btree_get_iter_at_mark(get_btree (buffer), iter, mark); } @@ -757,7 +798,7 @@ gtk_text_buffer_delete_mark(GtkTextBuffer *buffer, g_return_if_fail (!gtk_text_mark_deleted (mark)); g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); - gtk_text_btree_remove_mark (buffer->tree, mark); + gtk_text_btree_remove_mark (get_btree (buffer), mark); /* See rationale above for MARK_SET on why we emit this after removing the mark, rather than removing the mark in a default @@ -775,7 +816,7 @@ gtk_text_buffer_get_mark (GtkTextBuffer *buffer, g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), NULL); g_return_val_if_fail(name != NULL, NULL); - mark = gtk_text_btree_get_mark_by_name(buffer->tree, name); + mark = gtk_text_btree_get_mark_by_name(get_btree (buffer), name); return mark; } @@ -784,13 +825,20 @@ void gtk_text_buffer_place_cursor (GtkTextBuffer *buffer, const GtkTextIter *where) { - g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); + GtkTextIter real; - gtk_text_btree_place_cursor(buffer->tree, where); - gtk_text_buffer_mark_set (buffer, where, + g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); + + real = *where; + + if (gtk_text_iter_is_last (&real)) + gtk_text_iter_prev_char (&real); + + gtk_text_btree_place_cursor(get_btree (buffer), &real); + gtk_text_buffer_mark_set (buffer, &real, gtk_text_buffer_get_mark (buffer, "insert")); - gtk_text_buffer_mark_set (buffer, where, + gtk_text_buffer_mark_set (buffer, &real, gtk_text_buffer_get_mark (buffer, "selection_bound")); } @@ -809,7 +857,7 @@ gtk_text_buffer_create_tag(GtkTextBuffer *buffer, tag = gtk_text_tag_new(tag_name); - gtk_text_tag_table_add(buffer->tag_table, tag); + gtk_text_tag_table_add(get_table (buffer), tag); return tag; } @@ -894,7 +942,7 @@ gtk_text_buffer_apply_tag_by_name (GtkTextBuffer *buffer, g_return_if_fail(start != NULL); g_return_if_fail(end != NULL); - tag = gtk_text_tag_table_lookup(buffer->tag_table, + tag = gtk_text_tag_table_lookup(get_table (buffer), name); if (tag == NULL) @@ -919,7 +967,7 @@ gtk_text_buffer_remove_tag_by_name (GtkTextBuffer *buffer, g_return_if_fail(start != NULL); g_return_if_fail(end != NULL); - tag = gtk_text_tag_table_lookup(buffer->tag_table, + tag = gtk_text_tag_table_lookup(get_table (buffer), name); if (tag == NULL) @@ -945,7 +993,7 @@ gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer, g_return_if_fail(iter != NULL); g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); - gtk_text_btree_get_iter_at_line_char(buffer->tree, + gtk_text_btree_get_iter_at_line_char(get_btree (buffer), iter, line_number, char_offset); } @@ -968,7 +1016,7 @@ gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer, g_return_if_fail(iter != NULL); g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); - gtk_text_btree_get_iter_at_char(buffer->tree, iter, char_offset); + gtk_text_btree_get_iter_at_char(get_btree (buffer), iter, char_offset); } void @@ -978,7 +1026,7 @@ gtk_text_buffer_get_last_iter (GtkTextBuffer *buffer, g_return_if_fail(iter != NULL); g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); - gtk_text_btree_get_last_iter(buffer->tree, iter); + gtk_text_btree_get_last_iter(get_btree (buffer), iter); } void @@ -990,8 +1038,8 @@ gtk_text_buffer_get_bounds (GtkTextBuffer *buffer, g_return_if_fail(end != NULL); g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); - gtk_text_btree_get_iter_at_char(buffer->tree, start, 0); - gtk_text_btree_get_last_iter(buffer->tree, end); + gtk_text_btree_get_iter_at_char(get_btree (buffer), start, 0); + gtk_text_btree_get_last_iter(get_btree (buffer), end); } /* @@ -1070,7 +1118,7 @@ gtk_text_buffer_get_line_count(GtkTextBuffer *buffer) { g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), 0); - return gtk_text_btree_line_count(buffer->tree); + return gtk_text_btree_line_count(get_btree (buffer)); } gint @@ -1078,7 +1126,7 @@ gtk_text_buffer_get_char_count(GtkTextBuffer *buffer) { g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), 0); - return gtk_text_btree_char_count(buffer->tree); + return gtk_text_btree_char_count(get_btree (buffer)); } GSList* @@ -1655,7 +1703,7 @@ gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer, g_return_val_if_fail (buffer != NULL, FALSE); g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); - return gtk_text_btree_get_selection_bounds (buffer->tree, start, end); + return gtk_text_btree_get_selection_bounds (get_btree (buffer), start, end); } @@ -1666,5 +1714,6 @@ gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer, void gtk_text_buffer_spew(GtkTextBuffer *buffer) { - gtk_text_btree_spew(buffer->tree); + gtk_text_btree_spew(get_btree (buffer)); } + diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h index ae18d925ea..cef653c378 100644 --- a/gtk/gtktextbuffer.h +++ b/gtk/gtktextbuffer.h @@ -30,7 +30,7 @@ struct _GtkTextBuffer { GtkObject parent_instance; GtkTextTagTable *tag_table; - GtkTextBTree *tree; + GtkTextBTree *btree; /* Text currently pasted to the clipboard */ gchar *clipboard_text; @@ -97,6 +97,7 @@ gint gtk_text_buffer_get_line_count (GtkTextBuffer *buffer); gint gtk_text_buffer_get_char_count (GtkTextBuffer *buffer); +GtkTextTagTable* gtk_text_buffer_get_tag_table (GtkTextBuffer *buffer); /* Insert into the buffer */ void gtk_text_buffer_insert (GtkTextBuffer *buffer, @@ -278,6 +279,8 @@ gboolean gtk_text_buffer_find_regexp(GtkTextBuffer *buffer, /* INTERNAL private stuff */ void gtk_text_buffer_spew (GtkTextBuffer *buffer); +GtkTextBTree* _gtk_text_buffer_get_btree (GtkTextBuffer *buffer); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c index b3eec2f153..50805d32f6 100644 --- a/gtk/gtktextdisplay.c +++ b/gtk/gtktextdisplay.c @@ -547,9 +547,11 @@ gtk_text_layout_draw (GtkTextLayout *layout, GtkTextIter line_start, line_end; gint byte_count = gtk_text_line_byte_count (line); - gtk_text_btree_get_iter_at_line (layout->buffer->tree, &line_start, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + &line_start, line, 0); - gtk_text_btree_get_iter_at_line (layout->buffer->tree, &line_end, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + &line_end, line, byte_count - 1); if (gtk_text_iter_compare (&selection_start, &line_end) < 0 && diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c index e5b5e09e7a..5e3f1b1078 100644 --- a/gtk/gtktextiter.c +++ b/gtk/gtktextiter.c @@ -2,6 +2,7 @@ #include "gtktextbtree.h" #include "gtktextiterprivate.h" #include "gtkdebug.h" +#include #include typedef struct _GtkTextRealIter GtkTextRealIter; @@ -34,9 +35,9 @@ struct _GtkTextRealIter { and ditto for char offsets. */ gint segment_byte_offset; gint segment_char_offset; - /* These are here for binary-compatible expansion space. */ + /* Pads are here for binary-compatible expansion space. */ gpointer pad1; - gint pad2; + guint pad2; }; /* These "set" functions should not assume any fields @@ -114,7 +115,8 @@ iter_set_from_segment(GtkTextRealIter *iter, /* This function ensures that the segment-dependent information is truly computed lazily; often we don't need to do the full make_real - work. */ + work. This ensures the btree and line are valid, but doesn't + update the segments. */ static GtkTextRealIter* gtk_text_iter_make_surreal(const GtkTextIter *_iter) { @@ -308,9 +310,9 @@ ensure_char_offsets(GtkTextRealIter *iter) g_assert(iter->line_byte_offset >= 0); gtk_text_line_byte_to_char_offsets(iter->line, - iter->line_byte_offset, - &iter->line_char_offset, - &iter->segment_char_offset); + iter->line_byte_offset, + &iter->line_char_offset, + &iter->segment_char_offset); } } @@ -322,9 +324,9 @@ ensure_byte_offsets(GtkTextRealIter *iter) g_assert(iter->line_char_offset >= 0); gtk_text_line_char_to_byte_offsets(iter->line, - iter->line_char_offset, - &iter->line_byte_offset, - &iter->segment_byte_offset); + iter->line_char_offset, + &iter->line_byte_offset, + &iter->segment_byte_offset); } } @@ -487,7 +489,7 @@ gtk_text_iter_get_btree(const GtkTextIter *iter) */ gint -gtk_text_buffer_get_offset(const GtkTextIter *iter) +gtk_text_iter_get_offset(const GtkTextIter *iter) { GtkTextRealIter *real; @@ -690,6 +692,38 @@ gtk_text_iter_get_pixmap (const GtkTextIter *iter, } } +GSList* +gtk_text_iter_get_marks (const GtkTextIter *iter) +{ + GtkTextRealIter *real; + GtkTextLineSegment *seg; + GSList *retval; + + g_return_val_if_fail(iter != NULL, NULL); + + real = gtk_text_iter_make_real(iter); + + if (real == NULL) + return NULL; + + check_invariants(iter); + + retval = NULL; + seg = real->any_segment; + while (seg != real->segment) + { + if (seg->type == >k_text_left_mark_type || + seg->type == >k_text_right_mark_type) + retval = g_slist_prepend(retval, (GtkTextMark*)seg); + + seg = seg->next; + } + + /* The returned list isn't guaranteed to be in any special order, + and it isn't. */ + return retval; +} + GSList* gtk_text_iter_get_toggled_tags (const GtkTextIter *iter, gboolean toggled_on) @@ -878,6 +912,23 @@ gtk_text_iter_editable (const GtkTextIter *iter, return retval; } +static gchar* +gtk_text_iter_get_language (const GtkTextIter *iter) +{ + GtkTextStyleValues *values; + gchar *retval; + + values = gtk_text_style_values_new (); + + gtk_text_iter_get_style_values (iter, values); + + retval = g_strdup (values->language); + + gtk_text_style_values_unref (values); + + return retval; +} + gboolean gtk_text_iter_starts_line (const GtkTextIter *iter) { @@ -913,6 +964,29 @@ gtk_text_iter_ends_line (const GtkTextIter *iter) return gtk_text_iter_get_char(iter) == '\n'; } +gboolean +gtk_text_iter_is_last (const GtkTextIter *iter) +{ + GtkTextRealIter *real; + + g_return_val_if_fail(iter != NULL, FALSE); + + real = gtk_text_iter_make_surreal(iter); + + if (real == NULL) + return FALSE; + + check_invariants(iter); + + return gtk_text_line_is_last(real->line); +} + +gboolean +gtk_text_iter_is_first (const GtkTextIter *iter) +{ + return gtk_text_iter_get_offset (iter) == 0; +} + gint gtk_text_iter_get_chars_in_line (const GtkTextIter *iter) { @@ -988,6 +1062,10 @@ gtk_text_iter_get_style_values (const GtkTextIter *iter, * Increments/decrements */ +/* The return value of this indicates WHETHER WE MOVED. + * The return value of public functions indicates + * (MOVEMENT OCCURRED && NEW ITER IS DEREFERENCEABLE) + */ static gboolean forward_line_leaving_caches_unmodified(GtkTextRealIter *real) { @@ -1012,7 +1090,7 @@ forward_line_leaving_caches_unmodified(GtkTextRealIter *real) real->segment = real->any_segment; while (real->segment->char_count == 0) real->segment = real->segment->next; - + return TRUE; } else @@ -1177,8 +1255,11 @@ gtk_text_iter_forward_indexable_segment(GtkTextIter *iter) g_assert(gtk_text_iter_starts_line(iter)); check_invariants(iter); - - return TRUE; + + if (gtk_text_iter_is_last (iter)) + return FALSE; + else + return TRUE; } else { @@ -1196,6 +1277,8 @@ gtk_text_iter_backward_indexable_segment(GtkTextIter *iter) { g_warning("FIXME"); + + return FALSE; } gboolean @@ -1275,7 +1358,7 @@ gtk_text_iter_forward_chars(GtkTextIter *iter, gint count) check_invariants(iter); - current_char_index = gtk_text_buffer_get_offset(iter); + current_char_index = gtk_text_iter_get_offset(iter); if (current_char_index == gtk_text_btree_char_count(real->tree)) return FALSE; /* can't move forward */ @@ -1285,7 +1368,13 @@ gtk_text_iter_forward_chars(GtkTextIter *iter, gint count) check_invariants(iter); - return TRUE; + /* Return FALSE if we're on the non-dereferenceable end + * iterator. + */ + if (gtk_text_iter_is_last (iter)) + return FALSE; + else + return TRUE; } } @@ -1351,7 +1440,7 @@ gtk_text_iter_backward_chars(GtkTextIter *iter, gint count) gint current_char_index; gint new_char_index; - current_char_index = gtk_text_buffer_get_offset(iter); + current_char_index = gtk_text_iter_get_offset(iter); if (current_char_index == 0) return FALSE; /* can't move backward */ @@ -1387,8 +1476,11 @@ gtk_text_iter_forward_line(GtkTextIter *iter) adjust_line_number(real, 1); check_invariants(iter); - - return TRUE; + + if (gtk_text_iter_is_last (iter)) + return FALSE; + else + return TRUE; } else { @@ -1507,85 +1599,153 @@ gtk_text_iter_backward_lines(GtkTextIter *iter, gint count) } } +typedef gboolean (* FindLogAttrFunc) (PangoLogAttr *attrs, + gint offset, + gint min_offset, + gint len, + gint *found_offset); + static gboolean -is_word_char(gunichar ch, gpointer user_data) +find_word_end_func (PangoLogAttr *attrs, + gint offset, + gint min_offset, + gint len, + gint *found_offset) { - /* will likely need some i18n help FIXME */ - return isalpha(ch); + ++offset; /* We always go to the NEXT word end */ + + /* Find start of next word */ + while (offset < min_offset + len && + !attrs[offset].is_word_stop) + ++offset; + + /* Find end */ + while (offset < min_offset + len && + !attrs[offset].is_white) + ++offset; + + *found_offset = offset; + + return offset < min_offset + len; } static gboolean -is_not_word_char(gunichar ch, gpointer user_data) +find_word_start_func (PangoLogAttr *attrs, + gint offset, + gint min_offset, + gint len, + gint *found_offset) { - return !is_word_char(ch, user_data); + --offset; /* We always go to the NEXT word start */ + + /* Find end of prev word */ + while (offset >= min_offset && + attrs[offset].is_white) + --offset; + + /* Find start */ + while (offset >= min_offset && + !attrs[offset].is_word_stop) + --offset; + + *found_offset = offset; + + return offset >= min_offset; } +/* FIXME this function is very, very gratuitously slow */ static gboolean -gtk_text_iter_is_in_word(const GtkTextIter *iter) +find_by_log_attrs (GtkTextIter *iter, + FindLogAttrFunc func, + gboolean forward) { - gint ch; - - ch = gtk_text_iter_get_char(iter); - - return is_word_char(ch, NULL); -} - -gboolean -gtk_text_iter_forward_word_end(GtkTextIter *iter) -{ - gboolean in_word; + GtkTextIter orig; GtkTextIter start; + GtkTextIter end; + gchar *paragraph; + gint char_len, byte_len; + PangoLogAttr *attrs; + int offset; + gboolean found = FALSE; g_return_val_if_fail(iter != NULL, FALSE); + orig = *iter; start = *iter; - - in_word = gtk_text_iter_is_in_word(iter); + end = *iter; - if (!in_word) + gtk_text_iter_set_line_offset (&start, 0); + gtk_text_iter_forward_to_newline (&end); + + paragraph = gtk_text_iter_get_text (&start, &end); + char_len = g_utf8_strlen (paragraph, -1); + byte_len = strlen (paragraph); + + offset = gtk_text_iter_get_line_offset (iter); + + if (char_len > 0 && offset < char_len) { - if (!gtk_text_iter_forward_find_char(iter, is_word_char, NULL)) - return !gtk_text_iter_equal(iter, &start); - else - in_word = TRUE; + gchar *lang; + + attrs = g_new (PangoLogAttr, char_len); + + lang = gtk_text_iter_get_language (iter); + + pango_get_log_attrs (paragraph, byte_len, -1, + lang, + attrs); + + g_free (lang); + + found = (* func) (attrs, offset, 0, char_len, &offset); + + g_free (attrs); } - - g_assert(in_word); - gtk_text_iter_forward_find_char(iter, is_not_word_char, NULL); + g_free (paragraph); + + if (!found) + { + if (forward) + { + if (gtk_text_iter_forward_line (iter)) + return find_by_log_attrs (iter, func, forward); + else + return FALSE; + } + else + { + if (gtk_text_iter_backward_line (iter)) + return find_by_log_attrs (iter, func, forward); + else + return FALSE; + } + } + else + { + gtk_text_iter_set_line_offset (iter, offset); + + return + !gtk_text_iter_equal(iter, &orig) && + !gtk_text_iter_is_last (iter); + } +} - return !gtk_text_iter_equal(iter, &start); +gboolean +gtk_text_iter_forward_word_end(GtkTextIter *iter) +{ + return find_by_log_attrs (iter, find_word_end_func, TRUE); } gboolean gtk_text_iter_backward_word_start(GtkTextIter *iter) { - gboolean in_word; - GtkTextIter start; - - g_return_val_if_fail(iter != NULL, FALSE); - - start = *iter; - - in_word = gtk_text_iter_is_in_word(iter); - - if (!in_word) - { - if (!gtk_text_iter_backward_find_char(iter, is_word_char, NULL)) - return !gtk_text_iter_equal(iter, &start); - else - in_word = TRUE; - } - - g_assert(in_word); - - gtk_text_iter_backward_find_char(iter, is_not_word_char, NULL); - gtk_text_iter_next_char(iter); /* point to first char of word, - not first non-word char. */ - - return !gtk_text_iter_equal(iter, &start); + return find_by_log_attrs (iter, find_word_start_func, FALSE); } +/* FIXME a loop around a truly slow function means + * a truly spectacularly slow function. + */ gboolean gtk_text_iter_forward_word_ends(GtkTextIter *iter, gint count) @@ -1808,6 +1968,15 @@ gtk_text_iter_forward_find_tag_toggle (GtkTextIter *iter, } } + /* Check end iterator for tags */ + if (gtk_text_iter_toggles_tag(iter, tag)) + { + /* If there's a toggle here, it isn't indexable so + any_segment can't be the indexable segment. */ + g_assert(real->any_segment != real->segment); + return TRUE; + } + /* Reached end of buffer */ return FALSE; } @@ -1866,6 +2035,167 @@ gtk_text_iter_backward_find_char (GtkTextIter *iter, return FALSE; } +static gboolean +lines_match (const GtkTextIter *start, + const gchar **lines, + gboolean visible_only, + GtkTextIter *match_start) +{ + GtkTextIter next; + gchar *line_text; + const gchar *found; + gint offset; + + if (*lines == NULL || **lines == '\0') + return TRUE; + + next = *start; + gtk_text_iter_forward_line (&next); + + /* No more text in buffer, but *lines is nonempty */ + if (gtk_text_iter_equal (start, &next)) + return FALSE; + + if (visible_only) + line_text = gtk_text_iter_get_visible_text (start, &next); + else + line_text = gtk_text_iter_get_text (start, &next); + + if (match_start) /* if this is the first line we're matching */ + found = strstr (line_text, *lines); + else + { + /* If it's not the first line, we have to match from the + * start of the line. + */ + if (strncmp (line_text, *lines, strlen (*lines)) == 0) + found = line_text; + else + found = NULL; + } + + if (found == NULL) + { + g_free (line_text); + return FALSE; + } + + /* Get offset to start of search string */ + offset = g_utf8_strlen (line_text, found - line_text); + + next = *start; + + /* If match start needs to be returned, set it to the + * start of the search string. + */ + if (match_start) + { + *match_start = next; + gtk_text_iter_forward_chars (match_start, offset); + } + + /* Go to end of search string */ + offset += g_utf8_strlen (*lines, -1); + gtk_text_iter_forward_chars (&next, offset); + + g_free (line_text); + + ++lines; + + /* pass NULL for match_start, since we don't need to find the + * start again. + */ + return lines_match (&next, lines, visible_only, NULL); +} + +gboolean +gtk_text_iter_forward_search (GtkTextIter *iter, + const char *str, + gboolean visible_only) +{ + const gchar **lines = NULL; + const gchar *newline; + int line_num = 0; + int allocated = 2; + GtkTextIter match; + gboolean retval = FALSE; + GtkTextIter search; + + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + if (*str == '\0') + return TRUE; /* we found the empty string */ + + /* locate all lines */ + + lines = g_new (const gchar*, allocated); + lines[line_num] = str; + + newline = str; + while (*newline) + { + /* Note that we can have empty lines */ + + if (*newline == '\n') + { + ++newline; + + ++line_num; + + if (line_num == allocated) + { + allocated *= 2; + lines = g_realloc (lines, allocated + 1); /* alloc 1 for nul */ + } + + g_assert (line_num < allocated); + + lines[line_num] = newline; + } + else + ++newline; + } + + ++line_num; + lines[line_num] = NULL; + + search = *iter; + + do + { + /* This loop has an inefficient worst-case, where + * gtk_text_iter_get_text() is called repeatedly on + * a single line. + */ + if (lines_match (&search, lines, visible_only, &match)) + { + retval = TRUE; + + *iter = match; + + break; + } + } + while (gtk_text_iter_forward_line (&search)); + + g_free (lines); + + return retval; +} + +gboolean +gtk_text_iter_backward_search (GtkTextIter *iter, + const char *str, + gboolean visible_only) +{ + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + + +} + /* * Comparisons */ @@ -2192,7 +2522,7 @@ gtk_text_iter_spew (const GtkTextIter *iter, const gchar *desc) g_print(" %20s: line %d / char %d / line char %d / line byte %d\n", desc, gtk_text_iter_get_line(iter), - gtk_text_buffer_get_offset(iter), + gtk_text_iter_get_offset(iter), gtk_text_iter_get_line_offset(iter), gtk_text_iter_get_line_index(iter)); check_invariants(iter); diff --git a/gtk/gtktextiter.h b/gtk/gtktextiter.h index 45d14ca44e..e50ea3d72a 100644 --- a/gtk/gtktextiter.h +++ b/gtk/gtktextiter.h @@ -28,7 +28,7 @@ struct _GtkTextIter { gpointer dummy8; gint dummy9; gpointer pad1; - gint pad2; + guint pad2; }; @@ -47,7 +47,7 @@ void gtk_text_iter_free (GtkTextIter *iter); * Convert to different kinds of index */ -gint gtk_text_buffer_get_offset (const GtkTextIter *iter); +gint gtk_text_iter_get_offset (const GtkTextIter *iter); gint gtk_text_iter_get_line (const GtkTextIter *iter); gint gtk_text_iter_get_line_offset (const GtkTextIter *iter); gint gtk_text_iter_get_line_index (const GtkTextIter *iter); @@ -77,6 +77,8 @@ gboolean gtk_text_iter_get_pixmap (const GtkTextIter *iter, GdkPixmap **pixmap, GdkBitmap **mask); +GSList *gtk_text_iter_get_marks (const GtkTextIter *iter); + /* Return list of tags toggled at this point (toggled_on determines whether the list is of on-toggles or off-toggles) */ GSList *gtk_text_iter_get_toggled_tags (const GtkTextIter *iter, @@ -105,6 +107,9 @@ gint gtk_text_iter_get_chars_in_line (const GtkTextIter *iter); gboolean gtk_text_iter_get_style_values (const GtkTextIter *iter, GtkTextStyleValues *values); +gboolean gtk_text_iter_is_last (const GtkTextIter *iter); +gboolean gtk_text_iter_is_first (const GtkTextIter *iter); + /* * Moving around the buffer */ @@ -129,7 +134,7 @@ gboolean gtk_text_iter_forward_word_end (GtkTextIter *iter); gboolean gtk_text_iter_backward_word_start (GtkTextIter *iter); void gtk_text_iter_set_offset (GtkTextIter *iter, - gint char_index); + gint char_offset); void gtk_text_iter_set_line (GtkTextIter *iter, gint line_number); void gtk_text_iter_set_line_offset (GtkTextIter *iter, @@ -157,16 +162,24 @@ gboolean gtk_text_iter_backward_find_char (GtkTextIter *iter, GtkTextCharPredicate pred, gpointer user_data); +gboolean gtk_text_iter_forward_search (GtkTextIter *iter, + const char *str, + gboolean visible_only); + +gboolean gtk_text_iter_backward_search (GtkTextIter *iter, + const char *str, + gboolean visible_only); + /* * Comparisons */ gboolean gtk_text_iter_equal (const GtkTextIter *lhs, - const GtkTextIter *rhs); + const GtkTextIter *rhs); gint gtk_text_iter_compare (const GtkTextIter *lhs, - const GtkTextIter *rhs); + const GtkTextIter *rhs); gboolean gtk_text_iter_in_region (const GtkTextIter *iter, - const GtkTextIter *start, - const GtkTextIter *end); + const GtkTextIter *start, + const GtkTextIter *end); /* Put these two in ascending order */ void gtk_text_iter_reorder (GtkTextIter *first, diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 80ed886ce7..a6756e595a 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -246,7 +246,8 @@ gtk_text_layout_set_buffer (GtkTextLayout *layout, if (layout->buffer) { - gtk_text_btree_remove_view (layout->buffer->tree, layout); + gtk_text_btree_remove_view (_gtk_text_buffer_get_btree (layout->buffer), + layout); gtk_object_unref (GTK_OBJECT (layout->buffer)); layout->buffer = NULL; @@ -259,7 +260,7 @@ gtk_text_layout_set_buffer (GtkTextLayout *layout, gtk_object_sink (GTK_OBJECT (buffer)); gtk_object_ref (GTK_OBJECT (buffer)); - gtk_text_btree_add_view (buffer->tree, layout); + gtk_text_btree_add_view (_gtk_text_buffer_get_btree (buffer), layout); } } @@ -337,7 +338,8 @@ gtk_text_layout_get_size (GtkTextLayout *layout, g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); - gtk_text_btree_get_view_size (layout->buffer->tree, layout, + gtk_text_btree_get_view_size (_gtk_text_buffer_get_btree (layout->buffer), + layout, &w, &h); layout->width = w; @@ -419,7 +421,9 @@ gtk_text_layout_get_lines (GtkTextLayout *layout, retval = NULL; - first_btree_line = gtk_text_btree_find_line_by_y (layout->buffer->tree, layout, top_y, first_line_y); + first_btree_line = + gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer), + layout, top_y, first_line_y); if (first_btree_line == NULL) { g_assert (top_y > 0); @@ -428,11 +432,15 @@ gtk_text_layout_get_lines (GtkTextLayout *layout, } /* -1 since bottom_y is one past */ - last_btree_line = gtk_text_btree_find_line_by_y (layout->buffer->tree, layout, bottom_y - 1, NULL); + last_btree_line = + gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer), + layout, bottom_y - 1, NULL); if (!last_btree_line) - last_btree_line = gtk_text_btree_get_line (layout->buffer->tree, - gtk_text_btree_line_count (layout->buffer->tree) - 1, NULL); + last_btree_line = + gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer), + gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, + NULL); { GtkTextLineData *ld = gtk_text_line_get_data (last_btree_line, layout); @@ -588,7 +596,8 @@ gtk_text_layout_is_valid (GtkTextLayout *layout) g_return_val_if_fail (layout != NULL, FALSE); g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), FALSE); - return gtk_text_btree_is_valid (layout->buffer->tree, layout); + return gtk_text_btree_is_valid (_gtk_text_buffer_get_btree (layout->buffer), + layout); } /** @@ -639,7 +648,8 @@ gtk_text_layout_validate_yrange (GtkTextLayout *layout, { gint old_height = line_data ? line_data->height : 0; - gtk_text_btree_validate_line (layout->buffer->tree, line, layout); + gtk_text_btree_validate_line (_gtk_text_buffer_get_btree (layout->buffer), + line, layout); line_data = gtk_text_line_get_data (line, layout); delta_height += line_data->height - old_height; @@ -667,7 +677,8 @@ gtk_text_layout_validate_yrange (GtkTextLayout *layout, { gint old_height = line_data ? line_data->height : 0; - gtk_text_btree_validate_line (layout->buffer->tree, line, layout); + gtk_text_btree_validate_line (_gtk_text_buffer_get_btree (layout->buffer), + line, layout); line_data = gtk_text_line_get_data (line, layout); delta_height += line_data->height - old_height; @@ -689,7 +700,9 @@ gtk_text_layout_validate_yrange (GtkTextLayout *layout, */ if (first_line) { - gint line_top = gtk_text_btree_find_line_top (layout->buffer->tree, first_line, layout); + gint line_top = + gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), + first_line, layout); gtk_text_layout_changed (layout, line_top, @@ -717,7 +730,8 @@ gtk_text_layout_validate (GtkTextLayout *layout, g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); while (max_pixels > 0 && - gtk_text_btree_validate (layout->buffer->tree, layout, max_pixels, + gtk_text_btree_validate (_gtk_text_buffer_get_btree (layout->buffer), + layout, max_pixels, &y, &old_height, &new_height)) { max_pixels -= new_height; @@ -869,7 +883,8 @@ totally_invisible_line (GtkTextLayout *layout, function can use the whole btree to get it right. */ else { - gtk_text_btree_get_iter_at_line(layout->buffer->tree, iter, line, 0); + gtk_text_btree_get_iter_at_line(_gtk_text_buffer_get_btree (layout->buffer), + iter, line, 0); if (!gtk_text_btree_char_is_invisible (iter)) return FALSE; @@ -1117,7 +1132,8 @@ add_cursor (GtkTextLayout *layout, /* Hide insertion cursor when we have a selection */ - if (gtk_text_btree_mark_is_insert (layout->buffer->tree, (GtkTextMark*)seg) && + if (gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer), + (GtkTextMark*)seg) && gtk_text_buffer_get_selection_bounds (layout->buffer, &selection_start, &selection_end)) return; @@ -1187,7 +1203,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, display->size_only = size_only; display->line = line; - gtk_text_btree_get_iter_at_line (layout->buffer->tree, &iter, line, 0); + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + &iter, line, 0); /* Special-case optimization for completely * invisible lines; makes it faster to deal @@ -1212,7 +1229,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, if (seg->type == >k_text_char_type || seg->type == >k_text_pixmap_type) { - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), &iter, line, byte_offset); style = get_style (layout, &iter); @@ -1401,13 +1418,16 @@ get_line_at_y (GtkTextLayout *layout, if (y > layout->height) y = layout->height; - *line = gtk_text_btree_find_line_by_y (layout->buffer->tree, layout, y, line_top); + *line = gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer), + layout, y, line_top); if (*line == NULL) { - *line = gtk_text_btree_get_line (layout->buffer->tree, - gtk_text_btree_line_count (layout->buffer->tree) - 1, NULL); + *line = gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer), + gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, NULL); if (line_top) - *line_top = gtk_text_btree_find_line_top (layout->buffer->tree, *line, layout); + *line_top = + gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), + *line, layout); } } @@ -1434,7 +1454,8 @@ gtk_text_layout_get_line_at_y (GtkTextLayout *layout, g_return_if_fail (target_iter != NULL); get_line_at_y (layout, y, &line, line_top); - gtk_text_btree_get_iter_at_line (layout->buffer->tree, target_iter, line, 0); + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + target_iter, line, 0); } void @@ -1477,7 +1498,7 @@ gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout, trailing = 0; } - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), target_iter, line, byte_index); @@ -1520,7 +1541,8 @@ gtk_text_layout_get_cursor_locations (GtkTextLayout *layout, g_return_if_fail (iter != NULL); line = gtk_text_iter_get_text_line (iter); - line_top = gtk_text_btree_find_line_top (layout->buffer->tree, line, layout); + line_top = gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), + line, layout); display = gtk_text_layout_get_line_display (layout, line, TRUE); @@ -1564,10 +1586,11 @@ gtk_text_layout_get_line_y (GtkTextLayout *layout, GtkTextLine *line; g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), 0); - g_return_val_if_fail (gtk_text_iter_get_btree (iter) == layout->buffer->tree, 0); + g_return_val_if_fail (gtk_text_iter_get_btree (iter) == _gtk_text_buffer_get_btree (layout->buffer), 0); line = gtk_text_iter_get_text_line (iter); - return gtk_text_btree_find_line_top (layout->buffer->tree, line, layout); + return gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), + line, layout); } void @@ -1582,7 +1605,7 @@ gtk_text_layout_get_iter_location (GtkTextLayout *layout, gint byte_index; g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); - g_return_if_fail (gtk_text_iter_get_btree (iter) == layout->buffer->tree); + g_return_if_fail (gtk_text_iter_get_btree (iter) == _gtk_text_buffer_get_btree (layout->buffer)); g_return_if_fail (rect != NULL); tree = gtk_text_iter_get_btree (iter); @@ -1592,32 +1615,14 @@ gtk_text_layout_get_iter_location (GtkTextLayout *layout, rect->y = gtk_text_btree_find_line_top (tree, line, layout); - /* pango_layout_index_to_pos() expects the index of a character within the layout, - * so we have to special case the last character. FIXME: This should be moved - * to Pango. - */ - if (gtk_text_iter_ends_line (iter)) - { - PangoLayoutLine *last_line = g_slist_last (pango_layout_get_lines (display->layout))->data; - - pango_layout_line_get_extents (last_line, NULL, &pango_rect); - - rect->x = display->x_offset + (pango_rect.x + pango_rect.width) / PANGO_SCALE; - rect->y += display->top_margin; - rect->width = 0; - rect->height = pango_rect.height / PANGO_SCALE; - } - else - { - byte_index = gtk_text_iter_get_line_index (iter); + byte_index = gtk_text_iter_get_line_index (iter); - pango_layout_index_to_pos (display->layout, byte_index, &pango_rect); - - rect->x = display->x_offset + pango_rect.x / PANGO_SCALE; - rect->y += display->top_margin; - rect->width = pango_rect.width / PANGO_SCALE; - rect->height = pango_rect.height / PANGO_SCALE; - } + pango_layout_index_to_pos (display->layout, byte_index, &pango_rect); + + rect->x = display->x_offset + pango_rect.x / PANGO_SCALE; + rect->y += display->top_margin + pango_rect.y / PANGO_SCALE; + rect->width = pango_rect.width / PANGO_SCALE; + rect->height = pango_rect.height / PANGO_SCALE; gtk_text_layout_free_line_display (layout, display); } @@ -1636,12 +1641,17 @@ find_display_line_below (GtkTextLayout *layout, gint line_top; gint found_byte = 0; - line = gtk_text_btree_find_line_by_y (layout->buffer->tree, layout, y, &line_top); + line = gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer), + layout, y, &line_top); if (!line) { - line = gtk_text_btree_get_line (layout->buffer->tree, - gtk_text_btree_line_count (layout->buffer->tree) - 1, NULL); - line_top = gtk_text_btree_find_line_top (layout->buffer->tree, line, layout); + line = + gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer), + gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, + NULL); + line_top = + gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), + line, layout); } while (line && !found_line) @@ -1681,7 +1691,8 @@ find_display_line_below (GtkTextLayout *layout, line = next; } - gtk_text_btree_get_iter_at_line (layout->buffer->tree, iter, found_line, found_byte); + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + iter, found_line, found_byte); } /* Find the iter for the logical beginning of the last display line whose @@ -1698,12 +1709,12 @@ find_display_line_above (GtkTextLayout *layout, gint line_top; gint found_byte = 0; - line = gtk_text_btree_find_line_by_y (layout->buffer->tree, layout, y, &line_top); + line = gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer), layout, y, &line_top); if (!line) { - line = gtk_text_btree_get_line (layout->buffer->tree, - gtk_text_btree_line_count (layout->buffer->tree) - 1, NULL); - line_top = gtk_text_btree_find_line_top (layout->buffer->tree, line, layout); + line = gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer), + gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, NULL); + line_top = gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), line, layout); } while (line && !found_line) @@ -1747,7 +1758,8 @@ find_display_line_above (GtkTextLayout *layout, } if (found_line) - gtk_text_btree_get_iter_at_line (layout->buffer->tree, iter, found_line, found_byte); + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + iter, found_line, found_byte); else gtk_text_buffer_get_iter_at_offset (layout->buffer, iter, 0); } @@ -1821,7 +1833,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, g_return_if_fail (iter != NULL); line = gtk_text_iter_get_text_line (iter); - line_byte = gtk_text_iter_get_line_offset (iter); + line_byte = gtk_text_iter_get_line_index (iter); display = gtk_text_layout_get_line_display (layout, line, TRUE); @@ -1849,11 +1861,11 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, byte_offset += layout_line->length; } - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, prev_line, byte_offset); } else - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, line, 0); } else @@ -1868,7 +1880,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, if (line_byte < byte_offset + layout_line->length || !tmp_list->next) { - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, line, prev_offset); break; } @@ -1907,7 +1919,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout, g_return_if_fail (iter != NULL); line = gtk_text_iter_get_text_line (iter); - line_byte = gtk_text_iter_get_line_offset (iter); + line_byte = gtk_text_iter_get_line_index (iter); while (line && !found_after) { @@ -1923,7 +1935,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout, if (found) { - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, line, byte_offset); found_after = TRUE; @@ -2005,7 +2017,7 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout, x * PANGO_SCALE - x_offset, &byte_index, &trailing); - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, line, byte_index); @@ -2090,7 +2102,7 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout, new_index = 0; } - gtk_text_btree_get_iter_at_line (layout->buffer->tree, + gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, line, new_index); while (new_trailing--) diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index 9cf85f4cb8..05fba688a0 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -923,6 +923,14 @@ delta_priority_foreach(GtkTextTag *tag, gpointer user_data) tag->priority += dd->delta; } +gint +gtk_text_tag_get_priority (GtkTextTag *tag) +{ + g_return_val_if_fail(GTK_IS_TEXT_TAG(tag), 0); + + return tag->priority; +} + void gtk_text_tag_set_priority(GtkTextTag *tag, gint priority) diff --git a/gtk/gtktexttag.h b/gtk/gtktexttag.h index 30f43c2be2..3e5dd82a33 100644 --- a/gtk/gtktexttag.h +++ b/gtk/gtktexttag.h @@ -96,6 +96,7 @@ struct _GtkTextTagClass { GtkType gtk_text_tag_get_type (void); GtkTextTag *gtk_text_tag_new (const gchar *name); +gint gtk_text_tag_get_priority (GtkTextTag *tag); void gtk_text_tag_set_priority (GtkTextTag *tag, gint priority); gint gtk_text_tag_event (GtkTextTag *tag, diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index a255bed508..5cecceb37a 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -216,6 +216,9 @@ static void gtk_text_view_set_virtual_cursor_pos (GtkTextView *text_view, gint x, gint y); +static GtkAdjustment* get_hadjustment (GtkTextView *text_view); +static GtkAdjustment* get_vadjustment (GtkTextView *text_view); + enum { TARGET_STRING, TARGET_TEXT, @@ -826,7 +829,7 @@ gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view, if (scroll_inc != 0) { - set_adjustment_clamped (text_view->vadjustment, + set_adjustment_clamped (get_vadjustment (text_view), current_y_scroll + scroll_inc); retval = TRUE; } @@ -847,7 +850,7 @@ gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view, if (scroll_inc != 0) { - set_adjustment_clamped (text_view->hadjustment, + set_adjustment_clamped (get_hadjustment (text_view), current_x_scroll + scroll_inc); retval = TRUE; } @@ -1041,8 +1044,11 @@ gtk_text_view_finalize (GObject *object) text_view = GTK_TEXT_VIEW (object); - gtk_object_unref (GTK_OBJECT (text_view->hadjustment)); - gtk_object_unref (GTK_OBJECT (text_view->vadjustment)); + if (text_view->hadjustment) + gtk_object_unref (GTK_OBJECT (text_view->hadjustment)); + if (text_view->vadjustment) + gtk_object_unref (GTK_OBJECT (text_view->vadjustment)); + gtk_object_unref (GTK_OBJECT (text_view->im_context)); (* G_OBJECT_CLASS (parent_class)->finalize) (object); @@ -1127,8 +1133,8 @@ gtk_text_view_size_request (GtkWidget *widget, GtkTextView *text_view = GTK_TEXT_VIEW (widget); /* Hrm */ - requisition->width = 1; - requisition->height = 1; + requisition->width = 200; + requisition->height = 200; /* Check to see if the widget direction has changed */ @@ -1180,6 +1186,10 @@ gtk_text_view_size_allocate (GtkWidget *widget, gtk_text_view_get_first_para_iter (text_view, &first_para); y = gtk_text_layout_get_line_y (text_view->layout, &first_para) + text_view->first_para_pixels; + /* Ensure h/v adj exist */ + get_hadjustment (text_view); + get_vadjustment (text_view); + vadj = text_view->vadjustment; if (y > vadj->upper - vadj->page_size) y = MAX (0, vadj->upper - vadj->page_size); @@ -1189,7 +1199,7 @@ gtk_text_view_size_allocate (GtkWidget *widget, vadj->value = text_view->yoffset = y; yoffset_changed = TRUE; } - + text_view->hadjustment->page_size = allocation->width; text_view->hadjustment->page_increment = allocation->width / 2; text_view->hadjustment->lower = 0; @@ -1308,15 +1318,14 @@ changed_handler (GtkTextLayout *layout, if (start_y + old_height <= text_view->yoffset - text_view->first_para_pixels) { text_view->yoffset += new_height - old_height; - text_view->vadjustment->value = text_view->yoffset; + get_vadjustment (text_view)->value = text_view->yoffset; yoffset_changed = TRUE; } gtk_text_view_scroll_calc_now (text_view); if (yoffset_changed) - gtk_adjustment_value_changed (text_view->vadjustment); - + gtk_adjustment_value_changed (get_vadjustment (text_view)); } } @@ -2428,11 +2437,13 @@ gtk_text_view_scroll_calc_now (GtkTextView *text_view) text_view->width = width; text_view->height = height; - gtk_text_view_set_adjustment_upper (text_view->hadjustment, + gtk_text_view_set_adjustment_upper (get_hadjustment (text_view), MAX (widget->allocation.width, width)); - gtk_text_view_set_adjustment_upper (text_view->vadjustment, + gtk_text_view_set_adjustment_upper (get_vadjustment (text_view), MAX (widget->allocation.height, height)); + /* hadj/vadj exist since we called get_hadjustment/get_vadjustment above */ + /* Set up the step sizes; we'll say that a page is our allocation minus one step, and a step is 1/10 of our allocation. */ @@ -2871,6 +2882,33 @@ gtk_text_view_drag_data_received (GtkWidget *widget, } } +static GtkAdjustment* +get_hadjustment (GtkTextView *text_view) +{ + if (text_view->hadjustment == NULL) + gtk_text_view_set_scroll_adjustments (text_view, + (GtkAdjustment*) + gtk_adjustment_new (0.0, 0.0, 0.0, + 0.0, 0.0, 0.0), + text_view->vadjustment); + + return text_view->hadjustment; +} + +static GtkAdjustment* +get_vadjustment (GtkTextView *text_view) +{ + if (text_view->vadjustment == NULL) + gtk_text_view_set_scroll_adjustments (text_view, + text_view->hadjustment, + (GtkAdjustment*) + gtk_adjustment_new (0.0, 0.0, 0.0, + 0.0, 0.0, 0.0)); + + return text_view->vadjustment; +} + + static void gtk_text_view_set_scroll_adjustments (GtkTextView *text_view, GtkAdjustment *hadj, diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 1ac101450e..4f86df446b 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -1586,10 +1586,8 @@ static void gtk_window_real_set_transient_for (GtkWindow *window, GtkWindow *parent) { - g_return_if_fail (window != NULL); - g_return_if_fail (parent != NULL); g_return_if_fail (GTK_IS_WINDOW (window)); - g_return_if_fail (GTK_IS_WINDOW (parent)); + g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent)); g_return_if_fail (window != parent); if (window->transient_parent) diff --git a/gtk/testtext.c b/gtk/testtext.c index fcdec01ce2..42591859bc 100644 --- a/gtk/testtext.c +++ b/gtk/testtext.c @@ -21,6 +21,7 @@ struct _Buffer char *filename; gint untitled_serial; GtkTextTag *not_editable_tag; + GtkTextTag *found_text_tag; }; struct _View @@ -42,6 +43,9 @@ static gboolean save_buffer (Buffer *buffer); static gboolean save_as_buffer (Buffer *buffer); static char * buffer_pretty_name (Buffer *buffer); static void buffer_filename_set (Buffer *buffer); +static void buffer_search_forward (Buffer *buffer, + const char *str, + View *view); static View *view_from_widget (GtkWidget *widget); @@ -313,7 +317,7 @@ tag_event_handler (GtkTextTag *tag, GtkWidget *widget, GdkEvent *event, { gint char_index; - char_index = gtk_text_buffer_get_offset (iter); + char_index = gtk_text_iter_get_offset (iter); switch (event->type) { @@ -891,6 +895,71 @@ do_apply_editable (gpointer callback_data, } } +static void +dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) +{ + GtkTextBuffer *buffer; + View *view = data; + GtkTextIter start, end; + gchar *search_string; + + buffer = gtk_object_get_data (GTK_OBJECT (dialog), "buffer"); + + gtk_text_buffer_get_bounds (buffer, &start, &end); + + /* Remove trailing newline */ + gtk_text_iter_prev_char (&end); + + search_string = gtk_text_iter_get_text (&start, &end); + + printf ("Searching for `%s'\n", search_string); + + buffer_search_forward (view->buffer, search_string, view); + + g_free (search_string); + + gtk_widget_destroy (dialog); +} + +static void +do_search (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + View *view = view_from_widget (widget); + GtkWidget *dialog; + GtkWidget *search_text; + GtkTextBuffer *buffer; + + dialog = gtk_dialog_new_with_buttons ("Search", + GTK_WINDOW (view->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_BUTTON_OK, + 0, NULL); + + buffer = gtk_text_buffer_new (NULL); + + /* FIXME memory leak once buffer is a GObject */ + search_text = gtk_text_view_new_with_buffer (buffer); + + gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox), + search_text, + TRUE, TRUE, 0); + + gtk_object_set_data (GTK_OBJECT (dialog), "buffer", buffer); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (dialog_response_callback), + view); + + gtk_widget_show (search_text); + + gtk_widget_grab_focus (search_text); + + gtk_widget_show_all (dialog); +} + static void view_init_menus (View *view) { @@ -941,6 +1010,9 @@ static GtkItemFactoryEntry menu_items[] = { "/File/_Close", "W" , do_close, 0, NULL }, { "/File/E_xit", "Q" , do_exit, 0, NULL }, + { "/_Edit", NULL, 0, 0, "" }, + { "/Edit/Find...", NULL, do_search, 0, NULL }, + { "/_Settings", NULL, 0, 0, "" }, { "/Settings/Wrap _Off", NULL, do_wrap_changed, GTK_WRAPMODE_NONE, "" }, { "/Settings/Wrap _Words", NULL, do_wrap_changed, GTK_WRAPMODE_WORD, "/Settings/Wrap Off" }, @@ -1127,6 +1199,10 @@ create_buffer (void) gtk_object_set (GTK_OBJECT (buffer->not_editable_tag), "editable", FALSE, "foreground", "purple", NULL); + + buffer->found_text_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL); + gtk_object_set (GTK_OBJECT (buffer->found_text_tag), + "foreground", "red", NULL); buffers = g_slist_prepend (buffers, buffer); @@ -1174,6 +1250,55 @@ buffer_filename_set (Buffer *buffer) } } +static void +buffer_search_forward (Buffer *buffer, const char *str, + View *view) +{ + GtkTextIter iter; + GtkTextIter start, end; + gint char_len; + int i = 0; + GtkWidget *dialog; + + /* remove tag from whole buffer */ + gtk_text_buffer_get_bounds (buffer->buffer, &start, &end); + gtk_text_buffer_remove_tag (buffer->buffer, buffer->found_text_tag, + &start, &end ); + + gtk_text_buffer_get_iter_at_mark (buffer->buffer, &iter, + gtk_text_buffer_get_mark (buffer->buffer, + "insert")); + + + char_len = g_utf8_strlen (str, -1); + + while (gtk_text_iter_forward_search (&iter, str, TRUE)) + { + GtkTextIter end = iter; + + gtk_text_iter_forward_chars (&end, char_len); + + gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, + &iter, &end); + + ++i; + } + + dialog = gtk_message_dialog_new (GTK_WINDOW (view->window), + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + GTK_DIALOG_DESTROY_WITH_PARENT, + "%d strings found and marked in red", + i); + + gtk_signal_connect_object (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (dialog)); + + gtk_widget_show (dialog); +} + static void buffer_ref (Buffer *buffer) { @@ -1292,7 +1417,8 @@ main (int argc, char** argv) int i; gtk_init (&argc, &argv); - + gdk_rgb_init (); /* FIXME remove this */ + buffer = create_buffer (); view = create_view (buffer); buffer_unref (buffer); diff --git a/gtk/testtextbuffer.c b/gtk/testtextbuffer.c index fb0ca8ff92..8047dc62df 100644 --- a/gtk/testtextbuffer.c +++ b/gtk/testtextbuffer.c @@ -101,7 +101,7 @@ run_tests (GtkTextBuffer *buffer) g_error ("get_char_index didn't return current iter"); } - j = gtk_text_buffer_get_offset (&iter); + j = gtk_text_iter_get_offset (&iter); if (i != j) { @@ -128,9 +128,12 @@ run_tests (GtkTextBuffer *buffer) gtk_text_iter_spew (&mark, "mark"); g_error ("Mark not created in the right place."); } + + if (gtk_text_iter_is_last (&iter)) + g_error ("iterators ran out before chars (offset %d of %d)", + i, num_chars); - if (!gtk_text_iter_next_char (&iter)) - g_error ("iterators ran out before chars"); + gtk_text_iter_next_char (&iter); gtk_text_buffer_move_mark (buffer, bar_mark, &iter); @@ -163,7 +166,7 @@ run_tests (GtkTextBuffer *buffer) { g_error ("get_char_index didn't return current iter while going backward"); } - j = gtk_text_buffer_get_offset (&iter); + j = gtk_text_iter_get_offset (&iter); if (i != j) { @@ -218,11 +221,10 @@ run_tests (GtkTextBuffer *buffer) gtk_text_buffer_get_iter_at_line (buffer, &iter, 0); while (gtk_text_iter_forward_line (&iter)) ++i; - - /* Add 1 to the line count, because 'i' counts the end-iterator line */ - if (i != gtk_text_buffer_get_line_count (buffer) + 1) + + if (i != gtk_text_buffer_get_line_count (buffer)) g_error ("Counted %d lines, buffer has %d", i, - gtk_text_buffer_get_line_count (buffer) + 1); + gtk_text_buffer_get_line_count (buffer)); } diff --git a/tests/testtext.c b/tests/testtext.c index fcdec01ce2..42591859bc 100644 --- a/tests/testtext.c +++ b/tests/testtext.c @@ -21,6 +21,7 @@ struct _Buffer char *filename; gint untitled_serial; GtkTextTag *not_editable_tag; + GtkTextTag *found_text_tag; }; struct _View @@ -42,6 +43,9 @@ static gboolean save_buffer (Buffer *buffer); static gboolean save_as_buffer (Buffer *buffer); static char * buffer_pretty_name (Buffer *buffer); static void buffer_filename_set (Buffer *buffer); +static void buffer_search_forward (Buffer *buffer, + const char *str, + View *view); static View *view_from_widget (GtkWidget *widget); @@ -313,7 +317,7 @@ tag_event_handler (GtkTextTag *tag, GtkWidget *widget, GdkEvent *event, { gint char_index; - char_index = gtk_text_buffer_get_offset (iter); + char_index = gtk_text_iter_get_offset (iter); switch (event->type) { @@ -891,6 +895,71 @@ do_apply_editable (gpointer callback_data, } } +static void +dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) +{ + GtkTextBuffer *buffer; + View *view = data; + GtkTextIter start, end; + gchar *search_string; + + buffer = gtk_object_get_data (GTK_OBJECT (dialog), "buffer"); + + gtk_text_buffer_get_bounds (buffer, &start, &end); + + /* Remove trailing newline */ + gtk_text_iter_prev_char (&end); + + search_string = gtk_text_iter_get_text (&start, &end); + + printf ("Searching for `%s'\n", search_string); + + buffer_search_forward (view->buffer, search_string, view); + + g_free (search_string); + + gtk_widget_destroy (dialog); +} + +static void +do_search (gpointer callback_data, + guint callback_action, + GtkWidget *widget) +{ + View *view = view_from_widget (widget); + GtkWidget *dialog; + GtkWidget *search_text; + GtkTextBuffer *buffer; + + dialog = gtk_dialog_new_with_buttons ("Search", + GTK_WINDOW (view->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_BUTTON_OK, + 0, NULL); + + buffer = gtk_text_buffer_new (NULL); + + /* FIXME memory leak once buffer is a GObject */ + search_text = gtk_text_view_new_with_buffer (buffer); + + gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox), + search_text, + TRUE, TRUE, 0); + + gtk_object_set_data (GTK_OBJECT (dialog), "buffer", buffer); + + gtk_signal_connect (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (dialog_response_callback), + view); + + gtk_widget_show (search_text); + + gtk_widget_grab_focus (search_text); + + gtk_widget_show_all (dialog); +} + static void view_init_menus (View *view) { @@ -941,6 +1010,9 @@ static GtkItemFactoryEntry menu_items[] = { "/File/_Close", "W" , do_close, 0, NULL }, { "/File/E_xit", "Q" , do_exit, 0, NULL }, + { "/_Edit", NULL, 0, 0, "" }, + { "/Edit/Find...", NULL, do_search, 0, NULL }, + { "/_Settings", NULL, 0, 0, "" }, { "/Settings/Wrap _Off", NULL, do_wrap_changed, GTK_WRAPMODE_NONE, "" }, { "/Settings/Wrap _Words", NULL, do_wrap_changed, GTK_WRAPMODE_WORD, "/Settings/Wrap Off" }, @@ -1127,6 +1199,10 @@ create_buffer (void) gtk_object_set (GTK_OBJECT (buffer->not_editable_tag), "editable", FALSE, "foreground", "purple", NULL); + + buffer->found_text_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL); + gtk_object_set (GTK_OBJECT (buffer->found_text_tag), + "foreground", "red", NULL); buffers = g_slist_prepend (buffers, buffer); @@ -1174,6 +1250,55 @@ buffer_filename_set (Buffer *buffer) } } +static void +buffer_search_forward (Buffer *buffer, const char *str, + View *view) +{ + GtkTextIter iter; + GtkTextIter start, end; + gint char_len; + int i = 0; + GtkWidget *dialog; + + /* remove tag from whole buffer */ + gtk_text_buffer_get_bounds (buffer->buffer, &start, &end); + gtk_text_buffer_remove_tag (buffer->buffer, buffer->found_text_tag, + &start, &end ); + + gtk_text_buffer_get_iter_at_mark (buffer->buffer, &iter, + gtk_text_buffer_get_mark (buffer->buffer, + "insert")); + + + char_len = g_utf8_strlen (str, -1); + + while (gtk_text_iter_forward_search (&iter, str, TRUE)) + { + GtkTextIter end = iter; + + gtk_text_iter_forward_chars (&end, char_len); + + gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, + &iter, &end); + + ++i; + } + + dialog = gtk_message_dialog_new (GTK_WINDOW (view->window), + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + GTK_DIALOG_DESTROY_WITH_PARENT, + "%d strings found and marked in red", + i); + + gtk_signal_connect_object (GTK_OBJECT (dialog), + "response", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (dialog)); + + gtk_widget_show (dialog); +} + static void buffer_ref (Buffer *buffer) { @@ -1292,7 +1417,8 @@ main (int argc, char** argv) int i; gtk_init (&argc, &argv); - + gdk_rgb_init (); /* FIXME remove this */ + buffer = create_buffer (); view = create_view (buffer); buffer_unref (buffer); diff --git a/tests/testtextbuffer.c b/tests/testtextbuffer.c index fb0ca8ff92..8047dc62df 100644 --- a/tests/testtextbuffer.c +++ b/tests/testtextbuffer.c @@ -101,7 +101,7 @@ run_tests (GtkTextBuffer *buffer) g_error ("get_char_index didn't return current iter"); } - j = gtk_text_buffer_get_offset (&iter); + j = gtk_text_iter_get_offset (&iter); if (i != j) { @@ -128,9 +128,12 @@ run_tests (GtkTextBuffer *buffer) gtk_text_iter_spew (&mark, "mark"); g_error ("Mark not created in the right place."); } + + if (gtk_text_iter_is_last (&iter)) + g_error ("iterators ran out before chars (offset %d of %d)", + i, num_chars); - if (!gtk_text_iter_next_char (&iter)) - g_error ("iterators ran out before chars"); + gtk_text_iter_next_char (&iter); gtk_text_buffer_move_mark (buffer, bar_mark, &iter); @@ -163,7 +166,7 @@ run_tests (GtkTextBuffer *buffer) { g_error ("get_char_index didn't return current iter while going backward"); } - j = gtk_text_buffer_get_offset (&iter); + j = gtk_text_iter_get_offset (&iter); if (i != j) { @@ -218,11 +221,10 @@ run_tests (GtkTextBuffer *buffer) gtk_text_buffer_get_iter_at_line (buffer, &iter, 0); while (gtk_text_iter_forward_line (&iter)) ++i; - - /* Add 1 to the line count, because 'i' counts the end-iterator line */ - if (i != gtk_text_buffer_get_line_count (buffer) + 1) + + if (i != gtk_text_buffer_get_line_count (buffer)) g_error ("Counted %d lines, buffer has %d", i, - gtk_text_buffer_get_line_count (buffer) + 1); + gtk_text_buffer_get_line_count (buffer)); }