summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2000-11-03 20:40:57 +0000
committerHavoc Pennington <hp@src.gnome.org>2000-11-03 20:40:57 +0000
commitca83d0a3dcb6660cff67f61fca108b1b02c31859 (patch)
treee3fc8cfe149cdfaac5adb2750c24c200c38e276a
parentb506b461cb03d4b3aac16f82298a5427f1baf759 (diff)
downloadgtk+-ca83d0a3dcb6660cff67f61fca108b1b02c31859.tar.gz
Get widgets working on the btree/buffer side. Display of them still
2000-11-03 Havoc Pennington <hp@redhat.com> Get widgets working on the btree/buffer side. Display of them still doesn't work. * gtk/gtktextview.c: start implementing child widget stuff * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function * gtk/gtktextlayout.c: handle embedded widgets * gtk/gtktextdisplay.c: handle embedded widgets * gtk/gtktextchild.c: Implement all the child anchor goo * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New function * gtk/gtktextbtree.c: Add child anchor table to the btree struct (insert_pixbuf_or_widget_segment): abstract out common portions of creating a child anchor or a pixbuf segment. (gtk_text_btree_create_child_anchor): new function (gtk_text_btree_unregister_child_anchor): new function * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the allocate_child signal on GtkTextLayout * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return values (gtk_text_iter_get_child_anchor): new function * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a default handler for the changed signal, which calls gtk_text_buffer_set_modified(), instead of just always emitting changed then calling set_modified() manually. I guess this is maybe more flexible. It seems logical.
-rw-r--r--ChangeLog37
-rw-r--r--ChangeLog.pre-2-037
-rw-r--r--ChangeLog.pre-2-1037
-rw-r--r--ChangeLog.pre-2-237
-rw-r--r--ChangeLog.pre-2-437
-rw-r--r--ChangeLog.pre-2-637
-rw-r--r--ChangeLog.pre-2-837
-rw-r--r--gtk/gtkmarshal.list1
-rw-r--r--gtk/gtkmarshalers.list1
-rw-r--r--gtk/gtktextbtree.c63
-rw-r--r--gtk/gtktextbtree.h7
-rw-r--r--gtk/gtktextbuffer.c72
-rw-r--r--gtk/gtktextbuffer.h20
-rw-r--r--gtk/gtktextchild.c213
-rw-r--r--gtk/gtktextchild.h29
-rw-r--r--gtk/gtktextchildprivate.h18
-rw-r--r--gtk/gtktextdisplay.c147
-rw-r--r--gtk/gtktextiter.c55
-rw-r--r--gtk/gtktextiter.h3
-rw-r--r--gtk/gtktextlayout.c114
-rw-r--r--gtk/gtktextlayout.h27
-rw-r--r--gtk/gtktextview.c140
22 files changed, 970 insertions, 199 deletions
diff --git a/ChangeLog b/ChangeLog
index cde1f062e0..aa193e9b6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2000-11-03 Havoc Pennington <hp@redhat.com>
+
+ Get widgets working on the btree/buffer side. Display of them
+ still doesn't work.
+
+ * gtk/gtktextview.c: start implementing child widget stuff
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextlayout.c: handle embedded widgets
+
+ * gtk/gtktextdisplay.c: handle embedded widgets
+
+ * gtk/gtktextchild.c: Implement all the child anchor goo
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+ function
+
+ * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+ (insert_pixbuf_or_widget_segment): abstract out common portions of
+ creating a child anchor or a pixbuf segment.
+ (gtk_text_btree_create_child_anchor): new function
+ (gtk_text_btree_unregister_child_anchor): new function
+
+ * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+ allocate_child signal on GtkTextLayout
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+ values
+ (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+ default handler for the changed signal, which calls
+ gtk_text_buffer_set_modified(), instead of just always emitting
+ changed then calling set_modified() manually. I guess this is
+ maybe more flexible. It seems logical.
+
Fri Nov 3 08:58:38 2000 Tim Janik <timj@gtk.org>
* gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index cde1f062e0..aa193e9b6c 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,40 @@
+2000-11-03 Havoc Pennington <hp@redhat.com>
+
+ Get widgets working on the btree/buffer side. Display of them
+ still doesn't work.
+
+ * gtk/gtktextview.c: start implementing child widget stuff
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextlayout.c: handle embedded widgets
+
+ * gtk/gtktextdisplay.c: handle embedded widgets
+
+ * gtk/gtktextchild.c: Implement all the child anchor goo
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+ function
+
+ * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+ (insert_pixbuf_or_widget_segment): abstract out common portions of
+ creating a child anchor or a pixbuf segment.
+ (gtk_text_btree_create_child_anchor): new function
+ (gtk_text_btree_unregister_child_anchor): new function
+
+ * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+ allocate_child signal on GtkTextLayout
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+ values
+ (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+ default handler for the changed signal, which calls
+ gtk_text_buffer_set_modified(), instead of just always emitting
+ changed then calling set_modified() manually. I guess this is
+ maybe more flexible. It seems logical.
+
Fri Nov 3 08:58:38 2000 Tim Janik <timj@gtk.org>
* gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index cde1f062e0..aa193e9b6c 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,40 @@
+2000-11-03 Havoc Pennington <hp@redhat.com>
+
+ Get widgets working on the btree/buffer side. Display of them
+ still doesn't work.
+
+ * gtk/gtktextview.c: start implementing child widget stuff
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextlayout.c: handle embedded widgets
+
+ * gtk/gtktextdisplay.c: handle embedded widgets
+
+ * gtk/gtktextchild.c: Implement all the child anchor goo
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+ function
+
+ * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+ (insert_pixbuf_or_widget_segment): abstract out common portions of
+ creating a child anchor or a pixbuf segment.
+ (gtk_text_btree_create_child_anchor): new function
+ (gtk_text_btree_unregister_child_anchor): new function
+
+ * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+ allocate_child signal on GtkTextLayout
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+ values
+ (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+ default handler for the changed signal, which calls
+ gtk_text_buffer_set_modified(), instead of just always emitting
+ changed then calling set_modified() manually. I guess this is
+ maybe more flexible. It seems logical.
+
Fri Nov 3 08:58:38 2000 Tim Janik <timj@gtk.org>
* gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index cde1f062e0..aa193e9b6c 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,40 @@
+2000-11-03 Havoc Pennington <hp@redhat.com>
+
+ Get widgets working on the btree/buffer side. Display of them
+ still doesn't work.
+
+ * gtk/gtktextview.c: start implementing child widget stuff
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextlayout.c: handle embedded widgets
+
+ * gtk/gtktextdisplay.c: handle embedded widgets
+
+ * gtk/gtktextchild.c: Implement all the child anchor goo
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+ function
+
+ * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+ (insert_pixbuf_or_widget_segment): abstract out common portions of
+ creating a child anchor or a pixbuf segment.
+ (gtk_text_btree_create_child_anchor): new function
+ (gtk_text_btree_unregister_child_anchor): new function
+
+ * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+ allocate_child signal on GtkTextLayout
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+ values
+ (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+ default handler for the changed signal, which calls
+ gtk_text_buffer_set_modified(), instead of just always emitting
+ changed then calling set_modified() manually. I guess this is
+ maybe more flexible. It seems logical.
+
Fri Nov 3 08:58:38 2000 Tim Janik <timj@gtk.org>
* gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index cde1f062e0..aa193e9b6c 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,40 @@
+2000-11-03 Havoc Pennington <hp@redhat.com>
+
+ Get widgets working on the btree/buffer side. Display of them
+ still doesn't work.
+
+ * gtk/gtktextview.c: start implementing child widget stuff
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextlayout.c: handle embedded widgets
+
+ * gtk/gtktextdisplay.c: handle embedded widgets
+
+ * gtk/gtktextchild.c: Implement all the child anchor goo
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+ function
+
+ * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+ (insert_pixbuf_or_widget_segment): abstract out common portions of
+ creating a child anchor or a pixbuf segment.
+ (gtk_text_btree_create_child_anchor): new function
+ (gtk_text_btree_unregister_child_anchor): new function
+
+ * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+ allocate_child signal on GtkTextLayout
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+ values
+ (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+ default handler for the changed signal, which calls
+ gtk_text_buffer_set_modified(), instead of just always emitting
+ changed then calling set_modified() manually. I guess this is
+ maybe more flexible. It seems logical.
+
Fri Nov 3 08:58:38 2000 Tim Janik <timj@gtk.org>
* gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index cde1f062e0..aa193e9b6c 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,40 @@
+2000-11-03 Havoc Pennington <hp@redhat.com>
+
+ Get widgets working on the btree/buffer side. Display of them
+ still doesn't work.
+
+ * gtk/gtktextview.c: start implementing child widget stuff
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextlayout.c: handle embedded widgets
+
+ * gtk/gtktextdisplay.c: handle embedded widgets
+
+ * gtk/gtktextchild.c: Implement all the child anchor goo
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+ function
+
+ * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+ (insert_pixbuf_or_widget_segment): abstract out common portions of
+ creating a child anchor or a pixbuf segment.
+ (gtk_text_btree_create_child_anchor): new function
+ (gtk_text_btree_unregister_child_anchor): new function
+
+ * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+ allocate_child signal on GtkTextLayout
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+ values
+ (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+ default handler for the changed signal, which calls
+ gtk_text_buffer_set_modified(), instead of just always emitting
+ changed then calling set_modified() manually. I guess this is
+ maybe more flexible. It seems logical.
+
Fri Nov 3 08:58:38 2000 Tim Janik <timj@gtk.org>
* gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index cde1f062e0..aa193e9b6c 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,40 @@
+2000-11-03 Havoc Pennington <hp@redhat.com>
+
+ Get widgets working on the btree/buffer side. Display of them
+ still doesn't work.
+
+ * gtk/gtktextview.c: start implementing child widget stuff
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextlayout.c: handle embedded widgets
+
+ * gtk/gtktextdisplay.c: handle embedded widgets
+
+ * gtk/gtktextchild.c: Implement all the child anchor goo
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_create_child_anchor): New
+ function
+
+ * gtk/gtktextbtree.c: Add child anchor table to the btree struct
+ (insert_pixbuf_or_widget_segment): abstract out common portions of
+ creating a child anchor or a pixbuf segment.
+ (gtk_text_btree_create_child_anchor): new function
+ (gtk_text_btree_unregister_child_anchor): new function
+
+ * gtk/gtkmarshal.list: added VOID:OBJECT,INT,INT for the
+ allocate_child signal on GtkTextLayout
+
+ * gtk/gtktextiter.c (gtk_text_iter_get_pixbuf): fix bogus return
+ values
+ (gtk_text_iter_get_child_anchor): new function
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_real_changed): Add a
+ default handler for the changed signal, which calls
+ gtk_text_buffer_set_modified(), instead of just always emitting
+ changed then calling set_modified() manually. I guess this is
+ maybe more flexible. It seems logical.
+
Fri Nov 3 08:58:38 2000 Tim Janik <timj@gtk.org>
* gtk/gtkobject.c: _g_signal_handlers_destroy() is prefixed with '_'
diff --git a/gtk/gtkmarshal.list b/gtk/gtkmarshal.list
index 3b8624549d..5e01c765e4 100644
--- a/gtk/gtkmarshal.list
+++ b/gtk/gtkmarshal.list
@@ -56,6 +56,7 @@ VOID:INT,INT,POINTER
VOID:OBJECT
VOID:OBJECT,BOXED,BOXED
VOID:OBJECT,BOOLEAN
+VOID:OBJECT,INT,INT
VOID:ENUM,INT
VOID:POINTER
VOID:POINTER,BOOLEAN
diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list
index 3b8624549d..5e01c765e4 100644
--- a/gtk/gtkmarshalers.list
+++ b/gtk/gtkmarshalers.list
@@ -56,6 +56,7 @@ VOID:INT,INT,POINTER
VOID:OBJECT
VOID:OBJECT,BOXED,BOXED
VOID:OBJECT,BOOLEAN
+VOID:OBJECT,INT,INT
VOID:ENUM,INT
VOID:POINTER
VOID:POINTER,BOOLEAN
diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c
index 3f0f7c2c2e..b73ba456c6 100644
--- a/gtk/gtktextbtree.c
+++ b/gtk/gtktextbtree.c
@@ -195,6 +195,8 @@ struct _GtkTextBTree {
GtkTextLine *end_iter_line;
guint end_iter_line_stamp;
+
+ GHashTable *child_anchor_table;
};
@@ -417,7 +419,8 @@ gtk_text_btree_new (GtkTextTagTable *table,
tree);
tree->mark_table = g_hash_table_new (g_str_hash, g_str_equal);
-
+ tree->child_anchor_table = NULL;
+
/* We don't ref the buffer, since the buffer owns us;
* we'd have some circularity issues. The buffer always
* lasts longer than the BTree
@@ -1053,11 +1056,11 @@ gtk_text_btree_insert (GtkTextIter *iter,
}
}
-void
-gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
- GdkPixbuf *pixbuf)
+static void
+insert_pixbuf_or_widget_segment (GtkTextIter *iter,
+ GtkTextLineSegment *seg)
+
{
- GtkTextLineSegment *seg;
GtkTextIter start;
GtkTextLineSegment *prevPtr;
GtkTextLine *line;
@@ -1068,8 +1071,6 @@ gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
tree = gtk_text_iter_get_btree (iter);
start_byte_offset = gtk_text_iter_get_line_index (iter);
- seg = _gtk_pixbuf_segment_new (pixbuf);
-
prevPtr = gtk_text_line_segment_split (iter);
if (prevPtr == NULL)
{
@@ -1092,11 +1093,54 @@ gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
gtk_text_btree_get_iter_at_line (tree, &start, line, start_byte_offset);
*iter = start;
- gtk_text_iter_next_char (iter); /* skip forward past the pixmap */
+ gtk_text_iter_next_char (iter); /* skip forward past the segment */
gtk_text_btree_invalidate_region (tree, &start, iter);
}
+
+void
+gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
+ GdkPixbuf *pixbuf)
+{
+ GtkTextLineSegment *seg;
+
+ seg = _gtk_pixbuf_segment_new (pixbuf);
+
+ insert_pixbuf_or_widget_segment (iter, seg);
+}
+
+GtkTextChildAnchor*
+gtk_text_btree_create_child_anchor (GtkTextIter *iter)
+{
+ GtkTextLineSegment *seg;
+ GtkTextBTree *tree;
+
+ seg = _gtk_widget_segment_new ();
+
+ insert_pixbuf_or_widget_segment (iter, seg);
+
+ tree = seg->body.child.tree;
+
+ if (tree->child_anchor_table == NULL)
+ tree->child_anchor_table = g_hash_table_new (NULL, NULL);
+
+ g_hash_table_insert (tree->child_anchor_table,
+ seg->body.child.obj,
+ seg->body.child.obj);
+
+ return seg->body.child.obj;
+}
+
+void
+gtk_text_btree_unregister_child_anchor (GtkTextChildAnchor *anchor)
+{
+ GtkTextLineSegment *seg;
+ seg = anchor->segment;
+
+ g_hash_table_remove (seg->body.child.tree->child_anchor_table,
+ anchor);
+}
/*
* View stuff
@@ -2069,7 +2113,8 @@ copy_segment (GString *string,
/* printf (" :%s\n", string->str); */
}
- else if (seg->type == &gtk_text_pixbuf_type)
+ else if (seg->type == &gtk_text_pixbuf_type ||
+ seg->type == &gtk_text_child_type)
{
gboolean copy = TRUE;
diff --git a/gtk/gtktextbtree.h b/gtk/gtktextbtree.h
index f5ce91d159..a2229373ce 100644
--- a/gtk/gtktextbtree.h
+++ b/gtk/gtktextbtree.h
@@ -34,7 +34,9 @@ void gtk_text_btree_insert (GtkTextIter *iter,
void gtk_text_btree_insert_pixbuf (GtkTextIter *iter,
GdkPixbuf *pixbuf);
+GtkTextChildAnchor* gtk_text_btree_create_child_anchor (GtkTextIter *iter);
+void gtk_text_btree_unregister_child_anchor (GtkTextChildAnchor *anchor);
/* View stuff */
GtkTextLine *gtk_text_btree_find_line_by_y (GtkTextBTree *tree,
@@ -129,6 +131,11 @@ gboolean gtk_text_btree_get_iter_at_last_toggle (GtkTextBTree *tree,
GtkTextIter *iter,
GtkTextTag *tag);
+void gtk_text_btree_get_iter_at_child_anchor (GtkTextBTree *tree,
+ GtkTextIter *iter,
+ GtkTextChildAnchor *anchor);
+
+
/* Manipulate marks */
GtkTextMark *gtk_text_btree_set_mark (GtkTextBTree *tree,
diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index 0c3ded39c3..c3fcf25e17 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -93,6 +93,7 @@ static void gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffe
GtkTextTag *tag,
const GtkTextIter *start_char,
const GtkTextIter *end_char);
+static void gtk_text_buffer_real_changed (GtkTextBuffer *buffer);
static GtkTextBTree* get_btree (GtkTextBuffer *buffer);
@@ -230,6 +231,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
klass->delete_text = gtk_text_buffer_real_delete_text;
klass->apply_tag = gtk_text_buffer_real_apply_tag;
klass->remove_tag = gtk_text_buffer_real_remove_tag;
+ klass->changed = gtk_text_buffer_real_changed;
}
void
@@ -401,8 +403,6 @@ gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
gtk_text_btree_insert (iter, text, len);
gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
-
- gtk_text_buffer_set_modified (buffer, TRUE);
}
static void
@@ -738,8 +738,6 @@ gtk_text_buffer_real_delete_text (GtkTextBuffer *buffer,
gtk_text_buffer_update_primary_selection (buffer);
gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
-
- gtk_text_buffer_set_modified (buffer, TRUE);
}
static void
@@ -1021,10 +1019,31 @@ gtk_text_buffer_insert_pixbuf (GtkTextBuffer *buffer,
/* FIXME pixbuf-specific signal like insert_text */
gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
+}
- gtk_text_buffer_set_modified (buffer, TRUE);
+/*
+ * Child anchor
+ */
+
+GtkTextChildAnchor*
+gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
+ GtkTextIter *iter)
+{
+ GtkTextChildAnchor *anchor;
+
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+
+ anchor = gtk_text_btree_create_child_anchor (iter);
+
+ /* FIXME child-anchor-specific signal */
+
+ gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
+
+ return anchor;
}
+
/*
* Mark manipulation
*/
@@ -1350,41 +1369,19 @@ gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer)
return gtk_text_buffer_get_mark (buffer, "selection_bound");
}
-
-GtkTextChildAnchor*
-gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
- const GtkTextIter *where)
-{
- /* FIXME: Implement? */
-
- return NULL;
-}
-
-void
-gtk_text_buffer_move_child_anchor (GtkTextBuffer *buffer,
- GtkTextChildAnchor *anchor,
- GtkTextIter *where)
-{
-
-
-}
-
-void
-gtk_text_buffer_delete_child_anchor (GtkTextBuffer *buffer,
- GtkTextChildAnchor *anchor)
-{
-
-
-
-}
-
void
gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer *buffer,
GtkTextIter *iter,
GtkTextChildAnchor *anchor)
{
-
-
+ g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+ g_return_if_fail (!gtk_text_child_anchor_get_deleted (anchor));
+
+ gtk_text_btree_get_iter_at_child_anchor (get_btree (buffer),
+ iter,
+ anchor);
}
/**
@@ -1473,6 +1470,11 @@ gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
gtk_text_btree_tag (start, end, tag, FALSE);
}
+static void
+gtk_text_buffer_real_changed (GtkTextBuffer *buffer)
+{
+ gtk_text_buffer_set_modified (buffer, TRUE);
+}
static void
gtk_text_buffer_emit_tag (GtkTextBuffer *buffer,
diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h
index 2b60ab56e7..c1b5fcdd58 100644
--- a/gtk/gtktextbuffer.h
+++ b/gtk/gtktextbuffer.h
@@ -78,8 +78,9 @@ struct _GtkTextBufferClass {
GtkTextIter *end,
gboolean interactive);
- /* Only for text changed, marks/tags don't cause this
- to be emitted */
+ /* Only for text/widgets/pixbuf changed, marks/tags don't cause this
+ * to be emitted
+ */
void (* changed) (GtkTextBuffer *buffer);
@@ -193,6 +194,10 @@ void gtk_text_buffer_insert_pixbuf (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkPixbuf *pixbuf);
+/* Create a child anchor */
+GtkTextChildAnchor *gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
+ GtkTextIter *iter);
+
/* Mark manipulation */
GtkTextMark *gtk_text_buffer_create_mark (GtkTextBuffer *buffer,
const gchar *mark_name,
@@ -215,17 +220,6 @@ void gtk_text_buffer_delete_mark_by_name (GtkTextBuffer *buffer,
GtkTextMark* gtk_text_buffer_get_insert (GtkTextBuffer *buffer);
GtkTextMark* gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer);
-/* Child widget anchors */
-
-GtkTextChildAnchor* gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
- const GtkTextIter *where);
-void gtk_text_buffer_move_child_anchor (GtkTextBuffer *buffer,
- GtkTextChildAnchor *anchor,
- GtkTextIter *where);
-void gtk_text_buffer_delete_child_anchor (GtkTextBuffer *buffer,
- GtkTextChildAnchor *anchor);
-
-
/* efficiently move insert and selection_bound to same location */
void gtk_text_buffer_place_cursor (GtkTextBuffer *buffer,
const GtkTextIter *where);
diff --git a/gtk/gtktextchild.c b/gtk/gtktextchild.c
index 2baac10330..88c81267e8 100644
--- a/gtk/gtktextchild.c
+++ b/gtk/gtktextchild.c
@@ -49,6 +49,7 @@
#include "gtktextchild.h"
#include "gtktextbtree.h"
+#include "gtktextlayout.h"
static GtkTextLineSegment *
pixbuf_segment_cleanup_func (GtkTextLineSegment *seg,
@@ -137,8 +138,35 @@ child_segment_delete_func (GtkTextLineSegment *seg,
GtkTextLine *line,
gboolean tree_gone)
{
- _gtk_widget_segment_unref (seg);
+ GSList *tmp_list;
+ GSList *copy;
+ gtk_text_btree_unregister_child_anchor (seg->body.child.obj);
+
+ seg->body.child.tree = NULL;
+ seg->body.child.line = NULL;
+
+ /* avoid removing widgets while walking the list */
+ copy = g_slist_copy (seg->body.child.widgets);
+ tmp_list = copy;
+ while (tmp_list != NULL)
+ {
+ GtkWidget *child = tmp_list->data;
+
+ gtk_widget_destroy (child);
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+
+ /* On removal from the widget's parents (GtkTextView),
+ * the widget should have been removed from the anchor.
+ */
+ g_assert (seg->body.child.widgets == NULL);
+
+ g_slist_free (copy);
+
+ _gtk_widget_segment_unref (seg);
+
return 0;
}
@@ -185,7 +213,8 @@ _gtk_widget_segment_new (void)
*/
seg->char_count = 1;
- seg->body.child.ref_count = 1;
+ seg->body.child.obj = g_object_new (GTK_TYPE_TEXT_CHILD_ANCHOR, NULL);
+ seg->body.child.obj->segment = seg;
seg->body.child.widgets = NULL;
seg->body.child.tree = NULL;
seg->body.child.line = NULL;
@@ -197,21 +226,23 @@ void
_gtk_widget_segment_add (GtkTextLineSegment *widget_segment,
GtkWidget *child)
{
- g_assert (widget_segment->type = &gtk_text_child_type);
+ g_return_if_fail (widget_segment->type = &gtk_text_child_type);
+ g_return_if_fail (widget_segment->body.child.tree != NULL);
+ g_object_ref (G_OBJECT (child));
+
widget_segment->body.child.widgets =
g_slist_prepend (widget_segment->body.child.widgets,
child);
-
- g_object_ref (G_OBJECT (child));
}
void
_gtk_widget_segment_remove (GtkTextLineSegment *widget_segment,
GtkWidget *child)
{
- g_assert (widget_segment->type = &gtk_text_child_type);
-
+ g_return_if_fail (widget_segment->type = &gtk_text_child_type);
+ g_return_if_fail (widget_segment->body.child.tree != NULL);
+
widget_segment->body.child.widgets =
g_slist_remove (widget_segment->body.child.widgets,
child);
@@ -224,7 +255,7 @@ _gtk_widget_segment_ref (GtkTextLineSegment *widget_segment)
{
g_assert (widget_segment->type = &gtk_text_child_type);
- widget_segment->body.child.ref_count += 1;
+ g_object_ref (G_OBJECT (widget_segment->body.child.obj));
}
void
@@ -232,55 +263,112 @@ _gtk_widget_segment_unref (GtkTextLineSegment *widget_segment)
{
g_assert (widget_segment->type = &gtk_text_child_type);
- widget_segment->body.child.ref_count -= 1;
-
- if (widget_segment->body.child.ref_count == 0)
- {
- GSList *tmp_list;
+ g_object_unref (G_OBJECT (widget_segment->body.child.obj));
+}
- if (widget_segment->body.child.tree == NULL)
- g_warning ("widget segment destroyed while still in btree");
+GtkTextLayout*
+_gtk_anchored_child_get_layout (GtkWidget *child)
+{
+ return gtk_object_get_data (GTK_OBJECT (child), "gtk-text-child-anchor-layout");
+}
- tmp_list = widget_segment->body.child.widgets;
- while (tmp_list)
- {
- g_object_unref (G_OBJECT (tmp_list->data));
+static void
+_gtk_anchored_child_set_layout (GtkWidget *child,
+ GtkTextLayout *layout)
+{
+ gtk_object_set_data (GTK_OBJECT (child),
+ "gtk-text-child-anchor-layout",
+ layout);
+}
+
+static void gtk_text_child_anchor_init (GtkTextChildAnchor *child_anchor);
+static void gtk_text_child_anchor_class_init (GtkTextChildAnchorClass *klass);
+static void gtk_text_child_anchor_finalize (GObject *obj);
- tmp_list = g_slist_next (tmp_list);
- }
+static gpointer parent_class = NULL;
- g_slist_free (widget_segment->body.child.widgets);
+GType
+gtk_text_child_anchor_get_type (void)
+{
+ static GType object_type = 0;
- g_free (widget_segment);
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (GtkTextChildAnchorClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gtk_text_child_anchor_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GtkTextChildAnchor),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_text_child_anchor_init,
+ };
+
+ object_type = g_type_register_static (G_TYPE_OBJECT,
+ "GtkTextChildAnchor",
+ &object_info, 0);
}
+
+ return object_type;
}
-void
-gtk_text_child_anchor_ref (GtkTextChildAnchor *anchor)
+static void
+gtk_text_child_anchor_init (GtkTextChildAnchor *child_anchor)
{
- GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+ child_anchor->segment = NULL;
+}
- g_return_if_fail (seg->type = &gtk_text_child_type);
- g_return_if_fail (seg->body.child.ref_count > 0);
+static void
+gtk_text_child_anchor_class_init (GtkTextChildAnchorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- _gtk_widget_segment_ref (seg);
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = gtk_text_child_anchor_finalize;
}
-void
-gtk_text_child_anchor_unref (GtkTextChildAnchor *anchor)
+static void
+gtk_text_child_anchor_finalize (GObject *obj)
{
- GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+ GtkTextChildAnchor *anchor;
+ GSList *tmp_list;
+ GtkTextLineSegment *seg;
+
+ anchor = GTK_TEXT_CHILD_ANCHOR (obj);
- g_return_if_fail (seg->type = &gtk_text_child_type);
- g_return_if_fail (seg->body.child.ref_count > 0);
+ seg = anchor->segment;
+
+ if (seg->body.child.tree != NULL)
+ {
+ g_warning ("Someone removed a reference to a GtkTextChildAnchor "
+ "they didn't own; the anchor is still in the text buffer "
+ "and the refcount is 0.");
+ return;
+ }
+
+ tmp_list = seg->body.child.widgets;
+ while (tmp_list)
+ {
+ g_object_unref (G_OBJECT (tmp_list->data));
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+
+ g_slist_free (seg->body.child.widgets);
+
+ g_free (seg);
- _gtk_widget_segment_unref (seg);
+ anchor->segment = NULL;
}
GList*
gtk_text_child_anchor_get_widgets (GtkTextChildAnchor *anchor)
{
- GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+ GtkTextLineSegment *seg = anchor->segment;
GList *list = NULL;
GSList *iter;
@@ -303,12 +391,63 @@ gtk_text_child_anchor_get_widgets (GtkTextChildAnchor *anchor)
gboolean
gtk_text_child_anchor_get_deleted (GtkTextChildAnchor *anchor)
{
- GtkTextLineSegment *seg = (GtkTextLineSegment *) anchor;
+ GtkTextLineSegment *seg = anchor->segment;
g_return_val_if_fail (seg->type = &gtk_text_child_type, TRUE);
return seg->body.child.tree == NULL;
}
+void
+gtk_text_child_anchor_register_child (GtkTextChildAnchor *anchor,
+ GtkWidget *child,
+ GtkTextLayout *layout)
+{
+ g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ _gtk_anchored_child_set_layout (child, layout);
+
+ _gtk_widget_segment_add (anchor->segment, child);
+
+ gtk_text_child_anchor_queue_resize (anchor, layout);
+}
+
+void
+gtk_text_child_anchor_unregister_child (GtkTextChildAnchor *anchor,
+ GtkWidget *child)
+{
+ g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (_gtk_anchored_child_get_layout (child) != NULL);
+
+ gtk_text_child_anchor_queue_resize (anchor,
+ _gtk_anchored_child_get_layout (child));
+
+ _gtk_anchored_child_set_layout (child, NULL);
+
+ _gtk_widget_segment_remove (anchor->segment, child);
+}
+
+void
+gtk_text_child_anchor_queue_resize (GtkTextChildAnchor *anchor,
+ GtkTextLayout *layout)
+{
+ GtkTextIter start;
+ GtkTextIter end;
+ GtkTextLineSegment *seg;
+
+ g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+
+ seg = anchor->segment;
+
+ g_return_if_fail (seg->body.child.tree != NULL);
+
+ gtk_text_buffer_get_iter_at_child_anchor (layout->buffer,
+ &start, anchor);
+ end = start;
+ gtk_text_iter_next_char (&end);
+
+ gtk_text_layout_invalidate (layout, &start, &end);
+}
diff --git a/gtk/gtktextchild.h b/gtk/gtktextchild.h
index 5c8dc591fb..0b10c91ab0 100644
--- a/gtk/gtktextchild.h
+++ b/gtk/gtktextchild.h
@@ -27,7 +27,7 @@
#ifndef GTK_TEXT_CHILD_H
#define GTK_TEXT_CHILD_H
-#include <glib.h>
+#include <glib-object.h>
#ifdef __cplusplus
extern "C" {
@@ -39,10 +39,31 @@ extern "C" {
* views.
*/
-typedef struct _GtkTextChildAnchor GtkTextChildAnchor;
+typedef struct _GtkTextChildAnchor GtkTextChildAnchor;
+typedef struct _GtkTextChildAnchorClass GtkTextChildAnchorClass;
+
+#define GTK_TYPE_TEXT_CHILD_ANCHOR (gtk_text_child_anchor_get_type ())
+#define GTK_TEXT_CHILD_ANCHOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_TEXT_CHILD_ANCHOR, GtkTextChildAnchor))
+#define GTK_TEXT_CHILD_ANCHOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TEXT_CHILD_ANCHOR, GtkTextChildAnchorClass))
+#define GTK_IS_TEXT_CHILD_ANCHOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_TEXT_CHILD_ANCHOR))
+#define GTK_IS_TEXT_CHILD_ANCHOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT_CHILD_ANCHOR))
+#define GTK_TEXT_CHILD_ANCHOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TEXT_CHILD_ANCHOR, GtkTextChildAnchorClass))
+
+struct _GtkTextChildAnchor
+{
+ GObject parent_instance;
+
+ gpointer segment;
+};
+
+struct _GtkTextChildAnchorClass
+{
+ GObjectClass parent_class;
+
+};
+
+GType gtk_text_child_anchor_get_type (void) G_GNUC_CONST;
-void gtk_text_child_anchor_ref (GtkTextChildAnchor *anchor);
-void gtk_text_child_anchor_unref (GtkTextChildAnchor *anchor);
GList* gtk_text_child_anchor_get_widgets (GtkTextChildAnchor *anchor);
gboolean gtk_text_child_anchor_get_deleted (GtkTextChildAnchor *anchor);
diff --git a/gtk/gtktextchildprivate.h b/gtk/gtktextchildprivate.h
index 8c19f07c08..24bb908e4c 100644
--- a/gtk/gtktextchildprivate.h
+++ b/gtk/gtktextchildprivate.h
@@ -69,19 +69,21 @@ typedef struct _GtkTextChildBody GtkTextChildBody;
struct _GtkTextChildBody
{
- guint ref_count;
+ GtkTextChildAnchor *obj;
GSList *widgets;
GtkTextBTree *tree;
GtkTextLine *line;
};
-GtkTextLineSegment *_gtk_widget_segment_new (void);
-void _gtk_widget_segment_add (GtkTextLineSegment *widget_segment,
- GtkWidget *child);
-void _gtk_widget_segment_remove (GtkTextLineSegment *widget_segment,
- GtkWidget *child);
-void _gtk_widget_segment_ref (GtkTextLineSegment *widget_segment);
-void _gtk_widget_segment_unref (GtkTextLineSegment *widget_segment);
+GtkTextLineSegment *_gtk_widget_segment_new (void);
+void _gtk_widget_segment_add (GtkTextLineSegment *widget_segment,
+ GtkWidget *child);
+void _gtk_widget_segment_remove (GtkTextLineSegment *widget_segment,
+ GtkWidget *child);
+void _gtk_widget_segment_ref (GtkTextLineSegment *widget_segment);
+void _gtk_widget_segment_unref (GtkTextLineSegment *widget_segment);
+
+GtkTextLayout* _gtk_anchored_child_get_layout (GtkWidget *child);
#ifdef __cplusplus
}
diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c
index 3a103593ef..10fd95c562 100644
--- a/gtk/gtktextdisplay.c
+++ b/gtk/gtktextdisplay.c
@@ -185,7 +185,7 @@ static void
render_layout_line (GdkDrawable *drawable,
GtkTextRenderState *render_state,
PangoLayoutLine *line,
- GSList **pixbuf_pointer,
+ GSList **shaped_pointer,
int x,
int y,
gboolean selected)
@@ -272,68 +272,99 @@ render_layout_line (GdkDrawable *drawable,
x_off += logical_rect.width;
}
- else /* Pixbuf segment */
+ else /* Pixbuf or widget segment */
{
- GtkTextPixbuf *pixbuf = (*pixbuf_pointer)->data;
- gint width, height;
- GdkRectangle pixbuf_rect, draw_rect;
- GdkBitmap *mask = NULL;
+ GObject *shaped = (*shaped_pointer)->data;
- *pixbuf_pointer = (*pixbuf_pointer)->next;
-
- width = gdk_pixbuf_get_width (pixbuf->pixbuf);
- height = gdk_pixbuf_get_height (pixbuf->pixbuf);
-
- pixbuf_rect.x = x + x_off / PANGO_SCALE;
- pixbuf_rect.y = y - height;
- pixbuf_rect.width = width;
- pixbuf_rect.height = height;
-
- if (gdk_rectangle_intersect (&pixbuf_rect, &render_state->clip_rect,
- &draw_rect))
+ *shaped_pointer = (*shaped_pointer)->next;
+
+ if (GDK_IS_PIXBUF (shaped))
{
- if (gdk_pixbuf_get_has_alpha (pixbuf->pixbuf))
+ gint width, height;
+ GdkRectangle pixbuf_rect, draw_rect;
+ GdkPixbuf *pixbuf;
+
+ pixbuf = GDK_PIXBUF (shaped);
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ pixbuf_rect.x = x + x_off / PANGO_SCALE;
+ pixbuf_rect.y = y - height;
+ pixbuf_rect.width = width;
+ pixbuf_rect.height = height;
+
+ if (gdk_rectangle_intersect (&pixbuf_rect, &render_state->clip_rect,
+ &draw_rect))
{
- mask = gdk_pixmap_new (drawable,
- gdk_pixbuf_get_width (pixbuf->pixbuf),
- gdk_pixbuf_get_height (pixbuf->pixbuf),
- 1);
-
- gdk_pixbuf_render_threshold_alpha (pixbuf->pixbuf, mask,
- 0, 0, 0, 0,
- gdk_pixbuf_get_width (pixbuf->pixbuf),
- gdk_pixbuf_get_height (pixbuf->pixbuf),
- 128);
-
+ GdkBitmap *mask = NULL;
+
+ if (gdk_pixbuf_get_has_alpha (pixbuf))
+ {
+ mask = gdk_pixmap_new (drawable,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf),
+ 1);
+
+ gdk_pixbuf_render_threshold_alpha (pixbuf, mask,
+ 0, 0, 0, 0,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf),
+ 128);
+
+ }
+
+ if (mask)
+ {
+ gdk_gc_set_clip_mask (render_state->fg_gc, mask);
+ gdk_gc_set_clip_origin (render_state->fg_gc,
+ pixbuf_rect.x, pixbuf_rect.y);
+ }
+
+ gdk_pixbuf_render_to_drawable (pixbuf,
+ drawable,
+ render_state->fg_gc,
+ draw_rect.x - pixbuf_rect.x,
+ draw_rect.y - pixbuf_rect.y,
+ draw_rect.x, draw_rect.y,
+ draw_rect.width,
+ draw_rect.height,
+ GDK_RGB_DITHER_NORMAL,
+ 0, 0);
+
+ if (mask)
+ {
+ gdk_gc_set_clip_rectangle (render_state->fg_gc,
+ &render_state->clip_rect);
+ g_object_unref (G_OBJECT (mask));
+ }
}
- if (mask)
+ x_off += width * PANGO_SCALE;
+ }
+ else if (GTK_IS_WIDGET (shaped))
+ {
+ gint width, height;
+ GdkRectangle draw_rect;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (shaped);
+
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+
+ if (GTK_WIDGET_DRAWABLE (widget) &&
+ gtk_widget_intersect (widget,
+ &render_state->clip_rect,
+ &draw_rect))
{
- gdk_gc_set_clip_mask (render_state->fg_gc, mask);
- gdk_gc_set_clip_origin (render_state->fg_gc,
- pixbuf_rect.x, pixbuf_rect.y);
+ gtk_widget_draw (widget, &draw_rect);
}
- gdk_pixbuf_render_to_drawable (pixbuf->pixbuf,
- drawable,
- render_state->fg_gc,
- draw_rect.x - pixbuf_rect.x,
- draw_rect.y - pixbuf_rect.y,
- draw_rect.x, draw_rect.y,
- draw_rect.width,
- draw_rect.height,
- GDK_RGB_DITHER_NORMAL,
- 0, 0);
-
- if (mask)
- {
- gdk_gc_set_clip_rectangle (render_state->fg_gc,
- &render_state->clip_rect);
- g_object_unref (G_OBJECT (mask));
- }
+ x_off += width * PANGO_SCALE;
}
-
- x_off += width * PANGO_SCALE;
+ else
+ g_assert_not_reached (); /* not a pixbuf or widget */
}
}
}
@@ -348,7 +379,7 @@ render_para (GdkDrawable *drawable,
int selection_end_index)
{
PangoRectangle logical_rect;
- GSList *pixbuf_pointer = line_display->pixbufs;
+ GSList *shaped_pointer = line_display->shaped_objects;
GSList *tmp_list;
PangoAlignment align;
PangoLayout *layout = line_display->layout;
@@ -431,15 +462,15 @@ render_para (GdkDrawable *drawable,
TRUE,
x + line_display->left_margin, selection_y,
total_width / PANGO_SCALE, selection_height);
- render_layout_line (drawable, render_state, line, &pixbuf_pointer,
+ render_layout_line (drawable, render_state, line, &shaped_pointer,
x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE,
TRUE);
}
else
{
- GSList *pixbuf_pointer_tmp = pixbuf_pointer;
+ GSList *shaped_pointer_tmp = shaped_pointer;
- render_layout_line (drawable, render_state, line, &pixbuf_pointer,
+ render_layout_line (drawable, render_state, line, &shaped_pointer,
x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE,
FALSE);
@@ -461,7 +492,7 @@ render_para (GdkDrawable *drawable,
logical_rect.width / PANGO_SCALE,
selection_height);
- render_layout_line (drawable, render_state, line, &pixbuf_pointer_tmp,
+ render_layout_line (drawable, render_state, line, &shaped_pointer_tmp,
x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE,
TRUE);
diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c
index 4e5ba2bce8..e57855551a 100644
--- a/gtk/gtktextiter.c
+++ b/gtk/gtktextiter.c
@@ -849,22 +849,52 @@ gtk_text_iter_get_pixbuf (const GtkTextIter *iter)
{
GtkTextRealIter *real;
- g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter != NULL, NULL);
real = gtk_text_iter_make_real (iter);
if (real == NULL)
- return FALSE;
+ return NULL;
check_invariants (iter);
if (real->segment->type != &gtk_text_pixbuf_type)
- return FALSE;
+ return NULL;
else
return real->segment->body.pixbuf.pixbuf;
}
/**
+ * gtk_text_iter_get_child_anchor:
+ * @iter: an iterator
+ *
+ * If the location pointed to by @iter contains a child anchor, the
+ * anchor is returned (with no new reference count added). Otherwise,
+ * NULL is returned.
+ *
+ * Return value: the anchor at @iter
+ **/
+GtkTextChildAnchor*
+gtk_text_iter_get_child_anchor (const GtkTextIter *iter)
+{
+ GtkTextRealIter *real;
+
+ g_return_val_if_fail (iter != NULL, NULL);
+
+ real = gtk_text_iter_make_real (iter);
+
+ if (real == NULL)
+ return NULL;
+
+ check_invariants (iter);
+
+ if (real->segment->type != &gtk_text_child_type)
+ return NULL;
+ else
+ return real->segment->body.child.obj;
+}
+
+/**
* gtk_text_iter_get_marks:
* @iter: an iterator
*
@@ -3734,6 +3764,25 @@ gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
}
void
+gtk_text_btree_get_iter_at_child_anchor (GtkTextBTree *tree,
+ GtkTextIter *iter,
+ GtkTextChildAnchor *anchor)
+{
+ GtkTextLineSegment *seg;
+
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (tree != NULL);
+ g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
+
+ seg = anchor->segment;
+
+ iter_init_from_segment (iter, tree,
+ seg->body.child.line, seg);
+ g_assert (seg->body.child.line == gtk_text_iter_get_text_line (iter));
+ check_invariants (iter);
+}
+
+void
gtk_text_btree_get_last_iter (GtkTextBTree *tree,
GtkTextIter *iter)
{
diff --git a/gtk/gtktextiter.h b/gtk/gtktextiter.h
index 148046cfae..3e649d0b40 100644
--- a/gtk/gtktextiter.h
+++ b/gtk/gtktextiter.h
@@ -28,6 +28,7 @@
#define GTK_TEXT_ITER_H
#include <gtk/gtktexttag.h>
+#include <gtk/gtktextchild.h>
#ifdef __cplusplus
extern "C" {
@@ -100,6 +101,8 @@ gchar *gtk_text_iter_get_visible_text (const GtkTextIter *start,
GdkPixbuf* gtk_text_iter_get_pixbuf (const GtkTextIter *iter);
GSList * gtk_text_iter_get_marks (const GtkTextIter *iter);
+GtkTextChildAnchor* gtk_text_iter_get_child_anchor (const GtkTextIter *iter);
+
/* Return list of tags toggled at this point (toggled_on determines
whether the list is of on-toggles or off-toggles) */
GSList *gtk_text_iter_get_toggled_tags (const GtkTextIter *iter,
diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c
index 2d590af1a4..cba5557b31 100644
--- a/gtk/gtktextlayout.c
+++ b/gtk/gtktextlayout.c
@@ -115,6 +115,7 @@ static PangoAttribute *gtk_text_attr_appearance_new (const GtkTextAppearance *ap
enum {
INVALIDATED,
CHANGED,
+ ALLOCATE_CHILD,
LAST_SIGNAL
};
@@ -188,6 +189,18 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
GTK_TYPE_INT,
GTK_TYPE_INT);
+ signals[ALLOCATE_CHILD] =
+ gtk_signal_new ("allocate_child",
+ GTK_RUN_LAST,
+ GTK_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GtkTextLayoutClass, allocate_child),
+ gtk_marshal_VOID__OBJECT_INT_INT,
+ GTK_TYPE_NONE,
+ 3,
+ GTK_TYPE_OBJECT,
+ GTK_TYPE_INT,
+ GTK_TYPE_INT);
+
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
object_class->destroy = gtk_text_layout_destroy;
@@ -1195,7 +1208,7 @@ add_text_attrs (GtkTextLayout *layout,
static void
add_pixbuf_attrs (GtkTextLayout *layout,
GtkTextLineDisplay *display,
- GtkTextAttributes *style,
+ GtkTextAttributes *style,
GtkTextLineSegment *seg,
PangoAttrList *attrs,
gint start)
@@ -1218,7 +1231,70 @@ add_pixbuf_attrs (GtkTextLayout *layout,
attr->end_index = start + seg->byte_count;
pango_attr_list_insert (attrs, attr);
- display->pixbufs = g_slist_append (display->pixbufs, pixbuf);
+ display->shaped_objects =
+ g_slist_append (display->shaped_objects, pixbuf->pixbuf);
+}
+
+static void
+add_child_attrs (GtkTextLayout *layout,
+ GtkTextLineDisplay *display,
+ GtkTextAttributes *style,
+ GtkTextLineSegment *seg,
+ PangoAttrList *attrs,
+ gint start)
+{
+ PangoAttribute *attr;
+ PangoRectangle logical_rect;
+ GtkTextChildAnchor *anchor;
+ gint width, height;
+ GSList *tmp_list;
+
+ width = 1;
+ height = 1;
+
+ anchor = seg->body.child.obj;
+
+ tmp_list = seg->body.child.widgets;
+ while (tmp_list != NULL)
+ {
+ GtkWidget *child = tmp_list->data;
+
+ if (_gtk_anchored_child_get_layout (child) == layout)
+ {
+ /* Found it */
+ GtkRequisition req;
+
+ gtk_widget_get_child_requisition (child, &req);
+
+ width = req.width;
+ height = req.height;
+
+ display->shaped_objects =
+ g_slist_append (display->shaped_objects, child);
+ break;
+ }
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+
+ if (tmp_list == NULL)
+ {
+ /* No widget at this anchor in this display;
+ * not an error.
+ */
+
+ return;
+ }
+
+ logical_rect.x = 0;
+ logical_rect.y = -height * PANGO_SCALE;
+ logical_rect.width = width * PANGO_SCALE;
+ logical_rect.height = height * PANGO_SCALE;
+
+ attr = pango_attr_shape_new (&logical_rect, &logical_rect);
+ attr->start_index = start;
+ attr->end_index = start + seg->byte_count;
+ pango_attr_list_insert (attrs, attr);
}
static void
@@ -1266,6 +1342,19 @@ add_cursor (GtkTextLayout *layout,
}
}
+static void
+allocate_child_widgets (GtkTextLayout *layout,
+ GtkTextLineDisplay *display)
+{
+
+#if 0
+ gtk_signal_emit (GTK_OBJECT (layout),
+ signals[ALLOCATE_CHILD],
+ child,
+ x, y);
+#endif
+}
+
GtkTextLineDisplay *
gtk_text_layout_get_line_display (GtkTextLayout *layout,
GtkTextLine *line,
@@ -1329,7 +1418,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
{
/* Displayable segments */
if (seg->type == &gtk_text_char_type ||
- seg->type == &gtk_text_pixbuf_type)
+ seg->type == &gtk_text_pixbuf_type ||
+ seg->type == &gtk_text_child_type)
{
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
&iter, line,
@@ -1391,7 +1481,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
add_text_attrs (layout, style, byte_count, attrs,
byte_offset - byte_count, size_only);
}
- else
+ else if (seg->type == &gtk_text_pixbuf_type)
{
add_pixbuf_attrs (layout, display, style,
seg, attrs, byte_offset);
@@ -1399,6 +1489,18 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
seg->byte_count);
byte_offset += seg->byte_count;
}
+ else if (seg->type == &gtk_text_child_type)
+ {
+ add_child_attrs (layout, display, style,
+ seg, attrs, byte_offset);
+ memcpy (text + byte_offset, gtk_text_unknown_char_utf8,
+ seg->byte_count);
+ byte_offset += seg->byte_count;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
}
release_style (layout, style);
@@ -1476,6 +1578,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
layout->one_display_cache = display;
+ allocate_child_widgets (layout, display);
+
return display;
}
@@ -1491,7 +1595,7 @@ gtk_text_layout_free_line_display (GtkTextLayout *layout,
{
g_slist_foreach (display->cursors, (GFunc)g_free, NULL);
g_slist_free (display->cursors);
- g_slist_free (display->pixbufs);
+ g_slist_free (display->shaped_objects);
}
g_free (display);
diff --git a/gtk/gtktextlayout.h b/gtk/gtktextlayout.h
index a4eb5858fb..04ae9c0c77 100644
--- a/gtk/gtktextlayout.h
+++ b/gtk/gtktextlayout.h
@@ -153,7 +153,7 @@ struct _GtkTextLayout
/* Whether we are allowed to wrap right now */
gint wrap_loop_count;
-
+
/* Whether to show the insertion cursor */
guint cursor_visible : 1;
};
@@ -185,7 +185,13 @@ struct _GtkTextLayoutClass
void (*free_line_data) (GtkTextLayout *layout,
GtkTextLine *line,
GtkTextLineData *line_data);
+
+ void (*allocate_child) (GtkTextLayout *layout,
+ GtkWidget *child,
+ gint x,
+ gint y);
};
+
struct _GtkTextAttrAppearance
{
PangoAttribute attr;
@@ -203,8 +209,8 @@ struct _GtkTextLineDisplay
{
PangoLayout *layout;
GSList *cursors;
- GSList *pixbufs;
-
+ GSList *shaped_objects;
+
GtkTextDirection direction;
gint width; /* Width of layout */
@@ -334,9 +340,22 @@ void gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
GtkTextIter *iter,
gint count);
-void gtk_text_layout_spew (GtkTextLayout *layout);
+/* Don't use these. Use gtk_text_view_add_child_at_anchor().
+ * These functions are defined in gtktextchild.c, but here
+ * since they are semi-public and require GtkTextLayout to
+ * be declared.
+ */
+void gtk_text_child_anchor_register_child (GtkTextChildAnchor *anchor,
+ GtkWidget *child,
+ GtkTextLayout *layout);
+void gtk_text_child_anchor_unregister_child (GtkTextChildAnchor *anchor,
+ GtkWidget *child);
+
+void gtk_text_child_anchor_queue_resize (GtkTextChildAnchor *anchor,
+ GtkTextLayout *layout);
+void gtk_text_layout_spew (GtkTextLayout *layout);
#ifdef __cplusplus
}
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 3f6c934fa5..db43d8d36b 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -35,7 +35,6 @@
#include "gtktextview.h"
#include "gtkimmulticontext.h"
#include "gdk/gdkkeysyms.h"
-#include "gtktexttypes.h"
#include <string.h>
#define FOCUS_EDGE_WIDTH 1
@@ -235,7 +234,8 @@ struct _GtkTextViewChild
};
static GtkTextViewChild* text_view_child_new_anchored (GtkWidget *child,
- GtkTextChildAnchor *anchor);
+ GtkTextChildAnchor *anchor,
+ GtkTextLayout *layout);
static GtkTextViewChild* text_view_child_new_window (GtkWidget *child,
GtkTextWindowType type,
gint x,
@@ -244,7 +244,6 @@ static void text_view_child_free (GtkTextViewChild *child
static void text_view_child_realize (GtkTextView *text_view,
GtkTextViewChild *child);
-static void text_view_child_unrealize (GtkTextViewChild *child);
struct _GtkTextWindow
{
@@ -278,7 +277,8 @@ static void text_window_get_allocation (GtkTextWindow *win,
GdkRectangle *rect);
-enum {
+enum
+{
TARGET_STRING,
TARGET_TEXT,
TARGET_COMPOUND_TEXT,
@@ -708,7 +708,7 @@ gtk_text_view_new_with_buffer (GtkTextBuffer *buffer)
}
void
-gtk_text_view_set_buffer (GtkTextView *text_view,
+gtk_text_view_set_buffer (GtkTextView *text_view,
GtkTextBuffer *buffer)
{
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
@@ -719,6 +719,27 @@ gtk_text_view_set_buffer (GtkTextView *text_view,
if (text_view->buffer != NULL)
{
+ /* Destroy all anchored children */
+ GSList *tmp_list;
+ GSList *copy;
+
+ copy = g_slist_copy (text_view->children);
+ tmp_list = copy;
+ while (tmp_list != NULL)
+ {
+ GtkTextViewChild *vc = tmp_list->data;
+
+ if (vc->anchor)
+ {
+ gtk_widget_destroy (vc->widget);
+ /* vc may now be invalid! */
+ }
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+
+ g_slist_free (copy);
+
gtk_signal_disconnect_by_func (GTK_OBJECT (text_view->buffer),
gtk_text_view_mark_set_handler, text_view);
gtk_object_unref (GTK_OBJECT (text_view->buffer));
@@ -1251,7 +1272,8 @@ gtk_text_view_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkTextView *text_view;
-
+ GSList *tmp_list;
+
text_view = GTK_TEXT_VIEW (widget);
requisition->width = text_view->text_window->requisition.width + FOCUS_EDGE_WIDTH * 2;
@@ -1268,6 +1290,69 @@ gtk_text_view_size_request (GtkWidget *widget,
if (text_view->bottom_window)
requisition->height += text_view->bottom_window->requisition.height;
+
+ tmp_list = text_view->children;
+ while (tmp_list != NULL)
+ {
+ GtkTextViewChild *child = tmp_list->data;
+
+ if (child->anchor)
+ {
+ GtkRequisition child_req;
+ GtkRequisition old_req;
+
+ old_req = child->widget->requisition;
+
+ gtk_widget_size_request (child->widget, &child_req);
+
+ if (text_view->layout &&
+ (old_req.width != child_req.width ||
+ old_req.height != child_req.height))
+ gtk_text_child_anchor_queue_resize (child->anchor,
+ text_view->layout);
+ }
+ else
+ {
+
+ }
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+}
+
+static void
+gtk_text_view_allocate_children (GtkTextView *text_view)
+{
+ GSList *tmp_list;
+
+ return;
+
+ tmp_list = text_view->children;
+ while (tmp_list != NULL)
+ {
+ GtkTextViewChild *child = tmp_list->data;
+
+ if (child->anchor)
+ {
+ /* We need to force-validate the regions containing
+ * children.
+ */
+ GtkTextIter child_loc;
+ gtk_text_buffer_get_iter_at_child_anchor (text_view->buffer,
+ &child_loc,
+ child->anchor);
+
+ gtk_text_layout_validate_yrange (text_view->layout,
+ &child_loc,
+ 0, 1);
+ }
+ else
+ {
+
+ }
+
+ tmp_list = g_slist_next (tmp_list);
+ }
}
static void
@@ -1285,7 +1370,8 @@ gtk_text_view_size_allocate (GtkWidget *widget,
GdkRectangle right_rect;
GdkRectangle top_rect;
GdkRectangle bottom_rect;
-
+ GSList *tmp_list;
+
text_view = GTK_TEXT_VIEW (widget);
widget->allocation = *allocation;
@@ -1383,6 +1469,8 @@ gtk_text_view_size_allocate (GtkWidget *widget,
gtk_text_layout_set_screen_width (text_view->layout,
SCREEN_WIDTH (text_view));
+ gtk_text_view_allocate_children (text_view);
+
gtk_text_view_validate_onscreen (text_view);
gtk_text_view_scroll_calc_now (text_view);
@@ -1603,7 +1691,7 @@ static void
gtk_text_view_unrealize (GtkWidget *widget)
{
GtkTextView *text_view;
-
+
text_view = GTK_TEXT_VIEW (widget);
if (text_view->first_validate_idle)
@@ -1617,7 +1705,7 @@ gtk_text_view_unrealize (GtkWidget *widget)
g_source_remove (text_view->incremental_validate_idle);
text_view->incremental_validate_idle = 0;
}
-
+
text_window_unrealize (text_view->text_window);
if (text_view->left_window)
@@ -2242,7 +2330,7 @@ gtk_text_view_remove (GtkContainer *container,
}
g_assert (iter != NULL); /* be sure we had the child in the list */
-
+
text_view->children = g_slist_remove (text_view->children, vc);
gtk_widget_unparent (vc->widget);
@@ -4187,22 +4275,25 @@ gtk_text_view_set_text_window_size (GtkTextView *text_view,
static GtkTextViewChild*
text_view_child_new_anchored (GtkWidget *child,
- GtkTextChildAnchor *anchor)
+ GtkTextChildAnchor *anchor,
+ GtkTextLayout *layout)
{
GtkTextViewChild *vc;
-
+
vc = g_new (GtkTextViewChild, 1);
vc->widget = child;
vc->anchor = anchor;
g_object_ref (G_OBJECT (vc->widget));
- gtk_text_child_anchor_ref (vc->anchor);
+ g_object_ref (G_OBJECT (vc->anchor));
gtk_object_set_data (GTK_OBJECT (child),
"gtk-text-view-child",
vc);
+ gtk_text_child_anchor_register_child (anchor, child, layout);
+
return vc;
}
@@ -4235,9 +4326,15 @@ text_view_child_free (GtkTextViewChild *child)
gtk_object_remove_data (GTK_OBJECT (child->widget),
"gtk-text-view-child");
- g_object_unref (G_OBJECT (child->widget));
- gtk_text_child_anchor_unref (child->anchor);
+ if (child->anchor)
+ {
+ gtk_text_child_anchor_unregister_child (child->anchor,
+ child->widget);
+ g_object_unref (G_OBJECT (child->anchor));
+ }
+ g_object_unref (G_OBJECT (child->widget));
+
g_free (child);
}
@@ -4260,12 +4357,6 @@ text_view_child_realize (GtkTextView *text_view,
}
static void
-text_view_child_unrealize (GtkTextViewChild *vc)
-{
- gtk_widget_unrealize (vc->widget);
-}
-
-static void
add_child (GtkTextView *text_view,
GtkTextViewChild *vc)
{
@@ -4295,10 +4386,13 @@ gtk_text_view_add_child_at_anchor (GtkTextView *text_view,
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (anchor != NULL);
+ g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
g_return_if_fail (child->parent == NULL);
- vc = text_view_child_new_anchored (child, anchor);
+ gtk_text_view_ensure_layout (text_view);
+
+ vc = text_view_child_new_anchored (child, anchor,
+ text_view->layout);
add_child (text_view, vc);
}