1 /* GTK - The GIMP Toolkit
2 * gtktextbuffer.c Copyright (C) 2000 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
34 #include "gtkclipboard.h"
35 #include "gtkinvisible.h"
36 #include "gtkmarshalers.h"
37 #include "gtktextbuffer.h"
38 #include "gtktextbtree.h"
39 #include "gtktextiterprivate.h"
40 #include "gtkprivate.h"
44 typedef struct _ClipboardRequest ClipboardRequest;
46 struct _ClipboardRequest
48 GtkTextBuffer *buffer;
50 gboolean default_editable;
51 gboolean is_clipboard;
52 gboolean replace_selection;
83 TARGET_TEXT_BUFFER_CONTENTS
86 static void gtk_text_buffer_init (GtkTextBuffer *tkxt_buffer);
87 static void gtk_text_buffer_class_init (GtkTextBufferClass *klass);
88 static void gtk_text_buffer_finalize (GObject *object);
91 static void gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
95 static void gtk_text_buffer_real_insert_pixbuf (GtkTextBuffer *buffer,
98 static void gtk_text_buffer_real_insert_anchor (GtkTextBuffer *buffer,
100 GtkTextChildAnchor *anchor);
101 static void gtk_text_buffer_real_delete_range (GtkTextBuffer *buffer,
104 static void gtk_text_buffer_real_apply_tag (GtkTextBuffer *buffer,
106 const GtkTextIter *start_char,
107 const GtkTextIter *end_char);
108 static void gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
110 const GtkTextIter *start_char,
111 const GtkTextIter *end_char);
112 static void gtk_text_buffer_real_changed (GtkTextBuffer *buffer);
114 static GtkTextBTree* get_btree (GtkTextBuffer *buffer);
115 static void free_log_attr_cache (GtkTextLogAttrCache *cache);
117 static void remove_all_selection_clipboards (GtkTextBuffer *buffer);
118 static void update_selection_clipboards (GtkTextBuffer *buffer);
120 static GtkTextBuffer *create_clipboard_contents_buffer (GtkTextBuffer *buffer);
122 static GObjectClass *parent_class = NULL;
123 static guint signals[LAST_SIGNAL] = { 0 };
125 static void gtk_text_buffer_set_property (GObject *object,
129 static void gtk_text_buffer_get_property (GObject *object,
136 gtk_text_buffer_get_type (void)
138 static GType our_type = 0;
142 static const GTypeInfo our_info =
144 sizeof (GtkTextBufferClass),
145 (GBaseInitFunc) NULL,
146 (GBaseFinalizeFunc) NULL,
147 (GClassInitFunc) gtk_text_buffer_class_init,
148 NULL, /* class_finalize */
149 NULL, /* class_data */
150 sizeof (GtkTextBuffer),
152 (GInstanceInitFunc) gtk_text_buffer_init
155 our_type = g_type_register_static (G_TYPE_OBJECT, "GtkTextBuffer",
163 gtk_text_buffer_class_init (GtkTextBufferClass *klass)
165 GObjectClass *object_class = G_OBJECT_CLASS (klass);
167 parent_class = g_type_class_peek_parent (klass);
169 object_class->finalize = gtk_text_buffer_finalize;
170 object_class->set_property = gtk_text_buffer_set_property;
171 object_class->get_property = gtk_text_buffer_get_property;
173 klass->insert_text = gtk_text_buffer_real_insert_text;
174 klass->insert_pixbuf = gtk_text_buffer_real_insert_pixbuf;
175 klass->insert_child_anchor = gtk_text_buffer_real_insert_anchor;
176 klass->delete_range = gtk_text_buffer_real_delete_range;
177 klass->apply_tag = gtk_text_buffer_real_apply_tag;
178 klass->remove_tag = gtk_text_buffer_real_remove_tag;
179 klass->changed = gtk_text_buffer_real_changed;
182 g_object_class_install_property (object_class,
184 g_param_spec_object ("tag-table",
186 P_("Text Tag Table"),
187 GTK_TYPE_TEXT_TAG_TABLE,
188 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
190 signals[INSERT_TEXT] =
191 g_signal_new ("insert_text",
192 G_OBJECT_CLASS_TYPE (object_class),
194 G_STRUCT_OFFSET (GtkTextBufferClass, insert_text),
196 _gtk_marshal_VOID__BOXED_STRING_INT,
199 GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
200 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
203 signals[INSERT_PIXBUF] =
204 g_signal_new ("insert_pixbuf",
205 G_OBJECT_CLASS_TYPE (object_class),
207 G_STRUCT_OFFSET (GtkTextBufferClass, insert_pixbuf),
209 _gtk_marshal_VOID__BOXED_OBJECT,
212 GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
215 signals[INSERT_CHILD_ANCHOR] =
216 g_signal_new ("insert_child_anchor",
217 G_OBJECT_CLASS_TYPE (object_class),
219 G_STRUCT_OFFSET (GtkTextBufferClass, insert_child_anchor),
221 _gtk_marshal_VOID__BOXED_OBJECT,
224 GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
225 GTK_TYPE_TEXT_CHILD_ANCHOR);
228 * GtkTextBuffer::delete_range:
229 * @buffer: the object which received the signal.
230 * @start: the start of the range to be deleted
231 * @end: the end of the range to be deleted
233 * The ::delete_range signal is emitted to delete a range from
234 * a #GtkTextBuffer. Note that your handler must not invalidate the
235 * @start and @end iters (or has to revalidate them), if it runs before the
236 * default handler. There is no need to keep the iters valid in handlers
237 * which run after the default handler (see g_signal_connect_after()), but
238 * those don't have access to the deleted text.
240 signals[DELETE_RANGE] =
241 g_signal_new ("delete_range",
242 G_OBJECT_CLASS_TYPE (object_class),
244 G_STRUCT_OFFSET (GtkTextBufferClass, delete_range),
246 _gtk_marshal_VOID__BOXED_BOXED,
249 GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
250 GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE);
253 g_signal_new ("changed",
254 G_OBJECT_CLASS_TYPE (object_class),
256 G_STRUCT_OFFSET (GtkTextBufferClass, changed),
258 _gtk_marshal_VOID__VOID,
262 signals[MODIFIED_CHANGED] =
263 g_signal_new ("modified_changed",
264 G_OBJECT_CLASS_TYPE (object_class),
266 G_STRUCT_OFFSET (GtkTextBufferClass, modified_changed),
268 _gtk_marshal_VOID__VOID,
273 g_signal_new ("mark_set",
274 G_OBJECT_CLASS_TYPE (object_class),
276 G_STRUCT_OFFSET (GtkTextBufferClass, mark_set),
278 _gtk_marshal_VOID__BOXED_OBJECT,
284 signals[MARK_DELETED] =
285 g_signal_new ("mark_deleted",
286 G_OBJECT_CLASS_TYPE (object_class),
288 G_STRUCT_OFFSET (GtkTextBufferClass, mark_deleted),
290 _gtk_marshal_VOID__OBJECT,
296 g_signal_new ("apply_tag",
297 G_OBJECT_CLASS_TYPE (object_class),
299 G_STRUCT_OFFSET (GtkTextBufferClass, apply_tag),
301 _gtk_marshal_VOID__OBJECT_BOXED_BOXED,
308 signals[REMOVE_TAG] =
309 g_signal_new ("remove_tag",
310 G_OBJECT_CLASS_TYPE (object_class),
312 G_STRUCT_OFFSET (GtkTextBufferClass, remove_tag),
314 _gtk_marshal_VOID__OBJECT_BOXED_BOXED,
321 signals[BEGIN_USER_ACTION] =
322 g_signal_new ("begin_user_action",
323 G_OBJECT_CLASS_TYPE (object_class),
325 G_STRUCT_OFFSET (GtkTextBufferClass, begin_user_action),
327 _gtk_marshal_VOID__VOID,
331 signals[END_USER_ACTION] =
332 g_signal_new ("end_user_action",
333 G_OBJECT_CLASS_TYPE (object_class),
335 G_STRUCT_OFFSET (GtkTextBufferClass, end_user_action),
337 _gtk_marshal_VOID__VOID,
343 gtk_text_buffer_init (GtkTextBuffer *buffer)
345 buffer->clipboard_contents_buffers = NULL;
346 buffer->tag_table = NULL;
350 set_table (GtkTextBuffer *buffer, GtkTextTagTable *table)
352 g_return_if_fail (buffer->tag_table == NULL);
356 buffer->tag_table = table;
357 g_object_ref (buffer->tag_table);
358 _gtk_text_tag_table_add_buffer (table, buffer);
362 static GtkTextTagTable*
363 get_table (GtkTextBuffer *buffer)
365 if (buffer->tag_table == NULL)
367 buffer->tag_table = gtk_text_tag_table_new ();
368 _gtk_text_tag_table_add_buffer (buffer->tag_table, buffer);
371 return buffer->tag_table;
375 gtk_text_buffer_set_property (GObject *object,
380 GtkTextBuffer *text_buffer;
382 text_buffer = GTK_TEXT_BUFFER (object);
387 set_table (text_buffer, g_value_get_object (value));
396 gtk_text_buffer_get_property (GObject *object,
401 GtkTextBuffer *text_buffer;
403 text_buffer = GTK_TEXT_BUFFER (object);
408 g_value_set_object (value, get_table (text_buffer));
417 * gtk_text_buffer_new:
418 * @table: a tag table, or NULL to create a new one
420 * Creates a new text buffer.
422 * Return value: a new text buffer
425 gtk_text_buffer_new (GtkTextTagTable *table)
427 GtkTextBuffer *text_buffer;
429 text_buffer = g_object_new (GTK_TYPE_TEXT_BUFFER, "tag-table", table, NULL);
435 gtk_text_buffer_finalize (GObject *object)
437 GtkTextBuffer *buffer;
439 buffer = GTK_TEXT_BUFFER (object);
441 remove_all_selection_clipboards (buffer);
443 if (buffer->tag_table)
445 _gtk_text_tag_table_remove_buffer (buffer->tag_table, buffer);
446 g_object_unref (buffer->tag_table);
447 buffer->tag_table = NULL;
452 _gtk_text_btree_unref (buffer->btree);
453 buffer->btree = NULL;
456 if (buffer->log_attr_cache)
457 free_log_attr_cache (buffer->log_attr_cache);
459 buffer->log_attr_cache = NULL;
461 G_OBJECT_CLASS (parent_class)->finalize (object);
465 get_btree (GtkTextBuffer *buffer)
467 if (buffer->btree == NULL)
468 buffer->btree = _gtk_text_btree_new (gtk_text_buffer_get_tag_table (buffer),
471 return buffer->btree;
475 _gtk_text_buffer_get_btree (GtkTextBuffer *buffer)
477 return get_btree (buffer);
481 * gtk_text_buffer_get_tag_table:
482 * @buffer: a #GtkTextBuffer
484 * Get the #GtkTextTagTable associated with this buffer.
486 * Return value: the buffer's tag table
489 gtk_text_buffer_get_tag_table (GtkTextBuffer *buffer)
491 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
493 return get_table (buffer);
497 * gtk_text_buffer_set_text:
498 * @buffer: a #GtkTextBuffer
499 * @text: UTF-8 text to insert
500 * @len: length of @text in bytes
502 * Deletes current contents of @buffer, and inserts @text instead. If
503 * @len is -1, @text must be nul-terminated. @text must be valid UTF-8.
506 gtk_text_buffer_set_text (GtkTextBuffer *buffer,
510 GtkTextIter start, end;
512 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
513 g_return_if_fail (text != NULL);
518 gtk_text_buffer_get_bounds (buffer, &start, &end);
520 gtk_text_buffer_delete (buffer, &start, &end);
524 gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
525 gtk_text_buffer_insert (buffer, &start, text, len);
534 gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
539 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
540 g_return_if_fail (iter != NULL);
542 _gtk_text_btree_insert (iter, text, len);
544 g_signal_emit (buffer, signals[CHANGED], 0);
548 gtk_text_buffer_emit_insert (GtkTextBuffer *buffer,
553 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
554 g_return_if_fail (iter != NULL);
555 g_return_if_fail (text != NULL);
560 g_return_if_fail (g_utf8_validate (text, len, NULL));
564 g_signal_emit (buffer, signals[INSERT_TEXT], 0,
570 * gtk_text_buffer_insert:
571 * @buffer: a #GtkTextBuffer
572 * @iter: a position in the buffer
573 * @text: UTF-8 format text to insert
574 * @len: length of text in bytes, or -1
576 * Inserts @len bytes of @text at position @iter. If @len is -1,
577 * @text must be nul-terminated and will be inserted in its
578 * entirety. Emits the "insert_text" signal; insertion actually occurs
579 * in the default handler for the signal. @iter is invalidated when
580 * insertion occurs (because the buffer contents change), but the
581 * default signal handler revalidates it to point to the end of the
586 gtk_text_buffer_insert (GtkTextBuffer *buffer,
591 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
592 g_return_if_fail (iter != NULL);
593 g_return_if_fail (text != NULL);
594 g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
596 gtk_text_buffer_emit_insert (buffer, iter, text, len);
600 * gtk_text_buffer_insert_at_cursor:
601 * @buffer: a #GtkTextBuffer
602 * @text: some text in UTF-8 format
603 * @len: length of text, in bytes
605 * Simply calls gtk_text_buffer_insert (), using the current
606 * cursor position as the insertion point.
609 gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
615 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
616 g_return_if_fail (text != NULL);
618 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
619 gtk_text_buffer_get_mark (buffer,
622 gtk_text_buffer_insert (buffer, &iter, text, len);
626 * gtk_text_buffer_insert_interactive:
627 * @buffer: a #GtkTextBuffer
628 * @iter: a position in @buffer
629 * @text: some UTF-8 text
630 * @len: length of text in bytes, or -1
631 * @default_editable: default editability of buffer
633 * Like gtk_text_buffer_insert(), but the insertion will not occur if
634 * @iter is at a non-editable location in the buffer. Usually you
635 * want to prevent insertions at ineditable locations if the insertion
636 * results from a user action (is interactive).
638 * @default_editable indicates the editability of text that doesn't
639 * have a tag affecting editability applied to it. Typically the
640 * result of gtk_text_view_get_editable() is appropriate here.
642 * Return value: whether text was actually inserted
645 gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer,
649 gboolean default_editable)
651 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
652 g_return_val_if_fail (text != NULL, FALSE);
653 g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == buffer, FALSE);
655 if (gtk_text_iter_can_insert (iter, default_editable))
657 gtk_text_buffer_begin_user_action (buffer);
658 gtk_text_buffer_emit_insert (buffer, iter, text, len);
659 gtk_text_buffer_end_user_action (buffer);
667 * gtk_text_buffer_insert_interactive_at_cursor:
668 * @buffer: a #GtkTextBuffer
669 * @text: text in UTF-8 format
670 * @len: length of text in bytes, or -1
671 * @default_editable: default editability of buffer
673 * Calls gtk_text_buffer_insert_interactive () at the cursor
676 * @default_editable indicates the editability of text that doesn't
677 * have a tag affecting editability applied to it. Typically the
678 * result of gtk_text_view_get_editable() is appropriate here.
680 * Return value: whether text was actually inserted
683 gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer,
686 gboolean default_editable)
690 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
691 g_return_val_if_fail (text != NULL, FALSE);
693 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
694 gtk_text_buffer_get_mark (buffer,
697 return gtk_text_buffer_insert_interactive (buffer, &iter, text, len,
702 possibly_not_text (gunichar ch,
705 return ch == GTK_TEXT_UNKNOWN_CHAR;
709 insert_text_range (GtkTextBuffer *buffer,
711 const GtkTextIter *orig_start,
712 const GtkTextIter *orig_end,
713 gboolean interactive)
717 text = gtk_text_iter_get_text (orig_start, orig_end);
719 gtk_text_buffer_emit_insert (buffer, iter, text, -1);
724 typedef struct _Range Range;
727 GtkTextBuffer *buffer;
728 GtkTextMark *start_mark;
729 GtkTextMark *end_mark;
730 GtkTextMark *whole_end_mark;
731 GtkTextIter *range_start;
732 GtkTextIter *range_end;
733 GtkTextIter *whole_end;
737 save_range (GtkTextIter *range_start,
738 GtkTextIter *range_end,
739 GtkTextIter *whole_end)
743 r = g_new (Range, 1);
745 r->buffer = gtk_text_iter_get_buffer (range_start);
746 g_object_ref (r->buffer);
749 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
754 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
760 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
765 r->range_start = range_start;
766 r->range_end = range_end;
767 r->whole_end = whole_end;
773 restore_range (Range *r)
775 gtk_text_buffer_get_iter_at_mark (r->buffer,
779 gtk_text_buffer_get_iter_at_mark (r->buffer,
783 gtk_text_buffer_get_iter_at_mark (r->buffer,
787 gtk_text_buffer_delete_mark (r->buffer, r->start_mark);
788 gtk_text_buffer_delete_mark (r->buffer, r->end_mark);
789 gtk_text_buffer_delete_mark (r->buffer, r->whole_end_mark);
791 /* Due to the gravities on the marks, the ordering could have
792 * gotten mangled; we switch to an empty range in that
796 if (gtk_text_iter_compare (r->range_start, r->range_end) > 0)
797 *r->range_start = *r->range_end;
799 if (gtk_text_iter_compare (r->range_end, r->whole_end) > 0)
800 *r->range_end = *r->whole_end;
802 g_object_unref (r->buffer);
807 insert_range_untagged (GtkTextBuffer *buffer,
809 const GtkTextIter *orig_start,
810 const GtkTextIter *orig_end,
811 gboolean interactive)
813 GtkTextIter range_start;
814 GtkTextIter range_end;
815 GtkTextIter start, end;
816 GtkTextBuffer *src_buffer;
819 if (gtk_text_iter_equal (orig_start, orig_end))
825 src_buffer = gtk_text_iter_get_buffer (&start);
832 if (gtk_text_iter_equal (&range_start, &range_end))
834 /* Figure out how to move forward */
836 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
838 if (gtk_text_iter_equal (&range_end, &end))
840 /* nothing left to do */
843 else if (gtk_text_iter_get_char (&range_end) == GTK_TEXT_UNKNOWN_CHAR)
845 GdkPixbuf *pixbuf = NULL;
846 GtkTextChildAnchor *anchor = NULL;
847 pixbuf = gtk_text_iter_get_pixbuf (&range_end);
848 anchor = gtk_text_iter_get_child_anchor (&range_end);
852 r = save_range (&range_start,
856 gtk_text_buffer_insert_pixbuf (buffer,
863 gtk_text_iter_forward_char (&range_end);
865 range_start = range_end;
869 /* Just skip anchors */
871 gtk_text_iter_forward_char (&range_end);
872 range_start = range_end;
876 /* The GTK_TEXT_UNKNOWN_CHAR was in a text segment, so
879 gtk_text_iter_forward_find_char (&range_end,
880 possibly_not_text, NULL,
883 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
888 /* Text segment starts here, so forward search to
889 * find its possible endpoint
891 gtk_text_iter_forward_find_char (&range_end,
892 possibly_not_text, NULL,
895 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
900 r = save_range (&range_start,
904 insert_text_range (buffer,
913 range_start = range_end;
919 insert_range_not_inside_self (GtkTextBuffer *buffer,
921 const GtkTextIter *orig_start,
922 const GtkTextIter *orig_end,
923 gboolean interactive)
925 /* Find each range of uniformly-tagged text, insert it,
926 * then apply the tags.
928 GtkTextIter start = *orig_start;
929 GtkTextIter end = *orig_end;
930 GtkTextIter range_start;
931 GtkTextIter range_end;
932 GtkTextBuffer *src_buffer;
934 if (gtk_text_iter_equal (orig_start, orig_end))
937 src_buffer = gtk_text_iter_get_buffer (orig_start);
939 gtk_text_iter_order (&start, &end);
947 GtkTextIter start_iter;
952 if (gtk_text_iter_equal (&range_start, &end))
953 break; /* All done */
955 g_assert (gtk_text_iter_compare (&range_start, &end) < 0);
957 gtk_text_iter_forward_to_tag_toggle (&range_end, NULL);
959 g_assert (!gtk_text_iter_equal (&range_start, &range_end));
961 /* Clamp to the end iterator */
962 if (gtk_text_iter_compare (&range_end, &end) > 0)
965 /* We have a range with unique tags; insert it, and
968 start_offset = gtk_text_iter_get_offset (iter);
970 r = save_range (&range_start, &range_end, &end);
972 insert_range_untagged (buffer, iter, &range_start, &range_end, interactive);
977 gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_offset);
979 tags = gtk_text_iter_get_tags (&range_start);
981 while (tmp_list != NULL)
983 gtk_text_buffer_apply_tag (buffer,
988 tmp_list = g_slist_next (tmp_list);
992 range_start = range_end;
997 gtk_text_buffer_real_insert_range (GtkTextBuffer *buffer,
999 const GtkTextIter *orig_start,
1000 const GtkTextIter *orig_end,
1001 gboolean interactive)
1003 GtkTextBuffer *src_buffer;
1005 /* Find each range of uniformly-tagged text, insert it,
1006 * then apply the tags.
1008 if (gtk_text_iter_equal (orig_start, orig_end))
1012 gtk_text_buffer_begin_user_action (buffer);
1014 src_buffer = gtk_text_iter_get_buffer (orig_start);
1016 if (gtk_text_iter_get_buffer (iter) != src_buffer ||
1017 !gtk_text_iter_in_range (iter, orig_start, orig_end))
1019 insert_range_not_inside_self (buffer, iter, orig_start, orig_end, interactive);
1023 /* If you insert a range into itself, it could loop infinitely
1024 * because the region being copied keeps growing as we insert. So
1025 * we have to separately copy the range before and after
1026 * the insertion point.
1028 GtkTextIter start = *orig_start;
1029 GtkTextIter end = *orig_end;
1030 GtkTextIter range_start;
1031 GtkTextIter range_end;
1035 gtk_text_iter_order (&start, &end);
1037 range_start = start;
1039 first_half = save_range (&range_start, &range_end, &end);
1041 range_start = *iter;
1043 second_half = save_range (&range_start, &range_end, &end);
1045 restore_range (first_half);
1046 insert_range_not_inside_self (buffer, iter, &range_start, &range_end, interactive);
1048 restore_range (second_half);
1049 insert_range_not_inside_self (buffer, iter, &range_start, &range_end, interactive);
1053 gtk_text_buffer_end_user_action (buffer);
1057 * gtk_text_buffer_insert_range:
1058 * @buffer: a #GtkTextBuffer
1059 * @iter: a position in @buffer
1060 * @start: a position in a #GtkTextBuffer
1061 * @end: another position in the same buffer as @start
1063 * Copies text, tags, and pixbufs between @start and @end (the order
1064 * of @start and @end doesn't matter) and inserts the copy at @iter.
1065 * Used instead of simply getting/inserting text because it preserves
1066 * images and tags. If @start and @end are in a different buffer from
1067 * @buffer, the two buffers must share the same tag table.
1069 * Implemented via emissions of the insert_text and apply_tag signals,
1073 gtk_text_buffer_insert_range (GtkTextBuffer *buffer,
1075 const GtkTextIter *start,
1076 const GtkTextIter *end)
1078 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1079 g_return_if_fail (iter != NULL);
1080 g_return_if_fail (start != NULL);
1081 g_return_if_fail (end != NULL);
1082 g_return_if_fail (gtk_text_iter_get_buffer (start) ==
1083 gtk_text_iter_get_buffer (end));
1084 g_return_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
1086 g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1088 gtk_text_buffer_real_insert_range (buffer, iter, start, end, FALSE);
1092 * gtk_text_buffer_insert_range_interactive:
1093 * @buffer: a #GtkTextBuffer
1094 * @iter: a position in @buffer
1095 * @start: a position in a #GtkTextBuffer
1096 * @end: another position in the same buffer as @start
1097 * @default_editable: default editability of the buffer
1099 * Same as gtk_text_buffer_insert_range(), but does nothing if the
1100 * insertion point isn't editable. The @default_editable parameter
1101 * indicates whether the text is editable at @iter if no tags
1102 * enclosing @iter affect editability. Typically the result of
1103 * gtk_text_view_get_editable() is appropriate here.
1105 * Returns: whether an insertion was possible at @iter
1108 gtk_text_buffer_insert_range_interactive (GtkTextBuffer *buffer,
1110 const GtkTextIter *start,
1111 const GtkTextIter *end,
1112 gboolean default_editable)
1114 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1115 g_return_val_if_fail (iter != NULL, FALSE);
1116 g_return_val_if_fail (start != NULL, FALSE);
1117 g_return_val_if_fail (end != NULL, FALSE);
1118 g_return_val_if_fail (gtk_text_iter_get_buffer (start) ==
1119 gtk_text_iter_get_buffer (end), FALSE);
1120 g_return_val_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
1121 buffer->tag_table, FALSE);
1124 if (gtk_text_iter_can_insert (iter, default_editable))
1126 gtk_text_buffer_real_insert_range (buffer, iter, start, end, TRUE);
1134 * gtk_text_buffer_insert_with_tags:
1135 * @buffer: a #GtkTextBuffer
1136 * @iter: an iterator in @buffer
1138 * @len: length of @text, or -1
1139 * @first_tag: first tag to apply to @text
1140 * @Varargs: NULL-terminated list of tags to apply
1142 * Inserts @text into @buffer at @iter, applying the list of tags to
1143 * the newly-inserted text. The last tag specified must be NULL to
1144 * terminate the list. Equivalent to calling gtk_text_buffer_insert (),
1145 * then gtk_text_buffer_apply_tag () on the inserted text;
1146 * gtk_text_buffer_insert_with_tags () is just a convenience function.
1149 gtk_text_buffer_insert_with_tags (GtkTextBuffer *buffer,
1153 GtkTextTag *first_tag,
1161 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1162 g_return_if_fail (iter != NULL);
1163 g_return_if_fail (text != NULL);
1164 g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1166 start_offset = gtk_text_iter_get_offset (iter);
1168 gtk_text_buffer_insert (buffer, iter, text, len);
1170 if (first_tag == NULL)
1173 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
1175 va_start (args, first_tag);
1179 gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
1181 tag = va_arg (args, GtkTextTag*);
1188 * gtk_text_buffer_insert_with_tags_by_name:
1189 * @buffer: a #GtkTextBuffer
1190 * @iter: position in @buffer
1192 * @len: length of @text, or -1
1193 * @first_tag_name: name of a tag to apply to @text
1194 * @Varargs: more tag names
1196 * Same as gtk_text_buffer_insert_with_tags (), but allows you
1197 * to pass in tag names instead of tag objects.
1200 gtk_text_buffer_insert_with_tags_by_name (GtkTextBuffer *buffer,
1204 const gchar *first_tag_name,
1210 const gchar *tag_name;
1212 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1213 g_return_if_fail (iter != NULL);
1214 g_return_if_fail (text != NULL);
1215 g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1217 start_offset = gtk_text_iter_get_offset (iter);
1219 gtk_text_buffer_insert (buffer, iter, text, len);
1221 if (first_tag_name == NULL)
1224 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
1226 va_start (args, first_tag_name);
1227 tag_name = first_tag_name;
1232 tag = gtk_text_tag_table_lookup (buffer->tag_table,
1237 g_warning ("%s: no tag with name '%s'!", G_STRLOC, tag_name);
1241 gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
1243 tag_name = va_arg (args, const gchar*);
1255 gtk_text_buffer_real_delete_range (GtkTextBuffer *buffer,
1259 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1260 g_return_if_fail (start != NULL);
1261 g_return_if_fail (end != NULL);
1263 _gtk_text_btree_delete (start, end);
1265 /* may have deleted the selection... */
1266 update_selection_clipboards (buffer);
1268 g_signal_emit (buffer, signals[CHANGED], 0);
1272 gtk_text_buffer_emit_delete (GtkTextBuffer *buffer,
1276 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1277 g_return_if_fail (start != NULL);
1278 g_return_if_fail (end != NULL);
1280 if (gtk_text_iter_equal (start, end))
1283 gtk_text_iter_order (start, end);
1285 g_signal_emit (buffer,
1286 signals[DELETE_RANGE],
1292 * gtk_text_buffer_delete:
1293 * @buffer: a #GtkTextBuffer
1294 * @start: a position in @buffer
1295 * @end: another position in @buffer
1297 * Deletes text between @start and @end. The order of @start and @end
1298 * is not actually relevant; gtk_text_buffer_delete () will reorder
1299 * them. This function actually emits the "delete_range" signal, and
1300 * the default handler of that signal deletes the text. Because the
1301 * buffer is modified, all outstanding iterators become invalid after
1302 * calling this function; however, the @start and @end will be
1303 * re-initialized to point to the location where text was deleted.
1307 gtk_text_buffer_delete (GtkTextBuffer *buffer,
1311 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1312 g_return_if_fail (start != NULL);
1313 g_return_if_fail (end != NULL);
1314 g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
1315 g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
1317 gtk_text_buffer_emit_delete (buffer, start, end);
1321 * gtk_text_buffer_delete_interactive:
1322 * @buffer: a #GtkTextBuffer
1323 * @start_iter: start of range to delete
1324 * @end_iter: end of range
1325 * @default_editable: whether the buffer is editable by default
1327 * Deletes all <emphasis>editable</emphasis> text in the given range.
1328 * Calls gtk_text_buffer_delete () for each editable sub-range of
1329 * [@start,@end). @start and @end are revalidated to point to
1330 * the location of the last deleted range, or left untouched if
1331 * no text was deleted.
1333 * Return value: whether some text was actually deleted
1336 gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
1337 GtkTextIter *start_iter,
1338 GtkTextIter *end_iter,
1339 gboolean default_editable)
1341 GtkTextMark *end_mark;
1342 GtkTextMark *start_mark;
1344 gboolean current_state;
1345 gboolean deleted_stuff = FALSE;
1347 /* Delete all editable text in the range start_iter, end_iter */
1349 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1350 g_return_val_if_fail (start_iter != NULL, FALSE);
1351 g_return_val_if_fail (end_iter != NULL, FALSE);
1352 g_return_val_if_fail (gtk_text_iter_get_buffer (start_iter) == buffer, FALSE);
1353 g_return_val_if_fail (gtk_text_iter_get_buffer (end_iter) == buffer, FALSE);
1356 gtk_text_buffer_begin_user_action (buffer);
1358 gtk_text_iter_order (start_iter, end_iter);
1360 start_mark = gtk_text_buffer_create_mark (buffer, NULL,
1362 end_mark = gtk_text_buffer_create_mark (buffer, NULL,
1365 gtk_text_buffer_get_iter_at_mark (buffer, &iter, start_mark);
1367 current_state = gtk_text_iter_editable (&iter, default_editable);
1372 gboolean done = FALSE;
1375 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
1377 gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark);
1379 if (gtk_text_iter_compare (&iter, &end) >= 0)
1382 iter = end; /* clamp to the last boundary */
1385 new_state = gtk_text_iter_editable (&iter, default_editable);
1387 if (current_state == new_state)
1393 /* We're ending an editable region. Delete said region. */
1396 gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1398 gtk_text_buffer_emit_delete (buffer, &start, &iter);
1400 deleted_stuff = TRUE;
1402 /* revalidate user's iterators. */
1403 *start_iter = start;
1413 if (current_state && !new_state)
1415 /* End of an editable region. Delete it. */
1418 gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1420 gtk_text_buffer_emit_delete (buffer, &start, &iter);
1422 current_state = FALSE;
1423 deleted_stuff = TRUE;
1425 /* revalidate user's iterators. */
1426 *start_iter = start;
1431 /* We are at the start of an editable region. We won't be deleting
1432 * the previous region. Move start mark to start of this region.
1435 g_assert (!current_state && new_state);
1437 gtk_text_buffer_move_mark (buffer, start_mark,
1441 current_state = TRUE;
1449 gtk_text_buffer_delete_mark (buffer, start_mark);
1450 gtk_text_buffer_delete_mark (buffer, end_mark);
1452 gtk_text_buffer_end_user_action (buffer);
1454 return deleted_stuff;
1458 * Extracting textual buffer contents
1462 * gtk_text_buffer_get_text:
1463 * @buffer: a #GtkTextBuffer
1464 * @start: start of a range
1465 * @end: end of a range
1466 * @include_hidden_chars: whether to include invisible text
1468 * Returns the text in the range [@start,@end). Excludes undisplayed
1469 * text (text marked with tags that set the invisibility attribute) if
1470 * @include_hidden_chars is %FALSE. Does not include characters
1471 * representing embedded images, so byte and character indexes into
1472 * the returned string do <emphasis>not</emphasis> correspond to byte
1473 * and character indexes into the buffer. Contrast with
1474 * gtk_text_buffer_get_slice ().
1476 * Return value: an allocated UTF-8 string
1479 gtk_text_buffer_get_text (GtkTextBuffer *buffer,
1480 const GtkTextIter *start,
1481 const GtkTextIter *end,
1482 gboolean include_hidden_chars)
1484 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1485 g_return_val_if_fail (start != NULL, NULL);
1486 g_return_val_if_fail (end != NULL, NULL);
1487 g_return_val_if_fail (gtk_text_iter_get_buffer (start) == buffer, NULL);
1488 g_return_val_if_fail (gtk_text_iter_get_buffer (end) == buffer, NULL);
1490 if (include_hidden_chars)
1491 return gtk_text_iter_get_text (start, end);
1493 return gtk_text_iter_get_visible_text (start, end);
1497 * gtk_text_buffer_get_slice:
1498 * @buffer: a #GtkTextBuffer
1499 * @start: start of a range
1500 * @end: end of a range
1501 * @include_hidden_chars: whether to include invisible text
1503 * Returns the text in the range [@start,@end). Excludes undisplayed
1504 * text (text marked with tags that set the invisibility attribute) if
1505 * @include_hidden_chars is %FALSE. The returned string includes a
1506 * 0xFFFC character whenever the buffer contains
1507 * embedded images, so byte and character indexes into
1508 * the returned string <emphasis>do</emphasis> correspond to byte
1509 * and character indexes into the buffer. Contrast with
1510 * gtk_text_buffer_get_text (). Note that 0xFFFC can occur in normal
1511 * text as well, so it is not a reliable indicator that a pixbuf or
1512 * widget is in the buffer.
1514 * Return value: an allocated UTF-8 string
1517 gtk_text_buffer_get_slice (GtkTextBuffer *buffer,
1518 const GtkTextIter *start,
1519 const GtkTextIter *end,
1520 gboolean include_hidden_chars)
1522 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1523 g_return_val_if_fail (start != NULL, NULL);
1524 g_return_val_if_fail (end != NULL, NULL);
1525 g_return_val_if_fail (gtk_text_iter_get_buffer (start) == buffer, NULL);
1526 g_return_val_if_fail (gtk_text_iter_get_buffer (end) == buffer, NULL);
1528 if (include_hidden_chars)
1529 return gtk_text_iter_get_slice (start, end);
1531 return gtk_text_iter_get_visible_slice (start, end);
1539 gtk_text_buffer_real_insert_pixbuf (GtkTextBuffer *buffer,
1543 _gtk_text_btree_insert_pixbuf (iter, pixbuf);
1545 g_signal_emit (buffer, signals[CHANGED], 0);
1549 * gtk_text_buffer_insert_pixbuf:
1550 * @buffer: a #GtkTextBuffer
1551 * @iter: location to insert the pixbuf
1552 * @pixbuf: a #GdkPixbuf
1554 * Inserts an image into the text buffer at @iter. The image will be
1555 * counted as one character in character counts, and when obtaining
1556 * the buffer contents as a string, will be represented by the Unicode
1557 * "object replacement character" 0xFFFC. Note that the "slice"
1558 * variants for obtaining portions of the buffer as a string include
1559 * this character for pixbufs, but the "text" variants do
1560 * not. e.g. see gtk_text_buffer_get_slice() and
1561 * gtk_text_buffer_get_text().
1565 gtk_text_buffer_insert_pixbuf (GtkTextBuffer *buffer,
1569 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1570 g_return_if_fail (iter != NULL);
1571 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1572 g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1574 g_signal_emit (buffer, signals[INSERT_PIXBUF], 0,
1584 gtk_text_buffer_real_insert_anchor (GtkTextBuffer *buffer,
1586 GtkTextChildAnchor *anchor)
1588 _gtk_text_btree_insert_child_anchor (iter, anchor);
1590 g_signal_emit (buffer, signals[CHANGED], 0);
1594 * gtk_text_buffer_insert_child_anchor:
1595 * @buffer: a #GtkTextBuffer
1596 * @iter: location to insert the anchor
1597 * @anchor: a #GtkTextChildAnchor
1599 * Inserts a child widget anchor into the text buffer at @iter. The
1600 * anchor will be counted as one character in character counts, and
1601 * when obtaining the buffer contents as a string, will be represented
1602 * by the Unicode "object replacement character" 0xFFFC. Note that the
1603 * "slice" variants for obtaining portions of the buffer as a string
1604 * include this character for child anchors, but the "text" variants do
1605 * not. e.g. see gtk_text_buffer_get_slice() and
1606 * gtk_text_buffer_get_text(). Consider
1607 * gtk_text_buffer_create_child_anchor() as a more convenient
1608 * alternative to this function. The buffer will add a reference to
1609 * the anchor, so you can unref it after insertion.
1613 gtk_text_buffer_insert_child_anchor (GtkTextBuffer *buffer,
1615 GtkTextChildAnchor *anchor)
1617 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1618 g_return_if_fail (iter != NULL);
1619 g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
1620 g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1622 g_signal_emit (buffer, signals[INSERT_CHILD_ANCHOR], 0,
1628 * gtk_text_buffer_create_child_anchor:
1629 * @buffer: a #GtkTextBuffer
1630 * @iter: location in the buffer
1632 * This is a convenience function which simply creates a child anchor
1633 * with gtk_text_child_anchor_new() and inserts it into the buffer
1634 * with gtk_text_buffer_insert_child_anchor(). The new anchor is
1635 * owned by the buffer; no reference count is returned to
1636 * the caller of gtk_text_buffer_create_child_anchor().
1638 * Return value: the created child anchor
1641 gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
1644 GtkTextChildAnchor *anchor;
1646 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1647 g_return_val_if_fail (iter != NULL, NULL);
1648 g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == buffer, NULL);
1650 anchor = gtk_text_child_anchor_new ();
1652 gtk_text_buffer_insert_child_anchor (buffer, iter, anchor);
1654 g_object_unref (anchor);
1664 gtk_text_buffer_mark_set (GtkTextBuffer *buffer,
1665 const GtkTextIter *location,
1668 /* IMO this should NOT work like insert_text and delete_range,
1669 * where the real action happens in the default handler.
1671 * The reason is that the default handler would be _required_,
1672 * i.e. the whole widget would start breaking and segfaulting if the
1673 * default handler didn't get run. So you can't really override the
1674 * default handler or stop the emission; that is, this signal is
1675 * purely for notification, and not to allow users to modify the
1679 g_object_ref (mark);
1681 g_signal_emit (buffer,
1687 g_object_unref (mark);
1691 * gtk_text_buffer_set_mark:
1692 * @buffer: a #GtkTextBuffer
1693 * @mark_name: name of the mark
1694 * @iter: location for the mark.
1695 * @left_gravity: if the mark is created by this function, gravity for the new
1697 * @should_exist: if %TRUE, warn if the mark does not exist, and return
1700 * Move the mark to the given position, if not @should_exist, create the mark.
1702 * Return value: mark
1705 gtk_text_buffer_set_mark (GtkTextBuffer *buffer,
1706 GtkTextMark *existing_mark,
1707 const gchar *mark_name,
1708 const GtkTextIter *iter,
1709 gboolean left_gravity,
1710 gboolean should_exist)
1712 GtkTextIter location;
1715 g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == buffer, NULL);
1717 mark = _gtk_text_btree_set_mark (get_btree (buffer),
1724 if (_gtk_text_btree_mark_is_insert (get_btree (buffer), mark) ||
1725 _gtk_text_btree_mark_is_selection_bound (get_btree (buffer), mark))
1727 update_selection_clipboards (buffer);
1730 _gtk_text_btree_get_iter_at_mark (get_btree (buffer),
1734 gtk_text_buffer_mark_set (buffer, &location, mark);
1740 * gtk_text_buffer_create_mark:
1741 * @buffer: a #GtkTextBuffer
1742 * @mark_name: name for mark, or %NULL
1743 * @where: location to place mark
1744 * @left_gravity: whether the mark has left gravity
1746 * Creates a mark at position @where. If @mark_name is %NULL, the mark
1747 * is anonymous; otherwise, the mark can be retrieved by name using
1748 * gtk_text_buffer_get_mark (). If a mark has left gravity, and text is
1749 * inserted at the mark's current location, the mark will be moved to
1750 * the left of the newly-inserted text. If the mark has right gravity
1751 * (@left_gravity = %FALSE), the mark will end up on the right of
1752 * newly-inserted text. The standard left-to-right cursor is a mark
1753 * with right gravity (when you type, the cursor stays on the right
1754 * side of the text you're typing).
1756 * The caller of this function does <emphasis>not</emphasis> own a reference
1757 * to the returned #GtkTextMark, so you can ignore the return value
1758 * if you like. Marks are owned by the buffer and go away when the
1761 * Emits the "mark_set" signal as notification of the mark's initial
1764 * Return value: the new #GtkTextMark object
1767 gtk_text_buffer_create_mark (GtkTextBuffer *buffer,
1768 const gchar *mark_name,
1769 const GtkTextIter *where,
1770 gboolean left_gravity)
1772 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1774 return gtk_text_buffer_set_mark (buffer, NULL, mark_name, where,
1775 left_gravity, FALSE);
1779 * gtk_text_buffer_move_mark:
1780 * @buffer: a #GtkTextBuffer
1781 * @mark: a #GtkTextMark
1782 * @where: new location for @mark in @buffer
1784 * Moves @mark to the new location @where. Emits the "mark_set" signal
1785 * as notification of the move.
1788 gtk_text_buffer_move_mark (GtkTextBuffer *buffer,
1790 const GtkTextIter *where)
1792 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1793 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1794 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1796 gtk_text_buffer_set_mark (buffer, mark, NULL, where, FALSE, TRUE);
1800 * gtk_text_buffer_get_iter_at_mark:
1801 * @buffer: a #GtkTextBuffer
1802 * @iter: iterator to initialize
1803 * @mark: a #GtkTextMark in @buffer
1805 * Initializes @iter with the current position of @mark.
1808 gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer,
1812 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1813 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1814 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1816 _gtk_text_btree_get_iter_at_mark (get_btree (buffer),
1822 * gtk_text_buffer_delete_mark:
1823 * @buffer: a #GtkTextBuffer
1824 * @mark: a #GtkTextMark in @buffer
1826 * Deletes @mark, so that it's no longer located anywhere in the
1827 * buffer. Removes the reference the buffer holds to the mark, so if
1828 * you haven't called g_object_ref () on the mark, it will be freed. Even
1829 * if the mark isn't freed, most operations on @mark become
1830 * invalid. There is no way to undelete a
1831 * mark. gtk_text_mark_get_deleted () will return TRUE after this
1832 * function has been called on a mark; gtk_text_mark_get_deleted ()
1833 * indicates that a mark no longer belongs to a buffer. The "mark_deleted"
1834 * signal will be emitted as notification after the mark is deleted.
1837 gtk_text_buffer_delete_mark (GtkTextBuffer *buffer,
1840 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1841 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1842 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1844 g_object_ref (mark);
1846 _gtk_text_btree_remove_mark (get_btree (buffer), mark);
1848 /* See rationale above for MARK_SET on why we emit this after
1849 * removing the mark, rather than removing the mark in a default
1852 g_signal_emit (buffer, signals[MARK_DELETED],
1856 g_object_unref (mark);
1860 * gtk_text_buffer_get_mark:
1861 * @buffer: a #GtkTextBuffer
1862 * @name: a mark name
1864 * Returns the mark named @name in buffer @buffer, or NULL if no such
1865 * mark exists in the buffer.
1867 * Return value: a #GtkTextMark, or NULL
1870 gtk_text_buffer_get_mark (GtkTextBuffer *buffer,
1875 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1876 g_return_val_if_fail (name != NULL, NULL);
1878 mark = _gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1885 * gtk_text_buffer_move_mark_by_name:
1886 * @buffer: a #GtkTextBuffer
1887 * @name: name of a mark
1888 * @where: new location for mark
1890 * Moves the mark named @name (which must exist) to location @where.
1891 * See gtk_text_buffer_move_mark () for details.
1894 gtk_text_buffer_move_mark_by_name (GtkTextBuffer *buffer,
1896 const GtkTextIter *where)
1900 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1901 g_return_if_fail (name != NULL);
1903 mark = _gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1907 g_warning ("%s: no mark named '%s'", G_STRLOC, name);
1911 gtk_text_buffer_move_mark (buffer, mark, where);
1915 * gtk_text_buffer_delete_mark_by_name:
1916 * @buffer: a #GtkTextBuffer
1917 * @name: name of a mark in @buffer
1919 * Deletes the mark named @name; the mark must exist. See
1920 * gtk_text_buffer_delete_mark () for details.
1923 gtk_text_buffer_delete_mark_by_name (GtkTextBuffer *buffer,
1928 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1929 g_return_if_fail (name != NULL);
1931 mark = _gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1935 g_warning ("%s: no mark named '%s'", G_STRLOC, name);
1939 gtk_text_buffer_delete_mark (buffer, mark);
1943 * gtk_text_buffer_get_insert:
1944 * @buffer: a #GtkTextBuffer
1946 * Returns the mark that represents the cursor (insertion point).
1947 * Equivalent to calling gtk_text_buffer_get_mark () to get the mark
1948 * named "insert", but very slightly more efficient, and involves less
1951 * Return value: insertion point mark
1954 gtk_text_buffer_get_insert (GtkTextBuffer *buffer)
1956 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1958 /* FIXME use struct member in btree */
1959 return gtk_text_buffer_get_mark (buffer, "insert");
1963 * gtk_text_buffer_get_selection_bound:
1964 * @buffer: a #GtkTextBuffer
1966 * Returns the mark that represents the selection bound. Equivalent
1967 * to calling gtk_text_buffer_get_mark () to get the mark named
1968 * "selection_bound", but very slightly more efficient, and involves
1971 * The currently-selected text in @buffer is the region between the
1972 * "selection_bound" and "insert" marks. If "selection_bound" and
1973 * "insert" are in the same place, then there is no current selection.
1974 * gtk_text_buffer_get_selection_bounds() is another convenient function
1975 * for handling the selection, if you just want to know whether there's a
1976 * selection and what its bounds are.
1978 * Return value: selection bound mark
1981 gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer)
1983 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1985 /* FIXME use struct member in btree */
1986 return gtk_text_buffer_get_mark (buffer, "selection_bound");
1990 * gtk_text_buffer_get_iter_at_child_anchor:
1991 * @buffer: a #GtkTextBuffer
1992 * @iter: an iterator to be initialized
1993 * @anchor: a child anchor that appears in @buffer
1995 * Obtains the location of @anchor within @buffer.
1999 gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer *buffer,
2001 GtkTextChildAnchor *anchor)
2003 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2004 g_return_if_fail (iter != NULL);
2005 g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
2006 g_return_if_fail (!gtk_text_child_anchor_get_deleted (anchor));
2008 _gtk_text_btree_get_iter_at_child_anchor (get_btree (buffer),
2014 * gtk_text_buffer_place_cursor:
2015 * @buffer: a #GtkTextBuffer
2016 * @where: where to put the cursor
2018 * This function moves the "insert" and "selection_bound" marks
2019 * simultaneously. If you move them to the same place in two steps
2020 * with gtk_text_buffer_move_mark(), you will temporarily select a
2021 * region in between their old and new locations, which can be pretty
2022 * inefficient since the temporarily-selected region will force stuff
2023 * to be recalculated. This function moves them as a unit, which can
2027 gtk_text_buffer_place_cursor (GtkTextBuffer *buffer,
2028 const GtkTextIter *where)
2030 gtk_text_buffer_select_range (buffer, where, where);
2035 * gtk_text_buffer_select_range:
2036 * @buffer: a #GtkTextBuffer
2037 * @ins: where to put the "insert" mark
2038 * @bound: where to put the "selection_bound" mark
2040 * This function moves the "insert" and "selection_bound" marks
2041 * simultaneously. If you move them in two steps
2042 * with gtk_text_buffer_move_mark(), you will temporarily select a
2043 * region in between their old and new locations, which can be pretty
2044 * inefficient since the temporarily-selected region will force stuff
2045 * to be recalculated. This function moves them as a unit, which can
2051 gtk_text_buffer_select_range (GtkTextBuffer *buffer,
2052 const GtkTextIter *ins,
2053 const GtkTextIter *bound)
2055 GtkTextIter real_ins;
2056 GtkTextIter real_bound;
2058 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2061 real_bound = *bound;
2063 _gtk_text_btree_select_range (get_btree (buffer), &real_ins, &real_bound);
2064 gtk_text_buffer_mark_set (buffer, &real_ins,
2065 gtk_text_buffer_get_mark (buffer,
2067 gtk_text_buffer_mark_set (buffer, &real_bound,
2068 gtk_text_buffer_get_mark (buffer,
2069 "selection_bound"));
2070 update_selection_clipboards (buffer);
2078 * gtk_text_buffer_create_tag:
2079 * @buffer: a #GtkTextBuffer
2080 * @tag_name: name of the new tag, or %NULL
2081 * @first_property_name: name of first property to set, or %NULL
2082 * @Varargs: %NULL-terminated list of property names and values
2085 * Creates a tag and adds it to the tag table for @buffer.
2086 * Equivalent to calling gtk_text_tag_new () and then adding the
2087 * tag to the buffer's tag table. The returned tag is owned by
2088 * the buffer's tag table, so the ref count will be equal to one.
2090 * If @tag_name is %NULL, the tag is anonymous.
2092 * If @tag_name is non-%NULL, a tag called @tag_name must not already
2093 * exist in the tag table for this buffer.
2095 * The @first_property_name argument and subsequent arguments are a list
2096 * of properties to set on the tag, as with g_object_set().
2098 * Return value: a new tag
2101 gtk_text_buffer_create_tag (GtkTextBuffer *buffer,
2102 const gchar *tag_name,
2103 const gchar *first_property_name,
2109 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
2111 tag = gtk_text_tag_new (tag_name);
2113 gtk_text_tag_table_add (get_table (buffer), tag);
2115 if (first_property_name)
2117 va_start (list, first_property_name);
2118 g_object_set_valist (G_OBJECT (tag), first_property_name, list);
2122 g_object_unref (tag);
2128 gtk_text_buffer_real_apply_tag (GtkTextBuffer *buffer,
2130 const GtkTextIter *start,
2131 const GtkTextIter *end)
2133 if (tag->table != buffer->tag_table)
2135 g_warning ("Can only apply tags that are in the tag table for the buffer");
2139 _gtk_text_btree_tag (start, end, tag, TRUE);
2143 gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
2145 const GtkTextIter *start,
2146 const GtkTextIter *end)
2148 if (tag->table != buffer->tag_table)
2150 g_warning ("Can only remove tags that are in the tag table for the buffer");
2154 _gtk_text_btree_tag (start, end, tag, FALSE);
2158 gtk_text_buffer_real_changed (GtkTextBuffer *buffer)
2160 gtk_text_buffer_set_modified (buffer, TRUE);
2164 gtk_text_buffer_emit_tag (GtkTextBuffer *buffer,
2167 const GtkTextIter *start,
2168 const GtkTextIter *end)
2170 GtkTextIter start_tmp = *start;
2171 GtkTextIter end_tmp = *end;
2173 g_return_if_fail (tag != NULL);
2175 gtk_text_iter_order (&start_tmp, &end_tmp);
2178 g_signal_emit (buffer, signals[APPLY_TAG],
2180 tag, &start_tmp, &end_tmp);
2182 g_signal_emit (buffer, signals[REMOVE_TAG],
2184 tag, &start_tmp, &end_tmp);
2189 * gtk_text_buffer_apply_tag:
2190 * @buffer: a #GtkTextBuffer
2191 * @tag: a #GtkTextTag
2192 * @start: one bound of range to be tagged
2193 * @end: other bound of range to be tagged
2195 * Emits the "apply_tag" signal on @buffer. The default
2196 * handler for the signal applies @tag to the given range.
2197 * @start and @end do not have to be in order.
2201 gtk_text_buffer_apply_tag (GtkTextBuffer *buffer,
2203 const GtkTextIter *start,
2204 const GtkTextIter *end)
2206 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2207 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
2208 g_return_if_fail (start != NULL);
2209 g_return_if_fail (end != NULL);
2210 g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2211 g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2212 g_return_if_fail (tag->table == buffer->tag_table);
2214 gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
2218 * gtk_text_buffer_remove_tag:
2219 * @buffer: a #GtkTextBuffer
2220 * @tag: a #GtkTextTag
2221 * @start: one bound of range to be untagged
2222 * @end: other bound of range to be untagged
2224 * Emits the "remove_tag" signal. The default handler for the signal
2225 * removes all occurrences of @tag from the given range. @start and
2226 * @end don't have to be in order.
2230 gtk_text_buffer_remove_tag (GtkTextBuffer *buffer,
2232 const GtkTextIter *start,
2233 const GtkTextIter *end)
2236 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2237 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
2238 g_return_if_fail (start != NULL);
2239 g_return_if_fail (end != NULL);
2240 g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2241 g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2242 g_return_if_fail (tag->table == buffer->tag_table);
2244 gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
2249 * gtk_text_buffer_apply_tag_by_name:
2250 * @buffer: a #GtkTextBuffer
2251 * @name: name of a named #GtkTextTag
2252 * @start: one bound of range to be tagged
2253 * @end: other bound of range to be tagged
2255 * Calls gtk_text_tag_table_lookup() on the buffer's tag table to
2256 * get a #GtkTextTag, then calls gtk_text_buffer_apply_tag().
2260 gtk_text_buffer_apply_tag_by_name (GtkTextBuffer *buffer,
2262 const GtkTextIter *start,
2263 const GtkTextIter *end)
2267 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2268 g_return_if_fail (name != NULL);
2269 g_return_if_fail (start != NULL);
2270 g_return_if_fail (end != NULL);
2271 g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2272 g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2274 tag = gtk_text_tag_table_lookup (get_table (buffer),
2279 g_warning ("Unknown tag `%s'", name);
2283 gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
2287 * gtk_text_buffer_remove_tag_by_name:
2288 * @buffer: a #GtkTextBuffer
2289 * @name: name of a #GtkTextTag
2290 * @start: one bound of range to be untagged
2291 * @end: other bound of range to be untagged
2293 * Calls gtk_text_tag_table_lookup() on the buffer's tag table to
2294 * get a #GtkTextTag, then calls gtk_text_buffer_remove_tag().
2299 gtk_text_buffer_remove_tag_by_name (GtkTextBuffer *buffer,
2301 const GtkTextIter *start,
2302 const GtkTextIter *end)
2306 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2307 g_return_if_fail (name != NULL);
2308 g_return_if_fail (start != NULL);
2309 g_return_if_fail (end != NULL);
2310 g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2311 g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2313 tag = gtk_text_tag_table_lookup (get_table (buffer),
2318 g_warning ("Unknown tag `%s'", name);
2322 gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
2326 pointer_cmp (gconstpointer a,
2338 * gtk_text_buffer_remove_all_tags:
2339 * @buffer: a #GtkTextBuffer
2340 * @start: one bound of range to be untagged
2341 * @end: other bound of range to be untagged
2343 * Removes all tags in the range between @start and @end. Be careful
2344 * with this function; it could remove tags added in code unrelated to
2345 * the code you're currently writing. That is, using this function is
2346 * probably a bad idea if you have two or more unrelated code sections
2350 gtk_text_buffer_remove_all_tags (GtkTextBuffer *buffer,
2351 const GtkTextIter *start,
2352 const GtkTextIter *end)
2354 GtkTextIter first, second, tmp;
2360 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2361 g_return_if_fail (start != NULL);
2362 g_return_if_fail (end != NULL);
2363 g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2364 g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2369 gtk_text_iter_order (&first, &second);
2371 /* Get all tags turned on at the start */
2372 tags = gtk_text_iter_get_tags (&first);
2374 /* Find any that are toggled on within the range */
2376 while (gtk_text_iter_forward_to_tag_toggle (&tmp, NULL))
2381 if (gtk_text_iter_compare (&tmp, &second) >= 0)
2382 break; /* past the end of the range */
2384 toggled = gtk_text_iter_get_toggled_tags (&tmp, TRUE);
2386 /* We could end up with a really big-ass list here.
2389 tmp_list2 = toggled;
2390 while (tmp_list2 != NULL)
2392 tags = g_slist_prepend (tags, tmp_list2->data);
2394 tmp_list2 = g_slist_next (tmp_list2);
2397 g_slist_free (toggled);
2401 tags = g_slist_sort (tags, pointer_cmp);
2403 /* Strip duplicates */
2407 while (tmp_list != NULL)
2409 if (tag == tmp_list->data)
2413 prev->next = tmp_list->next;
2415 tmp_list->next = NULL;
2417 g_slist_free (tmp_list);
2419 tmp_list = prev->next;
2420 /* prev is unchanged */
2424 /* not a duplicate */
2425 tag = GTK_TEXT_TAG (tmp_list->data);
2427 tmp_list = tmp_list->next;
2431 g_slist_foreach (tags, (GFunc) g_object_ref, NULL);
2434 while (tmp_list != NULL)
2436 tag = GTK_TEXT_TAG (tmp_list->data);
2438 gtk_text_buffer_remove_tag (buffer, tag, &first, &second);
2440 tmp_list = tmp_list->next;
2443 g_slist_foreach (tags, (GFunc) g_object_unref, NULL);
2445 g_slist_free (tags);
2450 * Obtain various iterators
2454 * gtk_text_buffer_get_iter_at_line_offset:
2455 * @buffer: a #GtkTextBuffer
2456 * @iter: iterator to initialize
2457 * @line_number: line number counting from 0
2458 * @char_offset: char offset from start of line
2460 * Obtains an iterator pointing to @char_offset within the given
2461 * line. The @char_offset must exist, offsets off the end of the line
2462 * are not allowed. Note <emphasis>characters</emphasis>, not bytes;
2463 * UTF-8 may encode one character as multiple bytes.
2467 gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
2472 g_return_if_fail (iter != NULL);
2473 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2475 _gtk_text_btree_get_iter_at_line_char (get_btree (buffer),
2476 iter, line_number, char_offset);
2480 * gtk_text_buffer_get_iter_at_line_index:
2481 * @buffer: a #GtkTextBuffer
2482 * @iter: iterator to initialize
2483 * @line_number: line number counting from 0
2484 * @byte_index: byte index from start of line
2486 * Obtains an iterator pointing to @byte_index within the given line.
2487 * @byte_index must be the start of a UTF-8 character, and must not be
2488 * beyond the end of the line. Note <emphasis>bytes</emphasis>, not
2489 * characters; UTF-8 may encode one character as multiple bytes.
2493 gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
2498 g_return_if_fail (iter != NULL);
2499 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2501 _gtk_text_btree_get_iter_at_line_byte (get_btree (buffer),
2502 iter, line_number, byte_index);
2506 * gtk_text_buffer_get_iter_at_line:
2507 * @buffer: a #GtkTextBuffer
2508 * @iter: iterator to initialize
2509 * @line_number: line number counting from 0
2511 * Initializes @iter to the start of the given line.
2514 gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
2518 g_return_if_fail (iter != NULL);
2519 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2521 gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
2525 * gtk_text_buffer_get_iter_at_offset:
2526 * @buffer: a #GtkTextBuffer
2527 * @iter: iterator to initialize
2528 * @char_offset: char offset from start of buffer, counting from 0, or -1
2530 * Initializes @iter to a position @char_offset chars from the start
2531 * of the entire buffer. If @char_offset is -1 or greater than the number
2532 * of characters in the buffer, @iter is initialized to the end iterator,
2533 * the iterator one past the last valid character in the buffer.
2536 gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
2540 g_return_if_fail (iter != NULL);
2541 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2543 _gtk_text_btree_get_iter_at_char (get_btree (buffer), iter, char_offset);
2547 * gtk_text_buffer_get_start_iter:
2548 * @buffer: a #GtkTextBuffer
2549 * @iter: iterator to initialize
2551 * Initialized @iter with the first position in the text buffer. This
2552 * is the same as using gtk_text_buffer_get_iter_at_offset() to get
2553 * the iter at character offset 0.
2556 gtk_text_buffer_get_start_iter (GtkTextBuffer *buffer,
2559 g_return_if_fail (iter != NULL);
2560 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2562 _gtk_text_btree_get_iter_at_char (get_btree (buffer), iter, 0);
2566 * gtk_text_buffer_get_end_iter:
2567 * @buffer: a #GtkTextBuffer
2568 * @iter: iterator to initialize
2570 * Initializes @iter with the "end iterator," one past the last valid
2571 * character in the text buffer. If dereferenced with
2572 * gtk_text_iter_get_char(), the end iterator has a character value of
2573 * 0. The entire buffer lies in the range from the first position in
2574 * the buffer (call gtk_text_buffer_get_start_iter() to get
2575 * character position 0) to the end iterator.
2579 gtk_text_buffer_get_end_iter (GtkTextBuffer *buffer,
2582 g_return_if_fail (iter != NULL);
2583 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2585 _gtk_text_btree_get_end_iter (get_btree (buffer), iter);
2589 * gtk_text_buffer_get_bounds:
2590 * @buffer: a #GtkTextBuffer
2591 * @start: iterator to initialize with first position in the buffer
2592 * @end: iterator to initialize with the end iterator
2594 * Retrieves the first and last iterators in the buffer, i.e. the
2595 * entire buffer lies within the range [@start,@end).
2599 gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
2603 g_return_if_fail (start != NULL);
2604 g_return_if_fail (end != NULL);
2605 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2607 _gtk_text_btree_get_iter_at_char (get_btree (buffer), start, 0);
2608 _gtk_text_btree_get_end_iter (get_btree (buffer), end);
2616 * gtk_text_buffer_get_modified:
2617 * @buffer: a #GtkTextBuffer
2619 * Indicates whether the buffer has been modified since the last call
2620 * to gtk_text_buffer_set_modified() set the modification flag to
2621 * %FALSE. Used for example to enable a "save" function in a text
2624 * Return value: %TRUE if the buffer has been modified
2627 gtk_text_buffer_get_modified (GtkTextBuffer *buffer)
2629 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
2631 return buffer->modified;
2635 * gtk_text_buffer_set_modified:
2636 * @buffer: a #GtkTextBuffer
2637 * @setting: modification flag setting
2639 * Used to keep track of whether the buffer has been modified since the
2640 * last time it was saved. Whenever the buffer is saved to disk, call
2641 * gtk_text_buffer_set_modified (@buffer, FALSE). When the buffer is modified,
2642 * it will automatically toggled on the modified bit again. When the modified
2643 * bit flips, the buffer emits a "modified_changed" signal.
2647 gtk_text_buffer_set_modified (GtkTextBuffer *buffer,
2650 gboolean fixed_setting;
2652 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2654 fixed_setting = setting != FALSE;
2656 if (buffer->modified == fixed_setting)
2660 buffer->modified = fixed_setting;
2661 g_signal_emit (buffer, signals[MODIFIED_CHANGED], 0);
2667 * Assorted other stuff
2671 * gtk_text_buffer_get_line_count:
2672 * @buffer: a #GtkTextBuffer
2674 * Obtains the number of lines in the buffer. This value is cached, so
2675 * the function is very fast.
2677 * Return value: number of lines in the buffer
2680 gtk_text_buffer_get_line_count (GtkTextBuffer *buffer)
2682 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), 0);
2684 return _gtk_text_btree_line_count (get_btree (buffer));
2688 * gtk_text_buffer_get_char_count:
2689 * @buffer: a #GtkTextBuffer
2691 * Gets the number of characters in the buffer; note that characters
2692 * and bytes are not the same, you can't e.g. expect the contents of
2693 * the buffer in string form to be this many bytes long. The character
2694 * count is cached, so this function is very fast.
2696 * Return value: number of characters in the buffer
2699 gtk_text_buffer_get_char_count (GtkTextBuffer *buffer)
2701 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), 0);
2703 return _gtk_text_btree_char_count (get_btree (buffer));
2706 /* Called when we lose the primary selection.
2709 clipboard_clear_selection_cb (GtkClipboard *clipboard,
2712 /* Move selection_bound to the insertion point */
2714 GtkTextIter selection_bound;
2715 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2717 gtk_text_buffer_get_iter_at_mark (buffer, &insert,
2718 gtk_text_buffer_get_mark (buffer, "insert"));
2719 gtk_text_buffer_get_iter_at_mark (buffer, &selection_bound,
2720 gtk_text_buffer_get_mark (buffer, "selection_bound"));
2722 if (!gtk_text_iter_equal (&insert, &selection_bound))
2723 gtk_text_buffer_move_mark (buffer,
2724 gtk_text_buffer_get_mark (buffer, "selection_bound"),
2728 /* Called when we have the primary selection and someone else wants our
2729 * data in order to paste it.
2732 clipboard_get_selection_cb (GtkClipboard *clipboard,
2733 GtkSelectionData *selection_data,
2737 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2738 GtkTextIter start, end;
2740 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2742 if (selection_data->target ==
2743 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2745 /* Provide the address of the buffer; this will only be
2746 * used within-process
2748 gtk_selection_data_set (selection_data,
2749 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2758 str = gtk_text_iter_get_visible_text (&start, &end);
2759 gtk_selection_data_set_text (selection_data, str, -1);
2765 static GtkTextBuffer *
2766 create_clipboard_contents_buffer (GtkTextBuffer *buffer)
2768 GtkTextBuffer *contents;
2770 contents = gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer));
2772 g_object_set_data (G_OBJECT (contents), "gtk-text-buffer-clipboard", GINT_TO_POINTER (1));
2777 /* Provide cut/copied data */
2779 clipboard_get_contents_cb (GtkClipboard *clipboard,
2780 GtkSelectionData *selection_data,
2784 GtkTextBuffer *contents;
2786 contents = GTK_TEXT_BUFFER (data);
2788 g_assert (contents); /* This should never be called unless we own the clipboard */
2790 if (selection_data->target ==
2791 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2793 /* Provide the address of the clipboard buffer; this will only
2794 * be used within-process. OK to supply a NULL value for contents.
2796 gtk_selection_data_set (selection_data,
2797 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2805 GtkTextIter start, end;
2807 gtk_text_buffer_get_bounds (contents, &start, &end);
2809 str = gtk_text_iter_get_visible_text (&start, &end);
2810 gtk_selection_data_set_text (selection_data, str, -1);
2816 clipboard_clear_contents_cb (GtkClipboard *clipboard,
2819 GtkTextBuffer *contents = GTK_TEXT_BUFFER (data);
2821 g_object_unref (contents);
2825 get_paste_point (GtkTextBuffer *buffer,
2827 gboolean clear_afterward)
2829 GtkTextIter insert_point;
2830 GtkTextMark *paste_point_override;
2832 paste_point_override = gtk_text_buffer_get_mark (buffer,
2833 "gtk_paste_point_override");
2835 if (paste_point_override != NULL)
2837 gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
2838 paste_point_override);
2839 if (clear_afterward)
2840 gtk_text_buffer_delete_mark (buffer,
2841 gtk_text_buffer_get_mark (buffer,
2842 "gtk_paste_point_override"));
2846 gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
2847 gtk_text_buffer_get_mark (buffer,
2851 *iter = insert_point;
2855 pre_paste_prep (ClipboardRequest *request_data,
2856 GtkTextIter *insert_point)
2858 GtkTextBuffer *buffer = request_data->buffer;
2860 get_paste_point (buffer, insert_point, TRUE);
2862 /* If we're going to replace the selection, we insert before it to
2863 * avoid messing it up, then we delete the selection after inserting.
2865 if (request_data->replace_selection)
2867 GtkTextIter start, end;
2869 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2870 *insert_point = start;
2875 post_paste_cleanup (ClipboardRequest *request_data)
2877 if (request_data->replace_selection)
2879 GtkTextIter start, end;
2881 if (gtk_text_buffer_get_selection_bounds (request_data->buffer,
2884 if (request_data->interactive)
2885 gtk_text_buffer_delete_interactive (request_data->buffer,
2888 request_data->default_editable);
2890 gtk_text_buffer_delete (request_data->buffer, &start, &end);
2895 /* Called when we request a paste and receive the text data
2898 clipboard_text_received (GtkClipboard *clipboard,
2902 ClipboardRequest *request_data = data;
2903 GtkTextBuffer *buffer = request_data->buffer;
2907 GtkTextIter insert_point;
2909 if (request_data->interactive)
2910 gtk_text_buffer_begin_user_action (buffer);
2912 pre_paste_prep (request_data, &insert_point);
2914 if (request_data->interactive)
2915 gtk_text_buffer_insert_interactive (buffer, &insert_point,
2916 str, -1, request_data->default_editable);
2918 gtk_text_buffer_insert (buffer, &insert_point,
2921 post_paste_cleanup (request_data);
2923 if (request_data->interactive)
2924 gtk_text_buffer_end_user_action (buffer);
2927 g_object_unref (buffer);
2928 g_free (request_data);
2931 static GtkTextBuffer*
2932 selection_data_get_buffer (GtkSelectionData *selection_data,
2933 ClipboardRequest *request_data)
2936 GtkTextBuffer *src_buffer = NULL;
2938 /* If we can get the owner, the selection is in-process */
2939 owner = gdk_selection_owner_get_for_display (selection_data->display,
2940 selection_data->selection);
2945 if (gdk_window_get_window_type (owner) == GDK_WINDOW_FOREIGN)
2948 if (selection_data->type != gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2951 if (selection_data->length != sizeof (src_buffer))
2954 memcpy (&src_buffer, selection_data->data, sizeof (src_buffer));
2956 if (src_buffer == NULL)
2959 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (src_buffer), NULL);
2961 if (gtk_text_buffer_get_tag_table (src_buffer) !=
2962 gtk_text_buffer_get_tag_table (request_data->buffer))
2969 /* These are pretty handy functions; maybe something like them
2970 * should be in the public API. Also, there are other places in this
2971 * file where they could be used.
2974 save_iter (const GtkTextIter *iter,
2975 gboolean left_gravity)
2977 return gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (iter),
2984 restore_iter (const GtkTextIter *iter,
2987 gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (save_id),
2988 (GtkTextIter*) iter,
2990 gtk_text_buffer_delete_mark (gtk_text_mark_get_buffer (save_id),
2996 paste_from_buffer (ClipboardRequest *request_data,
2997 GtkTextBuffer *src_buffer,
2998 const GtkTextIter *start,
2999 const GtkTextIter *end)
3001 GtkTextIter insert_point;
3002 GtkTextBuffer *buffer = request_data->buffer;
3004 /* We're about to emit a bunch of signals, so be safe */
3005 g_object_ref (src_buffer);
3007 pre_paste_prep (request_data, &insert_point);
3009 if (request_data->interactive)
3010 gtk_text_buffer_begin_user_action (buffer);
3012 if (!gtk_text_iter_equal (start, end))
3014 if (!request_data->interactive ||
3015 (gtk_text_iter_can_insert (&insert_point,
3016 request_data->default_editable)))
3017 gtk_text_buffer_real_insert_range (buffer,
3021 request_data->interactive);
3024 post_paste_cleanup (request_data);
3026 if (request_data->interactive)
3027 gtk_text_buffer_end_user_action (buffer);
3029 g_object_unref (src_buffer);
3030 g_free (request_data);
3034 clipboard_clipboard_buffer_received (GtkClipboard *clipboard,
3035 GtkSelectionData *selection_data,
3038 ClipboardRequest *request_data = data;
3039 GtkTextBuffer *src_buffer;
3041 src_buffer = selection_data_get_buffer (selection_data, request_data);
3045 GtkTextIter start, end;
3047 if (g_object_get_data (G_OBJECT (src_buffer), "gtk-text-buffer-clipboard"))
3049 gtk_text_buffer_get_bounds (src_buffer, &start, &end);
3051 paste_from_buffer (request_data, src_buffer,
3056 if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end))
3057 paste_from_buffer (request_data, src_buffer,
3063 /* Request the text selection instead */
3064 gtk_clipboard_request_text (clipboard,
3065 clipboard_text_received,
3070 static const GtkTargetEntry targets[] = {
3071 { "STRING", 0, TARGET_STRING },
3072 { "TEXT", 0, TARGET_TEXT },
3073 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
3074 { "UTF8_STRING", 0, TARGET_UTF8_STRING },
3075 { "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS }
3080 GtkClipboard *clipboard;
3082 } SelectionClipboard;
3085 update_selection_clipboards (GtkTextBuffer *buffer)
3087 GSList *tmp_list = buffer->selection_clipboards;
3093 SelectionClipboard *selection_clipboard = tmp_list->data;
3094 GtkClipboard *clipboard = selection_clipboard->clipboard;
3096 /* Determine whether we have a selection and adjust X selection
3099 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
3101 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer))
3102 gtk_clipboard_clear (clipboard);
3106 /* Even if we already have the selection, we need to update our
3109 if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
3110 clipboard_get_selection_cb,
3111 clipboard_clear_selection_cb,
3113 clipboard_clear_selection_cb (clipboard, buffer);
3116 tmp_list = tmp_list->next;
3120 static SelectionClipboard *
3121 find_selection_clipboard (GtkTextBuffer *buffer,
3122 GtkClipboard *clipboard)
3124 GSList *tmp_list = buffer->selection_clipboards;
3127 SelectionClipboard *selection_clipboard = tmp_list->data;
3128 if (selection_clipboard->clipboard == clipboard)
3129 return selection_clipboard;
3131 tmp_list = tmp_list->next;
3138 * gtk_text_buffer_add_selection_clipboard:
3139 * @buffer: a #GtkTextBuffer
3140 * @clipboard: a #GtkClipboard
3142 * Adds @clipboard to the list of clipboards in which the selection contents
3143 * of @buffer are available. In most cases, @clipboard will be the #GtkClipboard
3144 * of type %GDK_SELECTION_PRIMARY for a view of @buffer.
3147 gtk_text_buffer_add_selection_clipboard (GtkTextBuffer *buffer,
3148 GtkClipboard *clipboard)
3150 SelectionClipboard *selection_clipboard;
3152 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
3153 g_return_if_fail (clipboard != NULL);
3155 selection_clipboard = find_selection_clipboard (buffer, clipboard);
3156 if (selection_clipboard)
3158 selection_clipboard->ref_count++;
3162 selection_clipboard = g_new (SelectionClipboard, 1);
3164 selection_clipboard->clipboard = clipboard;
3165 selection_clipboard->ref_count = 1;
3167 buffer->selection_clipboards = g_slist_prepend (buffer->selection_clipboards, selection_clipboard);
3172 * gtk_text_buffer_remove_selection_clipboard:
3173 * @buffer: a #GtkTextBuffer
3174 * @clipboard: a #GtkClipboard added to @buffer by gtk_text_buffer_add_selection_clipboard().
3176 * Removes a #GtkClipboard added with gtk_text_buffer_add_selection_clipboard()
3179 gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer *buffer,
3180 GtkClipboard *clipboard)
3182 SelectionClipboard *selection_clipboard;
3184 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
3185 g_return_if_fail (clipboard != NULL);
3187 selection_clipboard = find_selection_clipboard (buffer, clipboard);
3188 g_return_if_fail (selection_clipboard != NULL);
3190 selection_clipboard->ref_count--;
3191 if (selection_clipboard->ref_count == 0)
3193 if (gtk_clipboard_get_owner (selection_clipboard->clipboard) == G_OBJECT (buffer))
3194 gtk_clipboard_clear (selection_clipboard->clipboard);
3196 buffer->selection_clipboards = g_slist_remove (buffer->selection_clipboards,
3197 selection_clipboard);
3199 g_free (selection_clipboard);
3204 remove_all_selection_clipboards (GtkTextBuffer *buffer)
3206 GSList *tmp_list = buffer->selection_clipboards;
3209 SelectionClipboard *selection_clipboard = tmp_list->data;
3211 if (gtk_clipboard_get_owner (selection_clipboard->clipboard) == G_OBJECT (buffer))
3212 gtk_clipboard_clear (selection_clipboard->clipboard);
3214 g_free (selection_clipboard);
3216 tmp_list = tmp_list->next;
3219 g_slist_free (buffer->selection_clipboards);
3220 buffer->selection_clipboards = NULL;
3224 * gtk_text_buffer_paste_clipboard:
3225 * @buffer: a #GtkTextBuffer
3226 * @clipboard: the #GtkClipboard to paste from
3227 * @override_location: location to insert pasted text, or %NULL for at the cursor
3228 * @default_editable: whether the buffer is editable by default
3230 * Pastes the contents of a clipboard at the insertion point, or at @override_location.
3231 * (Note: pasting is asynchronous, that is, we'll ask for the paste data and
3232 * return, and at some point later after the main loop runs, the paste
3233 * data will be inserted.)
3237 gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
3238 GtkClipboard *clipboard,
3239 GtkTextIter *override_location,
3240 gboolean default_editable)
3242 ClipboardRequest *data = g_new (ClipboardRequest, 1);
3243 GtkTextIter paste_point;
3244 GtkTextIter start, end;
3246 if (override_location != NULL)
3247 gtk_text_buffer_create_mark (buffer,
3248 "gtk_paste_point_override",
3249 override_location, FALSE);
3251 data->buffer = buffer;
3252 g_object_ref (buffer);
3253 data->interactive = TRUE;
3254 data->default_editable = default_editable;
3256 /* When pasting with the cursor inside the selection area, you
3257 * replace the selection with the new text, otherwise, you
3258 * simply insert the new text at the point where the click
3259 * occured, unselecting any selected text. The replace_selection
3260 * flag toggles this behavior.
3262 data->replace_selection = FALSE;
3264 get_paste_point (buffer, &paste_point, FALSE);
3265 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end) &&
3266 (gtk_text_iter_in_range (&paste_point, &start, &end) ||
3267 gtk_text_iter_equal (&paste_point, &end)))
3268 data->replace_selection = TRUE;
3270 gtk_clipboard_request_contents (clipboard,
3271 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
3272 clipboard_clipboard_buffer_received, data);
3276 * gtk_text_buffer_delete_selection:
3277 * @buffer: a #GtkTextBuffer
3278 * @interactive: whether the deletion is caused by user interaction
3279 * @default_editable: whether the buffer is editable by default
3281 * Deletes the range between the "insert" and "selection_bound" marks,
3282 * that is, the currently-selected text. If @interactive is %TRUE,
3283 * the editability of the selection will be considered (users can't delete
3286 * Return value: whether there was a non-empty selection to delete
3289 gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
3290 gboolean interactive,
3291 gboolean default_editable)
3296 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
3298 return FALSE; /* No selection */
3304 gtk_text_buffer_begin_user_action (buffer);
3305 gtk_text_buffer_delete_interactive (buffer, &start, &end, default_editable);
3306 gtk_text_buffer_end_user_action (buffer);
3309 gtk_text_buffer_delete (buffer, &start, &end);
3311 return TRUE; /* We deleted stuff */
3316 * gtk_text_buffer_backspace:
3317 * @buffer: a #GtkTextBuffer
3318 * @iter: a position in @buffer
3319 * @interactive: whether the deletion is caused by user interaction
3320 * @default_editable: whether the buffer is editable by default
3322 * Performs the appropriate action as if the user hit the delete
3323 * key with the cursor at the position specified by @iter. In the
3324 * normal case a single character will be deleted, but when
3325 * combining accents are involved, more than one character can
3326 * be deleted, and when precomposed character and accent combinations
3327 * are involved, less than one character will be deleted.
3329 * Because the buffer is modified, all outstanding iterators become
3330 * invalid after calling this function; however, the @iter will be
3331 * re-initialized to point to the location where text was deleted.
3333 * Return value: %TRUE if the buffer was modified
3338 gtk_text_buffer_backspace (GtkTextBuffer *buffer,
3340 gboolean interactive,
3341 gboolean default_editable)
3343 gchar *cluster_text;
3346 gboolean retval = FALSE;
3347 const PangoLogAttr *attrs;
3349 gboolean backspace_deletes_character;
3351 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
3352 g_return_val_if_fail (iter != NULL, FALSE);
3357 attrs = _gtk_text_buffer_get_line_log_attrs (buffer, &start, NULL);
3359 /* For no good reason, attrs is NULL for the empty last line in
3360 * a buffer. Special case that here. (#156164)
3364 offset = gtk_text_iter_get_line_offset (&start);
3365 backspace_deletes_character = attrs[offset].backspace_deletes_character;
3368 backspace_deletes_character = FALSE;
3370 gtk_text_iter_backward_cursor_position (&start);
3372 if (gtk_text_iter_equal (&start, &end))
3375 cluster_text = gtk_text_iter_get_text (&start, &end);
3378 gtk_text_buffer_begin_user_action (buffer);
3380 if (gtk_text_buffer_delete_interactive (buffer, &start, &end,
3383 if (backspace_deletes_character)
3385 gchar *normalized_text = g_utf8_normalize (cluster_text,
3386 strlen (cluster_text),
3388 glong len = g_utf8_strlen (normalized_text, -1);
3391 gtk_text_buffer_insert_interactive (buffer,
3394 g_utf8_offset_to_pointer (normalized_text, len - 1) - normalized_text,
3397 g_free (normalized_text);
3404 gtk_text_buffer_end_user_action (buffer);
3406 g_free (cluster_text);
3408 /* Revalidate the users iter */
3415 cut_or_copy (GtkTextBuffer *buffer,
3416 GtkClipboard *clipboard,
3417 gboolean delete_region_after,
3418 gboolean interactive,
3419 gboolean default_editable)
3421 /* We prefer to cut the selected region between selection_bound and
3422 * insertion point. If that region is empty, then we cut the region
3423 * between the "anchor" and the insertion point (this is for
3424 * C-space and M-w and other Emacs-style copy/yank keys). Note that
3425 * insert and selection_bound are guaranteed to exist, but the
3426 * anchor only exists sometimes.
3431 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
3433 /* Let's try the anchor thing */
3434 GtkTextMark * anchor = gtk_text_buffer_get_mark (buffer, "anchor");
3440 gtk_text_buffer_get_iter_at_mark (buffer, &end, anchor);
3441 gtk_text_iter_order (&start, &end);
3445 if (!gtk_text_iter_equal (&start, &end))
3448 GtkTextBuffer *contents;
3450 contents = create_clipboard_contents_buffer (buffer);
3452 gtk_text_buffer_get_iter_at_offset (contents, &ins, 0);
3454 gtk_text_buffer_insert_range (contents, &ins, &start, &end);
3456 if (!gtk_clipboard_set_with_data (clipboard, targets, G_N_ELEMENTS (targets),
3457 clipboard_get_contents_cb,
3458 clipboard_clear_contents_cb,
3460 g_object_unref (contents);
3462 gtk_clipboard_set_can_store (clipboard, (GtkTargetEntry *)targets, G_N_ELEMENTS (targets) -1);
3464 if (delete_region_after)
3467 gtk_text_buffer_delete_interactive (buffer, &start, &end,
3470 gtk_text_buffer_delete (buffer, &start, &end);
3476 * gtk_text_buffer_cut_clipboard:
3477 * @buffer: a #GtkTextBuffer
3478 * @clipboard: the #GtkClipboard object to cut to.
3479 * @default_editable: default editability of the buffer
3481 * Copies the currently-selected text to a clipboard, then deletes
3482 * said text if it's editable.
3486 gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
3487 GtkClipboard *clipboard,
3488 gboolean default_editable)
3490 gtk_text_buffer_begin_user_action (buffer);
3491 cut_or_copy (buffer, clipboard, TRUE, TRUE, default_editable);
3492 gtk_text_buffer_end_user_action (buffer);
3496 * gtk_text_buffer_copy_clipboard:
3497 * @buffer: a #GtkTextBuffer
3498 * @clipboard: the #GtkClipboard object to copy to.
3500 * Copies the currently-selected text to a clipboard.
3504 gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer,
3505 GtkClipboard *clipboard)
3507 gtk_text_buffer_begin_user_action (buffer);
3508 cut_or_copy (buffer, clipboard, FALSE, TRUE, TRUE);
3509 gtk_text_buffer_end_user_action (buffer);
3514 * gtk_text_buffer_get_selection_bounds:
3515 * @buffer: a #GtkTextBuffer a #GtkTextBuffer
3516 * @start: iterator to initialize with selection start
3517 * @end: iterator to initialize with selection end
3519 * Returns %TRUE if some text is selected; places the bounds
3520 * of the selection in @start and @end (if the selection has length 0,
3521 * then @start and @end are filled in with the same value).
3522 * @start and @end will be in ascending order. If @start and @end are
3523 * NULL, then they are not filled in, but the return value still indicates
3524 * whether text is selected.
3526 * Return value: whether the selection has nonzero length
3529 gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer,
3533 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
3535 return _gtk_text_btree_get_selection_bounds (get_btree (buffer), start, end);
3539 * gtk_text_buffer_begin_user_action:
3540 * @buffer: a #GtkTextBuffer
3542 * Called to indicate that the buffer operations between here and a
3543 * call to gtk_text_buffer_end_user_action() are part of a single
3544 * user-visible operation. The operations between
3545 * gtk_text_buffer_begin_user_action() and
3546 * gtk_text_buffer_end_user_action() can then be grouped when creating
3547 * an undo stack. #GtkTextBuffer maintains a count of calls to
3548 * gtk_text_buffer_begin_user_action() that have not been closed with
3549 * a call to gtk_text_buffer_end_user_action(), and emits the "begin_user_action"
3550 * and "end_user_action" signals only for the outermost pair of calls.
3551 * This allows you to build user actions from other user actions.
3553 * The "interactive" buffer mutation functions, such as
3554 * gtk_text_buffer_insert_interactive(), automatically call begin/end
3555 * user action around the buffer operations they perform, so there's
3556 * no need to add extra calls if you user action consists solely of a
3557 * single call to one of those functions.
3560 gtk_text_buffer_begin_user_action (GtkTextBuffer *buffer)
3562 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
3564 buffer->user_action_count += 1;
3566 if (buffer->user_action_count == 1)
3568 /* Outermost nested user action begin emits the signal */
3569 g_signal_emit (buffer, signals[BEGIN_USER_ACTION], 0);
3574 * gtk_text_buffer_end_user_action:
3575 * @buffer: a #GtkTextBuffer
3577 * Should be paired with a call to gtk_text_buffer_begin_user_action().
3578 * See that function for a full explanation.
3581 gtk_text_buffer_end_user_action (GtkTextBuffer *buffer)
3583 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
3584 g_return_if_fail (buffer->user_action_count > 0);
3586 buffer->user_action_count -= 1;
3588 if (buffer->user_action_count == 0)
3590 /* Ended the outermost-nested user action end, so emit the signal */
3591 g_signal_emit (buffer, signals[END_USER_ACTION], 0);
3596 * Logical attribute cache
3599 #define ATTR_CACHE_SIZE 2
3601 typedef struct _CacheEntry CacheEntry;
3606 PangoLogAttr *attrs;
3610 struct _GtkTextLogAttrCache
3612 gint chars_changed_stamp;
3613 CacheEntry entries[ATTR_CACHE_SIZE];
3617 free_log_attr_cache (GtkTextLogAttrCache *cache)
3620 while (i < ATTR_CACHE_SIZE)
3622 g_free (cache->entries[i].attrs);
3629 clear_log_attr_cache (GtkTextLogAttrCache *cache)
3632 while (i < ATTR_CACHE_SIZE)
3634 g_free (cache->entries[i].attrs);
3635 cache->entries[i].attrs = NULL;
3640 static PangoLogAttr*
3641 compute_log_attrs (const GtkTextIter *iter,
3647 gint char_len, byte_len;
3648 PangoLogAttr *attrs = NULL;
3653 gtk_text_iter_set_line_offset (&start, 0);
3654 gtk_text_iter_forward_line (&end);
3656 paragraph = gtk_text_iter_get_slice (&start, &end);
3657 char_len = g_utf8_strlen (paragraph, -1);
3658 byte_len = strlen (paragraph);
3660 g_assert (char_len > 0);
3663 *char_lenp = char_len;
3665 attrs = g_new (PangoLogAttr, char_len + 1);
3667 /* FIXME we need to follow PangoLayout and allow different language
3668 * tags within the paragraph
3670 pango_get_log_attrs (paragraph, byte_len, -1,
3671 gtk_text_iter_get_language (&start),
3680 /* The return value from this is valid until you call this a second time.
3683 _gtk_text_buffer_get_line_log_attrs (GtkTextBuffer *buffer,
3684 const GtkTextIter *anywhere_in_line,
3688 GtkTextLogAttrCache *cache;
3691 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
3692 g_return_val_if_fail (anywhere_in_line != NULL, NULL);
3694 /* special-case for empty last line in buffer */
3695 if (gtk_text_iter_is_end (anywhere_in_line) &&
3696 gtk_text_iter_get_line_offset (anywhere_in_line) == 0)
3703 /* FIXME we also need to recompute log attrs if the language tag at
3704 * the start of a paragraph changes
3707 if (buffer->log_attr_cache == NULL)
3709 buffer->log_attr_cache = g_new0 (GtkTextLogAttrCache, 1);
3710 buffer->log_attr_cache->chars_changed_stamp =
3711 _gtk_text_btree_get_chars_changed_stamp (get_btree (buffer));
3713 else if (buffer->log_attr_cache->chars_changed_stamp !=
3714 _gtk_text_btree_get_chars_changed_stamp (get_btree (buffer)))
3716 clear_log_attr_cache (buffer->log_attr_cache);
3719 cache = buffer->log_attr_cache;
3720 line = gtk_text_iter_get_line (anywhere_in_line);
3723 while (i < ATTR_CACHE_SIZE)
3725 if (cache->entries[i].attrs &&
3726 cache->entries[i].line == line)
3729 *char_len = cache->entries[i].char_len;
3730 return cache->entries[i].attrs;
3735 /* Not in cache; open up the first cache entry */
3736 if (cache->entries[ATTR_CACHE_SIZE-1].attrs)
3737 g_free (cache->entries[ATTR_CACHE_SIZE-1].attrs);
3739 g_memmove (cache->entries + 1, cache->entries,
3740 sizeof (CacheEntry) * (ATTR_CACHE_SIZE - 1));
3742 cache->entries[0].line = line;
3743 cache->entries[0].attrs = compute_log_attrs (anywhere_in_line,
3744 &cache->entries[0].char_len);
3747 *char_len = cache->entries[0].char_len;
3749 return cache->entries[0].attrs;
3753 _gtk_text_buffer_notify_will_remove_tag (GtkTextBuffer *buffer,
3756 /* This removes tag from the buffer, but DOESN'T emit the
3757 * remove_tag signal, because we can't afford to have user
3758 * code messing things up at this point; the tag MUST be removed
3762 _gtk_text_btree_notify_will_remove_tag (buffer->btree, tag);
3770 _gtk_text_buffer_spew (GtkTextBuffer *buffer)
3772 _gtk_text_btree_spew (get_btree (buffer));
3775 #define __GTK_TEXT_BUFFER_C__
3776 #include "gtkaliasdef.c"