/* $Id: textbuffer.hg,v 1.20 2006/11/20 09:19:49 murrayc Exp $ */

/* Copyright(C) 1998-2002 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or(at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include <gtkmm/object.h>
#include <gtkmm/texttagtable.h>
#include <gtkmm/textchildanchor.h>
#include <gtkmm/textmark.h>
#include <gtkmm/textiter.h>
#include <gtkmm/clipboard.h>
#include <gdkmm/pixbuf.h>
#include <gtkmmconfig.h>
#include <utility>

GLIBMM_USING_STD(pair)

_DEFS(gtkmm,gtk)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gtk
{

class TextMark;
class TextIter;

/** Multi-line attributed text that can be displayed by one or more Gtk::TextView widgets.
 *
 * Text in a buffer can be marked with tags. A @link Gtk::TextTag Gtk::TextBuffer::Tag@endlink is an attribute that can be applied to some range of text. For example, a tag
 * might be called "bold" and make the text inside the tag bold. However, the tag concept is more general than that; tags don't
 * have to affect appearance. They can instead affect the behavior of mouse and key presses, "lock" a range of text so the user
 * can't edit it, or countless other things. A tag is represented by a @link Gtk::TextTag Gtk::TextBuffer::Tag@endlink object.
 * One @link Gtk::TextTag Gtk::TextBuffer::Tag@endlink can be applied to any number of text ranges in any number of @link Gtk::TextBuffer Gtk::TextBuffers@endlink.
 *
 * Each tag is stored in a @link Gtk::TextTagTable Gtk::TextBuffer::TagTable@endlink. A tag table defines a set of tags that can be used together. Each buffer has one tag
 * table associated with it; only tags from that tag table can be used with the buffer. A single tag table can be shared between
 * multiple buffers, however.
 *
 * Most text manipulation is accomplished with iterators, represented by an @link Gtk::TextIter iterator@endlink. The iterator can
 * be used to navigate over characters, words, lines, and sentences.
 *
 * But iterators can't be used to preserve positions across buffer modifications. To preserve a position, the
 * @link Gtk::TextMark Gtk::TextBuffer::Mark@endlink object is ideal. There are two marks built-in to GtkTextBuffer; these are
 * named "insert" and "selection_bound" and refer to the insertion point and the boundary of the selection which is not the
 * insertion point. If no text is selected, these two marks will be in the same position. You can manipulate what is selected and
 * where the cursor appears by moving these marks around.
 *
 * Text buffers always contain at least one line, but may be empty (that is, buffers can contain zero characters). The last line
 * in the text buffer never ends in a line separator (such as newline); the other lines in the buffer always end in a line
 * separator. Line separators count as characters when computing character counts and character offsets. Note that some Unicode
 * line separators are represented with multiple bytes in UTF-8, and the two-character sequence "\r\n" is also considered a line
 * separator.
 *
 * @ingroup TextView
 */
class TextBuffer : public Glib::Object
{
   _CLASS_GOBJECT(TextBuffer, GtkTextBuffer, GTK_TEXT_BUFFER, Glib::Object, GObject)
   _IGNORE(gtk_text_buffer_get_iter_at_line_offset, gtk_text_buffer_get_iter_at_line_index,
           gtk_text_buffer_get_iter_at_offset, gtk_text_buffer_get_iter_at_line, gtk_text_buffer_get_start_iter,
           gtk_text_buffer_get_end_iter, gtk_text_buffer_get_bounds, gtk_text_buffer_get_iter_at_mark,
           gtk_text_buffer_get_selection_bounds, gtk_text_buffer_insert_interactive,
           gtk_text_buffer_insert, gtk_text_buffer_insert_at_cursor, gtk_text_buffer_insert_interactive_at_cursor,
           gtk_text_buffer_insert_with_tags, gtk_text_buffer_insert_with_tags_by_name,
           gtk_text_buffer_get_iter_at_child_anchor)
public:
  typedef TextIter iterator;
  typedef TextTag Tag;
  typedef TextTagTable TagTable;
  typedef TextMark Mark;
  typedef TextChildAnchor ChildAnchor;

protected:
  _CTOR_DEFAULT()
  explicit TextBuffer(const Glib::RefPtr<TagTable>& tag_table);

public:
  _WRAP_CREATE()
  _WRAP_CREATE(const Glib::RefPtr<TagTable>& tag_table)

