Bind get_bounds and use out instead of out caller-allocates.
[gtk3:gtk.git] / gtk / gtktextbuffer.c
1 /* GTK - The GIMP Toolkit
2  * gtktextbuffer.c Copyright (C) 2000 Red Hat, Inc.
3  *                 Copyright (C) 2004 Nokia Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
26  */
27
28 #include "config.h"
29 #include <string.h>
30 #include <stdarg.h>
31
32 #define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
33 #include "gtkclipboard.h"
34 #include "gtkdnd.h"
35 #include "gtkinvisible.h"
36 #include "gtkmarshalers.h"
37 #include "gtktextbuffer.h"
38 #include "gtktextbufferrichtext.h"
39 #include "gtktextbtree.h"
40 #include "gtktextiterprivate.h"
41 #include "gtkprivate.h"
42 #include "gtkintl.h"
43 #include "gtkalias.h"
44
45
46 #define GTK_TEXT_BUFFER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TEXT_BUFFER, GtkTextBufferPrivate))
47
48 typedef struct _GtkTextBufferPrivate GtkTextBufferPrivate;
49
50 struct _GtkTextBufferPrivate
51 {
52   GtkTargetList  *copy_target_list;
53   GtkTargetEntry *copy_target_entries;
54   gint            n_copy_target_entries;
55
56   GtkTargetList  *paste_target_list;
57   GtkTargetEntry *paste_target_entries;
58   gint            n_paste_target_entries;
59 };
60
61
62 typedef struct _ClipboardRequest ClipboardRequest;
63
64 struct _ClipboardRequest
65 {
66   GtkTextBuffer *buffer;
67   gboolean interactive;
68   gboolean default_editable;
69   gboolean is_clipboard;
70   gboolean replace_selection;
71 };
72
73 enum {
74   INSERT_TEXT,
75   INSERT_PIXBUF,
76   INSERT_CHILD_ANCHOR,
77   DELETE_RANGE,
78   CHANGED,
79   MODIFIED_CHANGED,
80   MARK_SET,
81   MARK_DELETED,
82   APPLY_TAG,
83   REMOVE_TAG,
84   BEGIN_USER_ACTION,
85   END_USER_ACTION,
86   PASTE_DONE,
87   LAST_SIGNAL
88 };
89
90 enum {
91   PROP_0,
92
93   /* Construct */
94   PROP_TAG_TABLE,
95
96   /* Normal */
97   PROP_TEXT,
98   PROP_HAS_SELECTION,
99   PROP_CURSOR_POSITION,
100   PROP_COPY_TARGET_LIST,
101   PROP_PASTE_TARGET_LIST
102 };
103
104 static void gtk_text_buffer_finalize   (GObject            *object);
105
106 static void gtk_text_buffer_real_insert_text           (GtkTextBuffer     *buffer,
107                                                         GtkTextIter       *iter,
108                                                         const gchar       *text,
109                                                         gint               len);
110 static void gtk_text_buffer_real_insert_pixbuf         (GtkTextBuffer     *buffer,
111                                                         GtkTextIter       *iter,
112                                                         GdkPixbuf         *pixbuf);
113 static void gtk_text_buffer_real_insert_anchor         (GtkTextBuffer     *buffer,
114                                                         GtkTextIter       *iter,
115                                                         GtkTextChildAnchor *anchor);
116 static void gtk_text_buffer_real_delete_range          (GtkTextBuffer     *buffer,
117                                                         GtkTextIter       *start,
118                                                         GtkTextIter       *end);
119 static void gtk_text_buffer_real_apply_tag             (GtkTextBuffer     *buffer,
120                                                         GtkTextTag        *tag,
121                                                         const GtkTextIter *start_char,
122                                                         const GtkTextIter *end_char);
123 static void gtk_text_buffer_real_remove_tag            (GtkTextBuffer     *buffer,
124                                                         GtkTextTag        *tag,
125                                                         const GtkTextIter *start_char,
126                                                         const GtkTextIter *end_char);
127 static void gtk_text_buffer_real_changed               (GtkTextBuffer     *buffer);
128 static void gtk_text_buffer_real_mark_set              (GtkTextBuffer     *buffer,
129                                                         const GtkTextIter *iter,
130                                                         GtkTextMark       *mark);
131
132 static GtkTextBTree* get_btree (GtkTextBuffer *buffer);
133 static void          free_log_attr_cache (GtkTextLogAttrCache *cache);
134
135 static void remove_all_selection_clipboards       (GtkTextBuffer *buffer);
136 static void update_selection_clipboards           (GtkTextBuffer *buffer);
137
138 static GtkTextBuffer *create_clipboard_contents_buffer (GtkTextBuffer *buffer);
139
140 static void gtk_text_buffer_free_target_lists     (GtkTextBuffer *buffer);
141
142 static guint signals[LAST_SIGNAL] = { 0 };
143
144 static void gtk_text_buffer_set_property (GObject         *object,
145                                           guint            prop_id,
146                                           const GValue    *value,
147                                           GParamSpec      *pspec);
148 static void gtk_text_buffer_get_property (GObject         *object,
149                                           guint            prop_id,
150                                           GValue          *value,
151                                           GParamSpec      *pspec);
152 static void gtk_text_buffer_notify       (GObject         *object,
153                                           GParamSpec      *pspec);
154
155 G_DEFINE_TYPE (GtkTextBuffer, gtk_text_buffer, G_TYPE_OBJECT)
156
157 static void
158 gtk_text_buffer_class_init (GtkTextBufferClass *klass)
159 {
160   GObjectClass *object_class = G_OBJECT_CLASS (klass);
161
162   object_class->finalize = gtk_text_buffer_finalize;
163   object_class->set_property = gtk_text_buffer_set_property;
164   object_class->get_property = gtk_text_buffer_get_property;
165   object_class->notify       = gtk_text_buffer_notify;
166  
167   klass->insert_text = gtk_text_buffer_real_insert_text;
168   klass->insert_pixbuf = gtk_text_buffer_real_insert_pixbuf;
169   klass->insert_child_anchor = gtk_text_buffer_real_insert_anchor;
170   klass->delete_range = gtk_text_buffer_real_delete_range;
171   klass->apply_tag = gtk_text_buffer_real_apply_tag;
172   klass->remove_tag = gtk_text_buffer_real_remove_tag;
173   klass->changed = gtk_text_buffer_real_changed;
174   klass->mark_set = gtk_text_buffer_real_mark_set;
175
176   /* Construct */
177   g_object_class_install_property (object_class,
178                                    PROP_TAG_TABLE,
179                                    g_param_spec_object ("tag-table",
180                                                         P_("Tag Table"),
181                                                         P_("Text Tag Table"),
182                                                         GTK_TYPE_TEXT_TAG_TABLE,
183                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
184
185   /* Normal properties*/
186   
187   /**
188    * GtkTextBuffer:text:
189    *
190    * The text content of the buffer. Without child widgets and images,
191    * see gtk_text_buffer_get_text() for more information.
192    *
193    * Since: 2.8
194    */
195   g_object_class_install_property (object_class,
196                                    PROP_TEXT,
197                                    g_param_spec_string ("text",
198                                                         P_("Text"),
199                                                         P_("Current text of the buffer"),
200                                                         "",
201                                                         GTK_PARAM_READWRITE));
202
203   /**
204    * GtkTextBuffer:has-selection:
205    *
206    * Whether the buffer has some text currently selected.
207    *
208    * Since: 2.10
209    */
210   g_object_class_install_property (object_class,
211                                    PROP_HAS_SELECTION,
212                                    g_param_spec_boolean ("has-selection",
213                                                          P_("Has selection"),
214                                                          P_("Whether the buffer has some text currently selected"),
215                                                          FALSE,
216                                                          GTK_PARAM_READABLE));
217
218   /**
219    * GtkTextBuffer:cursor-position:
220    *
221    * The position of the insert mark (as offset from the beginning 
222    * of the buffer). It is useful for getting notified when the 
223    * cursor moves.
224    *
225    * Since: 2.10
226    */
227   g_object_class_install_property (object_class,
228                                    PROP_CURSOR_POSITION,
229                                    g_param_spec_int ("cursor-position",
230                                                      P_("Cursor position"),
231                                                      P_("The position of the insert mark (as offset from the beginning of the buffer)"),
232                                                      0, G_MAXINT, 0,
233                                                      GTK_PARAM_READABLE));
234
235   /**
236    * GtkTextBuffer:copy-target-list:
237    *
238    * The list of targets this buffer supports for clipboard copying
239    * and as DND source.
240    *
241    * Since: 2.10
242    */
243   g_object_class_install_property (object_class,
244                                    PROP_COPY_TARGET_LIST,
245                                    g_param_spec_boxed ("copy-target-list",
246                                                        P_("Copy target list"),
247                                                        P_("The list of targets this buffer supports for clipboard copying and DND source"),
248                                                        GTK_TYPE_TARGET_LIST,
249                                                        GTK_PARAM_READABLE));
250
251   /**
252    * GtkTextBuffer:paste-target-list:
253    *
254    * The list of targets this buffer supports for clipboard pasting
255    * and as DND destination.
256    *
257    * Since: 2.10
258    */
259   g_object_class_install_property (object_class,
260                                    PROP_PASTE_TARGET_LIST,
261                                    g_param_spec_boxed ("paste-target-list",
262                                                        P_("Paste target list"),
263                                                        P_("The list of targets this buffer supports for clipboard pasting and DND destination"),
264                                                        GTK_TYPE_TARGET_LIST,
265                                                        GTK_PARAM_READABLE));
266
267   /**
268    * GtkTextBuffer::insert-text:
269    * @textbuffer: the object which received the signal
270    * @location: position to insert @text in @textbuffer
271    * @text: the UTF-8 text to be inserted
272    * @len: length of the inserted text in bytes
273    * 
274    * The ::insert-text signal is emitted to insert text in a #GtkTextBuffer.
275    * Insertion actually occurs in the default handler.  
276    * 
277    * Note that if your handler runs before the default handler it must not 
278    * invalidate the @location iter (or has to revalidate it). 
279    * The default signal handler revalidates it to point to the end of the 
280    * inserted text.
281    * 
282    * See also: 
283    * gtk_text_buffer_insert(), 
284    * gtk_text_buffer_insert_range().
285    */
286   signals[INSERT_TEXT] =
287     g_signal_new (I_("insert-text"),
288                   G_OBJECT_CLASS_TYPE (object_class),
289                   G_SIGNAL_RUN_LAST,
290                   G_STRUCT_OFFSET (GtkTextBufferClass, insert_text),
291                   NULL, NULL,
292                   _gtk_marshal_VOID__BOXED_STRING_INT,
293                   G_TYPE_NONE,
294                   3,
295                   GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
296                   G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
297                   G_TYPE_INT);
298
299   /**
300    * GtkTextBuffer::insert-pixbuf:
301    * @textbuffer: the object which received the signal
302    * @location: position to insert @pixbuf in @textbuffer
303    * @pixbuf: the #GdkPixbuf to be inserted
304    * 
305    * The ::insert-pixbuf signal is emitted to insert a #GdkPixbuf 
306    * in a #GtkTextBuffer. Insertion actually occurs in the default handler.
307    * 
308    * Note that if your handler runs before the default handler it must not 
309    * invalidate the @location iter (or has to revalidate it). 
310    * The default signal handler revalidates it to be placed after the 
311    * inserted @pixbuf.
312    * 
313    * See also: gtk_text_buffer_insert_pixbuf().
314    */
315   signals[INSERT_PIXBUF] =
316     g_signal_new (I_("insert-pixbuf"),
317                   G_OBJECT_CLASS_TYPE (object_class),
318                   G_SIGNAL_RUN_LAST,
319                   G_STRUCT_OFFSET (GtkTextBufferClass, insert_pixbuf),
320                   NULL, NULL,
321                   _gtk_marshal_VOID__BOXED_OBJECT,
322                   G_TYPE_NONE,
323                   2,
324                   GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
325                   GDK_TYPE_PIXBUF);
326
327
328   /**
329    * GtkTextBuffer::insert-child-anchor:
330    * @textbuffer: the object which received the signal
331    * @location: position to insert @anchor in @textbuffer
332    * @anchor: the #GtkTextChildAnchor to be inserted
333    * 
334    * The ::insert-child-anchor signal is emitted to insert a
335    * #GtkTextChildAnchor in a #GtkTextBuffer.
336    * Insertion actually occurs in the default handler.
337    * 
338    * Note that if your handler runs before the default handler it must
339    * not invalidate the @location iter (or has to revalidate it). 
340    * The default signal handler revalidates it to be placed after the 
341    * inserted @anchor.
342    * 
343    * See also: gtk_text_buffer_insert_child_anchor().
344    */
345   signals[INSERT_CHILD_ANCHOR] =
346     g_signal_new (I_("insert-child-anchor"),
347                   G_OBJECT_CLASS_TYPE (object_class),
348                   G_SIGNAL_RUN_LAST,
349                   G_STRUCT_OFFSET (GtkTextBufferClass, insert_child_anchor),
350                   NULL, NULL,
351                   _gtk_marshal_VOID__BOXED_OBJECT,
352                   G_TYPE_NONE,
353                   2,
354                   GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
355                   GTK_TYPE_TEXT_CHILD_ANCHOR);
356   
357   /**
358    * GtkTextBuffer::delete-range:
359    * @textbuffer: the object which received the signal
360    * @start: the start of the range to be deleted
361    * @end: the end of the range to be deleted
362    * 
363    * The ::delete-range signal is emitted to delete a range 
364    * from a #GtkTextBuffer. 
365    * 
366    * Note that if your handler runs before the default handler it must not 
367    * invalidate the @start and @end iters (or has to revalidate them). 
368    * The default signal handler revalidates the @start and @end iters to 
369    * both point point to the location where text was deleted. Handlers
370    * which run after the default handler (see g_signal_connect_after())
371    * do not have access to the deleted text.
372    * 
373    * See also: gtk_text_buffer_delete().
374    */
375   signals[DELETE_RANGE] =
376     g_signal_new (I_("delete-range"),
377                   G_OBJECT_CLASS_TYPE (object_class),
378                   G_SIGNAL_RUN_LAST,
379                   G_STRUCT_OFFSET (GtkTextBufferClass, delete_range),
380                   NULL, NULL,
381                   _gtk_marshal_VOID__BOXED_BOXED,
382                   G_TYPE_NONE,
383                   2,
384                   GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
385                   GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE);
386
387   /**
388    * GtkTextBuffer::changed:
389    * @textbuffer: the object which received the signal
390    * 
391    * The ::changed signal is emitted when the content of a #GtkTextBuffer 
392    * has changed.
393    */
394   signals[CHANGED] =
395     g_signal_new (I_("changed"),
396                   G_OBJECT_CLASS_TYPE (object_class),
397                   G_SIGNAL_RUN_LAST,                   
398                   G_STRUCT_OFFSET (GtkTextBufferClass, changed),
399                   NULL, NULL,
400                   _gtk_marshal_VOID__VOID,
401                   G_TYPE_NONE,
402                   0);
403
404   /**
405    * GtkTextBuffer::modified-changed:
406    * @textbuffer: the object which received the signal
407    * 
408    * The ::modified-changed signal is emitted when the modified bit of a 
409    * #GtkTextBuffer flips.
410    * 
411    * See also:
412    * gtk_text_buffer_set_modified().
413    */
414   signals[MODIFIED_CHANGED] =
415     g_signal_new (I_("modified-changed"),
416                   G_OBJECT_CLASS_TYPE (object_class),
417                   G_SIGNAL_RUN_LAST,
418                   G_STRUCT_OFFSET (GtkTextBufferClass, modified_changed),
419                   NULL, NULL,
420                   _gtk_marshal_VOID__VOID,
421                   G_TYPE_NONE,
422                   0);
423
424   /**
425    * GtkTextBuffer::mark-set:
426    * @textbuffer: the object which received the signal
427    * @location: The location of @mark in @textbuffer
428    * @mark: The mark that is set
429    * 
430    * The ::mark-set signal is emitted as notification
431    * after a #GtkTextMark is set.
432    * 
433    * See also: 
434    * gtk_text_buffer_create_mark(),
435    * gtk_text_buffer_move_mark().
436    */
437   signals[MARK_SET] =
438     g_signal_new (I_("mark-set"),
439                   G_OBJECT_CLASS_TYPE (object_class),
440                   G_SIGNAL_RUN_LAST,                   
441                   G_STRUCT_OFFSET (GtkTextBufferClass, mark_set),
442                   NULL, NULL,
443                   _gtk_marshal_VOID__BOXED_OBJECT,
444                   G_TYPE_NONE,
445                   2,
446                   GTK_TYPE_TEXT_ITER,
447                   GTK_TYPE_TEXT_MARK);
448
449   /**
450    * GtkTextBuffer::mark-deleted:
451    * @textbuffer: the object which received the signal
452    * @mark: The mark that was deleted
453    * 
454    * The ::mark-deleted signal is emitted as notification
455    * after a #GtkTextMark is deleted. 
456    * 
457    * See also:
458    * gtk_text_buffer_delete_mark().
459    */
460   signals[MARK_DELETED] =
461     g_signal_new (I_("mark-deleted"),
462                   G_OBJECT_CLASS_TYPE (object_class),
463                   G_SIGNAL_RUN_LAST,                   
464                   G_STRUCT_OFFSET (GtkTextBufferClass, mark_deleted),
465                   NULL, NULL,
466                   _gtk_marshal_VOID__OBJECT,
467                   G_TYPE_NONE,
468                   1,
469                   GTK_TYPE_TEXT_MARK);
470
471    /**
472    * GtkTextBuffer::apply-tag:
473    * @textbuffer: the object which received the signal
474    * @tag: the applied tag
475    * @start: the start of the range the tag is applied to
476    * @end: the end of the range the tag is applied to
477    * 
478    * The ::apply-tag signal is emitted to apply a tag to a
479    * range of text in a #GtkTextBuffer. 
480    * Applying actually occurs in the default handler.
481    * 
482    * Note that if your handler runs before the default handler it must not 
483    * invalidate the @start and @end iters (or has to revalidate them). 
484    * 
485    * See also: 
486    * gtk_text_buffer_apply_tag(),
487    * gtk_text_buffer_insert_with_tags(),
488    * gtk_text_buffer_insert_range().
489    */ 
490   signals[APPLY_TAG] =
491     g_signal_new (I_("apply-tag"),
492                   G_OBJECT_CLASS_TYPE (object_class),
493                   G_SIGNAL_RUN_LAST,
494                   G_STRUCT_OFFSET (GtkTextBufferClass, apply_tag),
495                   NULL, NULL,
496                   _gtk_marshal_VOID__OBJECT_BOXED_BOXED,
497                   G_TYPE_NONE,
498                   3,
499                   GTK_TYPE_TEXT_TAG,
500                   GTK_TYPE_TEXT_ITER,
501                   GTK_TYPE_TEXT_ITER);
502
503
504    /**
505    * GtkTextBuffer::remove-tag:
506    * @textbuffer: the object which received the signal
507    * @tag: the tag to be removed
508    * @start: the start of the range the tag is removed from
509    * @end: the end of the range the tag is removed from
510    * 
511    * The ::remove-tag signal is emitted to remove all occurrences of @tag from
512    * a range of text in a #GtkTextBuffer. 
513    * Removal actually occurs in the default handler.
514    * 
515    * Note that if your handler runs before the default handler it must not 
516    * invalidate the @start and @end iters (or has to revalidate them). 
517    * 
518    * See also: 
519    * gtk_text_buffer_remove_tag(). 
520    */ 
521   signals[REMOVE_TAG] =
522     g_signal_new (I_("remove-tag"),
523                   G_OBJECT_CLASS_TYPE (object_class),
524                   G_SIGNAL_RUN_LAST,
525                   G_STRUCT_OFFSET (GtkTextBufferClass, remove_tag),
526                   NULL, NULL,
527                   _gtk_marshal_VOID__OBJECT_BOXED_BOXED,
528                   G_TYPE_NONE,
529                   3,
530                   GTK_TYPE_TEXT_TAG,
531                   GTK_TYPE_TEXT_ITER,
532                   GTK_TYPE_TEXT_ITER);
533
534    /**
535    * GtkTextBuffer::begin-user-action:
536    * @textbuffer: the object which received the signal
537    * 
538    * The ::begin-user-action signal is emitted at the beginning of a single
539    * user-visible operation on a #GtkTextBuffer.
540    * 
541    * See also: 
542    * gtk_text_buffer_begin_user_action(),
543    * gtk_text_buffer_insert_interactive(),
544    * gtk_text_buffer_insert_range_interactive(),
545    * gtk_text_buffer_delete_interactive(),
546    * gtk_text_buffer_backspace(),
547    * gtk_text_buffer_delete_selection().
548    */ 
549   signals[BEGIN_USER_ACTION] =
550     g_signal_new (I_("begin-user-action"),
551                   G_OBJECT_CLASS_TYPE (object_class),
552                   G_SIGNAL_RUN_LAST,                   
553                   G_STRUCT_OFFSET (GtkTextBufferClass, begin_user_action),
554                   NULL, NULL,
555                   _gtk_marshal_VOID__VOID,
556                   G_TYPE_NONE,
557                   0);
558
559    /**
560    * GtkTextBuffer::end-user-action:
561    * @textbuffer: the object which received the signal
562    * 
563    * The ::end-user-action signal is emitted at the end of a single
564    * user-visible operation on the #GtkTextBuffer.
565    * 
566    * See also: 
567    * gtk_text_buffer_end_user_action(),
568    * gtk_text_buffer_insert_interactive(),
569    * gtk_text_buffer_insert_range_interactive(),
570    * gtk_text_buffer_delete_interactive(),
571    * gtk_text_buffer_backspace(),
572    * gtk_text_buffer_delete_selection(),
573    * gtk_text_buffer_backspace().
574    */ 
575   signals[END_USER_ACTION] =
576     g_signal_new (I_("end-user-action"),
577                   G_OBJECT_CLASS_TYPE (object_class),
578                   G_SIGNAL_RUN_LAST,                   
579                   G_STRUCT_OFFSET (GtkTextBufferClass, end_user_action),
580                   NULL, NULL,
581                   _gtk_marshal_VOID__VOID,
582                   G_TYPE_NONE,
583                   0);
584
585    /**
586    * GtkTextBuffer::paste-done:
587    * @textbuffer: the object which received the signal
588    * 
589    * The paste-done signal is emitted after paste operation has been completed.
590    * This is useful to properly scroll the view to the end of the pasted text.
591    * See gtk_text_buffer_paste_clipboard() for more details.
592    * 
593    * Since: 2.16
594    */ 
595   signals[PASTE_DONE] =
596     g_signal_new (I_("paste-done"),
597                   G_OBJECT_CLASS_TYPE (object_class),
598                   G_SIGNAL_RUN_LAST,
599                   G_STRUCT_OFFSET (GtkTextBufferClass, paste_done),
600                   NULL, NULL,
601                   _gtk_marshal_VOID__OBJECT,
602                   G_TYPE_NONE,
603                   1,
604                   GTK_TYPE_CLIPBOARD);
605
606   g_type_class_add_private (object_class, sizeof (GtkTextBufferPrivate));
607 }
608
609 static void
610 gtk_text_buffer_init (GtkTextBuffer *buffer)
611 {
612   buffer->clipboard_contents_buffers = NULL;
613   buffer->tag_table = NULL;
614
615   /* allow copying of arbiatray stuff in the internal rich text format */
616   gtk_text_buffer_register_serialize_tagset (buffer, NULL);
617 }
618
619 static void
620 set_table (GtkTextBuffer *buffer, GtkTextTagTable *table)
621 {
622   g_return_if_fail (buffer->tag_table == NULL);
623
624   if (table)
625     {
626       buffer->tag_table = table;
627       g_object_ref (buffer->tag_table);
628       _gtk_text_tag_table_add_buffer (table, buffer);
629     }
630 }
631
632 static GtkTextTagTable*
633 get_table (GtkTextBuffer *buffer)
634 {
635   if (buffer->tag_table == NULL)
636     {
637       buffer->tag_table = gtk_text_tag_table_new ();
638       _gtk_text_tag_table_add_buffer (buffer->tag_table, buffer);
639     }
640
641   return buffer->tag_table;
642 }
643
644 static void
645 gtk_text_buffer_set_property (GObject         *object,
646                               guint            prop_id,
647                               const GValue    *value,
648                               GParamSpec      *pspec)
649 {
650   GtkTextBuffer *text_buffer;
651
652   text_buffer = GTK_TEXT_BUFFER (object);
653
654   switch (prop_id)
655     {
656     case PROP_TAG_TABLE:
657       set_table (text_buffer, g_value_get_object (value));
658       break;
659
660     case PROP_TEXT:
661       gtk_text_buffer_set_text (text_buffer,
662                                 g_value_get_string (value), -1);
663       break;
664
665     default:
666       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
667       break;
668     }
669 }
670
671 static void
672 gtk_text_buffer_get_property (GObject         *object,
673                               guint            prop_id,
674                               GValue          *value,
675                               GParamSpec      *pspec)
676 {
677   GtkTextBuffer *text_buffer;
678   GtkTextIter iter;
679
680   text_buffer = GTK_TEXT_BUFFER (object);
681
682   switch (prop_id)
683     {
684     case PROP_TAG_TABLE:
685       g_value_set_object (value, get_table (text_buffer));
686       break;
687
688     case PROP_TEXT:
689       {
690         GtkTextIter start, end;
691
692         gtk_text_buffer_get_start_iter (text_buffer, &start);
693         gtk_text_buffer_get_end_iter (text_buffer, &end);
694
695         g_value_take_string (value,
696                             gtk_text_buffer_get_text (text_buffer,
697                                                       &start, &end, FALSE));
698         break;
699       }
700
701     case PROP_HAS_SELECTION:
702       g_value_set_boolean (value, text_buffer->has_selection);
703       break;
704
705     case PROP_CURSOR_POSITION:
706       gtk_text_buffer_get_iter_at_mark (text_buffer, &iter, 
707                                         gtk_text_buffer_get_insert (text_buffer));
708       g_value_set_int (value, gtk_text_iter_get_offset (&iter));
709       break;
710
711     case PROP_COPY_TARGET_LIST:
712       g_value_set_boxed (value, gtk_text_buffer_get_copy_target_list (text_buffer));
713       break;
714
715     case PROP_PASTE_TARGET_LIST:
716       g_value_set_boxed (value, gtk_text_buffer_get_paste_target_list (text_buffer));
717       break;
718
719     default:
720       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
721       break;
722     }
723 }
724
725 static void
726 gtk_text_buffer_notify (GObject    *object,
727                         GParamSpec *pspec)
728 {
729   if (!strcmp (pspec->name, "copy-target-list") ||
730       !strcmp (pspec->name, "paste-target-list"))
731     {
732       gtk_text_buffer_free_target_lists (GTK_TEXT_BUFFER (object));
733     }
734 }
735
736 /**
737  * gtk_text_buffer_new:
738  * @table: (allow-none): a tag table, or %NULL to create a new one
739  *
740  * Creates a new text buffer.
741  *
742  * Return value: a new text buffer
743  **/
744 GtkTextBuffer*
745 gtk_text_buffer_new (GtkTextTagTable *table)
746 {
747   GtkTextBuffer *text_buffer;
748
749   text_buffer = g_object_new (GTK_TYPE_TEXT_BUFFER, "tag-table", table, NULL);
750
751   return text_buffer;
752 }
753
754 static void
755 gtk_text_buffer_finalize (GObject *object)
756 {
757   GtkTextBuffer *buffer;
758
759   buffer = GTK_TEXT_BUFFER (object);
760
761   remove_all_selection_clipboards (buffer);
762
763   if (buffer->tag_table)
764     {
765       _gtk_text_tag_table_remove_buffer (buffer->tag_table, buffer);
766       g_object_unref (buffer->tag_table);
767       buffer->tag_table = NULL;
768     }
769
770   if (buffer->btree)
771     {
772       _gtk_text_btree_unref (buffer->btree);
773       buffer->btree = NULL;
774     }
775
776   if (buffer->log_attr_cache)
777     free_log_attr_cache (buffer->log_attr_cache);
778
779   buffer->log_attr_cache = NULL;
780
781   gtk_text_buffer_free_target_lists (buffer);
782
783   G_OBJECT_CLASS (gtk_text_buffer_parent_class)->finalize (object);
784 }
785
786 static GtkTextBTree*
787 get_btree (GtkTextBuffer *buffer)
788 {
789   if (buffer->btree == NULL)
790     buffer->btree = _gtk_text_btree_new (gtk_text_buffer_get_tag_table (buffer),
791                                          buffer);
792
793   return buffer->btree;
794 }
795
796 GtkTextBTree*
797 _gtk_text_buffer_get_btree (GtkTextBuffer *buffer)
798 {
799   return get_btree (buffer);
800 }
801
802 /**
803  * gtk_text_buffer_get_tag_table:
804  * @buffer: a #GtkTextBuffer
805  *
806  * Get the #GtkTextTagTable associated with this buffer.
807  *
808  * Return value: (transfer none): the buffer's tag table
809  **/
810 GtkTextTagTable*
811 gtk_text_buffer_get_tag_table (GtkTextBuffer *buffer)
812 {
813   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
814
815   return get_table (buffer);
816 }
817
818 /**
819  * gtk_text_buffer_set_text:
820  * @buffer: a #GtkTextBuffer
821  * @text: UTF-8 text to insert
822  * @len: length of @text in bytes
823  *
824  * Deletes current contents of @buffer, and inserts @text instead. If
825  * @len is -1, @text must be nul-terminated. @text must be valid UTF-8.
826  **/
827 void
828 gtk_text_buffer_set_text (GtkTextBuffer *buffer,
829                           const gchar   *text,
830                           gint           len)
831 {
832   GtkTextIter start, end;
833
834   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
835   g_return_if_fail (text != NULL);
836
837   if (len < 0)
838     len = strlen (text);
839
840   gtk_text_buffer_get_bounds (buffer, &start, &end);
841
842   gtk_text_buffer_delete (buffer, &start, &end);
843
844   if (len > 0)
845     {
846       gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
847       gtk_text_buffer_insert (buffer, &start, text, len);
848     }
849   
850   g_object_notify (G_OBJECT (buffer), "text");
851 }
852
853  
854
855 /*
856  * Insertion
857  */
858
859 static void
860 gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
861                                   GtkTextIter   *iter,
862                                   const gchar   *text,
863                                   gint           len)
864 {
865   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
866   g_return_if_fail (iter != NULL);
867   
868   _gtk_text_btree_insert (iter, text, len);
869
870   g_signal_emit (buffer, signals[CHANGED], 0);
871   g_object_notify (G_OBJECT (buffer), "cursor-position");
872 }
873
874 static void
875 gtk_text_buffer_emit_insert (GtkTextBuffer *buffer,
876                              GtkTextIter   *iter,
877                              const gchar   *text,
878                              gint           len)
879 {
880   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
881   g_return_if_fail (iter != NULL);
882   g_return_if_fail (text != NULL);
883
884   if (len < 0)
885     len = strlen (text);
886
887   g_return_if_fail (g_utf8_validate (text, len, NULL));
888   
889   if (len > 0)
890     {
891       g_signal_emit (buffer, signals[INSERT_TEXT], 0,
892                      iter, text, len);
893     }
894 }
895
896 /**
897  * gtk_text_buffer_insert:
898  * @buffer: a #GtkTextBuffer
899  * @iter: a position in the buffer
900  * @text: UTF-8 format text to insert
901  * @len: length of text in bytes, or -1
902  *
903  * Inserts @len bytes of @text at position @iter.  If @len is -1,
904  * @text must be nul-terminated and will be inserted in its
905  * entirety. Emits the "insert-text" signal; insertion actually occurs
906  * in the default handler for the signal. @iter is invalidated when
907  * insertion occurs (because the buffer contents change), but the
908  * default signal handler revalidates it to point to the end of the
909  * inserted text.
910  **/
911 void
912 gtk_text_buffer_insert (GtkTextBuffer *buffer,
913                         GtkTextIter   *iter,
914                         const gchar   *text,
915                         gint           len)
916 {
917   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
918   g_return_if_fail (iter != NULL);
919   g_return_if_fail (text != NULL);
920   g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
921   
922   gtk_text_buffer_emit_insert (buffer, iter, text, len);
923 }
924
925 /**
926  * gtk_text_buffer_insert_at_cursor:
927  * @buffer: a #GtkTextBuffer
928  * @text: some text in UTF-8 format
929  * @len: length of text, in bytes
930  *
931  * Simply calls gtk_text_buffer_insert(), using the current
932  * cursor position as the insertion point.
933  **/
934 void
935 gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
936                                   const gchar   *text,
937                                   gint           len)
938 {
939   GtkTextIter iter;
940
941   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
942   g_return_if_fail (text != NULL);
943
944   gtk_text_buffer_get_iter_at_mark (buffer, &iter,
945                                     gtk_text_buffer_get_insert (buffer));
946
947   gtk_text_buffer_insert (buffer, &iter, text, len);
948 }
949
950 /**
951  * gtk_text_buffer_insert_interactive:
952  * @buffer: a #GtkTextBuffer
953  * @iter: a position in @buffer
954  * @text: some UTF-8 text
955  * @len: length of text in bytes, or -1
956  * @default_editable: default editability of buffer
957  *
958  * Like gtk_text_buffer_insert(), but the insertion will not occur if
959  * @iter is at a non-editable location in the buffer. Usually you
960  * want to prevent insertions at ineditable locations if the insertion
961  * results from a user action (is interactive).
962  *
963  * @default_editable indicates the editability of text that doesn't
964  * have a tag affecting editability applied to it. Typically the
965  * result of gtk_text_view_get_editable() is appropriate here.
966  *
967  * Return value: whether text was actually inserted
968  **/
969 gboolean
970 gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer,
971                                     GtkTextIter   *iter,
972                                     const gchar   *text,
973                                     gint           len,
974                                     gboolean       default_editable)
975 {
976   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
977   g_return_val_if_fail (text != NULL, FALSE);
978   g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == buffer, FALSE);
979
980   if (gtk_text_iter_can_insert (iter, default_editable))
981     {
982       gtk_text_buffer_begin_user_action (buffer);
983       gtk_text_buffer_emit_insert (buffer, iter, text, len);
984       gtk_text_buffer_end_user_action (buffer);
985       return TRUE;
986     }
987   else
988     return FALSE;
989 }
990
991 /**
992  * gtk_text_buffer_insert_interactive_at_cursor:
993  * @buffer: a #GtkTextBuffer
994  * @text: text in UTF-8 format
995  * @len: length of text in bytes, or -1
996  * @default_editable: default editability of buffer
997  *
998  * Calls gtk_text_buffer_insert_interactive() at the cursor
999  * position.
1000  *
1001  * @default_editable indicates the editability of text that doesn't
1002  * have a tag affecting editability applied to it. Typically the
1003  * result of gtk_text_view_get_editable() is appropriate here.
1004  * 
1005  * Return value: whether text was actually inserted
1006  **/
1007 gboolean
1008 gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buffer,
1009                                               const gchar   *text,
1010                                               gint           len,
1011                                               gboolean       default_editable)
1012 {
1013   GtkTextIter iter;
1014
1015   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1016   g_return_val_if_fail (text != NULL, FALSE);
1017
1018   gtk_text_buffer_get_iter_at_mark (buffer, &iter,
1019                                     gtk_text_buffer_get_insert (buffer));
1020
1021   return gtk_text_buffer_insert_interactive (buffer, &iter, text, len,
1022                                              default_editable);
1023 }
1024
1025 static gboolean
1026 possibly_not_text (gunichar ch,
1027                    gpointer user_data)
1028 {
1029   return ch == GTK_TEXT_UNKNOWN_CHAR;
1030 }
1031
1032 static void
1033 insert_text_range (GtkTextBuffer     *buffer,
1034                    GtkTextIter       *iter,
1035                    const GtkTextIter *orig_start,
1036                    const GtkTextIter *orig_end,
1037                    gboolean           interactive)
1038 {
1039   gchar *text;
1040
1041   text = gtk_text_iter_get_text (orig_start, orig_end);
1042
1043   gtk_text_buffer_emit_insert (buffer, iter, text, -1);
1044
1045   g_free (text);
1046 }
1047
1048 typedef struct _Range Range;
1049 struct _Range
1050 {
1051   GtkTextBuffer *buffer;
1052   GtkTextMark *start_mark;
1053   GtkTextMark *end_mark;
1054   GtkTextMark *whole_end_mark;
1055   GtkTextIter *range_start;
1056   GtkTextIter *range_end;
1057   GtkTextIter *whole_end;
1058 };
1059
1060 static Range*
1061 save_range (GtkTextIter *range_start,
1062             GtkTextIter *range_end,
1063             GtkTextIter *whole_end)
1064 {
1065   Range *r;
1066
1067   r = g_new (Range, 1);
1068
1069   r->buffer = gtk_text_iter_get_buffer (range_start);
1070   g_object_ref (r->buffer);
1071   
1072   r->start_mark = 
1073     gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
1074                                  NULL,
1075                                  range_start,
1076                                  FALSE);
1077   r->end_mark = 
1078     gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
1079                                  NULL,
1080                                  range_end,
1081                                  TRUE);
1082
1083   r->whole_end_mark = 
1084     gtk_text_buffer_create_mark (gtk_text_iter_get_buffer (range_start),
1085                                  NULL,
1086                                  whole_end,
1087                                  TRUE);
1088
1089   r->range_start = range_start;
1090   r->range_end = range_end;
1091   r->whole_end = whole_end;
1092
1093   return r;
1094 }
1095
1096 static void
1097 restore_range (Range *r)
1098 {
1099   gtk_text_buffer_get_iter_at_mark (r->buffer,
1100                                     r->range_start,
1101                                     r->start_mark);
1102       
1103   gtk_text_buffer_get_iter_at_mark (r->buffer,
1104                                     r->range_end,
1105                                     r->end_mark);
1106       
1107   gtk_text_buffer_get_iter_at_mark (r->buffer,
1108                                     r->whole_end,
1109                                     r->whole_end_mark);  
1110   
1111   gtk_text_buffer_delete_mark (r->buffer, r->start_mark);
1112   gtk_text_buffer_delete_mark (r->buffer, r->end_mark);
1113   gtk_text_buffer_delete_mark (r->buffer, r->whole_end_mark);
1114
1115   /* Due to the gravities on the marks, the ordering could have
1116    * gotten mangled; we switch to an empty range in that
1117    * case
1118    */
1119   
1120   if (gtk_text_iter_compare (r->range_start, r->range_end) > 0)
1121     *r->range_start = *r->range_end;
1122
1123   if (gtk_text_iter_compare (r->range_end, r->whole_end) > 0)
1124     *r->range_end = *r->whole_end;
1125   
1126   g_object_unref (r->buffer);
1127   g_free (r); 
1128 }
1129
1130 static void
1131 insert_range_untagged (GtkTextBuffer     *buffer,
1132                        GtkTextIter       *iter,
1133                        const GtkTextIter *orig_start,
1134                        const GtkTextIter *orig_end,
1135                        gboolean           interactive)
1136 {
1137   GtkTextIter range_start;
1138   GtkTextIter range_end;
1139   GtkTextIter start, end;
1140   Range *r;
1141   
1142   if (gtk_text_iter_equal (orig_start, orig_end))
1143     return;
1144
1145   start = *orig_start;
1146   end = *orig_end;
1147   
1148   range_start = start;
1149   range_end = start;
1150   
1151   while (TRUE)
1152     {
1153       if (gtk_text_iter_equal (&range_start, &range_end))
1154         {
1155           /* Figure out how to move forward */
1156
1157           g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
1158           
1159           if (gtk_text_iter_equal (&range_end, &end))
1160             {
1161               /* nothing left to do */
1162               break;
1163             }
1164           else if (gtk_text_iter_get_char (&range_end) == GTK_TEXT_UNKNOWN_CHAR)
1165             {
1166               GdkPixbuf *pixbuf = NULL;
1167               GtkTextChildAnchor *anchor = NULL;
1168               pixbuf = gtk_text_iter_get_pixbuf (&range_end);
1169               anchor = gtk_text_iter_get_child_anchor (&range_end);
1170
1171               if (pixbuf)
1172                 {
1173                   r = save_range (&range_start,
1174                                   &range_end,
1175                                   &end);
1176
1177                   gtk_text_buffer_insert_pixbuf (buffer,
1178                                                  iter,
1179                                                  pixbuf);
1180
1181                   restore_range (r);
1182                   r = NULL;
1183                   
1184                   gtk_text_iter_forward_char (&range_end);
1185                   
1186                   range_start = range_end;
1187                 }
1188               else if (anchor)
1189                 {
1190                   /* Just skip anchors */
1191
1192                   gtk_text_iter_forward_char (&range_end);
1193                   range_start = range_end;
1194                 }
1195               else
1196                 {
1197                   /* The GTK_TEXT_UNKNOWN_CHAR was in a text segment, so
1198                    * keep going. 
1199                    */
1200                   gtk_text_iter_forward_find_char (&range_end,
1201                                                    possibly_not_text, NULL,
1202                                                    &end);
1203                   
1204                   g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
1205                 }
1206             }
1207           else
1208             {
1209               /* Text segment starts here, so forward search to
1210                * find its possible endpoint
1211                */
1212               gtk_text_iter_forward_find_char (&range_end,
1213                                                possibly_not_text, NULL,
1214                                                &end);
1215               
1216               g_assert (gtk_text_iter_compare (&range_end, &end) <= 0);
1217             }
1218         }
1219       else
1220         {
1221           r = save_range (&range_start,
1222                           &range_end,
1223                           &end);
1224           
1225           insert_text_range (buffer,
1226                              iter,
1227                              &range_start,
1228                              &range_end,
1229                              interactive);
1230
1231           restore_range (r);
1232           r = NULL;
1233           
1234           range_start = range_end;
1235         }
1236     }
1237 }
1238
1239 static void
1240 insert_range_not_inside_self (GtkTextBuffer     *buffer,
1241                               GtkTextIter       *iter,
1242                               const GtkTextIter *orig_start,
1243                               const GtkTextIter *orig_end,
1244                               gboolean           interactive)
1245 {
1246   /* Find each range of uniformly-tagged text, insert it,
1247    * then apply the tags.
1248    */
1249   GtkTextIter start = *orig_start;
1250   GtkTextIter end = *orig_end;
1251   GtkTextIter range_start;
1252   GtkTextIter range_end;
1253   
1254   if (gtk_text_iter_equal (orig_start, orig_end))
1255     return;
1256   
1257   gtk_text_iter_order (&start, &end);
1258
1259   range_start = start;
1260   range_end = start;  
1261   
1262   while (TRUE)
1263     {
1264       gint start_offset;
1265       GtkTextIter start_iter;
1266       GSList *tags;
1267       GSList *tmp_list;
1268       Range *r;
1269       
1270       if (gtk_text_iter_equal (&range_start, &end))
1271         break; /* All done */
1272
1273       g_assert (gtk_text_iter_compare (&range_start, &end) < 0);
1274       
1275       gtk_text_iter_forward_to_tag_toggle (&range_end, NULL);
1276
1277       g_assert (!gtk_text_iter_equal (&range_start, &range_end));
1278
1279       /* Clamp to the end iterator */
1280       if (gtk_text_iter_compare (&range_end, &end) > 0)
1281         range_end = end;
1282       
1283       /* We have a range with unique tags; insert it, and
1284        * apply all tags.
1285        */
1286       start_offset = gtk_text_iter_get_offset (iter);
1287
1288       r = save_range (&range_start, &range_end, &end);
1289       
1290       insert_range_untagged (buffer, iter, &range_start, &range_end, interactive);
1291
1292       restore_range (r);
1293       r = NULL;
1294       
1295       gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_offset);
1296       
1297       tags = gtk_text_iter_get_tags (&range_start);
1298       tmp_list = tags;
1299       while (tmp_list != NULL)
1300         {
1301           gtk_text_buffer_apply_tag (buffer,
1302                                      tmp_list->data,
1303                                      &start_iter,
1304                                      iter);
1305           
1306           tmp_list = g_slist_next (tmp_list);
1307         }
1308       g_slist_free (tags);
1309
1310       range_start = range_end;
1311     }
1312 }
1313
1314 static void
1315 gtk_text_buffer_real_insert_range (GtkTextBuffer     *buffer,
1316                                    GtkTextIter       *iter,
1317                                    const GtkTextIter *orig_start,
1318                                    const GtkTextIter *orig_end,
1319                                    gboolean           interactive)
1320 {
1321   GtkTextBuffer *src_buffer;
1322   
1323   /* Find each range of uniformly-tagged text, insert it,
1324    * then apply the tags.
1325    */  
1326   if (gtk_text_iter_equal (orig_start, orig_end))
1327     return;
1328
1329   if (interactive)
1330     gtk_text_buffer_begin_user_action (buffer);
1331   
1332   src_buffer = gtk_text_iter_get_buffer (orig_start);
1333   
1334   if (gtk_text_iter_get_buffer (iter) != src_buffer ||
1335       !gtk_text_iter_in_range (iter, orig_start, orig_end))
1336     {
1337       insert_range_not_inside_self (buffer, iter, orig_start, orig_end, interactive);
1338     }
1339   else
1340     {
1341       /* If you insert a range into itself, it could loop infinitely
1342        * because the region being copied keeps growing as we insert. So
1343        * we have to separately copy the range before and after
1344        * the insertion point.
1345        */
1346       GtkTextIter start = *orig_start;
1347       GtkTextIter end = *orig_end;
1348       GtkTextIter range_start;
1349       GtkTextIter range_end;
1350       Range *first_half;
1351       Range *second_half;
1352
1353       gtk_text_iter_order (&start, &end);
1354       
1355       range_start = start;
1356       range_end = *iter;
1357       first_half = save_range (&range_start, &range_end, &end);
1358
1359       range_start = *iter;
1360       range_end = end;
1361       second_half = save_range (&range_start, &range_end, &end);
1362
1363       restore_range (first_half);
1364       insert_range_not_inside_self (buffer, iter, &range_start, &range_end, interactive);
1365
1366       restore_range (second_half);
1367       insert_range_not_inside_self (buffer, iter, &range_start, &range_end, interactive);
1368     }
1369   
1370   if (interactive)
1371     gtk_text_buffer_end_user_action (buffer);
1372 }
1373
1374 /**
1375  * gtk_text_buffer_insert_range:
1376  * @buffer: a #GtkTextBuffer
1377  * @iter: a position in @buffer
1378  * @start: a position in a #GtkTextBuffer
1379  * @end: another position in the same buffer as @start
1380  *
1381  * Copies text, tags, and pixbufs between @start and @end (the order
1382  * of @start and @end doesn't matter) and inserts the copy at @iter.
1383  * Used instead of simply getting/inserting text because it preserves
1384  * images and tags. If @start and @end are in a different buffer from
1385  * @buffer, the two buffers must share the same tag table.
1386  *
1387  * Implemented via emissions of the insert_text and apply_tag signals,
1388  * so expect those.
1389  **/
1390 void
1391 gtk_text_buffer_insert_range (GtkTextBuffer     *buffer,
1392                               GtkTextIter       *iter,
1393                               const GtkTextIter *start,
1394                               const GtkTextIter *end)
1395 {
1396   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1397   g_return_if_fail (iter != NULL);
1398   g_return_if_fail (start != NULL);
1399   g_return_if_fail (end != NULL);
1400   g_return_if_fail (gtk_text_iter_get_buffer (start) ==
1401                     gtk_text_iter_get_buffer (end));
1402   g_return_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
1403                     buffer->tag_table);  
1404   g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1405   
1406   gtk_text_buffer_real_insert_range (buffer, iter, start, end, FALSE);
1407 }
1408
1409 /**
1410  * gtk_text_buffer_insert_range_interactive:
1411  * @buffer: a #GtkTextBuffer
1412  * @iter: a position in @buffer
1413  * @start: a position in a #GtkTextBuffer
1414  * @end: another position in the same buffer as @start
1415  * @default_editable: default editability of the buffer
1416  *
1417  * Same as gtk_text_buffer_insert_range(), but does nothing if the
1418  * insertion point isn't editable. The @default_editable parameter
1419  * indicates whether the text is editable at @iter if no tags
1420  * enclosing @iter affect editability. Typically the result of
1421  * gtk_text_view_get_editable() is appropriate here.
1422  *
1423  * Returns: whether an insertion was possible at @iter
1424  **/
1425 gboolean
1426 gtk_text_buffer_insert_range_interactive (GtkTextBuffer     *buffer,
1427                                           GtkTextIter       *iter,
1428                                           const GtkTextIter *start,
1429                                           const GtkTextIter *end,
1430                                           gboolean           default_editable)
1431 {
1432   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1433   g_return_val_if_fail (iter != NULL, FALSE);
1434   g_return_val_if_fail (start != NULL, FALSE);
1435   g_return_val_if_fail (end != NULL, FALSE);
1436   g_return_val_if_fail (gtk_text_iter_get_buffer (start) ==
1437                         gtk_text_iter_get_buffer (end), FALSE);
1438   g_return_val_if_fail (gtk_text_iter_get_buffer (start)->tag_table ==
1439                         buffer->tag_table, FALSE);
1440
1441   if (gtk_text_iter_can_insert (iter, default_editable))
1442     {
1443       gtk_text_buffer_real_insert_range (buffer, iter, start, end, TRUE);
1444       return TRUE;
1445     }
1446   else
1447     return FALSE;
1448 }
1449
1450 /**
1451  * gtk_text_buffer_insert_with_tags:
1452  * @buffer: a #GtkTextBuffer
1453  * @iter: an iterator in @buffer
1454  * @text: UTF-8 text
1455  * @len: length of @text, or -1
1456  * @first_tag: first tag to apply to @text
1457  * @Varargs: NULL-terminated list of tags to apply
1458  *
1459  * Inserts @text into @buffer at @iter, applying the list of tags to
1460  * the newly-inserted text. The last tag specified must be NULL to
1461  * terminate the list. Equivalent to calling gtk_text_buffer_insert(),
1462  * then gtk_text_buffer_apply_tag() on the inserted text;
1463  * gtk_text_buffer_insert_with_tags() is just a convenience function.
1464  **/
1465 void
1466 gtk_text_buffer_insert_with_tags (GtkTextBuffer *buffer,
1467                                   GtkTextIter   *iter,
1468                                   const gchar   *text,
1469                                   gint           len,
1470                                   GtkTextTag    *first_tag,
1471                                   ...)
1472 {
1473   gint start_offset;
1474   GtkTextIter start;
1475   va_list args;
1476   GtkTextTag *tag;
1477
1478   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1479   g_return_if_fail (iter != NULL);
1480   g_return_if_fail (text != NULL);
1481   g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1482   
1483   start_offset = gtk_text_iter_get_offset (iter);
1484
1485   gtk_text_buffer_insert (buffer, iter, text, len);
1486
1487   if (first_tag == NULL)
1488     return;
1489
1490   gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
1491
1492   va_start (args, first_tag);
1493   tag = first_tag;
1494   while (tag)
1495     {
1496       gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
1497
1498       tag = va_arg (args, GtkTextTag*);
1499     }
1500
1501   va_end (args);
1502 }
1503
1504 /**
1505  * gtk_text_buffer_insert_with_tags_by_name:
1506  * @buffer: a #GtkTextBuffer
1507  * @iter: position in @buffer
1508  * @text: UTF-8 text
1509  * @len: length of @text, or -1
1510  * @first_tag_name: name of a tag to apply to @text
1511  * @Varargs: more tag names
1512  *
1513  * Same as gtk_text_buffer_insert_with_tags(), but allows you
1514  * to pass in tag names instead of tag objects.
1515  **/
1516 void
1517 gtk_text_buffer_insert_with_tags_by_name  (GtkTextBuffer *buffer,
1518                                            GtkTextIter   *iter,
1519                                            const gchar   *text,
1520                                            gint           len,
1521                                            const gchar   *first_tag_name,
1522                                            ...)
1523 {
1524   gint start_offset;
1525   GtkTextIter start;
1526   va_list args;
1527   const gchar *tag_name;
1528
1529   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1530   g_return_if_fail (iter != NULL);
1531   g_return_if_fail (text != NULL);
1532   g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1533   
1534   start_offset = gtk_text_iter_get_offset (iter);
1535
1536   gtk_text_buffer_insert (buffer, iter, text, len);
1537
1538   if (first_tag_name == NULL)
1539     return;
1540
1541   gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
1542
1543   va_start (args, first_tag_name);
1544   tag_name = first_tag_name;
1545   while (tag_name)
1546     {
1547       GtkTextTag *tag;
1548
1549       tag = gtk_text_tag_table_lookup (buffer->tag_table,
1550                                        tag_name);
1551
1552       if (tag == NULL)
1553         {
1554           g_warning ("%s: no tag with name '%s'!", G_STRLOC, tag_name);
1555           va_end (args);
1556           return;
1557         }
1558
1559       gtk_text_buffer_apply_tag (buffer, tag, &start, iter);
1560
1561       tag_name = va_arg (args, const gchar*);
1562     }
1563
1564   va_end (args);
1565 }
1566
1567
1568 /*
1569  * Deletion
1570  */
1571
1572 static void
1573 gtk_text_buffer_real_delete_range (GtkTextBuffer *buffer,
1574                                    GtkTextIter   *start,
1575                                    GtkTextIter   *end)
1576 {
1577   gboolean has_selection;
1578
1579   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1580   g_return_if_fail (start != NULL);
1581   g_return_if_fail (end != NULL);
1582
1583   _gtk_text_btree_delete (start, end);
1584
1585   /* may have deleted the selection... */
1586   update_selection_clipboards (buffer);
1587
1588   has_selection = gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL);
1589   if (has_selection != buffer->has_selection)
1590     {
1591       buffer->has_selection = has_selection;
1592       g_object_notify (G_OBJECT (buffer), "has-selection");
1593     }
1594
1595   g_signal_emit (buffer, signals[CHANGED], 0);
1596   g_object_notify (G_OBJECT (buffer), "cursor-position");
1597 }
1598
1599 static void
1600 gtk_text_buffer_emit_delete (GtkTextBuffer *buffer,
1601                              GtkTextIter *start,
1602                              GtkTextIter *end)
1603 {
1604   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1605   g_return_if_fail (start != NULL);
1606   g_return_if_fail (end != NULL);
1607
1608   if (gtk_text_iter_equal (start, end))
1609     return;
1610
1611   gtk_text_iter_order (start, end);
1612
1613   g_signal_emit (buffer,
1614                  signals[DELETE_RANGE],
1615                  0,
1616                  start, end);
1617 }
1618
1619 /**
1620  * gtk_text_buffer_delete:
1621  * @buffer: a #GtkTextBuffer
1622  * @start: a position in @buffer
1623  * @end: another position in @buffer
1624  *
1625  * Deletes text between @start and @end. The order of @start and @end
1626  * is not actually relevant; gtk_text_buffer_delete() will reorder
1627  * them. This function actually emits the "delete-range" signal, and
1628  * the default handler of that signal deletes the text. Because the
1629  * buffer is modified, all outstanding iterators become invalid after
1630  * calling this function; however, the @start and @end will be
1631  * re-initialized to point to the location where text was deleted.
1632  **/
1633 void
1634 gtk_text_buffer_delete (GtkTextBuffer *buffer,
1635                         GtkTextIter   *start,
1636                         GtkTextIter   *end)
1637 {
1638   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1639   g_return_if_fail (start != NULL);
1640   g_return_if_fail (end != NULL);
1641   g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
1642   g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
1643   
1644   gtk_text_buffer_emit_delete (buffer, start, end);
1645 }
1646
1647 /**
1648  * gtk_text_buffer_delete_interactive:
1649  * @buffer: a #GtkTextBuffer
1650  * @start_iter: start of range to delete
1651  * @end_iter: end of range
1652  * @default_editable: whether the buffer is editable by default
1653  *
1654  * Deletes all <emphasis>editable</emphasis> text in the given range.
1655  * Calls gtk_text_buffer_delete() for each editable sub-range of
1656  * [@start,@end). @start and @end are revalidated to point to
1657  * the location of the last deleted range, or left untouched if
1658  * no text was deleted.
1659  *
1660  * Return value: whether some text was actually deleted
1661  **/
1662 gboolean
1663 gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
1664                                     GtkTextIter   *start_iter,
1665                                     GtkTextIter   *end_iter,
1666                                     gboolean       default_editable)
1667 {
1668   GtkTextMark *end_mark;
1669   GtkTextMark *start_mark;
1670   GtkTextIter iter;
1671   gboolean current_state;
1672   gboolean deleted_stuff = FALSE;
1673
1674   /* Delete all editable text in the range start_iter, end_iter */
1675
1676   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1677   g_return_val_if_fail (start_iter != NULL, FALSE);
1678   g_return_val_if_fail (end_iter != NULL, FALSE);
1679   g_return_val_if_fail (gtk_text_iter_get_buffer (start_iter) == buffer, FALSE);
1680   g_return_val_if_fail (gtk_text_iter_get_buffer (end_iter) == buffer, FALSE);
1681
1682   
1683   gtk_text_buffer_begin_user_action (buffer);
1684   
1685   gtk_text_iter_order (start_iter, end_iter);
1686
1687   start_mark = gtk_text_buffer_create_mark (buffer, NULL,
1688                                             start_iter, TRUE);
1689   end_mark = gtk_text_buffer_create_mark (buffer, NULL,
1690                                           end_iter, FALSE);
1691
1692   gtk_text_buffer_get_iter_at_mark (buffer, &iter, start_mark);
1693
1694   current_state = gtk_text_iter_editable (&iter, default_editable);
1695
1696   while (TRUE)
1697     {
1698       gboolean new_state;
1699       gboolean done = FALSE;
1700       GtkTextIter end;
1701
1702       gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
1703
1704       gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark);
1705
1706       if (gtk_text_iter_compare (&iter, &end) >= 0)
1707         {
1708           done = TRUE;
1709           iter = end; /* clamp to the last boundary */
1710         }
1711
1712       new_state = gtk_text_iter_editable (&iter, default_editable);
1713
1714       if (current_state == new_state)
1715         {
1716           if (done)
1717             {
1718               if (current_state)
1719                 {
1720                   /* We're ending an editable region. Delete said region. */
1721                   GtkTextIter start;
1722
1723                   gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1724
1725                   gtk_text_buffer_emit_delete (buffer, &start, &iter);
1726
1727                   deleted_stuff = TRUE;
1728
1729                   /* revalidate user's iterators. */
1730                   *start_iter = start;
1731                   *end_iter = iter;
1732                 }
1733
1734               break;
1735             }
1736           else
1737             continue;
1738         }
1739
1740       if (current_state && !new_state)
1741         {
1742           /* End of an editable region. Delete it. */
1743           GtkTextIter start;
1744
1745           gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
1746
1747           gtk_text_buffer_emit_delete (buffer, &start, &iter);
1748
1749           /* It's more robust to ask for the state again then to assume that
1750            * we're on the next not-editable segment. We don't know what the
1751            * ::delete-range handler did.... maybe it deleted the following
1752            * not-editable segment because it was associated with the editable
1753            * segment.
1754            */
1755           current_state = gtk_text_iter_editable (&iter, default_editable);
1756           deleted_stuff = TRUE;
1757
1758           /* revalidate user's iterators. */
1759           *start_iter = start;
1760           *end_iter = iter;
1761         }
1762       else
1763         {
1764           /* We are at the start of an editable region. We won't be deleting
1765            * the previous region. Move start mark to start of this region.
1766            */
1767
1768           g_assert (!current_state && new_state);
1769
1770           gtk_text_buffer_move_mark (buffer, start_mark, &iter);
1771
1772           current_state = TRUE;
1773         }
1774
1775       if (done)
1776         break;
1777     }
1778
1779   gtk_text_buffer_delete_mark (buffer, start_mark);
1780   gtk_text_buffer_delete_mark (buffer, end_mark);
1781
1782   gtk_text_buffer_end_user_action (buffer);
1783   
1784   return deleted_stuff;
1785 }
1786
1787 /*
1788  * Extracting textual buffer contents
1789  */
1790
1791 /**
1792  * gtk_text_buffer_get_text:
1793  * @buffer: a #GtkTextBuffer
1794  * @start: start of a range
1795  * @end: end of a range
1796  * @include_hidden_chars: whether to include invisible text
1797  *
1798  * Returns the text in the range [@start,@end). Excludes undisplayed
1799  * text (text marked with tags that set the invisibility attribute) if
1800  * @include_hidden_chars is %FALSE. Does not include characters
1801  * representing embedded images, so byte and character indexes into
1802  * the returned string do <emphasis>not</emphasis> correspond to byte
1803  * and character indexes into the buffer. Contrast with
1804  * gtk_text_buffer_get_slice().
1805  *
1806  * Return value: an allocated UTF-8 string
1807  **/
1808 gchar*
1809 gtk_text_buffer_get_text (GtkTextBuffer     *buffer,
1810                           const GtkTextIter *start,
1811                           const GtkTextIter *end,
1812                           gboolean           include_hidden_chars)
1813 {
1814   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1815   g_return_val_if_fail (start != NULL, NULL);
1816   g_return_val_if_fail (end != NULL, NULL);
1817   g_return_val_if_fail (gtk_text_iter_get_buffer (start) == buffer, NULL);
1818   g_return_val_if_fail (gtk_text_iter_get_buffer (end) == buffer, NULL);
1819   
1820   if (include_hidden_chars)
1821     return gtk_text_iter_get_text (start, end);
1822   else
1823     return gtk_text_iter_get_visible_text (start, end);
1824 }
1825
1826 /**
1827  * gtk_text_buffer_get_slice:
1828  * @buffer: a #GtkTextBuffer
1829  * @start: start of a range
1830  * @end: end of a range
1831  * @include_hidden_chars: whether to include invisible text
1832  *
1833  * Returns the text in the range [@start,@end). Excludes undisplayed
1834  * text (text marked with tags that set the invisibility attribute) if
1835  * @include_hidden_chars is %FALSE. The returned string includes a
1836  * 0xFFFC character whenever the buffer contains
1837  * embedded images, so byte and character indexes into
1838  * the returned string <emphasis>do</emphasis> correspond to byte
1839  * and character indexes into the buffer. Contrast with
1840  * gtk_text_buffer_get_text(). Note that 0xFFFC can occur in normal
1841  * text as well, so it is not a reliable indicator that a pixbuf or
1842  * widget is in the buffer.
1843  *
1844  * Return value: an allocated UTF-8 string
1845  **/
1846 gchar*
1847 gtk_text_buffer_get_slice (GtkTextBuffer     *buffer,
1848                            const GtkTextIter *start,
1849                            const GtkTextIter *end,
1850                            gboolean           include_hidden_chars)
1851 {
1852   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1853   g_return_val_if_fail (start != NULL, NULL);
1854   g_return_val_if_fail (end != NULL, NULL);
1855   g_return_val_if_fail (gtk_text_iter_get_buffer (start) == buffer, NULL);
1856   g_return_val_if_fail (gtk_text_iter_get_buffer (end) == buffer, NULL);
1857   
1858   if (include_hidden_chars)
1859     return gtk_text_iter_get_slice (start, end);
1860   else
1861     return gtk_text_iter_get_visible_slice (start, end);
1862 }
1863
1864 /*
1865  * Pixbufs
1866  */
1867
1868 static void
1869 gtk_text_buffer_real_insert_pixbuf (GtkTextBuffer *buffer,
1870                                     GtkTextIter   *iter,
1871                                     GdkPixbuf     *pixbuf)
1872
1873   _gtk_text_btree_insert_pixbuf (iter, pixbuf);
1874
1875   g_signal_emit (buffer, signals[CHANGED], 0);
1876 }
1877
1878 /**
1879  * gtk_text_buffer_insert_pixbuf:
1880  * @buffer: a #GtkTextBuffer
1881  * @iter: location to insert the pixbuf
1882  * @pixbuf: a #GdkPixbuf
1883  *
1884  * Inserts an image into the text buffer at @iter. The image will be
1885  * counted as one character in character counts, and when obtaining
1886  * the buffer contents as a string, will be represented by the Unicode
1887  * "object replacement character" 0xFFFC. Note that the "slice"
1888  * variants for obtaining portions of the buffer as a string include
1889  * this character for pixbufs, but the "text" variants do
1890  * not. e.g. see gtk_text_buffer_get_slice() and
1891  * gtk_text_buffer_get_text().
1892  **/
1893 void
1894 gtk_text_buffer_insert_pixbuf (GtkTextBuffer *buffer,
1895                                GtkTextIter   *iter,
1896                                GdkPixbuf     *pixbuf)
1897 {
1898   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1899   g_return_if_fail (iter != NULL);
1900   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1901   g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1902   
1903   g_signal_emit (buffer, signals[INSERT_PIXBUF], 0,
1904                  iter, pixbuf);
1905 }
1906
1907 /*
1908  * Child anchor
1909  */
1910
1911
1912 static void
1913 gtk_text_buffer_real_insert_anchor (GtkTextBuffer      *buffer,
1914                                     GtkTextIter        *iter,
1915                                     GtkTextChildAnchor *anchor)
1916 {
1917   _gtk_text_btree_insert_child_anchor (iter, anchor);
1918
1919   g_signal_emit (buffer, signals[CHANGED], 0);
1920 }
1921
1922 /**
1923  * gtk_text_buffer_insert_child_anchor:
1924  * @buffer: a #GtkTextBuffer
1925  * @iter: location to insert the anchor
1926  * @anchor: a #GtkTextChildAnchor
1927  *
1928  * Inserts a child widget anchor into the text buffer at @iter. The
1929  * anchor will be counted as one character in character counts, and
1930  * when obtaining the buffer contents as a string, will be represented
1931  * by the Unicode "object replacement character" 0xFFFC. Note that the
1932  * "slice" variants for obtaining portions of the buffer as a string
1933  * include this character for child anchors, but the "text" variants do
1934  * not. E.g. see gtk_text_buffer_get_slice() and
1935  * gtk_text_buffer_get_text(). Consider
1936  * gtk_text_buffer_create_child_anchor() as a more convenient
1937  * alternative to this function. The buffer will add a reference to
1938  * the anchor, so you can unref it after insertion.
1939  **/
1940 void
1941 gtk_text_buffer_insert_child_anchor (GtkTextBuffer      *buffer,
1942                                      GtkTextIter        *iter,
1943                                      GtkTextChildAnchor *anchor)
1944 {
1945   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
1946   g_return_if_fail (iter != NULL);
1947   g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
1948   g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
1949   
1950   g_signal_emit (buffer, signals[INSERT_CHILD_ANCHOR], 0,
1951                  iter, anchor);
1952 }
1953
1954 /**
1955  * gtk_text_buffer_create_child_anchor:
1956  * @buffer: a #GtkTextBuffer
1957  * @iter: location in the buffer
1958  * 
1959  * This is a convenience function which simply creates a child anchor
1960  * with gtk_text_child_anchor_new() and inserts it into the buffer
1961  * with gtk_text_buffer_insert_child_anchor(). The new anchor is
1962  * owned by the buffer; no reference count is returned to
1963  * the caller of gtk_text_buffer_create_child_anchor().
1964  * 
1965  * Return value: the created child anchor
1966  **/
1967 GtkTextChildAnchor*
1968 gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer,
1969                                      GtkTextIter   *iter)
1970 {
1971   GtkTextChildAnchor *anchor;
1972   
1973   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
1974   g_return_val_if_fail (iter != NULL, NULL);
1975   g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == buffer, NULL);
1976   
1977   anchor = gtk_text_child_anchor_new ();
1978
1979   gtk_text_buffer_insert_child_anchor (buffer, iter, anchor);
1980
1981   g_object_unref (anchor);
1982
1983   return anchor;
1984 }
1985
1986 /*
1987  * Mark manipulation
1988  */
1989
1990 static void
1991 gtk_text_buffer_mark_set (GtkTextBuffer     *buffer,
1992                           const GtkTextIter *location,
1993                           GtkTextMark       *mark)
1994 {
1995   /* IMO this should NOT work like insert_text and delete_range,
1996    * where the real action happens in the default handler.
1997    * 
1998    * The reason is that the default handler would be _required_,
1999    * i.e. the whole widget would start breaking and segfaulting if the
2000    * default handler didn't get run. So you can't really override the
2001    * default handler or stop the emission; that is, this signal is
2002    * purely for notification, and not to allow users to modify the
2003    * default behavior.
2004    */
2005
2006   g_object_ref (mark);
2007
2008   g_signal_emit (buffer,
2009                  signals[MARK_SET],
2010                  0,
2011                  location,
2012                  mark);
2013
2014   g_object_unref (mark);
2015 }
2016
2017 /**
2018  * gtk_text_buffer_set_mark:
2019  * @buffer:       a #GtkTextBuffer
2020  * @mark_name:    name of the mark
2021  * @iter:         location for the mark
2022  * @left_gravity: if the mark is created by this function, gravity for 
2023  *                the new mark
2024  * @should_exist: if %TRUE, warn if the mark does not exist, and return
2025  *                immediately
2026  *
2027  * Move the mark to the given position, if not @should_exist, 
2028  * create the mark.
2029  *
2030  * Return value: mark
2031  **/
2032 static GtkTextMark*
2033 gtk_text_buffer_set_mark (GtkTextBuffer     *buffer,
2034                           GtkTextMark       *existing_mark,
2035                           const gchar       *mark_name,
2036                           const GtkTextIter *iter,
2037                           gboolean           left_gravity,
2038                           gboolean           should_exist)
2039 {
2040   GtkTextIter location;
2041   GtkTextMark *mark;
2042
2043   g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == buffer, NULL);
2044   
2045   mark = _gtk_text_btree_set_mark (get_btree (buffer),
2046                                    existing_mark,
2047                                    mark_name,
2048                                    left_gravity,
2049                                    iter,
2050                                    should_exist);
2051   
2052   _gtk_text_btree_get_iter_at_mark (get_btree (buffer),
2053                                    &location,
2054                                    mark);
2055
2056   gtk_text_buffer_mark_set (buffer, &location, mark);
2057
2058   return mark;
2059 }
2060
2061 /**
2062  * gtk_text_buffer_create_mark:
2063  * @buffer: a #GtkTextBuffer
2064  * @mark_name: (allow-none): name for mark, or %NULL
2065  * @where: location to place mark
2066  * @left_gravity: whether the mark has left gravity
2067  *
2068  * Creates a mark at position @where. If @mark_name is %NULL, the mark
2069  * is anonymous; otherwise, the mark can be retrieved by name using
2070  * gtk_text_buffer_get_mark(). If a mark has left gravity, and text is
2071  * inserted at the mark's current location, the mark will be moved to
2072  * the left of the newly-inserted text. If the mark has right gravity
2073  * (@left_gravity = %FALSE), the mark will end up on the right of
2074  * newly-inserted text. The standard left-to-right cursor is a mark
2075  * with right gravity (when you type, the cursor stays on the right
2076  * side of the text you're typing).
2077  *
2078  * The caller of this function does <emphasis>not</emphasis> own a 
2079  * reference to the returned #GtkTextMark, so you can ignore the 
2080  * return value if you like. Marks are owned by the buffer and go 
2081  * away when the buffer does.
2082  *
2083  * Emits the "mark-set" signal as notification of the mark's initial
2084  * placement.
2085  *
2086  * Return value: (transfer none): the new #GtkTextMark object
2087  **/
2088 GtkTextMark*
2089 gtk_text_buffer_create_mark (GtkTextBuffer     *buffer,
2090                              const gchar       *mark_name,
2091                              const GtkTextIter *where,
2092                              gboolean           left_gravity)
2093 {
2094   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
2095
2096   return gtk_text_buffer_set_mark (buffer, NULL, mark_name, where,
2097                                    left_gravity, FALSE);
2098 }
2099
2100 /**
2101  * gtk_text_buffer_add_mark:
2102  * @buffer: a #GtkTextBuffer
2103  * @mark: the mark to add
2104  * @where: location to place mark
2105  *
2106  * Adds the mark at position @where. The mark must not be added to
2107  * another buffer, and if its name is not %NULL then there must not
2108  * be another mark in the buffer with the same name.
2109  *
2110  * Emits the "mark-set" signal as notification of the mark's initial
2111  * placement.
2112  *
2113  * Since: 2.12
2114  **/
2115 void
2116 gtk_text_buffer_add_mark (GtkTextBuffer     *buffer,
2117                           GtkTextMark       *mark,
2118                           const GtkTextIter *where)
2119 {
2120   const gchar *name;
2121
2122   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2123   g_return_if_fail (GTK_IS_TEXT_MARK (mark));
2124   g_return_if_fail (where != NULL);
2125   g_return_if_fail (gtk_text_mark_get_buffer (mark) == NULL);
2126
2127   name = gtk_text_mark_get_name (mark);
2128
2129   if (name != NULL && gtk_text_buffer_get_mark (buffer, name) != NULL)
2130     {
2131       g_critical ("Mark %s already exists in the buffer", name);
2132       return;
2133     }
2134
2135   gtk_text_buffer_set_mark (buffer, mark, NULL, where, FALSE, FALSE);
2136 }
2137
2138 /**
2139  * gtk_text_buffer_move_mark:
2140  * @buffer: a #GtkTextBuffer
2141  * @mark: a #GtkTextMark
2142  * @where: new location for @mark in @buffer
2143  *
2144  * Moves @mark to the new location @where. Emits the "mark-set" signal
2145  * as notification of the move.
2146  **/
2147 void
2148 gtk_text_buffer_move_mark (GtkTextBuffer     *buffer,
2149                            GtkTextMark       *mark,
2150                            const GtkTextIter *where)
2151 {
2152   g_return_if_fail (GTK_IS_TEXT_MARK (mark));
2153   g_return_if_fail (!gtk_text_mark_get_deleted (mark));
2154   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2155
2156   gtk_text_buffer_set_mark (buffer, mark, NULL, where, FALSE, TRUE);
2157 }
2158
2159 /**
2160  * gtk_text_buffer_get_iter_at_mark:
2161  * @buffer: a #GtkTextBuffer
2162  * @iter: (out): iterator to initialize
2163  * @mark: a #GtkTextMark in @buffer
2164  *
2165  * Initializes @iter with the current position of @mark.
2166  **/
2167 void
2168 gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer,
2169                                   GtkTextIter   *iter,
2170                                   GtkTextMark   *mark)
2171 {
2172   g_return_if_fail (GTK_IS_TEXT_MARK (mark));
2173   g_return_if_fail (!gtk_text_mark_get_deleted (mark));
2174   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2175
2176   _gtk_text_btree_get_iter_at_mark (get_btree (buffer),
2177                                     iter,
2178                                     mark);
2179 }
2180
2181 /**
2182  * gtk_text_buffer_delete_mark:
2183  * @buffer: a #GtkTextBuffer
2184  * @mark: a #GtkTextMark in @buffer
2185  *
2186  * Deletes @mark, so that it's no longer located anywhere in the
2187  * buffer. Removes the reference the buffer holds to the mark, so if
2188  * you haven't called g_object_ref() on the mark, it will be freed. Even
2189  * if the mark isn't freed, most operations on @mark become
2190  * invalid, until it gets added to a buffer again with 
2191  * gtk_text_buffer_add_mark(). Use gtk_text_mark_get_deleted() to  
2192  * find out if a mark has been removed from its buffer.
2193  * The "mark-deleted" signal will be emitted as notification after 
2194  * the mark is deleted.
2195  **/
2196 void
2197 gtk_text_buffer_delete_mark (GtkTextBuffer *buffer,
2198                              GtkTextMark   *mark)
2199 {
2200   g_return_if_fail (GTK_IS_TEXT_MARK (mark));
2201   g_return_if_fail (!gtk_text_mark_get_deleted (mark));
2202   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2203
2204   g_object_ref (mark);
2205
2206   _gtk_text_btree_remove_mark (get_btree (buffer), mark);
2207
2208   /* See rationale above for MARK_SET on why we emit this after
2209    * removing the mark, rather than removing the mark in a default
2210    * handler.
2211    */
2212   g_signal_emit (buffer, signals[MARK_DELETED],
2213                  0,
2214                  mark);
2215
2216   g_object_unref (mark);
2217 }
2218
2219 /**
2220  * gtk_text_buffer_get_mark:
2221  * @buffer: a #GtkTextBuffer
2222  * @name: a mark name
2223  *
2224  * Returns the mark named @name in buffer @buffer, or %NULL if no such
2225  * mark exists in the buffer.
2226  *
2227  * Return value: (transfer none): a #GtkTextMark, or %NULL
2228  **/
2229 GtkTextMark*
2230 gtk_text_buffer_get_mark (GtkTextBuffer *buffer,
2231                           const gchar   *name)
2232 {
2233   GtkTextMark *mark;
2234
2235   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
2236   g_return_val_if_fail (name != NULL, NULL);
2237
2238   mark = _gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
2239
2240   return mark;
2241 }
2242
2243 /**
2244  * gtk_text_buffer_move_mark_by_name:
2245  * @buffer: a #GtkTextBuffer
2246  * @name: name of a mark
2247  * @where: new location for mark
2248  *
2249  * Moves the mark named @name (which must exist) to location @where.
2250  * See gtk_text_buffer_move_mark() for details.
2251  **/
2252 void
2253 gtk_text_buffer_move_mark_by_name (GtkTextBuffer     *buffer,
2254                                    const gchar       *name,
2255                                    const GtkTextIter *where)
2256 {
2257   GtkTextMark *mark;
2258
2259   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2260   g_return_if_fail (name != NULL);
2261
2262   mark = _gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
2263
2264   if (mark == NULL)
2265     {
2266       g_warning ("%s: no mark named '%s'", G_STRLOC, name);
2267       return;
2268     }
2269
2270   gtk_text_buffer_move_mark (buffer, mark, where);
2271 }
2272
2273 /**
2274  * gtk_text_buffer_delete_mark_by_name:
2275  * @buffer: a #GtkTextBuffer
2276  * @name: name of a mark in @buffer
2277  *
2278  * Deletes the mark named @name; the mark must exist. See
2279  * gtk_text_buffer_delete_mark() for details.
2280  **/
2281 void
2282 gtk_text_buffer_delete_mark_by_name (GtkTextBuffer *buffer,
2283                                      const gchar   *name)
2284 {
2285   GtkTextMark *mark;
2286
2287   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2288   g_return_if_fail (name != NULL);
2289
2290   mark = _gtk_text_btree_get_mark_by_name (get_btree (buffer), name);
2291
2292   if (mark == NULL)
2293     {
2294       g_warning ("%s: no mark named '%s'", G_STRLOC, name);
2295       return;
2296     }
2297
2298   gtk_text_buffer_delete_mark (buffer, mark);
2299 }
2300
2301 /**
2302  * gtk_text_buffer_get_insert:
2303  * @buffer: a #GtkTextBuffer
2304  *
2305  * Returns the mark that represents the cursor (insertion point).
2306  * Equivalent to calling gtk_text_buffer_get_mark() to get the mark
2307  * named "insert", but very slightly more efficient, and involves less
2308  * typing.
2309  *
2310  * Return value: (transfer none): insertion point mark
2311  **/
2312 GtkTextMark*
2313 gtk_text_buffer_get_insert (GtkTextBuffer *buffer)
2314 {
2315   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
2316
2317   return _gtk_text_btree_get_insert (get_btree (buffer));
2318 }
2319
2320 /**
2321  * gtk_text_buffer_get_selection_bound:
2322  * @buffer: a #GtkTextBuffer
2323  *
2324  * Returns the mark that represents the selection bound.  Equivalent
2325  * to calling gtk_text_buffer_get_mark() to get the mark named
2326  * "selection_bound", but very slightly more efficient, and involves
2327  * less typing.
2328  *
2329  * The currently-selected text in @buffer is the region between the
2330  * "selection_bound" and "insert" marks. If "selection_bound" and
2331  * "insert" are in the same place, then there is no current selection.
2332  * gtk_text_buffer_get_selection_bounds() is another convenient function
2333  * for handling the selection, if you just want to know whether there's a
2334  * selection and what its bounds are.
2335  *
2336  * Return value: (transfer none): selection bound mark
2337  **/
2338 GtkTextMark*
2339 gtk_text_buffer_get_selection_bound (GtkTextBuffer *buffer)
2340 {
2341   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
2342
2343   return _gtk_text_btree_get_selection_bound (get_btree (buffer));
2344 }
2345
2346 /**
2347  * gtk_text_buffer_get_iter_at_child_anchor:
2348  * @buffer: a #GtkTextBuffer
2349  * @iter: (out): an iterator to be initialized
2350  * @anchor: a child anchor that appears in @buffer
2351  *
2352  * Obtains the location of @anchor within @buffer.
2353  **/
2354 void
2355 gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer      *buffer,
2356                                           GtkTextIter        *iter,
2357                                           GtkTextChildAnchor *anchor)
2358 {
2359   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2360   g_return_if_fail (iter != NULL);
2361   g_return_if_fail (GTK_IS_TEXT_CHILD_ANCHOR (anchor));
2362   g_return_if_fail (!gtk_text_child_anchor_get_deleted (anchor));
2363   
2364   _gtk_text_btree_get_iter_at_child_anchor (get_btree (buffer),
2365                                            iter,
2366                                            anchor);
2367 }
2368
2369 /**
2370  * gtk_text_buffer_place_cursor:
2371  * @buffer: a #GtkTextBuffer
2372  * @where: where to put the cursor
2373  *
2374  * This function moves the "insert" and "selection_bound" marks
2375  * simultaneously.  If you move them to the same place in two steps
2376  * with gtk_text_buffer_move_mark(), you will temporarily select a
2377  * region in between their old and new locations, which can be pretty
2378  * inefficient since the temporarily-selected region will force stuff
2379  * to be recalculated. This function moves them as a unit, which can
2380  * be optimized.
2381  **/
2382 void
2383 gtk_text_buffer_place_cursor (GtkTextBuffer     *buffer,
2384                               const GtkTextIter *where)
2385 {
2386   gtk_text_buffer_select_range (buffer, where, where);
2387 }
2388
2389 /**
2390  * gtk_text_buffer_select_range:
2391  * @buffer: a #GtkTextBuffer
2392  * @ins: where to put the "insert" mark
2393  * @bound: where to put the "selection_bound" mark
2394  *
2395  * This function moves the "insert" and "selection_bound" marks
2396  * simultaneously.  If you move them in two steps
2397  * with gtk_text_buffer_move_mark(), you will temporarily select a
2398  * region in between their old and new locations, which can be pretty
2399  * inefficient since the temporarily-selected region will force stuff
2400  * to be recalculated. This function moves them as a unit, which can
2401  * be optimized.
2402  *
2403  * Since: 2.4
2404  **/
2405 void
2406 gtk_text_buffer_select_range (GtkTextBuffer     *buffer,
2407                               const GtkTextIter *ins,
2408                               const GtkTextIter *bound)
2409 {
2410   GtkTextIter real_ins;
2411   GtkTextIter real_bound;
2412
2413   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2414
2415   real_ins = *ins;
2416   real_bound = *bound;
2417
2418   _gtk_text_btree_select_range (get_btree (buffer), &real_ins, &real_bound);
2419   gtk_text_buffer_mark_set (buffer, &real_ins,
2420                             gtk_text_buffer_get_insert (buffer));
2421   gtk_text_buffer_mark_set (buffer, &real_bound,
2422                             gtk_text_buffer_get_selection_bound (buffer));
2423 }
2424
2425 /*
2426  * Tags
2427  */
2428
2429 /**
2430  * gtk_text_buffer_create_tag:
2431  * @buffer: a #GtkTextBuffer
2432  * @tag_name: (allow-none): name of the new tag, or %NULL
2433  * @first_property_name: (allow-none): name of first property to set, or %NULL
2434  * @Varargs: %NULL-terminated list of property names and values
2435  *
2436  *
2437  * Creates a tag and adds it to the tag table for @buffer.
2438  * Equivalent to calling gtk_text_tag_new() and then adding the
2439  * tag to the buffer's tag table. The returned tag is owned by
2440  * the buffer's tag table, so the ref count will be equal to one.
2441  *
2442  * If @tag_name is %NULL, the tag is anonymous.
2443  *
2444  * If @tag_name is non-%NULL, a tag called @tag_name must not already
2445  * exist in the tag table for this buffer.
2446  *
2447  * The @first_property_name argument and subsequent arguments are a list
2448  * of properties to set on the tag, as with g_object_set().
2449  *
2450  * Return value: a new tag
2451  **/
2452 GtkTextTag*
2453 gtk_text_buffer_create_tag (GtkTextBuffer *buffer,
2454                             const gchar   *tag_name,
2455                             const gchar   *first_property_name,
2456                             ...)
2457 {
2458   GtkTextTag *tag;
2459   va_list list;
2460   
2461   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
2462
2463   tag = gtk_text_tag_new (tag_name);
2464
2465   gtk_text_tag_table_add (get_table (buffer), tag);
2466
2467   if (first_property_name)
2468     {
2469       va_start (list, first_property_name);
2470       g_object_set_valist (G_OBJECT (tag), first_property_name, list);
2471       va_end (list);
2472     }
2473   
2474   g_object_unref (tag);
2475
2476   return tag;
2477 }
2478
2479 static void
2480 gtk_text_buffer_real_apply_tag (GtkTextBuffer     *buffer,
2481                                 GtkTextTag        *tag,
2482                                 const GtkTextIter *start,
2483                                 const GtkTextIter *end)
2484 {
2485   if (tag->table != buffer->tag_table)
2486     {
2487       g_warning ("Can only apply tags that are in the tag table for the buffer");
2488       return;
2489     }
2490   
2491   _gtk_text_btree_tag (start, end, tag, TRUE);
2492 }
2493
2494 static void
2495 gtk_text_buffer_real_remove_tag (GtkTextBuffer     *buffer,
2496                                  GtkTextTag        *tag,
2497                                  const GtkTextIter *start,
2498                                  const GtkTextIter *end)
2499 {
2500   if (tag->table != buffer->tag_table)
2501     {
2502       g_warning ("Can only remove tags that are in the tag table for the buffer");
2503       return;
2504     }
2505   
2506   _gtk_text_btree_tag (start, end, tag, FALSE);
2507 }
2508
2509 static void
2510 gtk_text_buffer_real_changed (GtkTextBuffer *buffer)
2511 {
2512   gtk_text_buffer_set_modified (buffer, TRUE);
2513 }
2514
2515 static void
2516 gtk_text_buffer_real_mark_set (GtkTextBuffer     *buffer,
2517                                const GtkTextIter *iter,
2518                                GtkTextMark       *mark)
2519 {
2520   GtkTextMark *insert;
2521   
2522   insert = gtk_text_buffer_get_insert (buffer);
2523
2524   if (mark == insert || mark == gtk_text_buffer_get_selection_bound (buffer))
2525     {
2526       gboolean has_selection;
2527
2528       update_selection_clipboards (buffer);
2529     
2530       has_selection = gtk_text_buffer_get_selection_bounds (buffer,
2531                                                             NULL,
2532                                                             NULL);
2533
2534       if (has_selection != buffer->has_selection)
2535         {
2536           buffer->has_selection = has_selection;
2537           g_object_notify (G_OBJECT (buffer), "has-selection");
2538         }
2539     }
2540     
2541     if (mark == insert)
2542       g_object_notify (G_OBJECT (buffer), "cursor-position");
2543 }
2544
2545 static void
2546 gtk_text_buffer_emit_tag (GtkTextBuffer     *buffer,
2547                           GtkTextTag        *tag,
2548                           gboolean           apply,
2549                           const GtkTextIter *start,
2550                           const GtkTextIter *end)
2551 {
2552   GtkTextIter start_tmp = *start;
2553   GtkTextIter end_tmp = *end;
2554
2555   g_return_if_fail (tag != NULL);
2556
2557   gtk_text_iter_order (&start_tmp, &end_tmp);
2558
2559   if (apply)
2560     g_signal_emit (buffer, signals[APPLY_TAG],
2561                    0,
2562                    tag, &start_tmp, &end_tmp);
2563   else
2564     g_signal_emit (buffer, signals[REMOVE_TAG],
2565                    0,
2566                    tag, &start_tmp, &end_tmp);
2567 }
2568
2569 /**
2570  * gtk_text_buffer_apply_tag:
2571  * @buffer: a #GtkTextBuffer
2572  * @tag: a #GtkTextTag
2573  * @start: one bound of range to be tagged
2574  * @end: other bound of range to be tagged
2575  *
2576  * Emits the "apply-tag" signal on @buffer. The default
2577  * handler for the signal applies @tag to the given range.
2578  * @start and @end do not have to be in order.
2579  **/
2580 void
2581 gtk_text_buffer_apply_tag (GtkTextBuffer     *buffer,
2582                            GtkTextTag        *tag,
2583                            const GtkTextIter *start,
2584                            const GtkTextIter *end)
2585 {
2586   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2587   g_return_if_fail (GTK_IS_TEXT_TAG (tag));
2588   g_return_if_fail (start != NULL);
2589   g_return_if_fail (end != NULL);
2590   g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2591   g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2592   g_return_if_fail (tag->table == buffer->tag_table);
2593   
2594   gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
2595 }
2596
2597 /**
2598  * gtk_text_buffer_remove_tag:
2599  * @buffer: a #GtkTextBuffer
2600  * @tag: a #GtkTextTag
2601  * @start: one bound of range to be untagged
2602  * @end: other bound of range to be untagged
2603  *
2604  * Emits the "remove-tag" signal. The default handler for the signal
2605  * removes all occurrences of @tag from the given range. @start and
2606  * @end don't have to be in order.
2607  **/
2608 void
2609 gtk_text_buffer_remove_tag (GtkTextBuffer     *buffer,
2610                             GtkTextTag        *tag,
2611                             const GtkTextIter *start,
2612                             const GtkTextIter *end)
2613
2614 {
2615   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2616   g_return_if_fail (GTK_IS_TEXT_TAG (tag));
2617   g_return_if_fail (start != NULL);
2618   g_return_if_fail (end != NULL);
2619   g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2620   g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2621   g_return_if_fail (tag->table == buffer->tag_table);
2622   
2623   gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
2624 }
2625
2626 /**
2627  * gtk_text_buffer_apply_tag_by_name:
2628  * @buffer: a #GtkTextBuffer
2629  * @name: name of a named #GtkTextTag
2630  * @start: one bound of range to be tagged
2631  * @end: other bound of range to be tagged
2632  *
2633  * Calls gtk_text_tag_table_lookup() on the buffer's tag table to
2634  * get a #GtkTextTag, then calls gtk_text_buffer_apply_tag().
2635  **/
2636 void
2637 gtk_text_buffer_apply_tag_by_name (GtkTextBuffer     *buffer,
2638                                    const gchar       *name,
2639                                    const GtkTextIter *start,
2640                                    const GtkTextIter *end)
2641 {
2642   GtkTextTag *tag;
2643
2644   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2645   g_return_if_fail (name != NULL);
2646   g_return_if_fail (start != NULL);
2647   g_return_if_fail (end != NULL);
2648   g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2649   g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2650
2651   tag = gtk_text_tag_table_lookup (get_table (buffer),
2652                                    name);
2653
2654   if (tag == NULL)
2655     {
2656       g_warning ("Unknown tag `%s'", name);
2657       return;
2658     }
2659
2660   gtk_text_buffer_emit_tag (buffer, tag, TRUE, start, end);
2661 }
2662
2663 /**
2664  * gtk_text_buffer_remove_tag_by_name:
2665  * @buffer: a #GtkTextBuffer
2666  * @name: name of a #GtkTextTag
2667  * @start: one bound of range to be untagged
2668  * @end: other bound of range to be untagged
2669  *
2670  * Calls gtk_text_tag_table_lookup() on the buffer's tag table to
2671  * get a #GtkTextTag, then calls gtk_text_buffer_remove_tag().
2672  **/
2673 void
2674 gtk_text_buffer_remove_tag_by_name (GtkTextBuffer     *buffer,
2675                                     const gchar       *name,
2676                                     const GtkTextIter *start,
2677                                     const GtkTextIter *end)
2678 {
2679   GtkTextTag *tag;
2680
2681   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2682   g_return_if_fail (name != NULL);
2683   g_return_if_fail (start != NULL);
2684   g_return_if_fail (end != NULL);
2685   g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2686   g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2687   
2688   tag = gtk_text_tag_table_lookup (get_table (buffer),
2689                                    name);
2690
2691   if (tag == NULL)
2692     {
2693       g_warning ("Unknown tag `%s'", name);
2694       return;
2695     }
2696
2697   gtk_text_buffer_emit_tag (buffer, tag, FALSE, start, end);
2698 }
2699
2700 static gint
2701 pointer_cmp (gconstpointer a,
2702              gconstpointer b)
2703 {
2704   if (a < b)
2705     return -1;
2706   else if (a > b)
2707     return 1;
2708   else
2709     return 0;
2710 }
2711
2712 /**
2713  * gtk_text_buffer_remove_all_tags:
2714  * @buffer: a #GtkTextBuffer
2715  * @start: one bound of range to be untagged
2716  * @end: other bound of range to be untagged
2717  * 
2718  * Removes all tags in the range between @start and @end.  Be careful
2719  * with this function; it could remove tags added in code unrelated to
2720  * the code you're currently writing. That is, using this function is
2721  * probably a bad idea if you have two or more unrelated code sections
2722  * that add tags.
2723  **/
2724 void
2725 gtk_text_buffer_remove_all_tags (GtkTextBuffer     *buffer,
2726                                  const GtkTextIter *start,
2727                                  const GtkTextIter *end)
2728 {
2729   GtkTextIter first, second, tmp;
2730   GSList *tags;
2731   GSList *tmp_list;
2732   GSList *prev, *next;
2733   GtkTextTag *tag;
2734   
2735   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2736   g_return_if_fail (start != NULL);
2737   g_return_if_fail (end != NULL);
2738   g_return_if_fail (gtk_text_iter_get_buffer (start) == buffer);
2739   g_return_if_fail (gtk_text_iter_get_buffer (end) == buffer);
2740   
2741   first = *start;
2742   second = *end;
2743
2744   gtk_text_iter_order (&first, &second);
2745
2746   /* Get all tags turned on at the start */
2747   tags = gtk_text_iter_get_tags (&first);
2748   
2749   /* Find any that are toggled on within the range */
2750   tmp = first;
2751   while (gtk_text_iter_forward_to_tag_toggle (&tmp, NULL))
2752     {
2753       GSList *toggled;
2754       GSList *tmp_list2;
2755
2756       if (gtk_text_iter_compare (&tmp, &second) >= 0)
2757         break; /* past the end of the range */
2758       
2759       toggled = gtk_text_iter_get_toggled_tags (&tmp, TRUE);
2760
2761       /* We could end up with a really big-ass list here.
2762        * Fix it someday.
2763        */
2764       tmp_list2 = toggled;
2765       while (tmp_list2 != NULL)
2766         {
2767           tags = g_slist_prepend (tags, tmp_list2->data);
2768
2769           tmp_list2 = g_slist_next (tmp_list2);
2770         }
2771
2772       g_slist_free (toggled);
2773     }
2774   
2775   /* Sort the list */
2776   tags = g_slist_sort (tags, pointer_cmp);
2777
2778   /* Strip duplicates */
2779   tag = NULL;
2780   prev = NULL;
2781   tmp_list = tags;
2782   while (tmp_list != NULL)
2783     {
2784       if (tag == tmp_list->data)
2785         {
2786           /* duplicate */
2787           next = tmp_list->next;
2788           if (prev)
2789             prev->next = next;
2790
2791           tmp_list->next = NULL;
2792
2793           g_slist_free (tmp_list);
2794
2795           tmp_list = next;
2796           /* prev is unchanged */
2797         }
2798       else
2799         {
2800           /* not a duplicate */
2801           tag = GTK_TEXT_TAG (tmp_list->data);
2802           prev = tmp_list;
2803           tmp_list = tmp_list->next;
2804         }
2805     }
2806
2807   g_slist_foreach (tags, (GFunc) g_object_ref, NULL);
2808   
2809   tmp_list = tags;
2810   while (tmp_list != NULL)
2811     {
2812       tag = GTK_TEXT_TAG (tmp_list->data);
2813
2814       gtk_text_buffer_remove_tag (buffer, tag, &first, &second);
2815       
2816       tmp_list = tmp_list->next;
2817     }
2818
2819   g_slist_foreach (tags, (GFunc) g_object_unref, NULL);
2820   
2821   g_slist_free (tags);
2822 }
2823
2824
2825 /*
2826  * Obtain various iterators
2827  */
2828
2829 /**
2830  * gtk_text_buffer_get_iter_at_line_offset:
2831  * @buffer: a #GtkTextBuffer
2832  * @iter: (out): iterator to initialize
2833  * @line_number: line number counting from 0
2834  * @char_offset: char offset from start of line
2835  *
2836  * Obtains an iterator pointing to @char_offset within the given
2837  * line. The @char_offset must exist, offsets off the end of the line
2838  * are not allowed. Note <emphasis>characters</emphasis>, not bytes;
2839  * UTF-8 may encode one character as multiple bytes.
2840  **/
2841 void
2842 gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
2843                                          GtkTextIter   *iter,
2844                                          gint           line_number,
2845                                          gint           char_offset)
2846 {
2847   g_return_if_fail (iter != NULL);
2848   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2849
2850   _gtk_text_btree_get_iter_at_line_char (get_btree (buffer),
2851                                          iter, line_number, char_offset);
2852 }
2853
2854 /**
2855  * gtk_text_buffer_get_iter_at_line_index:
2856  * @buffer: a #GtkTextBuffer 
2857  * @iter: (out): iterator to initialize 
2858  * @line_number: line number counting from 0
2859  * @byte_index: byte index from start of line
2860  *
2861  * Obtains an iterator pointing to @byte_index within the given line.
2862  * @byte_index must be the start of a UTF-8 character, and must not be
2863  * beyond the end of the line.  Note <emphasis>bytes</emphasis>, not
2864  * characters; UTF-8 may encode one character as multiple bytes.
2865  **/
2866 void
2867 gtk_text_buffer_get_iter_at_line_index  (GtkTextBuffer *buffer,
2868                                          GtkTextIter   *iter,
2869                                          gint           line_number,
2870                                          gint           byte_index)
2871 {
2872   g_return_if_fail (iter != NULL);
2873   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2874
2875   _gtk_text_btree_get_iter_at_line_byte (get_btree (buffer),
2876                                          iter, line_number, byte_index);
2877 }
2878
2879 /**
2880  * gtk_text_buffer_get_iter_at_line:
2881  * @buffer: a #GtkTextBuffer 
2882  * @iter: (out): iterator to initialize
2883  * @line_number: line number counting from 0
2884  * 
2885  * Initializes @iter to the start of the given line.
2886  **/
2887 void
2888 gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
2889                                   GtkTextIter   *iter,
2890                                   gint           line_number)
2891 {
2892   g_return_if_fail (iter != NULL);
2893   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2894
2895   gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
2896 }
2897
2898 /**
2899  * gtk_text_buffer_get_iter_at_offset:
2900  * @buffer: a #GtkTextBuffer 
2901  * @iter: (out): iterator to initialize
2902  * @char_offset: char offset from start of buffer, counting from 0, or -1
2903  *
2904  * Initializes @iter to a position @char_offset chars from the start
2905  * of the entire buffer. If @char_offset is -1 or greater than the number
2906  * of characters in the buffer, @iter is initialized to the end iterator,
2907  * the iterator one past the last valid character in the buffer.
2908  **/
2909 void
2910 gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
2911                                     GtkTextIter   *iter,
2912                                     gint           char_offset)
2913 {
2914   g_return_if_fail (iter != NULL);
2915   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2916
2917   _gtk_text_btree_get_iter_at_char (get_btree (buffer), iter, char_offset);
2918 }
2919
2920 /**
2921  * gtk_text_buffer_get_start_iter:
2922  * @buffer: a #GtkTextBuffer
2923  * @iter: (out): iterator to initialize
2924  *
2925  * Initialized @iter with the first position in the text buffer. This
2926  * is the same as using gtk_text_buffer_get_iter_at_offset() to get
2927  * the iter at character offset 0.
2928  **/
2929 void
2930 gtk_text_buffer_get_start_iter (GtkTextBuffer *buffer,
2931                                 GtkTextIter   *iter)
2932 {
2933   g_return_if_fail (iter != NULL);
2934   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2935
2936   _gtk_text_btree_get_iter_at_char (get_btree (buffer), iter, 0);
2937 }
2938
2939 /**
2940  * gtk_text_buffer_get_end_iter:
2941  * @buffer: a #GtkTextBuffer 
2942  * @iter: (out): iterator to initialize
2943  *
2944  * Initializes @iter with the "end iterator," one past the last valid
2945  * character in the text buffer. If dereferenced with
2946  * gtk_text_iter_get_char(), the end iterator has a character value of
2947  * 0. The entire buffer lies in the range from the first position in
2948  * the buffer (call gtk_text_buffer_get_start_iter() to get
2949  * character position 0) to the end iterator.
2950  **/
2951 void
2952 gtk_text_buffer_get_end_iter (GtkTextBuffer *buffer,
2953                               GtkTextIter   *iter)
2954 {
2955   g_return_if_fail (iter != NULL);
2956   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2957
2958   _gtk_text_btree_get_end_iter (get_btree (buffer), iter);
2959 }
2960
2961 /**
2962  * gtk_text_buffer_get_bounds:
2963  * @buffer: a #GtkTextBuffer 
2964  * @start: (out): iterator to initialize with first position in the buffer
2965  * @end: (out): iterator to initialize with the end iterator
2966  *
2967  * Retrieves the first and last iterators in the buffer, i.e. the
2968  * entire buffer lies within the range [@start,@end).
2969  **/
2970 void
2971 gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
2972                             GtkTextIter   *start,
2973                             GtkTextIter   *end)
2974 {
2975   g_return_if_fail (start != NULL);
2976   g_return_if_fail (end != NULL);
2977   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
2978
2979   _gtk_text_btree_get_iter_at_char (get_btree (buffer), start, 0);
2980   _gtk_text_btree_get_end_iter (get_btree (buffer), end);
2981 }
2982
2983 /*
2984  * Modified flag
2985  */
2986
2987 /**
2988  * gtk_text_buffer_get_modified:
2989  * @buffer: a #GtkTextBuffer 
2990  * 
2991  * Indicates whether the buffer has been modified since the last call
2992  * to gtk_text_buffer_set_modified() set the modification flag to
2993  * %FALSE. Used for example to enable a "save" function in a text
2994  * editor.
2995  * 
2996  * Return value: %TRUE if the buffer has been modified
2997  **/
2998 gboolean
2999 gtk_text_buffer_get_modified (GtkTextBuffer *buffer)
3000 {
3001   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
3002
3003   return buffer->modified;
3004 }
3005
3006 /**
3007  * gtk_text_buffer_set_modified:
3008  * @buffer: a #GtkTextBuffer 
3009  * @setting: modification flag setting
3010  *
3011  * Used to keep track of whether the buffer has been modified since the
3012  * last time it was saved. Whenever the buffer is saved to disk, call
3013  * gtk_text_buffer_set_modified (@buffer, FALSE). When the buffer is modified,
3014  * it will automatically toggled on the modified bit again. When the modified
3015  * bit flips, the buffer emits a "modified-changed" signal.
3016  **/
3017 void
3018 gtk_text_buffer_set_modified (GtkTextBuffer *buffer,
3019                               gboolean       setting)
3020 {
3021   gboolean fixed_setting;
3022
3023   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
3024
3025   fixed_setting = setting != FALSE;
3026
3027   if (buffer->modified == fixed_setting)
3028     return;
3029   else
3030     {
3031       buffer->modified = fixed_setting;
3032       g_signal_emit (buffer, signals[MODIFIED_CHANGED], 0);
3033     }
3034 }
3035
3036 /**
3037  * gtk_text_buffer_get_has_selection:
3038  * @buffer: a #GtkTextBuffer 
3039  * 
3040  * Indicates whether the buffer has some text currently selected.
3041  * 
3042  * Return value: %TRUE if the there is text selected
3043  *
3044  * Since: 2.10
3045  **/
3046 gboolean
3047 gtk_text_buffer_get_has_selection (GtkTextBuffer *buffer)
3048 {
3049   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
3050
3051   return buffer->has_selection;
3052 }
3053
3054
3055 /*
3056  * Assorted other stuff
3057  */
3058
3059 /**
3060  * gtk_text_buffer_get_line_count:
3061  * @buffer: a #GtkTextBuffer 
3062  * 
3063  * Obtains the number of lines in the buffer. This value is cached, so
3064  * the function is very fast.
3065  * 
3066  * Return value: number of lines in the buffer
3067  **/
3068 gint
3069 gtk_text_buffer_get_line_count (GtkTextBuffer *buffer)
3070 {