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/.
30 #include "gtkclipboard.h"
31 #include "gtkinvisible.h"
32 #include "gtksignal.h"
33 #include "gtktextbuffer.h"
34 #include "gtktextbtree.h"
35 #include "gtktextiterprivate.h"
38 typedef struct _ClipboardRequest ClipboardRequest;
40 struct _ClipboardRequest
42 GtkTextBuffer *buffer;
44 gboolean default_editable;
45 gboolean is_clipboard;
46 gboolean replace_selection;
71 TARGET_TEXT_BUFFER_CONTENTS
74 static void gtk_text_buffer_init (GtkTextBuffer *tkxt_buffer);
75 static void gtk_text_buffer_class_init (GtkTextBufferClass *klass);
76 static void gtk_text_buffer_finalize (GObject *object);
79 static void gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer);
80 static void gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
84 gboolean interactive);
85 static void gtk_text_buffer_real_delete_text (GtkTextBuffer *buffer,
88 gboolean interactive);
89 static void gtk_text_buffer_real_apply_tag (GtkTextBuffer *buffer,
91 const GtkTextIter *start_char,
92 const GtkTextIter *end_char);
93 static void gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
95 const GtkTextIter *start_char,
96 const GtkTextIter *end_char);
97 static void gtk_text_buffer_real_changed (GtkTextBuffer *buffer);
99 static GtkTextBTree* get_btree (GtkTextBuffer *buffer);
100 static void free_log_attr_cache (GtkTextLogAttrCache *cache);
102 static GtkObjectClass *parent_class = NULL;
103 static guint signals[LAST_SIGNAL] = { 0 };
106 gtk_text_buffer_get_type (void)
108 static GtkType our_type = 0;
112 static const GtkTypeInfo our_info =
115 sizeof (GtkTextBuffer),
116 sizeof (GtkTextBufferClass),
117 (GtkClassInitFunc) gtk_text_buffer_class_init,
118 (GtkObjectInitFunc) gtk_text_buffer_init,
119 /* reserved_1 */ NULL,
120 /* reserved_2 */ NULL,
121 (GtkClassInitFunc) NULL
124 our_type = gtk_type_unique (GTK_TYPE_OBJECT, &our_info);
131 gtk_text_buffer_class_init (GtkTextBufferClass *klass)
133 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
134 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
136 parent_class = gtk_type_class (GTK_TYPE_OBJECT);
138 signals[INSERT_TEXT] =
139 gtk_signal_new ("insert_text",
141 GTK_CLASS_TYPE (object_class),
142 GTK_SIGNAL_OFFSET (GtkTextBufferClass, insert_text),
143 gtk_marshal_VOID__BOXED_BOXED_INT_BOOLEAN,
151 signals[DELETE_TEXT] =
152 gtk_signal_new ("delete_text",
154 GTK_CLASS_TYPE (object_class),
155 GTK_SIGNAL_OFFSET (GtkTextBufferClass, delete_text),
156 gtk_marshal_VOID__BOXED_BOXED_BOOLEAN,
164 gtk_signal_new ("changed",
166 GTK_CLASS_TYPE (object_class),
167 GTK_SIGNAL_OFFSET (GtkTextBufferClass, changed),
168 gtk_marshal_VOID__VOID,
172 signals[MODIFIED_CHANGED] =
173 gtk_signal_new ("modified_changed",
175 GTK_CLASS_TYPE (object_class),
176 GTK_SIGNAL_OFFSET (GtkTextBufferClass, modified_changed),
177 gtk_marshal_VOID__VOID,
182 gtk_signal_new ("mark_set",
184 GTK_CLASS_TYPE (object_class),
185 GTK_SIGNAL_OFFSET (GtkTextBufferClass, mark_set),
186 gtk_marshal_VOID__BOXED_OBJECT,
192 signals[MARK_DELETED] =
193 gtk_signal_new ("mark_deleted",
195 GTK_CLASS_TYPE (object_class),
196 GTK_SIGNAL_OFFSET (GtkTextBufferClass, mark_deleted),
197 gtk_marshal_VOID__OBJECT,
203 gtk_signal_new ("apply_tag",
205 GTK_CLASS_TYPE (object_class),
206 GTK_SIGNAL_OFFSET (GtkTextBufferClass, apply_tag),
207 gtk_marshal_VOID__OBJECT_BOXED_BOXED,
214 signals[REMOVE_TAG] =
215 gtk_signal_new ("remove_tag",
217 GTK_CLASS_TYPE (object_class),
218 GTK_SIGNAL_OFFSET (GtkTextBufferClass, remove_tag),
219 gtk_marshal_VOID__OBJECT_BOXED_BOXED,
226 gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
228 gobject_class->finalize = gtk_text_buffer_finalize;
230 klass->insert_text = gtk_text_buffer_real_insert_text;
231 klass->delete_text = gtk_text_buffer_real_delete_text;
232 klass->apply_tag = gtk_text_buffer_real_apply_tag;
233 klass->remove_tag = gtk_text_buffer_real_remove_tag;
234 klass->changed = gtk_text_buffer_real_changed;
238 gtk_text_buffer_init (GtkTextBuffer *buffer)
240 buffer->clipboard_contents = NULL;
244 * gtk_text_buffer_new:
245 * @table: a tag table, or NULL to create a new one
247 * Creates a new text buffer.
249 * Return value: a new text buffer
252 gtk_text_buffer_new (GtkTextTagTable *table)
254 GtkTextBuffer *text_buffer;
256 text_buffer = GTK_TEXT_BUFFER (gtk_type_new (gtk_text_buffer_get_type ()));
260 text_buffer->tag_table = table;
262 gtk_object_ref (GTK_OBJECT (text_buffer->tag_table));
263 gtk_object_sink (GTK_OBJECT (text_buffer->tag_table));
266 gtk_object_ref (GTK_OBJECT (text_buffer));
267 gtk_object_sink (GTK_OBJECT (text_buffer));
273 gtk_text_buffer_finalize (GObject *object)
275 GtkTextBuffer *buffer;
277 buffer = GTK_TEXT_BUFFER (object);
279 if (buffer->clipboard_contents)
281 g_object_unref (G_OBJECT (buffer->clipboard_contents));
282 buffer->clipboard_contents = NULL;
285 if (buffer->tag_table)
287 gtk_object_unref (GTK_OBJECT (buffer->tag_table));
288 buffer->tag_table = NULL;
293 gtk_text_btree_unref (buffer->btree);
294 buffer->btree = NULL;
297 if (buffer->log_attr_cache)
298 free_log_attr_cache (buffer->log_attr_cache);
300 buffer->log_attr_cache = NULL;
302 G_OBJECT_CLASS (parent_class)->finalize (object);
305 static GtkTextTagTable*
306 get_table (GtkTextBuffer *buffer)
308 if (buffer->tag_table == NULL)
310 buffer->tag_table = gtk_text_tag_table_new ();
312 gtk_object_ref (GTK_OBJECT (buffer->tag_table));
313 gtk_object_sink (GTK_OBJECT (buffer->tag_table));
316 return buffer->tag_table;
320 get_btree (GtkTextBuffer *buffer)
322 if (buffer->btree == NULL)
323 buffer->btree = gtk_text_btree_new (gtk_text_buffer_get_tag_table (buffer),
326 return buffer->btree;
330 _gtk_text_buffer_get_btree (GtkTextBuffer *buffer)
332 return get_btree (buffer);
336 * gtk_text_buffer_get_tag_table:
337 * @buffer: a #GtkTextBuffer
339 * Get the #GtkTextTagTable associated with this buffer.
341 * Return value: the buffer's tag table
344 gtk_text_buffer_get_tag_table (GtkTextBuffer *buffer)
346 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
348 return get_table (buffer);
352 * gtk_text_buffer_set_text:
353 * @buffer: a #GtkTextBuffer
354 * @text: UTF-8 text to insert
355 * @len: length of @text in bytes
357 * Deletes current contents of @buffer, and inserts @text instead. If
358 * @text doesn't end with a newline, a newline is added;
359 * #GtkTextBuffer contents must always end with a newline. If @text
360 * ends with a newline, the new buffer contents will be exactly
361 * @text. If @len is -1, @text must be nul-terminated.
364 gtk_text_buffer_set_text (GtkTextBuffer *buffer,
368 GtkTextIter start, end;
370 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
371 g_return_if_fail (text != NULL);
376 /* Chop newline, since the buffer will already have one
379 if (len > 0 && text[len-1] == '\n')
382 gtk_text_buffer_get_bounds (buffer, &start, &end);
384 gtk_text_buffer_delete (buffer, &start, &end);
388 gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
389 gtk_text_buffer_insert (buffer, &start, text, len);
399 gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
403 gboolean interactive)
405 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
406 g_return_if_fail (iter != NULL);
408 gtk_text_btree_insert (iter, text, len);
410 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
414 gtk_text_buffer_emit_insert (GtkTextBuffer *buffer,
418 gboolean interactive)
420 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
421 g_return_if_fail (iter != NULL);
422 g_return_if_fail (text != NULL);
429 gtk_signal_emit (GTK_OBJECT (buffer), signals[INSERT_TEXT],
430 iter, text, len, interactive);
435 * gtk_text_buffer_insert:
436 * @buffer: a #GtkTextBuffer
437 * @iter: a position in the buffer
438 * @text: UTF-8 format text to insert
439 * @len: length of text in bytes, or -1
441 * Inserts @len bytes of @text at position @iter. If @len is -1,
442 * @text must be nul-terminated and will be inserted in its
443 * entirety. Emits the "insert_text" signal; insertion actually occurs
444 * in the default handler for the signal. @iter is invalidated when
445 * insertion occurs (because the buffer contents change), but the
446 * default signal handler revalidates it to point to the end of the
451 gtk_text_buffer_insert (GtkTextBuffer *buffer,
456 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
457 g_return_if_fail (iter != NULL);
458 g_return_if_fail (text != NULL);
460 gtk_text_buffer_emit_insert (buffer, iter, text, len, FALSE);
464 * gtk_text_buffer_insert_at_cursor:
465 * @buffer: a #GtkTextBuffer
466 * @text: some text in UTF-8 format
467 * @len: length of text, in bytes
469 * Simply calls gtk_text_buffer_insert (), using the current
470 * cursor position as the insertion point.
473 gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
479 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
480 g_return_if_fail (text != NULL);
482 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
483 gtk_text_buffer_get_mark (buffer,
486 gtk_text_buffer_insert (buffer, &iter, text, len);
490 * gtk_text_buffer_insert_interactive:
491 * @buffer: a #GtkTextBuffer
492 * @iter: a position in @buffer
493 * @text: some UTF-8 text
494 * @len: length of text in bytes, or -1
495 * @default_editable: default editability of buffer
497 * Like gtk_text_buffer_insert (), but the insertion will not occur if
498 * @iter is at a non-editable location in the buffer. Usually you
499 * want to prevent insertions at ineditable locations if the insertion
500 * results from a user action (is interactive).
502 * @default_editable indicates the editability of text that doesn't
503 * have a tag affecting editability applied to it. Typically the
504 * result of gtk_text_view_get_editable() is appropriate here.
506 * Return value: whether text was actually inserted
509 gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer,
513 gboolean default_editable)
515 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
516 g_return_val_if_fail (text != NULL, FALSE);
518 if (gtk_text_iter_editable (iter, default_editable))
520 gtk_text_buffer_emit_insert (buffer, iter, text, len, TRUE);
528 * gtk_text_buffer_insert_interactive_at_cursor:
529 * @buffer: a #GtkTextBuffer
530 * @text: text in UTF-8 format
531 * @len: length of text in bytes, or -1
532 * @default_editable: default editability of buffer
534 * Calls gtk_text_buffer_insert_interactive () at the cursor
537 * @default_editable indicates the editability of text that doesn't
538 * have a tag affecting editability applied to it. Typically the
539 * result of gtk_text_view_get_editable() is appropriate here.
541 * Return value: whether text was actually inserted
544 gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer,
547 gboolean default_editable)
551 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
552 g_return_val_if_fail (text != NULL, FALSE);
554 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
555 gtk_text_buffer_get_mark (buffer,
558 return gtk_text_buffer_insert_interactive (buffer, &iter, text, len,
563 possibly_not_text (gunichar ch,
566 return ch == GTK_TEXT_UNKNOWN_CHAR;
570 insert_text_range (GtkTextBuffer *buffer,
572 const GtkTextIter *orig_start,
573 const GtkTextIter *orig_end,
574 gboolean interactive)
578 text = gtk_text_iter_get_text (orig_start, orig_end);
580 gtk_text_buffer_emit_insert (buffer, iter, text, -1, interactive);
585 typedef struct _Range Range;
588 GtkTextBuffer *buffer;
589 GtkTextMark *start_mark;
590 GtkTextMark *end_mark;
591 GtkTextMark *whole_end_mark;
592 GtkTextIter *range_start;
593 GtkTextIter *range_end;
594 GtkTextIter *whole_end;
598 save_range (GtkTextIter *range_start,
599 GtkTextIter *range_end,
600 GtkTextIter *whole_end)
604 r = g_new (Range, 1);
606 r->buffer = gtk_text_iter_get_buffer (range_start);
607 g_object_ref (G_OBJECT (r->buffer));
610 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
615 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
621 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
626 r->range_start = range_start;
627 r->range_end = range_end;
628 r->whole_end = whole_end;
634 restore_range (Range *r)
636 gtk_text_buffer_get_iter_at_mark (r->buffer,
640 gtk_text_buffer_get_iter_at_mark (r->buffer,
644 gtk_text_buffer_get_iter_at_mark (r->buffer,
648 gtk_text_buffer_delete_mark (r->buffer, r->start_mark);
649 gtk_text_buffer_delete_mark (r->buffer, r->end_mark);
650 gtk_text_buffer_delete_mark (r->buffer, r->whole_end_mark);
652 g_object_unref (G_OBJECT (r->buffer));
657 insert_range_untagged (GtkTextBuffer *buffer,
659 const GtkTextIter *orig_start,
660 const GtkTextIter *orig_end,
661 gboolean interactive)
663 GtkTextIter range_start;
664 GtkTextIter range_end;
665 GtkTextIter start, end;
666 GtkTextBuffer *src_buffer;
669 if (gtk_text_iter_equal (orig_start, orig_end))
675 src_buffer = gtk_text_iter_get_buffer (&start);
682 if (gtk_text_iter_equal (&range_start, &range_end))
684 /* Figure out how to move forward */
686 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
688 if (gtk_text_iter_equal (&range_end, &end))
690 /* nothing left to do */
693 else if (gtk_text_iter_get_char (&range_end) == GTK_TEXT_UNKNOWN_CHAR)
695 GdkPixbuf *pixbuf = NULL;
696 GtkTextChildAnchor *anchor = NULL;
697 pixbuf = gtk_text_iter_get_pixbuf (&range_end);
698 anchor = gtk_text_iter_get_child_anchor (&range_end);
702 r = save_range (&range_start,
706 gtk_text_buffer_insert_pixbuf (buffer,
713 gtk_text_iter_forward_char (&range_end);
715 range_start = range_end;
719 /* Just skip anchors */
721 gtk_text_iter_forward_char (&range_end);
722 range_start = range_end;
726 /* The GTK_TEXT_UNKNOWN_CHAR was in a text segment, so
729 gtk_text_iter_forward_find_char (&range_end,
730 possibly_not_text, NULL,
733 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
738 /* Text segment starts here, so forward search to
739 * find its possible endpoint
741 gtk_text_iter_forward_find_char (&range_end,
742 possibly_not_text, NULL,
745 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
750 r = save_range (&range_start,
754 insert_text_range (buffer,
763 range_start = range_end;
769 gtk_text_buffer_real_insert_range (GtkTextBuffer *buffer,
771 const GtkTextIter *orig_start,
772 const GtkTextIter *orig_end,
773 gboolean interactive)
775 /* Find each range of uniformly-tagged text, insert it,
776 * then apply the tags.
778 GtkTextIter start = *orig_start;
779 GtkTextIter end = *orig_end;
780 GtkTextIter range_start;
781 GtkTextIter range_end;
782 GtkTextBuffer *src_buffer;
785 if (gtk_text_iter_equal (orig_start, orig_end))
788 src_buffer = gtk_text_iter_get_buffer (orig_start);
790 gtk_text_iter_reorder (&start, &end);
798 GtkTextIter start_iter;
802 if (gtk_text_iter_equal (&range_start, &end))
803 break; /* All done */
805 g_assert (gtk_text_iter_compare (&range_start, &end) < 0);
807 gtk_text_iter_forward_to_tag_toggle (&range_end, NULL);
809 g_assert (!gtk_text_iter_equal (&range_start, &range_end));
811 /* Clamp to the end iterator */
812 if (gtk_text_iter_compare (&range_end, &end) > 0)
815 /* We have a range with unique tags; insert it, and
818 start_offset = gtk_text_iter_get_offset (iter);
820 r = save_range (&range_start, &range_end, &end);
822 insert_range_untagged (buffer, iter, &range_start, &range_end, interactive);
827 gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_offset);
829 tags = gtk_text_iter_get_tags (&range_start);
831 while (tmp_list != NULL)
833 gtk_text_buffer_apply_tag (buffer,
838 tmp_list = g_slist_next (tmp_list);
842 range_start = range_end;
847 * gtk_text_buffer_insert_range:
848 * @buffer: a #GtkTextBuffer
849 * @iter: a position in @buffer
850 * @start: a position in a #GtkTextBuffer
851 * @end: another position in the same buffer as @start
853 * Copies text, tags, and pixbufs between @start and @end (the order
854 * of @start and @end doesn't matter) and inserts the copy at @iter.
855 * Used instead of simply getting/inserting text because it preserves
856 * images and tags. If @start and @end are in a different buffer from
857 * @buffer, the two buffers must share the same tag table.
859 * Implemented via emissions of the insert_text and apply_tag signals,
863 gtk_text_buffer_insert_range (GtkTextBuffer *buffer,
865 const GtkTextIter *start,
866 const GtkTextIter *end)
868 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
869 g_return_if_fail (iter != NULL);
870 g_return_if_fail (start != NULL);
871 g_return_if_fail (end != NULL);
872 g_return_if_fail (gtk_text_iter_get_buffer (start) ==
873 gtk_text_iter_get_buffer (end));
874 g_return_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
877 gtk_text_buffer_real_insert_range (buffer, iter, start, end, FALSE);
881 * gtk_text_buffer_insert_range_interactive:
882 * @buffer: a #GtkTextBuffer
883 * @iter: a position in @buffer
884 * @start: a position in a #GtkTextBuffer
885 * @end: another position in the same buffer as @start
886 * @default_editable: default editability of the buffer
888 * Same as gtk_text_buffer_insert_range(), but does nothing if the
889 * insertion point isn't editable. The @default_editable parameter
890 * indicates whether the text is editable at @iter if no tags
891 * enclosing @iter affect editability. Typically the result of
892 * gtk_text_view_get_editable() is appropriate here.
894 * Returns: whether an insertion was possible at @iter
897 gtk_text_buffer_insert_range_interactive (GtkTextBuffer *buffer,
899 const GtkTextIter *start,
900 const GtkTextIter *end,
901 gboolean default_editable)
903 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
904 g_return_val_if_fail (iter != NULL, FALSE);
905 g_return_val_if_fail (start != NULL, FALSE);
906 g_return_val_if_fail (end != NULL, FALSE);
907 g_return_val_if_fail (gtk_text_iter_get_buffer (start) ==
908 gtk_text_iter_get_buffer (end), FALSE);
909 g_return_val_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
910 buffer->tag_table, FALSE);
913 if (gtk_text_iter_editable (iter, default_editable))
915 gtk_text_buffer_real_insert_range (buffer, iter, start, end, TRUE);
923 * gtk_text_buffer_insert_with_tags:
924 * @buffer: a #GtkTextBuffer
925 * @iter: an iterator in @buffer
927 * @len: length of @text, or -1
928 * @first_tag: first tag to apply to @text
929 * @Varargs: NULL-terminated list of tags to apply
931 * Inserts @text into @buffer at @iter, applying the list of tags to
932 * the newly-inserted text. The last tag specified must be NULL to
933 * terminate the list. Equivalent to calling gtk_text_buffer_insert (),
934 * then gtk_text_buffer_apply_tag () on the inserted text;
935 * gtk_text_buffer_insert_with_tags () is just a convenience function.
938 gtk_text_buffer_insert_with_tags (GtkTextBuffer *buffer,
942 GtkTextTag *first_tag,
950 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
951 g_return_if_fail (iter != NULL);
952 g_return_if_fail (text != NULL);
954 start_offset = gtk_text_iter_get_offset (iter);
956 gtk_text_buffer_insert (buffer, iter, text, len);
958 if (first_tag == NULL)
961 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
963 va_start (args, first_tag);
967 gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
969 tag = va_arg (args, GtkTextTag*);
976 * gtk_text_buffer_insert_with_tags_by_name:
977 * @buffer: a #GtkTextBuffer
978 * @iter: position in @buffer
980 * @len: length of @text, or -1
981 * @first_tag_name: name of a tag to apply to @text
982 * @Varargs: more tag names
984 * Same as gtk_text_buffer_insert_with_tags (), but allows you
985 * to pass in tag names instead of tag objects.
988 gtk_text_buffer_insert_with_tags_by_name (GtkTextBuffer *buffer,
992 const gchar *first_tag_name,
998 const gchar *tag_name;
1000 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1001 g_return_if_fail (iter != NULL);
1002 g_return_if_fail (text != NULL);
1004 start_offset = gtk_text_iter_get_offset (iter);
1006 gtk_text_buffer_insert (buffer, iter, text, len);
1008 if (first_tag_name == NULL)
1011 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
1013 va_start (args, first_tag_name);
1014 tag_name = first_tag_name;
1019 tag = gtk_text_tag_table_lookup (buffer->tag_table,
1024 g_warning ("%s: no tag with name '%s'!", G_STRLOC, tag_name);
1028 gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
1030 tag_name = va_arg (args, const gchar*);
1042 gtk_text_buffer_real_delete_text (GtkTextBuffer *buffer,
1045 gboolean interactive)
1047 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1048 g_return_if_fail (start != NULL);
1049 g_return_if_fail (end != NULL);
1051 gtk_text_btree_delete (start, end);
1053 /* may have deleted the selection... */
1054 gtk_text_buffer_update_primary_selection (buffer);
1056 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
1060 gtk_text_buffer_emit_delete (GtkTextBuffer *buffer,
1063 gboolean interactive)
1065 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1066 g_return_if_fail (start != NULL);
1067 g_return_if_fail (end != NULL);
1069 if (gtk_text_iter_equal (start, end))
1072 gtk_text_iter_reorder (start, end);
1074 /* Somewhat annoyingly, if you try to delete the final newline
1075 * the BTree will put it back; which means you can't deduce the
1076 * final contents of the buffer purely by monitoring insert/delete
1077 * signals on the buffer. But if you delete the final newline, any
1078 * tags on the newline will go away, oddly. See comment in
1079 * gtktextbtree.c. This is all sort of annoying, but really hard
1082 gtk_signal_emit (GTK_OBJECT (buffer),
1083 signals[DELETE_TEXT],
1089 * gtk_text_buffer_delete:
1090 * @buffer: a #GtkTextBuffer
1091 * @start: a position in @buffer
1092 * @end: another position in @buffer
1094 * Deletes text between @start and @end. The order of @start and @end
1095 * is not actually relevant; gtk_text_buffer_delete () will reorder
1096 * them. This function actually emits the "delete_text" signal, and
1097 * the default handler of that signal deletes the text. Because the
1098 * buffer is modified, all outstanding iterators become invalid after
1099 * calling this function; however, the @start and @end will be
1100 * re-initialized to point to the location where text was deleted.
1102 * Note that the final newline in the buffer may not be deleted; a
1103 * #GtkTextBuffer always contains at least one newline. You can
1104 * safely include the final newline in the range [@start,@end) but it
1105 * won't be affected by the deletion.
1109 gtk_text_buffer_delete (GtkTextBuffer *buffer,
1113 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1114 g_return_if_fail (start != NULL);
1115 g_return_if_fail (end != NULL);
1117 gtk_text_buffer_emit_delete (buffer, start, end, FALSE);
1121 * gtk_text_buffer_delete_interactive:
1122 * @buffer: a #GtkTextBuffer
1123 * @start_iter: start of range to delete
1124 * @end_iter: end of range
1125 * @default_editable: whether the buffer is editable by default
1127 * Deletes all <emphasis>editable</emphasis> text in the given range.
1128 * Calls gtk_text_buffer_delete () for each editable sub-range of
1129 * [@start,@end). @start and @end are revalidated to point to
1130 * the location of the last deleted range, or left untouched if
1131 * no text was deleted.
1133 * Return value: whether some text was actually deleted
1136 gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
1137 GtkTextIter *start_iter,
1138 GtkTextIter *end_iter,
1139 gboolean default_editable)
1141 GtkTextMark *end_mark;
1142 GtkTextMark *start_mark;
1144 gboolean current_state;
1145 gboolean deleted_stuff = FALSE;
1147 /* Delete all editable text in the range start_iter, end_iter */
1149 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1150 g_return_val_if_fail (start_iter != NULL, FALSE);
1151 g_return_val_if_fail (end_iter != NULL, FALSE);
1153 gtk_text_iter_reorder (start_iter, end_iter);
1155 start_mark = gtk_text_buffer_create_mark (buffer, NULL,
1157 end_mark = gtk_text_buffer_create_mark (buffer, NULL,
1161 current_state = gtk_text_iter_editable (&iter, default_editable);
1166 gboolean done = FALSE;
1169 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
1171 gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark);
1173 if (gtk_text_iter_compare (&iter, &end) >= 0)
1176 iter = end; /* clamp to the last boundary */
1179 new_state = gtk_text_iter_editable (&iter, default_editable);
1181 if (current_state == new_state)
1187 /* We're ending an editable region. Delete said region. */
1190 gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1192 gtk_text_buffer_emit_delete (buffer, &start, &iter, TRUE);
1194 deleted_stuff = TRUE;
1196 /* revalidate user's iterators. */
1197 *start_iter = start;
1207 if (current_state && !new_state)
1209 /* End of an editable region. Delete it. */
1212 gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1214 gtk_text_buffer_emit_delete (buffer, &start, &iter, TRUE);
1216 current_state = FALSE;
1217 deleted_stuff = TRUE;
1219 /* revalidate user's iterators. */
1220 *start_iter = start;
1225 /* We are at the start of an editable region. We won't be deleting
1226 * the previous region. Move start mark to start of this region.
1229 g_assert (!current_state && new_state);
1231 gtk_text_buffer_move_mark (buffer, start_mark,
1235 current_state = TRUE;
1243 gtk_text_buffer_delete_mark (buffer, start_mark);
1244 gtk_text_buffer_delete_mark (buffer, end_mark);
1246 return deleted_stuff;
1250 * Extracting textual buffer contents
1254 * gtk_text_buffer_get_text:
1255 * @buffer: a #GtkTextBuffer
1256 * @start: start of a range
1257 * @end: end of a range
1258 * @include_hidden_chars: whether to include invisible text
1260 * Returns the text in the range [@start,@end). Excludes undisplayed
1261 * text (text marked with tags that set the invisibility attribute) if
1262 * @include_hidden_chars is FALSE. Does not include characters
1263 * representing embedded images, so byte and character indexes into
1264 * the returned string do <emphasis>not</emphasis> correspond to byte
1265 * and character indexes into the buffer. Contrast with
1266 * gtk_text_buffer_get_slice ().
1268 * Return value: an allocated UTF-8 string
1271 gtk_text_buffer_get_text (GtkTextBuffer *buffer,
1272 const GtkTextIter *start,
1273 const GtkTextIter *end,
1274 gboolean include_hidden_chars)
1276 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1277 g_return_val_if_fail (start != NULL, NULL);
1278 g_return_val_if_fail (end != NULL, NULL);
1280 if (include_hidden_chars)
1281 return gtk_text_iter_get_text (start, end);
1283 return gtk_text_iter_get_visible_text (start, end);
1287 * gtk_text_buffer_get_slice:
1288 * @buffer: a #GtkTextBuffer
1289 * @start: start of a range
1290 * @end: end of a range
1291 * @include_hidden_chars: whether to include invisible text
1293 * Returns the text in the range [@start,@end). Excludes undisplayed
1294 * text (text marked with tags that set the invisibility attribute) if
1295 * @include_hidden_chars is FALSE. The returned string includes a
1296 * 0xFFFC character whenever the buffer contains
1297 * embedded images, so byte and character indexes into
1298 * the returned string <emphasis>do</emphasis> correspond to byte
1299 * and character indexes into the buffer. Contrast with
1300 * gtk_text_buffer_get_text (). Note that 0xFFFC can occur in normal
1301 * text as well, so it is not a reliable indicator that a pixbuf or
1302 * widget is in the buffer.
1304 * Return value: an allocated UTF-8 string
1307 gtk_text_buffer_get_slice (GtkTextBuffer *buffer,
1308 const GtkTextIter *start,
1309 const GtkTextIter *end,
1310 gboolean include_hidden_chars)
1312 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1313 g_return_val_if_fail (start != NULL, NULL);
1314 g_return_val_if_fail (end != NULL, NULL);
1316 if (include_hidden_chars)
1317 return gtk_text_iter_get_slice (start, end);
1319 return gtk_text_iter_get_visible_slice (start, end);
1327 gtk_text_buffer_insert_pixbuf (GtkTextBuffer *buffer,
1331 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1332 g_return_if_fail (iter != NULL);
1333 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1335 gtk_text_btree_insert_pixbuf (iter, pixbuf);
1337 /* FIXME pixbuf-specific signal like insert_text */
1339 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
1347 gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
1350 GtkTextChildAnchor *anchor;
1352 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1353 g_return_val_if_fail (iter != NULL, NULL);
1355 anchor = gtk_text_btree_create_child_anchor (iter);
1357 /* FIXME child-anchor-specific signal */
1359 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
1370 gtk_text_buffer_mark_set (GtkTextBuffer *buffer,
1371 const GtkTextIter *location,
1374 /* IMO this should NOT work like insert_text and delete_text,
1375 where the real action happens in the default handler.
1377 The reason is that the default handler would be _required_,
1378 i.e. the whole widget would start breaking and segfaulting
1379 if the default handler didn't get run. So you can't really
1380 override the default handler or stop the emission; that is,
1381 this signal is purely for notification, and not to allow users
1382 to modify the default behavior. */
1384 g_object_ref (G_OBJECT (mark));
1386 gtk_signal_emit (GTK_OBJECT (buffer),
1391 g_object_unref (G_OBJECT (mark));
1395 * gtk_text_buffer_set_mark:
1396 * @buffer: a #GtkTextBuffer
1397 * @mark_name: name of the mark
1398 * @iter: location for the mark.
1399 * @left_gravity: if the mark is created by this function, gravity for the new
1401 * @should_exist: if %TRUE, warn if the mark does not exist, and return
1404 * Move the mark to the given position, if not @should_exist, create the mark.
1406 * Return value: mark
1409 gtk_text_buffer_set_mark (GtkTextBuffer *buffer,
1410 GtkTextMark *existing_mark,
1411 const gchar *mark_name,
1412 const GtkTextIter *iter,
1413 gboolean left_gravity,
1414 gboolean should_exist)
1416 GtkTextIter location;
1419 mark = gtk_text_btree_set_mark (get_btree (buffer),
1426 if (gtk_text_btree_mark_is_insert (get_btree (buffer), mark) ||
1427 gtk_text_btree_mark_is_selection_bound (get_btree (buffer), mark))
1429 gtk_text_buffer_update_primary_selection (buffer);
1432 gtk_text_btree_get_iter_at_mark (get_btree (buffer),
1436 gtk_text_buffer_mark_set (buffer, &location, mark);
1442 * gtk_text_buffer_create_mark:
1443 * @buffer: a #GtkTextBuffer
1444 * @mark_name: name for mark, or %NULL
1445 * @where: location to place mark
1446 * @left_gravity: whether the mark has left gravity
1448 * Creates a mark at position @where. If @mark_name is %NULL, the mark
1449 * is anonymous; otherwise, the mark can be retrieved by name using
1450 * gtk_text_buffer_get_mark (). If a mark has left gravity, and text is
1451 * inserted at the mark's current location, the mark will be moved to
1452 * the left of the newly-inserted text. If the mark has right gravity
1453 * (@left_gravity = %FALSE), the mark will end up on the right of
1454 * newly-inserted text. The standard left-to-right cursor is a mark
1455 * with right gravity (when you type, the cursor stays on the right
1456 * side of the text you're typing).
1458 * The caller of this function does <emphasis>not</emphasis> own a reference
1459 * to the returned #GtkTextMark, so you can ignore the return value
1460 * if you like. Marks are owned by the buffer and go away when the
1463 * Emits the "mark_set" signal as notification of the mark's initial
1466 * Return value: the new #GtkTextMark object
1469 gtk_text_buffer_create_mark (GtkTextBuffer *buffer,
1470 const gchar *mark_name,
1471 const GtkTextIter *where,
1472 gboolean left_gravity)
1474 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1476 return gtk_text_buffer_set_mark (buffer, NULL, mark_name, where,
1477 left_gravity, FALSE);
1481 * gtk_text_buffer_move_mark:
1482 * @buffer: a #GtkTextBuffer
1483 * @mark: a #GtkTextMark
1484 * @where: new location for @mark in @buffer
1486 * Moves @mark to the new location @where. Emits the "mark_set" signal
1487 * as notification of the move.
1490 gtk_text_buffer_move_mark (GtkTextBuffer *buffer,
1492 const GtkTextIter *where)
1494 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1495 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1496 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1498 gtk_text_buffer_set_mark (buffer, mark, NULL, where, FALSE, TRUE);
1502 * gtk_text_buffer_get_iter_at_mark:
1503 * @buffer: a #GtkTextBuffer
1504 * @iter: iterator to initialize
1505 * @mark: a #GtkTextMark in @buffer
1507 * Initializes @iter with the current position of @mark.
1510 gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer,
1514 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1515 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1516 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1518 gtk_text_btree_get_iter_at_mark (get_btree (buffer),
1524 * gtk_text_buffer_delete_mark:
1525 * @buffer: a #GtkTextBuffer
1526 * @mark: a #GtkTextMark in @buffer
1528 * Deletes @mark, so that it's no longer located anywhere in the
1529 * buffer. Removes the reference the buffer holds to the mark, so if
1530 * you haven't called g_object_ref () on the mark, it will be freed. Even
1531 * if the mark isn't freed, most operations on @mark become
1532 * invalid. There is no way to undelete a
1533 * mark. gtk_text_mark_get_deleted () will return TRUE after this
1534 * function has been called on a mark; gtk_text_mark_get_deleted ()
1535 * indicates that a mark no longer belongs to a buffer. The "mark_deleted"
1536 * signal will be emitted as notification after the mark is deleted.
1539 gtk_text_buffer_delete_mark (GtkTextBuffer *buffer,
1542 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1543 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1544 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1546 g_object_ref (G_OBJECT (mark));
1548 gtk_text_btree_remove_mark (get_btree (buffer), mark);
1550 /* See rationale above for MARK_SET on why we emit this after
1551 * removing the mark, rather than removing the mark in a default
1554 gtk_signal_emit (GTK_OBJECT (buffer), signals[MARK_DELETED],
1557 g_object_unref (G_OBJECT (mark));
1561 * gtk_text_buffer_get_mark:
1562 * @buffer: a #GtkTextBuffer
1563 * @name: a mark name
1565 * Returns the mark named @name in buffer @buffer, or NULL if no such
1566 * mark exists in the buffer.
1568 * Return value: a #GtkTextMark, or NULL
1571 gtk_text_buffer_get_mark (GtkTextBuffer *buffer,
1576 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1577 g_return_val_if_fail (name != NULL, NULL);
1579 mark = gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1586 * gtk_text_buffer_move_mark_by_name:
1587 * @buffer: a #GtkTextBuffer
1588 * @name: name of a mark
1589 * @where: new location for mark
1591 * Moves the mark named @name (which must exist) to location @where.
1592 * See gtk_text_buffer_move_mark () for details.
1595 gtk_text_buffer_move_mark_by_name (GtkTextBuffer *buffer,
1597 const GtkTextIter *where)
1601 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1602 g_return_if_fail (name != NULL);
1604 mark = gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1608 g_warning ("%s: no mark named '%s'", G_STRLOC, name);
1612 gtk_text_buffer_move_mark (buffer, mark, where);
1616 * gtk_text_buffer_delete_mark_by_name:
1617 * @buffer: a #GtkTextBuffer
1618 * @name: name of a mark in @buffer
1620 * Deletes the mark named @name; the mark must exist. See
1621 * gtk_text_buffer_delete_mark () for details.
1624 gtk_text_buffer_delete_mark_by_name (GtkTextBuffer *buffer,
1629 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1630 g_return_if_fail (name != NULL);
1632 mark = gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1636 g_warning ("%s: no mark named '%s'", G_STRLOC, name);
1640 gtk_text_buffer_delete_mark (buffer, mark);
1644 * gtk_text_buffer_get_insert:
1645 * @buffer: a #GtkTextBuffer
1647 * Returns the mark that represents the cursor (insertion point).
1648 * Equivalent to calling gtk_text_buffer_get_mark () to get the mark
1649 * name "insert," but very slightly more efficient, and involves less
1652 * Return value: insertion point mark
1655 gtk_text_buffer_get_insert (GtkTextBuffer *buffer)
1657 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1659 /* FIXME use struct member in btree */
1660 return gtk_text_buffer_get_mark (buffer, "insert");
1664 * gtk_text_buffer_get_selection_bound:
1665 * @buffer: a #GtkTextBuffer
1667 * Returns the mark that represents the selection bound. Equivalent
1668 * to calling gtk_text_buffer_get_mark () to get the mark name
1669 * "selection_bound," but very slightly more efficient, and involves
1672 * The currently-selected text in @buffer is the region between the
1673 * "selection_bound" and "insert" marks. If "selection_bound" and
1674 * "insert" are in the same place, then there is no current selection.
1675 * gtk_text_buffer_get_selection_bounds () is another convenient function
1676 * for handling the selection, if you just want to know whether there's a
1677 * selection and what its bounds are.
1679 * Return value: selection bound mark
1682 gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer)
1684 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1686 /* FIXME use struct member in btree */
1687 return gtk_text_buffer_get_mark (buffer, "selection_bound");
1691 gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer *buffer,
1693 GtkTextChildAnchor *anchor)
1695 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1696 g_return_if_fail (iter != NULL);
1697 g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
1698 g_return_if_fail (!gtk_text_child_anchor_get_deleted (anchor));
1700 gtk_text_btree_get_iter_at_child_anchor (get_btree (buffer),
1706 * gtk_text_buffer_place_cursor:
1707 * @buffer: a #GtkTextBuffer
1708 * @where: where to put the cursor
1710 * This function moves the "insert" and "selection_bound" marks
1711 * simultaneously. If you move them to the same place in two steps
1712 * with gtk_text_buffer_move_mark (), you will temporarily select a
1713 * region in between their old and new locations, which can be pretty
1714 * inefficient since the temporarily-selected region will force stuff
1715 * to be recalculated. This function moves them as a unit, which can
1719 gtk_text_buffer_place_cursor (GtkTextBuffer *buffer,
1720 const GtkTextIter *where)
1724 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1728 if (gtk_text_iter_is_last (&real))
1729 gtk_text_iter_backward_char (&real);
1731 gtk_text_btree_place_cursor (get_btree (buffer), &real);
1732 gtk_text_buffer_mark_set (buffer, &real,
1733 gtk_text_buffer_get_mark (buffer,
1735 gtk_text_buffer_mark_set (buffer, &real,
1736 gtk_text_buffer_get_mark (buffer,
1737 "selection_bound"));
1745 * gtk_text_buffer_create_tag:
1746 * @buffer: a #GtkTextBuffer
1747 * @tag_name: name of the new tag, or %NULL
1749 * Creates a tag and adds it to the tag table for @buffer.
1750 * Equivalent to calling gtk_text_tag_new () and then adding the
1751 * tag to the buffer's tag table. The returned tag has its refcount
1752 * incremented, as if you'd called gtk_text_tag_new ().
1754 * If @tag_name is %NULL, the tag is anonymous.
1756 * Return value: a new tag
1759 gtk_text_buffer_create_tag (GtkTextBuffer *buffer,
1760 const gchar *tag_name)
1764 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1766 tag = gtk_text_tag_new (tag_name);
1768 gtk_text_tag_table_add (get_table (buffer), tag);
1774 gtk_text_buffer_real_apply_tag (GtkTextBuffer *buffer,
1776 const GtkTextIter *start,
1777 const GtkTextIter *end)
1779 gtk_text_btree_tag (start, end, tag, TRUE);
1783 gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
1785 const GtkTextIter *start,
1786 const GtkTextIter *end)
1788 gtk_text_btree_tag (start, end, tag, FALSE);
1792 gtk_text_buffer_real_changed (GtkTextBuffer *buffer)
1794 gtk_text_buffer_set_modified (buffer, TRUE);
1798 gtk_text_buffer_emit_tag (GtkTextBuffer *buffer,
1801 const GtkTextIter *start,
1802 const GtkTextIter *end)
1804 GtkTextIter start_tmp = *start;
1805 GtkTextIter end_tmp = *end;
1807 g_return_if_fail (tag != NULL);
1809 gtk_text_iter_reorder (&start_tmp, &end_tmp);
1812 gtk_signal_emit (GTK_OBJECT (buffer), signals[APPLY_TAG],
1813 tag, &start_tmp, &end_tmp);
1815 gtk_signal_emit (GTK_OBJECT (buffer), signals[REMOVE_TAG],
1816 tag, &start_tmp, &end_tmp);
1821 gtk_text_buffer_apply_tag (GtkTextBuffer *buffer,
1823 const GtkTextIter *start,
1824 const GtkTextIter *end)
1826 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1827 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
1828 g_return_if_fail (start != NULL);
1829 g_return_if_fail (end != NULL);
1831 gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
1835 gtk_text_buffer_remove_tag (GtkTextBuffer *buffer,
1837 const GtkTextIter *start,
1838 const GtkTextIter *end)
1841 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1842 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
1843 g_return_if_fail (start != NULL);
1844 g_return_if_fail (end != NULL);
1846 gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
1851 gtk_text_buffer_apply_tag_by_name (GtkTextBuffer *buffer,
1853 const GtkTextIter *start,
1854 const GtkTextIter *end)
1858 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1859 g_return_if_fail (name != NULL);
1860 g_return_if_fail (start != NULL);
1861 g_return_if_fail (end != NULL);
1863 tag = gtk_text_tag_table_lookup (get_table (buffer),
1868 g_warning ("Unknown tag `%s'", name);
1872 gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
1876 gtk_text_buffer_remove_tag_by_name (GtkTextBuffer *buffer,
1878 const GtkTextIter *start,
1879 const GtkTextIter *end)
1883 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1884 g_return_if_fail (name != NULL);
1885 g_return_if_fail (start != NULL);
1886 g_return_if_fail (end != NULL);
1888 tag = gtk_text_tag_table_lookup (get_table (buffer),
1893 g_warning ("Unknown tag `%s'", name);
1897 gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
1902 * Obtain various iterators
1906 gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
1911 g_return_if_fail (iter != NULL);
1912 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1914 gtk_text_btree_get_iter_at_line_char (get_btree (buffer),
1915 iter, line_number, char_offset);
1919 gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
1924 g_return_if_fail (iter != NULL);
1925 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1927 gtk_text_btree_get_iter_at_line_byte (get_btree (buffer),
1928 iter, line_number, byte_index);
1932 gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
1936 g_return_if_fail (iter != NULL);
1937 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1939 gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
1943 gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
1947 g_return_if_fail (iter != NULL);
1948 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1950 gtk_text_btree_get_iter_at_char (get_btree (buffer), iter, char_offset);
1954 gtk_text_buffer_get_last_iter (GtkTextBuffer *buffer,
1957 g_return_if_fail (iter != NULL);
1958 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1960 gtk_text_btree_get_last_iter (get_btree (buffer), iter);
1964 gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
1968 g_return_if_fail (start != NULL);
1969 g_return_if_fail (end != NULL);
1970 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1972 gtk_text_btree_get_iter_at_char (get_btree (buffer), start, 0);
1973 gtk_text_btree_get_last_iter (get_btree (buffer), end);
1981 gtk_text_buffer_modified (GtkTextBuffer *buffer)
1983 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1985 return buffer->modified;
1989 gtk_text_buffer_set_modified (GtkTextBuffer *buffer,
1992 gboolean fixed_setting;
1994 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1996 fixed_setting = setting != FALSE;
1998 if (buffer->modified == fixed_setting)
2002 buffer->modified = fixed_setting;
2003 gtk_signal_emit (GTK_OBJECT (buffer), signals[MODIFIED_CHANGED]);
2009 * Assorted other stuff
2013 gtk_text_buffer_get_line_count (GtkTextBuffer *buffer)
2015 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), 0);
2017 return gtk_text_btree_line_count (get_btree (buffer));
2021 gtk_text_buffer_get_char_count (GtkTextBuffer *buffer)
2023 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), 0);
2025 return gtk_text_btree_char_count (get_btree (buffer));
2028 /* Called when we lose the primary selection.
2031 clipboard_clear_selection_cb (GtkClipboard *clipboard,
2034 /* Move selection_bound to the insertion point */
2036 GtkTextIter selection_bound;
2037 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2039 gtk_text_buffer_get_iter_at_mark (buffer, &insert,
2040 gtk_text_buffer_get_mark (buffer, "insert"));
2041 gtk_text_buffer_get_iter_at_mark (buffer, &selection_bound,
2042 gtk_text_buffer_get_mark (buffer, "selection_bound"));
2044 if (!gtk_text_iter_equal (&insert, &selection_bound))
2045 gtk_text_buffer_move_mark (buffer,
2046 gtk_text_buffer_get_mark (buffer, "selection_bound"),
2050 /* Called when we have the primary selection and someone else wants our
2051 * data in order to paste it.
2054 clipboard_get_selection_cb (GtkClipboard *clipboard,
2055 GtkSelectionData *selection_data,
2059 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2060 GtkTextIter start, end;
2062 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2064 if (selection_data->target ==
2065 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2067 /* Provide the address of the buffer; this will only be
2068 * used within-process
2070 gtk_selection_data_set (selection_data,
2071 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2080 str = gtk_text_iter_get_visible_text (&start, &end);
2081 gtk_selection_data_set_text (selection_data, str);
2087 /* Provide cut/copied data */
2089 clipboard_get_contents_cb (GtkClipboard *clipboard,
2090 GtkSelectionData *selection_data,
2094 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2095 GtkTextBuffer *contents = buffer->clipboard_contents;
2097 if (selection_data->target ==
2098 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2100 /* Provide the address of the clipboard buffer; this will only
2101 * be used within-process. OK to supply a NULL value for contents.
2103 gtk_selection_data_set (selection_data,
2104 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2111 /* Just provide text from the clipboard buffer */
2112 if (buffer->clipboard_contents)
2115 GtkTextIter start, end;
2117 gtk_text_buffer_get_bounds (contents, &start, &end);
2118 /* strip off the trailing newline, it isn't part of the text that was cut */
2119 gtk_text_iter_backward_char (&end);
2121 str = gtk_text_iter_get_visible_text (&start, &end);
2122 gtk_selection_data_set_text (selection_data, str);
2127 gtk_selection_data_set_text (selection_data, "");
2134 clipboard_clear_contents_cb (GtkClipboard *clipboard,
2137 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2139 if (buffer->clipboard_contents)
2141 g_object_unref (G_OBJECT (buffer->clipboard_contents));
2142 buffer->clipboard_contents = NULL;
2147 get_paste_point (GtkTextBuffer *buffer,
2149 gboolean clear_afterward)
2151 GtkTextIter insert_point;
2152 GtkTextMark *paste_point_override;
2154 paste_point_override = gtk_text_buffer_get_mark (buffer,
2155 "gtk_paste_point_override");
2157 if (paste_point_override != NULL)
2159 gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
2160 paste_point_override);
2161 if (clear_afterward)
2162 gtk_text_buffer_delete_mark (buffer,
2163 gtk_text_buffer_get_mark (buffer,
2164 "gtk_paste_point_override"));
2168 gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
2169 gtk_text_buffer_get_mark (buffer,
2173 *iter = insert_point;
2177 pre_paste_prep (ClipboardRequest *request_data,
2178 GtkTextIter *insert_point)
2180 GtkTextBuffer *buffer = request_data->buffer;
2182 get_paste_point (buffer, insert_point, TRUE);
2184 /* If we're going to replace the selection, we insert before it to
2185 * avoid messing it up, then we delete the selection after inserting.
2187 if (request_data->replace_selection)
2189 GtkTextIter start, end;
2191 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2192 *insert_point = start;
2197 post_paste_cleanup (ClipboardRequest *request_data)
2199 if (request_data->replace_selection)
2201 GtkTextIter start, end;
2203 if (gtk_text_buffer_get_selection_bounds (request_data->buffer,
2206 if (request_data->interactive)
2207 gtk_text_buffer_delete_interactive (request_data->buffer,
2210 request_data->default_editable);
2212 gtk_text_buffer_delete (request_data->buffer, &start, &end);
2217 /* Called when we request a paste and receive the text data
2220 clipboard_text_received (GtkClipboard *clipboard,
2224 ClipboardRequest *request_data = data;
2225 GtkTextBuffer *buffer = request_data->buffer;
2229 GtkTextIter insert_point;
2231 pre_paste_prep (request_data, &insert_point);
2233 if (request_data->interactive)
2234 gtk_text_buffer_insert_interactive (buffer, &insert_point,
2235 str, -1, request_data->default_editable);
2237 gtk_text_buffer_insert (buffer, &insert_point,
2240 post_paste_cleanup (request_data);
2243 g_object_unref (G_OBJECT (buffer));
2244 g_free (request_data);
2247 static GtkTextBuffer*
2248 selection_data_get_buffer (GtkSelectionData *selection_data,
2249 ClipboardRequest *request_data)
2252 GtkTextBuffer *src_buffer = NULL;
2254 /* If we can get the owner, the selection is in-process */
2255 owner = gdk_selection_owner_get (selection_data->selection);
2260 if (selection_data->type != gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2263 if (selection_data->length != sizeof (src_buffer))
2266 memcpy (&src_buffer, selection_data->data, sizeof (src_buffer));
2268 if (src_buffer == NULL)
2271 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (src_buffer), NULL);
2273 if (gtk_text_buffer_get_tag_table (src_buffer) !=
2274 gtk_text_buffer_get_tag_table (request_data->buffer))
2281 /* These are pretty handy functions; maybe something like them
2282 * should be in the public API. Also, there are other places in this
2283 * file where they could be used.
2286 save_iter (const GtkTextIter *iter,
2287 gboolean left_gravity)
2289 return gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (iter),
2296 restore_iter (const GtkTextIter *iter,
2299 gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (save_id),
2300 (GtkTextIter*) iter,
2302 gtk_text_buffer_delete_mark (gtk_text_mark_get_buffer (save_id),
2308 paste_from_buffer (ClipboardRequest *request_data,
2309 GtkTextBuffer *src_buffer,
2310 const GtkTextIter *start,
2311 const GtkTextIter *end)
2313 GtkTextIter insert_point;
2315 /* We're about to emit a bunch of signals, so be safe */
2316 g_object_ref (G_OBJECT (src_buffer));
2318 pre_paste_prep (request_data, &insert_point);
2320 if (!gtk_text_iter_equal (start, end))
2322 gtk_text_buffer_real_insert_range (request_data->buffer,
2326 request_data->interactive);
2329 post_paste_cleanup (request_data);
2331 g_object_unref (G_OBJECT (src_buffer));
2335 clipboard_clipboard_buffer_received (GtkClipboard *clipboard,
2336 GtkSelectionData *selection_data,
2339 ClipboardRequest *request_data = data;
2340 GtkTextBuffer *src_buffer;
2342 src_buffer = selection_data_get_buffer (selection_data, request_data);
2346 GtkTextIter start, end;
2348 gtk_text_buffer_get_bounds (src_buffer, &start, &end);
2349 /* There's an extra newline on clipboard_contents */
2350 gtk_text_iter_backward_char (&end);
2352 paste_from_buffer (request_data, src_buffer,
2357 /* Request the text selection instead */
2358 gtk_clipboard_request_text (clipboard,
2359 clipboard_text_received,
2365 clipboard_selection_buffer_received (GtkClipboard *clipboard,
2366 GtkSelectionData *selection_data,
2369 ClipboardRequest *request_data = data;
2370 GtkTextBuffer *src_buffer;
2372 src_buffer = selection_data_get_buffer (selection_data, request_data);
2376 GtkTextIter start, end;
2378 if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end))
2379 paste_from_buffer (request_data, src_buffer,
2384 /* Request the text selection instead */
2385 gtk_clipboard_request_text (clipboard,
2386 clipboard_text_received,
2391 static const GtkTargetEntry targets[] = {
2392 { "STRING", 0, TARGET_STRING },
2393 { "TEXT", 0, TARGET_TEXT },
2394 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
2395 { "UTF8_STRING", 0, TARGET_UTF8_STRING },
2396 { "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS }
2400 gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer)
2405 GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
2407 /* Determine whether we have a selection and adjust X selection
2411 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2413 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer))
2414 gtk_clipboard_clear (clipboard);
2418 /* Even if we already have the selection, we need to update our
2421 if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
2422 clipboard_get_selection_cb,
2423 clipboard_clear_selection_cb,
2425 clipboard_clear_selection_cb (clipboard, buffer);
2430 paste (GtkTextBuffer *buffer,
2431 gboolean is_clipboard,
2432 gboolean interactive,
2433 gboolean default_editable)
2435 ClipboardRequest *data = g_new (ClipboardRequest, 1);
2436 GtkTextIter paste_point;
2437 GtkTextIter start, end;
2439 data->buffer = buffer;
2440 g_object_ref (G_OBJECT (buffer));
2441 data->interactive = interactive;
2442 data->default_editable = default_editable;
2444 /* When pasting with the cursor inside the selection area, you
2445 * replace the selection with the new text, otherwise, you
2446 * simply insert the new text at the point where the click
2447 * occured, unselecting any selected text. The replace_selection
2448 * flag toggles this behavior.
2450 data->replace_selection = FALSE;
2452 get_paste_point (buffer, &paste_point, FALSE);
2453 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end) &&
2454 (gtk_text_iter_in_range (&paste_point, &start, &end) ||
2455 gtk_text_iter_equal (&paste_point, &end)))
2456 data->replace_selection = TRUE;
2459 gtk_clipboard_request_contents (gtk_clipboard_get (GDK_NONE),
2461 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2462 clipboard_clipboard_buffer_received, data);
2464 gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
2466 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2467 clipboard_selection_buffer_received, data);
2471 gtk_text_buffer_paste_primary (GtkTextBuffer *buffer,
2472 const GtkTextIter *override_location,
2473 gboolean default_editable)
2475 if (override_location != NULL)
2476 gtk_text_buffer_create_mark (buffer,
2477 "gtk_paste_point_override",
2478 override_location, FALSE);
2480 paste (buffer, FALSE, TRUE, default_editable);
2484 gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
2485 gboolean default_editable)
2487 paste (buffer, TRUE, TRUE, default_editable);
2491 gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
2492 gboolean interactive,
2493 gboolean default_editable)
2498 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2500 return FALSE; /* No selection */
2505 gtk_text_buffer_delete_interactive (buffer, &start, &end, default_editable);
2507 gtk_text_buffer_delete (buffer, &start, &end);
2509 return TRUE; /* We deleted stuff */
2514 cut_or_copy (GtkTextBuffer *buffer,
2515 gboolean delete_region_after,
2516 gboolean interactive,
2517 gboolean default_editable)
2519 /* We prefer to cut the selected region between selection_bound and
2520 * insertion point. If that region is empty, then we cut the region
2521 * between the "anchor" and the insertion point (this is for
2522 * C-space and M-w and other Emacs-style copy/yank keys). Note that
2523 * insert and selection_bound are guaranteed to exist, but the
2524 * anchor only exists sometimes.
2529 if (buffer->clipboard_contents)
2531 g_object_unref (G_OBJECT (buffer->clipboard_contents));
2532 buffer->clipboard_contents = NULL;
2535 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2537 /* Let's try the anchor thing */
2538 GtkTextMark * anchor = gtk_text_buffer_get_mark (buffer, "anchor");
2544 gtk_text_buffer_get_iter_at_mark (buffer, &end, anchor);
2545 gtk_text_iter_reorder (&start, &end);
2549 if (!gtk_text_iter_equal (&start, &end))
2551 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
2554 buffer->clipboard_contents =
2555 gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer));
2557 gtk_text_buffer_get_iter_at_offset (buffer->clipboard_contents,
2560 gtk_text_buffer_insert_range (buffer->clipboard_contents,
2565 if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
2566 clipboard_get_contents_cb,
2567 clipboard_clear_contents_cb,
2569 clipboard_clear_contents_cb (clipboard, buffer);
2571 if (delete_region_after)
2574 gtk_text_buffer_delete_interactive (buffer, &start, &end,
2577 gtk_text_buffer_delete (buffer, &start, &end);
2583 gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
2584 gboolean default_editable)
2586 cut_or_copy (buffer, TRUE, TRUE, default_editable);
2590 gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer)
2592 cut_or_copy (buffer, FALSE, TRUE, TRUE);
2597 * gtk_text_buffer_get_selection_bounds:
2598 * @buffer: a #GtkTextBuffer
2599 * @start: iterator to initialize with selection start
2600 * @end: iterator to initialize with selection end
2602 * Returns %TRUE if some text is selected; places the bounds
2603 * of the selection in @start and @end (if the selection has length 0,
2604 * then @start and @end are filled in with the same value).
2605 * @start and @end will be in ascending order. If @start and @end are
2606 * NULL, then they are not filled in, but the return value still indicates
2607 * whether text is selected.
2609 * Return value: whether the selection has nonzero length
2612 gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer,
2616 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
2618 return gtk_text_btree_get_selection_bounds (get_btree (buffer), start, end);
2622 * Logical attribute cache
2625 #define ATTR_CACHE_SIZE 2
2627 typedef struct _CacheEntry CacheEntry;
2632 PangoLogAttr *attrs;
2636 struct _GtkTextLogAttrCache
2638 gint chars_changed_stamp;
2639 CacheEntry entries[ATTR_CACHE_SIZE];
2643 free_log_attr_cache (GtkTextLogAttrCache *cache)
2646 while (i < ATTR_CACHE_SIZE)
2648 g_free (cache->entries[i].attrs);
2655 clear_log_attr_cache (GtkTextLogAttrCache *cache)
2658 while (i < ATTR_CACHE_SIZE)
2660 g_free (cache->entries[i].attrs);
2661 cache->entries[i].attrs = NULL;
2666 static PangoLogAttr*
2667 compute_log_attrs (const GtkTextIter *iter,
2673 gint char_len, byte_len;
2674 PangoLogAttr *attrs = NULL;
2680 gtk_text_iter_set_line_offset (&start, 0);
2681 gtk_text_iter_forward_line (&end);
2683 paragraph = gtk_text_iter_get_slice (&start, &end);
2684 char_len = g_utf8_strlen (paragraph, -1);
2685 byte_len = strlen (paragraph);
2687 g_assert (char_len > 0);
2690 *char_lenp = char_len;
2692 attrs = g_new (PangoLogAttr, char_len);
2694 lang = gtk_text_iter_get_language (&start);
2696 pango_get_log_attrs (paragraph, byte_len, -1,
2707 /* The return value from this is valid until you call this a second time.
2710 _gtk_text_buffer_get_line_log_attrs (GtkTextBuffer *buffer,
2711 const GtkTextIter *anywhere_in_line,
2715 GtkTextLogAttrCache *cache;
2718 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
2719 g_return_val_if_fail (anywhere_in_line != NULL, NULL);
2720 g_return_val_if_fail (!gtk_text_iter_is_last (anywhere_in_line), NULL);
2722 /* FIXME we also need to recompute log attrs if the language tag at
2723 * the start of a paragraph changes
2726 if (buffer->log_attr_cache == NULL)
2728 buffer->log_attr_cache = g_new0 (GtkTextLogAttrCache, 1);
2729 buffer->log_attr_cache->chars_changed_stamp =
2730 gtk_text_btree_get_chars_changed_stamp (get_btree (buffer));
2732 else if (buffer->log_attr_cache->chars_changed_stamp !=
2733 gtk_text_btree_get_chars_changed_stamp (get_btree (buffer)))
2735 clear_log_attr_cache (buffer->log_attr_cache);
2738 cache = buffer->log_attr_cache;
2739 line = gtk_text_iter_get_line (anywhere_in_line);
2742 while (i < ATTR_CACHE_SIZE)
2744 if (cache->entries[i].attrs &&
2745 cache->entries[i].line == line)
2748 *char_len = cache->entries[i].char_len;
2749 return cache->entries[i].attrs;
2754 /* Not in cache; open up the first cache entry */
2755 if (cache->entries[ATTR_CACHE_SIZE-1].attrs)
2756 g_free (cache->entries[ATTR_CACHE_SIZE-1].attrs);
2758 g_memmove (cache->entries + 1, cache->entries,
2759 sizeof (CacheEntry) * (ATTR_CACHE_SIZE - 1));
2761 cache->entries[0].line = line;
2762 cache->entries[0].attrs = compute_log_attrs (anywhere_in_line,
2763 &cache->entries[0].char_len);
2766 *char_len = cache->entries[0].char_len;
2768 return cache->entries[0].attrs;
2776 _gtk_text_buffer_spew (GtkTextBuffer *buffer)
2778 gtk_text_btree_spew (get_btree (buffer));