  _WRAP_METHOD(int get_line_count() const, gtk_text_buffer_get_line_count)
  _WRAP_METHOD(int get_char_count() const, gtk_text_buffer_get_char_count)

  /// See get_char_count().
  int size() const;

  _WRAP_METHOD(Glib::RefPtr<TextBuffer::TagTable> get_tag_table(), gtk_text_buffer_get_tag_table, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const TextBuffer::TagTable> get_tag_table() const, gtk_text_buffer_get_tag_table, refreturn, constversion)

  /** Removes the current contents of the buffer, and inserts @a text instead.
   * @param text The text to put in the buffer.
   */
  void set_text(const Glib::ustring& text);

  /** Removes the current contents of the buffer, and inserts @a text instead.
   * @param text_begin The start of a UTF8 character array.
   * @param text_end The end of the UTF8 character array.
   */
  void set_text(const char* text_begin, const char* text_end);
  _IGNORE(gtk_text_buffer_set_text)

  _DEPRECATE_IFDEF_START
  /** @deprecated Use set_text()
   */
  void assign(const Glib::ustring& text);
  
  /** @deprecated Use set_text()
   */
  void assign(const char* text_begin, const char* text_end);
  _DEPRECATE_IFDEF_END

  //TODO: Make all insert() methods have the same return type:
  
  /** Inserts @a text at position @a pos.
   * Emits the "insert_text" signal; insertion actually occurs in the default handler for the signal.
   * The @a pos iterator is invalidated when insertion occurs (because the buffer contents change).
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text The text to be inserted in the buffer.
   * @result An iterator that points to the end of the inserted text.
   */
  iterator insert(const iterator& pos, const Glib::ustring& text);

  /** Inserts text at position @a pos.
   * Emits the "insert_text" signal; insertion actually occurs in the default handler for the signal.
   * The @a pos iterator is invalidated when insertion occurs (because the buffer contents change).
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text_begin The start of a UTF8 character array.
   * @param text_end The end of the UTF8 character array.
   * @result An iterator that points to the end of the inserted text.
   */
  iterator insert(const iterator& pos, const char* text_begin, const char* text_end);

  /** Inserts @a text, using the current cursor position as the insertion point.
   * Emits the "insert_text" signal; insertion actually occurs in the default handler for the signal.
   *
   * @param text The text to be inserted in the buffer.
   * @result An iterator that points to the end of the inserted text.
   */
  void insert_at_cursor(const Glib::ustring& text);

  /** Inserts text, using the current cursor position as the insertion point.
   * Emits the "insert_text" signal; insertion actually occurs in the default handler for the signal.
   *
   * @param text_begin The start of a UTF8 character array.
   * @param text_end The end of the UTF8 character array.
   * @result An iterator that points to the end of the inserted text.
   */
  void insert_at_cursor(const char* text_begin, const char* text_end);

  /** Like insert(), but the insertion will not occur if @a iter is at a non-editable location in the buffer.
   * Usually you want to prevent insertions at ineditable locations if the insertion results from a user action (is interactive).
   *
   * @a default_editable indicates the editability of text that doesn't have a tag affecting editability applied to it.
   * Typically the result of Gtk::TextView::get_editable() is appropriate here.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text The text to be inserted in the buffer.
   * @param default_editable Default editability of buffer
   * @result Whether text was actually inserted
   */
  std::pair<iterator,bool> insert_interactive(
      const iterator& pos, const Glib::ustring& text, bool default_editable = true);

