mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 13:41:07 +00:00
Avoid recreating pangolayouts in GtkTextView on cursor movement (#435405,
2007-06-01 Yevgen Muntyan <muntyan@tamu.edu> Avoid recreating pangolayouts in GtkTextView on cursor movement (#435405, Behdad Esfahbod). * gtk/gtktextlayout.c: * gtk/gtktextlayout.h: new GtkTextLayout method invalidate_cursors(), and functions gtk_text_layout_invalidate_cursors() and gtk_text_layout_cursors_changed(), to use when invalidation is due to moved marks or changed selection. * gtk/gtktextbtree.c: * gtk/gtktextbtree.h: use what's appropriate when invalidating layout. * gtk/gtk.symbols: add new functions. * README.in: added a note about changed GtkTextLayout API. svn path=/trunk/; revision=18000
This commit is contained in:
parent
5ffdc33df0
commit
8f4aa8c6d7
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
||||
2007-06-01 Yevgen Muntyan <muntyan@tamu.edu>
|
||||
|
||||
Avoid recreating pangolayouts in GtkTextView on cursor movement
|
||||
(#435405, Behdad Esfahbod).
|
||||
|
||||
* gtk/gtktextlayout.c:
|
||||
* gtk/gtktextlayout.h: new GtkTextLayout method invalidate_cursors(),
|
||||
and functions gtk_text_layout_invalidate_cursors() and
|
||||
gtk_text_layout_cursors_changed(), to use when invalidation is due
|
||||
to moved marks or changed selection.
|
||||
|
||||
* gtk/gtktextbtree.c:
|
||||
* gtk/gtktextbtree.h: use what's appropriate when invalidating layout.
|
||||
|
||||
* gtk/gtk.symbols: add new functions.
|
||||
|
||||
* README.in: added a note about changed GtkTextLayout API.
|
||||
|
||||
2007-06-01 Alp Toker <alp.toker@collabora.co.uk>
|
||||
|
||||
* gdk/gdkcairo.c (gdk_cairo_set_source_pixmap): Fix doc typos.
|
||||
|
10
README.in
10
README.in
@ -48,6 +48,16 @@ Release notes for 2.12
|
||||
GDK for drawing decorations. In particular, metacity <= 2.18.0 is affected
|
||||
by this. The problem has been fixed in metacity 2.18.1.
|
||||
|
||||
* Semi-private GtkTextLayout api has changed: new GtkTextLayout method
|
||||
invalidate_cursors(), and new functions gtk_text_layout_invalidate_cursors()
|
||||
and gtk_text_layout_cursors_changed(), which should be used in place of
|
||||
gtk_text_layout_invalidate() and gtk_text_layout_changed() if invalidation
|
||||
is due to marks moved or changed selection; new GtkTextLineDisplay structure
|
||||
member. Source compatibility is preserved; binary compatibility may break
|
||||
only if GtkTextLineDisplay structure was created on stack or as a part
|
||||
of another structure (in particular GnomeCanvas and its clones do not need
|
||||
recompiling).
|
||||
|
||||
Release notes for 2.10
|
||||
======================
|
||||
|
||||
|
@ -3715,6 +3715,7 @@ gtk_text_iter_toggles_tag
|
||||
#if IN_HEADER(__GTK_TEXT_LAYOUT_H__)
|
||||
#if IN_FILE(__GTK_TEXT_LAYOUT_C__)
|
||||
gtk_text_layout_changed
|
||||
gtk_text_layout_cursors_changed
|
||||
gtk_text_layout_clamp_iter_to_vrange
|
||||
gtk_text_layout_default_style_changed
|
||||
gtk_text_layout_free_line_data
|
||||
@ -3733,6 +3734,7 @@ gtk_text_layout_get_line_yrange
|
||||
gtk_text_layout_get_size
|
||||
gtk_text_layout_get_type G_GNUC_CONST
|
||||
gtk_text_layout_invalidate
|
||||
gtk_text_layout_invalidate_cursors
|
||||
gtk_text_layout_is_valid
|
||||
gtk_text_layout_iter_starts_line
|
||||
gtk_text_layout_move_iter_to_line_end
|
||||
|
@ -340,7 +340,8 @@ static void gtk_text_btree_remove_tag_info (GtkTextBTree *tre
|
||||
|
||||
static void redisplay_region (GtkTextBTree *tree,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
const GtkTextIter *end,
|
||||
gboolean cursors_only);
|
||||
|
||||
/* Inline thingies */
|
||||
|
||||
@ -663,7 +664,7 @@ gtk_text_btree_resolve_bidi (GtkTextIter *start,
|
||||
*/
|
||||
line = _gtk_text_line_previous (line);
|
||||
_gtk_text_btree_get_iter_at_line (tree, &end_propagate, line, 0);
|
||||
_gtk_text_btree_invalidate_region (tree, end, &end_propagate);
|
||||
_gtk_text_btree_invalidate_region (tree, end, &end_propagate, FALSE);
|
||||
}
|
||||
|
||||
/* Sweep backward */
|
||||
@ -719,7 +720,7 @@ gtk_text_btree_resolve_bidi (GtkTextIter *start,
|
||||
if (line && line->dir_propagated_forward == PANGO_DIRECTION_NEUTRAL)
|
||||
{
|
||||
_gtk_text_btree_get_iter_at_line (tree, &start_propagate, line, 0);
|
||||
_gtk_text_btree_invalidate_region(tree, &start_propagate, start);
|
||||
_gtk_text_btree_invalidate_region (tree, &start_propagate, start, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -756,7 +757,7 @@ _gtk_text_btree_delete (GtkTextIter *start,
|
||||
|
||||
/* Broadcast the need for redisplay before we break the iterators */
|
||||
DV (g_print ("invalidating due to deleting some text (%s)\n", G_STRLOC));
|
||||
_gtk_text_btree_invalidate_region (tree, start, end);
|
||||
_gtk_text_btree_invalidate_region (tree, start, end, FALSE);
|
||||
|
||||
/* Save the byte offset so we can reset the iterators */
|
||||
start_byte_offset = gtk_text_iter_get_line_index (start);
|
||||
@ -1241,8 +1242,7 @@ _gtk_text_btree_insert (GtkTextIter *iter,
|
||||
gtk_text_iter_forward_chars (&end, char_count_delta);
|
||||
|
||||
DV (g_print ("invalidating due to inserting some text (%s)\n", G_STRLOC));
|
||||
_gtk_text_btree_invalidate_region (tree,
|
||||
&start, &end);
|
||||
_gtk_text_btree_invalidate_region (tree, &start, &end, FALSE);
|
||||
|
||||
|
||||
/* Convenience for the user */
|
||||
@ -1292,7 +1292,7 @@ insert_pixbuf_or_widget_segment (GtkTextIter *iter,
|
||||
gtk_text_iter_forward_char (iter); /* skip forward past the segment */
|
||||
|
||||
DV (g_print ("invalidating due to inserting pixbuf/widget (%s)\n", G_STRLOC));
|
||||
_gtk_text_btree_invalidate_region (tree, &start, iter);
|
||||
_gtk_text_btree_invalidate_region (tree, &start, iter, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1627,7 +1627,8 @@ _gtk_text_btree_remove_view (GtkTextBTree *tree,
|
||||
void
|
||||
_gtk_text_btree_invalidate_region (GtkTextBTree *tree,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
const GtkTextIter *end,
|
||||
gboolean cursors_only)
|
||||
{
|
||||
BTreeView *view;
|
||||
|
||||
@ -1635,7 +1636,10 @@ _gtk_text_btree_invalidate_region (GtkTextBTree *tree,
|
||||
|
||||
while (view != NULL)
|
||||
{
|
||||
gtk_text_layout_invalidate (view->layout, start, end);
|
||||
if (cursors_only)
|
||||
gtk_text_layout_invalidate_cursors (view->layout, start, end);
|
||||
else
|
||||
gtk_text_layout_invalidate (view->layout, start, end);
|
||||
|
||||
view = view->next;
|
||||
}
|
||||
@ -1740,12 +1744,12 @@ queue_tag_redisplay (GtkTextBTree *tree,
|
||||
if (_gtk_text_tag_affects_size (tag))
|
||||
{
|
||||
DV (g_print ("invalidating due to size-affecting tag (%s)\n", G_STRLOC));
|
||||
_gtk_text_btree_invalidate_region (tree, start, end);
|
||||
_gtk_text_btree_invalidate_region (tree, start, end, FALSE);
|
||||
}
|
||||
else if (_gtk_text_tag_affects_nonsize_appearance (tag))
|
||||
{
|
||||
/* We only need to queue a redraw, not a relayout */
|
||||
redisplay_region (tree, start, end);
|
||||
redisplay_region (tree, start, end, FALSE);
|
||||
}
|
||||
|
||||
/* We don't need to do anything if the tag doesn't affect display */
|
||||
@ -2599,7 +2603,8 @@ _gtk_text_btree_char_is_invisible (const GtkTextIter *iter)
|
||||
static void
|
||||
redisplay_region (GtkTextBTree *tree,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
const GtkTextIter *end,
|
||||
gboolean cursors_only)
|
||||
{
|
||||
BTreeView *view;
|
||||
GtkTextLine *start_line, *end_line;
|
||||
@ -2631,9 +2636,14 @@ 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);
|
||||
if (cursors_only)
|
||||
gtk_text_layout_cursors_changed (view->layout, start_y,
|
||||
end_y - start_y,
|
||||
end_y - start_y);
|
||||
else
|
||||
gtk_text_layout_changed (view->layout, start_y,
|
||||
end_y - start_y,
|
||||
end_y - start_y);
|
||||
|
||||
view = view->next;
|
||||
}
|
||||
@ -2653,8 +2663,7 @@ redisplay_mark (GtkTextLineSegment *mark)
|
||||
gtk_text_iter_forward_char (&end);
|
||||
|
||||
DV (g_print ("invalidating due to moving visible mark (%s)\n", G_STRLOC));
|
||||
_gtk_text_btree_invalidate_region (mark->body.mark.tree,
|
||||
&iter, &end);
|
||||
_gtk_text_btree_invalidate_region (mark->body.mark.tree, &iter, &end, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2729,7 +2738,7 @@ real_set_mark (GtkTextBTree *tree,
|
||||
|
||||
_gtk_text_btree_get_iter_at_mark (tree, &old_pos,
|
||||
mark->body.mark.obj);
|
||||
redisplay_region (tree, &old_pos, where);
|
||||
redisplay_region (tree, &old_pos, where, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2863,18 +2872,28 @@ _gtk_text_btree_select_range (GtkTextBTree *tree,
|
||||
const GtkTextIter *ins,
|
||||
const GtkTextIter *bound)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
GtkTextIter old_ins, old_bound;
|
||||
|
||||
if (_gtk_text_btree_get_selection_bounds (tree, &start, &end))
|
||||
redisplay_region (tree, &start, &end);
|
||||
_gtk_text_btree_get_iter_at_mark (tree, &old_ins,
|
||||
tree->insert_mark);
|
||||
_gtk_text_btree_get_iter_at_mark (tree, &old_bound,
|
||||
tree->selection_bound_mark);
|
||||
|
||||
/* Move insert AND selection_bound before we redisplay */
|
||||
real_set_mark (tree, tree->insert_mark,
|
||||
"insert", FALSE, ins, TRUE, FALSE);
|
||||
real_set_mark (tree, tree->selection_bound_mark,
|
||||
"selection_bound", FALSE, bound, TRUE, FALSE);
|
||||
/* Check if it's no-op since gtk_text_buffer_place_cursor()
|
||||
* also calls this, and this will redraw the cursor line. */
|
||||
if (!gtk_text_iter_equal (&old_ins, ins) ||
|
||||
!gtk_text_iter_equal (&old_bound, bound))
|
||||
{
|
||||
redisplay_region (tree, &old_ins, &old_bound, TRUE);
|
||||
|
||||
redisplay_region (tree, ins, bound);
|
||||
/* Move insert AND selection_bound before we redisplay */
|
||||
real_set_mark (tree, tree->insert_mark,
|
||||
"insert", FALSE, ins, TRUE, FALSE);
|
||||
real_set_mark (tree, tree->selection_bound_mark,
|
||||
"selection_bound", FALSE, bound, TRUE, FALSE);
|
||||
|
||||
redisplay_region (tree, ins, bound, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5619,8 +5638,7 @@ tag_changed_cb (GtkTextTagTable *table,
|
||||
/* Must be a last toggle if there was a first one. */
|
||||
_gtk_text_btree_get_iter_at_last_toggle (tree, &end, tag);
|
||||
DV (g_print ("invalidating due to tag change (%s)\n", G_STRLOC));
|
||||
_gtk_text_btree_invalidate_region (tree,
|
||||
&start, &end);
|
||||
_gtk_text_btree_invalidate_region (tree, &start, &end, FALSE);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,8 @@ void _gtk_text_btree_remove_view (GtkTextBTree *tree,
|
||||
gpointer view_id);
|
||||
void _gtk_text_btree_invalidate_region (GtkTextBTree *tree,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
const GtkTextIter *end,
|
||||
gboolean cursors_only);
|
||||
void _gtk_text_btree_get_view_size (GtkTextBTree *tree,
|
||||
gpointer view_id,
|
||||
gint *width,
|
||||
|
@ -110,9 +110,14 @@ static void gtk_text_layout_invalidated (GtkTextLayout *layout);
|
||||
static void gtk_text_layout_real_invalidate (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
static void gtk_text_layout_real_invalidate_cursors(GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
static void gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
|
||||
GtkTextLine *line);
|
||||
static void gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout);
|
||||
GtkTextLine *line,
|
||||
gboolean cursors_only);
|
||||
static void gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout,
|
||||
gboolean cursors_only);
|
||||
static void gtk_text_layout_real_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data);
|
||||
@ -172,6 +177,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
|
||||
|
||||
klass->wrap = gtk_text_layout_real_wrap;
|
||||
klass->invalidate = gtk_text_layout_real_invalidate;
|
||||
klass->invalidate_cursors = gtk_text_layout_real_invalidate_cursors;
|
||||
klass->free_line_data = gtk_text_layout_real_free_line_data;
|
||||
|
||||
signals[INVALIDATED] =
|
||||
@ -411,7 +417,7 @@ gtk_text_layout_set_cursor_direction (GtkTextLayout *layout,
|
||||
if (direction != layout->cursor_direction)
|
||||
{
|
||||
layout->cursor_direction = direction;
|
||||
gtk_text_layout_invalidate_cursor_line (layout);
|
||||
gtk_text_layout_invalidate_cursor_line (layout, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,7 +436,7 @@ gtk_text_layout_set_keyboard_direction (GtkTextLayout *layout,
|
||||
if (keyboard_dir != layout->keyboard_direction)
|
||||
{
|
||||
layout->keyboard_direction = keyboard_dir;
|
||||
gtk_text_layout_invalidate_cursor_line (layout);
|
||||
gtk_text_layout_invalidate_cursor_line (layout, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,7 +504,7 @@ gtk_text_layout_set_cursor_visible (GtkTextLayout *layout,
|
||||
gtk_text_layout_get_line_yrange (layout, &iter, &y, &height);
|
||||
gtk_text_layout_emit_changed (layout, y, height, height);
|
||||
|
||||
gtk_text_layout_invalidate_cache (layout, _gtk_text_iter_get_text_line (&iter));
|
||||
gtk_text_layout_invalidate_cache (layout, _gtk_text_iter_get_text_line (&iter), TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,7 +566,7 @@ gtk_text_layout_set_preedit_string (GtkTextLayout *layout,
|
||||
layout->preedit_cursor = 0;
|
||||
}
|
||||
|
||||
gtk_text_layout_invalidate_cursor_line (layout);
|
||||
gtk_text_layout_invalidate_cursor_line (layout, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -592,11 +598,12 @@ gtk_text_layout_emit_changed (GtkTextLayout *layout,
|
||||
g_signal_emit (layout, signals[CHANGED], 0, y, old_height, new_height);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_changed (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
gint new_height)
|
||||
static void
|
||||
text_layout_changed (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
gint new_height,
|
||||
gboolean cursors_only)
|
||||
{
|
||||
/* Check if the range intersects our cached line display,
|
||||
* and invalidate the cached line if so.
|
||||
@ -609,12 +616,30 @@ gtk_text_layout_changed (GtkTextLayout *layout,
|
||||
gint cache_height = layout->one_display_cache->height;
|
||||
|
||||
if (cache_y + cache_height > y && cache_y < y + old_height)
|
||||
gtk_text_layout_invalidate_cache (layout, line);
|
||||
gtk_text_layout_invalidate_cache (layout, line, cursors_only);
|
||||
}
|
||||
|
||||
|
||||
gtk_text_layout_emit_changed (layout, y, old_height, new_height);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_changed (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
gint new_height)
|
||||
{
|
||||
text_layout_changed (layout, y, old_height, new_height, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_cursors_changed (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
gint new_height)
|
||||
{
|
||||
text_layout_changed (layout, y, old_height, new_height, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
@ -633,6 +658,15 @@ gtk_text_layout_invalidate (GtkTextLayout *layout,
|
||||
(layout, start_index, end_index);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_invalidate_cursors (GtkTextLayout *layout,
|
||||
const GtkTextIter *start_index,
|
||||
const GtkTextIter *end_index)
|
||||
{
|
||||
(* GTK_TEXT_LAYOUT_GET_CLASS (layout)->invalidate_cursors)
|
||||
(layout, start_index, end_index);
|
||||
}
|
||||
|
||||
GtkTextLineData*
|
||||
gtk_text_layout_wrap (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
@ -748,20 +782,33 @@ gtk_text_layout_invalidate_all (GtkTextLayout *layout)
|
||||
|
||||
static void
|
||||
gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
|
||||
GtkTextLine *line)
|
||||
GtkTextLine *line,
|
||||
gboolean cursors_only)
|
||||
{
|
||||
if (layout->one_display_cache && line == layout->one_display_cache->line)
|
||||
{
|
||||
GtkTextLineDisplay *tmp_display = layout->one_display_cache;
|
||||
layout->one_display_cache = NULL;
|
||||
gtk_text_layout_free_line_display (layout, tmp_display);
|
||||
GtkTextLineDisplay *display = layout->one_display_cache;
|
||||
|
||||
if (cursors_only)
|
||||
{
|
||||
g_slist_foreach (display->cursors, (GFunc)g_free, NULL);
|
||||
g_slist_free (display->cursors);
|
||||
display->cursors = NULL;
|
||||
display->cursors_invalid = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
layout->one_display_cache = NULL;
|
||||
gtk_text_layout_free_line_display (layout, display);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now invalidate the paragraph containing the cursor
|
||||
*/
|
||||
static void
|
||||
gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout)
|
||||
gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout,
|
||||
gboolean cursors_only)
|
||||
{
|
||||
GtkTextLayoutPrivate *priv = GTK_TEXT_LAYOUT_GET_PRIVATE (layout);
|
||||
GtkTextLineData *line_data;
|
||||
@ -772,8 +819,14 @@ gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout)
|
||||
line_data = _gtk_text_line_get_data (priv->cursor_line, layout);
|
||||
if (line_data)
|
||||
{
|
||||
gtk_text_layout_invalidate_cache (layout, priv->cursor_line);
|
||||
_gtk_text_line_invalidate_wrap (priv->cursor_line, line_data);
|
||||
if (cursors_only)
|
||||
gtk_text_layout_invalidate_cache (layout, priv->cursor_line, TRUE);
|
||||
else
|
||||
{
|
||||
gtk_text_layout_invalidate_cache (layout, priv->cursor_line, FALSE);
|
||||
_gtk_text_line_invalidate_wrap (priv->cursor_line, line_data);
|
||||
}
|
||||
|
||||
gtk_text_layout_invalidated (layout);
|
||||
}
|
||||
}
|
||||
@ -820,7 +873,7 @@ gtk_text_layout_real_invalidate (GtkTextLayout *layout,
|
||||
{
|
||||
GtkTextLineData *line_data = _gtk_text_line_get_data (line, layout);
|
||||
|
||||
gtk_text_layout_invalidate_cache (layout, line);
|
||||
gtk_text_layout_invalidate_cache (layout, line, FALSE);
|
||||
|
||||
if (line_data)
|
||||
_gtk_text_line_invalidate_wrap (line, line_data);
|
||||
@ -834,12 +887,48 @@ gtk_text_layout_real_invalidate (GtkTextLayout *layout,
|
||||
gtk_text_layout_invalidated (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_layout_real_invalidate_cursors (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
{
|
||||
/* Check if the range intersects our cached line display,
|
||||
* and invalidate the cached line if so.
|
||||
*/
|
||||
if (layout->one_display_cache)
|
||||
{
|
||||
GtkTextIter line_start, line_end;
|
||||
GtkTextLine *line = layout->one_display_cache->line;
|
||||
|
||||
_gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
|
||||
&line_start, line, 0);
|
||||
line_end = line_start;
|
||||
if (!gtk_text_iter_ends_line (&line_end))
|
||||
gtk_text_iter_forward_to_line_end (&line_end);
|
||||
|
||||
if (gtk_text_iter_compare (start, end) > 0)
|
||||
{
|
||||
const GtkTextIter *tmp = start;
|
||||
start = end;
|
||||
end = tmp;
|
||||
}
|
||||
|
||||
if (gtk_text_iter_compare (&line_start, end) <= 0 &&
|
||||
gtk_text_iter_compare (start, &line_end) <= 0)
|
||||
{
|
||||
gtk_text_layout_invalidate_cache (layout, line, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_text_layout_invalidated (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_layout_real_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data)
|
||||
{
|
||||
gtk_text_layout_invalidate_cache (layout, line);
|
||||
gtk_text_layout_invalidate_cache (layout, line, FALSE);
|
||||
|
||||
g_free (line_data);
|
||||
}
|
||||
@ -1789,6 +1878,112 @@ add_preedit_attrs (GtkTextLayout *layout,
|
||||
pango_attr_iterator_destroy (iter);
|
||||
}
|
||||
|
||||
/* Iterate over the line and fill in display->cursors.
|
||||
* It's a stripped copy of gtk_text_layout_get_line_display() */
|
||||
static void
|
||||
update_text_display_cursors (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineDisplay *display)
|
||||
{
|
||||
GtkTextLineSegment *seg;
|
||||
GtkTextIter iter;
|
||||
gint layout_byte_offset, buffer_byte_offset;
|
||||
GSList *cursor_byte_offsets = NULL;
|
||||
GSList *cursor_segs = NULL;
|
||||
GSList *tmp_list1, *tmp_list2;
|
||||
|
||||
if (!display->cursors_invalid)
|
||||
return;
|
||||
|
||||
display->cursors_invalid = FALSE;
|
||||
|
||||
_gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
|
||||
&iter, line, 0);
|
||||
|
||||
/* Special-case optimization for completely
|
||||
* invisible lines; makes it faster to deal
|
||||
* with sequences of invisible lines.
|
||||
*/
|
||||
if (totally_invisible_line (layout, line, &iter))
|
||||
return;
|
||||
|
||||
/* Iterate over segments */
|
||||
layout_byte_offset = 0; /* position in the 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)
|
||||
{
|
||||
/* Displayable segments */
|
||||
if (seg->type == >k_text_char_type ||
|
||||
seg->type == >k_text_pixbuf_type ||
|
||||
seg->type == >k_text_child_type)
|
||||
{
|
||||
_gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
|
||||
&iter, line,
|
||||
buffer_byte_offset);
|
||||
|
||||
if (!_gtk_text_btree_char_is_invisible (&iter))
|
||||
layout_byte_offset += seg->byte_count;
|
||||
|
||||
buffer_byte_offset += seg->byte_count;
|
||||
}
|
||||
|
||||
/* Marks */
|
||||
else if (seg->type == >k_text_right_mark_type ||
|
||||
seg->type == >k_text_left_mark_type)
|
||||
{
|
||||
gint cursor_offset = 0;
|
||||
|
||||
/* At the insertion point, add the preedit string, if any */
|
||||
|
||||
if (_gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer),
|
||||
seg->body.mark.obj))
|
||||
{
|
||||
display->insert_index = layout_byte_offset;
|
||||
|
||||
if (layout->preedit_len > 0)
|
||||
{
|
||||
layout_byte_offset += layout->preedit_len;
|
||||
/* DO NOT increment the buffer byte offset for preedit */
|
||||
cursor_offset = layout->preedit_cursor - layout->preedit_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Display visible marks */
|
||||
|
||||
if (seg->body.mark.visible)
|
||||
{
|
||||
cursor_byte_offsets = g_slist_prepend (cursor_byte_offsets,
|
||||
GINT_TO_POINTER (layout_byte_offset + cursor_offset));
|
||||
cursor_segs = g_slist_prepend (cursor_segs, seg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Toggles */
|
||||
else if (seg->type == >k_text_toggle_on_type ||
|
||||
seg->type == >k_text_toggle_off_type)
|
||||
{
|
||||
}
|
||||
|
||||
else
|
||||
g_error ("Unknown segment type: %s", seg->type->name);
|
||||
|
||||
seg = seg->next;
|
||||
}
|
||||
|
||||
tmp_list1 = cursor_byte_offsets;
|
||||
tmp_list2 = cursor_segs;
|
||||
while (tmp_list1)
|
||||
{
|
||||
add_cursor (layout, display, tmp_list2->data,
|
||||
GPOINTER_TO_INT (tmp_list1->data));
|
||||
tmp_list1 = tmp_list1->next;
|
||||
tmp_list2 = tmp_list2->next;
|
||||
}
|
||||
g_slist_free (cursor_byte_offsets);
|
||||
g_slist_free (cursor_segs);
|
||||
}
|
||||
|
||||
GtkTextLineDisplay *
|
||||
gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
@ -1816,7 +2011,11 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
{
|
||||
if (line == layout->one_display_cache->line &&
|
||||
(size_only || !layout->one_display_cache->size_only))
|
||||
return layout->one_display_cache;
|
||||
{
|
||||
if (!size_only)
|
||||
update_text_display_cursors (layout, line, layout->one_display_cache);
|
||||
return layout->one_display_cache;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkTextLineDisplay *tmp_display = layout->one_display_cache;
|
||||
@ -1825,6 +2024,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
}
|
||||
}
|
||||
|
||||
DV (g_print ("creating one line display cache (%s)\n", G_STRLOC));
|
||||
|
||||
display = g_new0 (GtkTextLineDisplay, 1);
|
||||
|
||||
display->size_only = size_only;
|
||||
|
@ -209,11 +209,14 @@ struct _GtkTextLayoutClass
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
void (*invalidate_cursors) (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
};
|
||||
|
||||
struct _GtkTextAttrAppearance
|
||||
@ -254,6 +257,8 @@ struct _GtkTextLineDisplay
|
||||
GtkTextLine *line;
|
||||
|
||||
GdkColor *pg_bg_color;
|
||||
|
||||
guint cursors_invalid : 1;
|
||||
};
|
||||
|
||||
extern PangoAttrType gtk_text_attr_appearance_type;
|
||||
@ -327,6 +332,9 @@ void gtk_text_layout_get_iter_at_position (GtkTextLayout *layout,
|
||||
void gtk_text_layout_invalidate (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
void gtk_text_layout_invalidate_cursors(GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
void gtk_text_layout_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data);
|
||||
@ -353,6 +361,10 @@ void gtk_text_layout_changed (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
gint new_height);
|
||||
void gtk_text_layout_cursors_changed (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
gint new_height);
|
||||
void gtk_text_layout_get_iter_location (GtkTextLayout *layout,
|
||||
const GtkTextIter *iter,
|
||||
GdkRectangle *rect);
|
||||
|
Loading…
Reference in New Issue
Block a user