handle 0-height empty/invisible lines.

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.
This commit is contained in:
Havoc Pennington 2001-04-24 12:24:35 +00:00 • committed by Havoc Pennington
commit b84d2f1234
16 changed files with 584 additions and 104 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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);
}
/**

View file

@ -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);
}

View file

@ -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,

View file

@ -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)
if (line_display->height > 0)
{
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);
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;
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];
if (cursor->is_strong)
gc = widget->style->base_gc[GTK_STATE_SELECTED];
else
gc = widget->style->text_gc[GTK_STATE_NORMAL];
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;
}
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;

View file

@ -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

View file

@ -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

View file

@ -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 == &gtk_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 == &gtk_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 == &gtk_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);

View file

@ -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");
}
}