  /** Like insert(), but the insertion will not occur if @a pos is at a non-editable location in the buffer.
   * Usually you want to prevent insertions at ineditable locations if the insertion results from a user action (is interactive).
   *
   * @a default_editable indicates the editability of text that doesn't have a tag affecting editability applied to it.
   * Typically the result of Gtk::TextView::get_editable() is appropriate here.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text_begin The start of a UTF8 character array.
   * @param text_end The end of the UTF8 character array.
   * @param default_editable Default editability of buffer.
   * @result Whether text was actually inserted
   */
  std::pair<iterator,bool> insert_interactive(
      const iterator& pos, const char* text_begin, const char* text_end, bool default_editable = true);

  /** Calls insert_interactive() at the cursor position.
   *
   * @a default_editable indicates the editability of text that doesn't have a tag affecting editability applied to it.
   * Typically the result of Gtk::TextView::get_editable() is appropriate here.
   *
   * @param text The text to be inserted in the buffer.
   * @param default_editable Default editability of buffer
   * @result Whether text was actually inserted
   */
  bool insert_interactive_at_cursor(const Glib::ustring& text, bool default_editable = true);

  /** Calls insert_interactive() at the cursor position.
   *
   * @a default_editable indicates the editability of text that doesn't have a tag affecting editability applied to it.
   * Typically the result of Gtk::TextView::get_editable() is appropriate here.
   *
   * @param text_begin The start of a UTF8 character array.
   * @param text_end The end of the UTF8 character array.
   * @param default_editable Default editability of buffer
   * @result Whether text was actually inserted
   */
  bool insert_interactive_at_cursor(const char* text_begin, const char* text_end,
                                    bool default_editable = true);

  /** Copies text, tags, and pixbufs between @a range_begin and @a range_end (the order of range_begin and range_begin doesn't
   * matter) and inserts the copy at @a pos. Used instead of simply getting/inserting text because it preserves images and tags.
   * If range_begin and range_end are in a different buffer, the two buffers must share the same tag table.
   *
   * Implemented via emissions of the insert_text and apply_tag signals, so expect those.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param range_begin A position in a buffer.
   * @param range_end Another position in the same buffer as @a range_begin.
   * @result Whether text was actually inserted
   */
  iterator insert(const iterator& pos, const iterator& range_begin, const iterator& range_end);
  _IGNORE(gtk_text_buffer_insert_range)
 
  /** Same as insert_range(), but does nothing if the insertion point isn't editable.
   *
   * The @a default_editable parameter indicates whether the text is editable at @a pos if no tags enclosing @a pos affect editability.
   * Typically the result of Gtk::TextView::get_editable() is appropriate here.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param range_begin A position in a buffer.
   * @param range_end Another position in the same buffer as @a range_begin.
   * @param default_editable Default editability of buffer.
   * @result Whether text was actually inserted
   */
  std::pair<iterator,bool> insert_interactive(const iterator& pos, const iterator& range_begin, const iterator& range_end, bool default_editable = true);
  _IGNORE(gtk_text_buffer_insert_range_interactive)

  iterator insert_with_tag(const iterator& pos, const Glib::ustring& text, const Glib::RefPtr<Tag>& tag);
  iterator insert_with_tag(const iterator& pos, const char* text_begin, const char* text_end, const Glib::RefPtr<Tag>& tag);

  iterator insert_with_tag(const iterator& pos, const Glib::ustring& text, const Glib::ustring& tag_name);
  iterator insert_with_tag(const iterator& pos, const char* text_begin, const char* text_end, const Glib::ustring& tag_name);

  /** Inserts text into buffer at @a pos, applying the list of tags to the newly-inserted text.
   * Equivalent to calling insert(), then apply_tag() on the inserted text; This is just a convenience function.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text The text to be inserted in the buffer.
   * @param tags A standard C++ container of @link Gtk::TextTag Gtk::TextBuffer::Tags@endlink.
   * @result Whether text was actually inserted
   */
  iterator insert_with_tags(const iterator& pos, const Glib::ustring& text,
                            const Glib::ArrayHandle< Glib::RefPtr<Tag> >& tags);

