From 2fab0eb1fa92964cca24d55e51203c5af5113c8e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 24 Oct 2000 22:44:14 +0000 Subject: [PATCH] make it a static function 2000-10-24 Havoc Pennington * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make it a static function * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should redraw text when a tag is applied to it. * gtk/gtktexttag.c (gtk_text_tag_affects_size) (gtk_text_tag_affects_nonsize_appearance): private functions to see if a tag requires various kinds of redraw/layout to be queued up. * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock * gtk/testtext.c (fill_example_buffer): Put the cursor at the start of the buffer, so search works by default * gtk/gtktextiter.c (lines_match): init match_start always * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New function, get iter at a line + a byte index * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, to set byte position within a line (gtk_text_iter_check): remove leftover G_BREAKPOINT thing --- ChangeLog | 27 ++++ ChangeLog.pre-2-0 | 27 ++++ ChangeLog.pre-2-10 | 27 ++++ ChangeLog.pre-2-2 | 27 ++++ ChangeLog.pre-2-4 | 27 ++++ ChangeLog.pre-2-6 | 27 ++++ ChangeLog.pre-2-8 | 27 ++++ docs/reference/ChangeLog | 4 + docs/reference/gtk/text_widget.sgml | 10 ++ gtk/gtktextbtree.c | 233 +++++++++++++++++----------- gtk/gtktextbuffer.c | 51 +++--- gtk/gtktextbuffer.h | 4 + gtk/gtktextiter.c | 86 +++++++--- gtk/gtktextiter.h | 2 + gtk/gtktextlayout.c | 2 +- gtk/gtktextmark.c | 146 ++++++++++------- gtk/gtktextmark.h | 29 +++- gtk/gtktextmarkprivate.h | 7 +- gtk/gtktexttag.c | 40 ++++- gtk/gtktexttag.h | 5 +- gtk/gtktexttagprivate.h | 3 + gtk/testtext.c | 12 +- tests/testtext.c | 12 +- 23 files changed, 623 insertions(+), 212 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2f0f46c7de..515530e8f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2000-10-24 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make + it a static function + + * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should + redraw text when a tag is applied to it. + + * gtk/gtktexttag.c (gtk_text_tag_affects_size) + (gtk_text_tag_affects_nonsize_appearance): private functions to + see if a tag requires various kinds of redraw/layout to be queued + up. + + * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock + + * gtk/testtext.c (fill_example_buffer): Put the cursor + at the start of the buffer, so search works by default + + * gtk/gtktextiter.c (lines_match): init match_start always + + * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New + function, get iter at a line + a byte index + + * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, + to set byte position within a line + (gtk_text_iter_check): remove leftover G_BREAKPOINT thing + 2000-10-23 Havoc Pennington * gtk/testtext.c: Re-enable the "find" dialog diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 2f0f46c7de..515530e8f0 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,30 @@ +2000-10-24 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make + it a static function + + * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should + redraw text when a tag is applied to it. + + * gtk/gtktexttag.c (gtk_text_tag_affects_size) + (gtk_text_tag_affects_nonsize_appearance): private functions to + see if a tag requires various kinds of redraw/layout to be queued + up. + + * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock + + * gtk/testtext.c (fill_example_buffer): Put the cursor + at the start of the buffer, so search works by default + + * gtk/gtktextiter.c (lines_match): init match_start always + + * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New + function, get iter at a line + a byte index + + * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, + to set byte position within a line + (gtk_text_iter_check): remove leftover G_BREAKPOINT thing + 2000-10-23 Havoc Pennington * gtk/testtext.c: Re-enable the "find" dialog diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 2f0f46c7de..515530e8f0 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,30 @@ +2000-10-24 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make + it a static function + + * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should + redraw text when a tag is applied to it. + + * gtk/gtktexttag.c (gtk_text_tag_affects_size) + (gtk_text_tag_affects_nonsize_appearance): private functions to + see if a tag requires various kinds of redraw/layout to be queued + up. + + * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock + + * gtk/testtext.c (fill_example_buffer): Put the cursor + at the start of the buffer, so search works by default + + * gtk/gtktextiter.c (lines_match): init match_start always + + * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New + function, get iter at a line + a byte index + + * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, + to set byte position within a line + (gtk_text_iter_check): remove leftover G_BREAKPOINT thing + 2000-10-23 Havoc Pennington * gtk/testtext.c: Re-enable the "find" dialog diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 2f0f46c7de..515530e8f0 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,30 @@ +2000-10-24 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make + it a static function + + * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should + redraw text when a tag is applied to it. + + * gtk/gtktexttag.c (gtk_text_tag_affects_size) + (gtk_text_tag_affects_nonsize_appearance): private functions to + see if a tag requires various kinds of redraw/layout to be queued + up. + + * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock + + * gtk/testtext.c (fill_example_buffer): Put the cursor + at the start of the buffer, so search works by default + + * gtk/gtktextiter.c (lines_match): init match_start always + + * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New + function, get iter at a line + a byte index + + * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, + to set byte position within a line + (gtk_text_iter_check): remove leftover G_BREAKPOINT thing + 2000-10-23 Havoc Pennington * gtk/testtext.c: Re-enable the "find" dialog diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 2f0f46c7de..515530e8f0 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,30 @@ +2000-10-24 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make + it a static function + + * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should + redraw text when a tag is applied to it. + + * gtk/gtktexttag.c (gtk_text_tag_affects_size) + (gtk_text_tag_affects_nonsize_appearance): private functions to + see if a tag requires various kinds of redraw/layout to be queued + up. + + * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock + + * gtk/testtext.c (fill_example_buffer): Put the cursor + at the start of the buffer, so search works by default + + * gtk/gtktextiter.c (lines_match): init match_start always + + * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New + function, get iter at a line + a byte index + + * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, + to set byte position within a line + (gtk_text_iter_check): remove leftover G_BREAKPOINT thing + 2000-10-23 Havoc Pennington * gtk/testtext.c: Re-enable the "find" dialog diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 2f0f46c7de..515530e8f0 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,30 @@ +2000-10-24 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make + it a static function + + * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should + redraw text when a tag is applied to it. + + * gtk/gtktexttag.c (gtk_text_tag_affects_size) + (gtk_text_tag_affects_nonsize_appearance): private functions to + see if a tag requires various kinds of redraw/layout to be queued + up. + + * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock + + * gtk/testtext.c (fill_example_buffer): Put the cursor + at the start of the buffer, so search works by default + + * gtk/gtktextiter.c (lines_match): init match_start always + + * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New + function, get iter at a line + a byte index + + * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, + to set byte position within a line + (gtk_text_iter_check): remove leftover G_BREAKPOINT thing + 2000-10-23 Havoc Pennington * gtk/testtext.c: Re-enable the "find" dialog diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 2f0f46c7de..515530e8f0 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,30 @@ +2000-10-24 Havoc Pennington + + * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make + it a static function + + * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should + redraw text when a tag is applied to it. + + * gtk/gtktexttag.c (gtk_text_tag_affects_size) + (gtk_text_tag_affects_nonsize_appearance): private functions to + see if a tag requires various kinds of redraw/layout to be queued + up. + + * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock + + * gtk/testtext.c (fill_example_buffer): Put the cursor + at the start of the buffer, so search works by default + + * gtk/gtktextiter.c (lines_match): init match_start always + + * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New + function, get iter at a line + a byte index + + * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function, + to set byte position within a line + (gtk_text_iter_check): remove leftover G_BREAKPOINT thing + 2000-10-23 Havoc Pennington * gtk/testtext.c: Re-enable the "find" dialog diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 7fe274847a..488a60700a 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,7 @@ +2000-10-24 Havoc Pennington + + * gtk/text_widget.sgml: add note about UTF-8 + 2000-10-23 Havoc Pennington * gtk/gtk-sections.txt: remove GtkTextBTree diff --git a/docs/reference/gtk/text_widget.sgml b/docs/reference/gtk/text_widget.sgml index 776f079533..80cd81d2e6 100644 --- a/docs/reference/gtk/text_widget.sgml +++ b/docs/reference/gtk/text_widget.sgml @@ -21,6 +21,16 @@ display a GtkTextBuffer. Each buffer can be displayed by any number of views. + +One of the important things to remember about text in GTK+ is that it's in the +UTF-8 encoding. This means that one character can be encoded as multiple +bytes. Character counts are usually referred to as +offsets, while byte counts are called +indexes. If you confuse these two, things will work fine +with ASCII, but as soon as your buffer contains multibyte characters, bad things +will happen. + + Text in a buffer can be marked with tags. A tag is an attribute that can be applied to some range of text. For example, a tag might be diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index dcb5693606..5b1f98430b 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -172,8 +172,8 @@ struct _GtkTextBTree { GtkTextTagTable *table; GHashTable *mark_table; guint refcount; - GtkTextLineSegment *insert_mark; - GtkTextLineSegment *selection_bound_mark; + GtkTextMark *insert_mark; + GtkTextMark *selection_bound_mark; GtkTextBuffer *buffer; BTreeView *views; GSList *tag_infos; @@ -321,6 +321,9 @@ static GtkTextTagInfo *gtk_text_btree_get_existing_tag_info (GtkTextBTree *tre static void gtk_text_btree_remove_tag_info (GtkTextBTree *tree, GtkTextTag *tag); +static void redisplay_region (GtkTextBTree *tree, + const GtkTextIter *start, + const GtkTextIter *end); /* Inline thingies */ @@ -421,33 +424,36 @@ gtk_text_btree_new (GtkTextTagTable *table, { GtkTextIter start; - + GtkTextLineSegment *seg; + gtk_text_btree_get_iter_at_line_char(tree, &start, 0, 0); - tree->insert_mark = - (GtkTextLineSegment*) gtk_text_btree_set_mark(tree, - NULL, - "insert", - FALSE, - &start, - FALSE); - - tree->insert_mark->body.mark.not_deleteable = TRUE; - tree->insert_mark->body.mark.visible = TRUE; - - tree->selection_bound_mark = - (GtkTextLineSegment*) gtk_text_btree_set_mark(tree, - NULL, - "selection_bound", - FALSE, - &start, - FALSE); + tree->insert_mark = gtk_text_btree_set_mark (tree, + NULL, + "insert", + FALSE, + &start, + FALSE); - tree->selection_bound_mark->body.mark.not_deleteable = TRUE; + seg = tree->insert_mark->segment; - _mark_segment_ref(tree->insert_mark); - _mark_segment_ref(tree->selection_bound_mark); + seg->body.mark.not_deleteable = TRUE; + seg->body.mark.visible = TRUE; + + tree->selection_bound_mark = gtk_text_btree_set_mark (tree, + NULL, + "selection_bound", + FALSE, + &start, + FALSE); + + seg = tree->selection_bound_mark->segment; + + seg->body.mark.not_deleteable = TRUE; + + g_object_ref (G_OBJECT (tree->insert_mark)); + g_object_ref (G_OBJECT (tree->selection_bound_mark)); } tree->refcount = 1; @@ -467,7 +473,11 @@ gtk_text_btree_ref (GtkTextBTree *tree) static void mark_destroy_foreach (gpointer key, gpointer value, gpointer user_data) { - _mark_segment_unref (value); + GtkTextLineSegment *seg = value; + + g_return_if_fail (seg->body.mark.tree == NULL); + + g_object_unref (G_OBJECT (seg->body.mark.obj)); } void @@ -479,26 +489,26 @@ gtk_text_btree_unref (GtkTextBTree *tree) tree->refcount -= 1; if (tree->refcount == 0) - { - gtk_text_btree_node_destroy(tree, tree->root_node); + { + gtk_text_btree_node_destroy (tree, tree->root_node); - g_hash_table_foreach(tree->mark_table, - mark_destroy_foreach, - NULL); - g_hash_table_destroy(tree->mark_table); + g_hash_table_foreach (tree->mark_table, + mark_destroy_foreach, + NULL); + g_hash_table_destroy (tree->mark_table); - _mark_segment_unref(tree->insert_mark); - _mark_segment_unref(tree->selection_bound_mark); + g_object_unref (G_OBJECT (tree->insert_mark)); + g_object_unref (G_OBJECT (tree->selection_bound_mark)); - gtk_signal_disconnect(GTK_OBJECT(tree->table), - tree->tag_changed_handler); + gtk_signal_disconnect (GTK_OBJECT(tree->table), + tree->tag_changed_handler); - gtk_signal_disconnect(GTK_OBJECT(tree->table), - tree->tag_removed_handler); + gtk_signal_disconnect (GTK_OBJECT(tree->table), + tree->tag_removed_handler); - gtk_object_unref(GTK_OBJECT(tree->table)); + gtk_object_unref (GTK_OBJECT(tree->table)); - g_free(tree); + g_free (tree); } } @@ -1382,8 +1392,8 @@ gtk_text_btree_get_view_size (GtkTextBTree *tree, g_return_if_fail(tree != NULL); g_return_if_fail(view_id != NULL); - gtk_text_btree_node_get_size(tree->root_node, view_id, - width, height); + gtk_text_btree_node_get_size (tree->root_node, view_id, + width, height); } /* @@ -1461,6 +1471,26 @@ iter_stack_invert(IterStack *stack) } } +static void +queue_tag_redisplay (GtkTextBTree *tree, + GtkTextTag *tag, + const GtkTextIter *start, + const GtkTextIter *end) +{ + if (gtk_text_tag_affects_size (tag)) + { + gtk_text_btree_invalidate_region (tree, start, end); + + } + else if (gtk_text_tag_affects_nonsize_appearance (tag)) + { + /* We only need to queue a redraw, not a relayout */ + redisplay_region (tree, start, end); + } + + /* We don't need to do anything if the tag doesn't affect display */ +} + void gtk_text_btree_tag (const GtkTextIter *start_orig, const GtkTextIter *end_orig, @@ -1502,6 +1532,8 @@ gtk_text_btree_tag (const GtkTextIter *start_orig, tree = gtk_text_iter_get_btree(&start); + queue_tag_redisplay (tree, tag, &start, &end); + info = gtk_text_btree_get_tag_info(tree, tag); start_line = gtk_text_iter_get_text_line(&start); @@ -2311,21 +2343,23 @@ redisplay_region (GtkTextBTree *tree, if (ld) end_y += ld->height; - gtk_text_layout_changed (view->layout, start_y, end_y - start_y, end_y - start_y); + gtk_text_layout_changed (view->layout, start_y, + end_y - start_y, + end_y - start_y); view = view->next; } } static void -redisplay_mark(GtkTextLineSegment *mark) +redisplay_mark (GtkTextLineSegment *mark) { GtkTextIter iter; GtkTextIter end; gtk_text_btree_get_iter_at_mark(mark->body.mark.tree, &iter, - (GtkTextMark*)mark); + mark->body.mark.obj); end = iter; gtk_text_iter_next_char(&end); @@ -2370,10 +2404,10 @@ real_set_mark(GtkTextBTree *tree, g_return_val_if_fail(gtk_text_iter_get_btree(where) == tree, NULL); if (existing_mark) - mark = (GtkTextLineSegment*) existing_mark; + mark = existing_mark->segment; else if (name != NULL) - mark = g_hash_table_lookup(tree->mark_table, - name); + mark = g_hash_table_lookup (tree->mark_table, + name); else mark = NULL; @@ -2391,12 +2425,13 @@ real_set_mark(GtkTextBTree *tree, if (mark != NULL) { if (redraw_selections && - (mark == tree->insert_mark || - mark == tree->selection_bound_mark)) + (mark == tree->insert_mark->segment || + mark == tree->selection_bound_mark->segment)) { GtkTextIter old_pos; - gtk_text_btree_get_iter_at_mark (tree, &old_pos, (GtkTextMark*)mark); + gtk_text_btree_get_iter_at_mark (tree, &old_pos, + mark->body.mark.obj); redisplay_region (tree, &old_pos, where); } @@ -2411,7 +2446,7 @@ real_set_mark(GtkTextBTree *tree, } /* Redraw the mark's old location. */ - redisplay_mark_if_visible(mark); + redisplay_mark_if_visible (mark); /* Unlink mark from its current location. This could hose our iterator... */ @@ -2432,22 +2467,22 @@ real_set_mark(GtkTextBTree *tree, mark->body.mark.line = gtk_text_iter_get_text_line(&iter); if (mark->body.mark.name) - g_hash_table_insert(tree->mark_table, - mark->body.mark.name, - mark); + g_hash_table_insert (tree->mark_table, + mark->body.mark.name, + mark); } /* Link mark into new location */ - gtk_text_btree_link_segment(mark, &iter); + gtk_text_btree_link_segment (mark, &iter); /* Invalidate some iterators. */ - segments_changed(tree); + segments_changed (tree); /* * update the screen at the mark's new location. */ - redisplay_mark_if_visible(mark); + redisplay_mark_if_visible (mark); return mark; } @@ -2461,9 +2496,13 @@ gtk_text_btree_set_mark (GtkTextBTree *tree, const GtkTextIter *iter, gboolean should_exist) { - return (GtkTextMark*)real_set_mark(tree, existing_mark, - name, left_gravity, iter, should_exist, - TRUE); + GtkTextLineSegment *seg; + + seg = real_set_mark(tree, existing_mark, + name, left_gravity, iter, should_exist, + TRUE); + + return seg ? seg->body.mark.obj : NULL; } gboolean @@ -2474,9 +2513,9 @@ gtk_text_btree_get_selection_bounds (GtkTextBTree *tree, GtkTextIter tmp_start, tmp_end; gtk_text_btree_get_iter_at_mark (tree, &tmp_start, - (GtkTextMark*)tree->insert_mark); + tree->insert_mark); gtk_text_btree_get_iter_at_mark (tree, &tmp_end, - (GtkTextMark*)tree->selection_bound_mark); + tree->selection_bound_mark); if (gtk_text_iter_equal(&tmp_start, &tmp_end)) { @@ -2512,10 +2551,10 @@ gtk_text_btree_place_cursor(GtkTextBTree *tree, redisplay_region(tree, &start, &end); /* Move insert AND selection_bound before we redisplay */ - real_set_mark(tree, (GtkTextMark*) tree->insert_mark, - "insert", FALSE, iter, TRUE, FALSE); - real_set_mark(tree, (GtkTextMark*) tree->selection_bound_mark, - "selection_bound", FALSE, iter, TRUE, FALSE); + real_set_mark (tree, tree->insert_mark, + "insert", FALSE, iter, TRUE, FALSE); + real_set_mark (tree, tree->selection_bound_mark, + "selection_bound", FALSE, iter, TRUE, FALSE); } void @@ -2537,11 +2576,13 @@ void gtk_text_btree_remove_mark (GtkTextBTree *tree, GtkTextMark *mark) { - GtkTextLineSegment *segment = (GtkTextLineSegment*) mark; + GtkTextLineSegment *segment; - g_return_if_fail (segment != NULL); + g_return_if_fail (mark != NULL); g_return_if_fail (tree != NULL); + segment = mark->segment; + if (segment->body.mark.not_deleteable) { g_warning("Can't delete special mark `%s'", segment->body.mark.name); @@ -2553,8 +2594,9 @@ gtk_text_btree_remove_mark (GtkTextBTree *tree, if (segment->body.mark.name) g_hash_table_remove (tree->mark_table, segment->body.mark.name); - - _mark_segment_unref (segment); + + /* Remove the ref on the mark that belonged to the segment. */ + g_object_unref (G_OBJECT (mark)); segment->body.mark.tree = NULL; segment->body.mark.line = NULL; @@ -2564,24 +2606,28 @@ gboolean gtk_text_btree_mark_is_insert (GtkTextBTree *tree, GtkTextMark *segment) { - return segment == (GtkTextMark*) tree->insert_mark; + return segment == tree->insert_mark; } gboolean gtk_text_btree_mark_is_selection_bound (GtkTextBTree *tree, GtkTextMark *segment) { - return segment == (GtkTextMark*) tree->selection_bound_mark; + return segment == tree->selection_bound_mark; } GtkTextMark* gtk_text_btree_get_mark_by_name (GtkTextBTree *tree, const gchar *name) { + GtkTextLineSegment *seg; + g_return_val_if_fail(tree != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); - return g_hash_table_lookup(tree->mark_table, name); + seg = g_hash_table_lookup (tree->mark_table, name); + + return seg ? seg->body.mark.obj : NULL; } void @@ -2592,7 +2638,7 @@ gtk_text_mark_set_visible (GtkTextMark *mark, g_return_if_fail(mark != NULL); - seg = (GtkTextLineSegment*)mark; + seg = mark->segment; if (seg->body.mark.visible == setting) return; @@ -4964,7 +5010,15 @@ gtk_text_btree_node_destroy(GtkTextBTree *tree, GtkTextBTreeNode *node) { seg = line->segments; line->segments = seg->next; - (*seg->type->deleteFunc)(seg, line, 1); + + if (GTK_IS_TEXT_MARK_SEGMENT (seg)) + { + /* Set the mark as deleted */ + seg->body.mark.tree = NULL; + seg->body.mark.line = NULL; + } + + (*seg->type->deleteFunc) (seg, line, 1); } gtk_text_line_destroy(tree, line); } @@ -4977,12 +5031,13 @@ gtk_text_btree_node_destroy(GtkTextBTree *tree, GtkTextBTreeNode *node) { childPtr = node->children.node; node->children.node = childPtr->next; - gtk_text_btree_node_destroy(tree, childPtr); + gtk_text_btree_node_destroy (tree, childPtr); } } - summary_list_destroy(node->summary); - node_data_list_destroy(node->node_data); - g_free(node); + + summary_list_destroy (node->summary); + node_data_list_destroy (node->node_data); + g_free (node); } static NodeData* @@ -5111,15 +5166,16 @@ get_tree_bounds(GtkTextBTree *tree, } static void -tag_changed_cb(GtkTextTagTable *table, - GtkTextTag *tag, - gboolean size_changed, - GtkTextBTree *tree) +tag_changed_cb (GtkTextTagTable *table, + GtkTextTag *tag, + gboolean size_changed, + GtkTextBTree *tree) { if (size_changed) { - /* We need to queue a redisplay on all regions that are tagged with - this tag. */ + /* We need to queue a relayout on all regions that are tagged with + * this tag. + */ GtkTextIter start; GtkTextIter end; @@ -5127,14 +5183,15 @@ tag_changed_cb(GtkTextTagTable *table, if (gtk_text_btree_get_iter_at_first_toggle(tree, &start, tag)) { /* Must be a last toggle if there was a first one. */ - gtk_text_btree_get_iter_at_last_toggle(tree, &end, tag); - gtk_text_btree_invalidate_region(tree, - &start, &end); + gtk_text_btree_get_iter_at_last_toggle (tree, &end, tag); + gtk_text_btree_invalidate_region (tree, + &start, &end); } } else { + /* We only need to queue a redraw, not a relayout */ BTreeView *view; view = tree->views; diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index a686a4531f..557bd6bf5c 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -1072,14 +1072,14 @@ gtk_text_buffer_mark_set (GtkTextBuffer *buffer, this signal is purely for notification, and not to allow users to modify the default behavior. */ - gtk_text_mark_ref (mark); + g_object_ref (G_OBJECT (mark)); gtk_signal_emit(GTK_OBJECT(buffer), signals[MARK_SET], location, mark); - gtk_text_mark_unref (mark); + g_object_unref (G_OBJECT (mark)); } /** @@ -1107,12 +1107,12 @@ gtk_text_buffer_set_mark (GtkTextBuffer *buffer, GtkTextIter location; GtkTextMark *mark; - mark = gtk_text_btree_set_mark(get_btree (buffer), - existing_mark, - mark_name, - left_gravity, - iter, - should_exist); + 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(get_btree (buffer), mark) || gtk_text_btree_mark_is_selection_bound (get_btree (buffer), mark)) @@ -1126,7 +1126,7 @@ gtk_text_buffer_set_mark (GtkTextBuffer *buffer, gtk_text_buffer_mark_set (buffer, &location, mark); - return (GtkTextMark*)mark; + return mark; } /** @@ -1182,7 +1182,7 @@ gtk_text_buffer_move_mark (GtkTextBuffer *buffer, GtkTextMark *mark, const GtkTextIter *where) { - g_return_if_fail (mark != NULL); + g_return_if_fail (GTK_IS_TEXT_MARK (mark)); g_return_if_fail (!gtk_text_mark_get_deleted (mark)); g_return_if_fail (GTK_IS_TEXT_BUFFER(buffer)); @@ -1202,7 +1202,7 @@ gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark) { - g_return_if_fail (mark != NULL); + g_return_if_fail (GTK_IS_TEXT_MARK (mark)); g_return_if_fail (!gtk_text_mark_get_deleted (mark)); g_return_if_fail (GTK_IS_TEXT_BUFFER(buffer)); @@ -1218,7 +1218,7 @@ gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer, * * Deletes @mark, so that it's no longer located anywhere in the * buffer. Removes the reference the buffer holds to the mark, so if - * you haven't called gtk_text_mark_ref() the mark will be freed. Even + * you haven't called g_object_ref() on the mark, it will be freed. Even * if the mark isn't freed, most operations on @mark become * invalid. There is no way to undelete a * mark. gtk_text_mark_get_deleted() will return TRUE after this @@ -1230,11 +1230,11 @@ void gtk_text_buffer_delete_mark(GtkTextBuffer *buffer, GtkTextMark *mark) { - g_return_if_fail (mark != NULL); + g_return_if_fail (GTK_IS_TEXT_MARK (mark)); g_return_if_fail (!gtk_text_mark_get_deleted (mark)); g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); - gtk_text_mark_ref (mark); + g_object_ref (G_OBJECT (mark)); gtk_text_btree_remove_mark (get_btree (buffer), mark); @@ -1245,7 +1245,7 @@ gtk_text_buffer_delete_mark(GtkTextBuffer *buffer, gtk_signal_emit (GTK_OBJECT(buffer), signals[MARK_DELETED], mark); - gtk_text_mark_unref (mark); + g_object_unref (G_OBJECT (mark)); } /** @@ -1616,11 +1616,24 @@ gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer, gint line_number, gint char_offset) { - g_return_if_fail(iter != NULL); - g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer)); + g_return_if_fail (iter != NULL); + g_return_if_fail (GTK_IS_TEXT_BUFFER(buffer)); - gtk_text_btree_get_iter_at_line_char(get_btree (buffer), - iter, line_number, char_offset); + gtk_text_btree_get_iter_at_line_char (get_btree (buffer), + iter, line_number, char_offset); +} + +void +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)); + + gtk_text_btree_get_iter_at_line_byte (get_btree (buffer), + iter, line_number, byte_index); } void diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h index d35eb9a4f7..920d09d2e9 100644 --- a/gtk/gtktextbuffer.h +++ b/gtk/gtktextbuffer.h @@ -263,6 +263,10 @@ void gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer, GtkTextIter *iter, gint line_number, gint char_offset); +void gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer, + GtkTextIter *iter, + gint line_number, + gint byte_index); void gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer, GtkTextIter *iter, gint char_offset); diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c index 70ac5f19e8..32f85be9a2 100644 --- a/gtk/gtktextiter.c +++ b/gtk/gtktextiter.c @@ -134,7 +134,7 @@ iter_set_from_segment(GtkTextRealIter *iter, seg = seg->next; } - iter_set_from_byte_offset(iter, line, byte_offset); + iter_set_from_byte_offset (iter, line, byte_offset); } /* This function ensures that the segment-dependent information is @@ -667,7 +667,7 @@ gtk_text_iter_get_line_offset(const GtkTextIter *iter) * Return value: distance from start of line, in bytes **/ gint -gtk_text_iter_get_line_index(const GtkTextIter *iter) +gtk_text_iter_get_line_index (const GtkTextIter *iter) { GtkTextRealIter *real; @@ -898,7 +898,7 @@ gtk_text_iter_get_marks (const GtkTextIter *iter) { if (seg->type == >k_text_left_mark_type || seg->type == >k_text_right_mark_type) - retval = g_slist_prepend(retval, (GtkTextMark*)seg); + retval = g_slist_prepend (retval, seg->body.mark.obj); seg = seg->next; } @@ -2477,7 +2477,35 @@ gtk_text_iter_set_line_offset(GtkTextIter *iter, } void -gtk_text_iter_set_line(GtkTextIter *iter, gint line_number) +gtk_text_iter_set_line_index (GtkTextIter *iter, + gint byte_on_line) +{ + GtkTextRealIter *real; + + g_return_if_fail (iter != NULL); + + real = gtk_text_iter_make_surreal (iter); + + if (real == NULL) + return; + + check_invariants (iter); + + iter_set_from_byte_offset (real, real->line, byte_on_line); + + if (real->segment->type == >k_text_char_type && + (real->segment->body.chars[real->segment_byte_offset] & 0xc0) == 0x80) + g_warning ("%s: Incorrect byte offset %d falls in the middle of a UTF-8 " + "character; this will crash the text buffer. " + "Byte indexes must refer to the start of a character.", + G_STRLOC, byte_on_line); + + check_invariants (iter); +} + +void +gtk_text_iter_set_line (GtkTextIter *iter, + gint line_number) { GtkTextLine *line; gint real_line; @@ -2861,6 +2889,9 @@ lines_match (const GtkTextIter *start, if (*lines == NULL || **lines == '\0') { + if (match_start) + *match_start = *start; + if (match_end) *match_end = *start; return TRUE; @@ -2904,7 +2935,7 @@ lines_match (const GtkTextIter *start, } if (found == NULL) - { + { g_free (line_text); return FALSE; } @@ -2924,7 +2955,7 @@ lines_match (const GtkTextIter *start, forward_chars_with_skipping (match_start, offset, visible_only, !slice); } - + /* Go to end of search string */ offset += g_utf8_strlen (*lines, -1); @@ -3234,9 +3265,9 @@ gtk_text_btree_get_iter_at_line_char (GtkTextBTree *tree, void gtk_text_btree_get_iter_at_line_byte (GtkTextBTree *tree, - GtkTextIter *iter, - gint line_number, - gint byte_index) + GtkTextIter *iter, + gint line_number, + gint byte_index) { GtkTextRealIter *real = (GtkTextRealIter*)iter; GtkTextLine *line; @@ -3252,6 +3283,13 @@ gtk_text_btree_get_iter_at_line_byte (GtkTextBTree *tree, /* We might as well cache this, since we know it. */ real->cached_line_number = real_line; + if (real->segment->type == >k_text_char_type && + (real->segment->body.chars[real->segment_byte_offset] & 0xc0) == 0x80) + g_warning ("%s: Incorrect byte offset %d falls in the middle of a UTF-8 " + "character; this will crash the text buffer. " + "Byte indexes must refer to the start of a character.", + G_STRLOC, byte_index); + check_invariants(iter); } @@ -3336,32 +3374,34 @@ gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree, g_return_val_if_fail(iter != NULL, FALSE); g_return_val_if_fail(tree != NULL, FALSE); - mark = gtk_text_btree_get_mark_by_name(tree, mark_name); + mark = gtk_text_btree_get_mark_by_name (tree, mark_name); if (mark == NULL) return FALSE; else { - gtk_text_btree_get_iter_at_mark(tree, iter, mark); - check_invariants(iter); + gtk_text_btree_get_iter_at_mark (tree, iter, mark); + check_invariants (iter); return TRUE; } } void gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree, - GtkTextIter *iter, - GtkTextMark *mark) + GtkTextIter *iter, + GtkTextMark *mark) { - GtkTextLineSegment *seg = (GtkTextLineSegment*) mark; + GtkTextLineSegment *seg; - g_return_if_fail(iter != NULL); - g_return_if_fail(tree != NULL); - g_return_if_fail(GTK_IS_TEXT_MARK (mark)); + g_return_if_fail (iter != NULL); + g_return_if_fail (tree != NULL); + g_return_if_fail (GTK_IS_TEXT_MARK (mark)); + + seg = mark->segment; - iter_init_from_segment(iter, tree, - seg->body.mark.line, seg); - g_assert(seg->body.mark.line == gtk_text_iter_get_text_line(iter)); + iter_init_from_segment (iter, tree, + seg->body.mark.line, seg); + g_assert (seg->body.mark.line == gtk_text_iter_get_text_line(iter)); check_invariants(iter); } @@ -3431,10 +3471,6 @@ gtk_text_iter_check (const GtkTextIter *iter) real->line_byte_offset, real->line_char_offset); #endif - - if (real->line_byte_offset == 97 && - real->line_char_offset == 95) - G_BREAKPOINT(); if (segments_updated) { diff --git a/gtk/gtktextiter.h b/gtk/gtktextiter.h index 8e6eeaecdd..9a49dfbfab 100644 --- a/gtk/gtktextiter.h +++ b/gtk/gtktextiter.h @@ -160,6 +160,8 @@ void gtk_text_iter_set_line (GtkTextIter *iter, gint line_number); void gtk_text_iter_set_line_offset (GtkTextIter *iter, gint char_on_line); +void gtk_text_iter_set_line_index (GtkTextIter *iter, + gint byte_on_line); void gtk_text_iter_forward_to_end (GtkTextIter *iter); gboolean gtk_text_iter_forward_to_newline (GtkTextIter *iter); diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index d4b57f973a..99e3c39c40 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -1211,7 +1211,7 @@ add_cursor (GtkTextLayout *layout, * user has hidden the cursor. */ if (gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer), - (GtkTextMark*)seg) && + seg->body.mark.obj) && (!layout->cursor_visible || gtk_text_buffer_get_selection_bounds (layout->buffer, NULL, NULL))) return; diff --git a/gtk/gtktextmark.c b/gtk/gtktextmark.c index a1a4c6f65f..c66af21e2f 100644 --- a/gtk/gtktextmark.c +++ b/gtk/gtktextmark.c @@ -50,12 +50,89 @@ #include "gtktextbtree.h" +static void gtk_text_mark_init (GtkTextMark *mark); +static void gtk_text_mark_class_init (GtkTextMarkClass *klass); +static void gtk_text_mark_finalize (GObject *obj); + + +static gpointer parent_class = NULL; + +GType +gtk_text_mark_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GtkTextMarkClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gtk_text_mark_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkTextMark), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_text_mark_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GtkTextMark", + &object_info); + } + + return object_type; +} + +static void +gtk_text_mark_init (GtkTextMark *mark) +{ + mark->segment = NULL; +} + +static void +gtk_text_mark_class_init (GtkTextMarkClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gtk_text_mark_finalize; +} + +static void +gtk_text_mark_finalize (GObject *obj) +{ + GtkTextMark *mark; + GtkTextLineSegment *seg; + + mark = GTK_TEXT_MARK (obj); + + seg = mark->segment; + + if (seg) + { + g_return_if_fail (seg->body.mark.tree == NULL); + + if (seg->body.mark.tree != NULL) + g_warning ("GtkTextMark being finalized while still in the buffer; " + "someone removed a reference they didn't own! Crash " + "impending"); + + g_free (seg->body.mark.name); + g_free (seg); + + mark->segment = NULL; + } +} + gboolean gtk_text_mark_is_visible(GtkTextMark *mark) { GtkTextLineSegment *seg; - seg = (GtkTextLineSegment*)mark; + seg = mark->segment; return seg->body.mark.visible; } @@ -65,34 +142,11 @@ gtk_text_mark_get_name (GtkTextMark *mark) { GtkTextLineSegment *seg; - seg = (GtkTextLineSegment*)mark; + seg = mark->segment; return seg->body.mark.name; } - -GtkTextMark * -gtk_text_mark_ref (GtkTextMark *mark) -{ - GtkTextLineSegment *seg; - - seg = (GtkTextLineSegment*)mark; - - _mark_segment_ref (seg); - - return mark; -} - -void -gtk_text_mark_unref (GtkTextMark *mark) -{ - GtkTextLineSegment *seg; - - seg = (GtkTextLineSegment*)mark; - - _mark_segment_unref (seg); -} - gboolean gtk_text_mark_get_deleted (GtkTextMark *mark) { @@ -100,7 +154,10 @@ gtk_text_mark_get_deleted (GtkTextMark *mark) g_return_val_if_fail (mark != NULL, FALSE); - seg = (GtkTextLineSegment*)mark; + seg = mark->segment; + + if (seg == NULL) + return TRUE; return seg->body.mark.tree == NULL; } @@ -127,52 +184,23 @@ _mark_segment_new (GtkTextBTree *tree, mark->type = >k_text_left_mark_type; else mark->type = >k_text_right_mark_type; - + mark->byte_count = 0; mark->char_count = 0; + mark->body.mark.obj = g_object_new (GTK_TYPE_TEXT_MARK, NULL); + mark->body.mark.obj->segment = mark; + mark->body.mark.tree = tree; mark->body.mark.line = NULL; mark->next = NULL; - mark->body.mark.refcount = 1; - mark->body.mark.visible = FALSE; mark->body.mark.not_deleteable = FALSE; return mark; } -void -_mark_segment_ref (GtkTextLineSegment *mark) -{ - g_return_if_fail (mark != NULL); - g_return_if_fail (mark->type == >k_text_right_mark_type || - mark->type == >k_text_left_mark_type); - g_return_if_fail (mark->body.mark.refcount > 0); - - mark->body.mark.refcount += 1; -} - -void -_mark_segment_unref (GtkTextLineSegment *mark) -{ - g_return_if_fail (mark != NULL); - g_return_if_fail (mark->type == >k_text_right_mark_type || - mark->type == >k_text_left_mark_type); - g_return_if_fail (mark->body.mark.refcount > 0); - - mark->body.mark.refcount -= 1; - - if (mark->body.mark.refcount == 0) - { - g_free(mark->body.mark.name); - - g_free(mark); - } -} - - static int mark_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int treeGone); diff --git a/gtk/gtktextmark.h b/gtk/gtktextmark.h index 0ee0180639..45255f4459 100644 --- a/gtk/gtktextmark.h +++ b/gtk/gtktextmark.h @@ -56,15 +56,36 @@ extern "C" { /* The GtkTextMark data type */ -typedef struct _GtkTextMark GtkTextMark; +typedef struct _GtkTextMark GtkTextMark; +typedef struct _GtkTextMarkClass GtkTextMarkClass; + +#define GTK_TYPE_TEXT_MARK (gtk_text_mark_get_type ()) +#define GTK_TEXT_MARK(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_TEXT_MARK, GtkTextMark)) +#define GTK_TEXT_MARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TEXT_MARK, GtkTextMarkClass)) +#define GTK_IS_TEXT_MARK(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_TEXT_MARK)) +#define GTK_IS_TEXT_MARK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT_MARK)) +#define GTK_TEXT_MARK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TEXT_MARK, GtkTextMarkClass)) + +struct _GtkTextMark +{ + GObject parent_instance; + + gpointer segment; +}; + +struct _GtkTextMarkClass +{ + GObjectClass parent_class; + +}; + +GType gtk_text_mark_get_type (void) G_GNUC_CONST; void gtk_text_mark_set_visible (GtkTextMark *mark, gboolean setting); gboolean gtk_text_mark_is_visible (GtkTextMark *mark); /* FIXME gconst */ -const char * gtk_text_mark_get_name (GtkTextMark *mark); -GtkTextMark *gtk_text_mark_ref (GtkTextMark *mark); -void gtk_text_mark_unref (GtkTextMark *mark); +const char *gtk_text_mark_get_name (GtkTextMark *mark); gboolean gtk_text_mark_get_deleted (GtkTextMark *mark); diff --git a/gtk/gtktextmarkprivate.h b/gtk/gtktextmarkprivate.h index 87e862c289..4776ca6b10 100644 --- a/gtk/gtktextmarkprivate.h +++ b/gtk/gtktextmarkprivate.h @@ -8,7 +8,7 @@ extern "C" { #include #include -#define GTK_IS_TEXT_MARK(mark) (((GtkTextLineSegment*)mark)->type == >k_text_left_mark_type || \ +#define GTK_IS_TEXT_MARK_SEGMENT(mark) (((GtkTextLineSegment*)mark)->type == >k_text_left_mark_type || \ ((GtkTextLineSegment*)mark)->type == >k_text_right_mark_type) /* @@ -17,7 +17,7 @@ extern "C" { */ struct _GtkTextMarkBody { - guint refcount; + GtkTextMark *obj; gchar *name; GtkTextBTree *tree; GtkTextLine *line; @@ -28,9 +28,6 @@ struct _GtkTextMarkBody { GtkTextLineSegment *_mark_segment_new (GtkTextBTree *tree, gboolean left_gravity, const gchar *name); -void _mark_segment_ref (GtkTextLineSegment *mark); -void _mark_segment_unref (GtkTextLineSegment *mark); - #ifdef __cplusplus } diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index 54d91d0bf2..d769aa3dec 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -1233,10 +1233,7 @@ gtk_text_attributes_fill_from_tags(GtkTextAttributes *dest, dest->appearance.bg_color = vals->appearance.bg_color; dest->appearance.draw_bg = TRUE; - } - - if (tag->relief_set) - dest->relief = vals->relief; + } if (tag->bg_stipple_set) { @@ -1327,3 +1324,38 @@ gtk_text_attributes_fill_from_tags(GtkTextAttributes *dest, ++n; } } + +gboolean +gtk_text_tag_affects_size (GtkTextTag *tag) +{ + g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE); + + return + tag->font_set || + tag->justify_set || + tag->left_margin_set || + tag->left_wrapped_line_margin_set || + tag->offset_set || + tag->right_margin_set || + tag->pixels_above_lines_set || + tag->pixels_below_lines_set || + tag->pixels_inside_wrap_set || + tag->tabs_set || + tag->underline_set || + tag->wrap_mode_set || + tag->invisible_set; +} + +gboolean +gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag) +{ + g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE); + + return + tag->bg_color_set || + tag->bg_stipple_set || + tag->fg_color_set || + tag->fg_stipple_set || + tag->strikethrough_set || + tag->bg_full_height_set; +} diff --git a/gtk/gtktexttag.h b/gtk/gtktexttag.h index 91a0591f30..0465fb9a39 100644 --- a/gtk/gtktexttag.h +++ b/gtk/gtktexttag.h @@ -31,7 +31,8 @@ typedef struct _GtkTextAttributes GtkTextAttributes; typedef struct _GtkTextTag GtkTextTag; typedef struct _GtkTextTagClass GtkTextTagClass; -struct _GtkTextTag { +struct _GtkTextTag +{ GtkObject parent_instance; GtkTextTagTable *table; @@ -58,7 +59,6 @@ struct _GtkTextTag { * this tag does not affect it. */ guint bg_color_set : 1; - guint relief_set : 1; guint bg_stipple_set : 1; guint fg_color_set : 1; guint font_set : 1; @@ -139,7 +139,6 @@ struct _GtkTextAttributes GtkTextAppearance appearance; - GtkShadowType relief; GtkJustification justify; GtkTextDirection direction; diff --git a/gtk/gtktexttagprivate.h b/gtk/gtktexttagprivate.h index 200864503b..3e95017af9 100644 --- a/gtk/gtktexttagprivate.h +++ b/gtk/gtktexttagprivate.h @@ -23,4 +23,7 @@ void gtk_text_attributes_unrealize (GtkTextAttributes *values, GdkColormap *cmap, GdkVisual *visual); +gboolean gtk_text_tag_affects_size (GtkTextTag *tag); +gboolean gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag); + #endif diff --git a/gtk/testtext.c b/gtk/testtext.c index d813d6fed4..dcc363b6fe 100644 --- a/gtk/testtext.c +++ b/gtk/testtext.c @@ -421,6 +421,10 @@ fill_example_buffer (GtkTextBuffer *buffer) GdkPixbuf *pixbuf; int i; char *str; + + /* FIXME this is broken if called twice on a buffer, since + * we try to create tags a second time. + */ tag = gtk_text_buffer_create_tag (buffer, "fg_blue"); @@ -581,9 +585,13 @@ fill_example_buffer (GtkTextBuffer *buffer) g_object_unref (G_OBJECT (pixbuf)); printf ("%d lines %d chars\n", - gtk_text_buffer_get_line_count (buffer), - gtk_text_buffer_get_char_count (buffer)); + gtk_text_buffer_get_line_count (buffer), + gtk_text_buffer_get_char_count (buffer)); + /* Move cursor to start */ + gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0); + gtk_text_buffer_place_cursor (buffer, &iter); + gtk_text_buffer_set_modified (buffer, FALSE); } diff --git a/tests/testtext.c b/tests/testtext.c index d813d6fed4..dcc363b6fe 100644 --- a/tests/testtext.c +++ b/tests/testtext.c @@ -421,6 +421,10 @@ fill_example_buffer (GtkTextBuffer *buffer) GdkPixbuf *pixbuf; int i; char *str; + + /* FIXME this is broken if called twice on a buffer, since + * we try to create tags a second time. + */ tag = gtk_text_buffer_create_tag (buffer, "fg_blue"); @@ -581,9 +585,13 @@ fill_example_buffer (GtkTextBuffer *buffer) g_object_unref (G_OBJECT (pixbuf)); printf ("%d lines %d chars\n", - gtk_text_buffer_get_line_count (buffer), - gtk_text_buffer_get_char_count (buffer)); + gtk_text_buffer_get_line_count (buffer), + gtk_text_buffer_get_char_count (buffer)); + /* Move cursor to start */ + gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0); + gtk_text_buffer_place_cursor (buffer, &iter); + gtk_text_buffer_set_modified (buffer, FALSE); }