Commit b84d2f12 authored by Havoc Pennington's avatar Havoc Pennington Committed by Havoc Pennington

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.
parent 60051ff6
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
......
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
......
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
......
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
......
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
......
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
......
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
......
......@@ -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:
......
......@@ -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);
}
/**
......
......@@ -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);
}
......@@ -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,
......
......@@ -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;
......
......@@ -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);