  /** Inserts text into buffer at @a pos, applying the list of tags to the newly-inserted text.
   * Equivalent to calling insert(), then apply_tag() on the inserted text; This is just a convenience function.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text_begin The start of a UTF8 character array.
   * @param text_end The end of the UTF8 character array.
   * @param tags A standard C++ container of @link Gtk::TextTag Gtk::TextBuffer::Tags@endlink.
   * @result Whether text was actually inserted
   */                          
  iterator insert_with_tags(const iterator& pos, const char* text_begin, const char* text_end,
                            const Glib::ArrayHandle< Glib::RefPtr<Tag> >& tags);

  /** Inserts text into buffer at @a pos, applying the list of tags to the newly-inserted text.
   * Equivalent to calling insert(), then apply_tag() on the inserted text; This is just a convenience function.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text The text to be inserted in the buffer.
   * @param tag_names A standard C++ container of tag names.
   * @result Whether text was actually inserted
   */
  iterator insert_with_tags_by_name(const iterator& pos, const Glib::ustring& text,
                                    const Glib::StringArrayHandle& tag_names);


  /** Equivalent to calling insert(), then apply_tag() on the inserted text; This is just a convenience function.
   *
   * @param pos An iterator pointing to the position at which the text should be inserted.
   * @param text_begin The start of a UTF8 character array.
   * @param text_end The end of the UTF8 character array.
   * @param tag_names A standard C++ container of tag names.
   * @result Whether text was actually inserted
   */                                   
  iterator insert_with_tags_by_name(const iterator& pos, const char* text_begin, const char* text_end,
                                    const Glib::StringArrayHandle& tag_names);

  /* Deletes all text between @a range_begin and @a range_end. The order of range_begin and range_end is not actually relevant.
   * This function actually emits the "delete_range" signal, and the default handler of that signal deletes the text.
   * Because the buffer is modified, all outstanding iterators become invalid after calling this function.
   * @param range_begin
   * @param range_end
   * @result An iterator that points to the location where text was deleted.
   */
  iterator erase(const iterator& range_begin, const iterator& range_end);
  _IGNORE(gtk_text_buffer_delete)

   /* Deletes all editable text between @a range_begin and @a range_end. The order of range_begin and range_end is not actually relevant.
   * This function actually emits the "delete_range" signal, and the default handler of that signal deletes the text.
   * Because the buffer is modified, all outstanding iterators become invalid after calling this function.
   *
   * @a default_editable indicates the editability of text that doesn't have a tag affecting editability applied to it.
   * Typically the result of Gtk::TextView::get_editable() is appropriate here.
   *
   * @param range_begin
   * @param range_end
   * @param default_editable Default editability of buffer
   * @result An iterator that points to the location where text was deleted, or end() is no text was deleted.
   */
  std::pair<iterator,bool> erase_interactive(const iterator& range_begin, const iterator& range_end, bool default_editable = true);
  _IGNORE(gtk_text_buffer_delete_interactive)

  /** Performs the appropriate action as if the user hit the delete
   * key with the cursor at the position specified by @a iter. In the
   * normal case a single character will be deleted, but when
   * combining accents are involved, more than one character can
   * be deleted, and when precomposed character and accent combinations
   * are involved, less than one character will be deleted.
   * 
   * Because the buffer is modified, all outstanding iterators become 
   * invalid after calling this method; however, this method returns 
   * a valid iterator that points to the location where text was deleted.
   *
   * @param iter A position in the buffer.
   * @param interactive Whether the deletion is caused by user interaction.
   * @param default_editable Whether the buffer is editable by default.
   * @result An iterator to the location where text was deleted, if the buffer was modified.
   *
   * @newin2p6
   */
  iterator backspace(const iterator& iter, bool interactive = true, bool default_editable = true);
  _IGNORE(gtk_text_buffer_backspace)

  /** @deprecated Use get_text(const iterator& start, const iterator& end, bool include_hidden_chars) const
   */
  _WRAP_METHOD(Glib::ustring get_text(const iterator& start, const iterator& end, bool include_hidden_chars = true), gtk_text_buffer_get_text)

