diff options
-rw-r--r-- | ChangeLog | 24 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 24 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 24 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 24 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 24 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 24 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 24 | ||||
-rw-r--r-- | docs/reference/gtk/tmpl/gtkrc.sgml | 1 | ||||
-rw-r--r-- | gtk/gtkdialog.c | 74 | ||||
-rw-r--r-- | gtk/gtkmessagedialog.c | 52 | ||||
-rw-r--r-- | gtk/gtktextbuffer.h | 3 | ||||
-rw-r--r-- | gtk/gtktextdisplay.c | 99 | ||||
-rw-r--r-- | gtk/gtktextiter.c | 196 | ||||
-rw-r--r-- | gtk/gtktextiter.h | 7 | ||||
-rw-r--r-- | gtk/gtktextlayout.c | 86 | ||||
-rw-r--r-- | tests/testtext.c | 2 |
16 files changed, 584 insertions, 104 deletions
@@ -1,3 +1,27 @@ +2001-04-21 Havoc Pennington <hp@pobox.com> + + * gtk/gtktextdisplay.c (gtk_text_layout_draw): handle 0-height + empty/invisible lines. + + * gtk/gtktextiter.c (gtk_text_iter_set_visible_line_offset) + (gtk_text_iter_set_visible_line_index): new functions to set + indexes excluding invisible text + + * gtk/gtktextlayout.c (line_display_iter_to_index): get visible + index + + * gtk/gtktextiter.c (gtk_text_iter_get_visible_line_index) + (gtk_text_iter_get_visible_line_offset): new functions to + get indexes excluding invisible text + + * gtk/gtkmessagedialog.c (gtk_message_dialog_init): strip out a + bunch of extra padding that served no purpose + + * gtk/gtkdialog.c: Make all the spacings configurable via style + properties, for chubbiness configuration in themes + + * tests/testtext.c: fix path to the immodules. + Mon Apr 23 18:57:03 2001 Jonathan Blandford <jrb@redhat.com> * gtk/gtksocket.c (gtk_socket_filter_func): add missing '}' that diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 0b32b0f69a..2759990064 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,27 @@ +2001-04-21 Havoc Pennington <hp@pobox.com> + + * gtk/gtktextdisplay.c (gtk_text_layout_draw): handle 0-height + empty/invisible lines. + + * gtk/gtktextiter.c (gtk_text_iter_set_visible_line_offset) + (gtk_text_iter_set_visible_line_index): new functions to set + indexes excluding invisible text + + * gtk/gtktextlayout.c (line_display_iter_to_index): get visible + index + + * gtk/gtktextiter.c (gtk_text_iter_get_visible_line_index) + (gtk_text_iter_get_visible_line_offset): new functions to + get indexes excluding invisible text + + * gtk/gtkmessagedialog.c (gtk_message_dialog_init): strip out a + bunch of extra padding that served no purpose + + * gtk/gtkdialog.c: Make all the spacings configurable via style + properties, for chubbiness configuration in themes + + * tests/testtext.c: fix path to the immodules. + Mon Apr 23 18:57:03 2001 Jonathan Blandford <jrb@redhat.com> * gtk/gtksocket.c (gtk_socket_filter_func): add missing '}' that diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 0b32b0f69a..2759990064 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,27 @@ +2001-04-21 Havoc Pennington <hp@pobox.com> + + * gtk/gtktextdisplay.c (gtk_text_layout_draw): handle 0-height + empty/invisible lines. + + * gtk/gtktextiter.c (gtk_text_iter_set_visible_line_offset) + (gtk_text_iter_set_visible_line_index): new functions to set + indexes excluding invisible text + + * gtk/gtktextlayout.c (line_display_iter_to_index): get visible + index + + * gtk/gtktextiter.c (gtk_text_iter_get_visible_line_index) + (gtk_text_iter_get_visible_line_offset): new functions to + get indexes excluding invisible text + + * gtk/gtkmessagedialog.c (gtk_message_dialog_init): strip out a + bunch of extra padding that served no purpose + + * gtk/gtkdialog.c: Make all the spacings configurable via style + properties, for chubbiness configuration in themes + + * tests/testtext.c: fix path to the immodules. + Mon Apr 23 18:57:03 2001 Jonathan Blandford <jrb@redhat.com> * gtk/gtksocket.c (gtk_socket_filter_func): add missing '}' that diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 0b32b0f69a..2759990064 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,27 @@ +2001-04-21 Havoc Pennington <hp@pobox.com> + + * gtk/gtktextdisplay.c (gtk_text_layout_draw): handle 0-height + empty/invisible lines. + + * gtk/gtktextiter.c (gtk_text_iter_set_visible_line_offset) + (gtk_text_iter_set_visible_line_index): new functions to set + indexes excluding invisible text + + * gtk/gtktextlayout.c (line_display_iter_to_index): get visible + index + + * gtk/gtktextiter.c (gtk_text_iter_get_visible_line_index) + (gtk_text_iter_get_visible_line_offset): new functions to + get indexes excluding invisible text + + * gtk/gtkmessagedialog.c (gtk_message_dialog_init): strip out a + bunch of extra padding that served no purpose + + * gtk/gtkdialog.c: Make all the spacings configurable via style + properties, for chubbiness configuration in themes + + * tests/testtext.c: fix path to the immodules. + Mon Apr 23 18:57:03 2001 Jonathan Blandford <jrb@redhat.com> * gtk/gtksocket.c (gtk_socket_filter_func): add missing '}' that diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 0b32b0f69a..2759990064 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,27 @@ +2001-04-21 Havoc Pennington <hp@pobox.com> + + * gtk/gtktextdisplay.c (gtk_text_layout_draw): handle 0-height + empty/invisible lines. + + * gtk/gtktextiter.c (gtk_text_iter_set_visible_line_offset) + (gtk_text_iter_set_visible_line_index): new functions to set + indexes excluding invisible text + + * gtk/gtktextlayout.c (line_display_iter_to_index): get visible + index + + * gtk/gtktextiter.c (gtk_text_iter_get_visible_line_index) + (gtk_text_iter_get_visible_line_offset): new functions to + get indexes excluding invisible text + + * gtk/gtkmessagedialog.c (gtk_message_dialog_init): strip out a + bunch of extra padding that served no purpose + + * gtk/gtkdialog.c: Make all the spacings configurable via style + properties, for chubbiness configuration in themes + + * tests/testtext.c: fix path to the immodules. + Mon Apr 23 18:57:03 2001 Jonathan Blandford <jrb@redhat.com> * gtk/gtksocket.c (gtk_socket_filter_func): add missing '}' that diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 0b32b0f69a..2759990064 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,27 @@ +2001-04-21 Havoc Pennington <hp@pobox.com> + + * gtk/gtktextdisplay.c (gtk_text_layout_draw): handle 0-height + empty/invisible lines. + + * gtk/gtktextiter.c (gtk_text_iter_set_visible_line_offset) + (gtk_text_iter_set_visible_line_index): new functions to set + indexes excluding invisible text + + * gtk/gtktextlayout.c (line_display_iter_to_index): get visible + index + + * gtk/gtktextiter.c (gtk_text_iter_get_visible_line_index) + (gtk_text_iter_get_visible_line_offset): new functions to + get indexes excluding invisible text + + * gtk/gtkmessagedialog.c (gtk_message_dialog_init): strip out a + bunch of extra padding that served no purpose + + * gtk/gtkdialog.c: Make all the spacings configurable via style + properties, for chubbiness configuration in themes + + * tests/testtext.c: fix path to the immodules. + Mon Apr 23 18:57:03 2001 Jonathan Blandford <jrb@redhat.com> * gtk/gtksocket.c (gtk_socket_filter_func): add missing '}' that diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 0b32b0f69a..2759990064 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,27 @@ +2001-04-21 Havoc Pennington <hp@pobox.com> + + * gtk/gtktextdisplay.c (gtk_text_layout_draw): handle 0-height + empty/invisible lines. + + * gtk/gtktextiter.c (gtk_text_iter_set_visible_line_offset) + (gtk_text_iter_set_visible_line_index): new functions to set + indexes excluding invisible text + + * gtk/gtktextlayout.c (line_display_iter_to_index): get visible + index + + * gtk/gtktextiter.c (gtk_text_iter_get_visible_line_index) + (gtk_text_iter_get_visible_line_offset): new functions to + get indexes excluding invisible text + + * gtk/gtkmessagedialog.c (gtk_message_dialog_init): strip out a + bunch of extra padding that served no purpose + + * gtk/gtkdialog.c: Make all the spacings configurable via style + properties, for chubbiness configuration in themes + + * tests/testtext.c: fix path to the immodules. + Mon Apr 23 18:57:03 2001 Jonathan Blandford <jrb@redhat.com> * gtk/gtksocket.c (gtk_socket_filter_func): add missing '}' that diff --git a/docs/reference/gtk/tmpl/gtkrc.sgml b/docs/reference/gtk/tmpl/gtkrc.sgml index 178b403922..4c81682d17 100644 --- a/docs/reference/gtk/tmpl/gtkrc.sgml +++ b/docs/reference/gtk/tmpl/gtkrc.sgml @@ -496,6 +496,7 @@ This can later be composited together with other #GtkRcStyle structures to form a #GtkStyle. </para> +@parent_instance: @name: @bg_pixmap_name: @font_desc: diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c index b4af6a7a26..324f781d15 100644 --- a/gtk/gtkdialog.c +++ b/gtk/gtkdialog.c @@ -55,6 +55,8 @@ static void gtk_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void gtk_dialog_style_set (GtkWidget *widget, + GtkStyle *prev_style); enum { PROP_0, @@ -111,7 +113,8 @@ gtk_dialog_class_init (GtkDialogClass *class) gobject_class->get_property = gtk_dialog_get_property; widget_class->key_press_event = gtk_dialog_key_press; - + widget_class->style_set = gtk_dialog_style_set; + g_object_class_install_property (gobject_class, PROP_HAS_SEPARATOR, g_param_spec_boolean ("has_separator", @@ -128,6 +131,59 @@ gtk_dialog_class_init (GtkDialogClass *class) gtk_marshal_NONE__INT, GTK_TYPE_NONE, 1, GTK_TYPE_INT); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("content_area_border", + _("Content area border"), + _("Width of border around the main dialog area"), + 0, + G_MAXINT, + 2, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("button_spacing", + _("Button spacing"), + _("Spacing between buttons"), + 0, + G_MAXINT, + 1, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("action_area_border", + _("Action area border"), + _("Width of border around the button area at the bottom of the dialog"), + 0, + G_MAXINT, + 0, + G_PARAM_READABLE)); +} + +static void +update_spacings (GtkDialog *dialog) +{ + GtkWidget *widget; + gint content_area_border; + gint button_spacing; + gint action_area_border; + + widget = GTK_WIDGET (dialog); + + gtk_widget_style_get (widget, + "content_area_border", + &content_area_border, + "button_spacing", + &button_spacing, + "action_area_border", + &action_area_border, + NULL); + + gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), + content_area_border); + gtk_box_set_spacing (GTK_BOX (dialog->action_area), + button_spacing); + gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), + action_area_border); } static void @@ -143,8 +199,6 @@ gtk_dialog_init (GtkDialog *dialog) NULL); dialog->vbox = gtk_vbox_new (FALSE, 0); - - gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 2); gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox); gtk_widget_show (dialog->vbox); @@ -152,11 +206,8 @@ gtk_dialog_init (GtkDialog *dialog) dialog->action_area = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog->action_area), - GTK_BUTTONBOX_END); + GTK_BUTTONBOX_END); - gtk_box_set_spacing (GTK_BOX (dialog->action_area), 5); - - gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5); gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area, FALSE, TRUE, 0); gtk_widget_show (dialog->action_area); @@ -252,6 +303,13 @@ gtk_dialog_key_press (GtkWidget *widget, return TRUE; } +static void +gtk_dialog_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + update_spacings (GTK_DIALOG (widget)); +} + GtkWidget* gtk_dialog_new (void) { @@ -444,7 +502,7 @@ gtk_dialog_add_action_widget (GtkDialog *dialog, gtk_box_pack_end (GTK_BOX (dialog->action_area), child, - FALSE, TRUE, 5); + FALSE, TRUE, 0); } /** diff --git a/gtk/gtkmessagedialog.c b/gtk/gtkmessagedialog.c index 6a74193cf2..c6a0145a93 100644 --- a/gtk/gtkmessagedialog.c +++ b/gtk/gtkmessagedialog.c @@ -30,10 +30,14 @@ #include "gtkimage.h" #include "gtkstock.h" #include "gtkiconfactory.h" +#include "gtkintl.h" static void gtk_message_dialog_class_init (GtkMessageDialogClass *klass); static void gtk_message_dialog_init (GtkMessageDialog *dialog); +static void gtk_message_dialog_style_set (GtkWidget *widget, + GtkStyle *prev_style); +static gpointer parent_class; GtkType gtk_message_dialog_get_type (void) @@ -63,6 +67,22 @@ gtk_message_dialog_get_type (void) static void gtk_message_dialog_class_init (GtkMessageDialogClass *class) { + GtkWidgetClass *widget_class; + + widget_class = GTK_WIDGET_CLASS (class); + + parent_class = g_type_class_peek_parent (class); + + widget_class->style_set = gtk_message_dialog_style_set; + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("message_border", + _("Image/label border"), + _("Width of border around the label and image in the message dialog"), + 0, + G_MAXINT, + 8, + G_PARAM_READABLE)); } static void @@ -75,19 +95,17 @@ gtk_message_dialog_init (GtkMessageDialog *dialog) gtk_label_set_line_wrap (GTK_LABEL (dialog->label), TRUE); - hbox = gtk_hbox_new (FALSE, 10); + hbox = gtk_hbox_new (FALSE, 6); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 10); - gtk_box_pack_start (GTK_BOX (hbox), dialog->image, - FALSE, FALSE, 2); + FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), dialog->label, - TRUE, TRUE, 2); + TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, - FALSE, FALSE, 10); + FALSE, FALSE, 0); gtk_widget_show_all (hbox); } @@ -247,3 +265,25 @@ gtk_message_dialog_new (GtkWindow *parent, return widget; } + +static void +gtk_message_dialog_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + GtkWidget *parent; + gint border_width = 0; + + parent = GTK_WIDGET (GTK_MESSAGE_DIALOG (widget)->image->parent); + + if (parent) + { + gtk_widget_style_get (widget, "message_border", + &border_width, NULL); + + gtk_container_set_border_width (GTK_CONTAINER (parent), + border_width); + } + + if (GTK_WIDGET_CLASS (parent_class)->style_set) + (GTK_WIDGET_CLASS (parent_class)->style_set) (widget, prev_style); +} diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h index 54f245e8aa..b6f801f119 100644 --- a/gtk/gtktextbuffer.h +++ b/gtk/gtktextbuffer.h @@ -277,7 +277,8 @@ GtkTextTag *gtk_text_buffer_create_tag (GtkTextBuffer *buffer, ...); /* Obtain iterators pointed at various places, then you can move the - iterator around using the GtkTextIter operators */ + * iterator around using the GtkTextIter operators + */ void gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer, GtkTextIter *iter, gint line_number, diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c index 17e3f5b560..0b2c3f7872 100644 --- a/gtk/gtktextdisplay.c +++ b/gtk/gtktextdisplay.c @@ -739,66 +739,71 @@ gtk_text_layout_draw (GtkTextLayout *layout, GtkTextLine *line = tmp_list->data; line_display = gtk_text_layout_get_line_display (layout, line, FALSE); - - if (have_selection) - { - GtkTextIter line_start, line_end; - gint byte_count; - gtk_text_layout_get_iter_at_line (layout, - &line_start, - line, 0); - byte_count = gtk_text_iter_get_bytes_in_line (&line_start); + if (line_display->height > 0) + { + g_assert (line_display->layout != NULL); - /* FIXME the -1 assumes a newline I think */ - gtk_text_layout_get_iter_at_line (layout, - &line_end, - line, byte_count - 1); - - if (gtk_text_iter_compare (&selection_start, &line_end) < 0 && - gtk_text_iter_compare (&selection_end, &line_start) > 0) + if (have_selection) { - if (gtk_text_iter_compare (&selection_start, &line_start) >= 0) - selection_start_index = gtk_text_iter_get_line_index (&selection_start); - else - selection_start_index = -1; + GtkTextIter line_start, line_end; + gint byte_count; - if (gtk_text_iter_compare (&selection_end, &line_end) <= 0) - selection_end_index = gtk_text_iter_get_line_index (&selection_end); - else - selection_end_index = byte_count; + gtk_text_layout_get_iter_at_line (layout, + &line_start, + line, 0); + byte_count = gtk_text_iter_get_bytes_in_line (&line_start); + + /* FIXME the -1 assumes a newline I think */ + gtk_text_layout_get_iter_at_line (layout, + &line_end, + line, byte_count - 1); + + if (gtk_text_iter_compare (&selection_start, &line_end) < 0 && + gtk_text_iter_compare (&selection_end, &line_start) > 0) + { + if (gtk_text_iter_compare (&selection_start, &line_start) >= 0) + selection_start_index = gtk_text_iter_get_line_index (&selection_start); + else + selection_start_index = -1; + + if (gtk_text_iter_compare (&selection_end, &line_end) <= 0) + selection_end_index = gtk_text_iter_get_line_index (&selection_end); + else + selection_end_index = byte_count; + } } - } - render_para (drawable, render_state, line_display, - - x_offset, - current_y, - selection_start_index, selection_end_index); + render_para (drawable, render_state, line_display, + - x_offset, + current_y, + selection_start_index, selection_end_index); - /* We paint the cursors last, because they overlap another chunk + /* We paint the cursors last, because they overlap another chunk and need to appear on top. */ - cursor_list = line_display->cursors; - while (cursor_list) - { - GtkTextCursorDisplay *cursor = cursor_list->data; - GdkGC *gc; - - if (cursor->is_strong) - gc = widget->style->base_gc[GTK_STATE_SELECTED]; - else - gc = widget->style->text_gc[GTK_STATE_NORMAL]; + cursor_list = line_display->cursors; + while (cursor_list) + { + GtkTextCursorDisplay *cursor = cursor_list->data; + GdkGC *gc; - gdk_draw_line (drawable, gc, - line_display->x_offset + cursor->x - x_offset, - current_y + line_display->top_margin + cursor->y, - line_display->x_offset + cursor->x - x_offset, - current_y + line_display->top_margin + cursor->y + cursor->height - 1); + if (cursor->is_strong) + gc = widget->style->base_gc[GTK_STATE_SELECTED]; + else + gc = widget->style->text_gc[GTK_STATE_NORMAL]; - cursor_list = cursor_list->next; - } + gdk_draw_line (drawable, gc, + line_display->x_offset + cursor->x - x_offset, + current_y + line_display->top_margin + cursor->y, + line_display->x_offset + cursor->x - x_offset, + current_y + line_display->top_margin + cursor->y + cursor->height - 1); + cursor_list = cursor_list->next; + } + } /* line_display->height > 0 */ + current_y += line_display->height; gtk_text_layout_free_line_display (layout, line_display); render_state->last_appearance = NULL; diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c index 73a51ed368..241529d389 100644 --- a/gtk/gtktextiter.c +++ b/gtk/gtktextiter.c @@ -650,7 +650,6 @@ gtk_text_iter_get_line (const GtkTextIter *iter) gint gtk_text_iter_get_line_offset (const GtkTextIter *iter) { - GtkTextRealIter *real; g_return_val_if_fail (iter != NULL, 0); @@ -683,7 +682,7 @@ gint gtk_text_iter_get_line_index (const GtkTextIter *iter) { GtkTextRealIter *real; - + g_return_val_if_fail (iter != NULL, 0); real = gtk_text_iter_make_surreal (iter); @@ -698,6 +697,108 @@ gtk_text_iter_get_line_index (const GtkTextIter *iter) return real->line_byte_offset; } +gint +gtk_text_iter_get_visible_line_offset (const GtkTextIter *iter) +{ + GtkTextRealIter *real; + gint vis_offset; + GtkTextLineSegment *seg; + GtkTextIter pos; + + g_return_val_if_fail (iter != NULL, 0); + + real = gtk_text_iter_make_real (iter); + + if (real == NULL) + return 0; + + ensure_char_offsets (real); + + check_invariants (iter); + + vis_offset = real->line_char_offset; + + _gtk_text_btree_get_iter_at_line (real->tree, + &pos, + real->line, + 0); + + seg = _gtk_text_iter_get_indexable_segment (&pos); + + while (seg != real->segment) + { + /* This is a pretty expensive call, making the + * whole function pretty lame; we could keep track + * of current invisibility state by looking at toggle + * segments as we loop, and then call this function + * only once per line, in order to speed up the loop + * quite a lot. + */ + if (_gtk_text_btree_char_is_invisible (&pos)) + vis_offset -= seg->char_count; + + _gtk_text_iter_forward_indexable_segment (&pos); + + seg = _gtk_text_iter_get_indexable_segment (&pos); + } + + if (_gtk_text_btree_char_is_invisible (&pos)) + vis_offset -= real->segment_char_offset; + + return vis_offset; +} + +gint +gtk_text_iter_get_visible_line_index (const GtkTextIter *iter) +{ + GtkTextRealIter *real; + gint vis_offset; + GtkTextLineSegment *seg; + GtkTextIter pos; + + g_return_val_if_fail (iter != NULL, 0); + + real = gtk_text_iter_make_real (iter); + + if (real == NULL) + return 0; + + ensure_char_offsets (real); + + check_invariants (iter); + + vis_offset = real->line_byte_offset; + + _gtk_text_btree_get_iter_at_line (real->tree, + &pos, + real->line, + 0); + + seg = _gtk_text_iter_get_indexable_segment (&pos); + + while (seg != real->segment) + { + /* This is a pretty expensive call, making the + * whole function pretty lame; we could keep track + * of current invisibility state by looking at toggle + * segments as we loop, and then call this function + * only once per line, in order to speed up the loop + * quite a lot. + */ + if (_gtk_text_btree_char_is_invisible (&pos)) + vis_offset -= seg->byte_count; + + _gtk_text_iter_forward_indexable_segment (&pos); + + seg = _gtk_text_iter_get_indexable_segment (&pos); + } + + if (_gtk_text_btree_char_is_invisible (&pos)) + vis_offset -= real->segment_byte_offset; + + return vis_offset; +} + /* * Dereferencing */ @@ -3276,6 +3377,97 @@ gtk_text_iter_set_line_index (GtkTextIter *iter, check_invariants (iter); } + +/** + * gtk_text_iter_set_visible_line_offset: + * @iter: a #GtkTextIter + * @char_on_line: a character offset + * + * Like gtk_text_iter_set_line_offset(), but the offset is in visible + * characters, i.e. text with a tag making it invisible is not + * counted in the offset. + **/ +void +gtk_text_iter_set_visible_line_offset (GtkTextIter *iter, + gint char_on_line) +{ + gint chars_seen = 0; + GtkTextIter pos; + + g_return_if_fail (iter != NULL); + + pos = *iter; + + /* For now we use a ludicrously slow implementation */ + while (chars_seen < char_on_line) + { + if (!_gtk_text_btree_char_is_invisible (&pos)) + ++chars_seen; + + if (!gtk_text_iter_forward_char (&pos)) + break; + + if (chars_seen == char_on_line) + break; + } + + if (_gtk_text_iter_get_text_line (&pos) == _gtk_text_iter_get_text_line (iter)) + *iter = pos; + else + gtk_text_iter_forward_line (iter); +} + +static gint +bytes_in_char (GtkTextIter *iter) +{ + return g_unichar_to_utf8 (gtk_text_iter_get_char (iter), NULL); +} + +/** + * gtk_text_iter_set_visible_line_index: + * @iter: a #GtkTextIter + * @byte_on_line: a byte index + * + * Like gtk_text_iter_set_line_index(), but the index is in visible + * bytes, i.e. text with a tag making it invisible is not counted + * in the index. + **/ +void +gtk_text_iter_set_visible_line_index (GtkTextIter *iter, + gint byte_on_line) +{ + gint bytes_seen = 0; + GtkTextIter pos; + + g_return_if_fail (iter != NULL); + + pos = *iter; + + /* For now we use a ludicrously slow implementation */ + while (bytes_seen < byte_on_line) + { + if (!_gtk_text_btree_char_is_invisible (&pos)) + bytes_seen += bytes_in_char (&pos); + + if (!gtk_text_iter_forward_char (&pos)) + break; + + if (bytes_seen >= byte_on_line) + break; + } + + if (bytes_seen > byte_on_line) + g_warning ("%s: Incorrect visible byte index %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); + + if (_gtk_text_iter_get_text_line (&pos) == _gtk_text_iter_get_text_line (iter)) + *iter = pos; + else + gtk_text_iter_forward_line (iter); +} + /** * gtk_text_iter_set_line: * @iter: a #GtkTextIter diff --git a/gtk/gtktextiter.h b/gtk/gtktextiter.h index 9b25a8be49..00285e287b 100644 --- a/gtk/gtktextiter.h +++ b/gtk/gtktextiter.h @@ -78,6 +78,9 @@ 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); +gint gtk_text_iter_get_visible_line_offset (const GtkTextIter *iter); +gint gtk_text_iter_get_visible_line_index (const GtkTextIter *iter); + /* * "Dereference" operators @@ -197,6 +200,10 @@ void gtk_text_iter_set_line_index (GtkTextIter *iter, void gtk_text_iter_forward_to_end (GtkTextIter *iter); gboolean gtk_text_iter_forward_to_line_end (GtkTextIter *iter); +void gtk_text_iter_set_visible_line_offset (GtkTextIter *iter, + gint char_on_line); +void gtk_text_iter_set_visible_line_index (GtkTextIter *iter, + gint byte_on_line); /* returns TRUE if a toggle was found; NULL for the tag pointer * means "any tag toggle", otherwise the next toggle of the diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index dad06d319d..ec61bb250a 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -994,14 +994,16 @@ totally_invisible_line (GtkTextLayout *layout, int bytes = 0; /* If we have a cached style, then we know it does actually apply - and we can just see if it is invisible. */ + * and we can just see if it is invisible. + */ if (layout->one_style_cache && !layout->one_style_cache->invisible) return FALSE; /* Without the cache, we check if the first char is visible, if so - we are partially visible. Note that we have to check this since - we don't know the current invisible/noninvisible toggle state; this - function can use the whole btree to get it right. */ + * we are partially visible. Note that we have to check this since + * we don't know the current invisible/noninvisible toggle state; this + * function can use the whole btree to get it right. + */ else { _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), @@ -1020,10 +1022,11 @@ totally_invisible_line (GtkTextLayout *layout, bytes += seg->byte_count; /* Note that these two tests can cause us to bail out - when we shouldn't, because a higher-priority tag - may override these settings. However the important - thing is to only invisible really-invisible lines, rather - than to invisible all really-invisible lines. */ + * when we shouldn't, because a higher-priority tag + * may override these settings. However the important + * thing is to only invisible really-invisible lines, rather + * than to invisible all really-invisible lines. + */ else if (seg->type == >k_text_toggle_on_type) { @@ -1478,8 +1481,6 @@ allocate_child_widgets (GtkTextLayout *text_layout, pango_layout_iter_get_run_extents (iter, NULL, &extents); - - g_print ("extents at %d,%d\n", extents.x, extents.y); g_signal_emit (G_OBJECT (text_layout), signals[ALLOCATE_CHILD], @@ -1593,7 +1594,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, GtkTextAttributes *style; gchar *text; PangoAttrList *attrs; - gint byte_count, layout_byte_offset, layout_only_bytes; + gint text_allocated, layout_byte_offset, buffer_byte_offset; gdouble align; PangoRectangle extents; gboolean para_values_set = FALSE; @@ -1635,14 +1636,14 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, /* Allocate space for flat text for buffer */ - byte_count = _gtk_text_line_byte_count (line); - text = g_malloc (byte_count); + text_allocated = _gtk_text_line_byte_count (line); + text = g_malloc (text_allocated); attrs = pango_attr_list_new (); /* Iterate over segments, creating display chunks for them. */ - layout_byte_offset = 0; /* current length of layout text (includes preedit) */ - layout_only_bytes = 0; /* bytes in layout_byte_offset not in buffer */ + layout_byte_offset = 0; /* current length of layout text (includes preedit, does not include invisible text) */ + buffer_byte_offset = 0; /* position in the buffer line */ seg = _gtk_text_iter_get_any_segment (&iter); while (seg != NULL) { @@ -1653,7 +1654,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, { _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), &iter, line, - layout_byte_offset - layout_only_bytes); + buffer_byte_offset); style = get_style (layout, &iter); /* We have to delay setting the paragraph values until we @@ -1692,6 +1693,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, { memcpy (text + layout_byte_offset, seg->body.chars, seg->byte_count); layout_byte_offset += seg->byte_count; + buffer_byte_offset += seg->byte_count; bytes += seg->byte_count; } else if (seg->type == >k_text_right_mark_type || @@ -1739,6 +1741,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, memcpy (text + layout_byte_offset, gtk_text_unknown_char_utf8, seg->byte_count); layout_byte_offset += seg->byte_count; + buffer_byte_offset += seg->byte_count; } else if (seg->type == >k_text_child_type) { @@ -1753,11 +1756,19 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, memcpy (text + layout_byte_offset, gtk_text_unknown_char_utf8, seg->byte_count); layout_byte_offset += seg->byte_count; + buffer_byte_offset += seg->byte_count; } else { + /* We don't know this segment type */ g_assert_not_reached (); } + + } /* if (segment was visible) */ + else + { + /* Invisible segment */ + buffer_byte_offset += seg->byte_count; } release_style (layout, style); @@ -1787,8 +1798,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, if (layout->preedit_len > 0) { - byte_count += layout->preedit_len; - text = g_realloc (text, byte_count); + text_allocated += layout->preedit_len; + text = g_realloc (text, text_allocated); style = get_style (layout, &iter); add_preedit_attrs (layout, style, attrs, layout_byte_offset, size_only); @@ -1796,7 +1807,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, memcpy (text + layout_byte_offset, layout->preedit_string, layout->preedit_len); layout_byte_offset += layout->preedit_len; - layout_only_bytes += layout->preedit_len; + /* DO NOT increment the buffer byte offset for preedit */ cursor_offset = layout->preedit_cursor - layout->preedit_len; } @@ -1825,8 +1836,6 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, set_para_values (layout, style, display, &align); release_style (layout, style); } - - g_assert (layout_byte_offset == byte_count); /* Pango doesn't want the trailing paragraph delimiters */ @@ -1897,7 +1906,8 @@ gtk_text_layout_free_line_display (GtkTextLayout *layout, { if (display != layout->one_display_cache) { - g_object_unref (G_OBJECT (display->layout)); + if (display->layout) + g_object_unref (G_OBJECT (display->layout)); if (display->cursors) { @@ -1911,7 +1921,7 @@ gtk_text_layout_free_line_display (GtkTextLayout *layout, } /* Functions to convert iter <=> index for the line of a GtkTextLineDisplay - * taking into account the preedit string, if necessary. + * taking into account the preedit string and invisible text if necessary. */ static gint line_display_iter_to_index (GtkTextLayout *layout, @@ -1922,8 +1932,8 @@ line_display_iter_to_index (GtkTextLayout *layout, g_return_val_if_fail (_gtk_text_iter_get_text_line (iter) == display->line, 0); - index = gtk_text_iter_get_line_index (iter); - + index = gtk_text_iter_get_visible_line_index (iter); + if (index >= display->insert_index) index += layout->preedit_len; @@ -1937,8 +1947,6 @@ line_display_index_to_iter (GtkTextLayout *layout, gint index, gint trailing) { - gint line_len; - if (index >= display->insert_index + layout->preedit_len) index -= layout->preedit_len; else if (index > display->insert_index) @@ -1946,27 +1954,24 @@ line_display_index_to_iter (GtkTextLayout *layout, index = display->insert_index; trailing = 0; } - - line_len = _gtk_text_line_byte_count (display->line); - g_assert (index <= line_len); - if (index < line_len) - _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), - iter, display->line, index); - else + _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), + iter, display->line, 0); + + gtk_text_iter_set_visible_line_index (iter, index); + + if (_gtk_text_iter_get_text_line (iter) != display->line) { /* Clamp to end of line - really this clamping should have been done * before here, maybe in Pango, this is a broken band-aid I think */ - g_assert (index == line_len); - _gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer), iter, display->line, 0); if (!gtk_text_iter_ends_line (iter)) gtk_text_iter_forward_to_line_end (iter); } - + /* FIXME should this be cursor positions? */ gtk_text_iter_forward_chars (iter, trailing); } @@ -2414,7 +2419,7 @@ gtk_text_layout_clamp_iter_to_vrange (GtkTextLayout *layout, } /** - * gtk_text_layout_move_iter_to_next_line: + * gtk_text_layout_move_iter_to_previous_line: * @layout: a #GtkLayout * @iter: a #GtkTextIter * @@ -2439,9 +2444,10 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, orig = *iter; line = _gtk_text_iter_get_text_line (iter); - display = gtk_text_layout_get_line_display (layout, line, FALSE); + display = gtk_text_layout_get_line_display (layout, line, FALSE); line_byte = line_display_iter_to_index (layout, display, iter); + /* FIXME can't use layout until we check display->height > 0) */ tmp_list = pango_layout_get_lines (display->layout); layout_line = tmp_list->data; @@ -2449,6 +2455,8 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, { GtkTextLine *prev_line = _gtk_text_line_previous (line); + /* FIXME keep going back while display->height == 0 */ + if (prev_line) { gtk_text_layout_free_line_display (layout, display); diff --git a/tests/testtext.c b/tests/testtext.c index badbaf17a7..73c7231f64 100644 --- a/tests/testtext.c +++ b/tests/testtext.c @@ -2236,7 +2236,7 @@ test_init () if (file_exists ("../gdk-pixbuf/.libs/libpixbufloader-pnm.so")) { putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs"); - putenv ("GTK_IM_MODULE_FILE=./gtk.immodules"); + putenv ("GTK_IM_MODULE_FILE=../gtk/gtk.immodules"); } } |