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);
101 static GtkObjectClass *parent_class = NULL;
102 static guint signals[LAST_SIGNAL] = { 0 };
105 gtk_text_buffer_get_type (void)
107 static GtkType our_type = 0;
111 static const GtkTypeInfo our_info =
114 sizeof (GtkTextBuffer),
115 sizeof (GtkTextBufferClass),
116 (GtkClassInitFunc) gtk_text_buffer_class_init,
117 (GtkObjectInitFunc) gtk_text_buffer_init,
118 /* reserved_1 */ NULL,
119 /* reserved_2 */ NULL,
120 (GtkClassInitFunc) NULL
123 our_type = gtk_type_unique (GTK_TYPE_OBJECT, &our_info);
130 gtk_text_buffer_class_init (GtkTextBufferClass *klass)
132 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
133 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
135 parent_class = gtk_type_class (GTK_TYPE_OBJECT);
137 signals[INSERT_TEXT] =
138 gtk_signal_new ("insert_text",
140 GTK_CLASS_TYPE (object_class),
141 GTK_SIGNAL_OFFSET (GtkTextBufferClass, insert_text),
142 gtk_marshal_VOID__BOXED_BOXED_INT_BOOLEAN,
150 signals[DELETE_TEXT] =
151 gtk_signal_new ("delete_text",
153 GTK_CLASS_TYPE (object_class),
154 GTK_SIGNAL_OFFSET (GtkTextBufferClass, delete_text),
155 gtk_marshal_VOID__BOXED_BOXED_BOOLEAN,
163 gtk_signal_new ("changed",
165 GTK_CLASS_TYPE (object_class),
166 GTK_SIGNAL_OFFSET (GtkTextBufferClass, changed),
167 gtk_marshal_VOID__VOID,
171 signals[MODIFIED_CHANGED] =
172 gtk_signal_new ("modified_changed",
174 GTK_CLASS_TYPE (object_class),
175 GTK_SIGNAL_OFFSET (GtkTextBufferClass, modified_changed),
176 gtk_marshal_VOID__VOID,
181 gtk_signal_new ("mark_set",
183 GTK_CLASS_TYPE (object_class),
184 GTK_SIGNAL_OFFSET (GtkTextBufferClass, mark_set),
185 gtk_marshal_VOID__BOXED_OBJECT,
191 signals[MARK_DELETED] =
192 gtk_signal_new ("mark_deleted",
194 GTK_CLASS_TYPE (object_class),
195 GTK_SIGNAL_OFFSET (GtkTextBufferClass, mark_deleted),
196 gtk_marshal_VOID__OBJECT,
202 gtk_signal_new ("apply_tag",
204 GTK_CLASS_TYPE (object_class),
205 GTK_SIGNAL_OFFSET (GtkTextBufferClass, apply_tag),
206 gtk_marshal_VOID__OBJECT_BOXED_BOXED,
213 signals[REMOVE_TAG] =
214 gtk_signal_new ("remove_tag",
216 GTK_CLASS_TYPE (object_class),
217 GTK_SIGNAL_OFFSET (GtkTextBufferClass, remove_tag),
218 gtk_marshal_VOID__OBJECT_BOXED_BOXED,
225 gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
227 gobject_class->finalize = gtk_text_buffer_finalize;
229 klass->insert_text = gtk_text_buffer_real_insert_text;
230 klass->delete_text = gtk_text_buffer_real_delete_text;
231 klass->apply_tag = gtk_text_buffer_real_apply_tag;
232 klass->remove_tag = gtk_text_buffer_real_remove_tag;
233 klass->changed = gtk_text_buffer_real_changed;
237 gtk_text_buffer_init (GtkTextBuffer *buffer)
239 buffer->clipboard_contents = NULL;
243 * gtk_text_buffer_new:
244 * @table: a tag table, or NULL to create a new one
246 * Creates a new text buffer.
248 * Return value: a new text buffer
251 gtk_text_buffer_new (GtkTextTagTable *table)
253 GtkTextBuffer *text_buffer;
255 text_buffer = GTK_TEXT_BUFFER (gtk_type_new (gtk_text_buffer_get_type ()));
259 text_buffer->tag_table = table;
261 gtk_object_ref (GTK_OBJECT (text_buffer->tag_table));
262 gtk_object_sink (GTK_OBJECT (text_buffer->tag_table));
269 gtk_text_buffer_finalize (GObject *object)
271 GtkTextBuffer *buffer;
273 buffer = GTK_TEXT_BUFFER (object);
275 if (buffer->clipboard_contents)
277 g_object_unref (G_OBJECT (buffer->clipboard_contents));
278 buffer->clipboard_contents = NULL;
281 if (buffer->tag_table)
283 gtk_object_unref (GTK_OBJECT (buffer->tag_table));
284 buffer->tag_table = NULL;
289 gtk_text_btree_unref (buffer->btree);
290 buffer->btree = NULL;
293 G_OBJECT_CLASS (parent_class)->finalize (object);
296 static GtkTextTagTable*
297 get_table (GtkTextBuffer *buffer)
299 if (buffer->tag_table == NULL)
301 buffer->tag_table = gtk_text_tag_table_new ();
303 gtk_object_ref (GTK_OBJECT (buffer->tag_table));
304 gtk_object_sink (GTK_OBJECT (buffer->tag_table));
307 return buffer->tag_table;
311 get_btree (GtkTextBuffer *buffer)
313 if (buffer->btree == NULL)
314 buffer->btree = gtk_text_btree_new (gtk_text_buffer_get_tag_table (buffer),
317 return buffer->btree;
321 _gtk_text_buffer_get_btree (GtkTextBuffer *buffer)
323 return get_btree (buffer);
327 * gtk_text_buffer_get_tag_table:
328 * @buffer: a #GtkTextBuffer
330 * Get the #GtkTextTagTable associated with this buffer.
332 * Return value: the buffer's tag table
335 gtk_text_buffer_get_tag_table (GtkTextBuffer *buffer)
337 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
339 return get_table (buffer);
343 * gtk_text_buffer_set_text:
344 * @buffer: a #GtkTextBuffer
345 * @text: UTF-8 text to insert
346 * @len: length of @text in bytes
348 * Deletes current contents of @buffer, and inserts @text instead. If
349 * @text doesn't end with a newline, a newline is added;
350 * #GtkTextBuffer contents must always end with a newline. If @text
351 * ends with a newline, the new buffer contents will be exactly
352 * @text. If @len is -1, @text must be nul-terminated.
355 gtk_text_buffer_set_text (GtkTextBuffer *buffer,
359 GtkTextIter start, end;
361 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
362 g_return_if_fail (text != NULL);
367 /* Chop newline, since the buffer will already have one
370 if (len > 0 && text[len-1] == '\n')
373 gtk_text_buffer_get_bounds (buffer, &start, &end);
375 gtk_text_buffer_delete (buffer, &start, &end);
379 gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
380 gtk_text_buffer_insert (buffer, &start, text, len);
390 gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
394 gboolean interactive)
396 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
397 g_return_if_fail (iter != NULL);
399 gtk_text_btree_insert (iter, text, len);
401 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
405 gtk_text_buffer_emit_insert (GtkTextBuffer *buffer,
409 gboolean interactive)
411 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
412 g_return_if_fail (iter != NULL);
413 g_return_if_fail (text != NULL);
420 gtk_signal_emit (GTK_OBJECT (buffer), signals[INSERT_TEXT],
421 iter, text, len, interactive);
426 * gtk_text_buffer_insert:
427 * @buffer: a #GtkTextBuffer
428 * @iter: a position in the buffer
429 * @text: UTF-8 format text to insert
430 * @len: length of text in bytes, or -1
432 * Inserts @len bytes of @text at position @iter. If @len is -1,
433 * @text must be nul-terminated and will be inserted in its
434 * entirety. Emits the "insert_text" signal; insertion actually occurs
435 * in the default handler for the signal. @iter is invalidated when
436 * insertion occurs (because the buffer contents change), but the
437 * default signal handler revalidates it to point to the end of the
442 gtk_text_buffer_insert (GtkTextBuffer *buffer,
447 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
448 g_return_if_fail (iter != NULL);
449 g_return_if_fail (text != NULL);
451 gtk_text_buffer_emit_insert (buffer, iter, text, len, FALSE);
455 * gtk_text_buffer_insert_at_cursor:
456 * @buffer: a #GtkTextBuffer
457 * @text: some text in UTF-8 format
458 * @len: length of text, in bytes
460 * Simply calls gtk_text_buffer_insert (), using the current
461 * cursor position as the insertion point.
464 gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
470 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
471 g_return_if_fail (text != NULL);
473 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
474 gtk_text_buffer_get_mark (buffer,
477 gtk_text_buffer_insert (buffer, &iter, text, len);
481 * gtk_text_buffer_insert_interactive:
482 * @buffer: a #GtkTextBuffer
483 * @iter: a position in @buffer
484 * @text: some UTF-8 text
485 * @len: length of text in bytes, or -1
486 * @default_editable: default editability of buffer
488 * Like gtk_text_buffer_insert (), but the insertion will not occur if
489 * @iter is at a non-editable location in the buffer. Usually you
490 * want to prevent insertions at ineditable locations if the insertion
491 * results from a user action (is interactive).
493 * @default_editable indicates the editability of text that doesn't
494 * have a tag affecting editability applied to it. Typically the
495 * result of gtk_text_view_get_editable() is appropriate here.
497 * Return value: whether text was actually inserted
500 gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer,
504 gboolean default_editable)
506 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
507 g_return_val_if_fail (text != NULL, FALSE);
509 if (gtk_text_iter_editable (iter, default_editable))
511 gtk_text_buffer_emit_insert (buffer, iter, text, len, TRUE);
519 * gtk_text_buffer_insert_interactive_at_cursor:
520 * @buffer: a #GtkTextBuffer
521 * @text: text in UTF-8 format
522 * @len: length of text in bytes, or -1
523 * @default_editable: default editability of buffer
525 * Calls gtk_text_buffer_insert_interactive () at the cursor
528 * @default_editable indicates the editability of text that doesn't
529 * have a tag affecting editability applied to it. Typically the
530 * result of gtk_text_view_get_editable() is appropriate here.
532 * Return value: whether text was actually inserted
535 gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer,
538 gboolean default_editable)
542 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
543 g_return_val_if_fail (text != NULL, FALSE);
545 gtk_text_buffer_get_iter_at_mark (buffer, &iter,
546 gtk_text_buffer_get_mark (buffer,
549 return gtk_text_buffer_insert_interactive (buffer, &iter, text, len,
554 possibly_not_text (gunichar ch,
561 insert_text_range (GtkTextBuffer *buffer,
563 const GtkTextIter *orig_start,
564 const GtkTextIter *orig_end,
565 gboolean interactive)
569 text = gtk_text_iter_get_text (orig_start, orig_end);
571 gtk_text_buffer_emit_insert (buffer, iter, text, -1, interactive);
576 typedef struct _Range Range;
579 GtkTextBuffer *buffer;
580 GtkTextMark *start_mark;
581 GtkTextMark *end_mark;
582 GtkTextMark *whole_end_mark;
583 GtkTextIter *range_start;
584 GtkTextIter *range_end;
585 GtkTextIter *whole_end;
589 save_range (GtkTextIter *range_start,
590 GtkTextIter *range_end,
591 GtkTextIter *whole_end)
595 r = g_new (Range, 1);
597 r->buffer = gtk_text_iter_get_buffer (range_start);
598 g_object_ref (G_OBJECT (r->buffer));
601 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
606 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
612 gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
617 r->range_start = range_start;
618 r->range_end = range_end;
619 r->whole_end = whole_end;
625 restore_range (Range *r)
627 gtk_text_buffer_get_iter_at_mark (r->buffer,
631 gtk_text_buffer_get_iter_at_mark (r->buffer,
635 gtk_text_buffer_get_iter_at_mark (r->buffer,
639 gtk_text_buffer_delete_mark (r->buffer, r->start_mark);
640 gtk_text_buffer_delete_mark (r->buffer, r->end_mark);
641 gtk_text_buffer_delete_mark (r->buffer, r->whole_end_mark);
643 g_object_unref (G_OBJECT (r->buffer));
648 insert_range_untagged (GtkTextBuffer *buffer,
650 const GtkTextIter *orig_start,
651 const GtkTextIter *orig_end,
652 gboolean interactive)
654 GtkTextIter range_start;
655 GtkTextIter range_end;
656 GtkTextIter start, end;
657 GtkTextBuffer *src_buffer;
660 if (gtk_text_iter_equal (orig_start, orig_end))
666 src_buffer = gtk_text_iter_get_buffer (&start);
673 if (gtk_text_iter_equal (&range_start, &range_end))
675 /* Figure out how to move forward */
677 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
679 if (gtk_text_iter_equal (&range_end, &end))
681 /* nothing left to do */
684 else if (gtk_text_iter_get_char (&range_end) == 0xFFFD)
686 GdkPixbuf *pixbuf = NULL;
687 GtkTextChildAnchor *anchor = NULL;
688 pixbuf = gtk_text_iter_get_pixbuf (&range_end);
689 anchor = gtk_text_iter_get_child_anchor (&range_end);
693 r = save_range (&range_start,
697 gtk_text_buffer_insert_pixbuf (buffer,
704 gtk_text_iter_next_char (&range_end);
706 range_start = range_end;
710 /* Just skip anchors */
712 gtk_text_iter_next_char (&range_end);
713 range_start = range_end;
717 /* The 0xFFFD was in a text segment, so
720 gtk_text_iter_forward_find_char (&range_end,
721 possibly_not_text, NULL,
724 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
729 /* Text segment starts here, so forward search to
730 * find its possible endpoint
732 gtk_text_iter_forward_find_char (&range_end,
733 possibly_not_text, NULL,
736 g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
741 r = save_range (&range_start,
745 insert_text_range (buffer,
754 range_start = range_end;
760 gtk_text_buffer_real_insert_range (GtkTextBuffer *buffer,
762 const GtkTextIter *orig_start,
763 const GtkTextIter *orig_end,
764 gboolean interactive)
766 /* Find each range of uniformly-tagged text, insert it,
767 * then apply the tags.
769 GtkTextIter start = *orig_start;
770 GtkTextIter end = *orig_end;
771 GtkTextIter range_start;
772 GtkTextIter range_end;
773 GtkTextBuffer *src_buffer;
776 if (gtk_text_iter_equal (orig_start, orig_end))
779 src_buffer = gtk_text_iter_get_buffer (orig_start);
781 gtk_text_iter_reorder (&start, &end);
789 GtkTextIter start_iter;
793 if (gtk_text_iter_equal (&range_start, &end))
794 break; /* All done */
796 g_assert (gtk_text_iter_compare (&range_start, &end) < 0);
798 gtk_text_iter_forward_to_tag_toggle (&range_end, NULL);
800 g_assert (!gtk_text_iter_equal (&range_start, &range_end));
802 /* Clamp to the end iterator */
803 if (gtk_text_iter_compare (&range_end, &end) > 0)
806 /* We have a range with unique tags; insert it, and
809 start_offset = gtk_text_iter_get_offset (iter);
811 r = save_range (&range_start, &range_end, &end);
813 insert_range_untagged (buffer, iter, &range_start, &range_end, interactive);
818 gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_offset);
820 tags = gtk_text_iter_get_tags (&range_start);
822 while (tmp_list != NULL)
824 gtk_text_buffer_apply_tag (buffer,
829 tmp_list = g_slist_next (tmp_list);
833 range_start = range_end;
838 * gtk_text_buffer_insert_range:
839 * @buffer: a #GtkTextBuffer
840 * @iter: a position in @buffer
841 * @start: a position in a #GtkTextBuffer
842 * @end: another position in the same buffer as @start
844 * Copies text, tags, and pixbufs between @start and @end (the order
845 * of @start and @end doesn't matter) and inserts the copy at @iter.
846 * Used instead of simply getting/inserting text because it preserves
847 * images and tags. If @start and @end are in a different buffer from
848 * @buffer, the two buffers must share the same tag table.
850 * Implemented via emissions of the insert_text and apply_tag signals,
854 gtk_text_buffer_insert_range (GtkTextBuffer *buffer,
856 const GtkTextIter *start,
857 const GtkTextIter *end)
859 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
860 g_return_if_fail (iter != NULL);
861 g_return_if_fail (start != NULL);
862 g_return_if_fail (end != NULL);
863 g_return_if_fail (gtk_text_iter_get_buffer (start) ==
864 gtk_text_iter_get_buffer (end));
865 g_return_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
868 gtk_text_buffer_real_insert_range (buffer, iter, start, end, FALSE);
872 * gtk_text_buffer_insert_range_interactive:
873 * @buffer: a #GtkTextBuffer
874 * @iter: a position in @buffer
875 * @start: a position in a #GtkTextBuffer
876 * @end: another position in the same buffer as @start
877 * @default_editable: default editability of the buffer
879 * Same as gtk_text_buffer_insert_range(), but does nothing if the
880 * insertion point isn't editable. The @default_editable parameter
881 * indicates whether the text is editable at @iter if no tags
882 * enclosing @iter affect editability. Typically the result of
883 * gtk_text_view_get_editable() is appropriate here.
885 * Returns: whether an insertion was possible at @iter
888 gtk_text_buffer_insert_range_interactive (GtkTextBuffer *buffer,
890 const GtkTextIter *start,
891 const GtkTextIter *end,
892 gboolean default_editable)
894 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
895 g_return_val_if_fail (iter != NULL, FALSE);
896 g_return_val_if_fail (start != NULL, FALSE);
897 g_return_val_if_fail (end != NULL, FALSE);
898 g_return_val_if_fail (gtk_text_iter_get_buffer (start) ==
899 gtk_text_iter_get_buffer (end), FALSE);
900 g_return_val_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
901 buffer->tag_table, FALSE);
904 if (gtk_text_iter_editable (iter, default_editable))
906 gtk_text_buffer_real_insert_range (buffer, iter, start, end, TRUE);
914 * gtk_text_buffer_insert_with_tags:
915 * @buffer: a #GtkTextBuffer
916 * @iter: an iterator in @buffer
918 * @len: length of @text, or -1
919 * @first_tag: first tag to apply to @text
920 * @Varargs: NULL-terminated list of tags to apply
922 * Inserts @text into @buffer at @iter, applying the list of tags to
923 * the newly-inserted text. The last tag specified must be NULL to
924 * terminate the list. Equivalent to calling gtk_text_buffer_insert (),
925 * then gtk_text_buffer_apply_tag () on the inserted text;
926 * gtk_text_buffer_insert_with_tags () is just a convenience function.
929 gtk_text_buffer_insert_with_tags (GtkTextBuffer *buffer,
933 GtkTextTag *first_tag,
941 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
942 g_return_if_fail (iter != NULL);
943 g_return_if_fail (text != NULL);
945 start_offset = gtk_text_iter_get_offset (iter);
947 gtk_text_buffer_insert (buffer, iter, text, len);
949 if (first_tag == NULL)
952 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
954 va_start (args, first_tag);
958 gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
960 tag = va_arg (args, GtkTextTag*);
967 * gtk_text_buffer_insert_with_tags_by_name:
968 * @buffer: a #GtkTextBuffer
969 * @iter: position in @buffer
971 * @len: length of @text, or -1
972 * @first_tag_name: name of a tag to apply to @text
973 * @Varargs: more tag names
975 * Same as gtk_text_buffer_insert_with_tags (), but allows you
976 * to pass in tag names instead of tag objects.
979 gtk_text_buffer_insert_with_tags_by_name (GtkTextBuffer *buffer,
983 const gchar *first_tag_name,
989 const gchar *tag_name;
991 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
992 g_return_if_fail (iter != NULL);
993 g_return_if_fail (text != NULL);
995 start_offset = gtk_text_iter_get_offset (iter);
997 gtk_text_buffer_insert (buffer, iter, text, len);
999 if (first_tag_name == NULL)
1002 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
1004 va_start (args, first_tag_name);
1005 tag_name = first_tag_name;
1010 tag = gtk_text_tag_table_lookup (buffer->tag_table,
1015 g_warning ("%s: no tag with name '%s'!", G_STRLOC, tag_name);
1019 gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
1021 tag_name = va_arg (args, const gchar*);
1033 gtk_text_buffer_real_delete_text (GtkTextBuffer *buffer,
1036 gboolean interactive)
1038 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1039 g_return_if_fail (start != NULL);
1040 g_return_if_fail (end != NULL);
1042 gtk_text_btree_delete (start, end);
1044 /* may have deleted the selection... */
1045 gtk_text_buffer_update_primary_selection (buffer);
1047 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
1051 gtk_text_buffer_emit_delete (GtkTextBuffer *buffer,
1054 gboolean interactive)
1056 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1057 g_return_if_fail (start != NULL);
1058 g_return_if_fail (end != NULL);
1060 if (gtk_text_iter_equal (start, end))
1063 gtk_text_iter_reorder (start, end);
1065 /* Somewhat annoyingly, if you try to delete the final newline
1066 * the BTree will put it back; which means you can't deduce the
1067 * final contents of the buffer purely by monitoring insert/delete
1068 * signals on the buffer. But if you delete the final newline, any
1069 * tags on the newline will go away, oddly. See comment in
1070 * gtktextbtree.c. This is all sort of annoying, but really hard
1073 gtk_signal_emit (GTK_OBJECT (buffer),
1074 signals[DELETE_TEXT],
1080 * gtk_text_buffer_delete:
1081 * @buffer: a #GtkTextBuffer
1082 * @start: a position in @buffer
1083 * @end: another position in @buffer
1085 * Deletes text between @start and @end. The order of @start and @end
1086 * is not actually relevant; gtk_text_buffer_delete () will reorder
1087 * them. This function actually emits the "delete_text" signal, and
1088 * the default handler of that signal deletes the text. Because the
1089 * buffer is modified, all outstanding iterators become invalid after
1090 * calling this function; however, the @start and @end will be
1091 * re-initialized to point to the location where text was deleted.
1093 * Note that the final newline in the buffer may not be deleted; a
1094 * #GtkTextBuffer always contains at least one newline. You can
1095 * safely include the final newline in the range [@start,@end) but it
1096 * won't be affected by the deletion.
1100 gtk_text_buffer_delete (GtkTextBuffer *buffer,
1104 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1105 g_return_if_fail (start != NULL);
1106 g_return_if_fail (end != NULL);
1108 gtk_text_buffer_emit_delete (buffer, start, end, FALSE);
1112 * gtk_text_buffer_delete_interactive:
1113 * @buffer: a #GtkTextBuffer
1114 * @start_iter: start of range to delete
1115 * @end_iter: end of range
1116 * @default_editable: whether the buffer is editable by default
1118 * Deletes all <emphasis>editable</emphasis> text in the given range.
1119 * Calls gtk_text_buffer_delete () for each editable sub-range of
1120 * [@start,@end). @start and @end are revalidated to point to
1121 * the location of the last deleted range, or left untouched if
1122 * no text was deleted.
1124 * Return value: whether some text was actually deleted
1127 gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
1128 GtkTextIter *start_iter,
1129 GtkTextIter *end_iter,
1130 gboolean default_editable)
1132 GtkTextMark *end_mark;
1133 GtkTextMark *start_mark;
1135 gboolean current_state;
1136 gboolean deleted_stuff = FALSE;
1138 /* Delete all editable text in the range start_iter, end_iter */
1140 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1141 g_return_val_if_fail (start_iter != NULL, FALSE);
1142 g_return_val_if_fail (end_iter != NULL, FALSE);
1144 gtk_text_iter_reorder (start_iter, end_iter);
1146 start_mark = gtk_text_buffer_create_mark (buffer, NULL,
1148 end_mark = gtk_text_buffer_create_mark (buffer, NULL,
1152 current_state = gtk_text_iter_editable (&iter, default_editable);
1157 gboolean done = FALSE;
1160 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
1162 gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark);
1164 if (gtk_text_iter_compare (&iter, &end) >= 0)
1167 iter = end; /* clamp to the last boundary */
1170 new_state = gtk_text_iter_editable (&iter, default_editable);
1172 if (current_state == new_state)
1178 /* We're ending an editable region. Delete said region. */
1181 gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1183 gtk_text_buffer_emit_delete (buffer, &start, &iter, TRUE);
1185 deleted_stuff = TRUE;
1187 /* revalidate user's iterators. */
1188 *start_iter = start;
1198 if (current_state && !new_state)
1200 /* End of an editable region. Delete it. */
1203 gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1205 gtk_text_buffer_emit_delete (buffer, &start, &iter, TRUE);
1207 current_state = FALSE;
1208 deleted_stuff = TRUE;
1210 /* revalidate user's iterators. */
1211 *start_iter = start;
1216 /* We are at the start of an editable region. We won't be deleting
1217 * the previous region. Move start mark to start of this region.
1220 g_assert (!current_state && new_state);
1222 gtk_text_buffer_move_mark (buffer, start_mark,
1226 current_state = TRUE;
1234 gtk_text_buffer_delete_mark (buffer, start_mark);
1235 gtk_text_buffer_delete_mark (buffer, end_mark);
1237 return deleted_stuff;
1241 * Extracting textual buffer contents
1245 * gtk_text_buffer_get_text:
1246 * @buffer: a #GtkTextBuffer
1247 * @start: start of a range
1248 * @end: end of a range
1249 * @include_hidden_chars: whether to include invisible text
1251 * Returns the text in the range [@start,@end). Excludes undisplayed
1252 * text (text marked with tags that set the invisibility attribute) if
1253 * @include_hidden_chars is FALSE. Does not include characters
1254 * representing embedded images, so byte and character indexes into
1255 * the returned string do <emphasis>not</emphasis> correspond to byte
1256 * and character indexes into the buffer. Contrast with
1257 * gtk_text_buffer_get_slice ().
1259 * Return value: an allocated UTF-8 string
1262 gtk_text_buffer_get_text (GtkTextBuffer *buffer,
1263 const GtkTextIter *start,
1264 const GtkTextIter *end,
1265 gboolean include_hidden_chars)
1267 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1268 g_return_val_if_fail (start != NULL, NULL);
1269 g_return_val_if_fail (end != NULL, NULL);
1271 if (include_hidden_chars)
1272 return gtk_text_iter_get_text (start, end);
1274 return gtk_text_iter_get_visible_text (start, end);
1278 * gtk_text_buffer_get_slice:
1279 * @buffer: a #GtkTextBuffer
1280 * @start: start of a range
1281 * @end: end of a range
1282 * @include_hidden_chars: whether to include invisible text
1284 * Returns the text in the range [@start,@end). Excludes undisplayed
1285 * text (text marked with tags that set the invisibility attribute) if
1286 * @include_hidden_chars is FALSE. The returned string includes a
1287 * 0xFFFD character whenever the buffer contains
1288 * embedded images, so byte and character indexes into
1289 * the returned string <emphasis>do</emphasis> correspond to byte
1290 * and character indexes into the buffer. Contrast with
1291 * gtk_text_buffer_get_text (). Note that 0xFFFD can occur in normal
1292 * text as well, so it is not a reliable indicator that a pixbuf or
1293 * widget is in the buffer.
1295 * Return value: an allocated UTF-8 string
1298 gtk_text_buffer_get_slice (GtkTextBuffer *buffer,
1299 const GtkTextIter *start,
1300 const GtkTextIter *end,
1301 gboolean include_hidden_chars)
1303 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1304 g_return_val_if_fail (start != NULL, NULL);
1305 g_return_val_if_fail (end != NULL, NULL);
1307 if (include_hidden_chars)
1308 return gtk_text_iter_get_slice (start, end);
1310 return gtk_text_iter_get_visible_slice (start, end);
1318 gtk_text_buffer_insert_pixbuf (GtkTextBuffer *buffer,
1322 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1323 g_return_if_fail (iter != NULL);
1324 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1326 gtk_text_btree_insert_pixbuf (iter, pixbuf);
1328 /* FIXME pixbuf-specific signal like insert_text */
1330 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
1338 gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
1341 GtkTextChildAnchor *anchor;
1343 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1344 g_return_val_if_fail (iter != NULL, NULL);
1346 anchor = gtk_text_btree_create_child_anchor (iter);
1348 /* FIXME child-anchor-specific signal */
1350 gtk_signal_emit (GTK_OBJECT (buffer), signals[CHANGED]);
1361 gtk_text_buffer_mark_set (GtkTextBuffer *buffer,
1362 const GtkTextIter *location,
1365 /* IMO this should NOT work like insert_text and delete_text,
1366 where the real action happens in the default handler.
1368 The reason is that the default handler would be _required_,
1369 i.e. the whole widget would start breaking and segfaulting
1370 if the default handler didn't get run. So you can't really
1371 override the default handler or stop the emission; that is,
1372 this signal is purely for notification, and not to allow users
1373 to modify the default behavior. */
1375 g_object_ref (G_OBJECT (mark));
1377 gtk_signal_emit (GTK_OBJECT (buffer),
1382 g_object_unref (G_OBJECT (mark));
1386 * gtk_text_buffer_set_mark:
1387 * @buffer: a #GtkTextBuffer
1388 * @mark_name: name of the mark
1389 * @iter: location for the mark.
1390 * @left_gravity: if the mark is created by this function, gravity for the new
1392 * @should_exist: if %TRUE, warn if the mark does not exist, and return
1395 * Move the mark to the given position, if not @should_exist, create the mark.
1397 * Return value: mark
1400 gtk_text_buffer_set_mark (GtkTextBuffer *buffer,
1401 GtkTextMark *existing_mark,
1402 const gchar *mark_name,
1403 const GtkTextIter *iter,
1404 gboolean left_gravity,
1405 gboolean should_exist)
1407 GtkTextIter location;
1410 mark = gtk_text_btree_set_mark (get_btree (buffer),
1417 if (gtk_text_btree_mark_is_insert (get_btree (buffer), mark) ||
1418 gtk_text_btree_mark_is_selection_bound (get_btree (buffer), mark))
1420 gtk_text_buffer_update_primary_selection (buffer);
1423 gtk_text_btree_get_iter_at_mark (get_btree (buffer),
1427 gtk_text_buffer_mark_set (buffer, &location, mark);
1433 * gtk_text_buffer_create_mark:
1434 * @buffer: a #GtkTextBuffer
1435 * @mark_name: name for mark, or %NULL
1436 * @where: location to place mark
1437 * @left_gravity: whether the mark has left gravity
1439 * Creates a mark at position @where. If @mark_name is %NULL, the mark
1440 * is anonymous; otherwise, the mark can be retrieved by name using
1441 * gtk_text_buffer_get_mark (). If a mark has left gravity, and text is
1442 * inserted at the mark's current location, the mark will be moved to
1443 * the left of the newly-inserted text. If the mark has right gravity
1444 * (@left_gravity = %FALSE), the mark will end up on the right of
1445 * newly-inserted text. The standard left-to-right cursor is a mark
1446 * with right gravity (when you type, the cursor stays on the right
1447 * side of the text you're typing).
1449 * The caller of this function does <emphasis>not</emphasis> own a reference
1450 * to the returned #GtkTextMark, so you can ignore the return value
1451 * if you like. Marks are owned by the buffer and go away when the
1454 * Emits the "mark_set" signal as notification of the mark's initial
1457 * Return value: the new #GtkTextMark object
1460 gtk_text_buffer_create_mark (GtkTextBuffer *buffer,
1461 const gchar *mark_name,
1462 const GtkTextIter *where,
1463 gboolean left_gravity)
1465 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1467 return gtk_text_buffer_set_mark (buffer, NULL, mark_name, where,
1468 left_gravity, FALSE);
1472 * gtk_text_buffer_move_mark:
1473 * @buffer: a #GtkTextBuffer
1474 * @mark: a #GtkTextMark
1475 * @where: new location for @mark in @buffer
1477 * Moves @mark to the new location @where. Emits the "mark_set" signal
1478 * as notification of the move.
1481 gtk_text_buffer_move_mark (GtkTextBuffer *buffer,
1483 const GtkTextIter *where)
1485 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1486 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1487 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1489 gtk_text_buffer_set_mark (buffer, mark, NULL, where, FALSE, TRUE);
1493 * gtk_text_buffer_get_iter_at_mark:
1494 * @buffer: a #GtkTextBuffer
1495 * @iter: iterator to initialize
1496 * @mark: a #GtkTextMark in @buffer
1498 * Initializes @iter with the current position of @mark.
1501 gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer,
1505 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1506 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1507 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1509 gtk_text_btree_get_iter_at_mark (get_btree (buffer),
1515 * gtk_text_buffer_delete_mark:
1516 * @buffer: a #GtkTextBuffer
1517 * @mark: a #GtkTextMark in @buffer
1519 * Deletes @mark, so that it's no longer located anywhere in the
1520 * buffer. Removes the reference the buffer holds to the mark, so if
1521 * you haven't called g_object_ref () on the mark, it will be freed. Even
1522 * if the mark isn't freed, most operations on @mark become
1523 * invalid. There is no way to undelete a
1524 * mark. gtk_text_mark_get_deleted () will return TRUE after this
1525 * function has been called on a mark; gtk_text_mark_get_deleted ()
1526 * indicates that a mark no longer belongs to a buffer. The "mark_deleted"
1527 * signal will be emitted as notification after the mark is deleted.
1530 gtk_text_buffer_delete_mark (GtkTextBuffer *buffer,
1533 g_return_if_fail (GTK_IS_TEXT_MARK (mark));
1534 g_return_if_fail (!gtk_text_mark_get_deleted (mark));
1535 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1537 g_object_ref (G_OBJECT (mark));
1539 gtk_text_btree_remove_mark (get_btree (buffer), mark);
1541 /* See rationale above for MARK_SET on why we emit this after
1542 * removing the mark, rather than removing the mark in a default
1545 gtk_signal_emit (GTK_OBJECT (buffer), signals[MARK_DELETED],
1548 g_object_unref (G_OBJECT (mark));
1552 * gtk_text_buffer_get_mark:
1553 * @buffer: a #GtkTextBuffer
1554 * @name: a mark name
1556 * Returns the mark named @name in buffer @buffer, or NULL if no such
1557 * mark exists in the buffer.
1559 * Return value: a #GtkTextMark, or NULL
1562 gtk_text_buffer_get_mark (GtkTextBuffer *buffer,
1567 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1568 g_return_val_if_fail (name != NULL, NULL);
1570 mark = gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1577 * gtk_text_buffer_move_mark_by_name:
1578 * @buffer: a #GtkTextBuffer
1579 * @name: name of a mark
1580 * @where: new location for mark
1582 * Moves the mark named @name (which must exist) to location @where.
1583 * See gtk_text_buffer_move_mark () for details.
1586 gtk_text_buffer_move_mark_by_name (GtkTextBuffer *buffer,
1588 const GtkTextIter *where)
1592 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1593 g_return_if_fail (name != NULL);
1595 mark = gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1599 g_warning ("%s: no mark named '%s'", G_STRLOC, name);
1603 gtk_text_buffer_move_mark (buffer, mark, where);
1607 * gtk_text_buffer_delete_mark_by_name:
1608 * @buffer: a #GtkTextBuffer
1609 * @name: name of a mark in @buffer
1611 * Deletes the mark named @name; the mark must exist. See
1612 * gtk_text_buffer_delete_mark () for details.
1615 gtk_text_buffer_delete_mark_by_name (GtkTextBuffer *buffer,
1620 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1621 g_return_if_fail (name != NULL);
1623 mark = gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
1627 g_warning ("%s: no mark named '%s'", G_STRLOC, name);
1631 gtk_text_buffer_delete_mark (buffer, mark);
1635 * gtk_text_buffer_get_insert:
1636 * @buffer: a #GtkTextBuffer
1638 * Returns the mark that represents the cursor (insertion point).
1639 * Equivalent to calling gtk_text_buffer_get_mark () to get the mark
1640 * name "insert," but very slightly more efficient, and involves less
1643 * Return value: insertion point mark
1646 gtk_text_buffer_get_insert (GtkTextBuffer *buffer)
1648 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1650 /* FIXME use struct member in btree */
1651 return gtk_text_buffer_get_mark (buffer, "insert");
1655 * gtk_text_buffer_get_selection_bound:
1656 * @buffer: a #GtkTextBuffer
1658 * Returns the mark that represents the selection bound. Equivalent
1659 * to calling gtk_text_buffer_get_mark () to get the mark name
1660 * "selection_bound," but very slightly more efficient, and involves
1663 * The currently-selected text in @buffer is the region between the
1664 * "selection_bound" and "insert" marks. If "selection_bound" and
1665 * "insert" are in the same place, then there is no current selection.
1666 * gtk_text_buffer_get_selection_bounds () is another convenient function
1667 * for handling the selection, if you just want to know whether there's a
1668 * selection and what its bounds are.
1670 * Return value: selection bound mark
1673 gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer)
1675 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1677 /* FIXME use struct member in btree */
1678 return gtk_text_buffer_get_mark (buffer, "selection_bound");
1682 gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer *buffer,
1684 GtkTextChildAnchor *anchor)
1686 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1687 g_return_if_fail (iter != NULL);
1688 g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
1689 g_return_if_fail (!gtk_text_child_anchor_get_deleted (anchor));
1691 gtk_text_btree_get_iter_at_child_anchor (get_btree (buffer),
1697 * gtk_text_buffer_place_cursor:
1698 * @buffer: a #GtkTextBuffer
1699 * @where: where to put the cursor
1701 * This function moves the "insert" and "selection_bound" marks
1702 * simultaneously. If you move them to the same place in two steps
1703 * with gtk_text_buffer_move_mark (), you will temporarily select a
1704 * region in between their old and new locations, which can be pretty
1705 * inefficient since the temporarily-selected region will force stuff
1706 * to be recalculated. This function moves them as a unit, which can
1710 gtk_text_buffer_place_cursor (GtkTextBuffer *buffer,
1711 const GtkTextIter *where)
1715 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1719 if (gtk_text_iter_is_last (&real))
1720 gtk_text_iter_prev_char (&real);
1722 gtk_text_btree_place_cursor (get_btree (buffer), &real);
1723 gtk_text_buffer_mark_set (buffer, &real,
1724 gtk_text_buffer_get_mark (buffer,
1726 gtk_text_buffer_mark_set (buffer, &real,
1727 gtk_text_buffer_get_mark (buffer,
1728 "selection_bound"));
1736 * gtk_text_buffer_create_tag:
1737 * @buffer: a #GtkTextBuffer
1738 * @tag_name: name of the new tag, or %NULL
1740 * Creates a tag and adds it to the tag table for @buffer.
1741 * Equivalent to calling gtk_text_tag_new () and then adding the
1742 * tag to the buffer's tag table. The returned tag has its refcount
1743 * incremented, as if you'd called gtk_text_tag_new ().
1745 * If @tag_name is %NULL, the tag is anonymous.
1747 * Return value: a new tag
1750 gtk_text_buffer_create_tag (GtkTextBuffer *buffer,
1751 const gchar *tag_name)
1755 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1757 tag = gtk_text_tag_new (tag_name);
1759 gtk_text_tag_table_add (get_table (buffer), tag);
1765 gtk_text_buffer_real_apply_tag (GtkTextBuffer *buffer,
1767 const GtkTextIter *start,
1768 const GtkTextIter *end)
1770 gtk_text_btree_tag (start, end, tag, TRUE);
1774 gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
1776 const GtkTextIter *start,
1777 const GtkTextIter *end)
1779 gtk_text_btree_tag (start, end, tag, FALSE);
1783 gtk_text_buffer_real_changed (GtkTextBuffer *buffer)
1785 gtk_text_buffer_set_modified (buffer, TRUE);
1789 gtk_text_buffer_emit_tag (GtkTextBuffer *buffer,
1792 const GtkTextIter *start,
1793 const GtkTextIter *end)
1795 GtkTextIter start_tmp = *start;
1796 GtkTextIter end_tmp = *end;
1798 g_return_if_fail (tag != NULL);
1800 gtk_text_iter_reorder (&start_tmp, &end_tmp);
1803 gtk_signal_emit (GTK_OBJECT (buffer), signals[APPLY_TAG],
1804 tag, &start_tmp, &end_tmp);
1806 gtk_signal_emit (GTK_OBJECT (buffer), signals[REMOVE_TAG],
1807 tag, &start_tmp, &end_tmp);
1812 gtk_text_buffer_apply_tag (GtkTextBuffer *buffer,
1814 const GtkTextIter *start,
1815 const GtkTextIter *end)
1817 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1818 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
1819 g_return_if_fail (start != NULL);
1820 g_return_if_fail (end != NULL);
1822 gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
1826 gtk_text_buffer_remove_tag (GtkTextBuffer *buffer,
1828 const GtkTextIter *start,
1829 const GtkTextIter *end)
1832 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1833 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
1834 g_return_if_fail (start != NULL);
1835 g_return_if_fail (end != NULL);
1837 gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
1842 gtk_text_buffer_apply_tag_by_name (GtkTextBuffer *buffer,
1844 const GtkTextIter *start,
1845 const GtkTextIter *end)
1849 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1850 g_return_if_fail (name != NULL);
1851 g_return_if_fail (start != NULL);
1852 g_return_if_fail (end != NULL);
1854 tag = gtk_text_tag_table_lookup (get_table (buffer),
1859 g_warning ("Unknown tag `%s'", name);
1863 gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
1867 gtk_text_buffer_remove_tag_by_name (GtkTextBuffer *buffer,
1869 const GtkTextIter *start,
1870 const GtkTextIter *end)
1874 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1875 g_return_if_fail (name != NULL);
1876 g_return_if_fail (start != NULL);
1877 g_return_if_fail (end != NULL);
1879 tag = gtk_text_tag_table_lookup (get_table (buffer),
1884 g_warning ("Unknown tag `%s'", name);
1888 gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
1893 * Obtain various iterators
1897 gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
1902 g_return_if_fail (iter != NULL);
1903 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1905 gtk_text_btree_get_iter_at_line_char (get_btree (buffer),
1906 iter, line_number, char_offset);
1910 gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
1915 g_return_if_fail (iter != NULL);
1916 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1918 gtk_text_btree_get_iter_at_line_byte (get_btree (buffer),
1919 iter, line_number, byte_index);
1923 gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
1927 g_return_if_fail (iter != NULL);
1928 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1930 gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
1934 gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
1938 g_return_if_fail (iter != NULL);
1939 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1941 gtk_text_btree_get_iter_at_char (get_btree (buffer), iter, char_offset);
1945 gtk_text_buffer_get_last_iter (GtkTextBuffer *buffer,
1948 g_return_if_fail (iter != NULL);
1949 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1951 gtk_text_btree_get_last_iter (get_btree (buffer), iter);
1955 gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
1959 g_return_if_fail (start != NULL);
1960 g_return_if_fail (end != NULL);
1961 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1963 gtk_text_btree_get_iter_at_char (get_btree (buffer), start, 0);
1964 gtk_text_btree_get_last_iter (get_btree (buffer), end);
1972 gtk_text_buffer_modified (GtkTextBuffer *buffer)
1974 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1976 return buffer->modified;
1980 gtk_text_buffer_set_modified (GtkTextBuffer *buffer,
1983 gboolean fixed_setting;
1985 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1987 fixed_setting = setting != FALSE;
1989 if (buffer->modified == fixed_setting)
1993 buffer->modified = fixed_setting;
1994 gtk_signal_emit (GTK_OBJECT (buffer), signals[MODIFIED_CHANGED]);
2000 * Assorted other stuff
2004 gtk_text_buffer_get_line_count (GtkTextBuffer *buffer)
2006 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), 0);
2008 return gtk_text_btree_line_count (get_btree (buffer));
2012 gtk_text_buffer_get_char_count (GtkTextBuffer *buffer)
2014 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), 0);
2016 return gtk_text_btree_char_count (get_btree (buffer));
2019 /* Called when we lose the primary selection.
2022 clipboard_clear_selection_cb (GtkClipboard *clipboard,
2025 /* Move selection_bound to the insertion point */
2027 GtkTextIter selection_bound;
2028 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2030 gtk_text_buffer_get_iter_at_mark (buffer, &insert,
2031 gtk_text_buffer_get_mark (buffer, "insert"));
2032 gtk_text_buffer_get_iter_at_mark (buffer, &selection_bound,
2033 gtk_text_buffer_get_mark (buffer, "selection_bound"));
2035 if (!gtk_text_iter_equal (&insert, &selection_bound))
2036 gtk_text_buffer_move_mark (buffer,
2037 gtk_text_buffer_get_mark (buffer, "selection_bound"),
2041 /* Called when we have the primary selection and someone else wants our
2042 * data in order to paste it.
2045 clipboard_get_selection_cb (GtkClipboard *clipboard,
2046 GtkSelectionData *selection_data,
2050 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2051 GtkTextIter start, end;
2053 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2055 if (selection_data->target ==
2056 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2058 /* Provide the address of the buffer; this will only be
2059 * used within-process
2061 gtk_selection_data_set (selection_data,
2062 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2071 str = gtk_text_iter_get_visible_text (&start, &end);
2072 gtk_selection_data_set_text (selection_data, str);
2078 /* Provide cut/copied data */
2080 clipboard_get_contents_cb (GtkClipboard *clipboard,
2081 GtkSelectionData *selection_data,
2085 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2086 GtkTextBuffer *contents = buffer->clipboard_contents;
2088 if (selection_data->target ==
2089 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2091 /* Provide the address of the clipboard buffer; this will only
2092 * be used within-process. OK to supply a NULL value for contents.
2094 gtk_selection_data_set (selection_data,
2095 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2102 /* Just provide text from the clipboard buffer */
2103 if (buffer->clipboard_contents)
2106 GtkTextIter start, end;
2108 gtk_text_buffer_get_bounds (contents, &start, &end);
2109 /* strip off the trailing newline, it isn't part of the text that was cut */
2110 gtk_text_iter_prev_char (&end);
2112 str = gtk_text_iter_get_visible_text (&start, &end);
2113 gtk_selection_data_set_text (selection_data, str);
2118 gtk_selection_data_set_text (selection_data, "");
2125 clipboard_clear_contents_cb (GtkClipboard *clipboard,
2128 GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
2130 if (buffer->clipboard_contents)
2132 g_object_unref (G_OBJECT (buffer->clipboard_contents));
2133 buffer->clipboard_contents = NULL;
2138 get_paste_point (GtkTextBuffer *buffer,
2140 gboolean clear_afterward)
2142 GtkTextIter insert_point;
2143 GtkTextMark *paste_point_override;
2145 paste_point_override = gtk_text_buffer_get_mark (buffer,
2146 "gtk_paste_point_override");
2148 if (paste_point_override != NULL)
2150 gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
2151 paste_point_override);
2152 if (clear_afterward)
2153 gtk_text_buffer_delete_mark (buffer,
2154 gtk_text_buffer_get_mark (buffer,
2155 "gtk_paste_point_override"));
2159 gtk_text_buffer_get_iter_at_mark (buffer, &insert_point,
2160 gtk_text_buffer_get_mark (buffer,
2164 *iter = insert_point;
2168 pre_paste_prep (ClipboardRequest *request_data,
2169 GtkTextIter *insert_point)
2171 GtkTextBuffer *buffer = request_data->buffer;
2173 if (request_data->replace_selection)
2175 GtkTextIter start, end;
2177 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2179 if (request_data->interactive)
2180 gtk_text_buffer_delete_interactive (buffer,
2183 request_data->default_editable);
2185 gtk_text_buffer_delete (buffer, &start, &end);
2189 get_paste_point (buffer, insert_point, TRUE);
2192 /* Called when we request a paste and receive the text data
2195 clipboard_text_received (GtkClipboard *clipboard,
2199 ClipboardRequest *request_data = data;
2200 GtkTextBuffer *buffer = request_data->buffer;
2204 GtkTextIter insert_point;
2206 pre_paste_prep (request_data, &insert_point);
2208 if (request_data->interactive)
2209 gtk_text_buffer_insert_interactive (buffer, &insert_point,
2210 str, -1, request_data->default_editable);
2212 gtk_text_buffer_insert (buffer, &insert_point,
2216 g_object_unref (G_OBJECT (buffer));
2217 g_free (request_data);
2220 static GtkTextBuffer*
2221 selection_data_get_buffer (GtkSelectionData *selection_data,
2222 ClipboardRequest *request_data)
2225 GtkTextBuffer *src_buffer = NULL;
2227 /* If we can get the owner, the selection is in-process */
2228 owner = gdk_selection_owner_get (selection_data->selection);
2233 if (selection_data->type != gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
2236 if (selection_data->length != sizeof (src_buffer))
2239 memcpy (&src_buffer, selection_data->data, sizeof (src_buffer));
2241 if (src_buffer == NULL)
2244 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (src_buffer), NULL);
2246 if (gtk_text_buffer_get_tag_table (src_buffer) !=
2247 gtk_text_buffer_get_tag_table (request_data->buffer))
2254 paste_from_buffer (ClipboardRequest *request_data,
2255 GtkTextBuffer *src_buffer,
2256 const GtkTextIter *start,
2257 const GtkTextIter *end)
2259 GtkTextIter insert_point;
2261 /* We're about to emit a bunch of signals, so be safe */
2262 g_object_ref (G_OBJECT (src_buffer));
2264 pre_paste_prep (request_data, &insert_point);
2266 if (!gtk_text_iter_equal (start, end))
2268 gtk_text_buffer_real_insert_range (request_data->buffer,
2272 request_data->interactive);
2275 g_object_unref (G_OBJECT (src_buffer));
2279 clipboard_clipboard_buffer_received (GtkClipboard *clipboard,
2280 GtkSelectionData *selection_data,
2283 ClipboardRequest *request_data = data;
2284 GtkTextBuffer *src_buffer;
2286 src_buffer = selection_data_get_buffer (selection_data, request_data);
2290 GtkTextIter start, end;
2292 gtk_text_buffer_get_bounds (src_buffer, &start, &end);
2293 /* There's an extra newline on clipboard_contents */
2294 gtk_text_iter_prev_char (&end);
2296 paste_from_buffer (request_data, src_buffer,
2301 /* Request the text selection instead */
2302 gtk_clipboard_request_text (clipboard,
2303 clipboard_text_received,
2309 clipboard_selection_buffer_received (GtkClipboard *clipboard,
2310 GtkSelectionData *selection_data,
2313 ClipboardRequest *request_data = data;
2314 GtkTextBuffer *src_buffer;
2316 src_buffer = selection_data_get_buffer (selection_data, request_data);
2320 GtkTextIter start, end;
2322 if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end))
2323 paste_from_buffer (request_data, src_buffer,
2328 /* Request the text selection instead */
2329 gtk_clipboard_request_text (clipboard,
2330 clipboard_text_received,
2335 static const GtkTargetEntry targets[] = {
2336 { "STRING", 0, TARGET_STRING },
2337 { "TEXT", 0, TARGET_TEXT },
2338 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
2339 { "UTF8_STRING", 0, TARGET_UTF8_STRING },
2340 { "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS }
2344 gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer)
2349 GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
2351 /* Determine whether we have a selection and adjust X selection
2355 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2357 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer))
2358 gtk_clipboard_clear (clipboard);
2362 /* Even if we already have the selection, we need to update our
2365 if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
2366 clipboard_get_selection_cb,
2367 clipboard_clear_selection_cb,
2369 clipboard_clear_selection_cb (clipboard, buffer);
2374 paste (GtkTextBuffer *buffer,
2375 gboolean is_clipboard,
2376 gboolean interactive,
2377 gboolean default_editable)
2379 ClipboardRequest *data = g_new (ClipboardRequest, 1);
2380 GtkTextIter paste_point;
2381 GtkTextIter start, end;
2383 data->buffer = buffer;
2384 g_object_ref (G_OBJECT (buffer));
2385 data->interactive = interactive;
2386 data->default_editable = default_editable;
2388 /* When pasting with the cursor inside the selection area, you
2389 * replace the selection with the new text, otherwise, you
2390 * simply insert the new text at the point where the click
2391 * occured, unselecting any selected text. The replace_selection
2392 * flag toggles this behavior. FIXME set the flag based on something.
2394 data->replace_selection = FALSE;
2396 get_paste_point (buffer, &paste_point, FALSE);
2397 if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end) &&
2398 gtk_text_iter_in_range (&paste_point, &start, &end))
2399 data->replace_selection = TRUE;
2402 gtk_clipboard_request_contents (gtk_clipboard_get (GDK_NONE),
2404 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2405 clipboard_clipboard_buffer_received, data);
2407 gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
2409 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
2410 clipboard_selection_buffer_received, data);
2414 gtk_text_buffer_paste_primary (GtkTextBuffer *buffer,
2415 const GtkTextIter *override_location,
2416 gboolean default_editable)
2418 if (override_location != NULL)
2419 gtk_text_buffer_create_mark (buffer,
2420 "gtk_paste_point_override",
2421 override_location, FALSE);
2423 paste (buffer, FALSE, TRUE, default_editable);
2427 gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
2428 gboolean default_editable)
2430 paste (buffer, TRUE, TRUE, default_editable);
2434 gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
2435 gboolean interactive,
2436 gboolean default_editable)
2441 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2443 return FALSE; /* No selection */
2448 gtk_text_buffer_delete_interactive (buffer, &start, &end, default_editable);
2450 gtk_text_buffer_delete (buffer, &start, &end);
2452 return TRUE; /* We deleted stuff */
2457 cut_or_copy (GtkTextBuffer *buffer,
2458 gboolean delete_region_after,
2459 gboolean interactive,
2460 gboolean default_editable)
2462 /* We prefer to cut the selected region between selection_bound and
2463 * insertion point. If that region is empty, then we cut the region
2464 * between the "anchor" and the insertion point (this is for
2465 * C-space and M-w and other Emacs-style copy/yank keys). Note that
2466 * insert and selection_bound are guaranteed to exist, but the
2467 * anchor only exists sometimes.
2472 if (buffer->clipboard_contents)
2474 g_object_unref (G_OBJECT (buffer->clipboard_contents));
2475 buffer->clipboard_contents = NULL;
2478 if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
2480 /* Let's try the anchor thing */
2481 GtkTextMark * anchor = gtk_text_buffer_get_mark (buffer, "anchor");
2487 gtk_text_buffer_get_iter_at_mark (buffer, &end, anchor);
2488 gtk_text_iter_reorder (&start, &end);
2492 if (!gtk_text_iter_equal (&start, &end))
2494 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
2497 buffer->clipboard_contents =
2498 gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer));
2500 gtk_text_buffer_get_iter_at_offset (buffer->clipboard_contents,
2503 gtk_text_buffer_insert_range (buffer->clipboard_contents,
2508 if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
2509 clipboard_get_contents_cb,
2510 clipboard_clear_contents_cb,
2512 clipboard_clear_contents_cb (clipboard, buffer);
2514 if (delete_region_after)
2517 gtk_text_buffer_delete_interactive (buffer, &start, &end,
2520 gtk_text_buffer_delete (buffer, &start, &end);
2526 gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
2527 gboolean default_editable)
2529 cut_or_copy (buffer, TRUE, TRUE, default_editable);
2533 gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer)
2535 cut_or_copy (buffer, FALSE, TRUE, TRUE);
2540 * gtk_text_buffer_get_selection_bounds:
2541 * @buffer: a #GtkTextBuffer
2542 * @start: iterator to initialize with selection start
2543 * @end: iterator to initialize with selection end
2545 * Returns %TRUE if some text is selected; places the bounds
2546 * of the selection in @start and @end (if the selection has length 0,
2547 * then @start and @end are filled in with the same value).
2548 * @start and @end will be in ascending order. If @start and @end are
2549 * NULL, then they are not filled in, but the return value still indicates
2550 * whether text is selected.
2552 * Return value: whether the selection has nonzero length
2555 gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer,
2559 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
2561 return gtk_text_btree_get_selection_bounds (get_btree (buffer), start, end);
2570 _gtk_text_buffer_spew (GtkTextBuffer *buffer)
2572 gtk_text_btree_spew (get_btree (buffer));