  _WRAP_METHOD(Glib::ustring get_text(const iterator& start, const iterator& end, bool include_hidden_chars = true) const, gtk_text_buffer_get_text)

  /** @deprecated Use get_text(bool include_hidden_chars) const.
   */
  Glib::ustring get_text(bool include_hidden_chars = true);

  /** Returns all the text in the buffer. Excludes undisplayed
   * text (text marked with tags that set the invisibility attribute) if
   *  @a include_hidden_chars  is <tt>false</tt>. Does not include characters
   * representing embedded images, so byte and character indexes into
   * the returned string do <em>not</em> correspond to byte
   * and character indexes into the buffer. Contrast with
   * get_slice().
   *
   * @param include_hidden_chars Whether to include invisible text.
   * @return An allocated UTF-8 string.
   */
  Glib::ustring get_text(bool include_hidden_chars = true) const;

  /** @deprecated Use get_slice(const iterator& start, const iterator& end, bool include_hidden_chars) const.
   */
  _WRAP_METHOD(Glib::ustring get_slice(const iterator& start, const iterator& end, bool include_hidden_chars = true), gtk_text_buffer_get_slice)

  _WRAP_METHOD(Glib::ustring get_slice(const iterator& start, const iterator& end, bool include_hidden_chars = true) const, gtk_text_buffer_get_slice)

  iterator insert_pixbuf(const iterator& pos, const Glib::RefPtr<Gdk::Pixbuf>& pixbuf);
  _IGNORE(gtk_text_buffer_insert_pixbuf)

  iterator insert_child_anchor(const iterator& pos, const Glib::RefPtr<ChildAnchor>& anchor);
  _IGNORE(gtk_text_buffer_insert_child_anchor)

  Glib::RefPtr<ChildAnchor> create_child_anchor(const iterator& pos);
  _IGNORE(gtk_text_buffer_create_child_anchor)

  _WRAP_METHOD(void add_mark(const Glib::RefPtr<TextBuffer::Mark>& mark, const iterator& where), gtk_text_buffer_add_mark)

  _WRAP_METHOD(Glib::RefPtr<TextBuffer::Mark> create_mark(const Glib::ustring& mark_name, const iterator& where, bool left_gravity = true), gtk_text_buffer_create_mark, refreturn)

  /** Create an anonymous mark. */
  /** Creates an anonymous mark at position @a where.
   *
   * If a mark has left gravity, and text is
   * inserted at the mark's current location, the mark will be moved to
   * the left of the newly-inserted text. If the mark has right gravity
   * ( @a left_gravity  = <tt>false</tt>), the mark will end up on the right of
   * newly-inserted text. The standard left-to-right cursor is a mark
   * with right gravity (when you type, the cursor stays on the right
   * side of the text you're typing).
   *
   * Emits the "mark_set" signal as notification of the mark's initial
   * placement.
   * @param where Location to place mark.
   * @param left_gravity Whether the mark has left gravity.
   * @return The new Gtk::TextMark object.
   */ 
  Glib::RefPtr<Mark> create_mark(const iterator& where, bool left_gravity = true);

  _WRAP_METHOD(void move_mark(const Glib::RefPtr<Mark>& mark, const iterator& where), gtk_text_buffer_move_mark)
  _WRAP_METHOD(void delete_mark(const Glib::RefPtr<Mark>& mark), gtk_text_buffer_delete_mark)

  _WRAP_METHOD(Glib::RefPtr<TextBuffer::Mark> get_mark(const Glib::ustring& name), gtk_text_buffer_get_mark, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const TextBuffer::Mark> get_mark(const Glib::ustring& name) const, gtk_text_buffer_get_mark, refreturn, constversion)

  _WRAP_METHOD(void move_mark_by_name(const Glib::ustring& name, const iterator& where), gtk_text_buffer_move_mark_by_name)
  _WRAP_METHOD(void delete_mark_by_name(const Glib::ustring& name), gtk_text_buffer_delete_mark_by_name)

  _WRAP_METHOD(Glib::RefPtr<TextBuffer::Mark> get_insert(), gtk_text_buffer_get_insert, refreturn)
  _WRAP_METHOD(Glib::RefPtr<TextBuffer::Mark> get_selection_bound(), gtk_text_buffer_get_selection_bound, refreturn)

  _WRAP_METHOD(void place_cursor(const iterator& where), gtk_text_buffer_place_cursor)
  _WRAP_METHOD(void apply_tag(const Glib::RefPtr<Tag>& tag, const iterator& start, const iterator& end), gtk_text_buffer_apply_tag)
  _WRAP_METHOD(void remove_tag(const Glib::RefPtr<Tag>& tag, const iterator& start, const iterator& end), gtk_text_buffer_remove_tag)
  _WRAP_METHOD(void apply_tag_by_name(const Glib::ustring& name, const iterator& start, const iterator& end), gtk_text_buffer_apply_tag_by_name)
  _WRAP_METHOD(void remove_tag_by_name(const Glib::ustring& name, const iterator& start, const iterator& end), gtk_text_buffer_remove_tag_by_name)
  _WRAP_METHOD(void remove_all_tags(const iterator& start, const iterator& end), gtk_text_buffer_remove_all_tags)

  /** Creates a tag and adds it to the tag table for buffer. Equivalent to calling Gtk::TextBuffer::Tag::create() and then adding
   * the tag to the buffer's tag table.
   * A tag called @a tag_name must not already exist in the tag table for this buffer.
   *
   * @param tag_name The name for the new tag.
   * @result The new tag.
   */
  Glib::RefPtr<Tag> create_tag(const Glib::ustring& tag_name);
  _IGNORE(gtk_text_buffer_create_tag)

  /** Creates an anoymous tag and adds it to the tag table for buffer. Equivalent to calling Gtk::TextBuffer::Tag::create() and then adding
   * the tag to the buffer's tag table.
   *
   * @result The new tag.
   */
  Glib::RefPtr<Tag> create_tag();

  iterator get_iter_at_line_offset(int line_number, int char_offset);
  iterator get_iter_at_line_index(int line_number, int byte_index);
  iterator get_iter_at_offset(int char_offset);
  iterator get_iter_at_line(int line_number);
  iterator begin();
  iterator end();
  void get_bounds(iterator& range_begin, iterator& range_end);

  /** Get the current position of a mark.
   * @param mark The @link Gtk::TextMark Gtk::TextBuffer::Mark@endlink
   * @result An iterator that points to the position of the @a mark.
   */
  iterator get_iter_at_mark(const Glib::RefPtr<Mark>& mark);

  /** Get the current position of an anchor.
   * @param anchor A @link Gtk::TextChildAnchor Gtk::TextBuffer::Anchor@endlink that appears in the buffer.
   * @result An iterator that points to the position of the @a anchor.
   */
  iterator get_iter_at_child_anchor(const Glib::RefPtr<ChildAnchor>& anchor);

  _WRAP_METHOD(bool get_modified() const, gtk_text_buffer_get_modified)
  _WRAP_METHOD(void set_modified(bool setting = true), gtk_text_buffer_set_modified)

  _WRAP_METHOD(bool get_has_selection() const, gtk_text_buffer_get_has_selection)

  _WRAP_METHOD(void add_selection_clipboard(const Glib::RefPtr<Clipboard>& clipboard), gtk_text_buffer_add_selection_clipboard)
  _WRAP_METHOD(void remove_selection_clipboard(const Glib::RefPtr<Clipboard>& clipboard), gtk_text_buffer_remove_selection_clipboard)
  _WRAP_METHOD(void cut_clipboard(const Glib::RefPtr<Clipboard>& clipboard, bool default_editable = true), gtk_text_buffer_cut_clipboard)
  _WRAP_METHOD(void copy_clipboard(const Glib::RefPtr<Clipboard>& clipboard), gtk_text_buffer_copy_clipboard)
  void paste_clipboard(const Glib::RefPtr<Clipboard>& clipboard, const iterator& override_location, bool default_editable = true);
  void paste_clipboard(const Glib::RefPtr<Clipboard>& clipboard, bool default_editable = true);
  _IGNORE(gtk_text_buffer_paste_clipboard)

  _WRAP_METHOD(bool get_selection_bounds(iterator& start, iterator& end) const, gtk_text_buffer_get_selection_bounds)
  _WRAP_METHOD(bool erase_selection(bool interactive = true, bool default_editable = true), gtk_text_buffer_delete_selection)

  _WRAP_METHOD(void select_range(const iterator& ins, const iterator& bound), gtk_text_buffer_select_range)
  
/* Called to specify atomic user actions, used to implement undo */
  _WRAP_METHOD(void begin_user_action(), gtk_text_buffer_begin_user_action)
  _WRAP_METHOD(void end_user_action(), gtk_text_buffer_end_user_action)



  //These are only available on the Maemo platform (patched Gtk+):

  _WRAP_METHOD(void set_can_paste_rich_text(bool can_paste_rich_text), gtk_text_buffer_set_can_paste_rich_text, ifdef GTKMM_MAEMO_EXTENSIONS_ENABLED)
  _WRAP_METHOD(bool get_can_paste_rich_text() const, gtk_text_buffer_get_can_paste_rich_text, ifdef GTKMM_MAEMO_EXTENSIONS_ENABLED)

  _WRAP_METHOD(void set_rich_text_format(const Glib::ustring& format), gtk_text_buffer_set_rich_text_format, ifdef GTKMM_MAEMO_EXTENSIONS_ENABLED)

#ifdef GTKMM_MAEMO_EXTENSIONS_ENABLED
  /** Accept all formats from clipboard
   *
   */
  void set_rich_text_format_all();
#endif //GTKMM_MAEMO_EXTENSIONS_ENABLED

  _WRAP_METHOD(Glib::ustring get_rich_text_format() const, gtk_text_buffer_get_rich_text_format, ifdef GTKMM_MAEMO_EXTENSIONS_ENABLED) 



//TODO: I have commented these out for now because I don't understand what the register_buffer and content_buffer are. murrayc.
 //TODO: Documentation.
 // typedef sigc::slot<guint8*, const Glib::RefPtr<TextBuffer>& /* content_buffer */, const iterator& /* start */, const iterator& /* end */, gsize& /* length */> SlotSerialize;


//TODO: Use ArrayHandle, or just use guint8* to be more efficient?
  // typedef sigc::slot<bool, const Glib::RefPtr<TextBuffer>& /* content_buffer */, iterator& /* iter */, const guint8*  /* data */, gsize /* length */, bool /* create_tags */> SlotDeserialize;

/*
  Glib::ustring register_serialize_format(const Glib::ustring& mime_type, const SlotSerialize& slot);
  _IGNORE(gtk_text_buffer_register_serialize_format)
*/

  _WRAP_METHOD(Glib::ustring register_serialize_tagset(const Glib::ustring& tagset_name), gtk_text_buffer_register_serialize_tagset)

/*
  Glib::ustring register_deserialize_format(const Glib::ustring& mime_type, const SlotDeserialize& slot);
  _IGNORE(gtk_text_buffer_register_deserialize_format)
*/
  _WRAP_METHOD(Glib::ustring register_deserialize_tagset(const Glib::ustring& tagset_name), gtk_text_buffer_register_deserialize_tagset)

  _WRAP_METHOD(void unregister_serialize_format(const Glib::ustring& format), gtk_text_buffer_unregister_serialize_format)
  _WRAP_METHOD(void unregister_deserialize_format(const Glib::ustring& format), gtk_text_buffer_unregister_deserialize_format)

  _WRAP_METHOD(void set_can_create_tags(const Glib::ustring& format, bool can_create_tags = true), gtk_text_buffer_deserialize_set_can_create_tags)
  _WRAP_METHOD(bool get_can_create_tags(const Glib::ustring& format) const, gtk_text_buffer_deserialize_get_can_create_tags)


  Glib::StringArrayHandle get_serialize_formats() const;
  _IGNORE(gtk_text_buffer_get_serialize_formats)
  Glib::StringArrayHandle get_deserialize_formats() const;
  _IGNORE(gtk_text_buffer_get_deserialize_formats)

/*
//TODO: I have commented these out for now because I don't understand what the register_buffer and content_buffer are. murrayc.

//TODO: Use something other than gsize?
#m4 _CONVERSION(`const iterator&', `GtkTextIter*',`($3).gobj()')
  _WRAP_METHOD(guint8* serialize(const Glib::RefPtr<TextBuffer>& content_buffer,
                                                       const Glib::ustring& format,
                                                       const iterator& iterstart,
                                                       const iterator& iterend,
                                                       gsize& length), gtk_text_buffer_serialize)

//TODO: Is the bool superfluous?
//TODO: Use an ArrayHandle?
  _WRAP_METHOD(bool deserialize(const Glib::RefPtr<TextBuffer>& content_buffer,
                                                       const Glib::ustring& format,
                                                       const iterator& iter, const guint8* data,
                                                       gsize length), gtk_text_buffer_deserialize, errthrow)
*/




#m4begin
dnl // HACK: Override the default conversion to deal correctly
dnl // with non-0-terminated strings in insert_text_callback().
_CONVERSION(`const char*',`const Glib::ustring&',`Glib::ustring(p1, p1 + p2)')
#m4end
  _WRAP_SIGNAL(void insert(const TextBuffer::iterator& pos, const Glib::ustring& text, int bytes), "insert_text")
  _WRAP_SIGNAL(void insert_pixbuf(const TextBuffer::iterator& pos, const Glib::RefPtr<Gdk::Pixbuf>& pixbuf), "insert_pixbuf")
  _WRAP_SIGNAL(void insert_child_anchor(const TextBuffer::iterator& pos, const Glib::RefPtr<ChildAnchor>& anchor), "insert_child_anchor")
  
  /** The delete_range signal is emitted to delete a range from 
   * a TextBuffer. Note that your handler must not invalidate the
   * @a start and @a end iters (or has to revalidate them), if it runs before the 
   * default handler. There is no need to keep the iters valid in handlers
   * which run after the default handler but
   * those don't have access to the deleted text.
   *
   * @param start the start of the range to be deleted.
   * @param end the end of the range to be deleted.
   */
  _WRAP_SIGNAL(void erase(const TextBuffer::iterator& start, const TextBuffer::iterator& end), "delete_range")
  
  
  _WRAP_SIGNAL(void changed(), "changed")
  _WRAP_SIGNAL(void modified_changed(), "modified_changed")
  _WRAP_SIGNAL(void mark_set(const TextBuffer::iterator& location, const Glib::RefPtr<TextBuffer::Mark>& mark), "mark_set")
  _WRAP_SIGNAL(void mark_deleted(const Glib::RefPtr<TextBuffer::Mark>& mark), "mark_deleted")
  _WRAP_SIGNAL(void apply_tag(const Glib::RefPtr<TextBuffer::Tag>& tag, const TextBuffer::iterator& range_begin, const TextBuffer::iterator& range_end), "apply_tag")
  _WRAP_SIGNAL(void remove_tag(const Glib::RefPtr<TextBuffer::Tag>& tag, const TextBuffer::iterator& range_begin, const TextBuffer::iterator& range_end), "remove_tag")
  _WRAP_SIGNAL(void begin_user_action(), "begin_user_action")
  _WRAP_SIGNAL(void end_user_action(), "end_user_action")

  _WRAP_PROPERTY("text", Glib::ustring)
  _WRAP_PROPERTY("has-selection", bool)
  _WRAP_PROPERTY("cursor-position", int)
  //TODO: Check the ref-counting/conversion for these: _WRAP_PROPERTY("copy-target-list", Glib::ListHandle< Glib::RefPtr<TargetList> >)
  //TODO: _WRAP_PROPERTY("paste-target-list", Glib::ListHandle< Glib::RefPtr<TargetList> >)
};

} // namespace Gtk

